diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 4d0844414..35f0475de 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -636,59 +636,6 @@ void bounce(DDukeActor* actor) actor->spr.angle = vect.Angle(); } -//--------------------------------------------------------------------------- -// -// taken out of moveweapon -// -//--------------------------------------------------------------------------- - -void movetongue(DDukeActor *actor, int tongue, int jaw) -{ - actor->temp_data[0] = int(BobVal(actor->temp_data[1]) * 32); - actor->temp_data[1] += 32; - if (actor->temp_data[1] > 2047) - { - actor->Destroy(); - return; - } - - auto Owner = actor->GetOwner(); - if (!Owner) return; - - if (Owner->spr.statnum == MAXSTATUS) - if (badguy(Owner) == 0) - { - actor->Destroy(); - return; - } - - actor->spr.angle = Owner->spr.angle; - actor->spr.pos = Owner->spr.pos.plusZ(Owner->isPlayer() ? -34 : 0); - - for (int k = 0; k < actor->temp_data[0]; k++) - { - auto pos = actor->spr.pos + actor->spr.angle.ToVector() * 2 * k; - pos.Z += k * Sgn(actor->vel.Z) * abs(actor->vel.Z / 12); - - auto q = CreateActor(actor->sector(), pos, tongue, -40 + (k << 1), DVector2(0.125, 0.125), nullAngle, 0., 0., actor, 5); - if (q) - { - q->spr.cstat = CSTAT_SPRITE_YCENTER; - q->spr.pal = 8; - } - } - int k = actor->temp_data[0]; // do not depend on the above loop counter. - auto pos = actor->spr.pos + actor->spr.angle.ToVector() * 2 * k; - pos.Z += k * Sgn(actor->vel.Z) * abs(actor->vel.Z / 12); - auto spawned = CreateActor(actor->sector(), pos, jaw, -40, DVector2(0.5, 0.5), nullAngle, 0., 0., actor, 5); - if (spawned) - { - spawned->spr.cstat = CSTAT_SPRITE_YCENTER; - if (actor->temp_data[1] > 512 && actor->temp_data[1] < (1024)) - spawned->spr.picnum = jaw + 1; - } -} - //--------------------------------------------------------------------------- // // diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index e834d24d5..d4600571b 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -364,7 +364,7 @@ void hitradius_d(DDukeActor* actor, int r, int hp1, int hp2, int hp3, int h else { if (actor->spr.picnum == SHRINKSPARK || actor->spr.picnum == FLAMETHROWERFLAME) - act2->attackertype = actor->spr.picnum; + act2-> attackertype = actor->spr.picnum; else if (actor->spr.picnum != FIREBALL || !Owner || Owner->spr.picnum != APLAYER) { if (actor->spr.picnum == LAVAPOOL) @@ -1235,13 +1235,14 @@ void moveweapons_d(void) continue; } + if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + { + CallTick(act); + continue; + } switch(act->spr.picnum) { - case TONGUE: - movetongue(act, TONGUE, INNERJAW); - continue; - case FREEZEBLAST: if (act->spr.yint < 1 || act->spr.extra < 2 || (act->vel.X == 0 && act->vel.Z == 0)) { @@ -2596,17 +2597,6 @@ void moveexplosions_d(void) // STATNUM 5 case FRAMEEFFECT1: frameeffect1(act); continue; - case INNERJAW: - case INNERJAW + 1: - - p = findplayer(act, &xx); - if (xx < 32) - { - SetPlayerPal(&ps[p], PalEntry(32, 32, 0, 0)); - ps[p].GetActor()->spr.extra -= 4; - } - [[fallthrough]]; - case FIRELASER: if (act->spr.extra != 999) act->spr.extra = 999; @@ -2616,9 +2606,6 @@ void moveexplosions_d(void) // STATNUM 5 continue; } break; - case TONGUE: - act->Destroy(); - continue; case MONEY + 1: case MAIL + 1: case PAPER + 1: diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index baeb915c4..ff7310dde 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -1118,12 +1118,14 @@ void moveweapons_r(void) continue; } + if (proj->GetClass() != RUNTIME_CLASS(DDukeActor)) + { + CallTick(proj); + continue; + } + switch (proj->spr.picnum) { - case TONGUE: - movetongue(proj, TONGUE, INNERJAW); - continue; - case FREEZEBLAST: if (proj->spr.yint < 1 || proj->spr.extra < 2 || (proj->vel.X == 0 && proj->vel.Z == 0)) { @@ -2734,17 +2736,6 @@ void moveexplosions_r(void) // STATNUM 5 case FRAMEEFFECT1: frameeffect1(act); continue; - case INNERJAW: - case INNERJAW + 1: - - p = findplayer(act, &xx); - if (xx < 32) - { - SetPlayerPal(&ps[p], PalEntry(32, 32, 0, 0)); - ps[p].GetActor()->spr.extra -= 4; - } - [[fallthrough]]; - case COOLEXPLOSION1: case FIRELASER: case OWHIP: @@ -2757,9 +2748,6 @@ void moveexplosions_r(void) // STATNUM 5 continue; } break; - case TONGUE: - act->Destroy(); - continue; case FEATHER + 1: // feather act->spr.pos.Z = act->floorz = getflorzofslopeptr(act->sector(), act->spr.pos.X, act->spr.pos.Y); if (act->sector()->lotag == 800) diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 26fff59a4..322e4bc6b 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -35,7 +35,6 @@ void clearcameras(player_struct* p); void RANDOMSCRAP(DDukeActor* i); void detonate(DDukeActor* i, int explosion); void bounce(DDukeActor* i); -void movetongue(DDukeActor* i, int tongue, int jaw); void rpgexplode(DDukeActor* i, int j, const DVector3& pos, int EXPLOSION2, int EXPLOSIONBOT2, int newextra, int playsound); void lotsofstuff(DDukeActor* s, int n, int spawntype); bool respawnmarker(DDukeActor* i, int yellow, int green); diff --git a/source/games/duke/src/namelist_d.h b/source/games/duke/src/namelist_d.h index 9c69fa427..3813f4e80 100644 --- a/source/games/duke/src/namelist_d.h +++ b/source/games/duke/src/namelist_d.h @@ -425,6 +425,7 @@ x(OCTABRAINSTAYPUT, 1821) x(OCTATOP, 1845) x(OCTADEADSPRITE, 1855) x(INNERJAW, 1860) +x(INNERJAW1, 1861) x(DRONE, 1880) x(EXPLOSION2, 1890) x(COMMANDER, 1920) diff --git a/source/games/duke/src/namelist_r.h b/source/games/duke/src/namelist_r.h index e409aa9fd..1fc72f811 100644 --- a/source/games/duke/src/namelist_r.h +++ b/source/games/duke/src/namelist_r.h @@ -447,6 +447,7 @@ x(RADIUSEXPLOSION, 1426) x(FORCERIPPLE, 1427) x(CANNONBALL, 1437) x(INNERJAW, 1439) +x(INNERJAW1, 1440) x(EXPLOSION2, 1441) x(EXPLOSION3, 1442) x(JIBS1, 1463) diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp index 98068ff84..77d29d79a 100644 --- a/source/games/duke/src/sectors_d.cpp +++ b/source/games/duke/src/sectors_d.cpp @@ -1037,7 +1037,6 @@ void checkhitdefault_d(DDukeActor* targ, DDukeActor* proj) if (proj->spr.picnum == FREEZEBLAST && ((targ->spr.picnum == APLAYER && targ->spr.pal == 1) || (gs.freezerhurtowner == 0 && proj->GetOwner() == targ))) return; - int hitpic = proj->spr.picnum; auto Owner = proj->GetOwner(); if (Owner && Owner->spr.picnum == APLAYER) diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 66129be64..77cd914c2 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -109,6 +109,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, badguyID, badguypic) ACTION_RETURN_INT(badguypic(p)); } + + DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL(camsprite) @@ -435,6 +437,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, operatesectors, DukeActor_operatesecto return 0; } +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, badguy, badguy) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + ACTION_RETURN_INT(badguy(self)); +} + +int duke_isplayer(DDukeActor* act) +{ + return act->isPlayer(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, isplayer, duke_isplayer) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + ACTION_RETURN_INT(duke_isplayer(self)); +} + // temporary helpers to hide the fact that these flags are not part of the actor yet. DEFINE_ACTION_FUNCTION(DDukeActor, actorflag1) { diff --git a/wadsrc/static/filter/duke/engine/engine.def b/wadsrc/static/filter/duke/engine/engine.def index 804b83e7e..4cadf7fd4 100644 --- a/wadsrc/static/filter/duke/engine/engine.def +++ b/wadsrc/static/filter/duke/engine/engine.def @@ -56,5 +56,8 @@ spawnclasses 2807 = DukeCanWithSomething2 2808 = DukeCanWithSomething3 2809 = DukeCanWithSomething4 + 1647 = DukeTongue + 1860 = DukeInnerJaw + 1861 = DukeInnerJaw1 } diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index cedc1e347..b00f02221 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -43,5 +43,9 @@ spawnclasses 239 = DukeWaterdrip 120 = DukeDoorshock 1309 = DukeCanWithSomething + 1414 = DukeTongue + 1439 = DukeInnerJaw + 1440 = DukeInnerJaw1 + } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 3a5f63824..cf74d9647 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -70,6 +70,7 @@ version "4.10" #include "zscript/games/duke/actors/doorshock.zs" #include "zscript/games/duke/actors/viewscreen.zs" #include "zscript/games/duke/actors/canwithsomething.zs" +#include "zscript/games/duke/actors/tongue.zs" #include "zscript/games/duke/actors/rabbitspawner.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/tongue.zs b/wadsrc/static/zscript/games/duke/actors/tongue.zs new file mode 100644 index 000000000..403f2e5b3 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/tongue.zs @@ -0,0 +1,90 @@ +// This isn't used anywhere and looks broken anyway. Sprites are the animation of Shrinkspark. Only provided for completeness. +class DukeTongue : DukeActor +{ + default + { + statnum STAT_PROJECTILE; + pic "TONGUE"; + } + + override void Tick() + { + self.temp_data[0] = int(Raze.BobVal(self.temp_data[1]) * 32); + self.temp_data[1] += 32; + if (self.temp_data[1] > 2047 || statnum == STAT_MISC) + { + self.Destroy(); + return; + } + + let Owner = self.ownerActor; + if (!Owner) + { + self.Destroy(); + } + + self.angle = Owner.angle; + self.pos = Owner.pos.plusZ(Owner.isPlayer() ? -34 : 0); + + for (int k = 0; k < self.temp_data[0]; k++) + { + let pos = self.pos + self.angle.ToVector() * 2 * k; + pos.Z += k * self.vel.Z / 12; + + let q = dlevel.SpawnActor(self.sector, pos, "DukeTongue", -40 + (k << 1), (0.125, 0.125), 0, 0., 0., self, STAT_MISC); + if (q) + { + q.ChangeStat(STAT_MISC); + q.cstat = CSTAT_SPRITE_YCENTER; + q.pal = 8; + } + } + int k = self.temp_data[0]; // do not depend on the above loop counter. + let pos = self.pos + self.angle.ToVector() * 2 * k; + pos.Z += k * self.vel.Z / 12; + let jaw = 'DukeInnerJaw'; + if (self.temp_data[1] > 512 && self.temp_data[1] < 1024) jaw = 'DukeInnerJaw1'; + let spawned = dlevel.SpawnActor(self.sector, pos, jaw, -40, (0.5, 0.5), 0, 0., 0., self, STAT_MISC); + if (spawned) + { + spawned.cstat = CSTAT_SPRITE_YCENTER; + } + } +} + +class DukeInnerJaw : DukeActor +{ + default + { + statnum STAT_MISC; + pic "InnerJaw"; + } + + override void Tick() + { + double xx; + DukePlayer p; + [p, xx] = self.findplayer(); + if (xx < 32) + { + p.pals = Color(32, 32, 0, 0); + p.actor.extra -= 4; + } + + if (self.extra != 999) + self.extra = 999; + else + { + self.Destroy(); + } + } +} + +class DukeInnerJaw1 : DukeInnerJaw +{ + default + { + pic "InnerJaw1"; + } +} + diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 98af70a9c..fe06a3e48 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -183,6 +183,8 @@ class DukeActor : CoreActor native native double, DukeActor hitasprite(); native void ChangeSector(sectortype s, bool forcetail = false); native void ChangeStat(int s, bool forcetail = false); + native int badguy(); + native int isplayer(); // temporary flag accessors - need to be eliminated once we can have true actor flags diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index d27ce4be5..c5fd4cb22 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -145,6 +145,7 @@ struct Raze native static Color shadeToLight(int shade); native static String PlayerName(int i); static int bsin(double angle) { return int(sin(angle * (360. / 2048)) * 16384); } + static double bobval(double angle) { return sin(angle * (360. / 2048)); } native static TextureID PickTexture(TextureID texid); native static int GetBuildTime(); native static Font PickBigFont(String cmptext = "");