diff --git a/addons/sourcemod/gamedata/showplayerclips.games.txt b/addons/sourcemod/gamedata/showplayerclips.games.txt new file mode 100644 index 0000000..ef71465 --- /dev/null +++ b/addons/sourcemod/gamedata/showplayerclips.games.txt @@ -0,0 +1,312 @@ +"Games" +{ + "#default" + { + "Keys" + { + //EngineTrace interface name + "CEngineTrace" "EngineTraceServer004" + + //leafvis_t offsets + "leafvis_t::verts" "0" + "leafvis_t::polyVertCount" "20" + "leafvis_t::color" "40" + "leafvis_t::numbrushes" "52" + "leafvis_t::numentitychars" "56" + "leafvis_t::leafIndex" "60" + + //CUtlVector offsets + "CUtlVector::m_pMemory" "0" + "CUtlVector::m_nAllocationCount" "4" + "CUtlVector::m_nGrowSize" "8" + "CUtlVector::m_Size" "12" + "CUtlVector::m_pElements" "16" + + //CRangeValidatedArray offsets + "CRangeValidatedArray::m_pArray" "0" + "CRangeValidatedArray::m_nCount" "4" + + //cplane_t + "cplane_t::normal" "0" + "cplane_t::dist" "12" + "cplane_t::type" "16" + "cplane_t::signbits" "17" + + //cnode_t offsets + "cnode_t::plane" "0" + "cnode_t::children" "4" + "cnode_t::size" "12" + + //cboxbrush_t offsets + "cboxbrush_t::mins" "0" + "cboxbrush_t::maxs" "16" + "cboxbrush_t::surfaceIndex" "32" + "cboxbrush_t::size" "48" + + //cbrush_t offsets + "cbrush_t::contents" "0" + "cbrush_t::numsides" "4" + "cbrush_t::firstbrushside" "6" + "cbrush_t::size" "8" + + //cleaf_t offsets + "cleaf_t::contents" "0" + "cleaf_t::cluster" "4" + "cleaf_t::area" "6" + "cleaf_t::flags" "7" + "cleaf_t::firstleafbrush" "8" + "cleaf_t::numleafbrushes" "10" + "cleaf_t::dispListStart" "12" + "cleaf_t::dispCount" "14" + "cleaf_t::size" "16" + + //cbrushside_t offsets + "cbrushside_t::plane" "0" + "cbrushside_t::surfaceIndex" "4" + "cbrushside_t::bBevel" "6" + "cbrushside_t::size" "8" + + //cmodel_t offsets + "cmodel_t::mins" "0" + "cmodel_t::maxs" "12" + "cmodel_t::origin" "24" + "cmodel_t::headnode" "36" + //... + } + + "Offsets" + { + "WinOrLin" + { + "windows" "1" + "linux" "2" + } + } + + "Signatures" + { + "CreateInterface" + { + "library" "engine" + "windows" "@CreateInterface" + "linux" "@CreateInterface" + } + } + } + + "csgo" + { + "Keys" + { + //CUtlVectorUnknown size + "CUtlVectorUnknown::m_pElements::size" "8" + + //cmodel_t size + "cmodel_t::size" "56" + + //BrushSideInfo_t + "BrushSideInfo_t::plane" "0" + "BrushSideInfo_t::bevel" "20" + "BrushSideInfo_t::thin" "22" + "BrushSideInfo_t::Size" "24" + + //CCollisionBSPData offsets + "CCollisionBSPData::map_rootnode" "0" + //... + "CCollisionBSPData::numbrushsides" "100" + "CCollisionBSPData::map_brushsides" "104" + "CCollisionBSPData::numboxbrushes" "112" + "CCollisionBSPData::map_boxbrushes" "116" + //... + "CCollisionBSPData::numleafs" "148" + "CCollisionBSPData::map_leafs" "152" + //... + "CCollisionBSPData::numleafbrushes" "168" + "CCollisionBSPData::map_leafbrushes" "172" + "CCollisionBSPData::numcmodels" "180" + "CCollisionBSPData::map_cmodels" "184" + "CCollisionBSPData::numbrushes" "192" + "CCollisionBSPData::map_brushes" "196" + //... + } + + "Addresses" + { + "g_BSPData" + { + "linux" + { + "signature" "CM_LoadMap" + "read" "58" + } + } + } + + "Signatures" + { + "LeafVisDraw" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x83\xE4\xF8\x8B\x0D\x2A\x2A\x2A\x2A\x81\xEC\x34\x03\x00\x00" + } + + "DrawLeafVis" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x81\xEC\x1C\x02\x00\x00\x53\x56\x57" + } + + "RecomputeClipbrushes" + { + "library" "engine" + "windows" "\x53\x8B\xDC\x83\xEC\x08\x83\xE4\xF8\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x83\xEC\x70\x56\x57" + } + + "PolyFromPlane" + { + "library" "engine" + "linux" "\x55\x31\xD2\x89\xE5\x56\x53\x83\xEC\x2C" + } + + "ClipPolyToPlane" + { + "library" "engine" + "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\xC7\x45\xD8\x00\x00\x00\x00" + } + + "CEngineTrace::GetBrushInfo" + { + "library" "engine" + "linux" "\x55\x31\xC0\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x75\x0C\x8B\x5D\x14" + } + + "CM_LoadMap" + { + "library" "engine" + "linux" "\x55\x89\xE5\x83\xEC\x28\x89\x5D\xF4\x8B\x5D\x08\xC7\x04\x24\x2A\x2A\x2A\x2A" + } + + "malloc" + { + "library" "engine" + "linux" "\x55\x89\xE5\x5D\xE9\x2A\x2A\x2A\x2A\x8D\xB4\x26\x2A\x2A\x2A\x2A\x55\xA1\x2A\x2A\x2A\x2A" + } + + "free" + { + "library" "engine" + "linux" "\x55\x89\xE5\x5D\xE9\x2A\x2A\x2A\x2A\x8D\xB4\x26\x00\x00\x00\x00\x55\x89\xE5\x5D\xE9\x2A\x2A\x2A\x2A\x8D\xB4\x26\x00\x00\x00\x00\x55\xA1\x2A\x2A\x2A\x2A" + } + } + } + + "cstrike" + { + "Keys" + { + //CUtlVectorUnknown size + "CUtlVectorUnknown::m_pElements::size" "4" + + //cmodel_t size + "cmodel_t::size" "52" + + //BrushSideInfo_t + "BrushSideInfo_t::plane" "0" + "BrushSideInfo_t::bevel" "16" + "BrushSideInfo_t::thin" "18" + + //CCollisionBSPData offsets + "CCollisionBSPData::map_rootnode" "0" + //... + "CCollisionBSPData::numbrushsides" "100" + "CCollisionBSPData::map_brushsides" "104" + "CCollisionBSPData::numboxbrushes" "108" + "CCollisionBSPData::map_boxbrushes" "112" + //... + "CCollisionBSPData::numleafs" "132" + "CCollisionBSPData::map_leafs" "136" + //... + "CCollisionBSPData::numleafbrushes" "148" + "CCollisionBSPData::map_leafbrushes" "152" + "CCollisionBSPData::numcmodels" "156" + "CCollisionBSPData::map_cmodels" "160" + "CCollisionBSPData::numbrushes" "164" + "CCollisionBSPData::map_brushes" "168" + //... + } + + "Addresses" + { + "g_BSPData" + { + "linux" + { + "signature" "g_BSPData" + } + } + } + + "Signatures" + { + "LeafVisDraw" + { + "library" "engine" + "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x81\xEC\x7C\x03\x00\x00" + } + + "DrawLeafVis" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x81\xEC\xFC\x01\x00\x00\x8B\x0D\x2A\x2A\x2A\x2A" + } + + "RecomputeClipbrushes" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x83\xEC\x4C\x56\x57\xBF\x2A\x2A\x2A\x2A" + } + + "PolyFromPlane" + { + "library" "engine" + "linux" "@_Z13PolyFromPlaneP6VectorRKS_ff" + } + + "ClipPolyToPlane" + { + "library" "engine" + "linux" "@_Z15ClipPolyToPlaneP6VectoriS0_RKS_ff" + } + + "CM_LoadMap" + { + "library" "engine" + "linux" "@_Z10CM_LoadMapPKcbPj" + } + + "CEngineTrace::GetBrushInfo" + { + "library" "engine" + "linux" "@_ZN12CEngineTrace12GetBrushInfoEiP10CUtlVectorI8Vector4D10CUtlMemoryIS1_iEEPi" + } + + "malloc" + { + "library" "engine" + "linux" "@_ZL7SzAllocPvj" + } + + "free" + { + "library" "engine" + "linux" "@_ZL6SzFreePvS_" + } + + "g_BSPData" + { + "library" "engine" + "linux" "@g_BSPData" + } + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/dhooks_macros.inc b/addons/sourcemod/scripting/include/dhooks_macros.inc new file mode 100644 index 0000000..894ec47 --- /dev/null +++ b/addons/sourcemod/scripting/include/dhooks_macros.inc @@ -0,0 +1,45 @@ +#if defined _dhooks_macros_include +#endinput +#else +#define _dhooks_macros_include +#endif + +#if !defined SNAME +#define __SNAME "" +#else +#define __SNAME SNAME +#endif + +#define ASSERT_FMT_STRING_LEN 512 + +#define ASSERT(%1,%2) if(%1) SetFailState(__SNAME...%2) +stock void ASSERT_FMT(bool result, char[] fmt, any ...) +{ + if(result) + { + char buff[ASSERT_FMT_STRING_LEN]; + VFormat(buff, sizeof(buff), fmt, 3); + + SetFailState(__SNAME..."%s", buff); + } +} + +/** +* Setups detour dhook (Handle DHOOK, CallingConvention, ReturnType, ThisPointerType, Handle GCONF, SDKFuncConfSource, char[] GCONF_NAME) +*/ +#define DHOOK_SETUP_DETOUR(%1,%2,%3,%4,%5,%6,%7) Handle %1 = DHookCreateDetour(Address_Null,%2,%3,%4); \ +ASSERT(!%1, "Failed to create detour. ["...%7..."]"); \ +ASSERT(!DHookSetFromConf(%1,%5,%6,%7), "Failed to set from conf. ["...%7..."]") + +/** +* Setups offset dhook (Handle DHOOK, HookType, ReturnType, ThisPointerType, DhookCallback, Handle GCONF, char[] GCONF_NAME) +*/ +#define DHOOK_SETUP(%1,%2,%3,%4,%5,%6,%7) Handle %1 = DHookCreate(GameConfGetOffset(%6, %7), %2, %3, %4, %5); \ +ASSERT(!%1, "Failed to create dhook. ["...%7..."]") + +/** +* Setups gameconfig (Handle GCONF, Filename) +*/ +#define SETUP_GAMECONF(%1,%2) Handle %1 = LoadGameConfigFile(%2); \ +ASSERT(!%1, "Failed to open \""...%2...".txt\"") + diff --git a/addons/sourcemod/scripting/showplayerclips.sp b/addons/sourcemod/scripting/showplayerclips.sp new file mode 100644 index 0000000..ba5cfbc --- /dev/null +++ b/addons/sourcemod/scripting/showplayerclips.sp @@ -0,0 +1,939 @@ +#include "sourcemod" +#include "sdktools" +#include "sdkhooks" +#include "dhooks" +#include "dhooks_macros" +#include "regex" + +#define SNAME "[ShowPlayerClips] " +#define GAMECONF_FILENAME "showplayerclips.games" +#define TRANSLATE_FILENAME "showplayerclips.phrases" + +#define MAX_TEMPENTS_SEND_CSS 64 - 8 +#define MAX_TEMPENTS_SEND_CSGO 255 - 24 +#define PVIS_COUNT 3 +#define TEMPENT_MIN_LIFETIME 2.0 +#define TEMPENT_MAX_LIFETIME 25.0 +#define INTERNAL_REFRESHTIME 0.02 + +#define MAX_LEAF_PVERTS 128 +#define NUMSIDES_BOXBRUSH 0xFFFF + +//Cache data in plugin? +#define USE_CACHED_VALS 0 + +//Enable env_spritetrail draw +//#define USE_SPRITETRAIL 0 + +/*#if USE_SPRITETRAIL 1 +#define SPRITETRAIL_REFRESHRATE 1.0 +#define SPRITETRAIL_MATERIAL "" +#endif*/ + +public Plugin myinfo = +{ + name = "Show Player Clip Brushes", + author = "GAMMA CASE", + description = "Shows player clip brushes on map.", + version = "1.0.0", + url = "http://steamcommunity.com/id/_GAMMACASE_/" +}; + +enum OSType +{ + OSUnknown = 0, + OSWindows = 1, + OSLinux = 2 +}; + +OSType gOSType; +EngineVersion gEngineVer; + +Handle ghLeafVisDraw, + ghRecomputeClipbrushes, +//Linux only + ghPolyFromPlane, + ghClipPolyToPlane, + ghMalloc, + ghFree; +//==- + +#include "spc/methodmaps.sp" +//#include "spc_debug" + +ConVar gCvarCommands, + gCvarBeamRefreshRate, + gCvarBeamAlpha, + gCvarBeamWidth, + gCvarBeamSearchDelta, + gCvarBeamMaterial; + +ArrayList gClientsToDraw, + gFinalPolyCountEnd[PVIS_COUNT], + gFinalVerts[PVIS_COUNT]; + +//Linux only +CCollisionBSPData gpBSPData; +//==- + +int gModelIndex, + gpVisIdx, + gDrawCount[PVIS_COUNT], + gTotalCounter, + gColor[PVIS_COUNT][4]; + +#if USE_CACHED_VALS 1 +ArrayList gVerts[PVIS_COUNT], + gPolyVertCount[PVIS_COUNT]; +#else +Leafvis_t gpVis[PVIS_COUNT]; +#endif + +public void OnPluginStart() +{ + gCvarCommands = CreateConVar("spc_commands", "sm_showbrushes;sm_showclips;sm_showclipbrushes;sm_showplayerclips;sm_scb;sm_spc", "Available command names for toggling clip brushes visibility. (NOTE: Write command names with \"sm_\" prefix, and don't use ! or any other symbol except A-Z, 0-9 or underline symbol \"_\", also server needs to be restarted to see changes!)") + gCvarBeamRefreshRate = CreateConVar("spc_beams_refresh_rate", "5.0", "Refresh rate at which beams will be drawn, don't set this to very low value! Map restart needed for this to take effect.", .hasMin = true, .min = 0.1, .hasMax = true, .max = TEMPENT_MAX_LIFETIME); + gCvarBeamAlpha = CreateConVar("spc_beams_alpha", "255", "Alpha value for beams, lower = more transperent. Map restart needed for this to take effect.", .hasMin = true, .hasMax = true, .max = 255.0); + gCvarBeamWidth = CreateConVar("spc_beams_width", "1.0", "Beams width, lower = less visible from distance.", .hasMin = true); + gCvarBeamSearchDelta = CreateConVar("spc_beams_search_delta", "0.5", "Leave this value as default or a bit smaller then default. Lower the value, more precision for beams, more beams drawn, lower the fps will be. Set to 0 to disable. Map restart needed for this to take effect.", .hasMin = true); + gCvarBeamMaterial = CreateConVar("spc_beams_material", "sprites/laserbeam.vmt", "Material used for beams. Server restart needed for this to take effect."); + AutoExecConfig(); + + LoadTranslations(TRANSLATE_FILENAME); + RegConsoleCommands(); + + gEngineVer = GetEngineVersion(); + + gClientsToDraw = new ArrayList(); + + SETUP_GAMECONF(gconf, GAMECONF_FILENAME); + + GetOSType(gconf); + RetrieveOffsets(gconf); + SetupDhooks(gconf); + SetupSDKCalls(gconf); + + if(gOSType == OSLinux) + { + //CreateInterfaces(gconf); + GetCollisionBSPData(gconf); + } + + delete gconf; +} + +public void RegConsoleCommands() +{ + char buff[1024]; + gCvarCommands.GetString(buff, sizeof(buff)); + + if(buff[0] == '\0') + return; + + char error[64]; + RegexError ErrorCode; + Regex reg = new Regex("[a-zA-Z_0-9]+", 0, error, sizeof(error), ErrorCode); + if(error[0] != '\0') + SetFailState("[RegConsoleCommands] Regex error: \"%s\", with error code: %i", error, ErrorCode); + + int num = reg.MatchAll(buff, ErrorCode); + if(ErrorCode != REGEX_ERROR_NONE) + SetFailState("[RegConsoleCommands] Regex match error, error code: %i", ErrorCode); + + char sMatch[32]; + for(int i = 0; i < num; i++) + { + reg.GetSubString(0, sMatch, sizeof(sMatch), i); + RegConsoleCmd(sMatch, SM_ShowClipBrushes, "Shows player clip brushes."); + } +} + +public void OnMapStart() +{ + char buff[PLATFORM_MAX_PATH]; + gCvarBeamMaterial.GetString(buff, sizeof(buff)); + gModelIndex = PrecacheModel(buff, true); + + if(gOSType == OSWindows) + { + SDKCall(ghRecomputeClipbrushes, true); + SDKCall(ghLeafVisDraw); + } + else if(gOSType == OSLinux) + { + RecomputeClipbrushes(); + } + + if(IsClipsPresent()) + { + CreateTimer(gCvarBeamRefreshRate.FloatValue, RedrawClipBrushes, .flags = TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT); + } +} + +stock bool IsClipsPresent() +{ + for(int i = 0; i < PVIS_COUNT; i++) + if(gFinalVerts[i]) + return true; + return false; +} + +public void OnMapEnd() +{ +#if USE_CACHED_VALS 1 + for(int i = 0; i < PVIS_COUNT; i++) + { + if(gOSType == OSWindows) + { + delete gVerts[i]; + delete gPolyVertCount[i]; + } + + delete gFinalVerts[i]; + delete gFinalPolyCountEnd[i]; + for(int j = 0; j < sizeof(gColor); j++) + gColor[i][j] = 0; + } +#else + for(int i = 0; i < PVIS_COUNT; i++) + { + if(gOSType == OSWindows) + gpVis[i] = view_as(0); + + delete gFinalVerts[i]; + delete gFinalPolyCountEnd[i]; + for(int j = 0; j < sizeof(gColor); j++) + gColor[i][j] = 0; + } +#endif + + gpVisIdx = 0; +} + +public void OnClientDisconnect(int client) +{ + int idx = gClientsToDraw.FindValue(GetClientUserId(client)); + if(idx != -1) + gClientsToDraw.Erase(idx); +} + +public Action DrawClipBrushes(Handle timer) +{ + static int clients[MAXPLAYERS]; + int counter; + float vec[3], vec2[3]; + + GetClientsToDraw(clients, sizeof(clients)); + + for(int i = 0; i < PVIS_COUNT; i++) + { + if(!gFinalVerts[i]) + continue; + + for(int j = gDrawCount[i]; j < gFinalVerts[i].Length - 1; j++) + { + if(gFinalPolyCountEnd[i].Get(j) == 1) + continue; + + gFinalVerts[i].GetArray(j, vec); + gFinalVerts[i].GetArray(j + 1, vec2); + + //TODO: Rethink the way beams are drawn + TE_SetupBeamPoints(vec, vec2, gModelIndex, 0, 0, 0, + Clamp(gCvarBeamRefreshRate.FloatValue + (float(gTotalCounter) / float((gEngineVer == Engine_CSGO ? MAX_TEMPENTS_SEND_CSGO : MAX_TEMPENTS_SEND_CSS)) * INTERNAL_REFRESHTIME), TEMPENT_MIN_LIFETIME, TEMPENT_MAX_LIFETIME), + gCvarBeamWidth.FloatValue, gCvarBeamWidth.FloatValue, 0, 0.0, gColor[i], 0); + TE_Send(clients, gClientsToDraw.Length); + + gDrawCount[i]++; + counter++; + gTotalCounter++; + + if(counter >= (gEngineVer == Engine_CSGO ? MAX_TEMPENTS_SEND_CSGO : MAX_TEMPENTS_SEND_CSS)) + { + CreateTimer(INTERNAL_REFRESHTIME, DrawClipBrushes, .flags = TIMER_FLAG_NO_MAPCHANGE); + return Plugin_Continue; + } + } + } + + return Plugin_Continue; +} + +public Action RedrawClipBrushes(Handle timer) +{ + if(gClientsToDraw.Length == 0) + return Plugin_Continue; + + for(int i = 0; i < PVIS_COUNT; i++) + gDrawCount[i] = 0; + gTotalCounter = 0; + DrawClipBrushes(INVALID_HANDLE); + + return Plugin_Continue; +} + +stock void GetClientsToDraw(int[] clients, int size) +{ + int client; + for(int i = 0; i < gClientsToDraw.Length; i++) + { + if(i > size) + break; + + client = GetClientOfUserId(gClientsToDraw.Get(i)); + + if(client <= 0 || client > MaxClients || !IsClientConnected(client) || !IsClientInGame(client) || IsFakeClient(client)) + { + gClientsToDraw.Erase(i); + i--; + continue; + } + + clients[i] = client; + } +} + +public Action SM_ShowClipBrushes(int client, int args) +{ + int idx = gClientsToDraw.FindValue(GetClientUserId(client)); + if(idx != -1) + { + gClientsToDraw.Erase(idx); + ReplyToCommand(client, "%T", "playerclips_disabled", client); + } + else + { + gClientsToDraw.Push(GetClientUserId(client)); + ReplyToCommand(client, "%T", "playerclips_enabled", client); + } + + return Plugin_Handled; +} + +void GetOSType(Handle gconf) +{ + gOSType = view_as(GameConfGetOffset(gconf, "WinOrLin")); + + ASSERT(gOSType == OSUnknown, "Failed to get OS type. Make sure gamedata file is in gamedata folder, and you are using windows or linux."); +} + +void SetupDhooks(Handle gconf) +{ + if(gOSType == OSWindows) + { + DHOOK_SETUP_DETOUR(dhook, CallConv_CDECL, ReturnType_Void, ThisPointer_Ignore, gconf, SDKConf_Signature, "DrawLeafVis"); + + DHookAddParam(dhook, HookParamType_Int, .custom_register = (gEngineVer == Engine_CSGO ? DHookRegister_ECX : DHookRegister_Default)); + + ASSERT(!DHookEnableDetour(dhook, false, DrawLeafVis_CallBack), "Failed to enable detour for \"DrawLeafVis\"."); + } +} + +void SetupSDKCalls(Handle gconf) +{ + if(gOSType == OSWindows) + { + //LeafVisDraw + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "LeafVisDraw"), "Failed to get \"LeafVisDraw\" signature."); + + ghLeafVisDraw = EndPrepSDKCall(); + ASSERT(!ghLeafVisDraw, "Failed to create SDKCall to \"LeafVisDraw\"."); + + + //RecomputeClipbrushes + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "RecomputeClipbrushes"), "Failed to get \"RecomputeClipbrushes\" signature."); + + PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); + + ghRecomputeClipbrushes = EndPrepSDKCall(); + ASSERT(!ghRecomputeClipbrushes, "Failed to create SDKCall to \"RecomputeClipbrushes\"."); + } + else if(gOSType == OSLinux) + { + //PolyFromPlane + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "PolyFromPlane"), "Failed to get \"PolyFromPlane\" signature."); + + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef, .encflags = VENCODE_FLAG_COPYBACK); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + + ghPolyFromPlane = EndPrepSDKCall(); + ASSERT(!ghPolyFromPlane, "Failed to create SDKCall to \"PolyFromPlane\"."); + + //ClipPolyToPlane + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "ClipPolyToPlane"), "Failed to get \"ClipPolyToPlane\" signature."); + + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + + ghClipPolyToPlane = EndPrepSDKCall(); + ASSERT(!ghClipPolyToPlane, "Failed to create SDKCall to \"ClipPolyToPlane\"."); + + //malloc + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "malloc"), "Failed to get \"malloc\" signature."); + + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + if(gEngineVer == Engine_CSS) + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + + ghMalloc = EndPrepSDKCall(); + ASSERT(!ghMalloc, "Failed to create SDKCall to \"malloc\"."); + + //free + StartPrepSDKCall(SDKCall_Static); + ASSERT(!PrepSDKCall_SetFromConf(gconf, SDKConf_Signature, "free"), "Failed to get \"free\" signature."); + + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + if(gEngineVer == Engine_CSS) + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + + ghFree = EndPrepSDKCall(); + ASSERT(!ghFree, "Failed to create SDKCall to \"free\"."); + } +} + +void GetCollisionBSPData(Handle gconf) +{ + gpBSPData = CCollisionBSPData(GameConfGetAddress(gconf, "g_BSPData")); + ASSERT(gpBSPData.Address == Address_Null, "Invalid gpBSPData retrieved from \"g_BSPData\" address."); +} + +void RecomputeClipbrushes() +{ + int ibrush, contents[PVIS_COUNT] = {CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP, CONTENTS_MONSTERCLIP, CONTENTS_PLAYERCLIP}; + + ArrayList planeList = new ArrayList(4); + float normal[3], mins[3], maxs[3]; + Cbrush_t pBrush; + Cboxbrush_t pBox; + Cbrushside_t pSide; + + ArrayList vertsList = new ArrayList(3); + ArrayList vertCountList = new ArrayList(); + + int lastBrush = gpBSPData.numbrushes; + if(gpBSPData.numcmodels > 1) + lastBrush = FindMinBrush(view_as(gpBSPData.map_cmodels.Get(1, Cmodel_t.Size())).headnode, lastBrush); + + for(int j = 0; j < PVIS_COUNT; j++) + { + vertsList.Clear(); + vertCountList.Clear(); + + gColor[j][0] = j != 1 ? 255 : 125; + gColor[j][1] = 0; + gColor[j][2] = j != 0 ? 255 : 0; + gColor[j][3] = gCvarBeamAlpha.IntValue; + + for(ibrush = 0; ibrush < lastBrush; ibrush++) + { + pBrush = view_as(gpBSPData.map_brushes.Get(ibrush, Cbrush_t.Size())); + if((pBrush.contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP)) == contents[j]) + { + planeList.Clear(); + + if(pBrush.IsBox()) + { + pBox = view_as(gpBSPData.map_boxbrushes.Get(pBrush.GetBox(), Cboxbrush_t.Size())); + pBox.mins.ToArray(mins); + pBox.maxs.ToArray(maxs); + + for(int i = 0; i < 3; i++) + { + normal[0] = 0.0; + normal[1] = 0.0; + normal[2] = 0.0; + + normal[i] = 1.0; + + AddPlaneToList(planeList, normal, maxs[i], true); + NegateVector(normal); + AddPlaneToList(planeList, normal, -mins[i], true); + } + } + else + { + for(int i = 0; i < pBrush.numsides; i++) + { + pSide = view_as(gpBSPData.map_brushsides.Get(pBrush.firstbrushside + i, Cbrushside_t.Size())); + + if(pSide.bBevel == 1) + continue; + + pSide.plane.normal.ToArray(normal); + + AddPlaneToList(planeList, normal, pSide.plane.dist, true); + } + } + + CSGPlaneList(planeList, vertsList, vertCountList); + } + } + + CalculateVertsLinux(j, vertsList, vertCountList); + } + + delete vertsList; + delete vertCountList; + delete planeList; +} + +int FindMinBrush(int nodenum, int brushIndex) +{ + int leafIndex, firstbrush; + Cleaf_t leaf; + Cnode_t node; + + for(;;) + { + if(nodenum < 0) + { + leafIndex = -1 - nodenum; + leaf = view_as(gpBSPData.map_leafs.Get(leafIndex, Cleaf_t.Size())); + firstbrush = gpBSPData.map_leafbrushes.GetValue(leaf.firstleafbrush, 2, NumberType_Int16); + + if(firstbrush < brushIndex) + brushIndex = firstbrush; + + break; + } + + node = view_as(gpBSPData.map_rootnode.Get(nodenum)); + brushIndex = FindMinBrush(node.children(0), brushIndex); + nodenum = node.children(1); + } + + return brushIndex; +} + +void AddPlaneToList(ArrayList list, const float normal[3], float dist, bool invert) +{ + float plane_normal[3], plane_dist = invert ? -dist : dist; + plane_normal[0] = invert ? -normal[0] : normal[0]; + plane_normal[1] = invert ? -normal[1] : normal[1]; + plane_normal[2] = invert ? -normal[2] : normal[2]; + + float point[3], vec4d[4], d, vec[3]; + point = plane_normal; + ScaleVector(point, plane_dist); + for(int i = 0; i < list.Length; i++) + { + list.GetArray(i, vec4d); + vec[0] = vec4d[0]; + vec[1] = vec4d[1]; + vec[2] = vec4d[2]; + if(vec[0] == plane_normal[0] && vec[1] == plane_normal[1] && vec[2] == plane_normal[2]) + { + d = GetVectorDotProduct(point, vec) - vec4d[3]; + if(d > 0.0) + { + list.Set(i, plane_dist, 3); + } + + return; + } + } + + vec4d[0] = plane_normal[0]; + vec4d[1] = plane_normal[1]; + vec4d[2] = plane_normal[2]; + vec4d[3] = plane_dist; + list.PushArray(vec4d); +} + +void CSGPlaneList(ArrayList planeList, ArrayList vertsList, ArrayList vertCountList) +{ + PseudoPtrArray vertsIn = PseudoPtrArray(MAX_LEAF_PVERTS, Vector.Size()); + PseudoPtrArray vertsOut = PseudoPtrArray(MAX_LEAF_PVERTS, Vector.Size()); + float insidePoint[3], normal[3], vec4d[4], verts[3]; + int vertCount, vertCount2; + + CSGInsidePoint(planeList, insidePoint); + NegateVector(insidePoint); + TranslatePlaneList(planeList, insidePoint); + NegateVector(insidePoint); + + for(int i = 0; i < planeList.Length; i++) + { + planeList.GetArray(i, vec4d); + normal[0] = vec4d[0]; + normal[1] = vec4d[1]; + normal[2] = vec4d[2]; + vertCount = SDKCall(ghPolyFromPlane, vertsIn.Address, normal, vec4d[3], 9000.0); + + for(int j = 0; j < planeList.Length; j++) + { + if(i == j) + continue; + + if(vertCount < 3) + continue; + + planeList.GetArray(j, vec4d); + normal[0] = vec4d[0]; + normal[1] = vec4d[1]; + normal[2] = vec4d[2]; + + vertCount = SDKCall(ghClipPolyToPlane, vertsIn.Address, vertCount, vertsOut.Address, normal, vec4d[3], 0.1); + vertCount2 = 0; + + if(vertCount >= 4) + { + int tv = ((vertCount - 4) >> 2) + 1; + vertCount2 = 4 * tv; + + int tv2; + for(int k = 0; k < tv; k++) + { + view_as(vertsOut.Get(tv2)).CopyTo(view_as(vertsIn.Get(tv2))); + view_as(vertsOut.Get(tv2 + 1)).CopyTo(view_as(vertsIn.Get(tv2 + 1))); + view_as(vertsOut.Get(tv2 + 2)).CopyTo(view_as(vertsIn.Get(tv2 + 2))); + view_as(vertsOut.Get(tv2 + 3)).CopyTo(view_as(vertsIn.Get(tv2 + 3))); + + tv2 += 4; + } + } + + if(vertCount2 < vertCount) + { + for(int k = 0; k < vertCount - vertCount2; k++) + view_as(vertsOut.Get(vertCount2 + k)).CopyTo(view_as(vertsIn.Get(vertCount2 + k))); + } + } + + if(vertCount >= 3) + { + vertCountList.Push(vertCount); + for(int j = 0; j < vertCount; j++) + { + view_as(vertsIn.Get(j)).ToArray(verts); + AddVectors(verts, insidePoint, verts); + vertsList.PushArray(verts); + } + } + } + + vertsIn.Free(); + vertsOut.Free(); +} + +void CSGInsidePoint(ArrayList planes, float point[3]) +{ + float vec4d[4], normal[3], d; + + for(int i = 0; i < planes.Length; i++) + { + planes.GetArray(i, vec4d); + + normal[0] = vec4d[0]; + normal[1] = vec4d[1]; + normal[2] = vec4d[2]; + + d = GetVectorDotProduct(normal, point) - vec4d[3]; + + if(d < 0) + { + ScaleVector(normal, d); + SubtractVectors(point, normal, point); + } + } +} + +void TranslatePlaneList(ArrayList planes, float offset[3]) +{ + float vec4d[4], normal[3]; + for(int i = 0; i < planes.Length; i++) + { + planes.GetArray(i, vec4d); + + normal[0] = vec4d[0]; + normal[1] = vec4d[1]; + normal[2] = vec4d[2]; + + vec4d[3] += GetVectorDotProduct(offset, normal); + + planes.SetArray(i, vec4d); + } +} + +void CalculateVertsLinux(int pVisIdx, ArrayList vertsList, ArrayList vertCountList) +{ + gFinalVerts[pVisIdx] = new ArrayList(3); + gFinalPolyCountEnd[pVisIdx] = new ArrayList(); + ArrayList locvectors = new ArrayList(3); + int vert, vertcount, lastidx; + float vec[3], vec2[3]; + + for(int i = 0; i < vertCountList.Length; i++) + { + vertcount = vertCountList.Get(i); + if(vertcount >= 3) + { + for(int j = 0; j < vertcount; j++) + { + vertsList.GetArray(vert + j, vec); + vertsList.GetArray(vert + ((j + 1) % vertcount), vec2); + + if(IsVectorInArray(locvectors, vec, vec2)) + { + if(j == vertcount - 1 && lastidx != 0) + gFinalPolyCountEnd[pVisIdx].Set(lastidx, 1); + continue; + } + + gFinalVerts[pVisIdx].PushArray(vec); + gFinalVerts[pVisIdx].PushArray(vec2); + + gFinalPolyCountEnd[pVisIdx].Push(0); + lastidx = gFinalPolyCountEnd[pVisIdx].Push(j == vertcount - 1 ? true : false); + } + } + + lastidx = 0; + vert += vertcount; + } + + delete locvectors; +} + +public MRESReturn DrawLeafVis_CallBack(Handle hParams) +{ + Leafvis_t pVis = Leafvis_t(DHookGetParam(hParams, 1)); + + if(!pVis || (!pVis.verts.m_pElements || !pVis.polyVertCount.m_pElements) || (pVis.verts.Length == 0 || pVis.polyVertCount.Length == 0) || gpVisIdx > PVIS_COUNT - 1) + return MRES_Supercede; + + gColor[gpVisIdx][0] = RoundToCeil(pVis.color.x * 255); + gColor[gpVisIdx][1] = RoundToCeil(pVis.color.y * 255); + gColor[gpVisIdx][2] = RoundToCeil(pVis.color.z * 255); + gColor[gpVisIdx][3] = gCvarBeamAlpha.IntValue; + +#if USE_CACHED_VALS 1 + gVerts[gpVisIdx] = new ArrayList(3); + gPolyVertCount[gpVisIdx] = new ArrayList(); + + int len = pVis.verts.Length; + float vec[3]; + for(int i = 0; i < len; i++) + { + pVis.verts.Get(i).ToArray(vec); + gVerts[gpVisIdx].PushArray(vec); + } + + len = pVis.polyVertCount.Length; + for(int i = 0; i < len; i++) + gPolyVertCount[gpVisIdx].Push(pVis.polyVertCount.Get(i)); +#else + gpVis[gpVisIdx] = pVis; +#endif + + CalculateVertsWindows(); + //RayTraceVerts(); + gpVisIdx++; + + return MRES_Supercede; +} + +void CalculateVertsWindows() +{ + gFinalVerts[gpVisIdx] = new ArrayList(3); + gFinalPolyCountEnd[gpVisIdx] = new ArrayList(); + ArrayList locvectors = new ArrayList(3); + int vert, vertcount, lastidx; + float vec[3], vec2[3]; + +#if USE_CACHED_VALS 1 + for(int i = 0; i < gPolyVertCount[gpVisIdx].Length; i++) + { + vertcount = gPolyVertCount[gpVisIdx].Get(i); + if(vertcount >= 3) + { + for(int j = 0; j < vertcount; j++) + { + gVerts[gpVisIdx].GetArray(vert + j, vec); + gVerts[gpVisIdx].GetArray(vert + ((j + 1) % vertcount), vec2); + + if(IsVectorInArray(locvectors, vec, vec2)) + { + if(j == vertcount - 1 && lastidx != 0) + gFinalPolyCountEnd[gpVisIdx].Set(lastidx, 1); + continue; + } + + gFinalVerts[gpVisIdx].PushArray(vec); + gFinalVerts[gpVisIdx].PushArray(vec2); + + gFinalPolyCountEnd[gpVisIdx].Push(0); + lastidx = gFinalPolyCountEnd[gpVisIdx].Push(j == vertcount - 1 ? true : false); + } + } + + lastidx = 0; + vert += vertcount; + } +#else + for(int i = 0; i < gpVis[gpVisIdx].polyVertCount.Length; i++) + { + vertcount = gpVis[gpVisIdx].polyVertCount.Get(i); + if(vertcount >= 3) + { + for(int j = 0; j < vertcount; j++) + { + gpVis[gpVisIdx].verts.Get(vert + j).ToArray(vec); + gpVis[gpVisIdx].verts.Get(vert + ((j + 1) % vertcount)).ToArray(vec2); + + if(IsVectorInArray(locvectors, vec, vec2)) + { + if(j == vertcount - 1 && lastidx != 0) + gFinalPolyCountEnd[gpVisIdx].Set(lastidx, 1); + continue; + } + + gFinalVerts[gpVisIdx].PushArray(vec); + gFinalVerts[gpVisIdx].PushArray(vec2); + + gFinalPolyCountEnd[gpVisIdx].Push(0); + lastidx = gFinalPolyCountEnd[gpVisIdx].Push(j == vertcount - 1 ? true : false); + } + } + + lastidx = 0; + vert += vertcount; + } +#endif + + delete locvectors; +} + +stock void RayTraceVerts() +{ + float vec[3], vec2[3], newvec[3]; + + for(int i = 0; i < gFinalVerts[gpVisIdx].Length - 1; i++) + { + if(gFinalPolyCountEnd[gpVisIdx].Get(i)) + continue; + + gFinalVerts[gpVisIdx].GetArray(i, vec); + gFinalVerts[gpVisIdx].GetArray(i + 1, vec2); + + if(!TraceAsVector(vec, vec2, newvec, MASK_PLAYERSOLID)) + { + if(TraceAsVector(vec2, vec, newvec, MASK_SOLID)) + gFinalVerts[gpVisIdx].SetArray(i, newvec); + } + else if(!TraceAsVector(vec2, vec, newvec, MASK_PLAYERSOLID)) + if(TraceAsVector(vec, vec2, newvec, MASK_SOLID)) + gFinalVerts[gpVisIdx].SetArray(i + 1, newvec); + } +} + +//FIXME: This function is very unoptimized on maps with a lot of clip verts without hack!!! +stock bool IsVectorInArray(ArrayList vectors, float a1[3], float a2[3]) +{ + float vec[3], orig[3], vec2[3], orig2[3]; + + vec[0] = a1[0] - a2[0]; + vec[1] = a1[1] - a2[1]; + vec[2] = a1[2] - a2[2]; + orig = a2; + + vec2[0] = a2[0] - a1[0]; + vec2[1] = a2[1] - a1[1]; + vec2[2] = a2[2] - a1[2]; + orig2 = a1; + + float vecvec[3], vecorig[3]; + for(int i = /*HACK*/(vectors.Length > 32 ? vectors.Length - 32 : 0); i < vectors.Length; i += 2) + { + vectors.GetArray(i, vecvec); + vectors.GetArray(i + 1, vecorig); + if((ArrayEqual(orig, vecorig, gCvarBeamSearchDelta.FloatValue) && ArrayEqual(vec, vecvec, gCvarBeamSearchDelta.FloatValue)) || + (ArrayEqual(orig2, vecorig, gCvarBeamSearchDelta.FloatValue) && ArrayEqual(vec2, vecvec, gCvarBeamSearchDelta.FloatValue))) + return true; + } + + vectors.PushArray(vec); + vectors.PushArray(orig); + + return false; +} + +stock bool ArrayEqual(float l[3], float r[3], float delta = 0.0) +{ + return l[0] <= r[0] + delta && l[0] >= r[0] - delta && + l[1] <= r[1] + delta && l[1] >= r[1] - delta && + l[2] <= r[2] + delta && l[2] >= r[2] - delta; +} + +stock bool TraceAsVector(float pos[3], float pos2[3], float out[3], int mask) +{ + float dir[3]; + + dir[0] = pos2[0] - pos[0]; + dir[1] = pos2[1] - pos[1]; + dir[2] = pos2[2] - pos[2]; + + TR_TraceRay(pos, dir, mask, RayType_Infinite); + + if(TR_DidHit()) + { + TR_GetEndPosition(out); + return true; + } + + return false; +} + +stock float Clamp(float v, float min, float max) +{ + if (v < min) return min; + if (v > max) return max; + return v; +} + +stock void Memset(Address dest, int src, int size) +{ + for(int i = 0; i < size; i++) + StoreToAddress(dest + i, src, NumberType_Int8); +} + +stock Address Malloc(int size) +{ + Address addr; + + if(gEngineVer == Engine_CSGO) + addr = SDKCall(ghMalloc, size); + else if(gEngineVer == Engine_CSS) + addr = SDKCall(ghMalloc, 0, size); + + ASSERT_FMT(addr == Address_Null, "Failed to allocate memory. (%i)", size); + + return addr; +} + +stock void Free(Address addr) +{ + ASSERT(addr == Address_Null, "Null address passed to free function."); + + if(gEngineVer == Engine_CSGO) + SDKCall(ghFree, addr); + else if(gEngineVer == Engine_CSS) + SDKCall(ghFree, 0, addr); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/spc/methodmaps.sp b/addons/sourcemod/scripting/spc/methodmaps.sp new file mode 100644 index 0000000..ad6ad8c --- /dev/null +++ b/addons/sourcemod/scripting/spc/methodmaps.sp @@ -0,0 +1,1035 @@ +static StringMap ghArraysMap; + +#define DYNARRAY_START() if(!ghArraysMap) \ + ghArraysMap = new StringMap() + +#define DYNARRAY_SETSIZE(%1,%2,%3) Format(%1, sizeof(%1), "%i_size", %2); \ + ghArraysMap.SetValue(%1, %3, true) + +#define DYNARRAY_SETLENGTH(%1,%2,%3) Format(%1, sizeof(%1), "%i_length", %2); \ + ghArraysMap.SetValue(%1, %3, true) + +#define DYNARRAY_SETTEMP(%1,%2,%3) Format(%1, sizeof(%1), "%i_temp", %2); \ + ghArraysMap.SetValue(%1, %3, true) + +#define DYNARRAY_GETSIZE(%1,%2) Format(%1, sizeof(%1), "%i_size", this.Address); \ + ASSERT(!ghArraysMap.GetValue(%1, %2), "Failed to get length of the array from the ghArraysMap!") + +#define DYNARRAY_GETLENGTH(%1,%2) Format(%1, sizeof(%1), "%i_length", this.Address); \ + ASSERT(!ghArraysMap.GetValue(%1, %2), "Failed to get size of each element from the ghArraysMap!") + +#define DYNARRAY_GETTEMP(%1,%2) Format(%1, sizeof(%1), "%i_temp", this.Address); \ + ASSERT(!ghArraysMap.GetValue(%1, %2), "Failed to get temp from the ghArraysMap!") + +#define DYNARRAY_END(%1) Format(%1, sizeof(%1), "%i_length", this.Address); \ + ghArraysMap.Remove(%1); \ + Format(%1, sizeof(%1), "%i_size", this.Address); \ + ghArraysMap.Remove(%1); \ + Format(%1, sizeof(%1), "%i_temp", this.Address); \ + ghArraysMap.Remove(%1); \ + if(ghArraysMap.Size == 0) \ + delete ghArraysMap + +stock Address operator+(Address l, int r) +{ + return l + view_as
(r); +} + +methodmap AddressBase +{ + property Address Address + { + public get() { return view_as
(this); } + } +} + +methodmap AllocatableBase < AddressBase +{ + public static Address _malloc(int size) + { + Address addr = Malloc(size); + + return addr; + } + + public void _free() + { + Free(this.Address); + } +} + +enum CUtlVectorBase_members +{ + CUtlVectorBase_m_pMemory = 0, + CUtlVectorBase_m_nAllocationCount = 1, + CUtlVectorBase_m_nGrowSize, + CUtlVectorBase_m_Size, + CUtlVectorBase_m_pElements +}; +static int CUtlVectorBase_offsets[CUtlVectorBase_members]; + +methodmap CUtlVectorBase < AllocatableBase +{ + property Address m_pMemory + { + public get() { return view_as
(LoadFromAddress(this.Address + CUtlVectorBase_offsets[CUtlVectorBase_m_pMemory], NumberType_Int32)); } + } + + property int m_nAllocationCount + { + public get() { return LoadFromAddress(this.Address + CUtlVectorBase_offsets[CUtlVectorBase_m_nAllocationCount], NumberType_Int32); } + } + + property int m_nGrowSize + { + public get() { return LoadFromAddress(this.Address + CUtlVectorBase_offsets[CUtlVectorBase_m_nGrowSize], NumberType_Int32); } + } + + property int m_Size + { + public get() { return LoadFromAddress(this.Address + CUtlVectorBase_offsets[CUtlVectorBase_m_Size], NumberType_Int32); } + } + + property Address m_pElements + { + public get() { return view_as
(LoadFromAddress(this.Address + CUtlVectorBase_offsets[CUtlVectorBase_m_pElements], NumberType_Int32)); } + } + + property int Length + { + public get() { return this.m_Size; } + } +} + +methodmap Vector < AllocatableBase +{ + public static int Size() + { + return 12; + } + + public Vector() + { + Address addr = AllocatableBase._malloc(Vector.Size()); + return view_as(addr); + } + + property float x + { + public set(float _x) { StoreToAddress(this.Address, view_as(_x), NumberType_Int32); } + public get() { return view_as(LoadFromAddress(this.Address, NumberType_Int32)); } + } + + property float y + { + public set(float _y) { StoreToAddress(this.Address + 4, view_as(_y), NumberType_Int32); } + public get() { return view_as(LoadFromAddress(this.Address + 4, NumberType_Int32)); } + } + + property float z + { + public set(float _z) { StoreToAddress(this.Address + 8, view_as(_z), NumberType_Int32); } + public get() { return view_as(LoadFromAddress(this.Address + 8, NumberType_Int32)); } + } + + public void ToArray(float buff[3]) + { + buff[0] = this.x; + buff[1] = this.y; + buff[2] = this.z; + } + + public void CopyTo(Vector dst) + { + dst.x = this.x; + dst.y = this.y; + dst.z = this.z; + } +} + +methodmap Vector4D < AddressBase +{ + public Vector4D(Address addr) + { + return view_as(addr); + } + + property float x + { + public get() { return view_as(LoadFromAddress(this.Address, NumberType_Int32)); } + } + + property float y + { + public get() { return view_as(LoadFromAddress(this.Address + 4, NumberType_Int32)); } + } + + property float z + { + public get() { return view_as(LoadFromAddress(this.Address + 8, NumberType_Int32)); } + } + + property float w + { + public get() { return view_as(LoadFromAddress(this.Address + 12, NumberType_Int32)); } + } + + public void ToArray(float buff[4]) + { + buff[0] = this.x; + buff[1] = this.y; + buff[2] = this.z; + buff[3] = this.w; + } +} + +static int CUtlVectorUnknown_m_pElements_size; + +methodmap CUtlVectorUnknown < CUtlVectorBase +{ + //No allocation + public CUtlVectorUnknown(Address addr) + { + return view_as(addr); + } + + public int Get(int idx) + { + ASSERT(!this, "CUtlVectorUnknown trying to get values from null."); + ASSERT_FMT(idx > this.Length, "CUtlVectorUnknown wrong idx passed. (%i, length %i)", idx, this.Length); + + return LoadFromAddress(this.m_pElements + (idx * CUtlVectorUnknown_m_pElements_size), NumberType_Int32); + } +} + +methodmap CUtlVectorVector < CUtlVectorBase +{ + //No allocation + public CUtlVectorVector(Address addr) + { + return view_as(addr); + } + + public Vector Get(int idx) + { + ASSERT(!this, "CUtlVectorVector trying to get values from null."); + ASSERT_FMT(idx > this.Length, "CUtlVectorVector wrong idx passed. (%i, length %i)", idx, this.Length); + + return view_as(this.m_pElements + (idx * 12)); + } +} + +methodmap CUtlVectorVector4D < CUtlVectorBase +{ + public CUtlVectorVector4D() + { + Address addr = AllocatableBase._malloc(20); + + return view_as(addr); + } + + public Vector4D Get(int idx) + { + ASSERT(!this, "CUtlVectorVector4D trying to get values from null."); + ASSERT_FMT(idx > this.Length, "CUtlVectorVector4D wrong idx passed. (%i, length %i)", idx, this.Length); + + return view_as(this.m_pElements + (idx * 16)); + } +} + +enum Leafvis_t_members +{ + Leafvis_t_verts = 0, + Leafvis_t_polyVertCount = 1, + Leafvis_t_color, + Leafvis_t_numbrushes, + Leafvis_t_numentitychars, + Leafvis_t_leafIndex +}; +static int Leafvis_t_offsets[Leafvis_t_members]; + +methodmap Leafvis_t < AddressBase +{ + public Leafvis_t(Address addr) + { + return view_as(addr); + } + + property CUtlVectorVector verts + { + public get() { return view_as(this.Address + Leafvis_t_offsets[Leafvis_t_verts]); } + } + + property CUtlVectorUnknown polyVertCount + { + public get() { return view_as(this.Address + Leafvis_t_offsets[Leafvis_t_polyVertCount]); } + } + + property Vector color + { + public get() { return view_as(this.Address + Leafvis_t_offsets[Leafvis_t_color]); } + } + + property int numbrushes + { + public get() { return LoadFromAddress(this.Address + Leafvis_t_offsets[Leafvis_t_numbrushes], NumberType_Int32); } + } + + property int numentitychars + { + public get() { return LoadFromAddress(this.Address + Leafvis_t_offsets[Leafvis_t_numentitychars], NumberType_Int32); } + } + + property int leafIndex + { + public get() { return LoadFromAddress(this.Address + Leafvis_t_offsets[Leafvis_t_leafIndex], NumberType_Int32); } + } +} + +enum CRangeValidatedArray_members +{ + CRangeValidatedArray_m_pArray = 0, + CRangeValidatedArray_m_nCount = 1 +} +static int CRangeValidatedArray_offsets[CRangeValidatedArray_members]; + +methodmap CRangeValidatedArray < AddressBase +{ + public CRangeValidatedArray(Address addr) + { + return view_as(addr); + } + + property Address m_pArray + { + public get() { return view_as
(LoadFromAddress(this.Address + CRangeValidatedArray_offsets[CRangeValidatedArray_m_pArray], NumberType_Int32)); } + } + + property int m_nCount + { + public get() + { + ASSERT(gEngineVer == Engine_CSS, "Failed to get m_nCount member."); + return LoadFromAddress(this.Address + CRangeValidatedArray_offsets[CRangeValidatedArray_m_nCount], NumberType_Int32); + } + } + + property int Length + { + public get() { return this.m_nCount; } + } + + public Address Get(int idx, int sizeOfOneElem) + { + return this.m_pArray + (idx * sizeOfOneElem); + } + + public any GetValue(int idx, int sizeOfOneElem, NumberType type) + { + return LoadFromAddress(this.m_pArray + (idx * sizeOfOneElem), type); + } +} + +enum Cbrush_t_members +{ + Cbrush_t_contents = 0, + Cbrush_t_numsides = 1, + Cbrush_t_firstbrushside +} +static int Cbrush_t_offsets[Cbrush_t_members]; +static int Cbrush_t_size; + +methodmap Cbrush_t < AddressBase +{ + public Cbrush_t(Address addr) + { + return view_as(addr); + } + + property int contents + { + public get() { return LoadFromAddress(this.Address + Cbrush_t_offsets[Cbrush_t_contents], NumberType_Int32); } + } + + property int numsides + { + public get() { return LoadFromAddress(this.Address + Cbrush_t_offsets[Cbrush_t_numsides], NumberType_Int16); } + } + + property int firstbrushside + { + public get() { return LoadFromAddress(this.Address + Cbrush_t_offsets[Cbrush_t_firstbrushside], NumberType_Int16); } + } + + public int GetBox() + { + return this.firstbrushside; + } + + public bool IsBox() + { + return this.numsides == NUMSIDES_BOXBRUSH; + } + + public static int Size() + { + return Cbrush_t_size; + } +} + +enum Cboxbrush_t_members +{ + Cboxbrush_t_mins = 0, + Cboxbrush_t_maxs = 1, + Cboxbrush_t_surfaceIndex +} +static int Cboxbrush_t_offsets[Cboxbrush_t_members]; +static int Cboxbrush_t_size; + +methodmap Cboxbrush_t < AddressBase +{ + public Cboxbrush_t(Address addr) + { + return view_as(addr); + } + + property Vector mins + { + public get() { return view_as(this.Address + Cboxbrush_t_offsets[Cboxbrush_t_mins]); } + } + + property Vector maxs + { + public get() { return view_as(this.Address + Cboxbrush_t_offsets[Cboxbrush_t_maxs]); } + } + + public void surfaceIndex(int out[6]) + { + for(int i = 0; i < 6; i++) + out[i] = LoadFromAddress(this.Address + Cboxbrush_t_offsets[Cboxbrush_t_surfaceIndex] + (2 * i), NumberType_Int16); + } + + public static int Size() + { + return Cboxbrush_t_size; + } +} + +enum Cplane_t_members +{ + Cplane_t_normal = 0, + Cplane_t_dist = 1, + Cplane_t_type, + Cplane_t_signbits +}; +static int Cplane_t_offsets[Cplane_t_members]; + +methodmap Cplane_t < AddressBase +{ + public Cplane_t(Address addr) + { + return view_as(addr); + } + + property Vector normal + { + public get() { return view_as(this.Address + Cplane_t_offsets[Cplane_t_normal]); } + } + + property float dist + { + public get() { return view_as(LoadFromAddress(this.Address + Cplane_t_offsets[Cplane_t_dist], NumberType_Int32)); } + } + + property int type + { + public get() { return LoadFromAddress(this.Address + Cplane_t_offsets[Cplane_t_type], NumberType_Int8); } + } + + property int signbits + { + public get() { return LoadFromAddress(this.Address + Cplane_t_offsets[Cplane_t_signbits], NumberType_Int8); } + } +} + +enum Cnode_t_members +{ + Cnode_t_plane = 0, + Cnode_t_children = 1 +} +static int Cnode_t_offsets[Cboxbrush_t_members]; +static int Cnode_t_size; + +methodmap Cnode_t < AddressBase +{ + public Cnode_t(Address addr) + { + return view_as(addr); + } + + property Cplane_t plane + { + public get() { return view_as(LoadFromAddress(this.Address + Cnode_t_offsets[Cnode_t_plane], NumberType_Int32)); } + } + + public int children(int idx) + { + ASSERT(idx > 2, "Failed to get children member from cnode_t."); + + return LoadFromAddress(this.Address + Cnode_t_offsets[Cnode_t_children] + (4 * idx), NumberType_Int32); + } + + public static int Size() + { + return Cnode_t_size; + } +} + +enum Cmodel_t_members +{ + Cmodel_t_mins = 0, + Cmodel_t_maxs = 1, + Cmodel_t_origin, + Cmodel_t_headnode + //... +} +static int Cmodel_t_offsets[Cmodel_t_members]; +static int Cmodel_t_size; + +methodmap Cmodel_t < AddressBase +{ + public Cmodel_t(Address addr) + { + return view_as(addr); + } + + property Vector mins + { + public get() { return view_as(this.Address + Cmodel_t_offsets[Cmodel_t_mins]); } + } + + property Vector maxs + { + public get() { return view_as(this.Address + Cmodel_t_offsets[Cmodel_t_maxs]); } + } + + property Vector origin + { + public get() { return view_as(this.Address + Cmodel_t_offsets[Cmodel_t_origin]); } + } + + property int headnode + { + public get() { return LoadFromAddress(this.Address + Cmodel_t_offsets[Cmodel_t_headnode], NumberType_Int32); } + } + + //... + + public static int Size() + { + return Cmodel_t_size; + } +} + +enum BrushSideInfo_t_members +{ + BrushSideInfo_t_plane = 0, + BrushSideInfo_t_bevel = 1, + BrushSideInfo_t_thin +}; +static int BrushSideInfo_t_offsets[BrushSideInfo_t_members]; +static int BrushSideInfo_t_size; + +methodmap BrushSideInfo_t < AddressBase +{ + public BrushSideInfo_t(Address addr) + { + return view_as(addr); + } + + property Vector4D plane_Vector4D + { + public get() + { + ASSERT(gEngineVer != Engine_CSS, "Trying to get wrong member for BrushSideInfo_t (plane)"); + return view_as(this.Address + BrushSideInfo_t_offsets[BrushSideInfo_t_plane]); + } + } + + property Cplane_t plane_cplane_t + { + public get() + { + ASSERT(gEngineVer != Engine_CSGO, "Trying to get wrong member for BrushSideInfo_t (plane)"); + return view_as(this.Address + BrushSideInfo_t_offsets[BrushSideInfo_t_plane]); + } + } + + property int bevel + { + public get() { return LoadFromAddress(this.Address + BrushSideInfo_t_offsets[BrushSideInfo_t_bevel], NumberType_Int16); } + } + + property int thin + { + public get() { return LoadFromAddress(this.Address + BrushSideInfo_t_offsets[BrushSideInfo_t_thin], NumberType_Int16); } + } + + public static int Size() + { + return BrushSideInfo_t_size; + } +} + +enum Cleaf_t_members +{ + Cleaf_t_contents = 0, + Cleaf_t_cluster = 1, + Cleaf_t_area, + Cleaf_t_flags, + Cleaf_t_firstleafbrush, + Cleaf_t_numleafbrushes, + Cleaf_t_dispListStart, + Cleaf_t_dispCount +}; +static int Cleaf_t_offsets[Cleaf_t_members]; +static int Cleaf_t_size; + +methodmap Cleaf_t < AddressBase +{ + public Cleaf_t(Address addr) + { + return view_as(addr); + } + + property int contents + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_contents], NumberType_Int32); } + } + + property int cluster + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_cluster], NumberType_Int16); } + } + + property int area + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_area], NumberType_Int8); } + } + + property int flags + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_flags], NumberType_Int8); } + } + + property int firstleafbrush + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_firstleafbrush], NumberType_Int16); } + } + + property int numleafbrushes + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_numleafbrushes], NumberType_Int16); } + } + + property int dispListStart + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_dispListStart], NumberType_Int16); } + } + + property int dispCount + { + public get() { return LoadFromAddress(this.Address + Cleaf_t_offsets[Cleaf_t_dispCount], NumberType_Int16); } + } + + public static int Size() + { + return Cleaf_t_size; + } +} + +enum Cbrushside_t_members +{ + Cbrushside_t_plane = 0, + Cbrushside_t_surfaceIndex = 1, + Cbrushside_t_bBevel +}; +static int Cbrushside_t_offsets[Cbrushside_t_members]; +static int Cbrushside_t_size; + +methodmap Cbrushside_t < AddressBase +{ + public Cbrushside_t(Address addr) + { + return view_as(addr); + } + + property Cplane_t plane + { + public get() { return view_as(LoadFromAddress(this.Address + Cbrushside_t_offsets[Cbrushside_t_plane], NumberType_Int32)); } + } + + property int surfaceIndex + { + public get() { return LoadFromAddress(this.Address + Cbrushside_t_offsets[Cbrushside_t_surfaceIndex], NumberType_Int16); } + } + + property int bBevel + { + public get() { return LoadFromAddress(this.Address + Cbrushside_t_offsets[Cbrushside_t_bBevel], NumberType_Int16); } + } + + public static int Size() + { + return Cbrushside_t_size; + } +} + +methodmap PseudoPtrArray < AllocatableBase +{ + public PseudoPtrArray(int length, int sizeOfOneElem) + { + Address addr = AllocatableBase._malloc(length * sizeOfOneElem); + DYNARRAY_START(); + + char buff[32]; + + DYNARRAY_SETSIZE(buff, addr, sizeOfOneElem); + DYNARRAY_SETLENGTH(buff, addr, length); + DYNARRAY_SETTEMP(buff, addr, false); + + Memset(addr, 0, length * sizeOfOneElem); + + return view_as(addr); + } + + public static PseudoPtrArray FromAddress(Address addr, int length, int sizeOfOneElem, bool temp = false) + { + ASSERT(addr == Address_Null, "Null address passed to PseudoPtrArray constructor!"); + DYNARRAY_START(); + + char buff[32]; + + DYNARRAY_SETSIZE(buff, addr, sizeOfOneElem); + DYNARRAY_SETLENGTH(buff, addr, length); + DYNARRAY_SETTEMP(buff, addr, temp); + + return view_as(addr); + } + + public void Free(bool full = true) + { + if(full) + this._free(); + + char buff[32]; + DYNARRAY_END(buff); + } + + public Address Get(int idx) + { + int ibuff; + char buff[32]; + DYNARRAY_GETLENGTH(buff, ibuff); + if(ibuff != -1) + ASSERT_FMT(idx >= ibuff || idx < 0, "Invalid idx for PseudoPtrArray (%i, length %i)", idx, ibuff); + + DYNARRAY_GETSIZE(buff, ibuff); + + bool temp; + DYNARRAY_GETTEMP(buff, temp); + + if(!temp) + return this.Address + (idx * ibuff); + else + { + this.Free(false); + return this.Address + (idx * ibuff); + } + } + + property int Length + { + public get() + { + int len; + char buff[32]; + DYNARRAY_GETLENGTH(buff, len); + + return len; + } + } +} + +enum CCollisionBSPData_members +{ + CCollisionBSPData_map_rootnode = 0, + CCollisionBSPData_map_name = 1, + CCollisionBSPData_numbrushsides, + CCollisionBSPData_map_brushsides, + CCollisionBSPData_numboxbrushes, + CCollisionBSPData_map_boxbrushes, + CCollisionBSPData_numplanes, + CCollisionBSPData_map_planes, + CCollisionBSPData_numnodes, + CCollisionBSPData_map_nodes, + CCollisionBSPData_numleafs, + CCollisionBSPData_map_leafs, + CCollisionBSPData_emptyleaf, + CCollisionBSPData_solidleaf, + CCollisionBSPData_numleafbrushes, + CCollisionBSPData_map_leafbrushes, + CCollisionBSPData_numcmodels, + CCollisionBSPData_map_cmodels, + CCollisionBSPData_numbrushes, + CCollisionBSPData_map_brushes, + CCollisionBSPData_numdisplist, + CCollisionBSPData_map_dispList + //... +}; +static int CCollisionBSPData_offsets[CCollisionBSPData_members]; + +methodmap CCollisionBSPData < AddressBase +{ + public CCollisionBSPData(Address addr) + { + return view_as(addr); + } + + property PseudoPtrArray map_rootnode + { + public get() { return PseudoPtrArray.FromAddress(view_as
(LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_rootnode], NumberType_Int32)), -1, Cnode_t.Size(), true); } + } + + //... + + property int numbrushsides + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numbrushsides], NumberType_Int32); } + } + + property CRangeValidatedArray map_brushsides + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_brushsides]); } + } + + property int numboxbrushes + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numboxbrushes], NumberType_Int32); } + } + + property CRangeValidatedArray map_boxbrushes + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_boxbrushes]); } + } + + //... + + property int numleafs + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numleafs], NumberType_Int32); } + } + + property CRangeValidatedArray map_leafs + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_leafs]); } + } + + //... + + property int numleafbrushes + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numleafbrushes], NumberType_Int32); } + } + + property CRangeValidatedArray map_leafbrushes + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_leafbrushes]); } + } + + property int numcmodels + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numcmodels], NumberType_Int32); } + } + + property CRangeValidatedArray map_cmodels + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_cmodels]); } + } + + property int numbrushes + { + public get() { return LoadFromAddress(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_numbrushes], NumberType_Int32); } + } + + property CRangeValidatedArray map_brushes + { + public get() { return view_as(this.Address + CCollisionBSPData_offsets[CCollisionBSPData_map_brushes]); } + } + + //... +} + +void RetrieveOffsets(Handle gconf) +{ + char buff[32]; + + if(gOSType == OSWindows) + { + //Leafvis_t + GameConfGetKeyValue(gconf, "leafvis_t::verts", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_verts] = StringToInt(buff); + GameConfGetKeyValue(gconf, "leafvis_t::polyVertCount", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_polyVertCount] = StringToInt(buff); + GameConfGetKeyValue(gconf, "leafvis_t::color", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_color] = StringToInt(buff); + GameConfGetKeyValue(gconf, "leafvis_t::numbrushes", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_numbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "leafvis_t::numentitychars", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_numentitychars] = StringToInt(buff); + GameConfGetKeyValue(gconf, "leafvis_t::leafIndex", buff, sizeof(buff)); + Leafvis_t_offsets[Leafvis_t_leafIndex] = StringToInt(buff); + + //CUtlVector + GameConfGetKeyValue(gconf, "CUtlVector::m_pMemory", buff, sizeof(buff)); + CUtlVectorBase_offsets[CUtlVectorBase_m_pMemory] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CUtlVector::m_nAllocationCount", buff, sizeof(buff)); + CUtlVectorBase_offsets[CUtlVectorBase_m_nAllocationCount] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CUtlVector::m_nGrowSize", buff, sizeof(buff)); + CUtlVectorBase_offsets[CUtlVectorBase_m_nGrowSize] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CUtlVector::m_Size", buff, sizeof(buff)); + CUtlVectorBase_offsets[CUtlVectorBase_m_Size] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CUtlVector::m_pElements", buff, sizeof(buff)); + CUtlVectorBase_offsets[CUtlVectorBase_m_pElements] = StringToInt(buff); + + //CUtlVectorUnknown::m_pElements::size + GameConfGetKeyValue(gconf, "CUtlVectorUnknown::m_pElements::size", buff, sizeof(buff)); + CUtlVectorUnknown_m_pElements_size = StringToInt(buff); + } + else if(gOSType == OSLinux) + { + //CRangeValidatedArray + GameConfGetKeyValue(gconf, "CRangeValidatedArray::m_pArray", buff, sizeof(buff)); + CRangeValidatedArray_offsets[CRangeValidatedArray_m_pArray] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CRangeValidatedArray::m_nCount", buff, sizeof(buff)); + CRangeValidatedArray_offsets[CRangeValidatedArray_m_nCount] = StringToInt(buff); + + //cnode_t + GameConfGetKeyValue(gconf, "cnode_t::plane", buff, sizeof(buff)); + Cnode_t_offsets[Cnode_t_plane] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cnode_t::children", buff, sizeof(buff)); + Cnode_t_offsets[Cnode_t_children] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cnode_t::size", buff, sizeof(buff)); + Cnode_t_size = StringToInt(buff); + + //cboxbrush_t + GameConfGetKeyValue(gconf, "cboxbrush_t::mins", buff, sizeof(buff)); + Cboxbrush_t_offsets[Cboxbrush_t_mins] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cboxbrush_t::maxs", buff, sizeof(buff)); + Cboxbrush_t_offsets[Cboxbrush_t_maxs] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cboxbrush_t::surfaceIndex", buff, sizeof(buff)); + Cboxbrush_t_offsets[Cboxbrush_t_surfaceIndex] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cboxbrush_t::size", buff, sizeof(buff)); + Cboxbrush_t_size = StringToInt(buff); + + //cbrush_t + GameConfGetKeyValue(gconf, "cbrush_t::contents", buff, sizeof(buff)); + Cbrush_t_offsets[Cbrush_t_contents] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrush_t::numsides", buff, sizeof(buff)); + Cbrush_t_offsets[Cbrush_t_numsides] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrush_t::firstbrushside", buff, sizeof(buff)); + Cbrush_t_offsets[Cbrush_t_firstbrushside] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrush_t::size", buff, sizeof(buff)); + Cbrush_t_size = StringToInt(buff); + + //cleaf_t + GameConfGetKeyValue(gconf, "cleaf_t::contents", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_contents] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::cluster", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_cluster] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::area", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_area] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::flags", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_flags] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::firstleafbrush", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_firstleafbrush] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::numleafbrushes", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_numleafbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::dispListStart", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_dispListStart] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::dispCount", buff, sizeof(buff)); + Cleaf_t_offsets[Cleaf_t_dispCount] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cleaf_t::size", buff, sizeof(buff)); + Cleaf_t_size = StringToInt(buff); + + //cbrushside_t + GameConfGetKeyValue(gconf, "cbrushside_t::plane", buff, sizeof(buff)); + Cbrushside_t_offsets[Cbrushside_t_plane] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrushside_t::surfaceIndex", buff, sizeof(buff)); + Cbrushside_t_offsets[Cbrushside_t_surfaceIndex] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrushside_t::bBevel", buff, sizeof(buff)); + Cbrushside_t_offsets[Cbrushside_t_bBevel] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cbrushside_t::size", buff, sizeof(buff)); + Cbrushside_t_size = StringToInt(buff); + + //cmodel_t + GameConfGetKeyValue(gconf, "cmodel_t::mins", buff, sizeof(buff)); + Cmodel_t_offsets[Cmodel_t_mins] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cmodel_t::maxs", buff, sizeof(buff)); + Cmodel_t_offsets[Cmodel_t_maxs] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cmodel_t::origin", buff, sizeof(buff)); + Cmodel_t_offsets[Cmodel_t_origin] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cmodel_t::headnode", buff, sizeof(buff)); + Cmodel_t_offsets[Cmodel_t_headnode] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cmodel_t::size", buff, sizeof(buff)); + Cmodel_t_size = StringToInt(buff); + + //CCollisionBSPData + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_rootnode", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_rootnode] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numbrushsides", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numbrushsides] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_brushsides", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_brushsides] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numboxbrushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numboxbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_boxbrushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_boxbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numleafs", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numleafs] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_leafs", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_leafs] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numleafbrushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numleafbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_leafbrushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_leafbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numcmodels", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numcmodels] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_cmodels", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_cmodels] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::numbrushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_numbrushes] = StringToInt(buff); + GameConfGetKeyValue(gconf, "CCollisionBSPData::map_brushes", buff, sizeof(buff)); + CCollisionBSPData_offsets[CCollisionBSPData_map_brushes] = StringToInt(buff); + + //cplane_t + GameConfGetKeyValue(gconf, "cplane_t::normal", buff, sizeof(buff)); + Cplane_t_offsets[Cplane_t_normal] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cplane_t::dist", buff, sizeof(buff)); + Cplane_t_offsets[Cplane_t_dist] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cplane_t::type", buff, sizeof(buff)); + Cplane_t_offsets[Cplane_t_type] = StringToInt(buff); + GameConfGetKeyValue(gconf, "cplane_t::signbits", buff, sizeof(buff)); + Cplane_t_offsets[Cplane_t_signbits] = StringToInt(buff); + + //BrushSideInfo_t + GameConfGetKeyValue(gconf, "BrushSideInfo_t::plane", buff, sizeof(buff)); + BrushSideInfo_t_offsets[BrushSideInfo_t_plane] = StringToInt(buff); + GameConfGetKeyValue(gconf, "BrushSideInfo_t::bevel", buff, sizeof(buff)); + BrushSideInfo_t_offsets[BrushSideInfo_t_bevel] = StringToInt(buff); + GameConfGetKeyValue(gconf, "BrushSideInfo_t::thin", buff, sizeof(buff)); + BrushSideInfo_t_offsets[BrushSideInfo_t_thin] = StringToInt(buff); + GameConfGetKeyValue(gconf, "BrushSideInfo_t::Size", buff, sizeof(buff)); + BrushSideInfo_t_size = StringToInt(buff); + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/showplayerclips.phrases.txt b/addons/sourcemod/translations/showplayerclips.phrases.txt new file mode 100644 index 0000000..e945b69 --- /dev/null +++ b/addons/sourcemod/translations/showplayerclips.phrases.txt @@ -0,0 +1,12 @@ +"Phrases" +{ + "playerclips_disabled" + { + "en" "[ShowPlayerClips] Player clips now disabled!" + } + + "playerclips_enabled" + { + "en" "[ShowPlayerClips] Player clips now enabled!" + } +} \ No newline at end of file