From 0bc9023e172e506dea79729acff6a6285a7b29f5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Dec 2022 10:19:37 +0100 Subject: [PATCH] - scriptified the pipe bomb and RR's dynamite, which is mostly the same thing. The mortars were split off because they made the code too convoluted. --- source/games/duke/src/actors_d.cpp | 83 +----- source/games/duke/src/actors_r.cpp | 71 +----- source/games/duke/src/funct.h | 1 - source/games/duke/src/gameexec.cpp | 39 ++- source/games/duke/src/namelist_r.h | 3 + source/games/duke/src/player_d.cpp | 2 +- source/games/duke/src/player_r.cpp | 4 - source/games/duke/src/spawn.cpp | 25 -- source/games/duke/src/spawn_d.cpp | 18 -- source/games/duke/src/spawn_r.cpp | 7 - source/games/duke/src/types.h | 2 +- source/games/duke/src/vmexports.cpp | 43 +++- .../static/filter/dukelike/engine/engine.def | 1 + .../static/filter/redneck/engine/engine.def | 1 + wadsrc/static/zscript.txt | 1 + .../zscript/games/duke/actors/heavyhbomb.zs | 239 ++++++++++++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 4 + wadsrc/static/zscript/games/duke/dukegame.zs | 5 +- 18 files changed, 326 insertions(+), 223 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/heavyhbomb.zs diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index d1df49e55..f287262fb 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -1178,18 +1178,6 @@ static void heavyhbomb(DDukeActor *actor) int l; double xx; - 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); if (xx < 1220 / 16.) actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; @@ -1278,16 +1266,7 @@ static void heavyhbomb(DDukeActor *actor) DETONATEB: - bool bBoom = false; - if ((l >= 0 && ps[l].hbomb_on == 0) || actor->temp_data[3] == 1) - bBoom = true; - if (isNamWW2GI() && actor->spr.picnum == HEAVYHBOMB) - { - actor->spr.extra--; - if (actor->spr.extra <= 0) - bBoom = true; - } - if (bBoom) + if (actor->temp_data[3] == 1) { actor->temp_data[4]++; @@ -1297,7 +1276,6 @@ DETONATEB: int m = 0; switch (actor->spr.picnum) { - case HEAVYHBOMB: m = gs.pipebombblastradius; break; case MORTER: m = gs.morterblastradius; break; case BOUNCEMINE: m = gs.bouncemineblastradius; break; } @@ -1318,61 +1296,10 @@ DETONATEB: if (actor->temp_data[4] > 20) { - if (Owner != actor || ud.respawn_items == 0) - { - actor->Destroy(); - return; - } - else - { - actor->temp_data[2] = gs.respawnitemtime; - spawn(actor, PClass::FindActor("DukeRespawnMarker")); - actor->spr.cstat = CSTAT_SPRITE_INVISIBLE; - actor->spr.scale.Y = (0.140625); - return; - } + actor->Destroy(); + return; } } - else if (actor->spr.picnum == HEAVYHBOMB && xx < 788 / 16. && actor->temp_data[0] > 7 && actor->vel.X == 0) - if (cansee(actor->spr.pos.plusZ(-8), actor->sector(), ps[p].GetActor()->getPosWithOffsetZ(), ps[p].cursector)) - if (ps[p].ammo_amount[HANDBOMB_WEAPON] < gs.max_ammo_amount[HANDBOMB_WEAPON]) - { - if (ud.coop >= 1 && Owner == actor) - { - for (int j = 0; j < ps[p].weapreccnt; j++) - if (ps[p].weaprecs[j] == actor->spr.picnum) - continue; - - if (ps[p].weapreccnt < 255) // DukeGDX has 16 here. - ps[p].weaprecs[ps[p].weapreccnt++] = actor->spr.picnum; - } - - addammo(HANDBOMB_WEAPON, &ps[p], 1); - S_PlayActorSound(DUKE_GET, ps[p].GetActor()); - - if (ps[p].gotweapon[HANDBOMB_WEAPON] == 0 || Owner == ps[p].GetActor()) - fi.addweapon(&ps[p], HANDBOMB_WEAPON, true); - - if (!Owner || !Owner->isPlayer()) - { - SetPlayerPal(&ps[p], PalEntry(32, 0, 32, 0)); - } - - if (Owner != actor || ud.respawn_items == 0) - { - if (Owner == actor && ud.coop >= 1) - return; - - actor->Destroy(); - return; - } - else - { - actor->temp_data[2] = gs.respawnitemtime; - spawn(actor, PClass::FindActor("DukeRespawnMarker")); - actor->spr.cstat = CSTAT_SPRITE_INVISIBLE; - } - } if (actor->temp_data[0] < 8) actor->temp_data[0]++; } @@ -1417,13 +1344,9 @@ void moveactors_d(void) case BOUNCEMINE: case MORTER: spawn(act, FRAMEEFFECT1)->temp_data[0] = 3; - [[fallthrough]]; - - case HEAVYHBOMB: heavyhbomb(act); continue; } - if (monsterCheatCheck(act) && badguy(act)) { continue; diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 04b1a0414..39f0017a9 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -1275,22 +1275,6 @@ static void heavyhbomb(DDukeActor *actor) 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; - } - } - 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) @@ -1387,22 +1371,14 @@ static void heavyhbomb(DDukeActor *actor) DETONATEB: - if ((l >= 0 && ps[l].hbomb_on == 0) || actor->temp_data[3] == 1) + 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 POWDERKEG: m = gs.tripbombblastradius; break; // powder keg - case DYNAMITE: m = gs.pipebombblastradius; break; - case HBOMBAMMO: m = gs.pipebombblastradius; break; - case MORTER: m = gs.morterblastradius; break; - case CHEERBOMB: m = gs.morterblastradius; break; - } + int m = gs.morterblastradius; if (actor->sector()->lotag != 800) { @@ -1434,48 +1410,6 @@ DETONATEB: return; } } - else if (actor->spr.picnum == DYNAMITE && xx < 788 / 16. && actor->temp_data[0] > 7 && actor->vel.X == 0) - if (cansee(actor->spr.pos.plusZ(-8), actor->sector(), ps[p].GetActor()->getPosWithOffsetZ(), ps[p].cursector)) - if (ps[p].ammo_amount[DYNAMITE_WEAPON] < gs.max_ammo_amount[DYNAMITE_WEAPON]) - if (actor->spr.pal == 0) - { - if (ud.coop >= 1) - { - for (int j = 0; j < ps[p].weapreccnt; j++) - if (ps[p].weaprecs[j] == actor->spr.picnum) - return; - - if (ps[p].weapreccnt < 255) - ps[p].weaprecs[ps[p].weapreccnt++] = actor->spr.picnum; - } - - addammo(DYNAMITE_WEAPON, &ps[p], 1); - addammo(CROSSBOW_WEAPON, &ps[p], 1); - S_PlayActorSound(DUKE_GET, ps[p].GetActor()); - - if (ps[p].gotweapon[DYNAMITE_WEAPON] == 0 || Owner == ps[p].GetActor()) - fi.addweapon(&ps[p], DYNAMITE_WEAPON, true); - - if (!Owner || !Owner->isPlayer()) - { - SetPlayerPal(&ps[p], PalEntry(32, 0, 32, 0)); - } - - if (Owner && (Owner->attackertype != DYNAMITE || ud.respawn_items == 0 || Owner->isPlayer())) - { - if (actor->spr.picnum == DYNAMITE && !Owner->isPlayer() && ud.coop) - return; - actor->Destroy(); - return; - } - else - { - actor->temp_data[2] = gs.respawnitemtime; - spawn(actor, PClass::FindActor("RedneckRespawnMarker")); - actor->spr.cstat = CSTAT_SPRITE_INVISIBLE; - } - } - if (actor->temp_data[0] < 8) actor->temp_data[0]++; } @@ -1661,7 +1595,6 @@ void moveactors_r(void) if (!isRRRA()) break; [[fallthrough]]; case MORTER: - case DYNAMITE: heavyhbomb(act); continue; } diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 31a862dfb..1cfd418b4 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -177,7 +177,6 @@ void spawntransporter(DDukeActor* actj, DDukeActor* acti, bool beam); int spawnbloodpoolpart1(DDukeActor* acti); void initfootprint(DDukeActor* actj, DDukeActor* acti); void initshell(DDukeActor* actj, DDukeActor* acti, bool isshell); -int initreactor(DDukeActor* actj, DDukeActor* acti, bool isrecon); void spawneffector(DDukeActor* actor, TArray* actors); int startrts(int lumpNum, int localPlayer); diff --git a/source/games/duke/src/gameexec.cpp b/source/games/duke/src/gameexec.cpp index 769fa2ef8..98ee5ae82 100644 --- a/source/games/duke/src/gameexec.cpp +++ b/source/games/duke/src/gameexec.cpp @@ -1345,6 +1345,31 @@ void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, return; } +//--------------------------------------------------------------------------- +// +// what a lousy hack job... :( +// +//--------------------------------------------------------------------------- + +int CheckWeapRec(player_struct* p, DDukeActor* g_ac, int testonly) +{ + int j; + for (j = 0; j < p->weapreccnt; j++) + if (p->weaprecs[j] == g_ac->spr.picnum) + break; + + if (testonly) + { + return (j < p->weapreccnt && g_ac->GetOwner() == g_ac); + } + else if (p->weapreccnt < 32) + { + p->weaprecs[p->weapreccnt++] = g_ac->spr.picnum; + return (g_ac->GetOwner() == g_ac); + } + return false; +} + //--------------------------------------------------------------------------- // // @@ -1665,19 +1690,7 @@ int ParseState::parse(void) if (ud.coop >= 1 && ud.multimode > 1) { - if (*insptr == 0) - { - for (j = 0; j < ps[g_p].weapreccnt; j++) - if (ps[g_p].weaprecs[j] == g_ac->spr.picnum) - break; - - parseifelse(j < ps[g_p].weapreccnt&& g_ac->GetOwner() == g_ac); - } - else if (ps[g_p].weapreccnt < 16) - { - ps[g_p].weaprecs[ps[g_p].weapreccnt++] = g_ac->spr.picnum; - parseifelse(g_ac->GetOwner() == g_ac); - } + parseifelse(CheckWeapRec(&ps[g_p], g_ac, !*insptr)); } else parseifelse(0); break; diff --git a/source/games/duke/src/namelist_r.h b/source/games/duke/src/namelist_r.h index 2feab8fa2..04baa3e07 100644 --- a/source/games/duke/src/namelist_r.h +++ b/source/games/duke/src/namelist_r.h @@ -1390,6 +1390,9 @@ x(BOULDER, 256) x(BOULDER1, 264) x(TORNADO, 1930) x(CHEERBOMB, 3464) +x(CHEERBOMB1, 3465) +x(CHEERBOMB2, 3466) +x(CHEERBOMB3, 3467) x(CHEERBLADE, 3460) x(CHEERBLADE2, 3461) x(CHEERBLADE3, 3462) diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 5e8e49313..28088c778 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -2185,7 +2185,7 @@ static void operateweapon(int snum, ESyncBits actions) } auto spawned = CreateActor(p->cursector, p->GetActor()->getPosWithOffsetZ() + p->GetActor()->spr.Angles.Yaw.ToVector() * 16, HEAVYHBOMB, -16, DVector2(0.140625, 0.140625), - p->GetActor()->spr.Angles.Yaw, vel + p->hbomb_hold_delay * 2, zvel, pact, 1); + p->GetActor()->spr.Angles.Yaw, vel + p->hbomb_hold_delay * 2, zvel, pact, STAT_ACTOR); if (isNam()) { diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index ee16ec253..565b6b5e9 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -865,10 +865,6 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls) if (isRRRA()) goto rrra_rpg2; else break; - case FREEZEBLAST: - spos.Z += 3; - [[fallthrough]]; - case RPG: case SAWBLADE: rrra_rpg2: diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index a30259eff..d98f3c5c6 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -485,31 +485,6 @@ void initshell(DDukeActor* actj, DDukeActor* act, bool isshell) // //--------------------------------------------------------------------------- -int initreactor(DDukeActor* actj, DDukeActor* actor, bool isrecon) -{ - actor->spr.extra = gs.impact_damage; - - actor->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable - - if (ud.multimode < 2 && actor->spr.pal != 0) - { - actor->spr.scale = DVector2(0, 0); - ChangeActorStat(actor, STAT_MISC); - return false; - } - actor->spr.pal = 0; - actor->spr.shade = -17; - - ChangeActorStat(actor, 2); - return false; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - void spawneffector(DDukeActor* actor, TArray* actors) { auto sectp = actor->sector(); diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 7e7b5970e..c5e633a83 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -621,15 +621,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* break; - case HEAVYHBOMB: - if (actj) act->SetOwner(actj); - else act->SetOwner(act); - - act->spr.scale = DVector2(0.140625, 0.140625); - act->spr.yint = 4; - if (initreactor(actj, act, false)) return act; - break; - case FLAMETHROWERSPRITE: case FLAMETHROWERAMMO: // Twentieth Anniversary World Tour if (!isWorldTour()) @@ -724,15 +715,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* ChangeActorStat(act, STAT_STANDABLE); break; - case BOUNCEMINE: - act->SetOwner(act); - act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; //Make it hitable - act->spr.scale = DVector2(0.375, 0.375); - act->spr.shade = -127; - act->spr.extra = gs.impact_damage << 2; - ChangeActorStat(act, STAT_ZOMBIEACTOR); - break; - case CAMERAPOLE: act->spr.extra = 1; diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index 7836f2da8..a7d232338 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -659,13 +659,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* break; - case DYNAMITE: - act->SetOwner(act); - act->spr.scale = DVector2(0.140625, 0.140625); - act->spr.yint = 4; - if (initreactor(actj, act, false)) return act; - break; - case RPG2SPRITE: case MOTOAMMO: case BOATAMMO: diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 6abfa80f4..526c19153 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -240,7 +240,7 @@ struct player_struct short extra_extra8, quick_kick, last_quick_kick; short heat_amount, timebeforeexit, customexitsound; - short weaprecs[256], weapreccnt; + short weaprecs[32], weapreccnt; unsigned int interface_toggle_flag; short dead_flag, show_empty_weapon; diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 3cff9fb14..11bf5c845 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -23,7 +23,6 @@ int PicForName(int intname) {"RedneckRabbit","RABBIT"}, {"RedneckFeather","FEATHER"}, {"DukeBatteryAmmo", "BATTERYAMMO"}, - {"RedneckDynamite", "DYNAMITE"}, {"DukeSixpak", "SIXPAK"}, {"DukeAtomicHealth", "ATOMICHEALTH"}, {"DukeShrinkerExplosion", "SHRINKEREXPLOSION" }, @@ -800,8 +799,6 @@ DEFINE_FIELD_X(DukePlayer, player_struct, last_quick_kick) DEFINE_FIELD_X(DukePlayer, player_struct, heat_amount) DEFINE_FIELD_X(DukePlayer, player_struct, timebeforeexit) DEFINE_FIELD_X(DukePlayer, player_struct, customexitsound) -DEFINE_FIELD_X(DukePlayer, player_struct, weaprecs) -DEFINE_FIELD_X(DukePlayer, player_struct, weapreccnt) DEFINE_FIELD_X(DukePlayer, player_struct, interface_toggle_flag) DEFINE_FIELD_X(DukePlayer, player_struct, dead_flag) DEFINE_FIELD_X(DukePlayer, player_struct, show_empty_weapon) @@ -1045,6 +1042,45 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, quickkill, quickkill) return 0; } +DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, CheckWeapRec, CheckWeapRec) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_struct); + PARAM_POINTER(ac, DDukeActor); + PARAM_BOOL(test); + ACTION_RETURN_INT(CheckWeapRec(self, ac, test)); +} + +void DukePlayer_addammo(player_struct* p, int ammo, int amount) +{ + if ((unsigned)ammo >= MAX_WEAPONS) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Ammo number out of range"); + addammo(ammo, p, amount); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, addammo, DukePlayer_addammo) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_struct); + PARAM_INT(type); + PARAM_INT(amount); + DukePlayer_addammo(self, type, amount); + return 0; +} + +void DukePlayer_addweapon(player_struct* p, int wpn, int switchit) +{ + if ((unsigned)wpn >= MAX_WEAPONS) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Weapon number out of range"); + fi.addweapon(p, wpn, switchit); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, addweapon, DukePlayer_addweapon) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_struct); + PARAM_INT(type); + PARAM_INT(switchit); + DukePlayer_addweapon(self, type, switchit); + return 0; + +} + static DDukeActor* duke_firstStat(DukeStatIterator* it, int statnum) { it->Reset(statnum); @@ -1290,6 +1326,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, LocateTheLocator, LocateTheLocator) } +DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, max_ammo_amount); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, playerfriction); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, gravity); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, respawnactortime); diff --git a/wadsrc/static/filter/dukelike/engine/engine.def b/wadsrc/static/filter/dukelike/engine/engine.def index 9cf5735ba..0ab5e49a9 100644 --- a/wadsrc/static/filter/dukelike/engine/engine.def +++ b/wadsrc/static/filter/dukelike/engine/engine.def @@ -76,6 +76,7 @@ spawnclasses 4359 = DukeTarget 1346 = DukeHelicopter 2491 = DukeCar + 26 = DukePipeBomb 1272 = DukeTrash 634 = DukeBolt1 diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index 4d0c14517..b54ec372c 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -74,6 +74,7 @@ spawnclasses 1280 = DukeBottle10 1172 = DukeVase + 26 = RedneckDynamite 285 = RedneckChickenSpawner1 286 = RedneckChickenSpawner2 287 = RedneckFeatherSpawner diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 65a2a21ff..f09e178c9 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -88,6 +88,7 @@ version "4.10" #include "zscript/games/duke/actors/ducktarget.zs" #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/redneckmisc.zs" #include "zscript/games/duke/actors/rabbitspawner.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/heavyhbomb.zs b/wadsrc/static/zscript/games/duke/actors/heavyhbomb.zs new file mode 100644 index 000000000..ec57899c0 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/heavyhbomb.zs @@ -0,0 +1,239 @@ + +class DukePipeBomb : DukeActor +{ + default + { + pic "HEAVYHBOMB"; + detail 3; // ceiling distance + // do not add anything here! + } + + override void Initialize() + { + // This is only for placed items, not for armed weapons! + if (self.ownerActor == self) + { + self.extra = gs.impact_damage; + self.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable + + if (ud.multimode < 2 && self.pal != 0) + { + self.scale = (0, 0); + self.ChangeStat(STAT_MISC); + return; + } + self.ChangeStat(STAT_ZOMBIEACTOR); + self.yint = 4; + self.pal = 0; + self.shade = -17; + self.Scale = (0.140625, 0.140625); + } + } + + override void Tick() + { + if (self.statnum != STAT_ACTOR) return; + let Owner = self.ownerActor; + let sectp = self.sector; + DukePlayer p; + double xx; + + if ((self.cstat & CSTAT_SPRITE_INVISIBLE)) + { + self.temp_data[2]--; + if (self.temp_data[2] <= 0) + { + self.PlayActorSound("TELEPORTER"); + self.spawn("DukeTransporterStar"); + self.cstat = CSTAT_SPRITE_BLOCK_ALL; + } + return; + } + + [p, xx] = self.findplayer(); + + if (xx < 1220 / 16.) self.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; + else self.cstat |= CSTAT_SPRITE_BLOCK_ALL; + + if (self.temp_data[3] == 0) + { + int j = self.ifhitbyweapon(); + if (j >= 0) + { + self.temp_data[4] = 0; + self.vel.X = 0; + self.DetonateIt(); + return; + } + } + + 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)) + { + self.PlayActorSound("PIPEBOMB_BOUNCE"); + } + self.vel.Z = -(4 - self.yint); + if (sectp.lotag == 2) + self.vel.Z *= 0.25; + self.yint++; + } + if (self.pos.Z < self.ceilingz + 16 && (!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.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.cstat ^= CSTAT_SPRITE_XFLIP; + } + + if (coll.type == kHitWall) + { + let wal = coll.hitWall(); + dlevel.checkhitwall(wal, self, self.pos); + + let k = wal.delta().Angle(); + self.angle = k * 2 - self.angle; + self.vel.X *= 0.5; + } + + bool bBoom = false; + if (Owner && Owner.isPlayer()) + { + if (Raze.isNamWW2GI()) + { + self.extra--; + if (self.extra <= 0) + bBoom = true; + } + else bBoom = Owner.GetPlayer().hbomb_on == 0; + } + + if (bBoom) self.DetonateIt(); + else self.pickupCheck(p); + + if (self.temp_data[0] < 8) self.temp_data[0]++; + } + + void DetonateIt() + { + self.temp_data[4]++; + + if (self.temp_data[4] == 2) + { + int x = self.extra; + int m = gs.pipebombblastradius; + + 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 + 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(); + } + } + + protected bool doPickupCheck(DukePlayer p, int weapon1, int weapon2) + { + let xx = (p.actor.pos - self.pos).Sum(); + let Owner = self.ownerActor; + // Duke + if (xx < 788 / 16. && self.temp_data[0] > 7 && self.vel.X == 0) + if (Raze.cansee(self.pos.plusZ(-8), self.sector, p.actor.pos.plusZ(p.actor.viewzoffset), p.cursector)) + if (p.ammo_amount[weapon1] < gs.max_ammo_amount[weapon1]) + { + if (ud.coop >= 1 && Owner == self) + { + p.CheckWeapRec(self, false); + } + + p.addammo(weapon1, 1); + if (weapon2 >= 0) p.addammo(weapon2, 1); + p.actor.PlayActorSound("PLAYER_GET"); + + if (p.gotweapon[weapon1] == 0 || Owner == p.actor) + p.addweapon(weapon1, true); + + if (!Owner || !Owner.isPlayer()) + { + p.pals = Color(32, 0, 32, 0); + } + + if (Owner != self || ud.respawn_items == 0) + { + if (Owner == self && ud.coop >= 1) + return false; + + self.Destroy(); + return false; + } + else + { + self.temp_data[2] = gs.respawnitemtime; + self.cstat = CSTAT_SPRITE_INVISIBLE; + return true; + } + } + return false; + } + + virtual void pickupCheck(DukePlayer p) + { + if (doPickupCheck(p, DukeWpn.HANDBOMB_WEAPON, -1)) + self.spawn("DukeRespawnMarker"); + } +} +class RedneckDynamite : DukePipeBomb +{ + default + { + pic "DYNAMITE"; + detail 16; + } + + override void pickupCheck(DukePlayer p) + { + if (doPickupCheck(p, RRWpn.DYNAMITE_WEAPON, RRWpn.CROSSBOW_WEAPON)) + self.spawn("RedneckRespawnMarker"); + } + +} + diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index aeb64e5b9..d482f61e6 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -76,6 +76,10 @@ enum ESectorTriggers ST_41_JAILDOOR = 41, ST_42_MINECART = 42, + + ST_160_FLOOR_TELEPORT = 160, + ST_161_CEILING_TELEPORT = 161, + // left: ST 32767, 65534, 65535 }; diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index 88dd74818..bf806bb62 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -258,7 +258,6 @@ struct DukePlayer native native DukeActor actor, actorsqu, wackedbyactor, on_crane, somethingonplayer, access_spritenum, dummyplayersprite, newOwner, holoduke_on; native sectortype cursector; - native int16 weaprecs[256], weapreccnt; native uint interface_toggle_flag; native int16 dead_flag, show_empty_weapon; // JBF 20031220: added orotscrnang @@ -352,6 +351,9 @@ struct DukePlayer native native void addPitch(double p); native void centerView(); native int playerinput(int bit); + native int CheckWeapRec(DukeActor item, bool checkonly); + native void addammo(int type, int amount); + native void addweapon(int type, bool switchit); } @@ -414,6 +416,7 @@ struct DukeGameInfo native // Static constant global state readonly native double playerfriction; readonly native double gravity; + readonly native int16 max_ammo_amount[RRWpn.MAX_WEAPONS]; readonly native int respawnactortime; readonly native int bouncemineblastradius;