diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5d3e007b1..81f43f06b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -851,7 +851,6 @@ set( NOT_COMPILED_SOURCE_FILES g_doom/a_bossbrain.cpp g_doom/a_doomweaps.cpp g_doom/a_painelemental.cpp - g_doom/a_revenant.cpp g_doom/a_scriptedmarine.cpp g_heretic/a_chicken.cpp g_heretic/a_dsparil.cpp diff --git a/src/g_doom/a_doommisc.cpp b/src/g_doom/a_doommisc.cpp index 1df9a4e7cd..eabf887f07 100644 --- a/src/g_doom/a_doommisc.cpp +++ b/src/g_doom/a_doommisc.cpp @@ -25,6 +25,5 @@ #include "a_bossbrain.cpp" #include "a_doomweaps.cpp" #include "a_painelemental.cpp" -#include "a_revenant.cpp" #include "a_scriptedmarine.cpp" diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp deleted file mode 100644 index 0ffaed7534..0000000000 --- a/src/g_doom/a_revenant.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -#include "templates.h" -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_enemy.h" -#include "gstrings.h" -#include "a_action.h" -#include "vm.h" -#include "g_level.h" -*/ - -static FRandom pr_tracer ("Tracer"); -static FRandom pr_skelfist ("SkelFist"); - -// -// A_SkelMissile -// -DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *missile; - - if (!self->target) - return 0; - - A_FaceTarget (self); - self->AddZ(16.); - missile = P_SpawnMissile(self, self->target, PClass::FindActor("RevenantTracer")); - self->AddZ(-16.); - - if (missile != NULL) - { - missile->SetOrigin(missile->Vec3Offset(missile->Vel.X, missile->Vel.Y, 0.), false); - missile->tracer = self->target; - } - return 0; -} - -#define TRACEANGLE (16.875) - -DEFINE_ACTION_FUNCTION(AActor, A_Tracer) -{ - PARAM_SELF_PROLOGUE(AActor); - - double dist; - double slope; - AActor *dest; - AActor *smoke; - - // killough 1/18/98: this is why some missiles do not have smoke - // and some do. Also, internal demos start at random gametics, thus - // the bug in which revenants cause internal demos to go out of sync. - // - // killough 3/6/98: fix revenant internal demo bug by subtracting - // levelstarttic from gametic: - // - // [RH] level.time is always 0-based, so nothing special to do here. - - if (level.time & 3) - return 0; - - // spawn a puff of smoke behind the rocket - P_SpawnPuff (self, PClass::FindActor(NAME_BulletPuff), self->Pos(), self->Angles.Yaw, self->Angles.Yaw, 3); - - smoke = Spawn ("RevenantTracerSmoke", self->Vec3Offset(-self->Vel.X, -self->Vel.Y, 0.), ALLOW_REPLACE); - - smoke->Vel.Z = 1.; - smoke->tics -= pr_tracer()&3; - if (smoke->tics < 1) - smoke->tics = 1; - - // adjust direction - dest = self->tracer; - - if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest)) - return 0; - - // change angle - DAngle exact = self->AngleTo(dest); - DAngle diff = deltaangle(self->Angles.Yaw, exact); - - if (diff < 0) - { - self->Angles.Yaw -= TRACEANGLE; - if (deltaangle(self->Angles.Yaw, exact) > 0) - self->Angles.Yaw = exact; - } - else if (diff > 0) - { - self->Angles.Yaw += TRACEANGLE; - if (deltaangle(self->Angles.Yaw, exact) < 0.) - self->Angles.Yaw = exact; - } - - self->VelFromAngle(); - - if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) - { - // change slope - dist = self->DistanceBySpeed(dest, self->Speed); - - if (dest->Height >= 56.) - { - slope = (dest->Z() + 40. - self->Z()) / dist; - } - else - { - slope = (dest->Z() + self->Height*(2./3) - self->Z()) / dist; - } - - if (slope < self->Vel.Z) - self->Vel.Z -= 1. / 8; - else - self->Vel.Z += 1. / 8; - } - return 0; -} - - -DEFINE_ACTION_FUNCTION(AActor, A_SkelWhoosh) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) - return 0; - A_FaceTarget (self); - S_Sound (self, CHAN_WEAPON, "skeleton/swing", 1, ATTN_NORM); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_SkelFist) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!self->target) - return 0; - - A_FaceTarget (self); - - if (self->CheckMeleeRange ()) - { - int damage = ((pr_skelfist()%10)+1)*6; - S_Sound (self, CHAN_WEAPON, "skeleton/melee", 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - return 0; -} diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d0c0af1f55..21d32c2de2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1871,6 +1871,13 @@ bool AActor::CanSeek(AActor *target) const return true; } +DEFINE_ACTION_FUNCTION(AActor, CanSeek) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(target, AActor); + ACTION_RETURN_BOOL(self->CanSeek(target)); +} + //---------------------------------------------------------------------------- // // FUNC P_SeekerMissile @@ -5424,7 +5431,20 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos1 return puff; } - +DEFINE_ACTION_FUNCTION(AActor, SpawnPuff) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(pufftype, AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_ANGLE(hitdir); + PARAM_ANGLE(particledir); + PARAM_INT(updown); + PARAM_INT_DEF(flags); + PARAM_OBJECT_DEF(victim, AActor); + ACTION_RETURN_OBJECT(P_SpawnPuff(self, pufftype, DVector3(x, y, z), hitdir, particledir, updown, flags, victim)); +} //--------------------------------------------------------------------------- // @@ -6817,6 +6837,22 @@ void AActor::SetTranslation(const char *trname) // silently ignore if the name does not exist, this would create some insane message spam otherwise. } +DEFINE_ACTION_FUNCTION(AActor, deltaangle) // should this be global? +{ + PARAM_PROLOGUE; + PARAM_FLOAT(a1); + PARAM_FLOAT(a2); + ACTION_RETURN_FLOAT(deltaangle(DAngle(a1), DAngle(a2)).Degrees); +} + +DEFINE_ACTION_FUNCTION(AActor, AddZ) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(addz); + self->AddZ(addz); + return 0; +} + DEFINE_ACTION_FUNCTION(AActor, SetDamage) { PARAM_SELF_PROLOGUE(AActor); @@ -6856,6 +6892,14 @@ DEFINE_ACTION_FUNCTION(AActor, VelFromAngle) return 0; } +DEFINE_ACTION_FUNCTION(AActor, AngleTo) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(targ, AActor); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_FLOAT(self->AngleTo(targ, absolute).Degrees); +} + DEFINE_ACTION_FUNCTION(AActor, DistanceBySpeed) { PARAM_SELF_PROLOGUE(AActor); @@ -6894,6 +6938,16 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } +DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC3(self->Vec3Offset(x, y, z, absolute)); +} + //---------------------------------------------------------------------------- // // DropItem handling diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 287808b673..5aa1af2930 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -54,6 +54,7 @@ class Actor : Thinker native } native static readonly GetDefaultByType(class cls); + native static float deltaangle(float ang1, float ang2); native void SetDamage(int dmg); native static bool isDehState(state st); native void SetOrigin(vector3 newpos, bool moving); @@ -62,6 +63,8 @@ class Actor : Thinker native 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 OldSpawnMissile(Actor dest, class type, Actor owner = null); + native Actor SpawnPuff(class pufftype, vector3 pos, float hitdir, float particledir, int updown, int flags = 0, Actor vict = null); + native void TraceBleed(int damage, Actor missile); native bool CheckMeleeRange(); native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); @@ -72,6 +75,10 @@ class Actor : Thinker native native bool SetState(state st, bool nofunction = false); native void LinkToWorld(); native void UnlinkFromWorld(); + native bool CanSeek(Actor target); + native double AngleTo(Actor target, bool absolute = false); + native void AddZ(float zadd); + native vector3 Vec3Offset(float x, float y, float z, bool absolute = false); native vector3 Vec3Angle(float length, float angle, float z = 0, bool absolute = false); native vector3 Vec2OffsetZ(float x, float y, float atz, bool absolute = false); native void VelFromAngle(float speed = 0, float angle = 0); @@ -238,10 +245,6 @@ class Actor : Thinker native native void A_Chase(state melee = null, state missile = null, int flags = 0); native void A_Scream(); native void A_VileChase(); - native void A_Tracer(); - native void A_SkelWhoosh(); - native void A_SkelFist(); - native void A_SkelMissile(); native void A_BossDeath(); native void A_Detonate(); native bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0); diff --git a/wadsrc/static/zscript/doom/revenant.txt b/wadsrc/static/zscript/doom/revenant.txt index 7fc8b8e0df..2fc35c60f2 100644 --- a/wadsrc/static/zscript/doom/revenant.txt +++ b/wadsrc/static/zscript/doom/revenant.txt @@ -120,3 +120,123 @@ class RevenantTracerSmoke : Actor Stop; } } + +//=========================================================================== +// +// Code (must be attached to Actor) +// +//=========================================================================== + +extend class Actor +{ + const TRACEANGLE = (16.875); + + void A_SkelMissile() + { + if (target == null) return; + A_FaceTarget(); + AddZ(16); + Actor missile = SpawnMissile(target, "RevenantTracer"); + AddZ(-16); + if (missile != null) + { + missile.SetOrigin(missile.Vec3Offset(missile.Vel.X, missile.Vel.Y, 0.), false); + missile.tracer = target; + } + } + + void A_SkelWhoosh() + { + if (target == null) return; + A_FaceTarget(); + A_PlaySound("skeleton/swing", CHAN_WEAPON); + } + + void A_SkelFist() + { + if (target == null) return; + A_FaceTarget(); + + if (CheckMeleeRange ()) + { + int damage = random[SkelFist](1, 10) * 6; + A_PlaySound("skeleton/melee", CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + } + + void A_Tracer() + { + double dist; + double slope; + Actor dest; + Actor smoke; + + // killough 1/18/98: this is why some missiles do not have smoke + // and some do. Also, internal demos start at random gametics, thus + // the bug in which revenants cause internal demos to go out of sync. + // + // killough 3/6/98: fix revenant internal demo bug by subtracting + // levelstarttic from gametic: + // + // [RH] level.time is always 0-based, so nothing special to do here. + + if (level.time & 3) return; + + // spawn a puff of smoke behind the rocket + SpawnPuff ("BulletPuff", pos, angle, angle, 3); + smoke = Spawn ("RevenantTracerSmoke", Vec3Offset(-Vel.X, -Vel.Y, 0.), ALLOW_REPLACE); + + smoke.Vel.Z = 1.; + smoke.tics -= random[Tracer](0, 3); + if (smoke.tics < 1) + smoke.tics = 1; + + // adjust direction + dest = tracer; + + if (!dest || dest.health <= 0 || Speed == 0 || !CanSeek(dest)) + return; + + // change angle + double exact = AngleTo(dest); + double diff = deltaangle(angle, exact); + + if (diff < 0) + { + angle -= TRACEANGLE; + if (deltaangle(angle, exact) > 0) + angle = exact; + } + else if (diff > 0) + { + angle += TRACEANGLE; + if (deltaangle(angle, exact) < 0.) + angle = exact; + } + + VelFromAngle(); + + if (!bFloorHugger && !bCeilingHugger) + { + // change slope + dist = DistanceBySpeed(dest, Speed); + + if (dest.Height >= 56.) + { + slope = (dest.pos.z + 40. - pos.z) / dist; + } + else + { + slope = (dest.pos.z + Height*(2./3) - pos.z) / dist; + } + + if (slope < Vel.Z) + Vel.Z -= 1. / 8; + else + Vel.Z += 1. / 8; + } + } +} +