diff --git a/extension.cpp b/extension.cpp
index 564aa07..ef5b2e7 100644
--- a/extension.cpp
+++ b/extension.cpp
@@ -1,721 +1,721 @@
-/**
- * vim: set ts=4 :
- * =============================================================================
- * SourceMod Sample Extension
- * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- *
- * As a special exception, AlliedModders LLC gives you permission to link the
- * code of this program (as well as its derivative works) to "Half-Life 2," the
- * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
- * by the Valve Corporation. You must obey the GNU General Public License in
- * all respects for all other code used. Additionally, AlliedModders LLC grants
- * this exception to all derivative works. AlliedModders LLC defines further
- * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
- * or .
- *
- * Version: $Id$
- */
-
-#include "extension.h"
-#include "CDetour/detours.h"
-#include "iplayerinfo.h"
-#include
-#include
-#include
-#include
-#include
-
-#define SetBit(A,I) ((A)[(I) >> 5] |= (1 << ((I) & 31)))
-#define ClearBit(A,I) ((A)[(I) >> 5] &= ~(1 << ((I) & 31)))
-#define CheckBit(A,I) !!((A)[(I) >> 5] & (1 << ((I) & 31)))
-
-bool UTIL_ContainsDataTable(SendTable *pTable, const char *name)
-{
- const char *pname = pTable->GetName();
- int props = pTable->GetNumProps();
- SendProp *prop;
- SendTable *table;
-
- if (pname && strcmp(name, pname) == 0)
- return true;
-
- for (int i=0; iGetProp(i);
-
- if ((table = prop->GetDataTable()) != NULL)
- {
- pname = table->GetName();
- if (pname && strcmp(name, pname) == 0)
- {
- return true;
- }
-
- if (UTIL_ContainsDataTable(table, name))
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-class CTraceFilterSimple : public CTraceFilter
-{
-public:
- virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) = 0;
- virtual void SetPassEntity( const IHandleEntity *pPassEntity ) = 0;
- virtual void SetCollisionGroup( int iCollisionGroup ) = 0;
-};
-
-class CTraceFilterSkipTwoEntities : public CTraceFilterSimple
-{
-public:
- virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) = 0;
- virtual void SetPassEntity2( const IHandleEntity *pPassEntity2 ) = 0;
-};
-
-static struct SrcdsPatch
-{
- const char *pSignature;
- const unsigned char *pPatchSignature;
- const char *pPatchPattern;
- const unsigned char *pPatch;
-
- unsigned char *pOriginal;
- uintptr_t pAddress;
- uintptr_t pPatchAddress;
- bool engine;
-} gs_Patches[] = {
- // 0: game_ui should not apply FL_ONTRAIN flag, else client prediction turns off
- {
- "_ZN7CGameUI5ThinkEv",
- (unsigned char *)"\xC7\x44\x24\x04\x10\x00\x00\x00\x89\x34\x24\xE8\x00\x00\x00\x00",
- "xxxxxxxxxxxx????",
- (unsigned char *)"\xC7\x44\x24\x04\x10\x00\x00\x00\x89\x34\x24\x90\x90\x90\x90\x90",
- 0, 0, 0, false
- },
- // 1: player_speedmod should not turn off flashlight
- {
- "_ZN17CMovementSpeedMod13InputSpeedModER11inputdata_t",
- (unsigned char *)"\xFF\x90\x8C\x05\x00\x00\x85\xC0\x0F\x85\x75\x02\x00\x00",
- "xxxxxxxxxxxxxx",
- (unsigned char *)"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
- 0, 0, 0, false
- },
- // 2: only select CT spawnpoints
- {
- "_ZN9CCSPlayer19EntSelectSpawnPointEv",
- (unsigned char *)"\x89\x1C\x24\xE8\x00\x00\x00\x00\x83\xF8\x03\x74\x4B",
- "xxxx????xxxxx",
- (unsigned char *)"\x89\x1C\x24\x90\x90\x90\x90\x90\x90\x90\x90\xEB\x4B",
- 0, 0, 0, false
- },
- // 3: don't check if we have T spawns
- {
- "_ZN12CCSGameRules18NeededPlayersCheckERb",
- (unsigned char *)"\x74\x0E\x8B\x83\x80\x02\x00\x00\x85\xC0\x0F\x85\x9E\x00\x00\x00\xC7\x04\x24\xAC\xF7\x87\x00\xE8\xC2\x82\x91\x00",
- "xxxxxxxxxxxxxxxx????????????",
- (unsigned char *)"\x0F\x85\xA8\x00\x00\x00\x8B\x83\x80\x02\x00\x00\x85\xC0\x0F\x85\x9A\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90",
- 0, 0, 0, false
- },
- // 5: disable alive check in point_viewcontrol->Disable
- {
- "_ZN14CTriggerCamera7DisableEv",
- (unsigned char *)"\x8B\x10\x89\x04\x24\xFF\x92\x08\x01\x00\x00\x84\xC0\x0F\x84\x58\xFF\xFF\xFF",
- "xxxxxxx??xxxxxx?xxx",
- (unsigned char *)"\x8B\x10\x89\x04\x24\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
- 0, 0, 0, false
- },
- // 6: disable player->m_takedamage = DAMAGE_NO in point_viewcontrol->Enable
- {
- "_ZN14CTriggerCamera6EnableEv",
- (unsigned char *)"\x31\xFF\x80\xBF\xFD\x00\x00\x00\x00\x0F\x85\x96\x03\x00\x00",
- "xxxx?xxxxxx??xx",
- (unsigned char *)"\x31\xFF\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
- 0, 0, 0, false
- },
- // 7: disable player->m_takedamage = m_nOldTakeDamage in point_viewcontrol->Disable
- {
- "_ZN14CTriggerCamera7DisableEv",
- (unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x0F\x84\xAC\xFD\xFF\xFF",
- "xxxx?xxxxxxxxx",
- (unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x90\xE9\xAC\xFD\xFF\xFF",
- 0, 0, 0, false
- },
- // 8: userinfo stringtable don't write fakeclient field
- {
- "_ZN11CBaseClient12FillUserInfoER13player_info_s",
- (unsigned char *)"\xFF\x50\x70\x88\x46\x6C",
- "xxxxxx",
- (unsigned char *)"\x90\x90\x90\x90\x90\x90",
- 0, 0, 0, true
- }
-};
-
-class CBaseEntity;
-struct variant_hax
-{
- const char *pszValue;
-};
-
-struct inputdata_t
-{
- // The entity that initially caused this chain of output events.
- CBaseEntity *pActivator;
- // The entity that fired this particular output.
- CBaseEntity *pCaller;
- // The data parameter for this output.
- variant_hax value;
- // The unique ID of the output that was fired.
- int nOutputID;
-};
-
-typedef bool (*ShouldHitFunc_t)( IHandleEntity *pHandleEntity, int contentsMask );
-
-uintptr_t FindPattern(uintptr_t BaseAddr, const unsigned char *pData, const char *pPattern, size_t MaxSize);
-uintptr_t FindFunctionCall(uintptr_t BaseAddr, uintptr_t Function, size_t MaxSize);
-
-/**
- * @file extension.cpp
- * @brief Implement extension code here.
- */
-
-CSSFixes g_Interface;
-SMEXT_LINK(&g_Interface);
-
-IGameConfig *g_pGameConf = NULL;
-
-CDetour *g_pDetour_InputTestActivator = NULL;
-CDetour *g_pDetour_PostConstructor = NULL;
-CDetour *g_pDetour_FindUseEntity = NULL;
-CDetour *g_pDetour_CTraceFilterSimple = NULL;
-CDetour *g_pDetour_KeyValue = NULL;
-CDetour *g_pDetour_FireBullets = NULL;
-CDetour *g_pDetour_SwingOrStab = NULL;
-int g_SH_SkipTwoEntitiesShouldHitEntity = 0;
-int g_SH_SimpleShouldHitEntity = 0;
-
-uintptr_t g_CTraceFilterNoNPCsOrPlayer = 0;
-CTraceFilterSkipTwoEntities *g_CTraceFilterSkipTwoEntities = NULL;
-CTraceFilterSimple *g_CTraceFilterSimple = NULL;
-
-/* Fix crash in CBaseFilter::InputTestActivator */
-DETOUR_DECL_MEMBER1(DETOUR_InputTestActivator, void, inputdata_t *, inputdata)
-{
- if(!inputdata || !inputdata->pActivator || !inputdata->pCaller)
- return;
-
- DETOUR_MEMBER_CALL(DETOUR_InputTestActivator)(inputdata);
-}
-
-DETOUR_DECL_MEMBER1(DETOUR_PostConstructor, void, const char *, szClassname)
-{
- if(strncasecmp(szClassname, "info_player_", 12) == 0)
- {
- CBaseEntity *pEntity = (CBaseEntity *)this;
-
- datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
- typedescription_t *td = gamehelpers->FindInDataMap(pMap, "m_iEFlags");
-
- // Spawnpoints don't need edicts...
- *(uint32 *)((intptr_t)pEntity + td->fieldOffset[TD_OFFSET_NORMAL]) |= (1<<9); // EFL_SERVER_ONLY
-
- // Only CT spawnpoints
- if(strcasecmp(szClassname, "info_player_terrorist") == 0)
- szClassname = "info_player_counterterrorist";
- }
-
- DETOUR_MEMBER_CALL(DETOUR_PostConstructor)(szClassname);
-}
-
-DETOUR_DECL_MEMBER2(DETOUR_KeyValue, bool, const char *, szKeyName, const char *, szValue)
-{
- // Fix crash bug in engine
- if(strcasecmp(szKeyName, "angle") == 0)
- szKeyName = "angles";
-
- else if(strcasecmp(szKeyName, "classname") == 0 &&
- strcasecmp(szValue, "info_player_terrorist") == 0)
- {
- // Only CT spawnpoints
- szValue = "info_player_counterterrorist";
- }
- else if(strcasecmp(szKeyName, "teamnum") == 0 || strcasecmp(szKeyName, "teamnum") == 0 )
- {
- CBaseEntity *pEntity = (CBaseEntity *)this;
- const char *pClassname = gamehelpers->GetEntityClassname(pEntity);
-
- // All buyzones should be CT buyzones
- if(pClassname && strcasecmp(pClassname, "func_buyzone") == 0)
- szValue = "3";
- }
-
- return DETOUR_MEMBER_CALL(DETOUR_KeyValue)(szKeyName, szValue);
-}
-
-/* Ignore players in +USE trace */
-bool g_InFindUseEntity = false;
-DETOUR_DECL_MEMBER0(DETOUR_FindUseEntity, CBaseEntity *)
-{
- // Signal CTraceFilterSimple that we are in FindUseEntity
- g_InFindUseEntity = true;
- CBaseEntity *pEntity = DETOUR_MEMBER_CALL(DETOUR_FindUseEntity)();
- g_InFindUseEntity = false;
- return pEntity;
-}
-DETOUR_DECL_MEMBER3(DETOUR_CTraceFilterSimple, void, const IHandleEntity *, passedict, int, collisionGroup, ShouldHitFunc_t, pExtraShouldHitFunc)
-{
- DETOUR_MEMBER_CALL(DETOUR_CTraceFilterSimple)(passedict, collisionGroup, pExtraShouldHitFunc);
-
- // If we're in FindUseEntity right now then switch out the VTable
- if(g_InFindUseEntity)
- *(uintptr_t *)this = g_CTraceFilterNoNPCsOrPlayer;
-}
-
-/* Make bullets ignore teammates */
-char *g_pPhysboxToClientMap = NULL;
-bool g_InFireBullets = false;
-int g_FireBulletPlayerTeam = 0;
-SH_DECL_HOOK2(CTraceFilterSkipTwoEntities, ShouldHitEntity, SH_NOATTRIB, 0, bool, IHandleEntity *, int);
-SH_DECL_HOOK2(CTraceFilterSimple, ShouldHitEntity, SH_NOATTRIB, 0, bool, IHandleEntity *, int);
-bool ShouldHitEntity(IHandleEntity *pHandleEntity, int contentsMask)
-{
- if(!g_InFireBullets)
- RETURN_META_VALUE(MRES_IGNORED, true);
-
- if(META_RESULT_ORIG_RET(bool) == false)
- RETURN_META_VALUE(MRES_IGNORED, false);
-
- IServerUnknown *pUnk = (IServerUnknown *)pHandleEntity;
- CBaseHandle hndl = pUnk->GetRefEHandle();
- int index = hndl.GetEntryIndex();
-
- int iTeam = 0;
-
- if(index > SM_MAXPLAYERS && g_pPhysboxToClientMap && index < 2048)
- {
- index = g_pPhysboxToClientMap[index];
- }
-
- if(index >= -3 && index <= -1)
- {
- iTeam = -index;
- }
- else if(index < 1 || index > SM_MAXPLAYERS)
- {
- RETURN_META_VALUE(MRES_IGNORED, true);
- }
-
- if(!iTeam)
- {
- IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index);
- if(!pPlayer || !pPlayer->GetEdict())
- RETURN_META_VALUE(MRES_IGNORED, true);
-
- IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
- if(!pInfo)
- RETURN_META_VALUE(MRES_IGNORED, true);
-
- iTeam = pInfo->GetTeamIndex();
- }
-
- if(iTeam == g_FireBulletPlayerTeam)
- RETURN_META_VALUE(MRES_SUPERCEDE, false);
-
- RETURN_META_VALUE(MRES_IGNORED, true);
-}
-
-DETOUR_DECL_STATIC9(DETOUR_FireBullets, void, int, iPlayerIndex, const Vector *, vOrigin, const QAngle *, vAngles, int, iWeaponID, int, iMode, int, iSeed, float, flSpread, float, _f1, float, _f2)
-{
- if(iPlayerIndex <= 0 || iPlayerIndex > playerhelpers->GetMaxClients())
- return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
-
- IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(iPlayerIndex);
- if(!pPlayer || !pPlayer->GetEdict())
- return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
-
- IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
- if(!pInfo)
- return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
-
- g_FireBulletPlayerTeam = pInfo->GetTeamIndex();
-
- g_InFireBullets = true;
- DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
- g_InFireBullets = false;
-}
-
-DETOUR_DECL_MEMBER1(DETOUR_SwingOrStab, bool, bool, bStab)
-{
- static int offset = 0;
- if(!offset)
- {
- IServerUnknown *pUnk = (IServerUnknown *)this;
- IServerNetworkable *pNet = pUnk->GetNetworkable();
-
- if (!UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, "DT_BaseCombatWeapon"))
- return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
-
- sm_sendprop_info_t spi;
- if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))
- return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
-
- offset = spi.actual_offset;
- }
-
- CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)this + offset);
-
- edict_t *pEdict = gamehelpers->GetHandleEntity(hndl);
- if(!pEdict)
- return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
-
- IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(pEdict);
- if(!pPlayer || !pPlayer->GetEdict())
- return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
-
- IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
- if(!pInfo)
- return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
-
- g_FireBulletPlayerTeam = pInfo->GetTeamIndex();
-
- g_InFireBullets = true;
- bool bRet = DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
- g_InFireBullets = false;
-
- return bRet;
-}
-
-cell_t PhysboxToClientMap(IPluginContext *pContext, const cell_t *params)
-{
- if(params[2])
- pContext->LocalToPhysAddr(params[1], (cell_t **)&g_pPhysboxToClientMap);
- else
- g_pPhysboxToClientMap = NULL;
-
- return 0;
-}
-
-bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late)
-{
- srand((unsigned int)time(NULL));
-
- char conf_error[255] = "";
- if(!gameconfs->LoadGameConfigFile("CSSFixes", &g_pGameConf, conf_error, sizeof(conf_error)))
- {
- if(conf_error[0])
- snprintf(error, maxlength, "Could not read CSSFixes.txt: %s", conf_error);
-
- return false;
- }
-
- CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
-
- g_pDetour_InputTestActivator = DETOUR_CREATE_MEMBER(DETOUR_InputTestActivator, "CBaseFilter_InputTestActivator");
- if(g_pDetour_InputTestActivator == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CBaseFilter_InputTestActivator");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_PostConstructor = DETOUR_CREATE_MEMBER(DETOUR_PostConstructor, "CBaseEntity_PostConstructor");
- if(g_pDetour_PostConstructor == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CBaseEntity_PostConstructor");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_FindUseEntity = DETOUR_CREATE_MEMBER(DETOUR_FindUseEntity, "CBasePlayer_FindUseEntity");
- if(g_pDetour_FindUseEntity == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CBasePlayer_FindUseEntity");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_CTraceFilterSimple = DETOUR_CREATE_MEMBER(DETOUR_CTraceFilterSimple, "CTraceFilterSimple_CTraceFilterSimple");
- if(g_pDetour_CTraceFilterSimple == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CTraceFilterSimple_CTraceFilterSimple");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_KeyValue = DETOUR_CREATE_MEMBER(DETOUR_KeyValue, "CBaseEntity_KeyValue");
- if(g_pDetour_KeyValue == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CBaseEntity_KeyValue");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_FireBullets = DETOUR_CREATE_STATIC(DETOUR_FireBullets, "FX_FireBullets");
- if(g_pDetour_FireBullets == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for FX_FireBullets");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_SwingOrStab = DETOUR_CREATE_MEMBER(DETOUR_SwingOrStab, "CKnife_SwingOrStab");
- if(g_pDetour_SwingOrStab == NULL)
- {
- snprintf(error, maxlength, "Could not create detour for CKnife_SwingOrStab");
- SDK_OnUnload();
- return false;
- }
-
- g_pDetour_InputTestActivator->EnableDetour();
- g_pDetour_PostConstructor->EnableDetour();
- g_pDetour_FindUseEntity->EnableDetour();
- g_pDetour_CTraceFilterSimple->EnableDetour();
- g_pDetour_KeyValue->EnableDetour();
- g_pDetour_FireBullets->EnableDetour();
- g_pDetour_SwingOrStab->EnableDetour();
-
- // Find VTable for CTraceFilterSkipTwoEntities
- uintptr_t pCTraceFilterSkipTwoEntities;
- if(!g_pGameConf->GetMemSig("CTraceFilterSkipTwoEntities", (void **)(&pCTraceFilterSkipTwoEntities)) || !pCTraceFilterSkipTwoEntities)
- {
- snprintf(error, maxlength, "Failed to find CTraceFilterSkipTwoEntities.\n");
- SDK_OnUnload();
- return false;
- }
- // First function in VTable
- g_CTraceFilterSkipTwoEntities = (CTraceFilterSkipTwoEntities *)(pCTraceFilterSkipTwoEntities + 8);
-
- // Find VTable for CTraceFilterSimple
- uintptr_t pCTraceFilterSimple;
- if(!g_pGameConf->GetMemSig("CTraceFilterSimple", (void **)(&pCTraceFilterSimple)) || !pCTraceFilterSimple)
- {
- snprintf(error, maxlength, "Failed to find CTraceFilterSimple.\n");
- SDK_OnUnload();
- return false;
- }
- // First function in VTable
- g_CTraceFilterSimple = (CTraceFilterSimple *)(pCTraceFilterSimple + 8);
-
- // Find VTable for CTraceFilterNoNPCsOrPlayer
- uintptr_t pCTraceFilterNoNPCsOrPlayer;
- if(!g_pGameConf->GetMemSig("CTraceFilterNoNPCsOrPlayer", (void **)(&pCTraceFilterNoNPCsOrPlayer)) || !pCTraceFilterNoNPCsOrPlayer)
- {
- snprintf(error, maxlength, "Failed to find CTraceFilterNoNPCsOrPlayer.\n");
- SDK_OnUnload();
- return false;
- }
- // First function in VTable
- g_CTraceFilterNoNPCsOrPlayer = pCTraceFilterNoNPCsOrPlayer + 8;
-
- g_SH_SkipTwoEntitiesShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSkipTwoEntities, ShouldHitEntity, g_CTraceFilterSkipTwoEntities, SH_STATIC(ShouldHitEntity), true);
- g_SH_SimpleShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSimple, ShouldHitEntity, g_CTraceFilterSimple, SH_STATIC(ShouldHitEntity), true);
-
- void *pServerSo = dlopen("cstrike/bin/server_srv.so", RTLD_NOW);
- if(!pServerSo)
- {
- snprintf(error, maxlength, "Could not dlopen server_srv.so");
- SDK_OnUnload();
- return false;
- }
-
- void *pEngineSo = dlopen("bin/engine_srv.so", RTLD_NOW);
- if(!pEngineSo)
- {
- snprintf(error, maxlength, "Could not dlopen engine_srv.so");
- SDK_OnUnload();
- return false;
- }
-
- // Apply all patches
- for(size_t i = 0; i < sizeof(gs_Patches) / sizeof(*gs_Patches); i++)
- {
- struct SrcdsPatch *pPatch = &gs_Patches[i];
- int PatchLen = strlen(pPatch->pPatchPattern);
-
- void *pBinary = pPatch->engine ? pEngineSo : pServerSo;
- pPatch->pAddress = (uintptr_t)memutils->ResolveSymbol(pBinary, pPatch->pSignature);
- if(!pPatch->pAddress)
- {
- snprintf(error, maxlength, "Could not find symbol: %s", pPatch->pSignature);
- dlclose(pServerSo);
- dlclose(pEngineSo);
- SDK_OnUnload();
- return false;
- }
-
- pPatch->pPatchAddress = FindPattern(pPatch->pAddress, pPatch->pPatchSignature, pPatch->pPatchPattern, 1024);
- if(!pPatch->pPatchAddress)
- {
- snprintf(error, maxlength, "Could not find patch signature for symbol: %s", pPatch->pSignature);
- dlclose(pServerSo);
- dlclose(pEngineSo);
- SDK_OnUnload();
- return false;
- }
-
- pPatch->pOriginal = (unsigned char *)malloc(PatchLen * sizeof(unsigned char));
-
- SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
- for(int j = 0; j < PatchLen; j++)
- {
- pPatch->pOriginal[j] = *(unsigned char *)(pPatch->pPatchAddress + j);
- *(unsigned char *)(pPatch->pPatchAddress + j) = pPatch->pPatch[j];
- }
- SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC);
- }
-
- dlclose(pServerSo);
- dlclose(pEngineSo);
-
- return true;
-}
-
-const sp_nativeinfo_t MyNatives[] =
-{
- { "PhysboxToClientMap", PhysboxToClientMap },
- { NULL, NULL }
-};
-
-void CSSFixes::SDK_OnAllLoaded()
-{
- sharesys->AddNatives(myself, MyNatives);
- sharesys->RegisterLibrary(myself, "CSSFixes");
-}
-
-void CSSFixes::SDK_OnUnload()
-{
- if(g_pDetour_InputTestActivator != NULL)
- {
- g_pDetour_InputTestActivator->Destroy();
- g_pDetour_InputTestActivator = NULL;
- }
-
- if(g_pDetour_PostConstructor != NULL)
- {
- g_pDetour_PostConstructor->Destroy();
- g_pDetour_PostConstructor = NULL;
- }
-
- if(g_pDetour_FindUseEntity != NULL)
- {
- g_pDetour_FindUseEntity->Destroy();
- g_pDetour_FindUseEntity = NULL;
- }
-
- if(g_pDetour_CTraceFilterSimple != NULL)
- {
- g_pDetour_CTraceFilterSimple->Destroy();
- g_pDetour_CTraceFilterSimple = NULL;
- }
-
- if(g_pDetour_KeyValue != NULL)
- {
- g_pDetour_KeyValue->Destroy();
- g_pDetour_KeyValue = NULL;
- }
-
- if(g_pDetour_FireBullets != NULL)
- {
- g_pDetour_FireBullets->Destroy();
- g_pDetour_FireBullets = NULL;
- }
-
- if(g_pDetour_SwingOrStab != NULL)
- {
- g_pDetour_SwingOrStab->Destroy();
- g_pDetour_SwingOrStab = NULL;
- }
-
- if(g_SH_SkipTwoEntitiesShouldHitEntity)
- SH_REMOVE_HOOK_ID(g_SH_SkipTwoEntitiesShouldHitEntity);
-
- if(g_SH_SimpleShouldHitEntity)
- SH_REMOVE_HOOK_ID(g_SH_SimpleShouldHitEntity);
-
- gameconfs->CloseGameConfigFile(g_pGameConf);
-
- // Revert all applied patches
- for(size_t i = 0; i < sizeof(gs_Patches) / sizeof(*gs_Patches); i++)
- {
- struct SrcdsPatch *pPatch = &gs_Patches[i];
- int PatchLen = strlen(pPatch->pPatchPattern);
-
- if(!pPatch->pOriginal)
- continue;
-
- SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
- for(int j = 0; j < PatchLen; j++)
- {
- *(unsigned char *)(pPatch->pPatchAddress + j) = pPatch->pOriginal[j];
- }
- SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC);
-
- free(pPatch->pOriginal);
- pPatch->pOriginal = NULL;
- }
-}
-
-bool CSSFixes::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
-{
- return true;
-}
-
-uintptr_t FindPattern(uintptr_t BaseAddr, const unsigned char *pData, const char *pPattern, size_t MaxSize)
-{
- unsigned char *pMemory;
- uintptr_t PatternLen = strlen(pPattern);
-
- pMemory = reinterpret_cast(BaseAddr);
-
- for(uintptr_t i = 0; i < MaxSize; i++)
- {
- uintptr_t Matches = 0;
- while(*(pMemory + i + Matches) == pData[Matches] || pPattern[Matches] != 'x')
- {
- Matches++;
- if(Matches == PatternLen)
- return (uintptr_t)(pMemory + i);
- }
- }
-
- return 0x00;
-}
-
-uintptr_t FindFunctionCall(uintptr_t BaseAddr, uintptr_t Function, size_t MaxSize)
-{
- unsigned char *pMemory;
- pMemory = reinterpret_cast(BaseAddr);
-
- for(uintptr_t i = 0; i < MaxSize; i++)
- {
- if(pMemory[i] == 0xE8) // CALL
- {
- uintptr_t CallAddr = *(uintptr_t *)(pMemory + i + 1);
-
- CallAddr += (uintptr_t)(pMemory + i + 5);
-
- if(CallAddr == Function)
- return (uintptr_t)(pMemory + i);
-
- i += 4;
- }
- }
-
- return 0x00;
-}
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod Sample Extension
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include "extension.h"
+#include "CDetour/detours.h"
+#include "iplayerinfo.h"
+#include
+#include
+#include
+#include
+#include
+
+#define SetBit(A,I) ((A)[(I) >> 5] |= (1 << ((I) & 31)))
+#define ClearBit(A,I) ((A)[(I) >> 5] &= ~(1 << ((I) & 31)))
+#define CheckBit(A,I) !!((A)[(I) >> 5] & (1 << ((I) & 31)))
+
+bool UTIL_ContainsDataTable(SendTable *pTable, const char *name)
+{
+ const char *pname = pTable->GetName();
+ int props = pTable->GetNumProps();
+ SendProp *prop;
+ SendTable *table;
+
+ if (pname && strcmp(name, pname) == 0)
+ return true;
+
+ for (int i=0; iGetProp(i);
+
+ if ((table = prop->GetDataTable()) != NULL)
+ {
+ pname = table->GetName();
+ if (pname && strcmp(name, pname) == 0)
+ {
+ return true;
+ }
+
+ if (UTIL_ContainsDataTable(table, name))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+class CTraceFilterSimple : public CTraceFilter
+{
+public:
+ virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) = 0;
+ virtual void SetPassEntity( const IHandleEntity *pPassEntity ) = 0;
+ virtual void SetCollisionGroup( int iCollisionGroup ) = 0;
+};
+
+class CTraceFilterSkipTwoEntities : public CTraceFilterSimple
+{
+public:
+ virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) = 0;
+ virtual void SetPassEntity2( const IHandleEntity *pPassEntity2 ) = 0;
+};
+
+static struct SrcdsPatch
+{
+ const char *pSignature;
+ const unsigned char *pPatchSignature;
+ const char *pPatchPattern;
+ const unsigned char *pPatch;
+
+ unsigned char *pOriginal;
+ uintptr_t pAddress;
+ uintptr_t pPatchAddress;
+ bool engine;
+} gs_Patches[] = {
+ // 0: game_ui should not apply FL_ONTRAIN flag, else client prediction turns off
+ {
+ "_ZN7CGameUI5ThinkEv",
+ (unsigned char *)"\xC7\x44\x24\x04\x10\x00\x00\x00\x89\x34\x24\xE8\x00\x00\x00\x00",
+ "xxxxxxxxxxxx????",
+ (unsigned char *)"\xC7\x44\x24\x04\x10\x00\x00\x00\x89\x34\x24\x90\x90\x90\x90\x90",
+ 0, 0, 0, false
+ },
+ // 1: player_speedmod should not turn off flashlight
+ {
+ "_ZN17CMovementSpeedMod13InputSpeedModER11inputdata_t",
+ (unsigned char *)"\xFF\x90\x8C\x05\x00\x00\x85\xC0\x0F\x85\x75\x02\x00\x00",
+ "xxxxxxxxxxxxxx",
+ (unsigned char *)"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
+ 0, 0, 0, false
+ },
+ // 2: only select CT spawnpoints
+// {
+// "_ZN9CCSPlayer19EntSelectSpawnPointEv",
+// (unsigned char *)"\x89\x1C\x24\xE8\x00\x00\x00\x00\x83\xF8\x03\x74\x4B",
+// "xxxx????xxxxx",
+// (unsigned char *)"\x89\x1C\x24\x90\x90\x90\x90\x90\x90\x90\x90\xEB\x4B",
+// 0, 0, 0, false
+// },
+ // 3: don't check if we have T spawns
+// {
+// "_ZN12CCSGameRules18NeededPlayersCheckERb",
+// (unsigned char *)"\x74\x0E\x8B\x83\x80\x02\x00\x00\x85\xC0\x0F\x85\x9E\x00\x00\x00\xC7\x04\x24\xAC\xF7\x87\x00\xE8\xC2\x82\x91\x00",
+// "xxxxxxxxxxxxxxxx????????????",
+// (unsigned char *)"\x0F\x85\xA8\x00\x00\x00\x8B\x83\x80\x02\x00\x00\x85\xC0\x0F\x85\x9A\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90",
+// 0, 0, 0, false
+// },
+ // 5: disable alive check in point_viewcontrol->Disable
+ {
+ "_ZN14CTriggerCamera7DisableEv",
+ (unsigned char *)"\x8B\x10\x89\x04\x24\xFF\x92\x08\x01\x00\x00\x84\xC0\x0F\x84\x58\xFF\xFF\xFF",
+ "xxxxxxx??xxxxxx?xxx",
+ (unsigned char *)"\x8B\x10\x89\x04\x24\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
+ 0, 0, 0, false
+ },
+ // 6: disable player->m_takedamage = DAMAGE_NO in point_viewcontrol->Enable
+ {
+ "_ZN14CTriggerCamera6EnableEv",
+ (unsigned char *)"\x31\xFF\x80\xBF\xFD\x00\x00\x00\x00\x0F\x85\x96\x03\x00\x00",
+ "xxxx?xxxxxx??xx",
+ (unsigned char *)"\x31\xFF\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90",
+ 0, 0, 0, false
+ },
+ // 7: disable player->m_takedamage = m_nOldTakeDamage in point_viewcontrol->Disable
+ {
+ "_ZN14CTriggerCamera7DisableEv",
+ (unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x0F\x84\xAC\xFD\xFF\xFF",
+ "xxxx?xxxxxxxxx",
+ (unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x90\xE9\xAC\xFD\xFF\xFF",
+ 0, 0, 0, false
+ },
+ // 8: userinfo stringtable don't write fakeclient field
+ {
+ "_ZN11CBaseClient12FillUserInfoER13player_info_s",
+ (unsigned char *)"\xFF\x50\x70\x88\x46\x6C",
+ "xxxxxx",
+ (unsigned char *)"\x90\x90\x90\x90\x90\x90",
+ 0, 0, 0, true
+ }
+};
+
+class CBaseEntity;
+struct variant_hax
+{
+ const char *pszValue;
+};
+
+struct inputdata_t
+{
+ // The entity that initially caused this chain of output events.
+ CBaseEntity *pActivator;
+ // The entity that fired this particular output.
+ CBaseEntity *pCaller;
+ // The data parameter for this output.
+ variant_hax value;
+ // The unique ID of the output that was fired.
+ int nOutputID;
+};
+
+typedef bool (*ShouldHitFunc_t)( IHandleEntity *pHandleEntity, int contentsMask );
+
+uintptr_t FindPattern(uintptr_t BaseAddr, const unsigned char *pData, const char *pPattern, size_t MaxSize);
+uintptr_t FindFunctionCall(uintptr_t BaseAddr, uintptr_t Function, size_t MaxSize);
+
+/**
+ * @file extension.cpp
+ * @brief Implement extension code here.
+ */
+
+CSSFixes g_Interface;
+SMEXT_LINK(&g_Interface);
+
+IGameConfig *g_pGameConf = NULL;
+
+CDetour *g_pDetour_InputTestActivator = NULL;
+CDetour *g_pDetour_PostConstructor = NULL;
+CDetour *g_pDetour_FindUseEntity = NULL;
+CDetour *g_pDetour_CTraceFilterSimple = NULL;
+CDetour *g_pDetour_KeyValue = NULL;
+CDetour *g_pDetour_FireBullets = NULL;
+CDetour *g_pDetour_SwingOrStab = NULL;
+int g_SH_SkipTwoEntitiesShouldHitEntity = 0;
+int g_SH_SimpleShouldHitEntity = 0;
+
+uintptr_t g_CTraceFilterNoNPCsOrPlayer = 0;
+CTraceFilterSkipTwoEntities *g_CTraceFilterSkipTwoEntities = NULL;
+CTraceFilterSimple *g_CTraceFilterSimple = NULL;
+
+/* Fix crash in CBaseFilter::InputTestActivator */
+DETOUR_DECL_MEMBER1(DETOUR_InputTestActivator, void, inputdata_t *, inputdata)
+{
+ if(!inputdata || !inputdata->pActivator || !inputdata->pCaller)
+ return;
+
+ DETOUR_MEMBER_CALL(DETOUR_InputTestActivator)(inputdata);
+}
+
+DETOUR_DECL_MEMBER1(DETOUR_PostConstructor, void, const char *, szClassname)
+{
+ if(strncasecmp(szClassname, "info_player_", 12) == 0)
+ {
+ CBaseEntity *pEntity = (CBaseEntity *)this;
+
+ datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
+ typedescription_t *td = gamehelpers->FindInDataMap(pMap, "m_iEFlags");
+
+ // Spawnpoints don't need edicts...
+ *(uint32 *)((intptr_t)pEntity + td->fieldOffset[TD_OFFSET_NORMAL]) |= (1<<9); // EFL_SERVER_ONLY
+
+ // Only CT spawnpoints
+// if(strcasecmp(szClassname, "info_player_terrorist") == 0)
+// szClassname = "info_player_counterterrorist";
+ }
+
+ DETOUR_MEMBER_CALL(DETOUR_PostConstructor)(szClassname);
+}
+
+DETOUR_DECL_MEMBER2(DETOUR_KeyValue, bool, const char *, szKeyName, const char *, szValue)
+{
+ // Fix crash bug in engine
+ if(strcasecmp(szKeyName, "angle") == 0)
+ szKeyName = "angles";
+
+// else if(strcasecmp(szKeyName, "classname") == 0 &&
+// strcasecmp(szValue, "info_player_terrorist") == 0)
+// {
+ // Only CT spawnpoints
+// szValue = "info_player_counterterrorist";
+// }
+// else if(strcasecmp(szKeyName, "teamnum") == 0 || strcasecmp(szKeyName, "teamnum") == 0 )
+// {
+// CBaseEntity *pEntity = (CBaseEntity *)this;
+// const char *pClassname = gamehelpers->GetEntityClassname(pEntity);
+//
+ // All buyzones should be CT buyzones
+// if(pClassname && strcasecmp(pClassname, "func_buyzone") == 0)
+// szValue = "3";
+// }
+
+ return DETOUR_MEMBER_CALL(DETOUR_KeyValue)(szKeyName, szValue);
+}
+
+/* Ignore players in +USE trace */
+bool g_InFindUseEntity = false;
+DETOUR_DECL_MEMBER0(DETOUR_FindUseEntity, CBaseEntity *)
+{
+ // Signal CTraceFilterSimple that we are in FindUseEntity
+ g_InFindUseEntity = true;
+ CBaseEntity *pEntity = DETOUR_MEMBER_CALL(DETOUR_FindUseEntity)();
+ g_InFindUseEntity = false;
+ return pEntity;
+}
+DETOUR_DECL_MEMBER3(DETOUR_CTraceFilterSimple, void, const IHandleEntity *, passedict, int, collisionGroup, ShouldHitFunc_t, pExtraShouldHitFunc)
+{
+ DETOUR_MEMBER_CALL(DETOUR_CTraceFilterSimple)(passedict, collisionGroup, pExtraShouldHitFunc);
+
+ // If we're in FindUseEntity right now then switch out the VTable
+ if(g_InFindUseEntity)
+ *(uintptr_t *)this = g_CTraceFilterNoNPCsOrPlayer;
+}
+
+/* Make bullets ignore teammates */
+char *g_pPhysboxToClientMap = NULL;
+bool g_InFireBullets = false;
+int g_FireBulletPlayerTeam = 0;
+SH_DECL_HOOK2(CTraceFilterSkipTwoEntities, ShouldHitEntity, SH_NOATTRIB, 0, bool, IHandleEntity *, int);
+SH_DECL_HOOK2(CTraceFilterSimple, ShouldHitEntity, SH_NOATTRIB, 0, bool, IHandleEntity *, int);
+bool ShouldHitEntity(IHandleEntity *pHandleEntity, int contentsMask)
+{
+ if(!g_InFireBullets)
+ RETURN_META_VALUE(MRES_IGNORED, true);
+
+ if(META_RESULT_ORIG_RET(bool) == false)
+ RETURN_META_VALUE(MRES_IGNORED, false);
+
+ IServerUnknown *pUnk = (IServerUnknown *)pHandleEntity;
+ CBaseHandle hndl = pUnk->GetRefEHandle();
+ int index = hndl.GetEntryIndex();
+
+ int iTeam = 0;
+
+ if(index > SM_MAXPLAYERS && g_pPhysboxToClientMap && index < 2048)
+ {
+ index = g_pPhysboxToClientMap[index];
+ }
+
+ if(index >= -3 && index <= -1)
+ {
+ iTeam = -index;
+ }
+ else if(index < 1 || index > SM_MAXPLAYERS)
+ {
+ RETURN_META_VALUE(MRES_IGNORED, true);
+ }
+
+ if(!iTeam)
+ {
+ IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index);
+ if(!pPlayer || !pPlayer->GetEdict())
+ RETURN_META_VALUE(MRES_IGNORED, true);
+
+ IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
+ if(!pInfo)
+ RETURN_META_VALUE(MRES_IGNORED, true);
+
+ iTeam = pInfo->GetTeamIndex();
+ }
+
+ if(iTeam == g_FireBulletPlayerTeam)
+ RETURN_META_VALUE(MRES_SUPERCEDE, false);
+
+ RETURN_META_VALUE(MRES_IGNORED, true);
+}
+
+DETOUR_DECL_STATIC9(DETOUR_FireBullets, void, int, iPlayerIndex, const Vector *, vOrigin, const QAngle *, vAngles, int, iWeaponID, int, iMode, int, iSeed, float, flSpread, float, _f1, float, _f2)
+{
+ if(iPlayerIndex <= 0 || iPlayerIndex > playerhelpers->GetMaxClients())
+ return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
+
+ IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(iPlayerIndex);
+ if(!pPlayer || !pPlayer->GetEdict())
+ return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
+
+ IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
+ if(!pInfo)
+ return DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
+
+ g_FireBulletPlayerTeam = pInfo->GetTeamIndex();
+
+ g_InFireBullets = true;
+ DETOUR_STATIC_CALL(DETOUR_FireBullets)(iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread, _f1, _f2);
+ g_InFireBullets = false;
+}
+
+DETOUR_DECL_MEMBER1(DETOUR_SwingOrStab, bool, bool, bStab)
+{
+ static int offset = 0;
+ if(!offset)
+ {
+ IServerUnknown *pUnk = (IServerUnknown *)this;
+ IServerNetworkable *pNet = pUnk->GetNetworkable();
+
+ if (!UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, "DT_BaseCombatWeapon"))
+ return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+
+ sm_sendprop_info_t spi;
+ if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))
+ return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+
+ offset = spi.actual_offset;
+ }
+
+ CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)this + offset);
+
+ edict_t *pEdict = gamehelpers->GetHandleEntity(hndl);
+ if(!pEdict)
+ return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+
+ IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(pEdict);
+ if(!pPlayer || !pPlayer->GetEdict())
+ return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+
+ IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
+ if(!pInfo)
+ return DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+
+ g_FireBulletPlayerTeam = pInfo->GetTeamIndex();
+
+ g_InFireBullets = true;
+ bool bRet = DETOUR_MEMBER_CALL(DETOUR_SwingOrStab)(bStab);
+ g_InFireBullets = false;
+
+ return bRet;
+}
+
+cell_t PhysboxToClientMap(IPluginContext *pContext, const cell_t *params)
+{
+ if(params[2])
+ pContext->LocalToPhysAddr(params[1], (cell_t **)&g_pPhysboxToClientMap);
+ else
+ g_pPhysboxToClientMap = NULL;
+
+ return 0;
+}
+
+bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late)
+{
+ srand((unsigned int)time(NULL));
+
+ char conf_error[255] = "";
+ if(!gameconfs->LoadGameConfigFile("CSSFixes", &g_pGameConf, conf_error, sizeof(conf_error)))
+ {
+ if(conf_error[0])
+ snprintf(error, maxlength, "Could not read CSSFixes.txt: %s", conf_error);
+
+ return false;
+ }
+
+ CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
+
+ g_pDetour_InputTestActivator = DETOUR_CREATE_MEMBER(DETOUR_InputTestActivator, "CBaseFilter_InputTestActivator");
+ if(g_pDetour_InputTestActivator == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CBaseFilter_InputTestActivator");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_PostConstructor = DETOUR_CREATE_MEMBER(DETOUR_PostConstructor, "CBaseEntity_PostConstructor");
+ if(g_pDetour_PostConstructor == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CBaseEntity_PostConstructor");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_FindUseEntity = DETOUR_CREATE_MEMBER(DETOUR_FindUseEntity, "CBasePlayer_FindUseEntity");
+ if(g_pDetour_FindUseEntity == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CBasePlayer_FindUseEntity");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_CTraceFilterSimple = DETOUR_CREATE_MEMBER(DETOUR_CTraceFilterSimple, "CTraceFilterSimple_CTraceFilterSimple");
+ if(g_pDetour_CTraceFilterSimple == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CTraceFilterSimple_CTraceFilterSimple");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_KeyValue = DETOUR_CREATE_MEMBER(DETOUR_KeyValue, "CBaseEntity_KeyValue");
+ if(g_pDetour_KeyValue == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CBaseEntity_KeyValue");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_FireBullets = DETOUR_CREATE_STATIC(DETOUR_FireBullets, "FX_FireBullets");
+ if(g_pDetour_FireBullets == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for FX_FireBullets");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_SwingOrStab = DETOUR_CREATE_MEMBER(DETOUR_SwingOrStab, "CKnife_SwingOrStab");
+ if(g_pDetour_SwingOrStab == NULL)
+ {
+ snprintf(error, maxlength, "Could not create detour for CKnife_SwingOrStab");
+ SDK_OnUnload();
+ return false;
+ }
+
+ g_pDetour_InputTestActivator->EnableDetour();
+ g_pDetour_PostConstructor->EnableDetour();
+ g_pDetour_FindUseEntity->EnableDetour();
+ g_pDetour_CTraceFilterSimple->EnableDetour();
+ g_pDetour_KeyValue->EnableDetour();
+ g_pDetour_FireBullets->EnableDetour();
+ g_pDetour_SwingOrStab->EnableDetour();
+
+ // Find VTable for CTraceFilterSkipTwoEntities
+ uintptr_t pCTraceFilterSkipTwoEntities;
+ if(!g_pGameConf->GetMemSig("CTraceFilterSkipTwoEntities", (void **)(&pCTraceFilterSkipTwoEntities)) || !pCTraceFilterSkipTwoEntities)
+ {
+ snprintf(error, maxlength, "Failed to find CTraceFilterSkipTwoEntities.\n");
+ SDK_OnUnload();
+ return false;
+ }
+ // First function in VTable
+ g_CTraceFilterSkipTwoEntities = (CTraceFilterSkipTwoEntities *)(pCTraceFilterSkipTwoEntities + 8);
+
+ // Find VTable for CTraceFilterSimple
+ uintptr_t pCTraceFilterSimple;
+ if(!g_pGameConf->GetMemSig("CTraceFilterSimple", (void **)(&pCTraceFilterSimple)) || !pCTraceFilterSimple)
+ {
+ snprintf(error, maxlength, "Failed to find CTraceFilterSimple.\n");
+ SDK_OnUnload();
+ return false;
+ }
+ // First function in VTable
+ g_CTraceFilterSimple = (CTraceFilterSimple *)(pCTraceFilterSimple + 8);
+
+ // Find VTable for CTraceFilterNoNPCsOrPlayer
+ uintptr_t pCTraceFilterNoNPCsOrPlayer;
+ if(!g_pGameConf->GetMemSig("CTraceFilterNoNPCsOrPlayer", (void **)(&pCTraceFilterNoNPCsOrPlayer)) || !pCTraceFilterNoNPCsOrPlayer)
+ {
+ snprintf(error, maxlength, "Failed to find CTraceFilterNoNPCsOrPlayer.\n");
+ SDK_OnUnload();
+ return false;
+ }
+ // First function in VTable
+ g_CTraceFilterNoNPCsOrPlayer = pCTraceFilterNoNPCsOrPlayer + 8;
+
+ g_SH_SkipTwoEntitiesShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSkipTwoEntities, ShouldHitEntity, g_CTraceFilterSkipTwoEntities, SH_STATIC(ShouldHitEntity), true);
+ g_SH_SimpleShouldHitEntity = SH_ADD_DVPHOOK(CTraceFilterSimple, ShouldHitEntity, g_CTraceFilterSimple, SH_STATIC(ShouldHitEntity), true);
+
+ void *pServerSo = dlopen("cstrike/bin/server_srv.so", RTLD_NOW);
+ if(!pServerSo)
+ {
+ snprintf(error, maxlength, "Could not dlopen server_srv.so");
+ SDK_OnUnload();
+ return false;
+ }
+
+ void *pEngineSo = dlopen("bin/engine_srv.so", RTLD_NOW);
+ if(!pEngineSo)
+ {
+ snprintf(error, maxlength, "Could not dlopen engine_srv.so");
+ SDK_OnUnload();
+ return false;
+ }
+
+ // Apply all patches
+ for(size_t i = 0; i < sizeof(gs_Patches) / sizeof(*gs_Patches); i++)
+ {
+ struct SrcdsPatch *pPatch = &gs_Patches[i];
+ int PatchLen = strlen(pPatch->pPatchPattern);
+
+ void *pBinary = pPatch->engine ? pEngineSo : pServerSo;
+ pPatch->pAddress = (uintptr_t)memutils->ResolveSymbol(pBinary, pPatch->pSignature);
+ if(!pPatch->pAddress)
+ {
+ snprintf(error, maxlength, "Could not find symbol: %s", pPatch->pSignature);
+ dlclose(pServerSo);
+ dlclose(pEngineSo);
+ SDK_OnUnload();
+ return false;
+ }
+
+ pPatch->pPatchAddress = FindPattern(pPatch->pAddress, pPatch->pPatchSignature, pPatch->pPatchPattern, 1024);
+ if(!pPatch->pPatchAddress)
+ {
+ snprintf(error, maxlength, "Could not find patch signature for symbol: %s", pPatch->pSignature);
+ dlclose(pServerSo);
+ dlclose(pEngineSo);
+ SDK_OnUnload();
+ return false;
+ }
+
+ pPatch->pOriginal = (unsigned char *)malloc(PatchLen * sizeof(unsigned char));
+
+ SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
+ for(int j = 0; j < PatchLen; j++)
+ {
+ pPatch->pOriginal[j] = *(unsigned char *)(pPatch->pPatchAddress + j);
+ *(unsigned char *)(pPatch->pPatchAddress + j) = pPatch->pPatch[j];
+ }
+ SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC);
+ }
+
+ dlclose(pServerSo);
+ dlclose(pEngineSo);
+
+ return true;
+}
+
+const sp_nativeinfo_t MyNatives[] =
+{
+ { "PhysboxToClientMap", PhysboxToClientMap },
+ { NULL, NULL }
+};
+
+void CSSFixes::SDK_OnAllLoaded()
+{
+ sharesys->AddNatives(myself, MyNatives);
+ sharesys->RegisterLibrary(myself, "CSSFixes");
+}
+
+void CSSFixes::SDK_OnUnload()
+{
+ if(g_pDetour_InputTestActivator != NULL)
+ {
+ g_pDetour_InputTestActivator->Destroy();
+ g_pDetour_InputTestActivator = NULL;
+ }
+
+ if(g_pDetour_PostConstructor != NULL)
+ {
+ g_pDetour_PostConstructor->Destroy();
+ g_pDetour_PostConstructor = NULL;
+ }
+
+ if(g_pDetour_FindUseEntity != NULL)
+ {
+ g_pDetour_FindUseEntity->Destroy();
+ g_pDetour_FindUseEntity = NULL;
+ }
+
+ if(g_pDetour_CTraceFilterSimple != NULL)
+ {
+ g_pDetour_CTraceFilterSimple->Destroy();
+ g_pDetour_CTraceFilterSimple = NULL;
+ }
+
+ if(g_pDetour_KeyValue != NULL)
+ {
+ g_pDetour_KeyValue->Destroy();
+ g_pDetour_KeyValue = NULL;
+ }
+
+ if(g_pDetour_FireBullets != NULL)
+ {
+ g_pDetour_FireBullets->Destroy();
+ g_pDetour_FireBullets = NULL;
+ }
+
+ if(g_pDetour_SwingOrStab != NULL)
+ {
+ g_pDetour_SwingOrStab->Destroy();
+ g_pDetour_SwingOrStab = NULL;
+ }
+
+ if(g_SH_SkipTwoEntitiesShouldHitEntity)
+ SH_REMOVE_HOOK_ID(g_SH_SkipTwoEntitiesShouldHitEntity);
+
+ if(g_SH_SimpleShouldHitEntity)
+ SH_REMOVE_HOOK_ID(g_SH_SimpleShouldHitEntity);
+
+ gameconfs->CloseGameConfigFile(g_pGameConf);
+
+ // Revert all applied patches
+ for(size_t i = 0; i < sizeof(gs_Patches) / sizeof(*gs_Patches); i++)
+ {
+ struct SrcdsPatch *pPatch = &gs_Patches[i];
+ int PatchLen = strlen(pPatch->pPatchPattern);
+
+ if(!pPatch->pOriginal)
+ continue;
+
+ SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
+ for(int j = 0; j < PatchLen; j++)
+ {
+ *(unsigned char *)(pPatch->pPatchAddress + j) = pPatch->pOriginal[j];
+ }
+ SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC);
+
+ free(pPatch->pOriginal);
+ pPatch->pOriginal = NULL;
+ }
+}
+
+bool CSSFixes::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
+{
+ return true;
+}
+
+uintptr_t FindPattern(uintptr_t BaseAddr, const unsigned char *pData, const char *pPattern, size_t MaxSize)
+{
+ unsigned char *pMemory;
+ uintptr_t PatternLen = strlen(pPattern);
+
+ pMemory = reinterpret_cast(BaseAddr);
+
+ for(uintptr_t i = 0; i < MaxSize; i++)
+ {
+ uintptr_t Matches = 0;
+ while(*(pMemory + i + Matches) == pData[Matches] || pPattern[Matches] != 'x')
+ {
+ Matches++;
+ if(Matches == PatternLen)
+ return (uintptr_t)(pMemory + i);
+ }
+ }
+
+ return 0x00;
+}
+
+uintptr_t FindFunctionCall(uintptr_t BaseAddr, uintptr_t Function, size_t MaxSize)
+{
+ unsigned char *pMemory;
+ pMemory = reinterpret_cast(BaseAddr);
+
+ for(uintptr_t i = 0; i < MaxSize; i++)
+ {
+ if(pMemory[i] == 0xE8) // CALL
+ {
+ uintptr_t CallAddr = *(uintptr_t *)(pMemory + i + 1);
+
+ CallAddr += (uintptr_t)(pMemory + i + 5);
+
+ if(CallAddr == Function)
+ return (uintptr_t)(pMemory + i);
+
+ i += 4;
+ }
+ }
+
+ return 0x00;
+}