mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
- fixed: All melee functions calling TraceBleed after DamageMobj must first copy the target member to a local variable.
DamageMobj can destroy the damaged actor if the death state sequence has zero duration. But Actor.target is a garbage collected member variable, i.e. it will be null, once the actor it points to gets destroyed. This was originally done correctly in the C++ code but during the scriptification all those 'AActor *target = self->target' lines were removed because they looked redundant, but were not.
This commit is contained in:
parent
c698f10257
commit
a210aaea3e
16 changed files with 99 additions and 80 deletions
|
@ -904,22 +904,23 @@ class Actor : Thinker native
|
|||
|
||||
private void DoAttack (bool domelee, bool domissile, int MeleeDamage, Sound MeleeSound, Class<Actor> MissileType,double MissileHeight)
|
||||
{
|
||||
if (target == NULL) return;
|
||||
let targ = target;
|
||||
if (targ == NULL) return;
|
||||
|
||||
A_FaceTarget ();
|
||||
if (domelee && MeleeDamage>0 && CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[CustomMelee](1, 8) * MeleeDamage;
|
||||
if (MeleeSound) A_PlaySound (MeleeSound, CHAN_WEAPON);
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else if (domissile && MissileType != NULL)
|
||||
{
|
||||
// This seemingly senseless code is needed for proper aiming.
|
||||
double add = MissileHeight + GetBobOffset() - 32;
|
||||
AddZ(add);
|
||||
Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), target, MissileType, false);
|
||||
Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), targ, MissileType, false);
|
||||
AddZ(-add);
|
||||
|
||||
if (missile)
|
||||
|
@ -927,7 +928,7 @@ class Actor : Thinker native
|
|||
// automatic handling of seeker missiles
|
||||
if (missile.bSeekerMissile)
|
||||
{
|
||||
missile.tracer = target;
|
||||
missile.tracer = targ;
|
||||
}
|
||||
missile.CheckMissileSpawn(radius);
|
||||
}
|
||||
|
|
|
@ -149,14 +149,15 @@ extend class Actor
|
|||
{
|
||||
void A_BruisAttack()
|
||||
{
|
||||
if (target)
|
||||
let targ = target;
|
||||
if (targ)
|
||||
{
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[pr_bruisattack](1, 8) * 10;
|
||||
A_PlaySound ("baron/melee", CHAN_WEAPON);
|
||||
int newdam = target.DamageMobj (self, self, damage, "Melee");
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -99,19 +99,20 @@ extend class Actor
|
|||
{
|
||||
void A_HeadAttack()
|
||||
{
|
||||
if (target)
|
||||
let targ = target;
|
||||
if (targ)
|
||||
{
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[pr_headattack](1, 6) * 10;
|
||||
A_PlaySound (AttackSound, CHAN_WEAPON);
|
||||
int newdam = target.DamageMobj (self, self, damage, "Melee");
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
// launch a missile
|
||||
SpawnMissile (target, "CacodemonBall");
|
||||
SpawnMissile (targ, "CacodemonBall");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,11 +85,12 @@ extend class Actor
|
|||
{
|
||||
void A_SargAttack()
|
||||
{
|
||||
if (target && CheckMeleeRange())
|
||||
let targ = target;
|
||||
if (targ && CheckMeleeRange())
|
||||
{
|
||||
int damage = random[pr_sargattack](1, 10) * 4;
|
||||
int newdam = target.DamageMobj (self, self, damage, "Melee");
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, "Melee");
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,19 +104,20 @@ extend class Actor
|
|||
{
|
||||
void A_TroopAttack()
|
||||
{
|
||||
if (target)
|
||||
let targ = target;
|
||||
if (targ)
|
||||
{
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[pr_troopattack](1, 8) * 3;
|
||||
A_PlaySound ("imp/melee", CHAN_WEAPON);
|
||||
int newdam = target.DamageMobj (self, self, damage, "Melee");
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, "Melee");
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
// launch a missile
|
||||
SpawnMissile (target, "DoomImpBall");
|
||||
SpawnMissile (targ, "DoomImpBall");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,15 +154,16 @@ extend class Actor
|
|||
|
||||
void A_SkelFist()
|
||||
{
|
||||
if (target == null) return;
|
||||
let targ = target;
|
||||
if (targ == null) return;
|
||||
A_FaceTarget();
|
||||
|
||||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[SkelFist](1, 10) * 6;
|
||||
A_PlaySound("skeleton/melee", CHAN_WEAPON);
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,8 @@ class Sorcerer1 : Actor
|
|||
|
||||
void A_Srcr1Attack ()
|
||||
{
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -123,18 +124,18 @@ class Sorcerer1 : Actor
|
|||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[Srcr1Attack](1,8) * 8;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (health > (SpawnHealth()/3)*2)
|
||||
{ // Spit one fireball
|
||||
SpawnMissileZ (pos.z + 48, target, "SorcererFX1");
|
||||
SpawnMissileZ (pos.z + 48, targ, "SorcererFX1");
|
||||
}
|
||||
else
|
||||
{ // Spit three fireballs
|
||||
Actor mo = SpawnMissileZ (pos.z + 48, target, "SorcererFX1");
|
||||
Actor mo = SpawnMissileZ (pos.z + 48, targ, "SorcererFX1");
|
||||
if (mo != null)
|
||||
{
|
||||
double ang = mo.angle;
|
||||
|
@ -343,7 +344,8 @@ class Sorcerer2 : Actor
|
|||
|
||||
void A_Srcr2Attack ()
|
||||
{
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -351,8 +353,8 @@ class Sorcerer2 : Actor
|
|||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[Srcr2Atk](1, 8) * 20;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
int chance = health < SpawnHealth()/2 ? 96 : 48;
|
||||
|
@ -364,7 +366,7 @@ class Sorcerer2 : Actor
|
|||
}
|
||||
else
|
||||
{ // Blue bolt
|
||||
SpawnMissile (target, "Sorcerer2FX1");
|
||||
SpawnMissile (targ, "Sorcerer2FX1");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ class Ironlich : Actor
|
|||
// Whirlwind (close 40% : far 20%)
|
||||
// Distance threshold = 8 cells
|
||||
|
||||
if (target == null)
|
||||
let targ = target;
|
||||
if (targ == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -78,20 +79,20 @@ class Ironlich : Actor
|
|||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[LichAttack](1, 8) * 6;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
int dist = Distance2D(target) > 8 * 64;
|
||||
int dist = Distance2D(targ) > 8 * 64;
|
||||
int randAttack = random[LichAttack]();
|
||||
if (randAttack < atkResolve1[dist])
|
||||
{ // Ice ball
|
||||
SpawnMissile (target, "HeadFX1");
|
||||
SpawnMissile (targ, "HeadFX1");
|
||||
A_PlaySound ("ironlich/attack2", CHAN_BODY);
|
||||
}
|
||||
else if (randAttack < atkResolve2[dist])
|
||||
{ // Fire column
|
||||
Actor baseFire = SpawnMissile (target, "HeadFX3");
|
||||
Actor baseFire = SpawnMissile (targ, "HeadFX3");
|
||||
if (baseFire != null)
|
||||
{
|
||||
baseFire.SetStateLabel("NoGrow");
|
||||
|
@ -116,11 +117,11 @@ class Ironlich : Actor
|
|||
}
|
||||
else
|
||||
{ // Whirlwind
|
||||
Actor mo = SpawnMissile (target, "Whirlwind");
|
||||
Actor mo = SpawnMissile (targ, "Whirlwind");
|
||||
if (mo != null)
|
||||
{
|
||||
mo.AddZ(-32);
|
||||
mo.tracer = target;
|
||||
mo.tracer = targ;
|
||||
mo.health = 20*TICRATE; // Duration
|
||||
A_PlaySound ("ironlich/attack3", CHAN_BODY);
|
||||
}
|
||||
|
|
|
@ -62,12 +62,13 @@ class Knight : Actor
|
|||
|
||||
void A_KnightAttack ()
|
||||
{
|
||||
if (!target) return;
|
||||
let targ = target;
|
||||
if (!targ) return;
|
||||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[KnightAttack](1, 8) * 3;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
A_PlaySound ("hknight/melee", CHAN_BODY);
|
||||
return;
|
||||
}
|
||||
|
@ -75,11 +76,11 @@ class Knight : Actor
|
|||
A_PlaySound (AttackSound, CHAN_BODY);
|
||||
if (self.bShadow || random[KnightAttack]() < 40)
|
||||
{ // Red axe
|
||||
SpawnMissileZ (pos.Z + 36, target, "RedAxe");
|
||||
SpawnMissileZ (pos.Z + 36, targ, "RedAxe");
|
||||
}
|
||||
else
|
||||
{ // Green axe
|
||||
SpawnMissileZ (pos.Z + 36, target, "KnightAxe");
|
||||
SpawnMissileZ (pos.Z + 36, targ, "KnightAxe");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,16 +112,17 @@ class Wizard : Actor
|
|||
void A_WizAtk3 ()
|
||||
{
|
||||
A_GhostOff();
|
||||
if (!target) return;
|
||||
let targ = target;
|
||||
if (!targ) return;
|
||||
A_PlaySound (AttackSound, CHAN_WEAPON);
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[WizAtk3](1, 8) * 4;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
Actor mo = SpawnMissile (target, "WizardFX1");
|
||||
Actor mo = SpawnMissile (targ, "WizardFX1");
|
||||
if (mo != null)
|
||||
{
|
||||
SpawnMissileAngle("WizardFX1", mo.Angle - 45. / 8, mo.Vel.Z);
|
||||
|
|
|
@ -82,7 +82,8 @@ class Bishop : Actor
|
|||
|
||||
void A_BishopAttack()
|
||||
{
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -90,8 +91,8 @@ class Bishop : Actor
|
|||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[BishopAttack](1, 8) * 4;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
missilecount = (random[BishopAttack]() & 3) + 5;
|
||||
|
|
|
@ -109,8 +109,8 @@ class Dragon : Actor
|
|||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[DragonSeek](1, 8) * 10;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
A_PlaySound (AttackSound, CHAN_WEAPON);
|
||||
}
|
||||
else if (random[DragonSeek]() < 128 && CheckMissileRange())
|
||||
|
@ -210,7 +210,8 @@ class Dragon : Actor
|
|||
double ang;
|
||||
|
||||
DragonSeek (4., 8.);
|
||||
if (target)
|
||||
let targ = target;
|
||||
if (targ)
|
||||
{
|
||||
if(!target.bShootable)
|
||||
{ // target died
|
||||
|
@ -221,8 +222,8 @@ class Dragon : Actor
|
|||
if (ang <22.5 && CheckMeleeRange())
|
||||
{
|
||||
int damage = random[DragonFlight](1, 8) * 8;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
A_PlaySound (AttackSound, CHAN_WEAPON);
|
||||
}
|
||||
else if (ang <= 20)
|
||||
|
|
|
@ -240,15 +240,16 @@ class Serpent : Actor
|
|||
|
||||
void A_SerpentMeleeAttack()
|
||||
{
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[SerpentAttack](1, 8) * 5;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
A_PlaySound ("SerpentMeleeHit", CHAN_BODY);
|
||||
}
|
||||
if (random[SerpentAttack]() < 96)
|
||||
|
|
|
@ -178,25 +178,26 @@ class ThrustFloor : Actor
|
|||
BlockThingsIterator it = BlockThingsIterator.Create(self);
|
||||
while (it.Next())
|
||||
{
|
||||
let targ = it.thing;
|
||||
double blockdist = radius + it.thing.radius;
|
||||
if (abs(it.thing.pos.x - it.Position.X) >= blockdist || abs(it.thing.pos.y - it.Position.Y) >= blockdist)
|
||||
if (abs(targ.pos.x - it.Position.X) >= blockdist || abs(targ.pos.y - it.Position.Y) >= blockdist)
|
||||
continue;
|
||||
|
||||
// Q: Make this z-aware for everything? It never was before.
|
||||
if (it.thing.pos.z + it.thing.height < pos.z || it.thing.pos.z > pos.z + height)
|
||||
if (targ.pos.z + targ.height < pos.z || targ.pos.z > pos.z + height)
|
||||
{
|
||||
if (CurSector.PortalGroup != it.thing.CurSector.PortalGroup)
|
||||
if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!it.thing.bShootable)
|
||||
if (!targ.bShootable)
|
||||
continue;
|
||||
|
||||
if (it.thing == self)
|
||||
if (targ == self)
|
||||
continue; // don't clip against self
|
||||
|
||||
int newdam = it.thing.DamageMobj (self, self, 10001, 'Crush');
|
||||
it.thing.TraceBleed (newdam > 0 ? newdam : 10001, null);
|
||||
int newdam = targ.DamageMobj (self, self, 10001, 'Crush');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : 10001, null);
|
||||
args[1] = 1; // Mark thrust thing as bloody
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,18 +165,19 @@ class Minotaur : Actor
|
|||
|
||||
void A_MinotaurAtk1()
|
||||
{
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
A_PlaySound ("minotaur/melee", CHAN_WEAPON);
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
PlayerInfo player = targ.player;
|
||||
int damage = random[MinotaurAtk1](1, 8) * 4;
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
PlayerInfo player = target.player;
|
||||
if (player != null && player.mo == target)
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
if (player != null && player.mo == targ)
|
||||
{ // Squish the player
|
||||
player.deltaviewheight = -16;
|
||||
}
|
||||
|
@ -284,7 +285,8 @@ class Minotaur : Actor
|
|||
{
|
||||
bool friendly = bSummonedMonster;
|
||||
|
||||
if (target == null)
|
||||
let targ = target;
|
||||
if (targ == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -292,13 +294,13 @@ class Minotaur : Actor
|
|||
if (CheckMeleeRange())
|
||||
{
|
||||
int damage = random[MinotaurAtk2](1, 8) * (friendly ? 3 : 5);
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
return;
|
||||
}
|
||||
double z = pos.z + 40;
|
||||
Class<Actor> fx = "MinotaurFX1";
|
||||
Actor mo = SpawnMissileZ (z, target, fx);
|
||||
Actor mo = SpawnMissileZ (z, targ, fx);
|
||||
if (mo != null)
|
||||
{
|
||||
// S_Sound (mo, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM);
|
||||
|
@ -323,18 +325,19 @@ class Minotaur : Actor
|
|||
{
|
||||
bool friendly = bSummonedMonster;
|
||||
|
||||
if (!target)
|
||||
let targ = target;
|
||||
if (!targ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
A_PlaySound ("minotaur/attack3", CHAN_VOICE);
|
||||
if (CheckMeleeRange())
|
||||
{
|
||||
PlayerInfo player = targ.player;
|
||||
int damage = random[MinotaurAtk3](1, 8) * (friendly ? 3 : 5);
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
PlayerInfo player = target.player;
|
||||
if (player != null && player.mo == target)
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
if (player != null && player.mo == targ)
|
||||
{ // Squish the player
|
||||
player.deltaviewheight = -16;
|
||||
}
|
||||
|
|
|
@ -117,10 +117,11 @@ class Stalker : Actor
|
|||
A_FaceTarget ();
|
||||
if (CheckMeleeRange ())
|
||||
{
|
||||
let targ = target;
|
||||
int damage = (random[Stalker]() & 7) * 2 + 2;
|
||||
|
||||
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue