diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 32a5fa1a0..745d63e35 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -40,6 +40,7 @@ This file is a combination of code from the following sources: //------------------------------------------------------------------------- #include "ns.h" +#include "vm.h" #include "global.h" #include "names.h" #include "stats.h" @@ -51,6 +52,34 @@ BEGIN_DUKE_NS double adjustfall(DDukeActor* actor, double c); +//--------------------------------------------------------------------------- +// +// this is the implementation of DDukeActor::Tick. It is native so that +// its internally needed accesss does not have to be made public. +// +//--------------------------------------------------------------------------- + +void TickActor(DDukeActor* self) +{ + if (self->spr.statnum == STAT_ACTOR || actorflag(self, SFLAG3_FORCERUNCON)) + { + double xx; + int p = findplayer(self, &xx); + if (!execute(self, p, xx)) + { + self->state_player = &ps[p]; + self->state_dist = xx; + IFVIRTUALPTR(self, DDukeActor, RunState) + { + VMValue val[] = { self }; + VMCall(func, val, 1, nullptr, 0); + } + self->state_player = nullptr; + self->state_dist = -1; + } + } +} + //--------------------------------------------------------------------------- // // diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 31e325c6c..415ee5f66 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -706,16 +706,10 @@ void movestandables_d(void) { act->Destroy(); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - double x; - int p = findplayer(act, &x); - execute(act, p, x); - } } } @@ -734,16 +728,10 @@ void moveweapons_d(void) { act->Destroy(); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - double x; - int p = findplayer(act, &x); - execute(act, p, x); - } } } @@ -1052,6 +1040,7 @@ static void flamethrowerflame(DDukeActor *actor) double xx; int p = findplayer(actor, &xx); execute(actor, p, xx); + if (actor->ObjectFlags & OF_EuthanizeMe) return; // killed by script. actor->temp_data[0]++; if (sectp->lotag == 2) { @@ -1148,8 +1137,6 @@ static void flamethrowerflame(DDukeActor *actor) void moveactors_d(void) { - int p; - DukeStatIterator it(STAT_ACTOR); while (auto act = it.Next()) { @@ -1165,16 +1152,9 @@ void moveactors_d(void) { flamethrowerflame(act); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) - { - CallTick(act); - continue; - } else { - double xx; - p = findplayer(act, &xx); - execute(act, p, xx); + CallTick(act); } } @@ -1191,6 +1171,7 @@ static void fireflyflyingeffect(DDukeActor *actor) double xx; int p = findplayer(actor, &xx); execute(actor, p, xx); + if (actor->ObjectFlags & OF_EuthanizeMe) return; // killed by script. auto Owner = actor->GetOwner(); if (!Owner || Owner->spr.picnum != FIREFLY) @@ -1224,9 +1205,6 @@ static void fireflyflyingeffect(DDukeActor *actor) void moveexplosions_d(void) // STATNUM 5 { - int p; - double xx; - DukeStatIterator it(STAT_MISC); while (auto act = it.Next()) { @@ -1238,15 +1216,10 @@ void moveexplosions_d(void) // STATNUM 5 { fireflyflyingeffect(act); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - p = findplayer(act, &xx); - execute(act, p, xx); - } } } diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 400b7d4f5..b027c40f6 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -566,16 +566,10 @@ void movestandables_r(void) { act->Destroy(); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - double x; - int p = findplayer(act, &x); - execute(act, p, x); - } } } @@ -594,16 +588,10 @@ void moveweapons_r(void) { act->Destroy(); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - double x; - int p = findplayer(act, &x); - execute(act, p, x); - } } } @@ -1185,17 +1173,10 @@ void moveexplosions_r(void) // STATNUM 5 { act->Destroy(); } - else if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + else { CallTick(act); } - else if (actorflag(act, SFLAG3_FORCERUNCON)) - { - int p; - double xx; - p = findplayer(act, &xx); - execute(act, p, xx); - } } } diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 7822fe6da..799439193 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -128,6 +128,7 @@ bool CallShootThis(DDukeActor* clsdef, DDukeActor* actor, int pn, const DVector3 void CallStaticSetup(DDukeActor* actor); void CallPlayFTASound(DDukeActor* actor); void CallStandingOn(DDukeActor* actor, player_struct* p); +void CallRunState(DDukeActor* actor); END_DUKE_NS diff --git a/source/games/duke/src/flags_d.cpp b/source/games/duke/src/flags_d.cpp index 9a46c8de1..c06cd2a9d 100644 --- a/source/games/duke/src/flags_d.cpp +++ b/source/games/duke/src/flags_d.cpp @@ -164,7 +164,7 @@ void initactorflags_d() { setflag(SFLAG_INTERNAL_BADGUY, { FIREFLY }); setflag(SFLAG_INTERNAL_BADGUY|SFLAG_NODAMAGEPUSH|SFLAG_BOSS, { BOSS5 }); - setflag(SFLAG3_FORCERUNCON, { LAVAPOOL, ONFIRE, ONFIRESMOKE, BURNEDCORPSE, LAVAPOOLBUBBLE, WHISPYSMOKE }); + setflag(SFLAG3_FORCERUNCON, { LAVAPOOL, ONFIRE, ONFIRESMOKE, BURNEDCORPSE, LAVAPOOLBUBBLE, WHISPYSMOKE, FIREFLYFLYINGEFFECT }); } setflag(SFLAG_INVENTORY, { diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index eec0ddcc9..591c3d546 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -144,7 +144,7 @@ DDukeActor* LocateTheLocator(int n, sectortype* sectnum); void clearcamera(player_struct* ps); void LoadActor(DDukeActor* i, int p, int x); -void execute(DDukeActor* s, int p, double d); +bool execute(DDukeActor* s, int p, double d); void makeitfall(DDukeActor* s); DAngle furthestangle(DDukeActor* snum, int angDiv); void getglobalz(DDukeActor* s); diff --git a/source/games/duke/src/gameexec.cpp b/source/games/duke/src/gameexec.cpp index 2aa4824ed..7e8adaadf 100644 --- a/source/games/duke/src/gameexec.cpp +++ b/source/games/duke/src/gameexec.cpp @@ -3725,9 +3725,9 @@ void LoadActor(DDukeActor *actor, int p, int x) // //--------------------------------------------------------------------------- -void execute(DDukeActor *actor,int p,double xx) +bool execute(DDukeActor *actor,int p,double xx) { - if (gs.actorinfo[actor->spr.picnum].scriptaddress == 0) return; + if (gs.actorinfo[actor->spr.picnum].scriptaddress == 0) return false; int done; @@ -3737,17 +3737,17 @@ void execute(DDukeActor *actor,int p,double xx) s.g_ac = actor; s.g_t = &actor->temp_data[0]; // Sprite's 'extra' data - if (gs.actorinfo[actor->spr.picnum].scriptaddress == 0) return; s.insptr = &ScriptCode[4 + (gs.actorinfo[actor->spr.picnum].scriptaddress)]; s.killit_flag = 0; + // this must go away. if(!actor->insector()) { if(badguy(actor)) ps[p].actors_killed++; actor->Destroy(); - return; + return true; } if (s.g_t[4]) @@ -3805,6 +3805,7 @@ void execute(DDukeActor *actor,int p,double xx) quit: if (killthesprite) actor->Destroy(); killthesprite = false; + return true; } diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index d079059b6..9fd40b439 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -71,6 +71,10 @@ public: EDukeFlags2 flags2; EDukeFlags3 flags3; + // these two variables are only valid while RunState is executed. They are explicitly nulled right afterward and only accessible throgh the CON emulation interface. + struct player_struct* state_player; + double state_dist; + DDukeActor() = default; size_t PropagateMark() override; const ActorInfo* actorInfo() const; diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 2e25977bf..68c949334 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -242,6 +242,13 @@ DEFINE_FIELD(DDukeActor, temp_pos) DEFINE_FIELD(DDukeActor, temp_pos2) DEFINE_FIELD(DDukeActor, temp_angle) +void TickActor(DDukeActor*); +DEFINE_ACTION_FUNCTION(DDukeActor, Tick) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + TickActor(self); + return 0; +} void setSpritesetImage(DDukeActor* self, unsigned int index) { auto& spriteset = static_cast(self->GetClass())->ActorInfo()->SpriteSet; diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 018f0e01b..4209a9da0 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -181,12 +181,12 @@ class DukeActor : CoreActor native native void checkhitsprite(DukeActor hitter); + virtual native void Tick(); virtual void BeginPlay() {} virtual void StaticSetup() {} virtual void Initialize() {} - virtual void Tick() {} virtual void onHit(DukeActor hitter) { checkhitdefault(hitter); } virtual void onHurt(DukePlayer p) {} virtual bool onUse(DukePlayer user) { return false; }