Difference between revisions of "SDKTools (SourceMod Scripting)"
m (→Calling Functions) |
m (→GiveNamedItem Example) |
||
Line 130: | Line 130: | ||
GiveItem(client, const String:item[]) | GiveItem(client, const String:item[]) | ||
{ | { | ||
− | SDKCall(hGiveNamedItem, client, item, 0); | + | return SDKCall(hGiveNamedItem, client, item, 0); |
}</pawn> | }</pawn> | ||
Revision as of 13:37, 16 June 2007
The SDKTools extension is an extension for various functions provided by the Source SDK. Additionally, it has the ability to dynamically call many C++ functions in the SDK, for example, from CBaseEntity or any derived class.
SDKTools contains simplified versions of SDK functions pre-written for ease of use. These can be found in the additional include files:
- sdktools_functions.inc - Popular functions from the SDK.
Contents
GameConfigs
Virtual Offsets
For adding virtual offsets, add sub-sections to the "Offsets" section of your game config file. For example:
"Games" { "cstrike" { "Offsets" { "GiveNamedItem" { "windows" "329" "linux" "330" } } } }
Signature Scans
For automated signature scans, add sub-sections to the "Signatures" section of your game config file. There are three properties for a signature:
- library: Must be "server" right now.
- windows: A signature written in binary; for example, "\x56" instead of "0x56" -- the '*' character is a single byte wildcard.
- linux: Either a signature as with windows, or a named symbol. To use a named symbol, start the string with the '@' character. If a signature begins with '@', write the character in hexadecimal as above.
Example:
"Games" { "cstrike" { "Signatures" { "RoundRespawn" { "library" "server" "windows" "\x56\x8B\xF1\x8B\x06\xFF\x90*\x04\x00\x00\x8B\x86*\x0D\x00" "linux" "@_ZN9CCSPlayer12RoundRespawnEv" } } } }
Inheritance
If you wish for multiple mods to inherit from one block, you can add a special "#supported" section under a "#default" section. For example:
"Games" { "#default" { "#supported" { "game" "dod" } } }
This specifies that the given block will be read for Day of Defeat as well.
Calling Functions
Calling functions is complicated and requires strict attention to the C++ API you are trying to use. If you make a mistake, something bad will happen (and if not, you got lucky!) SDKTools is more complicated than PimpinJuice's "Hacks" extension because it precompiles all of the information needed to convert from Plugin memory to C++ types. This precompilation step ensures better safety and speed, but it lengthens the preparation process.
With that said, let's look at an overview of the call creation process. Before making calls, we must prepare the call. This will give us a Handle which will let us make as many calls as we like.
- Init - The preparation must be initialized. Here we can specify the calling convention, which is either static, or BaseEntity/BasePlayer-based. BasePlayer should be used when only player entities should be allowed as the this pointer.
- Destination - The call must have a destination address or virtual index to use. This is normally done via PrepSDKCall_SetFromConf which ties into gameconf files.
- Return Info - If the call has return information, it must be set via PrepSDKCall_SetReturnInfo.
- Parameters - Each parameter (if any) must be added with PrepSDKCall_AddParameter.
- Finalize - The call must be finalized with EndPrepSDKCall, which will return a Handle. If it doesn't, one or more of the preparation operations failed.
For the examples below, consider a plugin called "sdkexamples.sp" which has a gamedata file of "plugin.sdkexamples.txt" containing the definitions in the first section.
RoundRespawn Example
CCSPlayer::RestartRound is a Counter-Strike Source function which respawns players. It used by CS:S DM. Prototype:
void CCSPlayer::RoundRespawn()
SDKCall example:
#include <sourcemod> #include <sdktools> new Handle:hGameConf; new Handle:hRoundRespawn; public OnPluginInit() { hGameConf = LoadGameConfigFile("plugin.sdkexamples"); StartPrepSDKCall(SDKCall_Player); PrepSDKCall_SetFromConf(hGameConf, SDKConf_Signature, "RoundRespawn"); hRoundRespawn = EndPropSDKCall(); } RespawnPlayer(client) { SDKCall(hRoundRespawn, client); }
Note that we did not have to set any extra information for parameters or return info, since CCSPlayer::RoundRespawn has no parameters and has a void return.
GiveNamedItem Example
GiveNamedItem will give a player a named item. Prototype:
virtual CBaseEntity *CBasePlayer::GiveNamedItem(const char *item, int iSubType = 0);
#include <sourcemod> #include <sdktools> new Handle:hGameConf; new Handle:hGiveNamedItem; public OnPluginInit() { hGameConf = LoadGameConfigFile("plugin.sdkexamples"); StartPrepSDKCall(SDKCall_Player); PrepSDKCall_SetFromConf(hGameConf, SDKConf_Virtual, "GiveNamedItem"); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); hGiveNamedItem = EndPropSDKCall(); } GiveItem(client, const String:item[]) { return SDKCall(hGiveNamedItem, client, item, 0); }