From bf302f6e23777b54d966edda6487759149e3035a Mon Sep 17 00:00:00 2001 From: thesupremecommander Date: Wed, 7 May 2014 06:13:14 -0400 Subject: [PATCH] Initial version of project --- BUILD.md | 21 +++ CMakeLists.txt | 125 ++++++++++++++++++ LICENSE.md | 23 ++++ src/offsets.cpp | 181 +++++++++++++++++++++++++ src/offsets.h | 39 ++++++ src/statusspec.cpp | 323 +++++++++++++++++++++++++++++++++++++++++++++ src/statusspec.h | 196 +++++++++++++++++++++++++++ src/stdafx.h | 44 ++++++ src/vfuncs.cpp | 33 +++++ src/vfuncs.h | 42 ++++++ 10 files changed, 1027 insertions(+) create mode 100644 BUILD.md create mode 100644 CMakeLists.txt create mode 100644 LICENSE.md create mode 100644 src/offsets.cpp create mode 100644 src/offsets.h create mode 100644 src/statusspec.cpp create mode 100644 src/statusspec.h create mode 100644 src/stdafx.h create mode 100644 src/vfuncs.cpp create mode 100644 src/vfuncs.h diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 0000000..b9ed9f2 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,21 @@ +Building AdvSpec plugin +============================== + +Notice +- +AdvSpec is not yet available for Linux & OS X. + +Requirements +- +* **[Windows]** Visual Studio or Visual Express C++ +* cmake 2.6+ +* source-sdk-2013 - https://github.com/ValveSoftware/source-sdk-2013/ + +Building +- +**Windows** +`cmake -DHL2SDK=c:\path\to\source-sdk-2013\mp\src -G "Visual Studio 10" ..` +Then open in Visual Studio/C++ Express and build. Note the `\mp\src` in the SDK path! + +Open advspec properties, then in `Linker -> Input -> Ignore Specific Default Libraries`, change `libcmt`, to `libcmtd` +Do this for Debug and Release. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e2cb353 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,125 @@ +cmake_minimum_required(VERSION 2.6) + +project(statusspec) + +set(PACKAGE "statusspec") +set(PACKAGE_VERSION "v0.1") +set(PACKAGE_BUGREPORT "https://github.com/fwdcp/StatusSpec/issues") +set(PACKAGE_NAME "${PACKAGE}") +set(PACKAGE_STRING "${PACKAGE} ${PACKAGE_VERSION}") +set(PACKAGE_TARNAME "${PACKAGE}_${PACKAGE_VERSION}") +set(PACKAGE_URL "https://github.com/fwdcp/StatusSpec") +set(VERSION "${PACKAGE_VERSION}") + +include_directories(${PROJECT_BINARY_DIR}) +# Put final product in 'bin' folder +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") + +# Include source and hl2sdk +include_directories(${PROJECT_SOURCE_DIR}/src) +include_directories(${HL2SDK}/common) +include_directories(${HL2SDK}/public) +include_directories(${HL2SDK}/public/tier0) +include_directories(${HL2SDK}/public/tier1) +include_directories(${HL2SDK}/game/client) +include_directories(${HL2SDK}/game/shared) + +set(HDR_PUBLIC + src/statusspec.h + src/offsets.h + src/stdafx.h + src/vfuncs.h + ) + +set(SOURCES + src/statusspec.cpp + src/offsets.cpp + src/vfuncs.cpp + ) + +source_group("Header Files" FILES ${HDR_PUBLIC}) +source_group("Source FIles" FILES ${SOURCES}) + +# Setup defines, compiler options and linker options for each platform +if(UNIX) # Common Unix settings + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # Malloc fix + include_directories(/usr/include/malloc) + set(SymbolVisibility "hidden") + set(GCC_ExtraCompilerFlags "") + set(GCC_ExtraLinkerFlags "") + set(WarnFlags "-Wall -Wextra -Wshadow -Wno-invalid-offsetof -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security") + + #Set Optimizer Level + if(CMAKE_BUILD_TYPE MATCHES DEBUG) + set(OptimizerLevel "-gdwarf-2 -g -O0") + add_definitions(-DDEBUG -D_DEBUG -DGNUC -DPOSIX -D_OSX -DOSX -D_DARWIN_UNLIMITED_SELECT -DFD_SETSIZE=10240 -DQUICKTIME_VIDEO -DFORCE_QUICKTIME -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -D_MBCS -D_DLL_EXT=.dylib -D_POSIX=1) + else() + set(OptimizerLevel "-gdwarf-2 -g -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer") + add_definitions(-DNDEBUG -DGNUC -DPOSIX -D_OSX -DOSX -D_DARWIN_UNLIMITED_SELECT -DFD_SETSIZE=10240 -DQUICKTIME_VIDEO -DFORCE_QUICKTIME -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -D_MBCS -D_DLL_EXT=.dylib -D_POSIX=1) + endif() + + set(CFLAGS "-arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2 ${WarnFlags} -fvisibility=${SymbolVisibility} ${OptimizerLevel} -pipe ${GCC_ExtraCompilerFlags} -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE -mmacosx-version-min=10.5 -fasm-blocks") + set(COMPILER_FLAGS ${CFLAGS}) + add_definitions(-DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE) + set(LINKER_FLAGS "${CFLAGS} ${GCC_ExtraLinkerFlags} ${OptimizerLevel} -dynamiclib -current_version 1.0 -compatibility_version 1.0 -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms") + else() # Linux + set(SymbolVisibility "hidden") + set(GCC_ExtraCompilerFlags "-U_FORTIFY_SOURCE") + set(GCC_ExtraLinkerFlags "") + set(WarnFlags "-Wall -Wextra -Wshadow -Wno-invalid-offsetof -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type -fdiagnostics-show-option -Wformat -Wformat-security") + + # Set Optimizer Level + if(CMAKE_BUILD_TYPE MATCHES DEBUG) + set(OptimizerLevel "-gdwarf-2 -g -O0") + add_definitions(-DDEBUG -D_DEBUG -DPOSIX -DGNUC -DLINUX -D_LINUX -DRAD_TELEMETRY_DISABLED -DBINK_VIDEO -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DUSE_SDL -D_MBCS -D_EXTERNAL_DLL_EXT=.so -D_DLL_EXT=.so -D_LINUX=1 -D_POSIX=1 -DLINUX=1 -DPOSIX=1) + else() + set(OptimizerLevel "-gdwarf-2 -g -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer -ftree-vectorize -fpredictive-commoning -funswitch-loops") + add_definitions(-DNDEBUG -DPOSIX -DGNUC -DLINUX -D_LINUX -DRAD_TELEMETRY_DISABLED -DBINK_VIDEO -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DUSE_SDL -D_MBCS -D_EXTERNAL_DLL_EXT=.so -D_DLL_EXT=.so -D_LINUX=1 -D_POSIX=1 -DLINUX=1 -DPOSIX=1) + endif() + + set(CFLAGS "-m32 -march=pentium4 -mtune=core2 -msse2 -mfpmath=sse ${WarnFlags} -fvisibility=${SymbolVisibility} ${OptimizerLevel} -pipe ${GCC_ExtraCompilerFlags} -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE") + set(COMPILER_FLAGS ${CFLAGS}) + add_definitions(-DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE) + set(LINKER_FLAGS "${CFLAGS} ${GCC_ExtraLinkerFlags} ${OptimizerLevel} -Wl,--build-id -shared -Wl,--no-undefined -Wl,-Map,$(@:.so=).map -static-libgcc -Wl,--start-group -Wl,--end-group -lm -ldl -lpthread -l:ld-linux.so.2") + endif() +else() # Windows + # Force use of static libs + # Credit SteveL & brofield on StackOverflow + foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINOFO) + string(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}") + endforeach() + + add_definitions(/D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE) + set(COMPILER_FLAGS "/EHsc /DR- /W3 /nologo /Zi /TP") + set(LINKER_FLAGS "/MACHINE:X86 /subsystem:windows /NODEFAULTLIB:libc /NODEFAULTLIB:libcd") + set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmt") +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") + +# Create the plugin +add_library(statusspec SHARED + ${HDR_PUBLIC} + ${SOURCES}) + +# Remove 'lib' prefix +set_target_properties(statusspec PROPERTIES PREFIX "") + +# Link sdk libraries +if(WIN32) + target_link_libraries(statusspec ${HL2SDK}/lib/public/tier0.lib) + target_link_libraries(statusspec ${HL2SDK}/lib/public/tier1.lib) +else() + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_link_libraries(statusspec ${HL2SDK}/lib/public/osx32/libtier0.dylib) + target_link_libraries(statusspec ${HL2SDK}/lib/public/osx32/tier1.a) + else() + target_link_libraries(statusspec ${HL2SDK}/lib/public/linux32/libtier0.so) + target_link_libraries(statusspec ${HL2SDK}/lib/public/linux32/tier1.a) + endif() + + target_link_libraries(statusspec dl) +endif() diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..424d385 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,23 @@ +AdvSpec +Copyright (c) 2013, Matthew McNamara +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/offsets.cpp b/src/offsets.cpp new file mode 100644 index 0000000..a1edc70 --- /dev/null +++ b/src/offsets.cpp @@ -0,0 +1,181 @@ +/* + * offsets.cpp + * WebSpec project + * Modified for AdvSpec, used in StatusSpec + * + * Copyright (c) 2013 Matthew McNamara + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "offsets.h" + +int WSOffsets::pCTFPlayer__m_iTeamNum = 0; +int WSOffsets::pCTFPlayer__m_nPlayerCond = 0; +int WSOffsets::pCTFPlayer___condition_bits = 0; +int WSOffsets::pCTFPlayer__m_nPlayerCondEx = 0; +int WSOffsets::pCTFPlayer__m_nPlayerCondEx2 = 0; + +//================================================================================= +// Find the offsets for all stored NetVars +// TODO: change to bool when an offset can't be found +//================================================================================= +void WSOffsets::PrepareOffsets() { + WSOffsets::pCTFPlayer__m_iTeamNum = WSOffsets::FindOffsetOfClassProp("CTFPlayer", "m_iTeamNum"); + WSOffsets::pCTFPlayer__m_nPlayerCond = WSOffsets::FindOffsetOfClassProp("CTFPlayer", "m_nPlayerCond"); + WSOffsets::pCTFPlayer___condition_bits = WSOffsets::FindOffsetOfClassProp("CTFPlayer", "_condition_bits"); + WSOffsets::pCTFPlayer__m_nPlayerCondEx = WSOffsets::FindOffsetOfClassProp("CTFPlayer", "_condition_bits"); + WSOffsets::pCTFPlayer__m_nPlayerCondEx2 = WSOffsets::FindOffsetOfClassProp("CTFPlayer", "m_nPlayerCondEx2"); +} + +//================================================================================= +// Loop through all server classes until className is found, then crawl through the +// class to find the property +// TODO: return -1 when an offset is not found +//================================================================================= +int WSOffsets::FindOffsetOfClassProp(const char *className, const char *propName) { + //ServerClass *sc = serverGameDLL->GetAllServerClasses(); + ClientClass *sc = pClient->GetAllClasses(); + while (sc) { + if (Q_strcmp(sc->GetName(), className) == 0) { + //SendTable *sTable = sc->m_pTable; + RecvTable *sTable = sc->m_pRecvTable; + if (sTable) { + int offset = 0; + bool found = WSOffsets::CrawlForPropOffset(sTable, propName, offset); + if (!found) + offset = 0; + return offset; + } + } + sc = sc->m_pNext; + } + return 0; +} + +int WSOffsets::FindOffsetOfArrayEnt(const char *classname, const char *arrayName, int element) { + ClientClass *cc = pClient->GetAllClasses(); + while (cc) { + if (Q_strcmp(cc->GetName(), classname) == 0) { + RecvTable *rTable = cc->m_pRecvTable; + if (rTable) { + int offset = 0; + bool found = WSOffsets::CrawlForArrayEnt(rTable, arrayName, element, offset); + if (!found) + offset = 0; + return offset; + } + } + cc = cc->m_pNext; + } + + return 0; +} + +//================================================================================= +// Search through a class table, and any subtables, for a given property name +//================================================================================= +bool WSOffsets::CrawlForPropOffset(RecvTable *sTable, const char *propName, int &offset) { + for (int i=0; i < sTable->GetNumProps(); i++) { + //SendProp *sProp = sTable->GetProp(i); + RecvProp *sProp = sTable->GetProp(i); + if (strcmp(sProp->GetName(),"000") == 0) //End of an array + continue; + + //SendTable *sChildTable = sProp->GetDataTable(); + RecvTable *sChildTable = sProp->GetDataTable(); + + //Check if it is an array, don't care for these atm so skip them + bool isArray = false; + if (sChildTable && sChildTable->GetNumProps() > 0) { + if ( !strcmp(sChildTable->GetProp(0)->GetName(), "000") + || !strcmp(sChildTable->GetProp(0)->GetName(), "lengthproxy")) + isArray = true; + } + + if (!isArray) { + //If we have our property, add to the offset and start returning + if (strcmp(sProp->GetName(), propName) == 0) { + offset += sProp->GetOffset(); + return true; + } + + //If we find a subtable, search it for the property, + //but keep current offset in case it isn't found here + if (sProp->GetType() == DPT_DataTable) { + int origOffset = offset; + offset += sProp->GetOffset(); + bool found = WSOffsets::CrawlForPropOffset(sChildTable, propName, offset); + if (found) { + return true; + } else { + offset = origOffset; + } + } + } else { + continue; + } + + if (strcmp(sProp->GetName(), "000") == 0) //More array stuff from dumping function, may not be needed here + break; + } + return false; +} + +bool WSOffsets::CrawlForArrayEnt(RecvTable *sTable, const char *propName, int element, int &offset) { + for (int i=0; i < sTable->GetNumProps(); i++) { + RecvProp *sProp = sTable->GetProp(i); + if (strcmp(sProp->GetName(),"000") == 0) //End of an array + continue; + + //SendTable *sChildTable = sProp->GetDataTable(); + RecvTable *sChildTable = sProp->GetDataTable(); + + //Check if it is an array, don't care for these atm so skip them + bool isArray = false; + if (sChildTable && sChildTable->GetNumProps() > 0) { + if ( !strcmp(sChildTable->GetProp(0)->GetName(), "000") + || !strcmp(sChildTable->GetProp(0)->GetName(), "lengthproxy")) + isArray = true; + } + + if (!isArray) { + //If we have our property, add to the offset and start returning + if (strcmp(sProp->GetName(), propName) == 0) { + offset += sProp->GetOffset(); + return true; + } + + //If we find a subtable, search it for the property, + //but keep current offset in case it isn't found here + if (sProp->GetType() == DPT_DataTable) { + int origOffset = offset; + offset += sProp->GetOffset(); + bool found = WSOffsets::CrawlForArrayEnt(sChildTable, propName, element, offset); + if (found) { + return true; + } else { + offset = origOffset; + } + } + } else { + if (strcmp(sProp->GetName(), propName) != 0) + continue; + + //We have our array + offset += sProp->GetOffset(); + + int elements = sProp->GetDataTable()->GetNumProps(); + if (element < 0 || element >= elements) + return false; + + offset += sProp->GetDataTable()->GetProp(element)->GetOffset(); + return true; + } + + if (strcmp(sProp->GetName(), "000") == 0) //More array stuff from dumping function, may not be needed here + break; + } + return false; +} diff --git a/src/offsets.h b/src/offsets.h new file mode 100644 index 0000000..dc11bcf --- /dev/null +++ b/src/offsets.h @@ -0,0 +1,39 @@ +/* + * offsets.h + * WebSpec project + * Modified for AdvSpec, used in StatusSpec + * + * Copyright (c) 2013 Matthew McNamara + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#ifndef OFFSETS_H +#define OFFSETS_H + +#include "cdll_client_int.h" +#include "client_class.h" + +extern IBaseClientDLL *pClient; + +class WSOffsets { +public: + static int pCTFPlayer__m_iTeamNum; + static int pCTFPlayer__m_nPlayerCond; + static int pCTFPlayer___condition_bits; + static int pCTFPlayer__m_nPlayerCondEx; + static int pCTFPlayer__m_nPlayerCondEx2; + + static void PrepareOffsets(); + static int FindOffsetOfClassProp(const char *className, const char *propName); + static int FindOffsetOfArrayEnt(const char *classname, const char *arrayName, int element); + +private: + static bool CrawlForPropOffset(RecvTable *sTable, const char *propName, int &offset); + static bool CrawlForArrayEnt(RecvTable *sTable, const char *propName, int element, int &offset); +}; + +#define MakePtr( cast, ptr, addValue ) (cast)( (unsigned long)(ptr) + (unsigned long)(addValue)) + +#endif diff --git a/src/statusspec.cpp b/src/statusspec.cpp new file mode 100644 index 0000000..6397ef5 --- /dev/null +++ b/src/statusspec.cpp @@ -0,0 +1,323 @@ +/* + * statusspec.cpp + * StatusSpec project + * + * Copyright (c) 2013 thesupremecommander + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "statusspec.h" + +inline bool DataCompare( const BYTE* pData, const BYTE* bSig, const char* szMask ) +{ + for( ; *szMask; ++szMask, ++pData, ++bSig) + { + if( *szMask == 'x' && *pData != *bSig) + return false; + } + + return ( *szMask ) == NULL; +} + +// Finds a pattern at the specified address +inline DWORD FindPattern ( DWORD dwAddress, DWORD dwSize, BYTE* pbSig, const char* szMask ) +{ + for( DWORD i = NULL; i < dwSize; i++ ) + { + if( DataCompare( (BYTE*) ( dwAddress + i ), pbSig, szMask ) ) + return (DWORD)( dwAddress + i ); + } + return 0; +} + +IGameResources* GetGameResources() { + //IGameResources* res; + static DWORD funcadd = NULL; + if( !funcadd ) + funcadd = FindPattern( (DWORD) GetHandleOfModule( _T("client") ), 0x2680C6, (PBYTE) "\xA1\x00\x00\x00\x00\x85\xC0\x74\x06\x05", "x????xxxxx" ); + + typedef IGameResources* (*GGR_t) (void); + GGR_t GGR = (GGR_t) funcadd; + return GGR(); +} + +static void icons_enabled_change(IConVar *var, const char *pOldValue, float flOldValue); +ConVar icons_enabled("statusspec_icons_enabled", "0", 0, "enable status icons", icons_enabled_change); +ConVar icons_size("statusspec_icons_size", "33", 0, "square size of status icons"); +ConVar icons_max("statusspec_icons_max", "5", 0, "max number of icons to be rendered"); +ConVar icons_blu_x_base("statusspec_icons_blu_x_base", "360", 0, "x-coordinate of the first BLU player"); +ConVar icons_blu_x_delta("statusspec_icons_blu_x_delta", "0", 0, "amount to move in x-direction for next BLU player"); +ConVar icons_blu_y_base("statusspec_icons_blu_y_base", "497", 0, "y-coordinate of the first BLU player"); +ConVar icons_blu_y_delta("statusspec_icons_blu_y_delta", "-33", 0, "amount to move in y-direction for next BLU player"); +ConVar icons_blu_bg_red("statusspec_icons_blu_bg_red", "104", 0, "red value of the icon background for BLU players"); +ConVar icons_blu_bg_green("statusspec_icons_blu_bg_green", "124", 0, "green value of the icon background for BLU players"); +ConVar icons_blu_bg_blue("statusspec_icons_blu_bg_blue", "155", 0, "blue value of the icon background for BLU players"); +ConVar icons_blu_bg_alpha("statusspec_icons_blu_bg_alpha", "127", 0, "alpha value of the icon background for BLU players"); +ConVar icons_red_x_base("statusspec_icons_red_x_base", "360", 0, "x-coordinate of the first RED player"); +ConVar icons_red_x_delta("statusspec_icons_red_x_delta", "0", 0, "amount to move in x-direction for next RED player"); +ConVar icons_red_y_base("statusspec_icons_red_y_base", "542", 0, "y-coordinate of the first RED player"); +ConVar icons_red_y_delta("statusspec_icons_red_y_delta", "33", 0, "amount to move in y-direction for next RED player"); +ConVar icons_red_bg_red("statusspec_icons_red_bg_red", "180", 0, "red value of the icon background for RED players"); +ConVar icons_red_bg_green("statusspec_icons_red_bg_green", "92", 0, "green value of the icon background for RED players"); +ConVar icons_red_bg_blue("statusspec_icons_red_bg_blue", "77", 0, "blue value of the icon background for RED players"); +ConVar icons_red_bg_alpha("statusspec_icons_red_bg_alpha", "127", 0, "alpha value of the icon background for RED players"); + +void (__fastcall *origPaintTraverse)(void* thisptr, int edx, VPANEL, bool, bool); + +void UpdateEntities() { + int iEntCount = pEntityList->GetHighestEntityIndex(); + IClientEntity *cEntity; + + playerInfo.clear(); + + for (int i = 0; i < iEntCount; i++) { + cEntity = pEntityList->GetClientEntity(i); + + // Ensure valid player entity + if (cEntity == NULL || !(GetGameResources()->IsConnected(i))) { + continue; + } + + // get our stuff directly from entity data + int team = *MakePtr(int*, cEntity, WSOffsets::pCTFPlayer__m_iTeamNum); + uint32_t playerCond = *MakePtr(uint32_t*, cEntity, WSOffsets::pCTFPlayer__m_nPlayerCond); + uint32_t condBits = *MakePtr(uint32_t*, cEntity, WSOffsets::pCTFPlayer___condition_bits); + uint32_t playerCondEx = *MakePtr(uint32_t*, cEntity, WSOffsets::pCTFPlayer__m_nPlayerCondEx); + uint32_t playerCondEx2 = *MakePtr(uint32_t*, cEntity, WSOffsets::pCTFPlayer__m_nPlayerCondEx2); + + if (team != TEAM_RED && team != TEAM_BLU) { + continue; + } + + int j = playerInfo.size(); + playerInfo.push_back(player_t()); + + uint64_t playerCondExAdj = playerCondEx; + playerCondExAdj <<= 32; + + playerInfo[j].team = team; + playerInfo[j].lower = playerCond|condBits|playerCondExAdj; + playerInfo[j].upper = playerCondEx2; + } +} + +void __fastcall hookedPaintTraverse( vgui::IPanel *thisPtr, int edx, VPANEL vguiPanel, bool forceRepaint, bool allowForce = true ) { + if (icons_enabled.GetBool()) { + UpdateEntities(); + } + + origPaintTraverse(thisPtr, edx, vguiPanel, forceRepaint, allowForce); + + if (pEngineClient->IsDrawingLoadingImage() || !pEngineClient->IsInGame() || !pEngineClient->IsConnected() || pEngineClient->Con_IsVisible( )) + return; + + const char* panelName = pPanel->GetName(vguiPanel); + if (panelName[0] == 'M' && panelName[3] == 'S' && panelName[9] == 'T' && panelName[12] == 'P') { + if (icons_enabled.GetBool()) { + + int iSize = icons_size.GetInt(); + int iMaxIcons = icons_max.GetInt(); + int iBluXBase = icons_blu_x_base.GetInt(); + int iBluXDelta = icons_blu_x_delta.GetInt(); + int iBluYBase = icons_blu_y_base.GetInt(); + int iBluYDelta = icons_blu_y_delta.GetInt(); + int iBluBGRed = icons_blu_bg_red.GetInt(); + int iBluBGGreen = icons_blu_bg_green.GetInt(); + int iBluBGBlue = icons_blu_bg_blue.GetInt(); + int iBluBGAlpha = icons_blu_bg_alpha.GetInt(); + int iRedXBase = icons_red_x_base.GetInt(); + int iRedXDelta = icons_red_x_delta.GetInt(); + int iRedYBase = icons_red_y_base.GetInt(); + int iRedYDelta = icons_red_y_delta.GetInt(); + int iRedBGRed = icons_red_bg_red.GetInt(); + int iRedBGGreen = icons_red_bg_green.GetInt(); + int iRedBGBlue = icons_red_bg_blue.GetInt(); + int iRedBGAlpha = icons_red_bg_alpha.GetInt(); + + int iIconSize = iSize - 2; + int iBarSize = iSize * iMaxIcons; + + int iPlayerCount = playerInfo.size(); + int iRedPlayers = -1; + int iBluPlayers = -1; + + for (int i = 0; i < iPlayerCount; i++) { + int iX = 0; + int iY = 0; + + if (playerInfo[i].team == TEAM_RED) { + iRedPlayers++; + iX = iRedXBase + (iRedPlayers * iRedXDelta); + iY = iRedYBase + (iRedPlayers * iRedYDelta); + pSurface->DrawSetColor(iRedBGRed, iRedBGGreen, iRedBGBlue, iRedBGAlpha); + pSurface->DrawFilledRect(iX, iY, iX + iBarSize, iY + iSize); + } + else if (playerInfo[i].team == TEAM_BLU) { + iBluPlayers++; + iX = iBluXBase + (iBluPlayers * iBluXDelta); + iY = iBluYBase + (iBluPlayers * iBluYDelta); + pSurface->DrawSetColor(iBluBGRed, iBluBGGreen, iBluBGBlue, iBluBGAlpha); + pSurface->DrawFilledRect(iX, iY, iX + iBarSize, iY + iSize); + } + + int iIcons = 0; + + if (playerInfo[i].lower & TFCOND_LOWER_UBERCHARGED) { + pSurface->DrawSetTexture(m_iTextureUbercharged); + pSurface->DrawSetColor(255, 255, 255, 255); + + if (playerInfo[i].team == TEAM_RED) { + iX = iRedXBase + (iRedPlayers * iRedXDelta) + (iIcons * iSize) + 1; + iY = iRedYBase + (iRedPlayers * iRedYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + else if (playerInfo[i].team == TEAM_BLU) { + iX = iBluXBase + (iBluPlayers * iBluXDelta) + (iIcons * iSize) + 1; + iY = iBluYBase + (iBluPlayers * iBluYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + + iIcons++; + } + + if (iIcons >= iMaxIcons) { + continue; + } + + if (playerInfo[i].lower & TFCOND_LOWER_KRITZKRIEGED) { + pSurface->DrawSetTexture(m_iTextureCritBoosted); + pSurface->DrawSetColor(255, 255, 255, 255); + + if (playerInfo[i].team == TEAM_RED) { + iX = iRedXBase + (iRedPlayers * iRedXDelta) + (iIcons * iSize) + 1; + iY = iRedYBase + (iRedPlayers * iRedYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + else if (playerInfo[i].team == TEAM_BLU) { + iX = iBluXBase + (iBluPlayers * iBluXDelta) + (iIcons * iSize) + 1; + iY = iBluYBase + (iBluPlayers * iBluYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + + iIcons++; + } + + if (iIcons >= iMaxIcons) { + continue; + } + + if (playerInfo[i].lower & (TFCOND_LOWER_MARKEDFORDEATH | TFCOND_LOWER_MARKEDFORDEATHSILENT)) { + pSurface->DrawSetTexture(m_iTextureMarkedForDeath); + pSurface->DrawSetColor(255, 255, 255, 255); + + if (playerInfo[i].team == TEAM_RED) { + iX = iRedXBase + (iRedPlayers * iRedXDelta) + (iIcons * iSize) + 1; + iY = iRedYBase + (iRedPlayers * iRedYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + else if (playerInfo[i].team == TEAM_BLU) { + iX = iBluXBase + (iBluPlayers * iBluXDelta) + (iIcons * iSize) + 1; + iY = iBluYBase + (iBluPlayers * iBluYDelta) + 1; + pSurface->DrawTexturedRect(iX, iY, iX + iIconSize, iY + iIconSize); + } + + iIcons++; + } + + if (iIcons >= iMaxIcons) { + continue; + } + } + } + } +} + +// The plugin is a static singleton that is exported as an interface +StatusSpecPlugin g_StatusSpecPlugin; +EXPOSE_SINGLE_INTERFACE_GLOBALVAR(StatusSpecPlugin, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, g_StatusSpecPlugin ); + +StatusSpecPlugin::StatusSpecPlugin() +{ +} + +StatusSpecPlugin::~StatusSpecPlugin() +{ +} + +bool StatusSpecPlugin::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ) +{ + ConnectTier1Libraries( &interfaceFactory, 1 ); + + void* hmClient = GetHandleOfModule("client"); + CreateInterfaceFn pfnClient = (CreateInterfaceFn) GetFuncAddress(hmClient, "CreateInterface"); + pClient = (IBaseClientDLL*) pfnClient("VClient017", NULL); + pEntityList = (IClientEntityList*) pfnClient("VClientEntityList003", NULL); + + void* hmEngine = GetHandleOfModule("engine"); + CreateInterfaceFn pfnEngine = (CreateInterfaceFn) GetFuncAddress(hmEngine, "CreateInterface"); + pEngineClient = (IVEngineClient*) pfnEngine("VEngineClient013", NULL); + + void* hmVGUI2 = GetHandleOfModule("vgui2"); + void* hmVGUIMatSurface = GetHandleOfModule("vguimatsurface"); + CreateInterfaceFn pfnVGUI2 = (CreateInterfaceFn) GetFuncAddress(hmVGUI2, "CreateInterface"); + CreateInterfaceFn pfnVGUIMatSurface = (CreateInterfaceFn) GetFuncAddress(hmVGUIMatSurface, "CreateInterface"); + + pPanel = (vgui::IPanel*) pfnVGUI2("VGUI_Panel009", NULL); + pScheme = (vgui::ISchemeManager*) pfnVGUI2("VGUI_Scheme010", NULL); + pSurface = (vgui::ISurface*) pfnVGUIMatSurface("VGUI_Surface030", NULL); + + m_font = 0; + + m_iTextureUbercharged = pSurface->CreateNewTextureID(); + pSurface->DrawSetTextureFile(m_iTextureUbercharged, "vgui/replay/thumbnails/ubercharge", 0, false); + m_iTextureCritBoosted = pSurface->CreateNewTextureID(); + pSurface->DrawSetTextureFile(m_iTextureCritBoosted, "vgui/replay/thumbnails/critboost", 0, false); + m_iTextureMarkedForDeath = pSurface->CreateNewTextureID(); + pSurface->DrawSetTextureFile(m_iTextureMarkedForDeath, "vgui/marked_for_death", 0, false); + + //Hook PaintTraverse + origPaintTraverse = (void (__fastcall *)(void *, int, VPANEL, bool, bool)) + HookVFunc(*(DWORD**)pPanel, Index_PaintTraverse, (DWORD*) &hookedPaintTraverse); + + // Get offsets + WSOffsets::PrepareOffsets(); + + //Everything seems ok! + Msg("%s loaded!\n", PLUGIN_DESC); + + //Register cvars + ConVar_Register( 0 ); + return true; +} + +void StatusSpecPlugin::Unload( void ) +{ + ConVar_Unregister( ); + DisconnectTier1Libraries(); +} + +void StatusSpecPlugin::FireGameEvent( KeyValues * event ) {} +void StatusSpecPlugin::Pause( void ){} +void StatusSpecPlugin::UnPause( void ){} +const char *StatusSpecPlugin::GetPluginDescription( void ){return PLUGIN_DESC;} +void StatusSpecPlugin::LevelInit( char const *pMapName ){} +void StatusSpecPlugin::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ){} +void StatusSpecPlugin::GameFrame( bool simulating ){} +void StatusSpecPlugin::LevelShutdown( void ){} +void StatusSpecPlugin::ClientActive( edict_t *pEntity ){} +void StatusSpecPlugin::ClientDisconnect( edict_t *pEntity ){} +void StatusSpecPlugin::ClientPutInServer( edict_t *pEntity, char const *playername ){} +void StatusSpecPlugin::SetCommandClient( int index ){} +void StatusSpecPlugin::ClientSettingsChanged( edict_t *pEdict ){} +PLUGIN_RESULT StatusSpecPlugin::ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ){return PLUGIN_CONTINUE;} +PLUGIN_RESULT StatusSpecPlugin::ClientCommand( edict_t *pEntity, const CCommand &args ){return PLUGIN_CONTINUE;} +PLUGIN_RESULT StatusSpecPlugin::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ){return PLUGIN_CONTINUE;} +void StatusSpecPlugin::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ){} +void StatusSpecPlugin::OnEdictAllocated( edict_t *edict ){} +void StatusSpecPlugin::OnEdictFreed( const edict_t *edict ){} + +static void icons_enabled_change(IConVar *var, const char *pOldValue, float flOldValue) { + UpdateEntities(); +} diff --git a/src/statusspec.h b/src/statusspec.h new file mode 100644 index 0000000..8dbad7c --- /dev/null +++ b/src/statusspec.h @@ -0,0 +1,196 @@ +/* + * statusspec.h + * StatusSpec project + * + * Copyright (c) 2013 thesupremecommander + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#ifndef STATUSSPEC_H +#define STATUSSPEC_H + +#define CLIENT_DLL + +#include "stdafx.h" + +#include "tier1/tier1.h" +#include "engine/iserverplugin.h" +#include "igameevents.h" + +#include "offsets.h" +#include "vfuncs.h" +#include "icvar.h" + +#define PLUGIN_DESC "StatusSpec v0.1" +#define SHORT_DESC "StatusSpec v0.1" + +#define SCALED(normalValue) pScheme->GetProportionalScaledValue(normalValue) + +#define TEAM_RED 2 +#define TEAM_BLU 3 + +// taken from SourceMod and adapted + +#define TFCOND_LOWER_SLOWED ((uint64_t) 1 << 0) +#define TFCOND_LOWER_ZOOMED ((uint64_t) 1 << 1) +#define TFCOND_LOWER_DISGUISING ((uint64_t) 1 << 2) +#define TFCOND_LOWER_DISGUISED ((uint64_t) 1 << 3) +#define TFCOND_LOWER_CLOAKED ((uint64_t) 1 << 4) +#define TFCOND_LOWER_UBERCHARGED ((uint64_t) 1 << 5) +#define TFCOND_LOWER_TELEPORTEDGLOW ((uint64_t) 1 << 6) +#define TFCOND_LOWER_TAUNTING ((uint64_t) 1 << 7) +#define TFCOND_LOWER_UBERCHARGEFADING ((uint64_t) 1 << 8) +#define TFCOND_LOWER_CLOAKFLICKER ((uint64_t) 1 << 9) +#define TFCOND_LOWER_TELEPORTING ((uint64_t) 1 << 10) +#define TFCOND_LOWER_KRITZKRIEGED ((uint64_t) 1 << 11) +#define TFCOND_LOWER_TMPDAMAGEBONUS ((uint64_t) 1 << 12) +#define TFCOND_LOWER_DEADRINGERED ((uint64_t) 1 << 13) +#define TFCOND_LOWER_BONKED ((uint64_t) 1 << 14) +#define TFCOND_LOWER_DAZED ((uint64_t) 1 << 15) +#define TFCOND_LOWER_BUFFED ((uint64_t) 1 << 16) +#define TFCOND_LOWER_CHARGING ((uint64_t) 1 << 17) +#define TFCOND_LOWER_DEMOBUFF ((uint64_t) 1 << 18) +#define TFCOND_LOWER_CRITCOLA ((uint64_t) 1 << 19) +#define TFCOND_LOWER_INHEALRADIUS ((uint64_t) 1 << 20) +#define TFCOND_LOWER_HEALING ((uint64_t) 1 << 21) +#define TFCOND_LOWER_ONFIRE ((uint64_t) 1 << 22) +#define TFCOND_LOWER_OVERHEALED ((uint64_t) 1 << 23) +#define TFCOND_LOWER_JARATED ((uint64_t) 1 << 24) +#define TFCOND_LOWER_BLEEDING ((uint64_t) 1 << 25) +#define TFCOND_LOWER_DEFENSEBUFFED ((uint64_t) 1 << 26) +#define TFCOND_LOWER_MILKED ((uint64_t) 1 << 27) +#define TFCOND_LOWER_MEGAHEAL ((uint64_t) 1 << 28) +#define TFCOND_LOWER_REGENBUFFED ((uint64_t) 1 << 29) +#define TFCOND_LOWER_MARKEDFORDEATH ((uint64_t) 1 << 30) +#define TFCOND_LOWER_NOHEALINGDAMAGEBUFF ((uint64_t) 1 << 31) +#define TFCOND_LOWER_SPEEDBUFFALLY ((uint64_t) 1 << 32) +#define TFCOND_LOWER_HALLOWEENCRITCANDY ((uint64_t) 1 << 33) +#define TFCOND_LOWER_CRITCANTEEN ((uint64_t) 1 << 34) +#define TFCOND_LOWER_CRITDEMOCHARGE ((uint64_t) 1 << 35) +#define TFCOND_LOWER_CRITHYPE ((uint64_t) 1 << 36) +#define TFCOND_LOWER_CRITONFIRSTBLOOD ((uint64_t) 1 << 37) +#define TFCOND_LOWER_CRITONWIN ((uint64_t) 1 << 38) +#define TFCOND_LOWER_CRITONFLAGCAPTURE ((uint64_t) 1 << 39) +#define TFCOND_LOWER_CRITONKILL ((uint64_t) 1 << 40) +#define TFCOND_LOWER_RESTRICTTOMELEE ((uint64_t) 1 << 41) +#define TFCOND_LOWER_DEFENSEBUFFNOCRITBLOCK ((uint64_t) 1 << 42) +#define TFCOND_LOWER_REPROGRAMMED ((uint64_t) 1 << 43) +#define TFCOND_LOWER_CRITMMMPH ((uint64_t) 1 << 44) +#define TFCOND_LOWER_DEFENSEBUFFMMMPH ((uint64_t) 1 << 45) +#define TFCOND_LOWER_FOCUSBUFF ((uint64_t) 1 << 46) +#define TFCOND_LOWER_DISGUISEREMOVED ((uint64_t) 1 << 47) +#define TFCOND_LOWER_MARKEDFORDEATHSILENT ((uint64_t) 1 << 48) +#define TFCOND_LOWER_DISGUISEDASDISPENSER ((uint64_t) 1 << 49) +#define TFCOND_LOWER_SAPPED ((uint64_t) 1 << 50) +#define TFCOND_LOWER_UBERCHARGEDHIDDEN ((uint64_t) 1 << 51) +#define TFCOND_LOWER_UBERCHARGEDCANTEEN ((uint64_t) 1 << 52) +#define TFCOND_LOWER_HALLOWEENBOMBHEAD ((uint64_t) 1 << 53) +#define TFCOND_LOWER_HALLOWEENTHRILLER ((uint64_t) 1 << 54) +#define TFCOND_LOWER_RADIUSHEALONDAMAGE ((uint64_t) 1 << 55) +#define TFCOND_LOWER_CRITONDAMAGE ((uint64_t) 1 << 56) +#define TFCOND_LOWER_UBERCHARGEDONTAKEDAMAGE ((uint64_t) 1 << 57) +#define TFCOND_LOWER_UBERBULLETRESIST ((uint64_t) 1 << 58) +#define TFCOND_LOWER_UBERBLASTRESIST ((uint64_t) 1 << 59) +#define TFCOND_LOWER_UBERFIRERESIST ((uint64_t) 1 << 60) +#define TFCOND_LOWER_SMALLBULLETRESIST ((uint64_t) 1 << 61) +#define TFCOND_LOWER_SMALLBLASTRESIST ((uint64_t) 1 << 62) +#define TFCOND_LOWER_SMALLFIRERESIST ((uint64_t) 1 << 63) + +#define TFCOND_LOWER_STEALTHED ((uint64_t) 1 << 0) +#define TFCOND_UPPER_MEDIGUNDEBUFF ((uint64_t) 1 << 1) +#define TFCOND_UPPER_STEALTHEDUSERBUFFFADE ((uint64_t) 1 << 2) +#define TFCOND_UPPER_BULLETIMMUNE ((uint64_t) 1 << 3) +#define TFCOND_UPPER_BLASTIMMUNE ((uint64_t) 1 << 4) +#define TFCOND_UPPER_FIREIMMUNE ((uint64_t) 1 << 5) +#define TFCOND_UPPER_PREVENTDEATH ((uint64_t) 1 << 6) +#define TFCOND_UPPER_MVMBOTRADIOWAVE ((uint64_t) 1 << 7) +#define TFCOND_UPPER_HALLOWEENSPEEDBOOST ((uint64_t) 1 << 8) +#define TFCOND_UPPER_HALLOWEENQUICKHEAL ((uint64_t) 1 << 9) +#define TFCOND_UPPER_HALLOWEENGIANT ((uint64_t) 1 << 10) +#define TFCOND_UPPER_HALLOWEENTINY ((uint64_t) 1 << 11) +#define TFCOND_UPPER_HALLOWEENINHELL ((uint64_t) 1 << 12) +#define TFCOND_UPPER_HALLOWEENGHOSTMODE ((uint64_t) 1 << 13) + +#include "cbase.h" +#include "cdll_int.h" +#include "icliententitylist.h" +#include "icliententity.h" +#include "convar.h" +#include "edict.h" +#include "igameresources.h" +#include "igameevents.h" +#include "vgui/IPanel.h" +#include "vgui/ISurface.h" +#include "vgui/IScheme.h" +#include "ehandle.h" + +#include "stdint.h" +#include "vector" + +//class CBaseCombatCharacter; +class C_BaseCombatWeapon; +typedef unsigned int VPANEL; +typedef CHandle EHANDLE; + +// client.dll +IBaseClientDLL* pClient; +IClientEntityList* pEntityList; + +// engine.dll +IVEngineClient *pEngineClient; + +// vgui2.dll +vgui::IPanel* pPanel; +vgui::ISurface* pSurface; +vgui::ISchemeManager* pScheme; +vgui::HFont m_font; + +int m_iTextureUbercharged; +int m_iTextureCritBoosted; +int m_iTextureMarkedForDeath; + +typedef struct player_s { + int team; + uint64_t upper; + uint64_t lower; +} player_t; + +std::vector playerInfo; + +#define Round(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5)) + +class StatusSpecPlugin: public IServerPluginCallbacks, public IGameEventListener +{ +public: + StatusSpecPlugin(); + ~StatusSpecPlugin(); + + // IServerPluginCallbacks methods + virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ); + virtual void Unload( void ); + virtual void Pause( void ); + virtual void UnPause( void ); + virtual const char *GetPluginDescription( void ); + virtual void LevelInit( char const *pMapName ); + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); + virtual void GameFrame( bool simulating ); + virtual void LevelShutdown( void ); + virtual void ClientActive( edict_t *pEntity ); + virtual void ClientDisconnect( edict_t *pEntity ); + virtual void ClientPutInServer( edict_t *pEntity, char const *playername ); + virtual void SetCommandClient( int index ); + virtual void ClientSettingsChanged( edict_t *pEdict ); + virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); + virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args ); + virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); + virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); + virtual void OnEdictAllocated( edict_t *edict ); + virtual void OnEdictFreed( const edict_t *edict ); + + // IGameEventListener Interface + virtual void FireGameEvent( KeyValues * event ); +}; + +#endif diff --git a/src/stdafx.h b/src/stdafx.h new file mode 100644 index 0000000..e8a7f26 --- /dev/null +++ b/src/stdafx.h @@ -0,0 +1,44 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#ifndef _POSIX +//#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include +#else +#include +#include +#include + +typedef unsigned char BYTE; +typedef BYTE *PBYTE; + +#define __fastcall +#define __thiscall +#endif + +#ifndef _POSIX +// Only available on windows... +#include +#else +#define __debugbreak() +#endif + +#include +#include +#include +#include + +#ifdef _POSIX +#define GetFuncAddress(pAddress, szFunction) dlsym(pAddress, szFunction) +#define GetHandleOfModule(szModuleName) dlopen(szModuleName".so", RTLD_NOLOAD) +#else +#define GetFuncAddress(pAddress, szFunction) ::GetProcAddress((HMODULE)pAddress, szFunction) +#define GetHandleOfModule(szModuleName) GetModuleHandleA(szModuleName".dll") +#endif diff --git a/src/vfuncs.cpp b/src/vfuncs.cpp new file mode 100644 index 0000000..32c048e --- /dev/null +++ b/src/vfuncs.cpp @@ -0,0 +1,33 @@ +/* + * vfuncs.cpp + * WebSpec project + * Modified for AdvSpec, used in StatusSpec + * + * Copyright (c) 2013 Matthew McNamara + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "vfuncs.h" + +DWORD *HookVFunc(DWORD *vtable, int index, DWORD *newFunction) +{ + #ifndef _POSIX + DWORD dwOldProt; + #endif + DWORD *oldFunc; + + #ifdef _POSIX + mprotect(&vtable[index], 4, PROT_READ|PROT_WRITE|PROT_EXEC); + #else + VirtualProtect(&vtable[index], 4, PAGE_EXECUTE_READWRITE, &dwOldProt); + #endif + oldFunc=(DWORD*)vtable[index]; + vtable[index]=(DWORD)newFunction; + #ifndef _POSIX //TODO: Restore mem protection on posix + VirtualProtect(&vtable[index], 4, dwOldProt, &dwOldProt); + #endif + + return oldFunc; +} \ No newline at end of file diff --git a/src/vfuncs.h b/src/vfuncs.h new file mode 100644 index 0000000..5335316 --- /dev/null +++ b/src/vfuncs.h @@ -0,0 +1,42 @@ +/* + * vfuncs.h + * WebSpec project + * Modified for AdvSpec, used in StatusSpec + * + * Copyright (c) 2013 Matthew McNamara + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#ifndef VFUNCS_H +#define VFUNCS_H + +#define CLIENT_DLL + +#include "tier0/platform.h" +#include "cbase.h" + +class WSEmptyClass {}; + +#if defined (_POSIX) // client.dylib +enum vfuncIndices { + Index_PaintTraverse = 42 +}; +#else // client.dll +enum vfuncIndices { + Index_PaintTraverse = 41 +}; +#endif + +#if !defined( _POSIX ) +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +//typedef unsigned long DWORD; +#endif + +extern DWORD *HookVFunc(DWORD *vtable, int index, DWORD *newFunction); + +#endif