From 623276f5a643fecd4f3a387dbbd8037dbc49a1d5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 26 Jan 2016 09:43:47 +0100 Subject: [PATCH] - fixed: All access to weapon info in DECORATE functions should be restricted to when they get called from an actual weapon, not from a CustomInventory item. Issues this fixes: * all original Doom attack functions unconditionally altered the flash state. * A_FireOldBFG, A_RailAttack and A_Blast never checked for a valid ReadyWeapon. * CustomInventory items could deplete an unrelated weapon's ammo. --- src/g_doom/a_doomweaps.cpp | 39 +++++++++++++++++-------------- src/g_hexen/a_blastradius.cpp | 4 ++-- src/thingdef/thingdef.h | 2 +- src/thingdef/thingdef_codeptr.cpp | 6 ++--- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 4021ad206..283cf8323 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -36,7 +36,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch) if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO)) + if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; @@ -73,7 +73,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol) if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -148,7 +148,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) slope = P_AimLineAttack (self, angle, Range, &linetarget) + (pr_saw.Random2() * (Spread_Z / 255)); AWeapon *weapon = self->player->ReadyWeapon; - if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO)) + if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; @@ -250,7 +250,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -281,7 +281,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2)) return; @@ -390,7 +390,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) } AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -431,7 +431,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile) return; } AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -454,7 +454,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade) return; } AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; @@ -479,7 +479,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma) return; } AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -497,7 +497,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma) // // [RH] A_FireRailgun // -static void FireRailgun(AActor *self, int offset_xy) +static void FireRailgun(AActor *self, int offset_xy, bool fromweapon) { int damage; player_t *player; @@ -508,7 +508,7 @@ static void FireRailgun(AActor *self, int offset_xy) } AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && fromweapon) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; @@ -528,17 +528,17 @@ static void FireRailgun(AActor *self, int offset_xy) DEFINE_ACTION_FUNCTION(AActor, A_FireRailgun) { - FireRailgun(self, 0); + FireRailgun(self, 0, ACTION_CALL_FROM_WEAPON()); } DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunRight) { - FireRailgun(self, 10); + FireRailgun(self, 10, ACTION_CALL_FROM_WEAPON()); } DEFINE_ACTION_FUNCTION(AActor, A_FireRailgunLeft) { - FireRailgun(self, -10); + FireRailgun(self, -10, ACTION_CALL_FROM_WEAPON()); } DEFINE_ACTION_FUNCTION(AActor, A_RailWait) @@ -560,7 +560,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG) } AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) + if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, deh.BFGCells)) return; @@ -671,6 +671,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) AActor * mo = NULL; player_t *player; + bool doesautoaim = false; if (NULL == (player = self->player)) { @@ -678,18 +679,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) } AWeapon *weapon = self->player->ReadyWeapon; + if (ACTION_CALL_FROM_WEAPON()) weapon = NULL; if (weapon != NULL) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return; + + doesautoaim = !(weapon->WeaponFlags & WIF_NOAUTOAIM); + weapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun } self->player->extralight = 2; // Save values temporarily angle_t SavedPlayerAngle = self->angle; fixed_t SavedPlayerPitch = self->pitch; - bool doesautoaim = !(self->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM); - self->player->ReadyWeapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence { self->angle += ((pr_oldbfg()&127) - 64) * (ANG90/768); @@ -699,5 +702,5 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) self->angle = SavedPlayerAngle; self->pitch = SavedPlayerPitch; } - if (doesautoaim) self->player->ReadyWeapon->WeaponFlags &= ~WIF_NOAUTOAIM; // Restore autoaim setting + if (doesautoaim && weapon != NULL) weapon->WeaponFlags &= ~WIF_NOAUTOAIM; // Restore autoaim setting } diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index c7d962e12..bbd87c87d 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -109,10 +109,10 @@ DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) TThinkerIterator iterator; fixed_t dist; - if (self->player && (blastflags & BF_USEAMMO)) + if (self->player && (blastflags & BF_USEAMMO) && ACTION_CALL_FROM_WEAPON()) { AWeapon * weapon = self->player->ReadyWeapon; - if (!weapon->DepleteAmmo(weapon->bAltFire)) + if (weapon != NULL && !weapon->DepleteAmmo(weapon->bAltFire)) return; } diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 5225b787a..e60c746cd 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -382,7 +382,7 @@ struct StateCallData void AF_##name (AActor *self, AActor *stateowner, FState *, int, StateCallData *); \ static AFuncDesc info_##cls##_##name = { #name, AF_##name }; \ MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \ - void AF_##name (AActor *self, AActor *stateowner, FState *, int, StateCallData *statecall) + void AF_##name (AActor *self, AActor *stateowner, FState *CallingState, int, StateCallData *statecall) #define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) \ void AFP_##name (AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall); \ diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 6926c1fac..8ca30621b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1261,7 +1261,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) int bslope = 0; int laflags = (flags & FBF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; - if ((flags & FBF_USEAMMO) && weapon) + if ((flags & FBF_USEAMMO) && weapon && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo @@ -1450,7 +1450,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) pitch = P_AimLineAttack (self, angle, range, &linetarget); // only use ammo when actually hitting something! - if ((flags & CPF_USEAMMO) && linetarget && weapon) + if ((flags & CPF_USEAMMO) && linetarget && weapon && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo @@ -1548,7 +1548,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack) AWeapon *weapon = self->player->ReadyWeapon; // only use ammo when actually hitting something! - if (useammo) + if (useammo && weapon != NULL && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo