Merge pull request #232 from Arkshine/fix/tfc-crash-medic

Fix crash in TFCX module when Infection weapon is used (bug 6333)
This commit is contained in:
Vincent Herbet 2015-03-28 17:29:47 +01:00
commit d4bfebec22
2 changed files with 84 additions and 30 deletions

View File

@ -19,25 +19,27 @@
#include "CRank.h" #include "CRank.h"
#if defined(_WIN32) #if defined(_WIN32)
#define LINUXOFFSET 0 #define LINUXOFFSET 0
#define CLIP_LINUXOFFSET 0 #define PLAYER_LINUXOFFSET 0
#define CLIP_LINUXOFFSET 0
#else #else
#define LINUXOFFSET 4 #define LINUXOFFSET 4
#define CLIP_LINUXOFFSET 4 #define PLAYER_LINUXOFFSET 5
#define CLIP_LINUXOFFSET 4
#endif #endif
#define TFCMAX_CUSTOMWPNS 5 #define TFCMAX_CUSTOMWPNS 5
#define TFCMAX_WEAPONS MAX_WEAPONS + TFCMAX_CUSTOMWPNS #define TFCMAX_WEAPONS MAX_WEAPONS + TFCMAX_CUSTOMWPNS
#define PD_HAS_GOALITEM 26 + LINUXOFFSET #define PD_HAS_GOALITEM 26 + LINUXOFFSET
#define PD_GOALITEM_TEAM 36 + LINUXOFFSET #define PD_GOALITEM_TEAM 36 + LINUXOFFSET
#define PD_SENTRY_OWNER 83 + LINUXOFFSET #define PD_SENTRY_OWNER 83 + LINUXOFFSET
#define PD_TIMER_OWNER 932 + LINUXOFFSET #define PD_TIMER_OWNER 932 + PLAYER_LINUXOFFSET
// If somehow TFC updates, the following two offsets can be updated by // If somehow TFC updates, the following two offsets can be updated by
// disassembling CBaseEntity::KeyValuePartThree(KeyValueData_s *) // disassembling CBaseEntity::KeyValuePartThree(KeyValueData_s *)
#define PD_REPLACE_MODEL 170 + LINUXOFFSET #define PD_REPLACE_MODEL 170 + LINUXOFFSET
#define PD_REPLACE_SKIN 172 + LINUXOFFSET #define PD_REPLACE_SKIN 172 + LINUXOFFSET
#define MAX_TRACE 13 #define MAX_TRACE 13
@ -194,12 +196,12 @@ class Grenades
{ {
struct Obj struct Obj
{ {
CPlayer* player; CPlayer* player;
edict_t* grenade; edict_t* grenade;
float time; float time;
int type; int type;
Obj* next; Obj* next;
Obj* prev; Obj* prev;
} *head; } *head;

View File

@ -62,6 +62,49 @@ void Client_WeaponList(void* mValue){
} }
*/ */
int get_pdata_ehandle(edict_t* pEntity, int offset)
{
if (FNullEnt(pEntity) || !pEntity->pvPrivateData)
{
return 0;
}
edict_t* pEdict = *(edict_t **)((char *)(pEntity->pvPrivateData) + offset);
if (!pEdict)
{
return 0;
}
static edict_t* pWorld = nullptr;
if (!pWorld)
{
pWorld = INDEXENT(0);
}
int index = pEdict - pWorld;
if (index < 0 || index > gpGlobals->maxEntities)
{
return 0;
}
if (pEdict->free || !pEdict->pvPrivateData)
{
return 0;
}
int serialnumber = *(int *)((char *)pEntity->pvPrivateData + offset + 4);
if (pEdict->serialnumber != serialnumber)
{
return 0;
}
return index;
}
void Client_Damage(void* mValue){ void Client_Damage(void* mValue){
switch (mState++) { switch (mState++) {
case 1: case 1:
@ -144,15 +187,20 @@ void Client_Damage(void* mValue){
case 'e': case 'e':
weapon = TFC_WPN_TIMER; // TFC_WPN_MEDKIT ?? weapon = TFC_WPN_TIMER; // TFC_WPN_MEDKIT ??
tempInt = *( (int*)mPlayer->pEdict->pvPrivateData + pdTimerOwner ); tempInt = get_pdata_ehandle(mPlayer->pEdict, pdTimerOwner * 4); // function is char-based.
if (!tempInt)
if (tempInt < 1 || tempInt > gpGlobals->maxClients)
{
break; break;
tempEnt = (edict_t*)tempInt; }
pAttacker = GET_PLAYER_POINTER(tempEnt);
pAttacker = GET_PLAYER_POINTER_I(tempInt);
if ( pAttacker->teamId == mPlayer->teamId ) // ???
if (pAttacker->teamId == mPlayer->teamId) // ???
{
ignoreDamage = true; ignoreDamage = true;
}
pAttacker->saveShot(weapon); // ??? save shot too pAttacker->saveShot(weapon); // ??? save shot too
break; break;
case 'f': case 'f':
@ -174,12 +222,16 @@ void Client_Damage(void* mValue){
} }
} }
else { // nailgrenade , mirvgrenade , normalgrenade , rockets else { // nailgrenade , mirvgrenade , normalgrenade , rockets
if ( strstr("sentrygun",STRING(enemy->v.classname)) ){ if ( strstr("sentrygun",STRING(enemy->v.classname)) )
tempInt = *( (int*)enemy->pvPrivateData + pdSentryGunOwner ); {
if ( !tempInt ) tempInt = get_pdata_ehandle(mPlayer->pEdict, pdSentryGunOwner * 4); // function is char-based.
if (tempInt < 1 || tempInt > gpGlobals->maxClients)
{
break; break;
tempEnt = (edict_t*)tempInt; }
pAttacker = GET_PLAYER_POINTER(tempEnt);
pAttacker = GET_PLAYER_POINTER_I(tempInt);
weapon = TFC_WPN_SENTRYGUN; weapon = TFC_WPN_SENTRYGUN;
pAttacker->saveShot(weapon); // save shot too pAttacker->saveShot(weapon); // save shot too
pAttacker->saveHit( mPlayer , weapon , damage, aim ); pAttacker->saveHit( mPlayer , weapon , damage, aim );