diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ffd9f339a..3c165c345 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -868,7 +868,6 @@ set( NOT_COMPILED_SOURCE_FILES g_hexen/a_fighterhammer.cpp g_hexen/a_fighterplayer.cpp g_hexen/a_fighterquietus.cpp - g_hexen/a_firedemon.cpp g_hexen/a_flechette.cpp g_hexen/a_flies.cpp g_hexen/a_fog.cpp diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp deleted file mode 100644 index cc9beaaeb..000000000 --- a/src/g_hexen/a_firedemon.cpp +++ /dev/null @@ -1,248 +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 "vm.h" -*/ - -#define FIREDEMON_ATTACK_RANGE (64*8.) - -static FRandom pr_firedemonrock ("FireDemonRock"); -static FRandom pr_smbounce ("SMBounce"); -static FRandom pr_firedemonchase ("FiredChase"); -static FRandom pr_firedemonsplotch ("FiredSplotch"); - -//============================================================================ -// Fire Demon AI -// -// special1 index into floatbob -// special2 whether strafing or not -//============================================================================ - -//============================================================================ -// -// A_FiredSpawnRock -// -//============================================================================ - -void A_FiredSpawnRock (AActor *actor) -{ - AActor *mo; - PClassActor *rtype; - - switch (pr_firedemonrock() % 5) - { - case 0: - rtype = PClass::FindActor("FireDemonRock1"); - break; - case 1: - rtype = PClass::FindActor("FireDemonRock2"); - break; - case 2: - rtype = PClass::FindActor("FireDemonRock3"); - break; - case 3: - rtype = PClass::FindActor("FireDemonRock4"); - break; - case 4: - default: - rtype = PClass::FindActor("FireDemonRock5"); - break; - } - - double xo = (pr_firedemonrock() - 128) / 16.; - double yo = (pr_firedemonrock() - 128) / 16.; - double zo = pr_firedemonrock() / 32.; - mo = Spawn (rtype, actor->Vec3Offset(xo, yo, zo), ALLOW_REPLACE); - if (mo) - { - mo->target = actor; - mo->Vel.X = (pr_firedemonrock() - 128) / 64.; - mo->Vel.Y = (pr_firedemonrock() - 128) / 64.; - mo->Vel.Z = (pr_firedemonrock() / 64.); - mo->special1 = 2; // Number bounces - } - - // Initialize fire demon - actor->special2 = 0; - actor->flags &= ~MF_JUSTATTACKED; -} - -//============================================================================ -// -// A_FiredRocks -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredRocks) -{ - PARAM_SELF_PROLOGUE(AActor); - - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - A_FiredSpawnRock (self); - return 0; -} - -//============================================================================ -// -// A_SmBounce -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SmBounce) -{ - PARAM_SELF_PROLOGUE(AActor); - - // give some more velocity (x,y,&z) - self->SetZ(self->floorz + 1); - self->Vel.Z = 2. + pr_smbounce() / 64.; - self->Vel.X = pr_smbounce() % 3; - self->Vel.Y = pr_smbounce() % 3; - return 0; -} - -//============================================================================ -// -// A_FiredAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->target == NULL) - return 0; - AActor *mo = P_SpawnMissile (self, self->target, PClass::FindActor("FireDemonMissile")); - if (mo) S_Sound (self, CHAN_BODY, "FireDemonAttack", 1, ATTN_NORM); - return 0; -} - -//============================================================================ -// -// A_FiredChase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) -{ - PARAM_SELF_PROLOGUE(AActor); - - int weaveindex = self->special1; - AActor *target = self->target; - DAngle ang; - double dist; - - if (self->reactiontime) self->reactiontime--; - if (self->threshold) self->threshold--; - - // Float up and down - self->AddZ(BobSin(weaveindex)); - self->special1 = (weaveindex + 2) & 63; - - // Ensure it stays above certain height - if (self->Z() < self->floorz + 64) - { - self->AddZ(2); - } - - if(!self->target || !(self->target->flags&MF_SHOOTABLE)) - { // Invalid target - P_LookForPlayers (self,true, NULL); - return 0; - } - - // Strafe - if (self->special2 > 0) - { - self->special2--; - } - else - { - self->special2 = 0; - self->Vel.X = self->Vel.Y = 0; - dist = self->Distance2D(target); - if (dist < FIREDEMON_ATTACK_RANGE) - { - if (pr_firedemonchase() < 30) - { - ang = self->AngleTo(target); - if (pr_firedemonchase() < 128) - ang += 90; - else - ang -= 90; - self->Thrust(ang, 8); - self->special2 = 3; // strafe time - } - } - } - - FaceMovementDirection (self); - - // Normal movement - if (!self->special2) - { - if (--self->movecount<0 || !P_Move (self)) - { - P_NewChaseDir (self); - } - } - - // Do missile attack - if (!(self->flags & MF_JUSTATTACKED)) - { - if (P_CheckMissileRange (self) && (pr_firedemonchase() < 20)) - { - self->SetState (self->MissileState); - self->flags |= MF_JUSTATTACKED; - return 0; - } - } - else - { - self->flags &= ~MF_JUSTATTACKED; - } - - // make active sound - if (pr_firedemonchase() < 3) - { - self->PlayActiveSound (); - } - return 0; -} - -//============================================================================ -// -// A_FiredSplotch -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FiredSplotch) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *mo; - - mo = Spawn ("FireDemonSplotch1", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3; - } - mo = Spawn ("FireDemonSplotch2", self->Pos(), ALLOW_REPLACE); - if (mo) - { - mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.; - mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3; - } - return 0; -} diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 3676bf21b..1a635ff71 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -38,7 +38,6 @@ #include "a_fighterhammer.cpp" #include "a_fighterplayer.cpp" #include "a_fighterquietus.cpp" -#include "a_firedemon.cpp" #include "a_flechette.cpp" #include "a_flies.cpp" #include "a_fog.cpp" diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 61be39a0e..edd97a6d4 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -449,3 +449,10 @@ void FaceMovementDirection(AActor *actor) break; } } + +DEFINE_ACTION_FUNCTION(AActor, FaceMovementDirection) +{ + PARAM_SELF_PROLOGUE(AActor); + FaceMovementDirection(self); + return 0; +} diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 20a549a51..cbddb4840 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -414,6 +414,12 @@ bool P_CheckMissileRange (AActor *actor) return actor->SuggestMissileAttack (dist); } +DEFINE_ACTION_FUNCTION(AActor, CheckMissileRange) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_CheckMissileRange(self)); +} + bool AActor::SuggestMissileAttack (double dist) { // new version encapsulates the different behavior in flags instead of virtual functions @@ -707,6 +713,11 @@ bool P_Move (AActor *actor) } return true; } +DEFINE_ACTION_FUNCTION(AActor, MonsterMove) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_BOOL(P_Move(self)); +} //============================================================================= @@ -1030,7 +1041,12 @@ void P_NewChaseDir(AActor * actor) } - +DEFINE_ACTION_FUNCTION(AActor, NewChaseDir) +{ + PARAM_SELF_PROLOGUE(AActor); + P_NewChaseDir(self); + return 0; +} //============================================================================= diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bd05941b3..db6b9a287 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3327,6 +3327,13 @@ void AActor::PlayActiveSound () } } +DEFINE_ACTION_FUNCTION(AActor, PlayActiveSound) +{ + PARAM_SELF_PROLOGUE(AActor); + self->PlayActiveSound(); + return 0; +} + bool AActor::IsOkayToAttack (AActor *link) { if (!(player // Original AActor::IsOkayToAttack was only for players @@ -6877,6 +6884,13 @@ DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? ACTION_RETURN_FLOAT(deltaangle(DAngle(a1), DAngle(a2)).Degrees); } +DEFINE_ACTION_FUNCTION(AActor, Distance2D) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_FLOAT(self->Distance2D(other)); +} + DEFINE_ACTION_FUNCTION(AActor, AddZ) { PARAM_SELF_PROLOGUE(AActor); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c7a009038..48b5f7ded 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -66,9 +66,11 @@ class Actor : Thinker native native float GetBobOffset(float frac = 0); native void SetDamage(int dmg); native static bool isDehState(state st); + native double Distance2D(Actor other); native void SetOrigin(vector3 newpos, bool moving); native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); + native void FaceMovementDirection(); native static Actor Spawn(class type, vector3 pos = (0,0,0), int replace = NO_REPLACE); native Actor SpawnMissile(Actor dest, class type, Actor owner = null); native Actor SpawnMissileZ (double z, Actor dest, class type); @@ -84,6 +86,9 @@ class Actor : Thinker native native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null); native bool CheckSight(Actor target, int flags = 0); native bool HitFriend(); + native bool MonsterMove(); + native void NewChaseDir(); + native bool CheckMissileRange(); native bool SetState(state st, bool nofunction = false); native void LinkToWorld(); native void UnlinkFromWorld(); @@ -104,6 +109,7 @@ class Actor : Thinker native native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); native double DistanceBySpeed(Actor other, double speed); native name GetSpecies(); + native void PlayActiveSound(); // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); diff --git a/wadsrc/static/zscript/hexen/firedemon.txt b/wadsrc/static/zscript/hexen/firedemon.txt index 001e1629f..b425ecb11 100644 --- a/wadsrc/static/zscript/hexen/firedemon.txt +++ b/wadsrc/static/zscript/hexen/firedemon.txt @@ -3,6 +3,9 @@ class FireDemon : Actor { + const FIREDEMON_ATTACK_RANGE = 64*8.; + int strafecount; + Default { Health 80; @@ -23,11 +26,6 @@ class FireDemon : Actor Obituary "$OB_FIREDEMON"; } - native void A_FiredRocks(); - native void A_FiredChase(); - native void A_FiredAttack(); - native void A_FiredSplotch(); - States { Spawn: @@ -71,6 +69,208 @@ class FireDemon : Actor FDMN R 1 A_FreezeDeathChunks; Wait; } + + + + + //============================================================================ + // Fire Demon AI + // + // special1 index into floatbob + // strafecount whether strafing or not + //============================================================================ + + //============================================================================ + // + // A_FiredSpawnRock + // + //============================================================================ + + private void A_FiredSpawnRock () + { + Actor mo; + class rtype; + + switch (random[FireDemonRock](0, 4)) + { + case 0: + rtype = "FireDemonRock1"; + break; + case 1: + rtype = "FireDemonRock2"; + break; + case 2: + rtype = "FireDemonRock3"; + break; + case 3: + rtype = "FireDemonRock4"; + break; + case 4: + default: + rtype = "FireDemonRock5"; + break; + } + + double xo = (random[FireDemonRock]() - 128) / 16.; + double yo = (random[FireDemonRock]() - 128) / 16.; + double zo = random[FireDemonRock]() / 32.; + mo = Spawn (rtype, Vec3Offset(xo, yo, zo), ALLOW_REPLACE); + if (mo) + { + mo.target = self; + mo.Vel.X = (random[FireDemonRock]() - 128) / 64.; + mo.Vel.Y = (random[FireDemonRock]() - 128) / 64.; + mo.Vel.Z = (random[FireDemonRock]() / 64.); + mo.special1 = 2; // Number bounces + } + + // Initialize fire demon + strafecount = 0; + bJustAttacked = false; + } + + //============================================================================ + // + // A_FiredRocks + // + //============================================================================ + void A_FiredRocks() + { + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + A_FiredSpawnRock (); + } + + //============================================================================ + // + // A_FiredAttack + // + //============================================================================ + + void A_FiredAttack() + { + if (target == null) return; + Actor mo = SpawnMissile (target, "FireDemonMissile"); + if (mo) A_PlaySound ("FireDemonAttack", CHAN_BODY); + } + + //============================================================================ + // + // A_FiredChase + // + //============================================================================ + + void A_FiredChase() + { + int weaveindex = special1; + double ang; + double dist; + + if (reactiontime) reactiontime--; + if (threshold) threshold--; + + // Float up and down + AddZ(BobSin(weaveindex)); + special1 = (weaveindex + 2) & 63; + + // Ensure it stays above certain height + if (pos.Z < floorz + 64) + { + AddZ(2); + } + + if(!target || !target.bShootable) + { // Invalid target + LookForPlayers (true); + return; + } + + // Strafe + if (strafecount > 0) + { + strafecount--; + } + else + { + strafecount = 0; + Vel.X = Vel.Y = 0; + dist = Distance2D(target); + if (dist < FIREDEMON_ATTACK_RANGE) + { + if (random[FiredChase]() < 30) + { + ang = AngleTo(target); + if (random[FiredChase]() < 128) + ang += 90; + else + ang -= 90; + Thrust(8, ang); + strafecount = 3; // strafe time + } + } + } + + FaceMovementDirection (); + + // Normal movement + if (!strafecount) + { + if (--movecount<0 || !MonsterMove ()) + { + NewChaseDir (); + } + } + + // Do missile attack + if (!bJustAttacked) + { + if (CheckMissileRange () && (random[FiredChase]() < 20)) + { + SetState (MissileState); + bJustAttacked = true; + return; + } + } + else + { + bJustAttacked = false; + } + + // make active sound + if (random[FiredChase]() < 3) + { + PlayActiveSound (); + } + } + + //============================================================================ + // + // A_FiredSplotch + // + //============================================================================ + + void A_FiredSplotch() + { + Actor mo; + + mo = Spawn ("FireDemonSplotch1", Pos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.X = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Y = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Z = (random[FireDemonSplotch]() / 64.) + 3; + } + mo = Spawn ("FireDemonSplotch2", Pos, ALLOW_REPLACE); + if (mo) + { + mo.Vel.X = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Y = (random[FireDemonSplotch]() - 128) / 32.; + mo.Vel.Z = (random[FireDemonSplotch]() / 64.) + 3; + } + } + } // FireDemonSplotch1 ------------------------------------------------------- @@ -124,8 +324,6 @@ class FireDemonRock1 : Actor +NOTELEPORT } - native void A_SmBounce(); - States { Spawn: @@ -137,6 +335,21 @@ class FireDemonRock1 : Actor FDMN S 200; Stop; } + + //============================================================================ + // + // A_SmBounce + // + //============================================================================ + + void A_SmBounce() + { + // give some more velocity (x,y,&z) + SetZ(floorz + 1); + Vel.Z = 2. + random[SMBounce]() / 64.; + Vel.X = random[SMBounce](0, 2); + Vel.Y = random[SMBounce](0, 2); + } } // FireDemonRock2 ------------------------------------------------------------