mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- scriptified the Ironlich.
This commit is contained in:
parent
1a20a5b999
commit
5e67cf79d3
9 changed files with 215 additions and 223 deletions
|
@ -860,7 +860,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
||||||
g_heretic/a_dsparil.cpp
|
g_heretic/a_dsparil.cpp
|
||||||
g_heretic/a_hereticartifacts.cpp
|
g_heretic/a_hereticartifacts.cpp
|
||||||
g_heretic/a_hereticweaps.cpp
|
g_heretic/a_hereticweaps.cpp
|
||||||
g_heretic/a_ironlich.cpp
|
|
||||||
g_hexen/a_blastradius.cpp
|
g_hexen/a_blastradius.cpp
|
||||||
g_hexen/a_boostarmor.cpp
|
g_hexen/a_boostarmor.cpp
|
||||||
g_hexen/a_clericflame.cpp
|
g_hexen/a_clericflame.cpp
|
||||||
|
|
|
@ -22,5 +22,3 @@
|
||||||
#include "a_dsparil.cpp"
|
#include "a_dsparil.cpp"
|
||||||
#include "a_hereticartifacts.cpp"
|
#include "a_hereticartifacts.cpp"
|
||||||
#include "a_hereticweaps.cpp"
|
#include "a_hereticweaps.cpp"
|
||||||
#include "a_ironlich.cpp"
|
|
||||||
|
|
||||||
|
|
|
@ -1,213 +0,0 @@
|
||||||
/*
|
|
||||||
#include "actor.h"
|
|
||||||
#include "info.h"
|
|
||||||
#include "m_random.h"
|
|
||||||
#include "s_sound.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "p_enemy.h"
|
|
||||||
#include "a_action.h"
|
|
||||||
#include "gstrings.h"
|
|
||||||
#include "vm.h"
|
|
||||||
#include "g_level.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
static FRandom pr_foo ("WhirlwindDamage");
|
|
||||||
static FRandom pr_atk ("LichAttack");
|
|
||||||
static FRandom pr_seek ("WhirlwindSeek");
|
|
||||||
|
|
||||||
class AWhirlwind : public AActor
|
|
||||||
{
|
|
||||||
DECLARE_CLASS (AWhirlwind, AActor)
|
|
||||||
public:
|
|
||||||
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(AWhirlwind, false, false, false, false)
|
|
||||||
|
|
||||||
int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype)
|
|
||||||
{
|
|
||||||
int randVal;
|
|
||||||
|
|
||||||
if (!(target->flags7 & MF7_DONTTHRUST))
|
|
||||||
{
|
|
||||||
target->Angles.Yaw += pr_foo.Random2() * (360 / 4096.);
|
|
||||||
target->Vel.X += pr_foo.Random2() / 64.;
|
|
||||||
target->Vel.Y += pr_foo.Random2() / 64.;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST))
|
|
||||||
{
|
|
||||||
randVal = pr_foo();
|
|
||||||
if (randVal > 160)
|
|
||||||
{
|
|
||||||
randVal = 160;
|
|
||||||
}
|
|
||||||
target->Vel.Z += randVal / 32.;
|
|
||||||
if (target->Vel.Z > 12)
|
|
||||||
{
|
|
||||||
target->Vel.Z = 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!(level.time & 7))
|
|
||||||
{
|
|
||||||
P_DamageMobj (target, NULL, this->target, 3, NAME_Melee);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_LichAttack
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
AActor *fire;
|
|
||||||
AActor *baseFire;
|
|
||||||
AActor *mo;
|
|
||||||
AActor *target;
|
|
||||||
int randAttack;
|
|
||||||
static const int atkResolve1[] = { 50, 150 };
|
|
||||||
static const int atkResolve2[] = { 150, 200 };
|
|
||||||
|
|
||||||
// Ice ball (close 20% : far 60%)
|
|
||||||
// Fire column (close 40% : far 20%)
|
|
||||||
// Whirlwind (close 40% : far 20%)
|
|
||||||
// Distance threshold = 8 cells
|
|
||||||
|
|
||||||
target = self->target;
|
|
||||||
if (target == NULL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
A_FaceTarget (self);
|
|
||||||
if (self->CheckMeleeRange ())
|
|
||||||
{
|
|
||||||
int damage = pr_atk.HitDice (6);
|
|
||||||
int newdam = P_DamageMobj (target, self, self, damage, NAME_Melee);
|
|
||||||
P_TraceBleed (newdam > 0 ? newdam : damage, target, self);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int dist = self->Distance2D(target) > 8 * 64;
|
|
||||||
randAttack = pr_atk ();
|
|
||||||
if (randAttack < atkResolve1[dist])
|
|
||||||
{ // Ice ball
|
|
||||||
P_SpawnMissile (self, target, PClass::FindActor("HeadFX1"));
|
|
||||||
S_Sound (self, CHAN_BODY, "ironlich/attack2", 1, ATTN_NORM);
|
|
||||||
}
|
|
||||||
else if (randAttack < atkResolve2[dist])
|
|
||||||
{ // Fire column
|
|
||||||
baseFire = P_SpawnMissile (self, target, PClass::FindActor("HeadFX3"));
|
|
||||||
if (baseFire != NULL)
|
|
||||||
{
|
|
||||||
baseFire->SetState (baseFire->FindState("NoGrow"));
|
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
fire = Spawn("HeadFX3", baseFire->Pos(), ALLOW_REPLACE);
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
S_Sound (self, CHAN_BODY, "ironlich/attack1", 1, ATTN_NORM);
|
|
||||||
}
|
|
||||||
fire->target = baseFire->target;
|
|
||||||
fire->Angles.Yaw = baseFire->Angles.Yaw;
|
|
||||||
fire->Vel = baseFire->Vel;
|
|
||||||
fire->SetDamage(0);
|
|
||||||
fire->health = (i+1) * 2;
|
|
||||||
P_CheckMissileSpawn (fire, self->radius);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Whirlwind
|
|
||||||
mo = P_SpawnMissile (self, target, RUNTIME_CLASS(AWhirlwind));
|
|
||||||
if (mo != NULL)
|
|
||||||
{
|
|
||||||
mo->AddZ(-32);
|
|
||||||
mo->tracer = target;
|
|
||||||
mo->health = 20*TICRATE; // Duration
|
|
||||||
S_Sound (self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_WhirlwindSeek
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
self->health -= 3;
|
|
||||||
if (self->health < 0)
|
|
||||||
{
|
|
||||||
self->Vel.Zero();
|
|
||||||
self->SetState(self->FindState(NAME_Death));
|
|
||||||
self->flags &= ~MF_MISSILE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((self->threshold -= 3) < 0)
|
|
||||||
{
|
|
||||||
self->threshold = 58 + (pr_seek() & 31);
|
|
||||||
S_Sound(self, CHAN_BODY, "ironlich/attack3", 1, ATTN_NORM);
|
|
||||||
}
|
|
||||||
if (self->tracer && self->tracer->flags&MF_SHADOW)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
P_SeekerMissile(self, 10, 30);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_LichIceImpact
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
AActor *shard;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
shard = Spawn("HeadFX2", self->Pos(), ALLOW_REPLACE);
|
|
||||||
shard->target = self->target;
|
|
||||||
shard->Angles.Yaw = i*45.;
|
|
||||||
shard->VelFromAngle();
|
|
||||||
shard->Vel.Z = -.6;
|
|
||||||
P_CheckMissileSpawn (shard, self->radius);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC A_LichFireGrow
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
self->health--;
|
|
||||||
self->AddZ(9.);
|
|
||||||
if (self->health == 0)
|
|
||||||
{
|
|
||||||
self->RestoreDamage();
|
|
||||||
self->SetState (self->FindState("NoGrow"));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -6668,6 +6668,17 @@ int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, DoSpecialDamage)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_OBJECT(target, AActor);
|
||||||
|
PARAM_INT(damage);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
self->VMSuperCall();
|
||||||
|
ACTION_RETURN_INT(self->DoSpecialDamage(target, damage, damagetype));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype)
|
int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype)
|
||||||
{
|
{
|
||||||
FState *death;
|
FState *death;
|
||||||
|
@ -7180,6 +7191,13 @@ DEFINE_ACTION_FUNCTION(AActor, Vec3Offset)
|
||||||
ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute));
|
ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, RestoreDamage)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
self->RestoreDamage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// DropItem handling
|
// DropItem handling
|
||||||
|
|
|
@ -2326,6 +2326,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
|
|
||||||
if (varflags & VARF_Virtual)
|
if (varflags & VARF_Virtual)
|
||||||
{
|
{
|
||||||
|
if (sym->Variants[0].Implementation == nullptr)
|
||||||
|
{
|
||||||
|
Error(f, "Virtual function %s.%s not present.", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (varflags & VARF_Final)
|
if (varflags & VARF_Final)
|
||||||
{
|
{
|
||||||
sym->Variants[0].Implementation->Final = true;
|
sym->Variants[0].Implementation->Final = true;
|
||||||
|
|
|
@ -38,6 +38,7 @@ VMEXPORTED_NATIVES_START
|
||||||
VMEXPORTED_NATIVES_FUNC(BeginPlay)
|
VMEXPORTED_NATIVES_FUNC(BeginPlay)
|
||||||
VMEXPORTED_NATIVES_FUNC(Activate)
|
VMEXPORTED_NATIVES_FUNC(Activate)
|
||||||
VMEXPORTED_NATIVES_FUNC(Deactivate)
|
VMEXPORTED_NATIVES_FUNC(Deactivate)
|
||||||
|
VMEXPORTED_NATIVES_FUNC(DoSpecialDamage)
|
||||||
VMEXPORTED_NATIVES_END
|
VMEXPORTED_NATIVES_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,6 +193,26 @@ public:
|
||||||
stack.Call(VFUNC, params, 2, nullptr, 0, nullptr);
|
stack.Call(VFUNC, params, 2, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int DoSpecialDamage(AActor *target, int damage, FName damagetype)
|
||||||
|
{
|
||||||
|
if (this->ObjectFlags & OF_SuperCall)
|
||||||
|
{
|
||||||
|
this->ObjectFlags &= ~OF_SuperCall;
|
||||||
|
return ExportedNatives<T>::Get()->template DoSpecialDamage<int, T>(this, target, damage, damagetype);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VINDEX(AActor, DoSpecialDamage);
|
||||||
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
|
VMValue params[4] = { (DObject*)this, (DObject*)target, damage, damagetype.GetIndex() };
|
||||||
|
VMReturn ret;
|
||||||
|
VMFrameStack stack;
|
||||||
|
int retval;
|
||||||
|
ret.IntAt(&retval);
|
||||||
|
stack.Call(VFUNC, params, 4, &ret, 1, nullptr);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,6 +244,7 @@ VMEXPORT_NATIVES_START(AActor, DThinker)
|
||||||
VMEXPORT_NATIVES_FUNC(BeginPlay)
|
VMEXPORT_NATIVES_FUNC(BeginPlay)
|
||||||
VMEXPORT_NATIVES_FUNC(Activate)
|
VMEXPORT_NATIVES_FUNC(Activate)
|
||||||
VMEXPORT_NATIVES_FUNC(Deactivate)
|
VMEXPORT_NATIVES_FUNC(Deactivate)
|
||||||
|
VMEXPORT_NATIVES_FUNC(DoSpecialDamage)
|
||||||
VMEXPORT_NATIVES_END(AActor)
|
VMEXPORT_NATIVES_END(AActor)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -237,6 +237,7 @@ class Actor : Thinker native
|
||||||
virtual native void BeginPlay();
|
virtual native void BeginPlay();
|
||||||
virtual native void Activate(Actor activator);
|
virtual native void Activate(Actor activator);
|
||||||
virtual native void Deactivate(Actor activator);
|
virtual native void Deactivate(Actor activator);
|
||||||
|
virtual native int DoSpecialDamage (Actor target, int damage, Name damagetype);
|
||||||
|
|
||||||
native void AdjustPlayerAngle(FTranslatedLineTarget t);
|
native void AdjustPlayerAngle(FTranslatedLineTarget t);
|
||||||
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
||||||
|
@ -247,6 +248,7 @@ class Actor : Thinker native
|
||||||
native void ClearCounters();
|
native void ClearCounters();
|
||||||
native bool GiveBody (int num, int max=0);
|
native bool GiveBody (int num, int max=0);
|
||||||
|
|
||||||
|
native void RestoreDamage();
|
||||||
native void SetDamage(int dmg);
|
native void SetDamage(int dmg);
|
||||||
native double Distance2D(Actor other);
|
native double Distance2D(Actor other);
|
||||||
native void SetOrigin(vector3 newpos, bool moving);
|
native void SetOrigin(vector3 newpos, bool moving);
|
||||||
|
|
|
@ -12,6 +12,8 @@ class Object native
|
||||||
|
|
||||||
class Thinker : Object native
|
class Thinker : Object native
|
||||||
{
|
{
|
||||||
|
const TICRATE = 35;
|
||||||
|
|
||||||
virtual native void Tick();
|
virtual native void Tick();
|
||||||
virtual native void PostBeginPlay();
|
virtual native void PostBeginPlay();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ class Ironlich : Actor
|
||||||
DropItem "ArtiEgg", 51, 0;
|
DropItem "ArtiEgg", 51, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_LichAttack ();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
|
@ -54,6 +53,77 @@ class Ironlich : Actor
|
||||||
LICH I -1 A_BossDeath;
|
LICH I -1 A_BossDeath;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_LichAttack
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_LichAttack ()
|
||||||
|
{
|
||||||
|
static const int atkResolve1[] = { 50, 150 };
|
||||||
|
static const int atkResolve2[] = { 150, 200 };
|
||||||
|
|
||||||
|
// Ice ball (close 20% : far 60%)
|
||||||
|
// Fire column (close 40% : far 20%)
|
||||||
|
// Whirlwind (close 40% : far 20%)
|
||||||
|
// Distance threshold = 8 cells
|
||||||
|
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
A_FaceTarget ();
|
||||||
|
if (CheckMeleeRange ())
|
||||||
|
{
|
||||||
|
int damage = random[LichAttack](1, 8) * 6;
|
||||||
|
int newdam = target.DamageMobj (self, self, damage, 'Melee');
|
||||||
|
target.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int dist = Distance2D(target) > 8 * 64;
|
||||||
|
int randAttack = random[LichAttack]();
|
||||||
|
if (randAttack < atkResolve1[dist])
|
||||||
|
{ // Ice ball
|
||||||
|
SpawnMissile (target, "HeadFX1");
|
||||||
|
A_PlaySound ("ironlich/attack2", CHAN_BODY);
|
||||||
|
}
|
||||||
|
else if (randAttack < atkResolve2[dist])
|
||||||
|
{ // Fire column
|
||||||
|
Actor baseFire = SpawnMissile (target, "HeadFX3");
|
||||||
|
if (baseFire != null)
|
||||||
|
{
|
||||||
|
baseFire.SetStateLabel("NoGrow");
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
Actor fire = Spawn("HeadFX3", baseFire.Pos, ALLOW_REPLACE);
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
A_PlaySound ("ironlich/attack1", CHAN_BODY);
|
||||||
|
}
|
||||||
|
fire.target = baseFire.target;
|
||||||
|
fire.angle = baseFire.angle;
|
||||||
|
fire.Vel = baseFire.Vel;
|
||||||
|
fire.SetDamage(0);
|
||||||
|
fire.health = (i+1) * 2;
|
||||||
|
fire.CheckMissileSpawn (radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Whirlwind
|
||||||
|
Actor mo = SpawnMissile (target, "Whirlwind");
|
||||||
|
if (mo != null)
|
||||||
|
{
|
||||||
|
mo.AddZ(-32);
|
||||||
|
mo.tracer = target;
|
||||||
|
mo.health = 20*TICRATE; // Duration
|
||||||
|
A_PlaySound ("ironlich/attack3", CHAN_BODY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Head FX 1 ----------------------------------------------------------------
|
// Head FX 1 ----------------------------------------------------------------
|
||||||
|
@ -74,7 +144,6 @@ class HeadFX1 : Actor
|
||||||
RenderStyle "Add";
|
RenderStyle "Add";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_LichIceImpact();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
|
@ -86,6 +155,25 @@ class HeadFX1 : Actor
|
||||||
FX05 EFG 5 BRIGHT;
|
FX05 EFG 5 BRIGHT;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_LichIceImpact
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_LichIceImpact()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
Actor shard = Spawn("HeadFX2", Pos, ALLOW_REPLACE);
|
||||||
|
shard.target = target;
|
||||||
|
shard.angle = i*45.;
|
||||||
|
shard.VelFromAngle();
|
||||||
|
shard.Vel.Z = -.6;
|
||||||
|
shard.CheckMissileSpawn (radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Head FX 2 ----------------------------------------------------------------
|
// Head FX 2 ----------------------------------------------------------------
|
||||||
|
@ -135,8 +223,6 @@ class HeadFX3 : Actor
|
||||||
RenderStyle "Add";
|
RenderStyle "Add";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_LichFireGrow ();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -149,12 +235,29 @@ class HeadFX3 : Actor
|
||||||
FX06 DEFG 5 BRIGHT;
|
FX06 DEFG 5 BRIGHT;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_LichFireGrow
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_LichFireGrow ()
|
||||||
|
{
|
||||||
|
health--;
|
||||||
|
AddZ(9.);
|
||||||
|
if (health == 0)
|
||||||
|
{
|
||||||
|
RestoreDamage();
|
||||||
|
SetStateLabel("NoGrow");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Whirlwind ----------------------------------------------------------------
|
// Whirlwind ----------------------------------------------------------------
|
||||||
|
|
||||||
class Whirlwind : Actor native
|
class Whirlwind : Actor
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -174,8 +277,6 @@ class Whirlwind : Actor native
|
||||||
Alpha 0.4;
|
Alpha 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_WhirlwindSeek();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -186,6 +287,64 @@ class Whirlwind : Actor native
|
||||||
FX07 GFED 4;
|
FX07 GFED 4;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override int DoSpecialDamage (Actor target, int damage, Name damagetype)
|
||||||
|
{
|
||||||
|
int randVal;
|
||||||
|
|
||||||
|
if (!target.bDontThrust)
|
||||||
|
{
|
||||||
|
target.angle += Random2[WhirlwindDamage]() * (360 / 4096.);
|
||||||
|
target.Vel.X += Random2[WhirlwindDamage]() / 64.;
|
||||||
|
target.Vel.Y += Random2[WhirlwindDamage]() / 64.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((level.time & 16) && !target.bBoss && !target.bDontThrust)
|
||||||
|
{
|
||||||
|
randVal = min(160, random[WhirlwindSeek]());
|
||||||
|
target.Vel.Z += randVal / 32.;
|
||||||
|
if (target.Vel.Z > 12)
|
||||||
|
{
|
||||||
|
target.Vel.Z = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(level.time & 7))
|
||||||
|
{
|
||||||
|
target.DamageMobj (null, target, 3, 'Melee');
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// PROC A_WhirlwindSeek
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void A_WhirlwindSeek()
|
||||||
|
{
|
||||||
|
|
||||||
|
health -= 3;
|
||||||
|
if (health < 0)
|
||||||
|
{
|
||||||
|
Vel = (0,0,0);
|
||||||
|
SetStateLabel("Death");
|
||||||
|
bMissile = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((threshold -= 3) < 0)
|
||||||
|
{
|
||||||
|
threshold = 58 + (random[WhirlwindSeek]() & 31);
|
||||||
|
A_PlaySound("ironlich/attack3", CHAN_BODY);
|
||||||
|
}
|
||||||
|
if (tracer && tracer.bShadow)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
A_SeekerMissile(10, 30);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue