- scriptified Hexen's Wraith and parts of the Spike.

This commit is contained in:
Christoph Oelckers 2016-11-17 00:44:43 +01:00
parent df43ee96ce
commit 21a1d5ffc8
12 changed files with 354 additions and 444 deletions

View file

@ -900,7 +900,6 @@ set( NOT_COMPILED_SOURCE_FILES
g_hexen/a_spike.cpp g_hexen/a_spike.cpp
g_hexen/a_summon.cpp g_hexen/a_summon.cpp
g_hexen/a_teleportother.cpp g_hexen/a_teleportother.cpp
g_hexen/a_wraith.cpp
g_strife/a_acolyte.cpp g_strife/a_acolyte.cpp
g_strife/a_alienspectres.cpp g_strife/a_alienspectres.cpp
g_strife/a_coin.cpp g_strife/a_coin.cpp

View file

@ -52,4 +52,3 @@
#include "a_spike.cpp" #include "a_spike.cpp"
#include "a_summon.cpp" #include "a_summon.cpp"
#include "a_teleportother.cpp" #include "a_teleportother.cpp"
#include "a_wraith.cpp"

View file

@ -20,28 +20,13 @@ static FRandom pr_thrustraise ("ThrustRaise");
class AThrustFloor : public AActor class AThrustFloor : public AActor
{ {
DECLARE_CLASS (AThrustFloor, AActor) DECLARE_CLASS (AThrustFloor, AActor)
HAS_OBJECT_POINTERS
public: public:
void Serialize(FSerializer &arc);
void Activate (AActor *activator); void Activate (AActor *activator);
void Deactivate (AActor *activator); void Deactivate (AActor *activator);
TObjPtr<AActor> DirtClump;
}; };
IMPLEMENT_CLASS(AThrustFloor, false, true, false, false) IMPLEMENT_CLASS(AThrustFloor, false, false, false, false)
IMPLEMENT_POINTERS_START(AThrustFloor)
IMPLEMENT_POINTER(DirtClump)
IMPLEMENT_POINTERS_END
void AThrustFloor::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("dirtclump", DirtClump);
}
void AThrustFloor::Activate (AActor *activator) void AThrustFloor::Activate (AActor *activator)
{ {
@ -68,90 +53,6 @@ void AThrustFloor::Deactivate (AActor *activator)
} }
} }
//===========================================================================
//
// Thrust floor stuff
//
// Thrust Spike Variables
// DirtClump pointer to dirt clump actor
// special2 speed of raise
// args[0] 0 = lowered, 1 = raised
// args[1] 0 = normal, 1 = bloody
//===========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitUp)
{
PARAM_SELF_PROLOGUE(AActor);
self->special2 = 5; // Raise speed
self->args[0] = 1; // Mark as up
self->Floorclip = 0;
self->flags = MF_SOLID;
self->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP;
self->special1 = 0L;
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_ThrustInitDn)
{
PARAM_SELF_PROLOGUE(AActor);
self->special2 = 5; // Raise speed
self->args[0] = 0; // Mark as down
self->Floorclip = self->GetDefault()->Height;
self->flags = 0;
self->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP;
self->renderflags = RF_INVISIBLE;
static_cast<AThrustFloor *>(self)->DirtClump =
Spawn("DirtClump", self->Pos(), ALLOW_REPLACE);
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_ThrustRaise)
{
PARAM_SELF_PROLOGUE(AActor);
AThrustFloor *actor = static_cast<AThrustFloor *>(self);
if (A_RaiseMobj (actor, self->special2))
{ // Reached it's target height
actor->args[0] = 1;
if (actor->args[1])
actor->SetState (actor->FindState ("BloodThrustInit2"), true);
else
actor->SetState (actor->FindState ("ThrustInit2"), true);
}
// Lose the dirt clump
if ((actor->Floorclip < actor->Height) && actor->DirtClump)
{
actor->DirtClump->Destroy ();
actor->DirtClump = NULL;
}
// Spawn some dirt
if (pr_thrustraise()<40)
P_SpawnDirt (actor, actor->radius);
actor->special2++; // Increase raise speed
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_ThrustLower)
{
PARAM_SELF_PROLOGUE(AActor);
if (A_SinkMobj (self, 6))
{
self->args[0] = 0;
if (self->args[1])
self->SetState (self->FindState ("BloodThrustInit1"), true);
else
self->SetState (self->FindState ("ThrustInit1"), true);
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_ThrustImpale) DEFINE_ACTION_FUNCTION(AActor, A_ThrustImpale)
{ {
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);

View file

@ -1,258 +0,0 @@
/*
#include "actor.h"
#include "info.h"
#include "p_local.h"
#include "s_sound.h"
#include "p_enemy.h"
#include "a_action.h"
#include "m_random.h"
#include "a_sharedglobal.h"
#include "vm.h"
*/
static FRandom pr_stealhealth ("StealHealth");
static FRandom pr_wraithfx2 ("WraithFX2");
static FRandom pr_wraithfx3 ("WraithFX3");
static FRandom pr_wraithfx4 ("WraithFX4");
//============================================================================
//
// A_WraithInit
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithInit)
{
PARAM_SELF_PROLOGUE(AActor);
self->AddZ(48);
// [RH] Make sure the wraith didn't go into the ceiling
if (self->Top() > self->ceilingz)
{
self->SetZ(self->ceilingz - self->Height);
}
self->WeaveIndexZ = 0; // index into floatbob
return 0;
}
//============================================================================
//
// A_WraithRaiseInit
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithRaiseInit)
{
PARAM_SELF_PROLOGUE(AActor);
self->renderflags &= ~RF_INVISIBLE;
self->flags2 &= ~MF2_NONSHOOTABLE;
self->flags3 &= ~MF3_DONTBLAST;
self->flags |= MF_SHOOTABLE|MF_SOLID;
self->Floorclip = self->Height;
return 0;
}
//============================================================================
//
// A_WraithRaise
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithRaise)
{
PARAM_SELF_PROLOGUE(AActor);
if (A_RaiseMobj (self, 2))
{
// Reached it's target height
// [RH] Once a buried wraith is fully raised, it should be
// morphable, right?
self->flags3 &= ~(MF3_DONTMORPH|MF3_SPECIALFLOORCLIP);
self->SetState (self->FindState("Chase"));
// [RH] Reset PainChance to a normal wraith's.
self->PainChance = GetDefaultByName ("Wraith")->PainChance;
}
P_SpawnDirt (self, self->radius);
return 0;
}
//============================================================================
//
// A_WraithMelee
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithMelee)
{
PARAM_SELF_PROLOGUE(AActor);
int amount;
// Steal health from target and give to self
if (self->CheckMeleeRange() && (pr_stealhealth()<220))
{
amount = pr_stealhealth.HitDice (2);
P_DamageMobj (self->target, self, self, amount, NAME_Melee);
self->health += amount;
}
return 0;
}
//============================================================================
//
// A_WraithFX2 - spawns sparkle tail of missile
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithFX2)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *mo;
DAngle angle;
int i;
for (i = 2; i; --i)
{
mo = Spawn ("WraithFX2", self->Pos(), ALLOW_REPLACE);
if(mo)
{
angle = pr_wraithfx2() * (360 / 1024.f);
if (pr_wraithfx2() >= 128)
{
angle = -angle;
}
angle += self->Angles.Yaw;
mo->Vel.X = ((pr_wraithfx2() / 512.) + 1) * angle.Cos();
mo->Vel.Y = ((pr_wraithfx2() / 512.) + 1) * angle.Sin();
mo->Vel.Z = 0;
mo->target = self;
mo->Floorclip = 10;
}
}
return 0;
}
//============================================================================
//
// A_WraithFX3
//
// Spawn an FX3 around the self during attacks
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithFX3)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *mo;
int numdropped = pr_wraithfx3() % 15;
while (numdropped-- > 0)
{
double xo = (pr_wraithfx3() - 128) / 32.;
double yo = (pr_wraithfx3() - 128) / 32.;
double zo = pr_wraithfx3() / 64.;
mo = Spawn("WraithFX3", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)
{
mo->floorz = self->floorz;
mo->ceilingz = self->ceilingz;
mo->target = self;
}
}
return 0;
}
//============================================================================
//
// A_WraithFX4
//
// Spawn an FX4 during movement
//
//============================================================================
void A_WraithFX4 (AActor *self)
{
AActor *mo;
int chance = pr_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 = (pr_wraithfx4() - 128) / 16.;
double yo = (pr_wraithfx4() - 128) / 16.;
double zo = (pr_wraithfx4() / 64.);
mo = Spawn ("WraithFX4", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)
{
mo->floorz = self->floorz;
mo->ceilingz = self->ceilingz;
mo->target = self;
}
}
if (spawn5)
{
double xo = (pr_wraithfx4() - 128) / 32.;
double yo = (pr_wraithfx4() - 128) / 32.;
double zo = (pr_wraithfx4() / 64.);
mo = Spawn ("WraithFX5", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)
{
mo->floorz = self->floorz;
mo->ceilingz = self->ceilingz;
mo->target = self;
}
}
}
//============================================================================
//
// A_WraithChase
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_WraithChase)
{
PARAM_SELF_PROLOGUE(AActor);
int weaveindex = self->WeaveIndexZ;
self->AddZ(BobSin(weaveindex));
self->WeaveIndexZ = (weaveindex + 2) & 63;
// if (self->Floorclip > 0)
// {
// P_SetMobjState(self, S_WRAITH_RAISE2);
// return;
// }
A_Chase (stack, self);
A_WraithFX4 (self);
return 0;
}

View file

@ -3,8 +3,6 @@
#include "m_random.h" #include "m_random.h"
#include "m_fixed.h" #include "m_fixed.h"
static FRandom pr_dirt ("SpawnDirt");
// Stained glass ------------------------------------------------------------ // Stained glass ------------------------------------------------------------
class AGlassShard : public AActor class AGlassShard : public AActor
@ -27,25 +25,3 @@ public:
IMPLEMENT_CLASS(AGlassShard, false, false, false, false) IMPLEMENT_CLASS(AGlassShard, false, false, false, false)
// Dirt stuff
void P_SpawnDirt (AActor *actor, double radius)
{
PClassActor *dtype = NULL;
AActor *mo;
double zo = pr_dirt() / 128. + 1;
DVector3 pos = actor->Vec3Angle(radius, pr_dirt() * (360./256), zo);
char fmt[8];
mysnprintf(fmt, countof(fmt), "Dirt%d", 1 + pr_dirt()%6);
dtype = PClass::FindActor(fmt);
if (dtype)
{
mo = Spawn (dtype, pos, ALLOW_REPLACE);
if (mo)
{
mo->Vel.Z = pr_dirt() / 64.;
}
}
}

View file

@ -10,7 +10,6 @@ struct side_t;
struct F3DFloor; struct F3DFloor;
class DBaseDecal; class DBaseDecal;
void P_SpawnDirt (AActor *actor, double radius);
class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent); class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent);
class DBaseDecal : public DThinker class DBaseDecal : public DThinker

View file

@ -3468,47 +3468,6 @@ int P_Massacre ()
return killcount; return killcount;
} }
//
// A_SinkMobj
// Sink a mobj incrementally into the floor
//
bool A_SinkMobj (AActor *actor, double speed)
{
if (actor->Floorclip < actor->Height)
{
actor->Floorclip += speed;
return false;
}
return true;
}
//
// A_RaiseMobj
// Raise a mobj incrementally from the floor to
//
bool A_RaiseMobj (AActor *actor, double speed)
{
bool done = true;
// Raise a mobj from the ground
if (actor->Floorclip > 0)
{
actor->Floorclip -= speed;
if (actor->Floorclip <= 0)
{
actor->Floorclip = 0;
done = true;
}
else
{
done = false;
}
}
return done; // Reached target height
}
DEFINE_ACTION_FUNCTION(AActor, A_ClassBossHealth) DEFINE_ACTION_FUNCTION(AActor, A_ClassBossHealth)
{ {
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);

View file

@ -75,9 +75,6 @@ void A_Chase(VMFrameStack *stack, AActor *self);
void A_FaceTarget(AActor *actor); void A_FaceTarget(AActor *actor);
void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0); void A_Face(AActor *self, AActor *other, DAngle max_turn = 0., DAngle max_pitch = 270., DAngle ang_offset = 0., DAngle pitch_offset = 0., int flags = 0, double z_add = 0);
bool A_RaiseMobj (AActor *, double speed);
bool A_SinkMobj (AActor *, double speed);
bool CheckBossDeath (AActor *); bool CheckBossDeath (AActor *);
int P_Massacre (); int P_Massacre ();
bool P_CheckMissileRange (AActor *actor); bool P_CheckMissileRange (AActor *actor);

View file

@ -204,8 +204,8 @@ void AActor::InitNativeFields()
meta->AddNativeField("fillcolor", TypeColor, myoffsetof(AActor, fillcolor)); meta->AddNativeField("fillcolor", TypeColor, myoffsetof(AActor, fillcolor));
meta->AddNativeField("Sector", TypeSector, myoffsetof(AActor, Sector)); meta->AddNativeField("Sector", TypeSector, myoffsetof(AActor, Sector));
//meta->AddNativeField("Subsector", TypeSubsector, myoffsetof(AActor, subsector)); //meta->AddNativeField("Subsector", TypeSubsector, myoffsetof(AActor, subsector));
meta->AddNativeField(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz), VARF_ReadOnly); meta->AddNativeField(NAME_CeilingZ, TypeFloat64, myoffsetof(AActor, ceilingz));
meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz), VARF_ReadOnly); meta->AddNativeField(NAME_FloorZ, TypeFloat64, myoffsetof(AActor, floorz));
meta->AddNativeField("DropoffZ", TypeFloat64, myoffsetof(AActor, dropoffz), VARF_ReadOnly); meta->AddNativeField("DropoffZ", TypeFloat64, myoffsetof(AActor, dropoffz), VARF_ReadOnly);
meta->AddNativeField("floorsector", TypeSector, myoffsetof(AActor, floorsector)); meta->AddNativeField("floorsector", TypeSector, myoffsetof(AActor, floorsector));
meta->AddNativeField("floorpic", TypeSInt32, myoffsetof(AActor, floorpic)); // Do we need a variable type 'texture' to do this? meta->AddNativeField("floorpic", TypeSInt32, myoffsetof(AActor, floorpic)); // Do we need a variable type 'texture' to do this?
@ -225,7 +225,7 @@ void AActor::InitNativeFields()
meta->AddNativeField("specialf1", TypeFloat64, myoffsetof(AActor, specialf1)); meta->AddNativeField("specialf1", TypeFloat64, myoffsetof(AActor, specialf1));
meta->AddNativeField("specialf2", TypeFloat64, myoffsetof(AActor, specialf2)); meta->AddNativeField("specialf2", TypeFloat64, myoffsetof(AActor, specialf2));
meta->AddNativeField("weaponspecial", TypeSInt32, myoffsetof(AActor, weaponspecial)); meta->AddNativeField("weaponspecial", TypeSInt32, myoffsetof(AActor, weaponspecial));
meta->AddNativeField(NAME_Health, TypeSInt32, myoffsetof(AActor, health), VARF_ReadOnly); meta->AddNativeField(NAME_Health, TypeSInt32, myoffsetof(AActor, health));
meta->AddNativeField("movedir", TypeUInt8, myoffsetof(AActor, movedir)); meta->AddNativeField("movedir", TypeUInt8, myoffsetof(AActor, movedir));
meta->AddNativeField("visdir", TypeSInt8, myoffsetof(AActor, visdir)); meta->AddNativeField("visdir", TypeSInt8, myoffsetof(AActor, visdir));
meta->AddNativeField("movecount", TypeSInt16, myoffsetof(AActor, movecount)); meta->AddNativeField("movecount", TypeSInt16, myoffsetof(AActor, movecount));

View file

@ -268,6 +268,68 @@ class Actor : Thinker native
DamageMobj(null, null, health, damagetype, DMG_FORCED); DamageMobj(null, null, health, damagetype, DMG_FORCED);
} }
void SpawnDirt (double radius)
{
class<Actor> dtype;
switch (random[Dirt](0, 5))
{
case 0: dtype = "Dirt1"; break;
case 1: dtype = "Dirt2"; break;
case 2: dtype = "Dirt3"; break;
case 3: dtype = "Dirt4"; break;
case 4: dtype = "Dirt5"; break;
default: dtype = "Dirt6"; break;
}
double zo = random[Dirt]() / 128. + 1;
Vector3 pos = Vec3Angle(radius, random[Dirt]() * (360./256), zo);
Actor mo = Spawn (dtype, pos, ALLOW_REPLACE);
if (mo)
{
mo.Vel.Z = random[Dirt]() / 64.;
}
}
//
// A_SinkMobj
// Sink a mobj incrementally into the floor
//
bool SinkMobj (double speed)
{
if (Floorclip < Height)
{
Floorclip += speed;
return false;
}
return true;
}
//
// A_RaiseMobj
// Raise a mobj incrementally from the floor to
//
bool RaiseMobj (double speed)
{
// Raise a mobj from the ground
if (Floorclip > 0)
{
Floorclip -= speed;
if (Floorclip <= 0)
{
Floorclip = 0;
return true;
}
else
{
return false;
}
}
return true;
}
native void A_Face(Actor faceto, float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0); native void A_Face(Actor faceto, float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0);

View file

@ -26,11 +26,7 @@ class ThrustFloor : Actor native
Height 128; Height 128;
} }
native void A_ThrustRaise();
native void A_ThrustImpale(); native void A_ThrustImpale();
native void A_ThrustLower();
native void A_ThrustInitDn();
native void A_ThrustInitUp();
States States
{ {
@ -81,6 +77,79 @@ class ThrustFloor : Actor native
TSPK B 2 A_ThrustImpale; TSPK B 2 A_ThrustImpale;
Loop; Loop;
} }
//===========================================================================
//
// Thrust floor stuff
//
// Thrust Spike Variables
// master pointer to dirt clump actor
// special2 speed of raise
// args[0] 0 = lowered, 1 = raised
// args[1] 0 = normal, 1 = bloody
//===========================================================================
void A_ThrustInitUp()
{
special2 = 5; // Raise speed
args[0] = 1; // Mark as up
Floorclip = 0;
bSolid = true;
bNoTeleport = true;
bFloorClip = true;
special1 = 0;
}
void A_ThrustInitDn()
{
special2 = 5; // Raise speed
args[0] = 0; // Mark as down
Floorclip = Default.Height;
bSolid = false;
bNoTeleport = true;
bFloorClip = true;
bInvisible = true;
master = Spawn("DirtClump", Pos, ALLOW_REPLACE);
}
void A_ThrustRaise()
{
if (RaiseMobj (special2))
{ // Reached it's target height
args[0] = 1;
if (args[1])
SetStateLabel ("BloodThrustInit2", true);
else
SetStateLabel ("ThrustInit2", true);
}
// Lose the dirt clump
if ((Floorclip < Height) && master)
{
master.Destroy ();
master = null;
}
// Spawn some dirt
if (random[Thrustraise]()<40)
SpawnDirt (radius);
special2++; // Increase raise speed
}
void A_ThrustLower()
{
if (SinkMobj (6))
{
args[0] = 0;
if (args[1])
SetStateLabel ("BloodThrustInit1", true);
else
SetStateLabel ("ThrustInit1", true);
}
}
} }
// Spike up ----------------------------------------------------------------- // Spike up -----------------------------------------------------------------

View file

@ -23,11 +23,6 @@ class Wraith : Actor
Obituary "$OB_WRAITH"; Obituary "$OB_WRAITH";
} }
native void A_WraithInit();
native void A_WraithChase();
native void A_WraithFX3();
native void A_WraithMelee();
States States
{ {
Spawn: Spawn:
@ -78,6 +73,150 @@ class Wraith : Actor
WRT2 I 1 A_FreezeDeathChunks; WRT2 I 1 A_FreezeDeathChunks;
Wait; 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 ------------------------------------------------------------ // Buried wraith ------------------------------------------------------------
@ -97,8 +236,6 @@ class WraithBuried : Wraith
PainChance 0; PainChance 0;
} }
native void A_WraithRaiseInit();
native void A_WraithRaise();
States States
{ {
@ -113,6 +250,47 @@ class WraithBuried : Wraith
Chase: Chase:
Goto Super::See; 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 -------------------------------------------------------------- // Wraith FX 1 --------------------------------------------------------------
@ -133,7 +311,6 @@ class WraithFX1 : Actor
DeathSound "WraithMissileExplode"; DeathSound "WraithMissileExplode";
} }
native void A_WraithFX2();
States States
{ {
@ -150,6 +327,36 @@ class WraithFX1 : Actor
WRBL I 3 Bright; WRBL I 3 Bright;
Stop; 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 -------------------------------------------------------------- // Wraith FX 2 --------------------------------------------------------------