qzdoom/wadsrc/static/zscript/doom/cacodemon.txt
Christoph Oelckers a210aaea3e - 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.
2017-06-06 09:12:58 +02:00

119 lines
2 KiB
Text

//===========================================================================
//
// Cacodemon
//
//===========================================================================
class Cacodemon : Actor
{
Default
{
Health 400;
Radius 31;
Height 56;
Mass 400;
Speed 8;
PainChance 128;
Monster;
+FLOAT +NOGRAVITY
SeeSound "caco/sight";
PainSound "caco/pain";
DeathSound "caco/death";
ActiveSound "caco/active";
Obituary "$OB_CACO";
HitObituary "$OB_CACOHIT";
}
States
{
Spawn:
HEAD A 10 A_Look;
Loop;
See:
HEAD A 3 A_Chase;
Loop;
Missile:
HEAD B 5 A_FaceTarget;
HEAD C 5 A_FaceTarget;
HEAD D 5 BRIGHT A_HeadAttack;
Goto See;
Pain:
HEAD E 3;
HEAD E 3 A_Pain;
HEAD F 6;
Goto See;
Death:
HEAD G 8;
HEAD H 8 A_Scream;
HEAD I 8;
HEAD J 8;
HEAD K 8 A_NoBlocking;
HEAD L -1 A_SetFloorClip;
Stop;
Raise:
HEAD L 8 A_UnSetFloorClip;
HEAD KJIHG 8;
Goto See;
}
}
//===========================================================================
//
// Cacodemon plasma ball
//
//===========================================================================
class CacodemonBall : Actor
{
Default
{
Radius 6;
Height 8;
Speed 10;
FastSpeed 20;
Damage 5;
Projectile;
+RANDOMIZE
+ZDOOMTRANS
RenderStyle "Add";
Alpha 1;
SeeSound "caco/attack";
DeathSound "caco/shotx";
}
States
{
Spawn:
BAL2 AB 4 BRIGHT;
Loop;
Death:
BAL2 CDE 6 BRIGHT;
Stop;
}
}
//===========================================================================
//
// Code (must be attached to Actor)
//
//===========================================================================
extend class Actor
{
void A_HeadAttack()
{
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");
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
}
else
{
// launch a missile
SpawnMissile (targ, "CacodemonBall");
}
}
}
}