- scriptified the respawn controller.

This also handles one special RRRA controller which was just easier to scriptify right away than temporarily work around it.
This commit is contained in:
Christoph Oelckers 2022-11-20 11:58:19 +01:00
parent f467e72ac2
commit 9fa2fb75cf
29 changed files with 188 additions and 180 deletions

View file

@ -15,3 +15,4 @@ xx(AltHud)
xx(DukeMasterSwitch)
xx(DukeTouchplate)
xx(DukeSoundController)
xx(DukeRespawnController)

View file

@ -531,34 +531,25 @@ void movefx(void)
{
DukeStatIterator iti(STAT_FX);
while (auto act = iti.Next())
CallTick(act);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void operaterespawns(int low)
{
DukeStatIterator it(STAT_FX);
while (auto act = it.Next())
{
switch (act->spr.picnum)
{
default:
CallTick(act);
break;
case RESPAWN:
if (act->spr.extra == 66)
{
auto j = spawn(act, act->spr.hitag);
if (isRRRA() && j)
{
respawn_rrra(act, j);
}
else
{
deletesprite(act);
}
}
else if (act->spr.extra > (66 - 13))
act->spr.extra++;
break;
}
CallOnRespawn(act, low);
}
}
//---------------------------------------------------------------------------
//
//

View file

@ -3265,10 +3265,10 @@ void respawnhitag_d(DDukeActor* actor)
case PODFEM1:
case NAKED1:
case STATUE:
if (actor->spr.yint) fi.operaterespawns(actor->spr.yint);
if (actor->spr.yint) operaterespawns(actor->spr.yint);
break;
default:
if (actor->spr.hitag >= 0) fi.operaterespawns(actor->spr.hitag);
if (actor->spr.hitag >= 0) operaterespawns(actor->spr.hitag);
break;
}
}

View file

@ -568,53 +568,6 @@ int ifhitbyweapon_r(DDukeActor *actor)
//
//---------------------------------------------------------------------------
void respawn_rrra(DDukeActor* oldact, DDukeActor* newact)
{
newact->spr.pal = oldact->spr.pal;
if (newact->spr.picnum == MAMA)
{
if (newact->spr.pal == 30)
{
newact->spr.scale = DVector2(0.40625, 0.40625);
newact->clipdist = 18.75;
}
else if (newact->spr.pal == 31)
{
newact->spr.scale = DVector2(0.5625, 0.5625);
newact->clipdist = 25;
}
else if (newact->spr.pal == 32)
{
newact->spr.scale = DVector2(0.78125, 0.78125);
newact->clipdist = 25;
}
else
{
newact->spr.scale = DVector2(0.78125, 0.78125);
newact->clipdist = 25;
}
}
if (newact->spr.pal == 8)
{
newact->spr.cstat |= CSTAT_SPRITE_TRANSLUCENT;
}
if (newact->spr.pal != 6)
{
deletesprite(oldact);
return;
}
oldact->spr.extra = (66 - 13);
newact->spr.pal = 0;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void movefallers_r(void)
{
DukeStatIterator it(STAT_FALLER);
@ -1746,20 +1699,10 @@ static void rrra_specialstats()
}
}
it.Reset(119);
it.Reset(STAT_RABBITSPAWN);
while (auto act = it.Next())
{
if (act->spr.hitag > 0)
{
if (act->spr.extra == 0)
{
act->spr.hitag--;
act->spr.extra = 150;
spawn(act, RABBIT);
}
else
act->spr.extra--;
}
CallTick(act);
}
it.Reset(116);
while (auto act = it.Next())
@ -3795,10 +3738,10 @@ void respawnhitag_r(DDukeActor *actor)
case FEM10:
case NAKED1:
case STATUE:
if (actor->spr.yint) fi.operaterespawns(actor->spr.yint);
if (actor->spr.yint) operaterespawns(actor->spr.yint);
break;
default:
if (actor->spr.hitag >= 0) fi.operaterespawns(actor->spr.hitag);
if (actor->spr.hitag >= 0) operaterespawns(actor->spr.hitag);
break;
}
}

View file

@ -274,6 +274,7 @@ enum
STAT_DESTRUCT = 100,
STAT_BOWLING = 105,
STAT_RABBITSPAWN = 119,
STAT_REMOVED = MAXSTATUS-2,
STAT_NETALLOC = MAXSTATUS-1
};

View file

@ -39,8 +39,6 @@ bool isadoorwall_d(int dapic);
bool isadoorwall_r(int dapic);
void animatewalls_d(void);
void animatewalls_r(void);
void operaterespawns_d(int low);
void operaterespawns_r(int low);
void operateforcefields_r(DDukeActor* act, int low);
void operateforcefields_d(DDukeActor* act, int low);
bool checkhitswitch_d(int snum, walltype* w, DDukeActor *act);
@ -114,7 +112,6 @@ void SetDispatcher()
initactorflags_d,
isadoorwall_d,
animatewalls_d,
operaterespawns_d,
operateforcefields_d,
checkhitswitch_d,
activatebysector_d,
@ -157,7 +154,6 @@ void SetDispatcher()
initactorflags_r,
isadoorwall_r,
animatewalls_r,
operaterespawns_r,
operateforcefields_r,
checkhitswitch_r,
activatebysector_r,

View file

@ -73,7 +73,6 @@ struct Dispatcher
void (*initactorflags)();
bool (*isadoorwall)(int dapic);
void (*animatewalls)();
void (*operaterespawns)(int low);
void (*operateforcefields)(DDukeActor* act, int low);
bool (*checkhitswitch)(int snum, walltype* w, DDukeActor* act);
void (*activatebysector)(sectortype* sect, DDukeActor* j);
@ -122,6 +121,7 @@ void CallAction(DDukeActor* actor);
void CallOnHit(DDukeActor* actor, DDukeActor* hitter);
void CallOnHurt(DDukeActor* actor, player_struct* hitter);
bool CallOnUse(DDukeActor* actor, player_struct* user);
void CallOnRespawn(DDukeActor* actor, int low);
bool CallAnimate(DDukeActor* actor, tspritetype* hitter);

View file

@ -26,6 +26,7 @@ void resetlanepics(void);
void moveplayers();
void doanimations();
void movefx();
void operaterespawns(int low);
void moveclouds(double interpfrac);
void movefta();
@ -85,7 +86,6 @@ void handle_se35(DDukeActor* i, int SMALLSMOKE, int EXPLOSION2);
void handle_se128(DDukeActor* i);
void handle_se130(DDukeActor* i, int countmax, int EXPLOSION2);
void respawn_rrra(DDukeActor* oldact, DDukeActor* newact);
void check_fta_sounds_d(DDukeActor* i);
void check_fta_sounds_r(DDukeActor* i);

View file

@ -458,6 +458,15 @@ bool CallOnUse(DDukeActor* actor, player_struct* user)
return nval;
}
void CallOnRespawn(DDukeActor* actor, int low)
{
IFVIRTUALPTR(actor, DDukeActor, onRespawn)
{
VMValue val[2] = { actor, low };
VMCall(func, val, 2, nullptr, 0);
}
}
bool CallAnimate(DDukeActor* actor, tspritetype* tspr)
{
int nval = false;

View file

@ -24,6 +24,11 @@ inline int issoundcontroller(DDukeActor* actor)
return actor->GetClass()->TypeName == NAME_DukeSoundController;
}
inline int isrespawncontroller(DDukeActor* actor)
{
return actor->GetClass()->TypeName == NAME_DukeRespawnController;
}
inline int badguypic(int const tileNum)
{
return ((gs.actorinfo[tileNum].flags & (SFLAG_INTERNAL_BADGUY | SFLAG_BADGUY)) != 0);

View file

@ -1103,7 +1103,7 @@ y(RRTILE7213, 7213)
y(RRTILE7219, 7219)
x(EMPTYBIKE, 7220)
x(EMPTYBOAT, 7233)
y(RRTILE7424, 7424)
y(RABBITSPAWNER, 7424)
y(RRTILE7430, 7430)
y(RRTILE7433, 7433)
y(RRTILE7441, 7441)

View file

@ -394,7 +394,7 @@ void dokneeattack(int snum, const std::initializer_list<int> & respawnlist)
if (isIn(p->actorsqu->spr.picnum, respawnlist))
{
if (p->actorsqu->spr.yint)
fi.operaterespawns(p->actorsqu->spr.yint);
operaterespawns(p->actorsqu->spr.yint);
}
if (p->actorsqu->isPlayer())

View file

@ -51,7 +51,6 @@ void premapcontroller(DDukeActor* ac)
case ACTIVATORLOCKED:
case LOCATORS:
case MUSICANDSFX:
case RESPAWN:
case SECTOREFFECTOR:
ac->spr.cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN | CSTAT_SPRITE_ALIGNMENT_MASK);
break;

View file

@ -1187,7 +1187,7 @@ void operateactivators(int low, player_struct* plr)
}
}
fi.operaterespawns(low);
operaterespawns(low);
}
//---------------------------------------------------------------------------

View file

@ -186,34 +186,6 @@ void animatewalls_d(void)
//
//---------------------------------------------------------------------------
void operaterespawns_d(int low)
{
DukeStatIterator it(STAT_FX);
while (auto act = it.Next())
{
if (act->spr.lotag == low) switch (act->spr.picnum)
{
case RESPAWN:
if (badguypic(act->spr.hitag) && ud.monsters_off) break;
auto star = spawn(act, TRANSPORTERSTAR);
if (star)
{
star->spr.pos.Z -= 32;
act->spr.extra = 66 - 12; // Just a way to killit
}
break;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void operateforcefields_d(DDukeActor* act, int low)
{
operateforcefields_common(act, low, { W_FORCEFIELD, W_FORCEFIELD + 1, W_FORCEFIELD + 2, BIGFORCE });

View file

@ -301,38 +301,6 @@ void animatewalls_r(void)
//
//---------------------------------------------------------------------------
void operaterespawns_r(int low)
{
DukeStatIterator it(STAT_FX);
while (auto act = it.Next())
{
if (act->spr.lotag == low) switch (act->spr.picnum)
{
case RESPAWN:
{
if (badguypic(act->spr.hitag) && ud.monsters_off) break;
auto star = spawn(act, TRANSPORTERSTAR);
if (star) star->spr.pos.Z -= 32;
act->spr.extra = 66 - 12; // Just a way to killit
break;
}
case RRTILE7424:
if (isRRRA() && !ud.monsters_off)
ChangeActorStat(act, 119);
break;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void operateforcefields_r(DDukeActor* act, int low)
{
operateforcefields_common(act, low, { BIGFORCE });

View file

@ -63,7 +63,7 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
case BOSS5:
if (act->spr.picnum != FIREFLY)
{
if (actj && actj->spr.picnum == RESPAWN)
if (actj && isrespawncontroller(actj))
act->spr.pal = actj->spr.pal;
if (act->spr.pal != 0)
{
@ -710,7 +710,7 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
if (bossguy(act))
{
if (actj && actj->spr.picnum == RESPAWN)
if (actj && isrespawncontroller(actj))
act->spr.pal = actj->spr.pal;
if (act->spr.pal && (!isWorldTour() || !(currentLevel->flags & LEVEL_WT_BOSSSPAWN) || act->spr.pal != 22))
{

View file

@ -93,12 +93,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
act->spr.hitag = 0;
ChangeActorStat(act, 117);
break;
case RRTILE7424:
if (!isRRRA()) goto default_case;
act->spr.extra = 0;
act->spr.scale = DVector2(0, 0);
ChangeActorStat(act, STAT_FX);
break;
case RRTILE7936:
if (!isRRRA()) goto default_case;
act->spr.scale = DVector2(0, 0);
@ -569,17 +563,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
case SHOTGUNSHELL:
initshell(actj, act, act->spr.picnum == SHELL);
break;
case RESPAWN:
act->spr.extra = 66 - 13;
if (ud.multimode < 2 && act->spr.pal == 1)
{
act->spr.scale = DVector2(0, 0);
ChangeActorStat(act, STAT_MISC);
break;
}
act->spr.cstat = CSTAT_SPRITE_INVISIBLE;
ChangeActorStat(act, STAT_FX);
break;
case SOUNDFX:
{
act->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
@ -829,6 +812,9 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
act->spr.pos.Z += krandf(8) - 4;
break;
case MAMA:
if (actj && isrespawncontroller(actj))
act->spr.pal = actj->spr.pal;
if (act->spr.pal == 30)
{
act->spr.scale = DVector2(0.40625, 0.40625);

View file

@ -114,6 +114,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, GetSoundFlags, S_GetUserFlags)
ACTION_RETURN_INT(S_GetUserFlags(snd));
}
DEFINE_ACTION_FUNCTION_NATIVE(_Duke, badguyID, badguypic)
{
PARAM_PROLOGUE;
PARAM_INT(p);
ACTION_RETURN_INT(badguypic(p));
}
DEFINE_GLOBAL_UNSIZED(dlevel)
DEFINE_GLOBAL(camsprite)
@ -261,15 +268,23 @@ DDukeActor* DukeActor_Spawn(DDukeActor* origin, int intname)
{
picnum = TileFiles.tileForName("BURNIMG");
}
if (FName(ENamedName(intname)) == FName("DukeBloodPool"))
else if (FName(ENamedName(intname)) == FName("DukeBloodPool"))
{
picnum = TileFiles.tileForName("BLOODPOOL");
}
if (FName(ENamedName(intname)) == FName("DukeExplosion2"))
else if (FName(ENamedName(intname)) == FName("DukeExplosion2"))
{
picnum = TileFiles.tileForName("EXPLOSION2");
}
else if (FName(ENamedName(intname)) == FName("DukeTransporterStar"))
{
picnum = TileFiles.tileForName("TRANSPORTERSTAR");
}
else if (FName(ENamedName(intname)) == FName("RedneckRabbit"))
{
picnum = TileFiles.tileForName("RABBIT");
}
if (picnum == -1)
{

View file

@ -3,6 +3,7 @@ spawnclasses
3 = DukeTouchplate
5 = DukeSoundController
8 = DukeMasterSwitch
9 = DukeRespawnController
1221 = DukeCranePole
1222 = DukeCrane

View file

@ -0,0 +1,4 @@
spawnclasses
{
7424 = RedneckRabbitSpawner
}

View file

@ -3,6 +3,7 @@ spawnclasses
3 = DukeTouchplate
5 = DukeSoundController
8 = DukeMasterSwitch
9 = DukeRespawnController
1298 = DukeCranePole
1299 = DukeCrane

View file

@ -53,6 +53,7 @@ version "4.10"
#include "zscript/games/duke/actors/masterswitch.zs"
#include "zscript/games/duke/actors/touchplate.zs"
#include "zscript/games/duke/actors/soundcontroller.zs"
#include "zscript/games/duke/actors/respawncontroller.zs"
#include "zscript/games/duke/actors/crane.zs"
#include "zscript/games/duke/actors/waterfountain.zs"
#include "zscript/games/duke/actors/flammables.zs"
@ -69,6 +70,8 @@ version "4.10"
#include "zscript/games/duke/actors/viewscreen.zs"
#include "zscript/games/duke/actors/canwithsomething.zs"
#include "zscript/games/duke/actors/rabbitspawner.zs"
#include "zscript/games/blood/bloodgame.zs"
#include "zscript/games/blood/ui/menu.zs"
#include "zscript/games/blood/ui/sbar.zs"

View file

@ -0,0 +1,43 @@
class RedneckRabbitSpawner : DukeActor
{
default
{
statnum STAT_FX;
extra 0;
}
override void Initialize()
{
self.cstat = CSTAT_SPRITE_INVISIBLE;
}
override void Tick()
{
if (self.statnum == STAT_RABBITSPAWN)
{
if (self.hitag > 0)
{
if (self.extra == 0)
{
self.hitag--;
self.extra = 150;
self.spawn("RedneckRabbit");
}
else
self.extra--;
}
}
}
override void onRespawn(int low)
{
if (self.lotag == low)
{
if (!ud.monsters_off)
self.ChangeStat(STAT_RABBITSPAWN);
}
}
}

View file

@ -0,0 +1,67 @@
class DukeRespawnController : DukeActor
{
default
{
statnum STAT_FX;
extra 66 - 13;
}
override void Initialize()
{
if (ud.multimode < 2 && self.pal == 1)
{
self.scale = (0, 0);
self.ChangeStat(STAT_MISC);
}
else
self.cstat = CSTAT_SPRITE_INVISIBLE;
}
override void Tick()
{
if (self.extra == 66)
{
let newact = self.spawnsprite(self.hitag);
if (Raze.isRRRA() && newact)
{
newact.pal = self.pal;
// RRRA's ghost monsters.
if (newact.pal == 8)
{
newact.cstat |= CSTAT_SPRITE_TRANSLUCENT;
}
if (newact.pal != 6)
{
self.Destroy();
return;
}
self.extra = (66 - 13);
newact.pal = 0;
}
else
{
self.Destroy();
}
}
else if (self.extra > (66 - 13))
self.extra++;
}
override void onRespawn(int low)
{
if (self.lotag == low)
{
if (Duke.badguyID(self.hitag) && ud.monsters_off) return;
let star = self.spawn("DukeTransporterStar");
if (star)
{
star.pos.Z -= 32;
}
self.extra = 66 - 12; // Trigger the spawn countdown
}
}
}

View file

@ -81,6 +81,7 @@ class DukeSoundController : DukeActor
override void OnDestroy()
{
Super.OnDestroy();
if (self.temp_data[0] == 1)
self.StopSound(self.lotag);
}

View file

@ -93,7 +93,6 @@ class DukeTouchPlate : DukeActor
{
if (self.temp_data[0] == 0 && !dlevel.check_activator_motion(self.lotag))
{
Console.Printf("Trigger %d", self.spawnindex);
self.temp_data[0] = 1;
self.temp_data[1] = 1;
self.temp_data[3] = !self.temp_data[3];

View file

@ -102,6 +102,7 @@ class DukeActor : CoreActor native
STAT_DESTRUCT = 100,
STAT_BOWLING = 105,
STAT_RABBITSPAWN = 119,
STAT_REMOVED = MAXSTATUS-2,
@ -172,6 +173,7 @@ class DukeActor : CoreActor native
virtual void onHit(DukeActor hitter) { checkhitdefault(hitter); }
virtual void onHurt(DukePlayer p) {}
virtual bool onUse(DukePlayer user) { return false; }
virtual void onRespawn(int tag) { }
virtual bool animate(tspritetype tspr) { return false; }
virtual void RunState() {} // this is the CON function.

View file

@ -100,6 +100,7 @@ struct Duke native
native static int floorflags(sectortype s);
native static int global_random();
native static int GetSoundFlags(int sound);
native static int badguyID(int id);
static void PlayBonusMusic()
{