// Wraith ------------------------------------------------------------------- class Wraith : Actor { Default { Health 150; PainChance 25; Speed 11; Height 55; Mass 75; Damage 10; Monster; +NOGRAVITY +DROPOFF +FLOAT +FLOORCLIP +TELESTOMP SeeSound "WraithSight"; AttackSound "WraithAttack"; PainSound "WraithPain"; DeathSound "WraithDeath"; ActiveSound "WraithActive"; HitObituary "$OB_WRAITHHIT"; Obituary "$OB_WRAITH"; } States { Spawn: WRTH A 10; WRTH B 5 A_WraithInit; Goto Look; Look: WRTH AB 15 A_Look; Loop; See: WRTH ABCD 4 A_WraithChase; Loop; Pain: WRTH A 2; WRTH H 6 A_Pain; Goto See; Melee: WRTH E 6 A_FaceTarget; WRTH F 6 A_WraithFX3; WRTH G 6 A_WraithMelee; Goto See; Missile: WRTH E 6 A_FaceTarget; WRTH F 6; WRTH G 6 A_SpawnProjectile("WraithFX1"); Goto See; Death: WRTH I 4; WRTH J 4 A_Scream; WRTH KL 4; WRTH M 4 A_NoBlocking; WRTH N 4 A_QueueCorpse; WRTH O 4; WRTH PQ 5; WRTH R -1; Stop; XDeath: WRT2 A 5; WRT2 B 5 A_Scream; WRT2 CD 5; WRT2 E 5 A_NoBlocking; WRT2 F 5 A_QueueCorpse; WRT2 G 5; WRT2 H -1; Stop; Ice: WRT2 I 5 A_FreezeDeath; WRT2 I 1 A_FreezeDeathChunks; Wait; } //============================================================================ // // A_WraithInit // //============================================================================ void A_WraithInit() { AddZ(48); // [RH] Make sure the wraith didn't go into the ceiling if (pos.z + height > ceilingz) { SetZ(ceilingz - Height); } WeaveIndexZ = 0; // index into floatbob } //============================================================================ // // A_WraithChase // //============================================================================ void A_WraithChase() { int weaveindex = WeaveIndexZ; AddZ(BobSin(weaveindex)); WeaveIndexZ = (weaveindex + 2) & 63; A_Chase (); A_WraithFX4 (); } //============================================================================ // // A_WraithFX3 // // Spawn an FX3 around the wraith during attacks // //============================================================================ void A_WraithFX3() { int numdropped = random[WraithFX3](0,14); while (numdropped-- > 0) { double xo = (random[WraithFX3]() - 128) / 32.; double yo = (random[WraithFX3]() - 128) / 32.; double zo = random[WraithFX3]() / 64.; Actor mo = Spawn("WraithFX3", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); if (mo) { mo.floorz = floorz; mo.ceilingz = ceilingz; mo.target = self; } } } //============================================================================ // // A_WraithFX4 // // Spawn an FX4 during movement // //============================================================================ void A_WraithFX4 () { int chance = random[WraithFX4](); bool spawn4, spawn5; if (chance < 10) { spawn4 = true; spawn5 = false; } else if (chance < 20) { spawn4 = false; spawn5 = true; } else if (chance < 25) { spawn4 = true; spawn5 = true; } else { spawn4 = false; spawn5 = false; } if (spawn4) { double xo = (random[WraithFX4]() - 128) / 16.; double yo = (random[WraithFX4]() - 128) / 16.; double zo = (random[WraithFX4]() / 64.); Actor mo = Spawn ("WraithFX4", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); if (mo) { mo.floorz = floorz; mo.ceilingz = ceilingz; mo.target = self; } } if (spawn5) { double xo = (random[WraithFX4]() - 128) / 32.; double yo = (random[WraithFX4]() - 128) / 32.; double zo = (random[WraithFX4]() / 64.); Actor mo = Spawn ("WraithFX5", Vec3Offset(xo, yo, zo), ALLOW_REPLACE); if (mo) { mo.floorz = floorz; mo.ceilingz = ceilingz; mo.target = self; } } } //============================================================================ // // A_WraithMelee // //============================================================================ void A_WraithMelee() { // Steal health from target and give to self if (CheckMeleeRange() && (random[StealHealth]()<220)) { int amount = random[StealHealth](1, 8) * 2; target.DamageMobj (self, self, amount, 'Melee'); health += amount; } } } // Buried wraith ------------------------------------------------------------ class WraithBuried : Wraith { Default { Height 68; -SHOOTABLE -SOLID +DONTMORPH +DONTBLAST +SPECIALFLOORCLIP +STAYMORPHED +INVISIBLE PainChance 0; } States { Spawn: Goto Super::Look; See: WRTH A 2 A_WraithRaiseInit; WRTH A 2 A_WraithRaise; WRTH A 2 A_FaceTarget; WRTH BB 2 A_WraithRaise; Goto See + 1; Chase: Goto Super::See; } //============================================================================ // // A_WraithRaiseInit // //============================================================================ void A_WraithRaiseInit() { bInvisible = false; bNonShootable = false; bDontBlast = false; bShootable = true; bSolid = true; Floorclip = Height; } //============================================================================ // // A_WraithRaise // //============================================================================ void A_WraithRaise() { if (RaiseMobj (2)) { // Reached it's target height // [RH] Once a buried wraith is fully raised, it should be // morphable, right? bDontMorph = false; bSpecialFloorClip = false; SetStateLabel ("Chase"); // [RH] Reset PainChance to a normal wraith's. PainChance = GetDefaultByType("Wraith").PainChance; } SpawnDirt (radius); } } // Wraith FX 1 -------------------------------------------------------------- class WraithFX1 : Actor { Default { Speed 14; Radius 10; Height 6; Mass 5; Damage 5; DamageType "Fire"; Projectile; +FLOORCLIP SeeSound "WraithMissileFire"; DeathSound "WraithMissileExplode"; } States { Spawn: WRBL A 3 Bright; WRBL B 3 Bright A_WraithFX2; WRBL C 3 Bright; Loop; Death: WRBL D 4 Bright; WRBL E 4 Bright A_WraithFX2; WRBL F 4 Bright; WRBL GH 3 Bright A_WraithFX2; WRBL I 3 Bright; Stop; } //============================================================================ // // A_WraithFX2 - spawns sparkle tail of missile // //============================================================================ void A_WraithFX2() { for (int i = 2; i; --i) { Actor mo = Spawn ("WraithFX2", Pos, ALLOW_REPLACE); if(mo) { double newangle = random[WraithFX2]() * (360 / 1024.f); if (random[WraithFX2]() >= 128) { newangle = -newangle; } newangle += angle; mo.Vel.X = ((random[WraithFX2]() / 512.) + 1) * cos(newangle); mo.Vel.Y = ((random[WraithFX2]() / 512.) + 1) * sin(newangle); mo.Vel.Z = 0; mo.target = self; mo.Floorclip = 10; } } } } // Wraith FX 2 -------------------------------------------------------------- class WraithFX2 : Actor { Default { Radius 2; Height 5; Mass 5; +NOBLOCKMAP +DROPOFF +FLOORCLIP +NOTELEPORT } States { Spawn: WRBL JKLMNOP 4 Bright; Stop; } } // Wraith FX 3 -------------------------------------------------------------- class WraithFX3 : Actor { Default { Radius 2; Height 5; Mass 5; +NOBLOCKMAP +DROPOFF +MISSILE +FLOORCLIP +NOTELEPORT DeathSound "Drip"; } States { Spawn: WRBL QRS 4 Bright; Loop; Death: WRBL S 4 Bright; Stop; } } // Wraith FX 4 -------------------------------------------------------------- class WraithFX4 : Actor { Default { Radius 2; Height 5; Mass 5; +NOBLOCKMAP +DROPOFF +MISSILE +NOTELEPORT DeathSound "Drip"; } States { Spawn: WRBL TUVW 4; Loop; Death: WRBL W 10; Stop; } } // Wraith FX 5 -------------------------------------------------------------- class WraithFX5 : WraithFX4 { States { Spawn: WRBL XYZ 7; Loop; Death: WRBL Z 35; Stop; } }