From 9783b8c40256b0168d77092935d975e4c8afdbc6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Dec 2022 00:58:04 +0100 Subject: [PATCH] - scriptified World Tour's flamethrowerflame. The first of 3 mixed native/CON items which are the last things remaining in the main thinker loops. --- source/core/vmexports.cpp | 1 + source/games/duke/src/actors.cpp | 6 +- source/games/duke/src/actors_d.cpp | 134 +----------- source/games/duke/src/player_d.cpp | 89 -------- source/games/duke/src/vmexports.cpp | 14 ++ .../duke.worldtour/rmapinfo.spawnclasses | 1 + wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/coreactor.zs | 1 + .../games/duke/actors/flamethrowerflame.zs | 192 ++++++++++++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 22 ++ wadsrc/static/zscript/games/duke/dukegame.zs | 2 + wadsrc/static/zscript/razebase.zs | 5 + 12 files changed, 244 insertions(+), 224 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index 928312081..4754510ac 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -822,6 +822,7 @@ DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Yaw, angle) DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Pitch, pitch) DEFINE_FIELD(DCoreActor, vel) DEFINE_FIELD(DCoreActor, viewzoffset) +DEFINE_FIELD(DCoreActor, oviewzoffset) DEFINE_FIELD(DCoreActor, opos) void coreactor_setpos(DCoreActor* self, double x, double y, double z, int relink) diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 4bf59a4d1..3e8275250 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -577,9 +577,11 @@ void tickstat(int stat, bool deleteinvalid) if (actorflag(act, SFLAG2_DIENOW) || act->sector() == nullptr || (deleteinvalid && act->spr.scale.X == 0)) { act->Destroy(); - continue; } - CallTick(act); + else if (stat != STAT_ACTOR || !badguy(act) || !monsterCheatCheck(act)) + { + CallTick(act); + } } } diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index f4d0343f5..912965d68 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -991,138 +991,6 @@ void movetransports_d(void) // //--------------------------------------------------------------------------- -static void flamethrowerflame(DDukeActor *actor) -{ - auto sectp = actor->sector(); - 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) - { - spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127; - actor->Destroy(); - return; - } - - auto dapos = actor->spr.pos; - - getglobalz(actor); - - int ds = actor->temp_data[0] / 6; - if (actor->spr.scale.X < 0.1250) - { - actor->spr.scale.X += (ds * REPEAT_SCALE); - actor->spr.scale.Y = (actor->spr.scale.X); - } - actor->clipdist += ds * 0.25; - if (actor->temp_data[0] <= 2) - actor->temp_data[3] = krand() % 10; - if (actor->temp_data[0] > 30) - { - spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127; - actor->Destroy(); - return; - } - - Collision coll; - movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK1, coll); - - if (!actor->insector()) - { - actor->Destroy(); - return; - } - - if (coll.type != kHitSprite) - { - if (actor->spr.pos.Z < actor->ceilingz) - { - coll.setSector(actor->sector()); - actor->vel.Z -= 1/256.; - } - else if ((actor->spr.pos.Z > actor->floorz && actor->sector()->lotag != 1) - || (actor->spr.pos.Z > actor->floorz + 16 && actor->sector()->lotag == 1)) - { - coll.setSector(actor->sector()); - if (actor->sector()->lotag != 1) - actor->vel.Z += 1/256.; - } - } - - if (coll.type != 0) { - actor->vel.XY().Zero(); - actor->vel.Z = 0; - if (coll.type == kHitSprite) - { - fi.checkhitsprite(coll.actor(), actor); - if (coll.actor()->isPlayer()) - S_PlayActorSound(PISTOL_BODYHIT, coll.actor()); - } - else if (coll.type == kHitWall) - { - SetActor(actor, dapos); - checkhitwall(actor, coll.hitWall, actor->spr.pos); - } - else if (coll.type == kHitSector) - { - SetActor(actor, dapos); - if (actor->vel.Z < 0) - checkhitceiling(actor->sector()); - } - - if (actor->spr.scale.X >= 0.15625) - { - int x = actor->spr.extra; - fi.hitradius(actor, gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); - } - else - { - int x = actor->spr.extra + (global_random & 3); - fi.hitradius(actor, (gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); - } - } -} - - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void moveactors_d(void) -{ - DukeStatIterator it(STAT_ACTOR); - while (auto act = it.Next()) - { - if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW)) - { - act->Destroy(); - } - else if (monsterCheatCheck(act) && badguy(act)) - { - continue; - } - else if (isWorldTour() && act->spr.picnum == DTILE_FLAMETHROWERFLAME) - { - flamethrowerflame(act); - } - else - { - CallTick(act); - } - } - -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - static void fireflyflyingeffect(DDukeActor *actor) { double xx; @@ -1745,7 +1613,7 @@ void think_d(void) actortime.Reset(); actortime.Clock(); - moveactors_d(); //ST 1 + tickstat(STAT_ACTOR); //ST 1 actortime.Unclock(); moveeffectors_d(); //ST 3 diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 0c95b9feb..f7d6e972f 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -140,91 +140,6 @@ static void shootfireball(DDukeActor *actor, int p, DVector3 pos, DAngle ang) // //--------------------------------------------------------------------------- -static void shootflamethrowerflame(DDukeActor* actor, int p, DVector3 spos, DAngle sang) -{ - double vel, zvel = 0; - - if (actor->spr.extra >= 0) - actor->spr.shade = -96; - vel = 25; - - DDukeActor* spawned = nullptr; - if (p < 0) - { - double x; - int j = findplayer(actor, &x); - sang = (ps[j].GetActor()->opos.XY() - spos.XY()).Angle(); - - if (actor->spr.picnum == DTILE_BOSS5) - { - vel = 33; - spos.Z += 24; - } - else if (actor->spr.picnum == DTILE_BOSS3) - spos.Z -= 32; - - double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length(); - if (dist != 0) - zvel = (((ps[j].GetActor()->getPrevOffsetZ() - spos.Z) * vel) / dist); - - if (badguy(actor) && (actor->spr.hitag & face_player_smart) != 0) - sang = actor->spr.Angles.Yaw + mapangle((krand() & 31) - 16); - - if (actor->sector()->lotag == 2 && (krand() % 5) == 0) - spawned = spawn(actor, DTILE_WATERBUBBLE); - } - else - { - setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5); - - // WTF??? - DAngle myang = DAngle90 - (DAngle180 - abs(abs((spos.XY() - ps[p].GetActor()->spr.pos.XY()).Angle() - sang) - DAngle180)); - if (ps[p].GetActor()->vel.X != 0) - vel = ((myang / DAngle90) * ps[p].GetActor()->vel.X) + 25; - if (actor->sector()->lotag == 2 && (krand() % 5) == 0) - spawned = spawn(actor, DTILE_WATERBUBBLE); - } - - if (spawned == nullptr) - { - spawned = spawn(actor, DTILE_FLAMETHROWERFLAME); - if (!spawned) return; - spawned->vel.X = vel; - spawned->vel.Z = zvel; - } - - - DVector3 offset; - offset.X = (sang + DAngle::fromBuild(118)).Cos() * (1024 / 448.); // Yes, these angles are really different! - offset.Y = (sang + DAngle::fromBuild(112)).Sin() * (1024 / 448.); - offset.Z = -1; - - spawned->spr.pos = spos + offset; - spawned->spr.pos.Z--; - spawned->setsector(actor->sector()); - spawned->spr.cstat = CSTAT_SPRITE_YCENTER; - spawned->spr.Angles.Yaw = sang; - spawned->spr.scale = DVector2(0.03125, 0.03125); - spawned->clipdist = 10; - spawned->spr.yint = p; - spawned->SetOwner(actor); - - if (p == -1) - { - if (actor->spr.picnum == DTILE_BOSS5) - { - spawned->spr.pos += sang.ToVector() * (128. / 7); - spawned->spr.scale = DVector2(0.15625, 0.15625); - } - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - static void shootknee(DDukeActor* actor, int p, DVector3 pos, DAngle ang) { auto sectp = actor->sector(); @@ -1074,10 +989,6 @@ void shoot_d(DDukeActor* actor, int atwith, PClass *cls) shootfireball(actor, p, spos, sang); return; - case DTILE_FLAMETHROWERFLAME: - shootflamethrowerflame(actor, p, spos, sang); - return; - case DTILE_FIREFLY: // DTILE_BOSS5 shot { auto k = spawn(actor, atwith); diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 2e1c7cb4e..2651449e6 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -212,6 +212,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, StopCommentary, StopCommentary) return 0; } +int getPlayerIndex(player_struct* p) +{ + if (!p) return -1; + return int(p - ps); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Duke, getPlayerIndex, getPlayerIndex) +{ + PARAM_PROLOGUE; + PARAM_POINTER(p, player_struct); + ACTION_RETURN_INT(getPlayerIndex(p)); + return 0; +} + DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL(camsprite) diff --git a/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses b/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses index d0cdb2a38..d17dcaeb1 100644 --- a/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses +++ b/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses @@ -5,4 +5,5 @@ spawnclasses 5736 = DukeGenericDestructible, "WTGLASS1", "", "GLASS_BREAKING", spawnglass 5737 = DukeGenericDestructible, "WTGLASS2", "", "GLASS_BREAKING", spawnglass 5294 = DeveloperCommentary + 1891 = DukeFlamethrowerFlame } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 0d28984f8..edcdf53a7 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -102,6 +102,7 @@ version "4.10" #include "zscript/games/duke/actors/bloodpool.zs" #include "zscript/games/duke/actors/toilet.zs" +#include "zscript/games/duke/actors/flamethrowerflame.zs" #include "zscript/games/duke/actors/redneckmisc.zs" #include "zscript/games/duke/actors/emptybike.zs" diff --git a/wadsrc/static/zscript/coreactor.zs b/wadsrc/static/zscript/coreactor.zs index 4169c41ba..8ad6ce4dd 100644 --- a/wadsrc/static/zscript/coreactor.zs +++ b/wadsrc/static/zscript/coreactor.zs @@ -57,6 +57,7 @@ class CoreActor native native double pitch; native Vector3 vel; native double viewzoffset; + native double oviewzoffset; native readonly int16 spritesetindex; native readonly int spawnindex; diff --git a/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs b/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs new file mode 100644 index 000000000..90d8ec331 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs @@ -0,0 +1,192 @@ +class DukeFlamethrowerFlame : DukeActor +{ + default + { + pic "FLAMETHROWERFLAME"; + } + + override void Tick() + { + Console.Printf("ticky"); + let sectp = self.sector; + double xx; + Super.Tick(); // Run CON or its replacement. + if (self.bDestroyed) return; // killed by script. + self.temp_data[0]++; + if (sectp.lotag == ST_2_UNDERWATER) + { + let spawned = self.spawn("DukeExplosion2"); + if (spawned) spawned.shade = 127; + self.Destroy(); + return; + } + + let dapos = self.pos; + + self.getglobalz(); + + int ds = self.temp_data[0] / 6; + if (self.scale.X < 0.1250) + { + self.scale.X += (ds * REPEAT_SCALE); + self.scale.Y = (self.scale.X); + } + self.clipdist += ds * 0.25; + if (self.temp_data[0] <= 2) + self.temp_data[3] = random(0, 9); + if (self.temp_data[0] > 30) + { + let spawned = self.spawn("DukeExplosion2"); + if (spawned) spawned.shade = 127; + self.Destroy(); + return; + } + + CollisionData coll; + self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK1, coll); + + if (self.sector == null) + { + self.Destroy(); + return; + } + + if (coll.type != kHitSprite) + { + if (self.pos.Z < self.ceilingz) + { + coll.setSector(self.sector); + self.vel.Z -= 1/256.; + } + else if ((self.pos.Z > self.floorz && self.sector.lotag != ST_1_ABOVE_WATER) + || (self.pos.Z > self.floorz + 16 && self.sector.lotag == ST_1_ABOVE_WATER)) + { + coll.setSector(self.sector); + if (self.sector.lotag != 1) + self.vel.Z += 1/256.; + } + } + + if (coll.type != 0) + { + self.vel.XY = (0, 0); + self.vel.Z = 0; + if (coll.type == kHitSprite) + { + let hitact = DukeActor(coll.hitActor()); + hitact.checkhitsprite(self); + if (hitact.isPlayer()) + hitact.PlayActorSound("PISTOL_BODYHIT"); + } + else if (coll.type == kHitWall) + { + self.SetPosition(dapos); + dlevel.checkhitwall(coll.hitWall(), self, self.pos); + } + else if (coll.type == kHitSector) + { + self.SetPosition(dapos); + if (self.vel.Z < 0) + dlevel.checkhitceiling(self.sector, self); + } + + if (self.scale.X >= 0.15625) + { + int x = self.extra; + self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); + } + else + { + int x = self.extra + (Duke.global_random() & 3); + self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); + } + } + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + override bool shootthis(DukeActor actor, DukePlayer p, Vector3 spos, double sang) const + { + Console.Printf("launching"); + double vel, zvel = 0; + + if (actor.extra >= 0) + actor.shade = -96; + vel = 25; + + DukeActor spawned = nullptr; + if (p == null) + { + double x; + DukePlayer j; + [j, x] = actor.findplayer(); + sang = (j.Actor.opos.XY - spos.XY).Angle(); + + if (actor.checktype("BOSS5")) + { + vel = 33; + spos.Z += 24; + } + else if (actor.checktype("BOSS3")) + spos.Z -= 32; + + double dist = (j.actor.pos.XY - actor.pos.XY).Length(); + if (dist != 0) + zvel = (((j.actor.opos.Z + j.actor.oviewzoffset - spos.Z) * vel) / dist); + + if (actor.badguy() && (actor.hitag & face_player_smart) != 0) + sang = actor.Angle + Raze.BAngToDegree * random(-16, 15); + + } + else + { + [vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 40.5); + + // WTF??? + double myang = 90. - (180. - abs(abs((spos.XY - p.actor.pos.XY).Angle() - sang) - 180.)); + if (p.actor.vel.X != 0) + vel = ((myang / 90.) * p.actor.vel.X) + 25; + } + + if (actor.sector.lotag == ST_2_UNDERWATER && (random(0, 4)) == 0) + spawned = actor.spawn("DukeWaterBubble"); + + if (spawned == nullptr) + { + spawned = actor.spawn("DukeFlamethrowerFlame"); + if (!spawned) return true; + spawned.vel.X = vel; + spawned.vel.Z = zvel; + } + + + Vector3 offset; + offset.X = cos(sang + Raze.BAngToDegree * 118) * (1024 / 448.); // Yes, these angles are really different! + offset.Y = sin(sang + Raze.BAngToDegree * 112) * (1024 / 448.); + offset.Z = -1; + + spawned.pos = spos + offset; + spawned.pos.Z--; + spawned.sector = actor.sector; + spawned.cstat = CSTAT_SPRITE_YCENTER; + spawned.Angle = sang; + spawned.scale = (0.03125, 0.03125); + spawned.clipdist = 10; + spawned.yint = Duke.GetPlayerIndex(p); + spawned.ownerActor = actor; + + if (p == null) + { + if (actor.checktype("BOSS5")) + { + spawned.pos += sang.ToVector() * (128. / 7); + spawned.scale = (0.15625, 0.15625); + } + } + return true; + } +} diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 7e8cf73cb..a5a4ab80a 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -115,6 +115,28 @@ class DukeActor : CoreActor native STAT_REMOVED = MAXSTATUS-2, }; + + enum amoveflags_t + { + face_player = 1, + geth = 2, + getv = 4, + random_angle = 8, + face_player_slow = 16, + spin = 32, + face_player_smart = 64, + fleeenemy = 128, + jumptoplayer_only = 256, + justjump1 = 256, + jumptoplayer = 257, + seekplayer = 512, + furthestdir = 1024, + dodgebullet = 4096, + justjump2 = 8192, + windang = 16384, + antifaceplayerslow = 32768 + }; + native void SetSpritesetImage(int index); native int GetSpritesetSize(); diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index 90f66dd88..aeb545fb6 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -170,6 +170,7 @@ struct Duke native native static void updatepindisplay(int tag, int pinmask); native static bool StartCommentary(int tag, DukeActor act); native static void StopCommentary(); + static native int getPlayerIndex(DukePlayer p); static int rnd(int val) { return (random(0, 255) >= (255 - (val))); @@ -216,6 +217,7 @@ struct Duke native if (align != -1) x -= myfont.StringWidth(t) * (align == 0 ? 0.5 : 1); Screen.DrawText(myfont, Font.CR_NATIVEPAL, x, y + 2, t, DTA_FullscreenScale, fsmode, DTA_TranslationIndex, Translation.MakeID(Translation_Remap, trans), DTA_Color, Raze.shadeToLight(shade)); } + } struct DukePlayer native diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index 65ba5a27e..a3f412e33 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -264,6 +264,11 @@ struct Raze // Right now, with no MP support there is no need, though. } + static double, double setFreeAimVelocity(double vel, double zvel, double pitch, double zvspeed) + { + return vel * cos(pitch), sin(pitch) * zvspeed; + } + } /*