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

@ -20,9 +20,11 @@
#if defined(_WIN32)
#define LINUXOFFSET 0
#define PLAYER_LINUXOFFSET 0
#define CLIP_LINUXOFFSET 0
#else
#define LINUXOFFSET 4
#define PLAYER_LINUXOFFSET 5
#define CLIP_LINUXOFFSET 4
#endif
@ -32,7 +34,7 @@
#define PD_HAS_GOALITEM 26 + LINUXOFFSET
#define PD_GOALITEM_TEAM 36 + 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
// disassembling CBaseEntity::KeyValuePartThree(KeyValueData_s *)

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){
switch (mState++) {
case 1:
@ -144,14 +187,19 @@ void Client_Damage(void* mValue){
case 'e':
weapon = TFC_WPN_TIMER; // TFC_WPN_MEDKIT ??
tempInt = *( (int*)mPlayer->pEdict->pvPrivateData + pdTimerOwner );
if (!tempInt)
break;
tempEnt = (edict_t*)tempInt;
pAttacker = GET_PLAYER_POINTER(tempEnt);
tempInt = get_pdata_ehandle(mPlayer->pEdict, pdTimerOwner * 4); // function is char-based.
if ( pAttacker->teamId == mPlayer->teamId ) // ???
if (tempInt < 1 || tempInt > gpGlobals->maxClients)
{
break;
}
pAttacker = GET_PLAYER_POINTER_I(tempInt);
if (pAttacker->teamId == mPlayer->teamId) // ???
{
ignoreDamage = true;
}
pAttacker->saveShot(weapon); // ??? save shot too
break;
@ -174,12 +222,16 @@ void Client_Damage(void* mValue){
}
}
else { // nailgrenade , mirvgrenade , normalgrenade , rockets
if ( strstr("sentrygun",STRING(enemy->v.classname)) ){
tempInt = *( (int*)enemy->pvPrivateData + pdSentryGunOwner );
if ( !tempInt )
if ( strstr("sentrygun",STRING(enemy->v.classname)) )
{
tempInt = get_pdata_ehandle(mPlayer->pEdict, pdSentryGunOwner * 4); // function is char-based.
if (tempInt < 1 || tempInt > gpGlobals->maxClients)
{
break;
tempEnt = (edict_t*)tempInt;
pAttacker = GET_PLAYER_POINTER(tempEnt);
}
pAttacker = GET_PLAYER_POINTER_I(tempInt);
weapon = TFC_WPN_SENTRYGUN;
pAttacker->saveShot(weapon); // save shot too
pAttacker->saveHit( mPlayer , weapon , damage, aim );