From 44d4e7a20a3d186a8168ae5062e49b80d3848b31 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2022 11:55:35 +0100 Subject: [PATCH] - scriptified the mortar projectiles. This was split off heavyhbomb for clarity and to avoid interference with the pickup code. --- source/games/duke/src/actors_d.cpp | 145 +----------- source/games/duke/src/actors_r.cpp | 173 +------------- source/games/duke/src/animatesprites_r.cpp | 7 - .../static/filter/dukelike/engine/engine.def | 2 + .../redneck.ridesagain/engine/engine.def | 1 + .../static/filter/redneck/engine/engine.def | 1 + wadsrc/static/zscript.txt | 1 + .../zscript/games/duke/actors/mortar.zs | 215 ++++++++++++++++++ 8 files changed, 222 insertions(+), 323 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/mortar.zs diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index f287262fb..9a30b0bde 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -1165,144 +1165,6 @@ static void flamethrowerflame(DDukeActor *actor) } } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void heavyhbomb(DDukeActor *actor) -{ - auto Owner = actor->GetOwner(); - auto sectp = actor->sector(); - int l; - double xx; - - int p = findplayer(actor, &xx); - - if (xx < 1220 / 16.) actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; - else actor->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; - - if (actor->temp_data[3] == 0) - { - int j = fi.ifhitbyweapon(actor); - if (j >= 0) - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 0; - l = 0; - actor->vel.X = 0; - goto DETONATEB; - } - } - - if (actor->spr.picnum != BOUNCEMINE) - { - makeitfall(actor); - - if (sectp->lotag != 1 && actor->spr.pos.Z >= actor->floorz - FOURSLEIGHT_F && actor->spr.yint < 3) - { - if (actor->spr.yint > 0 || (actor->spr.yint == 0 && actor->floorz == sectp->floorz)) - S_PlayActorSound(PIPEBOMB_BOUNCE, actor); - actor->vel.Z = -(4 - actor->spr.yint); - if (actor->sector()->lotag == 2) - actor->vel.Z *= 0.25; - actor->spr.yint++; - } - if (actor->spr.pos.Z < actor->ceilingz) // && sectp->lotag != 2 ) - { - actor->spr.pos.Z = actor->ceilingz + 3; - actor->vel.Z = 0; - } - } - - Collision coll; - movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll); - - if (actor->sector()->lotag == 1 && actor->vel.Z == 0) - { - actor->spr.pos.Z += 32; - if (actor->temp_data[5] == 0) - { - actor->temp_data[5] = 1; - spawn(actor, WATERSPLASH2); - } - } - else actor->temp_data[5] = 0; - - if (actor->temp_data[3] == 0 && (actor->spr.picnum == BOUNCEMINE || actor->spr.picnum == MORTER) && (coll.type || xx < 844/16.)) - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 0; - l = 0; - actor->vel.X = 0; - goto DETONATEB; - } - - if ( Owner && Owner->isPlayer()) - l = Owner->PlayerIndex(); - else l = -1; - - if(actor->vel.X > 0) - { - actor->vel.X -= 5. / 16; - if (sectp->lotag == 2) - actor->vel.X -= 10. / 16; - - if(actor->vel.X < 0) - actor->vel.X = 0; - if (int(actor->vel.X * 16) & 8) actor->spr.cstat ^= CSTAT_SPRITE_XFLIP; - } - - if (coll.type== kHitWall) - { - auto wal = coll.hitWall; - fi.checkhitwall(actor, wal, actor->spr.pos, actor->spr.picnum); - - DAngle k = wal->delta().Angle(); - actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw; - actor->vel.X *= 0.5; - } - -DETONATEB: - - if (actor->temp_data[3] == 1) - { - actor->temp_data[4]++; - - if (actor->temp_data[4] == 2) - { - int x = actor->spr.extra; - int m = 0; - switch (actor->spr.picnum) - { - case MORTER: m = gs.morterblastradius; break; - case BOUNCEMINE: m = gs.bouncemineblastradius; break; - } - - fi.hitradius(actor, m, x >> 2, x >> 1, x - (x >> 2), x); - spawn(actor, EXPLOSION2); - if (actor->vel.Z == 0) spawn(actor, EXPLOSION2BOT); - S_PlayActorSound(PIPEBOMB_EXPLODE, actor); - for (x = 0; x < 8; x++) - RANDOMSCRAP(actor); - } - - if (actor->spr.scale.Y) - { - actor->spr.scale.Y = (0); - return; - } - - if (actor->temp_data[4] > 20) - { - actor->Destroy(); - return; - } - } - - if (actor->temp_data[0] < 8) actor->temp_data[0]++; -} //--------------------------------------------------------------------------- // @@ -1334,18 +1196,13 @@ void moveactors_d(void) if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { CallTick(act); + continue; } else switch (act->spr.picnum) { case FLAMETHROWERFLAME: if (isWorldTour()) flamethrowerflame(act); continue; - - case BOUNCEMINE: - case MORTER: - spawn(act, FRAMEEFFECT1)->temp_data[0] = 3; - heavyhbomb(act); - continue; } if (monsterCheatCheck(act) && badguy(act)) { diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 39f0017a9..a3bb0e0a7 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -1254,171 +1254,6 @@ void rr_specialstats() // //--------------------------------------------------------------------------- -static void heavyhbomb(DDukeActor *actor) -{ - auto sectp = actor->sector(); - int l; - double xx; - auto Owner = actor->GetOwner(); - - if ((actor->spr.cstat & CSTAT_SPRITE_INVISIBLE)) - { - actor->temp_data[2]--; - if (actor->temp_data[2] <= 0) - { - S_PlayActorSound(TELEPORTER, actor); - spawn(actor, TRANSPORTERSTAR); - actor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - } - return; - } - - int p = findplayer(actor, &xx); - - makeitfall(actor); - - if (sectp->lotag != 1 && (!isRRRA() || sectp->lotag != ST_160_FLOOR_TELEPORT) && actor->spr.pos.Z >= actor->floorz - FOURSLEIGHT_F && actor->spr.yint < 3) - { - if (actor->spr.yint > 0 || (actor->spr.yint == 0 && actor->floorz == sectp->floorz)) - { - if (actor->spr.picnum != CHEERBOMB) - S_PlayActorSound(PIPEBOMB_BOUNCE, actor); - else - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 1; - l = 0; - goto DETONATEB; - } - } - actor->vel.Z = -(4 - actor->spr.yint); - if (actor->sector()->lotag == 2) - actor->vel.Z *= 0.25; - actor->spr.yint++; - } - if (actor->spr.picnum != CHEERBOMB && actor->spr.pos.Z < actor->ceilingz + 16 && sectp->lotag != 2) - { - actor->spr.pos.Z = actor->ceilingz + 16; - actor->vel.Z = 0; - } - - Collision coll; - movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll); - - if (actor->sector()->lotag == 1 && actor->vel.Z == 0) - { - actor->spr.pos.Z += 32; - if (actor->temp_data[5] == 0) - { - actor->temp_data[5] = 1; - spawn(actor, WATERSPLASH2); - if (isRRRA() && actor->spr.picnum == MORTER) - actor->vel.X = 0; - } - } - else actor->temp_data[5] = 0; - - if (actor->temp_data[3] == 0 && actor->spr.picnum == MORTER && (coll.type || xx < 844 / 16.)) - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 0; - l = 0; - actor->vel.X = 0; - goto DETONATEB; - } - - if (actor->temp_data[3] == 0 && actor->spr.picnum == CHEERBOMB && (coll.type || xx < 844 / 16.)) - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 0; - l = 0; - actor->vel.X = 0; - goto DETONATEB; - } - - if (Owner && Owner->isPlayer()) - l = Owner->PlayerIndex(); - else l = -1; - - if(actor->vel.X > 0) - { - actor->vel.X -= 5. / 16; - if (sectp->lotag == 2) - actor->vel.X -= 10. / 16; - - if(actor->vel.X < 0) - actor->vel.X = 0; - if (int(actor->vel.X * 16) & 8) actor->spr.cstat ^= CSTAT_SPRITE_XFLIP; - } - - if (coll.type == kHitWall) - { - auto wal = coll.hitWall; - fi.checkhitwall(actor, wal, actor->spr.pos, actor->spr.picnum); - - if (actor->spr.picnum == CHEERBOMB) - { - actor->temp_data[3] = 1; - actor->temp_data[4] = 0; - l = 0; - actor->vel.X = 0; - goto DETONATEB; - } - DAngle k = wal->delta().Angle(); - actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw; - actor->vel.X *= 0.5; - } - -DETONATEB: - - if (actor->temp_data[3] == 1) - { - actor->temp_data[4]++; - - if (actor->temp_data[4] == 2) - { - int x = actor->spr.extra; - int m = gs.morterblastradius; - - if (actor->sector()->lotag != 800) - { - fi.hitradius(actor, m, x >> 2, x >> 1, x - (x >> 2), x); - spawn(actor, EXPLOSION2); - if (actor->spr.picnum == CHEERBOMB) - spawn(actor, BURNING); - S_PlayActorSound(PIPEBOMB_EXPLODE, actor); - for (x = 0; x < 8; x++) - RANDOMSCRAP(actor); - } - } - - if (actor->spr.scale.Y) - { - actor->spr.scale.Y = (0); - return; - } - - if (actor->temp_data[4] > 20) - { - actor->Destroy(); - return; - } - if (actor->spr.picnum == CHEERBOMB) - { - spawn(actor, BURNING); - actor->Destroy(); - return; - } - } - if (actor->temp_data[0] < 8) actor->temp_data[0]++; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - static int henstand(DDukeActor *actor) { if (actor->spr.picnum == HENSTAND || actor->spr.picnum == HENSTAND + 1) @@ -1535,6 +1370,7 @@ void moveactors_r(void) if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { CallTick(act); + continue; } else switch(act->spr.picnum) { @@ -1590,13 +1426,6 @@ void moveactors_r(void) act->vel.X -= 1. / 16.; } break; - - case CHEERBOMB: - if (!isRRRA()) break; - [[fallthrough]]; - case MORTER: - heavyhbomb(act); - continue; } diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index eb7326636..9396e07bf 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -205,13 +205,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi case CRYSTALAMMO: t->shade = int(BobVal(PlayClock << 4) * 16); break; - case CHEERBOMB: - if (isRRRA()) - { - t->picnum = CHEERBOMB + ((PlayClock >> 4) & 3); - break; - } - else goto default_case; case EMPTYBIKE: if (!isRRRA()) goto default_case; kang = (h->spr.pos - viewVec).Angle(); diff --git a/wadsrc/static/filter/dukelike/engine/engine.def b/wadsrc/static/filter/dukelike/engine/engine.def index 0ab5e49a9..dbb273643 100644 --- a/wadsrc/static/filter/dukelike/engine/engine.def +++ b/wadsrc/static/filter/dukelike/engine/engine.def @@ -77,6 +77,8 @@ spawnclasses 1346 = DukeHelicopter 2491 = DukeCar 26 = DukePipeBomb + 940 = DukeBounceMine + 1650 = DukeMortar 1272 = DukeTrash 634 = DukeBolt1 diff --git a/wadsrc/static/filter/redneck.ridesagain/engine/engine.def b/wadsrc/static/filter/redneck.ridesagain/engine/engine.def index 0633f596e..761ff7081 100644 --- a/wadsrc/static/filter/redneck.ridesagain/engine/engine.def +++ b/wadsrc/static/filter/redneck.ridesagain/engine/engine.def @@ -2,6 +2,7 @@ include "engine/defines.def" spawnclasses { + 3464 = RedneckCheerBomb 2430 = RedneckCactusLargeYellow 2431 = RedneckCactusLargeGreen 2432 = RedneckCactusLargeBrown diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index b54ec372c..06d39d01f 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -75,6 +75,7 @@ spawnclasses 1172 = DukeVase 26 = RedneckDynamite + 1416 = RedneckMortar 285 = RedneckChickenSpawner1 286 = RedneckChickenSpawner2 287 = RedneckFeatherSpawner diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index f09e178c9..105fb5448 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -89,6 +89,7 @@ version "4.10" #include "zscript/games/duke/actors/helicopt.zs" #include "zscript/games/duke/actors/greenslime.zs" #include "zscript/games/duke/actors/heavyhbomb.zs" +#include "zscript/games/duke/actors/mortar.zs" #include "zscript/games/duke/actors/redneckmisc.zs" #include "zscript/games/duke/actors/rabbitspawner.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/mortar.zs b/wadsrc/static/zscript/games/duke/actors/mortar.zs new file mode 100644 index 000000000..d44eba925 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/mortar.zs @@ -0,0 +1,215 @@ +class DukeMortar : DukeActor +{ + default + { + pic "MORTAR"; + detail 3; + } + + override void Tick() + { + let spawned = self.spawn("DukeFrameEffect1"); + if (spawned) spawned.temp_data[0] = 3; + Common(1); + } + + void Common(int itemmode) + { + let Owner = self.ownerActor; + let sectp = self.sector; + DukePlayer p; + double xx; + + [p,xx] = self.findplayer(); + + if (self.temp_data[3] == 0) + { + int j = self.ifhitbyweapon(); + if (j >= 0) + { + self.temp_data[3] = 1; + self.temp_data[4] = 0; + self.vel.X = 0; + self.DetonateIt(itemmode); + return; + } + } + + if (itemmode != 0) + { + self.makeitfall(); + + // Feature check later needs to be map controlled, not game controlled. + if (sectp.lotag != ST_1_ABOVE_WATER && (!Raze.isRRRA() || sectp.lotag != ST_160_FLOOR_TELEPORT) && self.pos.Z >= self.floorz - 1 && self.yint < 3) + { + if (self.yint > 0 || (self.yint == 0 && self.floorz == sectp.floorz)) + { + if (itemmode != 2) + self.PlayActorSound("PIPEBOMB_BOUNCE"); + else if (self.temp_data[3] == 0) + { + self.temp_data[3] = 1; + self.temp_data[4] = 0; + self.DetonateIt(itemmode); + return; + } + } + self.vel.Z = -(4 - self.yint); + if (sectp.lotag == 2) + self.vel.Z *= 0.25; + self.yint++; + } + if (itemmode != 2 && self.pos.Z < self.ceilingz + self.detail && (!Raze.isRR() || sectp.lotag != ST_2_UNDERWATER)) // underwater check only for RR + { + self.pos.Z = self.ceilingz + self.detail; + self.vel.Z = 0; + } + } + + CollisionData coll; + self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0, coll); + + if (sectp.lotag == ST_1_ABOVE_WATER && self.vel.Z == 0) + { + self.pos.Z += 32; + if (self.temp_data[5] == 0) + { + self.temp_data[5] = 1; + self.spawn("DukeWaterSplash2"); + } + } + else self.temp_data[5] = 0; + + if (self.temp_data[3] == 0 && (coll.type || xx < 844 / 16.)) + { + self.temp_data[3] = 1; + self.temp_data[4] = 0; + self.vel.X = 0; + } + else if(self.vel.X > 0) + { + self.vel.X -= 5. / 16; + if (sectp.lotag == ST_2_UNDERWATER) + self.vel.X -= 10. / 16; + + if(self.vel.X < 0) + self.vel.X = 0; + //if (int(self.vel.X * 16) & 8) self.spr.cstat ^= CSTAT_SPRITE_XFLIP; + } + self.DetonateIt(itemmode); + } + + void DetonateIt(int itemmode) + { + if (self.temp_data[3] == 1) + { + self.temp_data[4]++; + + DukePlayer p; + double xx; + + [p,xx] = self.findplayer(); + + if (self.temp_data[4] == 2) + { + int x = self.extra; + int m = itemmode == 0? gs.bouncemineblastradius : gs.morterblastradius; + + if (self.sector.lotag != 800 || !Raze.isRR()) // this line is RR only + { + self.hitradius(m, x >> 2, x >> 1, x - (x >> 2), x); + self.spawn("DukeExplosion2"); + if (self.vel.Z == 0 && !Raze.isRR()) self.spawn("DukeExplosion2Bot"); // this line is Duke only + if (itemmode == 2) self.spawn("DukeBurning"); + self.PlayActorSound("PIPEBOMB_EXPLODE"); + for (x = 0; x < 8; x++) + self.RANDOMSCRAP(); + } + } + + if (self.scale.Y) + { + self.scale.Y = 0; + return; + } + if (self.temp_data[4] > 20) + { + self.Destroy(); + return; + } + if (itemmode == 2) + { + self.spawn("DukeBurning"); + self.Destroy(); + return; + } + } + if (self.temp_data[0] < 8) self.temp_data[0]++; + } + +} + +class DukeBounceMine : DukeMortar +{ + default + { + pic "BOUNCEMINE"; + } + + override void Initialize() + { + // This is only for placed items, not for armed weapons! + // Although this can be shot, it doesn't really work for that. + if (self.ownerActor == self) + { + self.ownerActor = self; + self.extra = gs.impact_damage << 2; + self.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable + self.ChangeStat(STAT_ZOMBIEACTOR); + self.shade = -127; + self.Scale = (0.375, 0.375); + } + } + + override void Tick() + { + Common(0); + } +} + +class RedneckNortar : DukeMortar +{ + default + { + pic "MORTAR"; + detail 16; + } + + override void Tick() + { + Common(1); + } + +} + +class RedneckCheerBomb : DukeMortar +{ + default + { + spriteset "CHEERBOMB", "CHEERBOMB1", "CHEERBOMB2", "CHEERBOMB3"; + detail 16; + } + + override bool Animate(tspritetype t) + { + t.SetSpritePic(self, (PlayClock >> 4) & 3); + return true; + } + + override void Tick() + { + Common(2); + } +} + +