1.1 --- a/extensions/tf2/Makefile Thu Apr 10 00:10:45 2008 +0000
1.2 +++ b/extensions/tf2/Makefile Thu Apr 10 04:49:17 2008 +0000
1.3 @@ -17,7 +17,7 @@
1.4 #Uncomment for Metamod: Source enabled extension
1.5 USEMETA = true
1.6
1.7 -OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp
1.8 +OBJECTS = sdk/smsdk_ext.cpp extension.cpp natives.cpp RegNatives.cpp criticals.cpp
1.9
1.10 ##############################################
1.11 ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/extensions/tf2/criticals.cpp Thu Apr 10 04:49:17 2008 +0000
2.3 @@ -0,0 +1,422 @@
2.4 +/**
2.5 + * vim: set ts=4 :
2.6 + * =============================================================================
2.7 + * SourceMod TF2 Extension
2.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
2.9 + * =============================================================================
2.10 + *
2.11 + * This program is free software; you can redistribute it and/or modify it under
2.12 + * the terms of the GNU General Public License, version 3.0, as published by the
2.13 + * Free Software Foundation.
2.14 + *
2.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2.18 + * details.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License along with
2.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
2.22 + *
2.23 + * As a special exception, AlliedModders LLC gives you permission to link the
2.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
2.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
2.26 + * by the Valve Corporation. You must obey the GNU General Public License in
2.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
2.28 + * this exception to all derivative works. AlliedModders LLC defines further
2.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
2.30 + * or <http://www.sourcemod.net/license.php>.
2.31 + *
2.32 + * Version: $Id$
2.33 + */
2.34 +
2.35 +#include "criticals.h"
2.36 +
2.37 +ISourcePawnEngine *spengine = NULL;
2.38 +CriticalHitManager g_CriticalHitManager;
2.39 +IServerGameEnts *gameents = NULL;
2.40 +
2.41 +int g_returnvalue;
2.42 +
2.43 +bool CriticalHitManager::CreateCriticalDetour()
2.44 +{
2.45 + if (!g_pGameConf->GetMemSig("CalcCritical", &critical_address) || !critical_address)
2.46 + {
2.47 + g_pSM->LogError(myself, "Could not locate CalcCritical - Disabling Critical Hit forward");
2.48 + return false;
2.49 + }
2.50 +
2.51 + if (!g_pGameConf->GetOffset("CalcCriticalBackup", (int *)&(critical_restore.bytes)))
2.52 + {
2.53 + g_pSM->LogError(myself, "Could not locate CalcCriticalBackup - Disabling Critical Hit forward");
2.54 + return false;
2.55 + }
2.56 +
2.57 + /* First, save restore bits */
2.58 + for (size_t i=0; i<critical_restore.bytes; i++)
2.59 + {
2.60 + critical_restore.patch[i] = ((unsigned char *)critical_address)[i];
2.61 + }
2.62 +
2.63 + critical_callback = spengine->ExecAlloc(100);
2.64 + JitWriter wr;
2.65 + JitWriter *jit = ≀
2.66 + wr.outbase = (jitcode_t)critical_callback;
2.67 + wr.outptr = wr.outbase;
2.68 +
2.69 + /* Function we are detouring into is
2.70 + *
2.71 + * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
2.72 + *
2.73 + * push pWeapon [ecx]
2.74 + */
2.75 +
2.76 +#if defined PLATFORM_WINDOWS
2.77 + IA32_Push_Reg(jit, REG_ECX);
2.78 +#elif defined PLATFORM_LINUX
2.79 + IA32_Push_Rm_Disp8_ESP(jit, 4);
2.80 +#endif
2.81 +
2.82 + jitoffs_t call = IA32_Call_Imm32(jit, 0);
2.83 + IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
2.84 +
2.85 +
2.86 +#if defined PLATFORM_LINUX
2.87 + IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
2.88 +#elif defined PLATFORM_WINDOWS
2.89 + IA32_Pop_Reg(jit, REG_ECX);
2.90 +#endif
2.91 +
2.92 + //If TempDetour returns non-zero we want to load something into eax and return this value
2.93 +
2.94 + //IA32_Test_Rm_Reg(jit, eax, eax, something);
2.95 + jit->write_ubyte(0x85);
2.96 + jit->write_ubyte(0xC0);
2.97 +
2.98 + //JNZ critical_callback+50
2.99 + jit->write_ubyte(0x75);
2.100 + jit->write_ubyte(50-((jit->outptr+1)-jit->outbase));
2.101 +
2.102 + /* Patch old bytes in */
2.103 + for (size_t i=0; i<critical_restore.bytes; i++)
2.104 + {
2.105 + jit->write_ubyte(critical_restore.patch[i]);
2.106 + }
2.107 +
2.108 + /* Return to the original function */
2.109 + call = IA32_Jump_Imm32(jit, 0);
2.110 + IA32_Write_Jump32_Abs(jit, call, (unsigned char *)critical_address + critical_restore.bytes);
2.111 +
2.112 + wr.outbase = (jitcode_t)critical_callback+50;
2.113 + wr.outptr = wr.outbase;
2.114 +
2.115 + //copy g_returnvalue into eax
2.116 + jit->write_ubyte(0xA1);
2.117 + jit->write_uint32((jit_uint32_t)&g_returnvalue);
2.118 +
2.119 + IA32_Return(jit);
2.120 +
2.121 + return true;
2.122 +}
2.123 +
2.124 +bool CriticalHitManager::CreateCriticalMeleeDetour()
2.125 +{
2.126 + if (!g_pGameConf->GetMemSig("CalcCriticalMelee", &melee_address) || !melee_address)
2.127 + {
2.128 + g_pSM->LogError(myself, "Could not locate CalcCriticalMelee - Disabling Critical Hit forward");
2.129 + return false;
2.130 + }
2.131 +
2.132 + if (!g_pGameConf->GetOffset("CalcCriticalMeleeBackup", (int *)&(melee_restore.bytes)))
2.133 + {
2.134 + g_pSM->LogError(myself, "Could not locate CalcCriticalMeleeBackup - Disabling Critical Hit forward");
2.135 + return false;
2.136 + }
2.137 +
2.138 + /* First, save restore bits */
2.139 + for (size_t i=0; i<melee_restore.bytes; i++)
2.140 + {
2.141 + melee_restore.patch[i] = ((unsigned char *)melee_address)[i];
2.142 + }
2.143 +
2.144 + melee_callback = spengine->ExecAlloc(100);
2.145 + JitWriter wr;
2.146 + JitWriter *jit = ≀
2.147 + wr.outbase = (jitcode_t)melee_callback;
2.148 + wr.outptr = wr.outbase;
2.149 +
2.150 + /* Function we are detouring into is
2.151 + *
2.152 + * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
2.153 + *
2.154 + * push pWeapon [ecx]
2.155 + */
2.156 +
2.157 +#if defined PLATFORM_WINDOWS
2.158 + IA32_Push_Reg(jit, REG_ECX);
2.159 +#elif defined PLATFORM_LINUX
2.160 + IA32_Push_Rm_Disp8_ESP(jit, 4);
2.161 +#endif
2.162 +
2.163 + jitoffs_t call = IA32_Call_Imm32(jit, 0);
2.164 + IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
2.165 +
2.166 +
2.167 +#if defined PLATFORM_LINUX
2.168 + IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
2.169 +#elif defined PLATFORM_WINDOWS
2.170 + IA32_Pop_Reg(jit, REG_ECX);
2.171 +#endif
2.172 +
2.173 + //If TempDetour returns non-zero we want to load something into eax and return this value
2.174 +
2.175 + //IA32_Test_Rm_Reg(jit, eax, eax, something);
2.176 + jit->write_ubyte(0x85);
2.177 + jit->write_ubyte(0xC0);
2.178 +
2.179 + //JNZ critical_callback+50
2.180 + jit->write_ubyte(0x75);
2.181 + jit->write_ubyte(50-((jit->outptr+1)-jit->outbase));
2.182 +
2.183 + /* Patch old bytes in */
2.184 + for (size_t i=0; i<melee_restore.bytes; i++)
2.185 + {
2.186 + jit->write_ubyte(melee_restore.patch[i]);
2.187 + }
2.188 +
2.189 + /* Return to the original function */
2.190 + call = IA32_Jump_Imm32(jit, 0);
2.191 + IA32_Write_Jump32_Abs(jit, call, (unsigned char *)melee_address + melee_restore.bytes);
2.192 +
2.193 + wr.outbase = (jitcode_t)melee_callback+50;
2.194 + wr.outptr = wr.outbase;
2.195 +
2.196 + //copy g_returnvalue into eax
2.197 + jit->write_ubyte(0xA1);
2.198 + jit->write_uint32((jit_uint32_t)&g_returnvalue);
2.199 +
2.200 + IA32_Return(jit);
2.201 +
2.202 + return true;
2.203 +}
2.204 +
2.205 +bool CriticalHitManager::CreateCriticalKnifeDetour()
2.206 +{
2.207 + if (!g_pGameConf->GetMemSig("CalcCriticalKnife", &knife_address) || !knife_address)
2.208 + {
2.209 + g_pSM->LogError(myself, "Could not locate CalcCriticalKnife - Disabling Critical Hit forward");
2.210 + return false;
2.211 + }
2.212 +
2.213 + if (!g_pGameConf->GetOffset("CalcCriticalMeleeBackup", (int *)&(knife_restore.bytes)))
2.214 + {
2.215 + g_pSM->LogError(myself, "Could not locate CalcCriticalKnifeBackup - Disabling Critical Hit forward");
2.216 + return false;
2.217 + }
2.218 +
2.219 + /* First, save restore bits */
2.220 + for (size_t i=0; i<knife_restore.bytes; i++)
2.221 + {
2.222 + knife_restore.patch[i] = ((unsigned char *)knife_address)[i];
2.223 + }
2.224 +
2.225 + knife_callback = spengine->ExecAlloc(100);
2.226 + JitWriter wr;
2.227 + JitWriter *jit = ≀
2.228 + wr.outbase = (jitcode_t)knife_callback;
2.229 + wr.outptr = wr.outbase;
2.230 +
2.231 + /* Function we are detouring into is
2.232 + *
2.233 + * void CriticalDetour(CTFWeaponBase(void *) *pWeapon)
2.234 + *
2.235 + * push pWeapon [ecx]
2.236 + */
2.237 +
2.238 +#if defined PLATFORM_WINDOWS
2.239 + IA32_Push_Reg(jit, REG_ECX);
2.240 +#elif defined PLATFORM_LINUX
2.241 + IA32_Push_Rm_Disp8_ESP(jit, 4);
2.242 +#endif
2.243 +
2.244 + jitoffs_t call = IA32_Call_Imm32(jit, 0);
2.245 + IA32_Write_Jump32_Abs(jit, call, (void *)TempDetour);
2.246 +
2.247 +
2.248 +#if defined PLATFORM_LINUX
2.249 + IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); //add esp, 4
2.250 +#elif defined PLATFORM_WINDOWS
2.251 + IA32_Pop_Reg(jit, REG_ECX);
2.252 +#endif
2.253 +
2.254 + //If TempDetour returns non-zero we want to load something into eax and return this value
2.255 +
2.256 + //IA32_Test_Rm_Reg(jit, eax, eax, something);
2.257 + jit->write_ubyte(0x85);
2.258 + jit->write_ubyte(0xC0);
2.259 +
2.260 + //JNZ critical_callback+50
2.261 + jit->write_ubyte(0x75);
2.262 + jit->write_ubyte(50-((jit->outptr+1)-jit->outbase));
2.263 +
2.264 + /* Patch old bytes in */
2.265 + for (size_t i=0; i<knife_restore.bytes; i++)
2.266 + {
2.267 + jit->write_ubyte(knife_restore.patch[i]);
2.268 + }
2.269 +
2.270 + /* Return to the original function */
2.271 + call = IA32_Jump_Imm32(jit, 0);
2.272 + IA32_Write_Jump32_Abs(jit, call, (unsigned char *)knife_address + knife_restore.bytes);
2.273 +
2.274 + wr.outbase = (jitcode_t)knife_callback+50;
2.275 + wr.outptr = wr.outbase;
2.276 +
2.277 + //copy g_returnvalue into eax
2.278 + jit->write_ubyte(0xA1);
2.279 + jit->write_uint32((jit_uint32_t)&g_returnvalue);
2.280 +
2.281 + IA32_Return(jit);
2.282 +
2.283 + return true;
2.284 +}
2.285 +
2.286 +void CriticalHitManager::EnableCriticalDetour()
2.287 +{
2.288 + if (!detoured)
2.289 + {
2.290 + DoGatePatch((unsigned char *)critical_address, &critical_callback);
2.291 + DoGatePatch((unsigned char *)melee_address, &melee_callback);
2.292 + DoGatePatch((unsigned char *)knife_address, &knife_callback);
2.293 + detoured = true;
2.294 + }
2.295 +}
2.296 +
2.297 +void CriticalHitManager::DeleteCriticalDetour()
2.298 +{
2.299 + if (detoured)
2.300 + {
2.301 + DisableCriticalDetour();
2.302 + }
2.303 +
2.304 + if (critical_callback)
2.305 + {
2.306 + /* Free the gate */
2.307 + spengine->ExecFree(critical_callback);
2.308 + critical_callback = NULL;
2.309 + }
2.310 +
2.311 + if (melee_callback)
2.312 + {
2.313 + /* Free the gate */
2.314 + spengine->ExecFree(melee_callback);
2.315 + melee_callback = NULL;
2.316 + }
2.317 +
2.318 + if (knife_callback)
2.319 + {
2.320 + /* Free the gate */
2.321 + spengine->ExecFree(knife_callback);
2.322 + knife_callback = NULL;
2.323 + }
2.324 +}
2.325 +
2.326 +bool TempDetour(void *pWeapon)
2.327 +{
2.328 + return g_CriticalHitManager.CriticalDetour(pWeapon);
2.329 +}
2.330 +
2.331 +void CriticalHitManager::DisableCriticalDetour()
2.332 +{
2.333 + if (critical_callback)
2.334 + {
2.335 + /* Remove the patch */
2.336 + ApplyPatch(critical_address, 0, &critical_restore, NULL);
2.337 + detoured = false;
2.338 + }
2.339 +
2.340 + if (melee_callback)
2.341 + {
2.342 + /* Remove the patch */
2.343 + ApplyPatch(melee_address, 0, &melee_restore, NULL);
2.344 + detoured = false;
2.345 + }
2.346 +
2.347 + if (melee_callback)
2.348 + {
2.349 + /* Remove the patch */
2.350 + ApplyPatch(knife_address, 0, &knife_restore, NULL);
2.351 + detoured = false;
2.352 + }
2.353 +}
2.354 +
2.355 +int CheckBaseHandle(CBaseHandle &hndl)
2.356 +{
2.357 + if (!hndl.IsValid())
2.358 + {
2.359 + return -1;
2.360 + }
2.361 +
2.362 + int index = hndl.GetEntryIndex();
2.363 +
2.364 + edict_t *pStoredEdict;
2.365 +
2.366 + pStoredEdict = engine->PEntityOfEntIndex(index);
2.367 +
2.368 + if (pStoredEdict == NULL)
2.369 + {
2.370 + return -1;
2.371 + }
2.372 +
2.373 + IServerEntity *pSE = pStoredEdict->GetIServerEntity();
2.374 +
2.375 + if (pSE == NULL)
2.376 + {
2.377 + return -1;
2.378 + }
2.379 +
2.380 + if (pSE->GetRefEHandle() != hndl)
2.381 + {
2.382 + return -1;
2.383 + }
2.384 +
2.385 + return index;
2.386 +}
2.387 +
2.388 +bool CriticalHitManager::CriticalDetour(void *pWeapon)
2.389 +{
2.390 + edict_t *pEdict = gameents->BaseEntityToEdict((CBaseEntity *)pWeapon);
2.391 +
2.392 + if (!pEdict)
2.393 + {
2.394 + g_pSM->LogMessage(myself, "Entity Error");
2.395 + return false;
2.396 + }
2.397 +
2.398 + sm_sendprop_info_t info;
2.399 +
2.400 + if (!gamehelpers->FindSendPropInfo(pEdict->GetNetworkable()->GetServerClass()->GetName(), "m_hOwnerEntity", &info))
2.401 + {
2.402 + g_pSM->LogMessage(myself, "Offset Error");
2.403 + return false;
2.404 + }
2.405 +
2.406 + if (!forward)
2.407 + {
2.408 + g_pSM->LogMessage(myself, "Invalid Forward");
2.409 + return false;
2.410 + }
2.411 +
2.412 + CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pWeapon + info.actual_offset);
2.413 + int index = CheckBaseHandle(hndl);
2.414 +
2.415 + forward->PushCell(index); //Client index
2.416 + forward->PushCell(engine->IndexOfEdict(pEdict)); // Weapon index
2.417 + forward->PushString(pEdict->GetClassName()); //Weapon classname
2.418 + forward->PushCellByRef(&g_returnvalue); //return value
2.419 +
2.420 + cell_t result = 0;
2.421 +
2.422 + forward->Execute(&result);
2.423 +
2.424 + return !!result;
2.425 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/extensions/tf2/criticals.h Thu Apr 10 04:49:17 2008 +0000
3.3 @@ -0,0 +1,125 @@
3.4 +/**
3.5 + * vim: set ts=4 :
3.6 + * =============================================================================
3.7 + * SourceMod TF2 Extension
3.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
3.9 + * =============================================================================
3.10 + *
3.11 + * This program is free software; you can redistribute it and/or modify it under
3.12 + * the terms of the GNU General Public License, version 3.0, as published by the
3.13 + * Free Software Foundation.
3.14 + *
3.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
3.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.18 + * details.
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License along with
3.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
3.22 + *
3.23 + * As a special exception, AlliedModders LLC gives you permission to link the
3.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
3.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
3.26 + * by the Valve Corporation. You must obey the GNU General Public License in
3.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
3.28 + * this exception to all derivative works. AlliedModders LLC defines further
3.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
3.30 + * or <http://www.sourcemod.net/license.php>.
3.31 + *
3.32 + * Version: $Id$
3.33 + */
3.34 +
3.35 +#include "extension.h"
3.36 +#include <jit/jit_helpers.h>
3.37 +#include <jit/x86/x86_macros.h>
3.38 +#include "detours.h"
3.39 +
3.40 +class CriticalHitManager
3.41 +{
3.42 +public:
3.43 + CriticalHitManager()
3.44 + {
3.45 + enabled = false;
3.46 + detoured = false;
3.47 + critical_address = NULL;
3.48 + critical_callback = NULL;
3.49 +
3.50 + melee_address = NULL;
3.51 + melee_callback = NULL;
3.52 +
3.53 + knife_address = NULL;
3.54 + knife_callback = NULL;
3.55 +
3.56 + forward = NULL;
3.57 + }
3.58 +
3.59 + ~CriticalHitManager()
3.60 + {
3.61 + forwards->ReleaseForward(forward);
3.62 + DeleteCriticalDetour();
3.63 + }
3.64 +
3.65 + void Init()
3.66 + {
3.67 + if (!CreateCriticalDetour() || !CreateCriticalMeleeDetour() || !CreateCriticalKnifeDetour())
3.68 + {
3.69 + enabled = false;
3.70 + return;
3.71 + }
3.72 +
3.73 + forward = forwards->CreateForward("TF2_CalcIsAttackCritical", ET_Hook, 4, NULL, Param_Cell, Param_Cell, Param_String, Param_CellByRef);
3.74 +
3.75 + if (!forward)
3.76 + {
3.77 + g_pSM->LogError(myself, "Failed to create forward - Disabling critical hit hook");
3.78 + enabled = false;
3.79 + return;
3.80 + }
3.81 +
3.82 + /* TODO: Only enable this once forwards exist. Requires IForwardListener functionality */
3.83 + EnableCriticalDetour();
3.84 +
3.85 + enabled = true;
3.86 + }
3.87 +
3.88 + bool IsEnabled()
3.89 + {
3.90 + return enabled;
3.91 + }
3.92 +
3.93 + bool CriticalDetour(void *pWeapon);
3.94 +
3.95 +private:
3.96 + IForward *forward;
3.97 +
3.98 + /* These create/delete the allocated memory */
3.99 + bool CreateCriticalDetour();
3.100 + bool CreateCriticalMeleeDetour();
3.101 + bool CreateCriticalKnifeDetour();
3.102 + void DeleteCriticalDetour();
3.103 +
3.104 + /* These patch/unpatch the server.dll */
3.105 + void EnableCriticalDetour();
3.106 + void DisableCriticalDetour();
3.107 +
3.108 + bool enabled;
3.109 + bool detoured;
3.110 +
3.111 + patch_t critical_restore;
3.112 + void *critical_address;
3.113 + void *critical_callback;
3.114 +
3.115 + patch_t melee_restore;
3.116 + void *melee_address;
3.117 + void *melee_callback;
3.118 +
3.119 + patch_t knife_restore;
3.120 + void *knife_address;
3.121 + void *knife_callback;
3.122 +};
3.123 +
3.124 +bool TempDetour(void *pWeapon);
3.125 +
3.126 +extern ISourcePawnEngine *spengine;
3.127 +extern IServerGameEnts *gameents;
3.128 +extern CriticalHitManager g_CriticalHitManager;
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/extensions/tf2/detours.h Thu Apr 10 04:49:17 2008 +0000
4.3 @@ -0,0 +1,98 @@
4.4 +/**
4.5 + * vim: set ts=4 :
4.6 + * =============================================================================
4.7 + * SourceMod SDKTools Extension
4.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
4.9 + * =============================================================================
4.10 + *
4.11 + * This program is free software; you can redistribute it and/or modify it under
4.12 + * the terms of the GNU General Public License, version 3.0, as published by the
4.13 + * Free Software Foundation.
4.14 + *
4.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
4.18 + * details.
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License along with
4.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
4.22 + *
4.23 + * As a special exception, AlliedModders LLC gives you permission to link the
4.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
4.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
4.26 + * by the Valve Corporation. You must obey the GNU General Public License in
4.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
4.28 + * this exception to all derivative works. AlliedModders LLC defines further
4.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
4.30 + * or <http://www.sourcemod.net/license.php>.
4.31 + *
4.32 + * Version: $Id$
4.33 + */
4.34 +
4.35 +#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
4.36 +#define _INCLUDE_SOURCEMOD_DETOURS_H_
4.37 +
4.38 +#if defined PLATFORM_LINUX
4.39 +#include <sys/mman.h>
4.40 +#define PAGE_SIZE 4096
4.41 +#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
4.42 +#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC
4.43 +#endif
4.44 +
4.45 +struct patch_t
4.46 +{
4.47 + patch_t()
4.48 + {
4.49 + patch[0] = 0;
4.50 + bytes = 0;
4.51 + }
4.52 + unsigned char patch[20];
4.53 + size_t bytes;
4.54 +};
4.55 +
4.56 +inline void ProtectMemory(void *addr, int length, int prot)
4.57 +{
4.58 +#if defined PLATFORM_LINUX
4.59 + void *addr2 = (void *)ALIGN(addr);
4.60 + mprotect(addr2, sysconf(_SC_PAGESIZE), prot);
4.61 +#elif defined PLATFORM_WINDOWS
4.62 + DWORD old_prot;
4.63 + VirtualProtect(addr, length, prot, &old_prot);
4.64 +#endif
4.65 +}
4.66 +
4.67 +inline void SetMemPatchable(void *address, size_t size)
4.68 +{
4.69 + ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE);
4.70 +}
4.71 +
4.72 +inline void DoGatePatch(unsigned char *target, void *callback)
4.73 +{
4.74 + SetMemPatchable(target, 20);
4.75 +
4.76 + target[0] = 0xFF; /* JMP */
4.77 + target[1] = 0x25; /* MEM32 */
4.78 + *(void **)(&target[2]) = callback;
4.79 +}
4.80 +
4.81 +inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore)
4.82 +{
4.83 + ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE);
4.84 +
4.85 + unsigned char *addr = (unsigned char *)address + offset;
4.86 + if (restore)
4.87 + {
4.88 + for (size_t i=0; i<patch->bytes; i++)
4.89 + {
4.90 + restore->patch[i] = addr[i];
4.91 + }
4.92 + restore->bytes = patch->bytes;
4.93 + }
4.94 +
4.95 + for (size_t i=0; i<patch->bytes; i++)
4.96 + {
4.97 + addr[i] = patch->patch[i];
4.98 + }
4.99 +}
4.100 +
4.101 +#endif //_INCLUDE_SOURCEMOD_DETOURS_H_
5.1 --- a/extensions/tf2/extension.cpp Thu Apr 10 00:10:45 2008 +0000
5.2 +++ b/extensions/tf2/extension.cpp Thu Apr 10 04:49:17 2008 +0000
5.3 @@ -34,6 +34,7 @@
5.4 #include "RegNatives.h"
5.5 #include "iplayerinfo.h"
5.6 #include "sm_trie_tpl.h"
5.7 +#include "criticals.h"
5.8
5.9 /**
5.10 * @file extension.cpp
5.11 @@ -48,6 +49,8 @@
5.12
5.13 SMEXT_LINK(&g_TF2Tools);
5.14
5.15 +ICvar *icvar = NULL;
5.16 +
5.17 CGlobalVars *gpGlobals = NULL;
5.18
5.19 sm_sendprop_info_t *playerSharedOffset;
5.20 @@ -94,6 +97,10 @@
5.21
5.22 playerhelpers->RegisterCommandTargetProcessor(this);
5.23
5.24 + spengine = g_pSM->GetScriptingEngine();
5.25 +
5.26 + g_pCVar = icvar;
5.27 +
5.28 return true;
5.29 }
5.30
5.31 @@ -105,6 +112,10 @@
5.32
5.33 SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_STATIC(OnServerActivate), true);
5.34
5.35 + GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
5.36 +
5.37 + GET_V_IFACE_CURRENT(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
5.38 +
5.39 return true;
5.40 }
5.41
5.42 @@ -120,8 +131,16 @@
5.43 void TF2Tools::SDK_OnAllLoaded()
5.44 {
5.45 SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
5.46 +
5.47 + g_CriticalHitManager.Init();
5.48 }
5.49
5.50 +bool TF2Tools::RegisterConCommandBase(ConCommandBase *pVar)
5.51 +{
5.52 + return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
5.53 +}
5.54 +
5.55 +
5.56 bool TF2Tools::QueryRunning(char *error, size_t maxlength)
5.57 {
5.58 SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
5.59 @@ -291,7 +310,6 @@
5.60 if (!filled)
5.61 {
5.62 trie.insert("scout", TFClass_Scout);
5.63 - trie.insert("scout", TFClass_Scout);
5.64 trie.insert("sniper", TFClass_Sniper);
5.65 trie.insert("soldier", TFClass_Soldier);
5.66 trie.insert("demoman", TFClass_DemoMan);
6.1 --- a/extensions/tf2/extension.h Thu Apr 10 00:10:45 2008 +0000
6.2 +++ b/extensions/tf2/extension.h Thu Apr 10 04:49:17 2008 +0000
6.3 @@ -46,7 +46,8 @@
6.4 */
6.5 class TF2Tools :
6.6 public SDKExtension,
6.7 - public ICommandTargetProcessor
6.8 + public ICommandTargetProcessor,
6.9 + public IConCommandBaseAccessor
6.10 {
6.11 public:
6.12 /**
6.13 @@ -88,6 +89,7 @@
6.14 bool QueryInterfaceDrop(SMInterface *pInterface);
6.15 public:
6.16 bool ProcessCommandTarget(cmd_target_info_t *info);
6.17 + bool RegisterConCommandBase(ConCommandBase *pVar);
6.18 public:
6.19 #if defined SMEXT_CONF_METAMOD
6.20 /**
7.1 --- a/extensions/tf2/msvc8/tf2.vcproj Thu Apr 10 00:10:45 2008 +0000
7.2 +++ b/extensions/tf2/msvc8/tf2.vcproj Thu Apr 10 04:49:17 2008 +0000
7.3 @@ -122,7 +122,7 @@
7.4 Name="VCCLCompilerTool"
7.5 FavorSizeOrSpeed="1"
7.6 AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(SOURCEMM16)";"$(SOURCEMM16)\sourcemm";"$(SOURCEMM16)\sourcehook""
7.7 - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
7.8 + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
7.9 RuntimeLibrary="0"
7.10 EnableEnhancedInstructionSet="1"
7.11 RuntimeTypeInfo="false"
7.12 @@ -186,6 +186,10 @@
7.13 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
7.14 >
7.15 <File
7.16 + RelativePath="..\criticals.cpp"
7.17 + >
7.18 + </File>
7.19 + <File
7.20 RelativePath="..\extension.cpp"
7.21 >
7.22 </File>
7.23 @@ -208,6 +212,14 @@
7.24 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
7.25 >
7.26 <File
7.27 + RelativePath="..\criticals.h"
7.28 + >
7.29 + </File>
7.30 + <File
7.31 + RelativePath="..\detours.h"
7.32 + >
7.33 + </File>
7.34 + <File
7.35 RelativePath="..\extension.h"
7.36 >
7.37 </File>
8.1 --- a/extensions/tf2/sdk/smsdk_config.h Thu Apr 10 00:10:45 2008 +0000
8.2 +++ b/extensions/tf2/sdk/smsdk_config.h Thu Apr 10 04:49:17 2008 +0000
8.3 @@ -61,7 +61,7 @@
8.4 #define SMEXT_CONF_METAMOD
8.5
8.6 /** Enable interfaces you want to use here by uncommenting lines */
8.7 -//#define SMEXT_ENABLE_FORWARDSYS
8.8 +#define SMEXT_ENABLE_FORWARDSYS
8.9 //#define SMEXT_ENABLE_HANDLESYS
8.10 #define SMEXT_ENABLE_PLAYERHELPERS
8.11 //#define SMEXT_ENABLE_DBMANAGER
9.1 --- a/gamedata/sm-tf2.games.txt Thu Apr 10 00:10:45 2008 +0000
9.2 +++ b/gamedata/sm-tf2.games.txt Thu Apr 10 04:49:17 2008 +0000
9.3 @@ -28,6 +28,24 @@
9.4 "windows" "\x56\x8B\xF1\x8B\x4E\x7C\xE8"
9.5 "linux" "@_ZN15CTFPlayerShared8DisguiseEii"
9.6 }
9.7 + "CalcCritical"
9.8 + {
9.9 + "library" "server"
9.10 + "linux" "@_ZN13CTFWeaponBase26CalcIsAttackCriticalHelperEv"
9.11 + "windows" "\x83\xEC\x08\x56\x57\x6A\x00\x68"
9.12 + }
9.13 + "CalcCriticalMelee"
9.14 + {
9.15 + "library" "server"
9.16 + "linux" "@_ZN18CTFWeaponBaseMelee26CalcIsAttackCriticalHelperEv"
9.17 + "windows" "\x83\xEC\x08\x56\xE8\x2A\x2A\x2A\x2A\x8B\xF0\x85\xF6"
9.18 + }
9.19 + "CalcCriticalKnife"
9.20 + {
9.21 + "library" "server"
9.22 + "linux" "@_ZN8CTFKnife26CalcIsAttackCriticalHelperEv"
9.23 + "windows" "\x33\xC0\x83\xB9\x20\x05\x00"
9.24 + }
9.25
9.26 }
9.27 "Offsets"
9.28 @@ -36,7 +54,22 @@
9.29 {
9.30 "windows" "279"
9.31 "linux" "280"
9.32 - }
9.33 + }
9.34 + "CalcCriticalBackup"
9.35 + {
9.36 + "linux" "7"
9.37 + "windows" "7"
9.38 + }
9.39 + "CalcCriticalMeleeBackup"
9.40 + {
9.41 + "linux" "7"
9.42 + "windows" "9"
9.43 + }
9.44 + "CalcCriticalKnifeBackup"
9.45 + {
9.46 + "linux" "11"
9.47 + "windows" "9"
9.48 + }
9.49 }
9.50 }
9.51 }
9.52 \ No newline at end of file
10.1 --- a/plugins/include/tf2.inc Thu Apr 10 00:10:45 2008 +0000
10.2 +++ b/plugins/include/tf2.inc Thu Apr 10 04:49:17 2008 +0000
10.3 @@ -114,6 +114,23 @@
10.4 native TFClassType:TF2_GetClass(const String:classname[]);
10.5
10.6 /**
10.7 + * Called on weapon fire to decide if the current shot should be critical.
10.8 + * Return Plugin_Continue to let the original calculation or return a higher
10.9 + * action to override the decision with the value of 'result'
10.10 + *
10.11 + * @note Since critical shots are also calculated client side any changes made with
10.12 + * this will not show for the shooter. Projectile weapons such as the rocketlauncher
10.13 + * and demoman weapons will show a critical bullet but no critical sound effect.
10.14 + * Bullet hits should appear as expected.
10.15 + *
10.16 + * @param client Client Index.
10.17 + * @param weapon Weapon entity Index.
10.18 + * @param weaponname Classname of the weapon.
10.19 + * @param result Buffer param for the result of the decision.
10.20 + */
10.21 +forward Action:TF2_CalcIsAttackCritical(client, weapon, String:weaponname[], &bool:result)
10.22 +
10.23 +/**
10.24 * Do not edit below this line!
10.25 */
10.26 public Extension:__ext_tf2 =