diff --git a/tools/gdc-psyfork/GameConfigs.cpp b/tools/gdc-psyfork/GameConfigs.cpp index c77e6a13..5a5368d3 100644 --- a/tools/gdc-psyfork/GameConfigs.cpp +++ b/tools/gdc-psyfork/GameConfigs.cpp @@ -45,6 +45,7 @@ #define PSTATE_GAMEDEFS_CRC 9 #define PSTATE_GAMEDEFS_CRC_BINARY 10 #define PSTATE_GAMEDEFS_CUSTOM 11 +#define PSTATE_GAMEDEFS_OPTIONS 12 #define WIN 0 #define LIN 1 @@ -134,6 +135,10 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n { m_ParseState = PSTATE_GAMEDEFS_KEYS; } + else if (strcmp(name, "Options") == 0) + { + m_ParseState = PSTATE_GAMEDEFS_OPTIONS; + } else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0)) { m_ParseState = PSTATE_GAMEDEFS_SUPPORTED; @@ -206,6 +211,8 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key } } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { m_Keys.replace(key, m_pStrings->AddString(value)); + } else if (m_ParseState == PSTATE_GAMEDEFS_OPTIONS) { + m_Options.replace(key, m_pStrings->AddString(value)); } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { if (strcmp(key, "game") == 0) { @@ -289,6 +296,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) } case PSTATE_GAMEDEFS_KEYS: case PSTATE_GAMEDEFS_OFFSETS: + case PSTATE_GAMEDEFS_OPTIONS: { m_ParseState = PSTATE_GAMEDEFS; break; @@ -471,6 +479,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) m_Offsets.clear(); m_Sigs.clear(); m_Keys.clear(); + m_Options.clear(); char path[PLATFORM_MAX_PATH]; @@ -557,6 +566,14 @@ const char *CGameConfig::GetKeyValue(const char *key) return m_pStrings->GetString(*pkey); } +const char *CGameConfig::GetOptionValue(const char *key) +{ + int *pkey; + if ((pkey = m_Options.retrieve(key)) == NULL) + return NULL; + return m_pStrings->GetString(*pkey); +} + list CGameConfig::GetOffsets() { return m_Offsets; } list CGameConfig::GetSigs() { return m_Sigs; } diff --git a/tools/gdc-psyfork/GameConfigs.h b/tools/gdc-psyfork/GameConfigs.h index af64c948..c7066469 100644 --- a/tools/gdc-psyfork/GameConfigs.h +++ b/tools/gdc-psyfork/GameConfigs.h @@ -201,6 +201,7 @@ public: //ITextListener_SMC SMCResult ReadSMC_LeavingSection(const SMCStates *states); public: //IGameConfig const char *GetKeyValue(const char *key); + const char *GetOptionValue(const char *key); bool GetOffset(const char *key, int *value); SendProp *GetSendProp(const char *key); bool GetMemSig(const char *key, void **addr); @@ -218,6 +219,7 @@ public: list m_Sigs; // map m_Keys; KTrie m_Keys; + KTrie m_Options; unsigned int m_RefCount; /* Parse states */ int m_ParseState; diff --git a/tools/gdc-psyfork/MemoryUtils.cpp b/tools/gdc-psyfork/MemoryUtils.cpp index 2ffcd8b7..2aa73183 100644 --- a/tools/gdc-psyfork/MemoryUtils.cpp +++ b/tools/gdc-psyfork/MemoryUtils.cpp @@ -67,20 +67,27 @@ MemoryUtils::~MemoryUtils() #endif } -void *MemoryUtils::FindPatternInFile(int fd, const char *pattern, size_t len) +void *MemoryUtils::FindPatternInFile(int fd, const char *pattern, size_t len, int &matches, bool &atFuncStart) { size_t size; size = lseek (fd , 0 , SEEK_END); + + matches = 0; + // TODO: fix this + atFuncStart = true; lseek(fd, 0, SEEK_SET); void *map; - char *ptr, *end; + char *ptr, *start, *end; bool found = true; map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); ptr = (char *)map; + start = ptr; end = ptr + size; + + void *firstMatch = NULL; while (ptr < end) { @@ -95,19 +102,49 @@ void *MemoryUtils::FindPatternInFile(int fd, const char *pattern, size_t len) } if (found) - return ptr; + { + if( !firstMatch ) + { + firstMatch = ptr; + if( ptr - start >= 1 ) + { + unsigned char oneBack = *(unsigned char*)((intptr_t)ptr - 1); + if( oneBack != 0xC3 && oneBack != 0xCB && oneBack != 0xCC ) + { + if( ptr - start >= 3 ) + { + unsigned char threeBack = *(unsigned char*)((intptr_t)ptr - 3); + if( threeBack != 0xCA && threeBack != 0xC2 ) + { + atFuncStart = false; + } + } + else + { + atFuncStart = false; + } + } + } + } + + ++matches; + } - ptr++; + ++ptr; } - return NULL; + return firstMatch; } -void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len) +void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len, int &matches, bool &atFuncStart) { DynLibInfo lib; bool found; char *ptr, *end; + + matches = 0; + // TODO: fix this + atFuncStart = true; memset(&lib, 0, sizeof(DynLibInfo)); @@ -115,7 +152,8 @@ void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t l { return NULL; } - + + void *firstMatch = NULL; ptr = reinterpret_cast(lib.baseAddress); end = ptr + lib.memorySize - 1; @@ -132,12 +170,17 @@ void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t l } if (found) - return ptr; + { + if( !firstMatch ) + firstMatch = ptr; + + ++matches; + } - ptr++; + ++ptr; } - return NULL; + return firstMatch; } void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol) diff --git a/tools/gdc-psyfork/MemoryUtils.h b/tools/gdc-psyfork/MemoryUtils.h index ca8e64e7..d246535a 100644 --- a/tools/gdc-psyfork/MemoryUtils.h +++ b/tools/gdc-psyfork/MemoryUtils.h @@ -64,11 +64,11 @@ public: MemoryUtils(); ~MemoryUtils(); public: // IMemoryUtils - void *FindPattern(const void *libPtr, const char *pattern, size_t len); + void *FindPattern(const void *libPtr, const char *pattern, size_t len, int &matches, bool &atFuncStart); void *ResolveSymbol(void *handle, const char *symbol); const char *ResolveAddr(void *handle, void *addr); public: - void *FindPatternInFile(int fd, const char *pattern, size_t len); + void *FindPatternInFile(int fd, const char *pattern, size_t len, int &matches, bool &atFuncStart); bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib); #if defined PLATFORM_LINUX || defined PLATFORM_APPLE private: diff --git a/tools/gdc-psyfork/example-scripts/gdc_cstrike.sh b/tools/gdc-psyfork/example-scripts/gdc_cstrike.sh index 9fd1258b..7d55a360 100644 --- a/tools/gdc-psyfork/example-scripts/gdc_cstrike.sh +++ b/tools/gdc-psyfork/example-scripts/gdc_cstrike.sh @@ -22,7 +22,7 @@ ENGINE_NAME=orangebox_valve gamedata_files=( "sdktools.games/game.cstrike.txt" "sdktools.games/engine.ep2valve.txt" - "sm-cstrike.games.txt" + "sm-cstrike.games/game.css.txt" ) # Is game a 2006/2007 "mod" ? diff --git a/tools/gdc-psyfork/gdc.cpp b/tools/gdc-psyfork/gdc.cpp index 7a152433..9e2c31f4 100644 --- a/tools/gdc-psyfork/gdc.cpp +++ b/tools/gdc-psyfork/gdc.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gdc.h" #include "GameConfigs.h" #include "MemoryUtils.h" @@ -16,6 +17,11 @@ char *engine_binary = NULL; char *wgame_binary = NULL; char *wengine_binary = NULL; +inline bool IsDigit( char c ) +{ + return c < 58 && c > 47; +} + int main(int argc, char **argv) { char *gamedata = NULL; @@ -125,26 +131,6 @@ int main(int argc, char **argv) return 0; } - const char *vtsym = symbols.GetKeyValue("vtsym"); - if (!vtsym) - { - printf("Couldn't find vtsym\n"); - return 0; - } - - void **vt = (void**) mu.ResolveSymbol(ghandle, vtsym); - if (!vt) - { - printf("Couldn't find vtable %s\n", vtsym); - dlclose(ghandle); - dlclose(ehandle); - close(wgfile); - close(wefile); - - return 0; - } - - for (list::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) { if (debug) @@ -155,34 +141,60 @@ int main(int argc, char **argv) const char *symbol = symbols.GetKeyValue(it->name); if (symbol) { - int newOffset; - char symvt[128]; - strcpy(symvt, it->name); - strcat(symvt, "_vt"); - const char *newvtsym = symbols.GetKeyValue(symvt); - if (newvtsym && newvtsym[0]) + char symvt[128] = "_ZTV"; + bool bGotFirstNumbers = false; + bool bLastNumberDigit = false; + unsigned int symlen = strlen(symbol); + unsigned int pos = strlen(symvt); + + for ( unsigned int i = 0; i < symlen && pos < (sizeof(symvt)-1); ++i ) { - void **newvt = (void**) mu.ResolveSymbol(ghandle, newvtsym); + bool isDigit = IsDigit( symbol[i] ); + if( !isDigit && bLastNumberDigit ) + { + bGotFirstNumbers = true; + } + + // we're before the class len + if( !bGotFirstNumbers && !isDigit ) + continue; + + // we're at the function name len + if( bGotFirstNumbers && isDigit ) + { + symvt[pos] = 0; + break; + } + + // we're at the class len or class name. we want these + symvt[pos++] = symbol[i]; + if( isDigit ) + { + bLastNumberDigit = isDigit; + } + } + symvt[pos] = 0; + + int newOffset; + if (symvt[0]) + { + void **newvt = (void**) mu.ResolveSymbol(ghandle, symvt); if (!newvt) { - printf("O: %-22s - can't find, skipping\n", symvt); + printf("? O: %-22s - can't find, skipping\n", symvt); continue; } newOffset = findVFunc(ghandle, newvt, symbol); } - else - { - newOffset = findVFunc(ghandle, vt, symbol); - } if (newOffset == it->lin) { - printf("O: %-22s - GOOD. current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin); + printf(" O: %-22s - GOOD. current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin); } else { - printf("O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n", + printf("! O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin, newOffset - (it->lin - it->win), newOffset @@ -191,7 +203,7 @@ int main(int argc, char **argv) } else // !symbol { - printf("O: %-22s - no Linux symbol, skipping\n", it->name); + printf(" O: %-22s - no Linux symbol, skipping\n", it->name); } } @@ -210,7 +222,7 @@ int main(int argc, char **argv) bool hasWindows = (winSymbol && winSymbol[0]); if (!hasLinux && !hasWindows) { - printf("S: %-22s - hasn't linux nor windows data, skipping\n", it->name); + printf(" S: %-22s - hasn't linux nor windows data, skipping\n", it->name); continue; } @@ -228,16 +240,17 @@ int main(int argc, char **argv) } else { - printf("S: %-22s - isn't from server nor engine, skipping\n", it->name); + printf(" S: %-22s - isn't from server nor engine, skipping\n", it->name); continue; } - bool foundLinux = (!hasLinux || checkSigStringL(linHandle, linSymbol)); - bool foundWindows = (!hasWindows || checkSigStringW(winFile, winSymbol)); + int linuxMatches = 0, windowsMatches = 0; + if( hasLinux ) + linuxMatches = checkSigStringL(linHandle, linSymbol); + if( hasWindows ) + windowsMatches = checkSigStringW(winFile, winSymbol); - // Prepare for ternery ABUSE - - if (foundLinux && foundWindows) + if (linuxMatches == 1 && windowsMatches == 1) { // too much clutter to print current data if it matches anyway, unlike with offsets /* @@ -248,42 +261,86 @@ int main(int argc, char **argv) linSymbol ? linSymbol : "" ); */ - printf("S: %-22s (%s) - GOOD.\n", + printf(" S: %-22s (%s) - w: GOOD - l: GOOD \n", it->name, (it->lib == Server) ? "server" : "engine" ); } else { - // extra \n at end is intentional to add buffer after possibly long sigs - printf("S: %-22s (%s) - w: %s - l: %s\n%s%s%s%s%s%s%s%s\n", - it->name, - (it->lib == Server) ? "server" : "engine", - hasWindows ? (foundWindows ? "GOOD" : "CHANGED") : "UNKNOWN", - hasLinux ? (foundLinux ? "GOOD" : "CHANGED") : "UNKNOWN", - - hasWindows ? "\tcurrent - w: " : "", - (hasWindows && foundWindows) ? " (found) \"" : (hasWindows ? "(NOT found) \"" : ""), - (hasWindows && winSymbol) ? winSymbol : "", - hasWindows ? "\"\n" : "", - - hasLinux ? "\tcurrent - l: " : "", - (hasLinux && foundLinux) ? " (found) \"" : (hasLinux ? "(NOT found) \"" : ""), - (hasLinux && linSymbol) ? linSymbol : "", - hasLinux ? "\"\n" : "" - ); + char winStatus[16]; + // right now the only option is to ignore + const char *options = symbols.GetOptionValue(it->name); + bool allowMulti = ( options && strstr(options, "allowmultiple") != NULL ); + bool allowMidfunc = ( options && strstr(options, "allowmidfunc") != NULL ); + bool bWinGood = false; + if( !hasWindows ) { + snprintf( winStatus, sizeof(winStatus), "UNKNOWN" ); + } + else if( windowsMatches == -1 && !allowMidfunc) { + snprintf( winStatus, sizeof(winStatus), "MIDFUNC" ); + } + else if( windowsMatches == 0 ) { + snprintf( winStatus, sizeof(winStatus), "NOTFOUND" ); + } + else if( windowsMatches > 1 && !allowMulti) { + snprintf( winStatus, sizeof(winStatus), "MULTIPLE" ); + } + else { + bWinGood = true; + snprintf( winStatus, sizeof(winStatus), "GOOD" ); + } + + char linStatus[16]; + bool bLinGood = false; + if( !hasLinux ) { + snprintf( linStatus, sizeof(linStatus), "UNKNOWN" ); + } + else if( linuxMatches == 0 ) { + snprintf( linStatus, sizeof(linStatus), "NOTFOUND" ); + } + else if( linuxMatches == 1 ) { + bLinGood = true; + snprintf( linStatus, sizeof(linStatus), "GOOD" ); + } + else { + snprintf( linStatus, sizeof(linStatus), "CHECK" ); + } + + bool showWinExtra = (hasWindows && !bWinGood); + bool showLinExtra = ( ( hasLinux && !bLinGood ) || showWinExtra ); + + printf("%s S: %-22s (%s)", (showWinExtra || showLinExtra) ? "!" : " ", it->name, (it->lib == Server) ? "server" : "engine" ); + printf(" - w: %-8s - l: %-8s\n", winStatus, linStatus ); + + if( showWinExtra || showLinExtra ) + printf( "! current:\n" ); + + if( showWinExtra ) + { + printf("! w: \"%s\"\n", + winSymbol ? winSymbol : "" + ); + } + + if( showLinExtra ) + { + // extra \n at end is intentional to add buffer after possibly long sigs + printf("! l: \"%s\"\n\n", + linSymbol ? linSymbol : "" + ); + } } - - // j/k, no way that anyone could have been prepared for that } return 0; } -bool checkSigStringW(int file, const char* symbol) +int checkSigStringW(int file, const char* symbol) { - void *addr = NULL; + int matches = 0; + bool atFuncStart = true; bool isAt = (symbol[0] == '@'); // we can't support this on windows from here if (isAt) @@ -294,23 +351,25 @@ bool checkSigStringW(int file, const char* symbol) if (real_bytes >= 1) { - addr = mu.FindPatternInFile(file, (char*)real_sig, real_bytes); + mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart); } - if (addr) - return true; + if( !atFuncStart ) + return -1; - return false; + return matches; } -bool checkSigStringL(void *handle, const char* symbol) +int checkSigStringL(void *handle, const char* symbol) { - void *addr = NULL; bool isAt = (symbol[0] == '@'); + int matches = 0; + bool dummy; if (isAt) { - addr = mu.ResolveSymbol(handle, symbol + 1); + if( mu.ResolveSymbol(handle, symbol + 1) ) + matches = 1; } else { @@ -319,14 +378,11 @@ bool checkSigStringL(void *handle, const char* symbol) if (real_bytes >= 1) { - addr = mu.FindPattern(handle, (char*)real_sig, real_bytes); + mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy); } } - if (addr) - return true; - - return false; + return matches; } /* diff --git a/tools/gdc-psyfork/gdc.h b/tools/gdc-psyfork/gdc.h index 540f8f60..64ad5404 100644 --- a/tools/gdc-psyfork/gdc.h +++ b/tools/gdc-psyfork/gdc.h @@ -12,8 +12,8 @@ using namespace SourceMod; int findFuncPos(const char* sym); int findVFunc(void *handle, void **vt, const char *symbol); -bool checkSigStringW(int file, const char* symbol); -bool checkSigStringL(void* handle, const char* symbol); +int checkSigStringW(int file, const char* symbol); +int checkSigStringL(void* handle, const char* symbol); size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr); diff --git a/tools/gdc-psyfork/symbols.txt b/tools/gdc-psyfork/symbols.txt index ee4a5ded..dff997c3 100644 --- a/tools/gdc-psyfork/symbols.txt +++ b/tools/gdc-psyfork/symbols.txt @@ -1,30 +1,28 @@ "Games" { + /* + * "Keys" are used to map gamedata offset names to linux symbol. + * "Options" are used to mark validation options for windows signatures. + * Current valid options are: + * allowmultiple - don't warn if multiple matches are found + * allowmidfunc - don't warn if signature does not match the + * start of a function. + * Multiple options can be specified, separating them with a comma. + * ie. "allowmultiple,allowmidfunc" + */ + "#default" { "Keys" { - "vtsym" "_ZTV11CBaseEntity" + // SDKTools "GiveNamedItem" "_ZN11CBasePlayer13GiveNamedItemEPKci" - "GiveNamedItem_vt" "_ZTV11CBasePlayer" - "RemovePlayerItem" "_ZN11CBasePlayer16RemovePlayerItemEP17CBaseCombatWeapon" - "RemovePlayerItem_vt" "_ZTV11CBasePlayer" - "Weapon_GetSlot" "_ZNK20CBaseCombatCharacter14Weapon_GetSlotEi" - "Weapon_GetSlot_vt" "_ZTV20CBaseCombatCharacter" - "Ignite" "_ZN14CBaseAnimating6IgniteEfbfb" - "Ignite_vt" "_ZTV14CBaseAnimating" - "Extinguish" "_ZN14CBaseAnimating10ExtinguishEv" - "Extinguish_vt" "_ZTV14CBaseAnimating" - "Teleport" "_ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS2_" - "CommitSuicide" "_ZN11CBasePlayer13CommitSuicideEbb" - "CommitSuicide_vt" "_ZTV11CBasePlayer" - "GetVelocity" "_ZN11CBaseEntity11GetVelocityEP6VectorS1_" "EyeAngles" "_ZN11CBasePlayer9EyeAnglesEv" "DispatchKeyValue" "_ZN11CBaseEntity8KeyValueEPKcS1_" @@ -32,14 +30,9 @@ "DispatchKeyValueVector" "_ZN11CBaseEntity8KeyValueEPKcRK6Vector" "SetEntityModel" "_ZN11CBaseEntity8SetModelEPKc" "AcceptInput" "_ZN11CBaseEntity11AcceptInputEPKcPS_S2_9variant_ti" - "WeaponEquip" "_ZN11CBasePlayer12Weapon_EquipEP17CBaseCombatWeapon" - "WeaponEquip_vt" "_ZTV20CBaseCombatCharacter" - "Activate" "_ZN11CBaseEntity8ActivateEv" - "PlayerRunCmd" "_ZN11CBasePlayer16PlayerRunCommandEP8CUserCmdP11IMoveHelper" - "PlayerRunCmd_vt" "_ZTV11CBasePlayer" // SDKHooks "EndTouch" "_ZN11CBaseEntity8EndTouchEPS_" @@ -47,11 +40,8 @@ "GroundEntChanged" "_ZN11CBaseEntity35NetworkStateChanged_m_hGroundEntityEv" "OnTakeDamage" "_ZN11CBaseEntity12OnTakeDamageERK15CTakeDamageInfo" "PreThink" "_ZN11CBasePlayer8PreThinkEv" - "PreThink_vt" "_ZTV11CBasePlayer" "PostThink" "_ZN11CBasePlayer9PostThinkEv" - "PostThink_vt" "_ZTV11CBasePlayer" "Reload" "_ZN17CBaseCombatWeapon6ReloadEv" - "Reload_vt" "_ZTV17CBaseCombatWeapon" "SetTransmit" "_ZN11CBaseEntity11SetTransmitEP18CCheckTransmitInfob" "ShouldCollide" "_ZNK11CBaseEntity13ShouldCollideEii" "Spawn" "_ZN11CBaseEntity5SpawnEv" @@ -63,15 +53,33 @@ "Use" "_ZN11CBaseEntity3UseEPS_S0_8USE_TYPEf" "VPhysicsUpdate" "_ZN11CBaseEntity14VPhysicsUpdateEP14IPhysicsObject" "Weapon_CanSwitchTo" "_ZN20CBaseCombatCharacter18Weapon_CanSwitchToEP17CBaseCombatWeapon" - "Weapon_CanSwitchTo_vt" "_ZTV20CBaseCombatCharacter" "Weapon_CanUse" "_ZN20CBaseCombatCharacter13Weapon_CanUseEP17CBaseCombatWeapon" - "Weapon_CanUse_vt" "_ZTV20CBaseCombatCharacter" "Weapon_Drop" "_ZN20CBaseCombatCharacter11Weapon_DropEP17CBaseCombatWeaponPK6VectorS4_" - "Weapon_Drop_vt" "_ZTV20CBaseCombatCharacter" "Weapon_Equip" "_ZN11CBasePlayer12Weapon_EquipEP17CBaseCombatWeapon" - "Weapon_Equip_vt" "_ZTV20CBaseCombatCharacter" "Weapon_Switch" "_ZN20CBaseCombatCharacter13Weapon_SwitchEP17CBaseCombatWeaponi" - "Weapon_Switch_vt" "_ZTV20CBaseCombatCharacter" + + // CEntity extras + "FVisible" "_ZN20CBaseCombatCharacter8FVisibleEP11CBaseEntityiPS1_" + "VPhysicsTakeDamage" "_ZN11CBaseEntity18VPhysicsTakeDamageERK15CTakeDamageInfo" + "VPhysicsGetObjectList" "_ZN11CBaseEntity21VPhysicsGetObjectListEPP14IPhysicsObjecti" + "GetClientEyeAngles" "_ZN11CBaseEntity9EyeAnglesEv" + "WeaponSwitch" "_ZN20CBaseCombatCharacter13Weapon_SwitchEP17CBaseCombatWeaponi" + "CanSpeakVoiceCommand" "_ZN22CBaseMultiplayerPlayer20CanSpeakVoiceCommandEv" + "IsReadyToSpawn" "_ZN11CBasePlayer14IsReadyToSpawnEv" + "OnTakeDamage_Alive" "_ZN20CBaseCombatCharacter18OnTakeDamage_AliveERK15CTakeDamageInfo" + "Jump" "_ZN11CBasePlayer4JumpEv" + "ProcessUserCmds" "_ZN11CBasePlayer15ProcessUsercmdsEP8CUserCmdiiib" + "GetSoundEmissionOrigin" "_ZNK11CBaseEntity22GetSoundEmissionOriginEv" + "GetServerClass" "_ZN11CBaseEntity14GetServerClassEv" + "StudioFrameAdvance" "_ZN14CBaseAnimating18StudioFrameAdvanceEv" + "ShouldGib" "_ZN20CBaseCombatCharacter9ShouldGibERK15CTakeDamageInfo" + "GetRadius" "_ZN13CTFBaseRocket9GetRadiusEv" + "DeflectPlayer" "_ZN13CTFWeaponBase13DeflectPlayerEP9CTFPlayerS1_R6VectorS3_S3_" + } + + "Options" + { + "CreateGameRulesObject" "allowmultiple,allowmidfunc" } } @@ -82,6 +90,7 @@ "engine" "orangebox_valve" "engine" "left4dead2" "engine" "alienswarm" + "engine" "csgo" } "Keys" @@ -100,15 +109,10 @@ "Keys" { "ForceRespawn" "_ZN9CTFPlayer12ForceRespawnEv" - "ForceRespawn_vt" "_ZTV9CTFPlayer" "GiveNamedItemTF" "_ZN9CTFPlayer13GiveNamedItemEPKciP13CEconItemViewb" - "GiveNamedItemTF_vt" "_ZTV9CTFPlayer" "EquipWearable" "_ZN11CBasePlayer13EquipWearableEP13CEconWearable" - "EquipWearable_vt" "_ZTV11CBasePlayer" "RemoveWearable" "_ZN11CBasePlayer14RemoveWearableEP13CEconWearable" - "RemoveWearable_vt" "_ZTV11CBasePlayer" "GrenadeDetonate" "_ZN12CBaseGrenade8DetonateEv" - "GrenadeDetonate_vt" "_ZTV12CBaseGrenade" } } @@ -117,13 +121,38 @@ "#supported" { "engine" "left4dead" - "engine" "left4dead2" + "game" "left4dead2" } "Keys" { "GiveNamedItem" "_ZN9CCSPlayer13GiveNamedItemEPKci" - "GiveNamedItem_vt" "_ZTV9CCSPlayer" + } + } + + "#default" + { + "#supported" + { + "game" "nucleardawn" + } + "Keys" + { + "GiveNamedItem" "_ZN9CNDPlayer13GiveNamedItemEPKcib" + } + } + + "#default" + { + "#supported" + { + "engine" "csgo" + } + + "Keys" + { + "Teleport" "_ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS2_b" + "GiveNamedItem" "_ZN11CBasePlayer13GiveNamedItemEPKcib" } } }