|  |  |  | @@ -37,6 +37,8 @@ | 
		
	
		
			
				|  |  |  |  | #include <IEngineTrace.h> | 
		
	
		
			
				|  |  |  |  | #include <server_class.h> | 
		
	
		
			
				|  |  |  |  | #include <ispatialpartition.h> | 
		
	
		
			
				|  |  |  |  | #include <utlvector.h> | 
		
	
		
			
				|  |  |  |  | #include <string_t.h> | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | #define SetBit(A,I)		((A)[(I) >> 5] |= (1 << ((I) & 31))) | 
		
	
		
			
				|  |  |  |  | #define ClearBit(A,I)	((A)[(I) >> 5] &= ~(1 << ((I) & 31))) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -74,6 +76,38 @@ bool UTIL_ContainsDataTable(SendTable *pTable, const char *name) | 
		
	
		
			
				|  |  |  |  | 	return false; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void UTIL_StringToVector( float *pVector, const char *pString ) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	char *pstr, *pfront, tempString[128]; | 
		
	
		
			
				|  |  |  |  | 	int	j; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	Q_strncpy( tempString, pString, sizeof(tempString) ); | 
		
	
		
			
				|  |  |  |  | 	pstr = pfront = tempString; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	for ( j = 0; j < 3; j++ )			// lifted from pr_edict.c | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		pVector[j] = atof( pfront ); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// skip any leading whitespace | 
		
	
		
			
				|  |  |  |  | 		while ( *pstr && *pstr <= ' ' ) | 
		
	
		
			
				|  |  |  |  | 			pstr++; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// skip to next whitespace | 
		
	
		
			
				|  |  |  |  | 		while ( *pstr && *pstr > ' ' ) | 
		
	
		
			
				|  |  |  |  | 			pstr++; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!*pstr) | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pstr++; | 
		
	
		
			
				|  |  |  |  | 		pfront = pstr; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	for ( j++; j < 3; j++ ) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		pVector[j] = 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | class CTraceFilterSimple : public CTraceFilter | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | public: | 
		
	
	
		
			
				
					
					|  |  |  | @@ -91,15 +125,26 @@ public: | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static struct SrcdsPatch | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	const char *pSignature; | 
		
	
		
			
				|  |  |  |  | 	const unsigned char *pPatchSignature; | 
		
	
		
			
				|  |  |  |  | 	const char *pPatchPattern; | 
		
	
		
			
				|  |  |  |  | 	const unsigned char *pPatch; | 
		
	
		
			
				|  |  |  |  | 	const char *pSignature; // function symbol | 
		
	
		
			
				|  |  |  |  | 	const unsigned char *pPatchSignature; // original opcode signature | function symbol for functionCall = true | 
		
	
		
			
				|  |  |  |  | 	const char *pPatchPattern; // pattern = x/?, ? = ignore signature | 
		
	
		
			
				|  |  |  |  | 	const unsigned char *pPatch; // replace with bytes | 
		
	
		
			
				|  |  |  |  | 	const char *pLibrary; // library of function symbol pSignature | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	unsigned char *pOriginal; | 
		
	
		
			
				|  |  |  |  | 	uintptr_t pAddress; | 
		
	
		
			
				|  |  |  |  | 	uintptr_t pPatchAddress; | 
		
	
		
			
				|  |  |  |  | 	bool engine; | 
		
	
		
			
				|  |  |  |  | 	int range = 0x400; // search range: scan up to this many bytes for the signature | 
		
	
		
			
				|  |  |  |  | 	int occurrences = 1; // maximum(!) number of occurences to patch | 
		
	
		
			
				|  |  |  |  | 	bool functionCall = false; // true = FindFunctionCall (pPatchSignature = function symbol) | false = FindPattern | 
		
	
		
			
				|  |  |  |  | 	const char *pFunctionLibrary = ""; // library of function symbol pPatchSignature for functionCall = true | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	struct Restore | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		unsigned char *pOriginal = NULL; | 
		
	
		
			
				|  |  |  |  | 		uintptr_t pPatchAddress = 0; | 
		
	
		
			
				|  |  |  |  | 		struct Restore *pNext = NULL; | 
		
	
		
			
				|  |  |  |  | 	} *pRestore = NULL; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uintptr_t pAddress = 0; | 
		
	
		
			
				|  |  |  |  | 	uintptr_t pSignatureAddress = 0; | 
		
	
		
			
				|  |  |  |  | } gs_Patches[] = { | 
		
	
		
			
				|  |  |  |  | 	// 0: game_ui should not apply FL_ONTRAIN flag, else client prediction turns off | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -107,55 +152,56 @@ static struct SrcdsPatch | 
		
	
		
			
				|  |  |  |  | 		(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 | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\xFF\x90\x8C\x05\x00\x00\x85\xC0\x0F\x85\x85\x02\x00\x00", | 
		
	
		
			
				|  |  |  |  | 		"xxxxxxxxxxxxxx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90", | 
		
	
		
			
				|  |  |  |  | 		0, 0, 0, false | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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 | 
		
	
		
			
				|  |  |  |  | //	}, | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		"_ZN9CCSPlayer19EntSelectSpawnPointEv", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x89\x1C\x24\xE8\x00\x00\x00\x00\x83\xF8\x03\x74\x6B", | 
		
	
		
			
				|  |  |  |  | 		"xxxx????xxxxx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x89\x1C\x24\x90\x90\x90\x90\x90\x90\x90\x90\xEB\x6B", | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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 | 
		
	
		
			
				|  |  |  |  | //	}, | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		"_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", | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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 | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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 | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\xC6\x86\x00\x00\x00\x00\x00\x8B\x83\x00\x00\x00\x00\xA8\x20", | 
		
	
		
			
				|  |  |  |  | 		"xx?????xx????xx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x90\x90\x90\x90\x90\x90\x90\x8B\x83\x00\x00\x00\x00\xA8\x20", | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so", | 
		
	
		
			
				|  |  |  |  | 		0x600 | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 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", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x0F\x84\xCA\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 | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x89\xF9\x38\x8E\xFD\x00\x00\x00\x90\xE9\xCA\xFD\xFF\xFF", | 
		
	
		
			
				|  |  |  |  | 		"cstrike/bin/server_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 8: userinfo stringtable don't write fakeclient field | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -163,8 +209,28 @@ static struct SrcdsPatch | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\xFF\x50\x70\x88\x46\x6C", | 
		
	
		
			
				|  |  |  |  | 		"xxxxxx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x90\x90\x90\x90\x90\x90", | 
		
	
		
			
				|  |  |  |  | 		0, 0, 0, true | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 		"bin/engine_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 9: fix server lagging resulting from too many ConMsgs due to packet spam | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		"_ZN8CNetChan19ProcessPacketHeaderEP11netpacket_s", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"_Z6ConMsgPKcz", | 
		
	
		
			
				|  |  |  |  | 		"xxxxx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x90\x90\x90\x90\x90", | 
		
	
		
			
				|  |  |  |  | 		"bin/engine_srv.so", | 
		
	
		
			
				|  |  |  |  | 		0x7d1, 100, | 
		
	
		
			
				|  |  |  |  | 		true, "bin/libtier0_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | 	// 10: fix server lagging resulting from too many ConMsgs due to packet spam | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		"_Z11NET_GetLongiP11netpacket_s", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"Msg", | 
		
	
		
			
				|  |  |  |  | 		"xxxxx", | 
		
	
		
			
				|  |  |  |  | 		(unsigned char *)"\x90\x90\x90\x90\x90", | 
		
	
		
			
				|  |  |  |  | 		"bin/engine_srv.so", | 
		
	
		
			
				|  |  |  |  | 		0x800, 100, | 
		
	
		
			
				|  |  |  |  | 		true, "bin/libtier0_srv.so" | 
		
	
		
			
				|  |  |  |  | 	}, | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | class CBaseEntity; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -173,6 +239,13 @@ struct variant_hax | 
		
	
		
			
				|  |  |  |  | 	const char *pszValue; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | struct ResponseContext_t | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	string_t m_iszName; | 
		
	
		
			
				|  |  |  |  | 	string_t m_iszValue; | 
		
	
		
			
				|  |  |  |  | 	float m_fExpirationTime; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | struct inputdata_t | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	// The entity that initially caused this chain of output events. | 
		
	
	
		
			
				
					
					|  |  |  | @@ -202,6 +275,8 @@ IGameConfig *g_pGameConf = NULL; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_InputTestActivator = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_PostConstructor = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_CreateEntityByName = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_PassesFilterImpl = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_FindUseEntity = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_CTraceFilterSimple = NULL; | 
		
	
		
			
				|  |  |  |  | CDetour *g_pDetour_KeyValue = NULL; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -210,6 +285,8 @@ CDetour *g_pDetour_SwingOrStab = NULL; | 
		
	
		
			
				|  |  |  |  | int g_SH_SkipTwoEntitiesShouldHitEntity = 0; | 
		
	
		
			
				|  |  |  |  | int g_SH_SimpleShouldHitEntity = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | int g_iMaxPlayers = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | uintptr_t g_CTraceFilterNoNPCsOrPlayer = 0; | 
		
	
		
			
				|  |  |  |  | CTraceFilterSkipTwoEntities *g_CTraceFilterSkipTwoEntities = NULL; | 
		
	
		
			
				|  |  |  |  | CTraceFilterSimple *g_CTraceFilterSimple = NULL; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -223,47 +300,155 @@ DETOUR_DECL_MEMBER1(DETOUR_InputTestActivator, void, inputdata_t *, inputdata) | 
		
	
		
			
				|  |  |  |  | 	DETOUR_MEMBER_CALL(DETOUR_InputTestActivator)(inputdata); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | DETOUR_DECL_MEMBER1(DETOUR_PostConstructor, void, const char *, szClassname) | 
		
	
		
			
				|  |  |  |  | const char *pszNonEdicts[] = | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if(strncasecmp(szClassname, "info_player_", 12) == 0) | 
		
	
		
			
				|  |  |  |  | 	"ambient_generic", | 
		
	
		
			
				|  |  |  |  | 	"game_score", | 
		
	
		
			
				|  |  |  |  | 	"game_text", | 
		
	
		
			
				|  |  |  |  | 	"game_ui", | 
		
	
		
			
				|  |  |  |  | 	"logic_auto",	// bruh | 
		
	
		
			
				|  |  |  |  | 	"phys_thruster", | 
		
	
		
			
				|  |  |  |  | 	"phys_keepupright", | 
		
	
		
			
				|  |  |  |  | 	"player_speedmod", | 
		
	
		
			
				|  |  |  |  | 	"player_weaponstrip", | 
		
	
		
			
				|  |  |  |  | 	"point_clientcommand", | 
		
	
		
			
				|  |  |  |  | 	"point_servercommand", | 
		
	
		
			
				|  |  |  |  | 	"point_teleport", | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | DETOUR_DECL_MEMBER1(DETOUR_PostConstructor, void, const char *, szClassname) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	CBaseEntity *pEntity = (CBaseEntity *)this; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		datamap_t *pMap = gamehelpers->GetDataMap(pEntity); | 
		
	
		
			
				|  |  |  |  | 		typedescription_t *td = gamehelpers->FindInDataMap(pMap, "m_iEFlags"); | 
		
	
		
			
				|  |  |  |  | 	static datamap_t *pMap = gamehelpers->GetDataMap(pEntity); | 
		
	
		
			
				|  |  |  |  | 	static typedescription_t *td = gamehelpers->FindInDataMap(pMap, "m_iEFlags"); | 
		
	
		
			
				|  |  |  |  | 	static uint32 offset = td->fieldOffset[TD_OFFSET_NORMAL]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if(strncasecmp(szClassname, "info_player_", 12) == 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		// Spawnpoints don't need edicts... | 
		
	
		
			
				|  |  |  |  | 		*(uint32 *)((intptr_t)pEntity + td->fieldOffset[TD_OFFSET_NORMAL]) |= (1<<9); // EFL_SERVER_ONLY | 
		
	
		
			
				|  |  |  |  | 		*(uint32 *)((intptr_t)pEntity + offset) |= (1<<9); // EFL_SERVER_ONLY | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// Only CT spawnpoints | 
		
	
		
			
				|  |  |  |  | //		if(strcasecmp(szClassname, "info_player_terrorist") == 0) | 
		
	
		
			
				|  |  |  |  | //			szClassname = "info_player_counterterrorist"; | 
		
	
		
			
				|  |  |  |  | 		if(strcasecmp(szClassname, "info_player_terrorist") == 0) | 
		
	
		
			
				|  |  |  |  | 			szClassname = "info_player_counterterrorist"; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		DETOUR_MEMBER_CALL(DETOUR_PostConstructor)(szClassname); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// Remove edicts for a bunch of entities that REALLY don't need them | 
		
	
		
			
				|  |  |  |  | 	for (int i = 0; i < sizeof(pszNonEdicts)/sizeof(*pszNonEdicts); i++) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (!strcasecmp(szClassname, pszNonEdicts[i])) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			*(uint32 *)((intptr_t)pEntity + offset) |= (1<<9); // EFL_SERVER_ONLY | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	DETOUR_MEMBER_CALL(DETOUR_PostConstructor)(szClassname); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Implementation for custom filter entities | 
		
	
		
			
				|  |  |  |  | DETOUR_DECL_MEMBER2(DETOUR_PassesFilterImpl, bool, CBaseEntity*, pCaller, CBaseEntity*, pEntity) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	CBaseEntity* pThisEnt = (CBaseEntity*)this; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// filter_activator_context: filters activators based on whether they have a given context with a nonzero value | 
		
	
		
			
				|  |  |  |  | 	// https://developer.valvesoftware.com/wiki/Filter_activator_context | 
		
	
		
			
				|  |  |  |  | 	// Implemented here because CUtlVectors are not supported in sourcepawn | 
		
	
		
			
				|  |  |  |  | 	if (!strcasecmp(gamehelpers->GetEntityClassname(pThisEnt), "filter_activator_context")) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		static int m_ResponseContexts_offset = 0, m_iszResponseContext_offset = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!m_ResponseContexts_offset && !m_iszResponseContext_offset) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			datamap_t *pDataMap = gamehelpers->GetDataMap(pEntity); | 
		
	
		
			
				|  |  |  |  | 			sm_datatable_info_t info; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			// Both are CBaseEntity members, so the offsets will always be the same across different entity classes | 
		
	
		
			
				|  |  |  |  | 			gamehelpers->FindDataMapInfo(pDataMap, "m_ResponseContexts", &info); | 
		
	
		
			
				|  |  |  |  | 			m_ResponseContexts_offset = info.actual_offset; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			gamehelpers->FindDataMapInfo(pDataMap, "m_iszResponseContext", &info); | 
		
	
		
			
				|  |  |  |  | 			m_iszResponseContext_offset = info.actual_offset; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		CUtlVector<ResponseContext_t> vecResponseContexts; | 
		
	
		
			
				|  |  |  |  | 		vecResponseContexts = *(CUtlVector<ResponseContext_t>*)((uint8_t*)pEntity + m_ResponseContexts_offset); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		const char *szFilterContext = (*(string_t*)((uint8_t*)pThisEnt + m_iszResponseContext_offset)).ToCStr(); | 
		
	
		
			
				|  |  |  |  | 		const char *szContext; | 
		
	
		
			
				|  |  |  |  | 		int iContextValue; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		for (int i = 0; i < vecResponseContexts.Count(); i++) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			szContext = vecResponseContexts[i].m_iszName.ToCStr(); | 
		
	
		
			
				|  |  |  |  | 			iContextValue = atoi(vecResponseContexts[i].m_iszValue.ToCStr()); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (!strcasecmp(szFilterContext, szContext) && iContextValue > 0) | 
		
	
		
			
				|  |  |  |  | 				return true; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// CBaseFilter::PassesFilterImpl just returns true so no need to call it | 
		
	
		
			
				|  |  |  |  | 	return true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Switch new entity classnames to ones that can be instantiated while keeping the classname keyvalue intact so it can be used later | 
		
	
		
			
				|  |  |  |  | DETOUR_DECL_STATIC2(DETOUR_CreateEntityByName, CBaseEntity*, const char*, className, int, iForceEdictIndex) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	// Nice of valve to expose CBaseFilter as filter_base :) | 
		
	
		
			
				|  |  |  |  | 	if (strcasecmp(className, "filter_activator_context") == 0) | 
		
	
		
			
				|  |  |  |  | 		className = "filter_base"; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return DETOUR_STATIC_CALL(DETOUR_CreateEntityByName)(className, iForceEdictIndex); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | DETOUR_DECL_MEMBER2(DETOUR_KeyValue, bool, const char *, szKeyName, const char *, szValue) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  |     CBaseEntity *pEntity = (CBaseEntity *)this; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// Fix crash bug in engine | 
		
	
		
			
				|  |  |  |  | 	if(strcasecmp(szKeyName, "angle") == 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		szKeyName = "angles"; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | //	else if(strcasecmp(szKeyName, "classname") == 0 && | 
		
	
		
			
				|  |  |  |  | //		strcasecmp(szValue, "info_player_terrorist") == 0) | 
		
	
		
			
				|  |  |  |  | //	{ | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	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); | 
		
	
		
			
				|  |  |  |  | // | 
		
	
		
			
				|  |  |  |  | 		szValue = "info_player_counterterrorist"; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else if(strcasecmp(szKeyName, "teamnum") == 0 || strcasecmp(szKeyName, "teamnum") == 0 ) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		const char *pClassname = gamehelpers->GetEntityClassname(pEntity); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		// All buyzones should be CT buyzones | 
		
	
		
			
				|  |  |  |  | //		if(pClassname && strcasecmp(pClassname, "func_buyzone") == 0) | 
		
	
		
			
				|  |  |  |  | //			szValue = "3"; | 
		
	
		
			
				|  |  |  |  | //	} | 
		
	
		
			
				|  |  |  |  | 		if(pClassname && strcasecmp(pClassname, "func_buyzone") == 0) | 
		
	
		
			
				|  |  |  |  | 			szValue = "3"; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |     else if(strcasecmp(szKeyName, "absvelocity") == 0) | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |         static int m_AbsVelocity_offset = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!m_AbsVelocity_offset) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			datamap_t *pDataMap = gamehelpers->GetDataMap(pEntity); | 
		
	
		
			
				|  |  |  |  | 			sm_datatable_info_t info; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			gamehelpers->FindDataMapInfo(pDataMap, "m_vecAbsVelocity", &info); | 
		
	
		
			
				|  |  |  |  | 			m_AbsVelocity_offset = info.actual_offset; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		float tmp[3]; | 
		
	
		
			
				|  |  |  |  | 		UTIL_StringToVector(tmp, szValue); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		Vector *vecAbsVelocity = (Vector*)((uint8_t*)pEntity + m_AbsVelocity_offset); | 
		
	
		
			
				|  |  |  |  | 		vecAbsVelocity->Init(tmp[0], tmp[1], tmp[2]); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return DETOUR_MEMBER_CALL(DETOUR_KeyValue)(szKeyName, szValue); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -307,7 +492,7 @@ bool ShouldHitEntity(IHandleEntity *pHandleEntity, int contentsMask) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	int iTeam = 0; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if(index > SM_MAXPLAYERS && g_pPhysboxToClientMap && index < 2048) | 
		
	
		
			
				|  |  |  |  | 	if(index > g_iMaxPlayers && g_pPhysboxToClientMap && index < 2048) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		index = g_pPhysboxToClientMap[index]; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -316,11 +501,12 @@ bool ShouldHitEntity(IHandleEntity *pHandleEntity, int contentsMask) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		iTeam = -index; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else if(index < 1 || index > SM_MAXPLAYERS) | 
		
	
		
			
				|  |  |  |  | 	else if(index < 1 || index > g_iMaxPlayers) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		RETURN_META_VALUE(MRES_IGNORED, true); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	char lifeState = 0; | 
		
	
		
			
				|  |  |  |  | 	if(!iTeam) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -332,9 +518,21 @@ bool ShouldHitEntity(IHandleEntity *pHandleEntity, int contentsMask) | 
		
	
		
			
				|  |  |  |  | 			RETURN_META_VALUE(MRES_IGNORED, true); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		iTeam = pInfo->GetTeamIndex(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		static int offset = 0; | 
		
	
		
			
				|  |  |  |  | 		if(!offset) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			sm_sendprop_info_t spi; | 
		
	
		
			
				|  |  |  |  | 			if (!gamehelpers->FindSendPropInfo("CBasePlayer", "m_lifeState", &spi)) | 
		
	
		
			
				|  |  |  |  | 				RETURN_META_VALUE(MRES_IGNORED, true); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			offset = spi.actual_offset; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if(iTeam == g_FireBulletPlayerTeam) | 
		
	
		
			
				|  |  |  |  | 		lifeState = *(char *)((uint8_t *)pHandleEntity + offset); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if(iTeam == g_FireBulletPlayerTeam || lifeState != 0) | 
		
	
		
			
				|  |  |  |  | 		RETURN_META_VALUE(MRES_SUPERCEDE, false); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	RETURN_META_VALUE(MRES_IGNORED, true); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -415,6 +613,8 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	srand((unsigned int)time(NULL)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     g_iMaxPlayers = playerhelpers->GetMaxClients(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	char conf_error[255] = ""; | 
		
	
		
			
				|  |  |  |  | 	if(!gameconfs->LoadGameConfigFile("CSSFixes", &g_pGameConf, conf_error, sizeof(conf_error))) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -442,6 +642,22 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_CreateEntityByName = DETOUR_CREATE_STATIC(DETOUR_CreateEntityByName, "CreateEntityByName"); | 
		
	
		
			
				|  |  |  |  | 	if (g_pDetour_CreateEntityByName == NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		snprintf(error, maxlength, "Could not create detour for CreateEntityByName"); | 
		
	
		
			
				|  |  |  |  | 		SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_PassesFilterImpl = DETOUR_CREATE_MEMBER(DETOUR_PassesFilterImpl, "CBaseFilter_PassesFilterImpl"); | 
		
	
		
			
				|  |  |  |  | 	if (g_pDetour_PassesFilterImpl == NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		snprintf(error, maxlength, "Could not create detour for CBaseFilter_PassesFilterImpl"); | 
		
	
		
			
				|  |  |  |  | 		SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_FindUseEntity = DETOUR_CREATE_MEMBER(DETOUR_FindUseEntity, "CBasePlayer_FindUseEntity"); | 
		
	
		
			
				|  |  |  |  | 	if(g_pDetour_FindUseEntity == NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -484,6 +700,8 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_InputTestActivator->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_PostConstructor->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_CreateEntityByName->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_PassesFilterImpl->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_FindUseEntity->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_CTraceFilterSimple->EnableDetour(); | 
		
	
		
			
				|  |  |  |  | 	g_pDetour_KeyValue->EnableDetour(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -526,62 +744,91 @@ bool CSSFixes::SDK_OnLoad(char *error, size_t maxlength, bool late) | 
		
	
		
			
				|  |  |  |  | 	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; | 
		
	
		
			
				|  |  |  |  | 		void *pBinary = dlopen(pPatch->pLibrary, RTLD_NOW); | 
		
	
		
			
				|  |  |  |  | 		if(!pBinary) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			snprintf(error, maxlength, "Could not dlopen %s", pPatch->pLibrary); | 
		
	
		
			
				|  |  |  |  | 			SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 			return false; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pPatch->pAddress = (uintptr_t)memutils->ResolveSymbol(pBinary, pPatch->pSignature); | 
		
	
		
			
				|  |  |  |  | 		dlclose(pBinary); | 
		
	
		
			
				|  |  |  |  | 		if(!pPatch->pAddress) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			snprintf(error, maxlength, "Could not find symbol: %s", pPatch->pSignature); | 
		
	
		
			
				|  |  |  |  | 			dlclose(pServerSo); | 
		
	
		
			
				|  |  |  |  | 			dlclose(pEngineSo); | 
		
	
		
			
				|  |  |  |  | 			snprintf(error, maxlength, "Could not find symbol: %s in %s (%p)", | 
		
	
		
			
				|  |  |  |  | 				pPatch->pSignature, pPatch->pLibrary, pBinary); | 
		
	
		
			
				|  |  |  |  | 			SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 			return false; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pPatch->pPatchAddress = FindPattern(pPatch->pAddress, pPatch->pPatchSignature, pPatch->pPatchPattern, 1024); | 
		
	
		
			
				|  |  |  |  | 		if(!pPatch->pPatchAddress) | 
		
	
		
			
				|  |  |  |  | 		SrcdsPatch::Restore **ppRestore = &pPatch->pRestore; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if(pPatch->functionCall) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			snprintf(error, maxlength, "Could not find patch signature for symbol: %s", pPatch->pSignature); | 
		
	
		
			
				|  |  |  |  | 			dlclose(pServerSo); | 
		
	
		
			
				|  |  |  |  | 			dlclose(pEngineSo); | 
		
	
		
			
				|  |  |  |  | 			void *pFunctionBinary = dlopen(pPatch->pFunctionLibrary, RTLD_NOW); | 
		
	
		
			
				|  |  |  |  | 			if(!pFunctionBinary) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				snprintf(error, maxlength, "Could not dlopen %s", pPatch->pFunctionLibrary); | 
		
	
		
			
				|  |  |  |  | 				SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 				return false; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		pPatch->pOriginal = (unsigned char *)malloc(PatchLen * sizeof(unsigned char)); | 
		
	
		
			
				|  |  |  |  | 			pPatch->pSignatureAddress = (uintptr_t)memutils->ResolveSymbol(pFunctionBinary, (char *)pPatch->pPatchSignature); | 
		
	
		
			
				|  |  |  |  | 			dlclose(pFunctionBinary); | 
		
	
		
			
				|  |  |  |  | 			if(!pPatch->pSignatureAddress) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				snprintf(error, maxlength, "Could not find patch signature symbol: %s in %s (%p)", | 
		
	
		
			
				|  |  |  |  | 					(char *)pPatch->pPatchSignature, pPatch->pFunctionLibrary, pFunctionBinary); | 
		
	
		
			
				|  |  |  |  | 				SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 				return false; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); | 
		
	
		
			
				|  |  |  |  | 		uintptr_t ofs = 0; | 
		
	
		
			
				|  |  |  |  | 		int found; | 
		
	
		
			
				|  |  |  |  | 		for(found = 0; found < pPatch->occurrences; found++) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			uintptr_t pPatchAddress; | 
		
	
		
			
				|  |  |  |  | 			if(pPatch->functionCall) | 
		
	
		
			
				|  |  |  |  | 				pPatchAddress = FindFunctionCall(pPatch->pAddress + ofs, pPatch->pSignatureAddress, pPatch->range - ofs); | 
		
	
		
			
				|  |  |  |  | 			else | 
		
	
		
			
				|  |  |  |  | 				pPatchAddress = FindPattern(pPatch->pAddress + ofs, pPatch->pPatchSignature, pPatch->pPatchPattern, pPatch->range - ofs); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if(!pPatchAddress) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				if(found) | 
		
	
		
			
				|  |  |  |  | 					break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				snprintf(error, maxlength, "Could not find patch signature for symbol: %s", pPatch->pSignature); | 
		
	
		
			
				|  |  |  |  | 				SDK_OnUnload(); | 
		
	
		
			
				|  |  |  |  | 				return false; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			ofs = pPatchAddress - pPatch->pAddress + PatchLen; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			// Create restore object | 
		
	
		
			
				|  |  |  |  | 			*ppRestore = (SrcdsPatch::Restore *)new SrcdsPatch::Restore(); | 
		
	
		
			
				|  |  |  |  | 			SrcdsPatch::Restore *pRestore = *ppRestore; | 
		
	
		
			
				|  |  |  |  | 			pRestore->pPatchAddress = pPatchAddress; | 
		
	
		
			
				|  |  |  |  | 			pRestore->pOriginal = (unsigned char *)malloc(PatchLen * sizeof(unsigned char)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			SourceHook::SetMemAccess((void *)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); | 
		
	
		
			
				|  |  |  |  | 				pRestore->pOriginal[j] = *(unsigned char *)(pPatchAddress + j); | 
		
	
		
			
				|  |  |  |  | 				*(unsigned char *)(pPatchAddress + j) = pPatch->pPatch[j]; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			SourceHook::SetMemAccess((void *)pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	dlclose(pServerSo); | 
		
	
		
			
				|  |  |  |  | 	dlclose(pEngineSo); | 
		
	
		
			
				|  |  |  |  | 			ppRestore = &((*ppRestore)->pNext); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -612,6 +859,18 @@ void CSSFixes::SDK_OnUnload() | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_PostConstructor = NULL; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (g_pDetour_CreateEntityByName != NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_CreateEntityByName->Destroy(); | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_CreateEntityByName = NULL; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (g_pDetour_PassesFilterImpl != NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_PassesFilterImpl->Destroy(); | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_PassesFilterImpl = NULL; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if(g_pDetour_FindUseEntity != NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		g_pDetour_FindUseEntity->Destroy(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -656,18 +915,26 @@ void CSSFixes::SDK_OnUnload() | 
		
	
		
			
				|  |  |  |  | 		struct SrcdsPatch *pPatch = &gs_Patches[i]; | 
		
	
		
			
				|  |  |  |  | 		int PatchLen = strlen(pPatch->pPatchPattern); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if(!pPatch->pOriginal) | 
		
	
		
			
				|  |  |  |  | 			continue; | 
		
	
		
			
				|  |  |  |  | 		SrcdsPatch::Restore *pRestore = pPatch->pRestore; | 
		
	
		
			
				|  |  |  |  | 		while(pRestore) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if(!pRestore->pOriginal) | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); | 
		
	
		
			
				|  |  |  |  | 			SourceHook::SetMemAccess((void *)pRestore->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]; | 
		
	
		
			
				|  |  |  |  | 				*(unsigned char *)(pRestore->pPatchAddress + j) = pRestore->pOriginal[j]; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		SourceHook::SetMemAccess((void *)pPatch->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC); | 
		
	
		
			
				|  |  |  |  | 			SourceHook::SetMemAccess((void *)pRestore->pPatchAddress, PatchLen, SH_MEM_READ|SH_MEM_EXEC); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		free(pPatch->pOriginal); | 
		
	
		
			
				|  |  |  |  | 		pPatch->pOriginal = NULL; | 
		
	
		
			
				|  |  |  |  | 			free(pRestore->pOriginal); | 
		
	
		
			
				|  |  |  |  | 			pRestore->pOriginal = NULL; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			void *freeMe = pRestore; | 
		
	
		
			
				|  |  |  |  | 			pRestore = pRestore->pNext; | 
		
	
		
			
				|  |  |  |  | 			free(freeMe); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  |   |