From 15fb7dab355b3bdf4c4600cf5e1e9fe7edf48f37 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2022 13:06:42 +0100 Subject: [PATCH] - virtualized the 'shoot' interface and scriptified the bloodsplats to test it. This calls virtual functions on the actor defaults now to allow writing specific shoot functions for subclasses. --- source/core/vmexports.cpp | 20 +++ source/games/duke/src/actors.cpp | 24 +--- source/games/duke/src/actors_d.cpp | 10 +- source/games/duke/src/actors_r.cpp | 10 +- source/games/duke/src/animatesprites_d.cpp | 10 -- source/games/duke/src/animatesprites_r.cpp | 10 -- source/games/duke/src/constants.h | 4 +- source/games/duke/src/dispatch.cpp | 4 +- source/games/duke/src/duke3d.h | 3 +- source/games/duke/src/funct.h | 2 - source/games/duke/src/game.cpp | 12 ++ source/games/duke/src/gameexec.cpp | 2 +- source/games/duke/src/player.cpp | 64 --------- source/games/duke/src/player_d.cpp | 71 ++++------ source/games/duke/src/player_r.cpp | 92 ++++++------- source/games/duke/src/player_w.cpp | 6 +- source/games/duke/src/sectors_d.cpp | 26 ++-- source/games/duke/src/sectors_r.cpp | 8 +- source/games/duke/src/spawn_d.cpp | 14 -- source/games/duke/src/spawn_r.cpp | 14 -- source/games/duke/src/vmexports.cpp | 12 +- .../filter/dukeengine/engine/defines.def | 2 + .../static/filter/dukelike/engine/engine.def | 8 ++ .../static/filter/redneck/engine/engine.def | 4 + wadsrc/static/zscript.txt | 1 + .../zscript/games/duke/actors/bloodsplats.zs | 129 ++++++++++++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 6 +- wadsrc/static/zscript/games/duke/dukegame.zs | 16 ++- wadsrc/static/zscript/razebase.zs | 11 +- 29 files changed, 309 insertions(+), 286 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/bloodsplats.zs diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index a7aaa2e20..16fe1726a 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -95,6 +95,26 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, cansee, Raze_cansee) ACTION_RETURN_BOOL(Raze_cansee(x, y, z, s, xe, ye, ze, se)); } +int Raze_hitscan(double x, double y, double z, sectortype* sec, double xe, double ye, double ze, HitInfoBase* hit, unsigned cliptype, double maxrange) +{ + return hitscan(DVector3(x, y, z), sec, DVector3(xe, ye, ze), *hit, cliptype, maxrange); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Raze, hitscan, Raze_hitscan) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_POINTER(s, sectortype); + PARAM_FLOAT(xe); + PARAM_FLOAT(ye); + PARAM_FLOAT(ze); + PARAM_POINTER(se, HitInfoBase); + PARAM_UINT(clip); + PARAM_FLOAT(maxrange); + ACTION_RETURN_INT(Raze_hitscan(x, y, z, s, xe, ye, ze, se, clip, maxrange)); +} DEFINE_ACTION_FUNCTION_NATIVE(_Raze, SoundEnabled, SoundEnabled) diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 7ad2fcd0d..3b9bacf1b 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -808,26 +808,6 @@ void reactor(DDukeActor* const actor, int REACTOR, int REACTOR2, int REACTORBURN } } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void bloodsplats(DDukeActor *actor) -{ - if (actor->temp_data[0] < 14 * 26) - { - auto offset = krandf(1); - auto lerp = 1. - (double(actor->temp_data[0]) / (14 * 26)); - auto zadj = (1. / 16.) * lerp; - auto sadj = (1. / 12.) * lerp * REPEAT_SCALE; - actor->spr.pos.Z += zadj + offset * zadj; - actor->spr.scale.Y += sadj + offset * sadj; - actor->temp_data[0]++; - } -} - //--------------------------------------------------------------------------- // // @@ -1406,7 +1386,7 @@ void handle_se14(DDukeActor* actor, bool checkstat, int RPG, int JIBS6) { auto saved_angle = actor->spr.Angles.Yaw; actor->spr.Angles.Yaw = (actor->spr.pos.XY() - ps[p].GetActor()->spr.pos.XY()).Angle(); - fi.shoot(actor, RPG); + fi.shoot(actor, RPG, nullptr); actor->spr.Angles.Yaw = saved_angle; } } @@ -1892,7 +1872,7 @@ void handle_se05(DDukeActor* actor, int FIRELASER) { auto ang = actor->spr.Angles.Yaw; actor->spr.Angles.Yaw = (actor->spr.pos.XY() - ps[p].GetActor()->spr.pos.XY()).Angle(); - fi.shoot(actor, FIRELASER); + fi.shoot(actor, FIRELASER, nullptr); actor->spr.Angles.Yaw = ang; } diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 7c2828285..65ad99d3b 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -2426,14 +2426,6 @@ void moveexplosions_d(void) // STATNUM 5 else act->spr.shade = 127; continue; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - - bloodsplats(act); - continue; - case NUKEBUTTON: case NUKEBUTTON + 1: case NUKEBUTTON + 2: @@ -2824,7 +2816,7 @@ void moveeffectors_d(void) //STATNUM 3 if (act->temp_data[0]) { if (act->temp_data[0] == 1) - fi.shoot(act, sc->extra); + fi.shoot(act, sc->extra, nullptr); else if (act->temp_data[0] == 26 * 5) act->temp_data[0] = 0; act->temp_data[0]++; diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 410a8ac9a..278d82ae1 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -2171,14 +2171,6 @@ void moveexplosions_r(void) // STATNUM 5 else act->spr.shade = 127; continue; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - - bloodsplats(act); - continue; - case MUD: act->temp_data[0]++; @@ -2559,7 +2551,7 @@ void moveeffectors_r(void) //STATNUM 3 if (act->temp_data[0]) { if (act->temp_data[0] == 1) - fi.shoot(act, sc->extra); + fi.shoot(act, sc->extra, nullptr); else if (act->temp_data[0] == 26 * 5) act->temp_data[0] = 0; act->temp_data[0]++; diff --git a/source/games/duke/src/animatesprites_d.cpp b/source/games/duke/src/animatesprites_d.cpp index a015c4567..4bee5a94f 100644 --- a/source/games/duke/src/animatesprites_d.cpp +++ b/source/games/duke/src/animatesprites_d.cpp @@ -89,16 +89,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi else t->cstat &= ~CSTAT_SPRITE_XFLIP; t->picnum = h->spr.picnum + k; break; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - if (t->pal == 6) - { - t->shade = -127; - continue; - } - [[fallthrough]]; case BULLETHOLE: t->shade = 16; continue; diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index ce78e4830..fbf6bcd7f 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -73,16 +73,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi else t->cstat &= ~CSTAT_SPRITE_XFLIP; t->picnum = h->spr.picnum + k; break; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - if (t->pal == 6) - { - t->shade = -127; - continue; - } - [[fallthrough]]; case BULLETHOLE: t->shade = 16; continue; diff --git a/source/games/duke/src/constants.h b/source/games/duke/src/constants.h index aae547119..3fb9805ce 100644 --- a/source/games/duke/src/constants.h +++ b/source/games/duke/src/constants.h @@ -392,8 +392,8 @@ enum TFLAG_DOORWALL = 1 << 5, TFLAG_BLOCKDOOR = 1 << 6, TFLAG_OUTERSPACE = 1 << 7, - - TFLAG_NOCIRCLEREFLECT = 32, + TFLAG_NOBLOODSPLAT = 1 << 8, + TFLAG_NOCIRCLEREFLECT = 1 << 9, }; enum diff --git a/source/games/duke/src/dispatch.cpp b/source/games/duke/src/dispatch.cpp index c2a72cac2..304d1a532 100644 --- a/source/games/duke/src/dispatch.cpp +++ b/source/games/duke/src/dispatch.cpp @@ -74,8 +74,8 @@ void move_d(DDukeActor* i, int g_p, int g_x); void move_r(DDukeActor* i, int g_p, int g_x); void incur_damage_d(player_struct* p); void incur_damage_r(player_struct* p); -void shoot_d(DDukeActor* i, int atwith); -void shoot_r(DDukeActor* i, int atwith); +void shoot_d(DDukeActor* i, int atwith, PClass* cls); +void shoot_r(DDukeActor* i, int atwith, PClass* cls); void selectweapon_d(int snum, int j); void selectweapon_r(int snum, int j); int doincrements_d(player_struct* p); diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 4ba73ef74..6f03e893a 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -99,7 +99,7 @@ struct Dispatcher // player void (*incur_damage)(player_struct* p); - void (*shoot)(DDukeActor*, int); + void (*shoot)(DDukeActor*, int, PClass* cls); void (*selectweapon)(int snum, int j); int (*doincrements)(player_struct* p); void (*checkweapons)(player_struct* p); @@ -125,6 +125,7 @@ bool CallOnUse(DDukeActor* actor, player_struct* user); void CallOnMotoSmash(DDukeActor* actor, player_struct* hitter); void CallOnRespawn(DDukeActor* actor, int low); bool CallAnimate(DDukeActor* actor, tspritetype* hitter); +bool CallShootThis(DDukeActor* clsdef, DDukeActor* actor, int pn, const DVector3& spos, DAngle sang); void CallStaticSetup(DDukeActor* actor); diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index f1b377ba5..5750f115a 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -44,7 +44,6 @@ bool respawnmarker(DDukeActor* i, int yellow, int green); void forcesphere(DDukeActor* i, int forcesphere); void recon(DDukeActor* i, int explosion, int firelaser, int attacksnd, int painsnd, int roamsnd, int shift, int (*getspawn)(DDukeActor* i)); void reactor(DDukeActor* i, int REACTOR, int REACTOR2, int REACTORBURNT, int REACTOR2BURNT, int REACTORSPARK, int REACTOR2SPARK); -void bloodsplats(DDukeActor* actor); void forcesphereexplode(DDukeActor* i); void watersplash2(DDukeActor* i); void frameeffect1(DDukeActor* i); @@ -123,7 +122,6 @@ void quickkill(player_struct* p); int setpal(player_struct* p); int madenoise(int playerNum); int haskey(sectortype* sect, int snum); -void shootbloodsplat(DDukeActor* i, int p, const DVector3& pos, DAngle ang, int atwith, int BIGFORCE); void breakwall(int newpn, DDukeActor* spr, walltype* dawallnum); int callsound(sectortype* sectnum,DDukeActor* snum, bool endstate = false); diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index b043f1e60..4ad7d46d9 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -507,4 +507,16 @@ void CallStaticSetup(DDukeActor* actor) } } +bool CallShootThis(DDukeActor* clsdef, DDukeActor* actor, int pn, const DVector3& spos, DAngle sang) +{ + int rv = 0; + VMReturn ret(&rv); + IFVIRTUALPTR(clsdef, DDukeActor, ShootThis) + { + VMValue val[] = {clsdef, actor, pn >= 0? &ps[pn] : nullptr, spos.X, spos.Y, spos.Z, sang.Degrees()}; + VMCall(func, val, 7, &ret, 1); + } + return rv; +} + END_DUKE_NS diff --git a/source/games/duke/src/gameexec.cpp b/source/games/duke/src/gameexec.cpp index e32ed3b0e..bbb3f4651 100644 --- a/source/games/duke/src/gameexec.cpp +++ b/source/games/duke/src/gameexec.cpp @@ -1755,7 +1755,7 @@ int ParseState::parse(void) break; case concmd_shoot: insptr++; - fi.shoot(g_ac, (short)*insptr); + fi.shoot(g_ac, (short)*insptr, nullptr); insptr++; break; case concmd_ifsoundid: diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index 2862300f8..9c6bcd3a8 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -993,69 +993,5 @@ int haskey(sectortype* sectp, int snum) return 0; } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void shootbloodsplat(DDukeActor* actor, int p, const DVector3& pos, DAngle ang, int atwith, int BIGFORCE) -{ - auto sectp = actor->sector(); - double zvel; - HitInfo hit{}; - - if (p >= 0) - ang += DAngle22_5 / 2 - randomAngle(22.5); - else ang += DAngle180 + DAngle22_5/2 - randomAngle(22.5); - - zvel = 4 - krandf(8); - - - hitscan(pos, sectp, DVector3(ang.ToVector() * 1024, zvel * 64), hit, CLIPMASK1); - - // oh my... - if ( (pos.XY() - hit.hitpos.XY()).Length() < 64 && - (hit.hitWall != nullptr && hit.hitWall->overpicnum != BIGFORCE) && - ((hit.hitWall->twoSided() && hit.hitSector != nullptr && - hit.hitWall->nextSector()->lotag == 0 && - hit.hitSector->lotag == 0 && - (hit.hitSector->floorz - hit.hitWall->nextSector()->floorz) > 16) || - (!hit.hitWall->twoSided() && hit.hitSector->lotag == 0))) - { - if ((hit.hitWall->cstat & CSTAT_WALL_MASKED) == 0) - { - if (hit.hitWall->twoSided()) - { - DukeSectIterator it(hit.hitWall->nextSector()); - while (auto act2 = it.Next()) - { - if (act2->spr.statnum == STAT_EFFECTOR && act2->spr.lotag == SE_13_EXPLOSIVE) - return; - } - } - - if (hit.hitWall->twoSided() && - hit.hitWall->nextWall()->hitag != 0) - return; - - if (hit.hitWall->hitag == 0) - { - auto spawned = spawn(actor, atwith); - if (spawned) - { - spawned->vel.X = -0.75; - spawned->spr.Angles.Yaw = hit.hitWall->delta().Angle() - DAngle90; - spawned->spr.pos = hit.hitpos; - spawned->spr.cstat |= randomXFlip(); - ssp(spawned, CLIPMASK0); - SetActor(spawned, spawned->spr.pos); - if (actorflag(actor, SFLAG2_GREENBLOOD)) - spawned->spr.pal = 6; - } - } - } - } -} END_DUKE_NS diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index d75d77bb1..1405348cb 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -1044,7 +1044,7 @@ static void shootshrinker(DDukeActor* actor, int p, const DVector3& pos, DAngle // //--------------------------------------------------------------------------- -void shoot_d(DDukeActor* actor, int atwith) +void shoot_d(DDukeActor* actor, int atwith, PClass *cls) { int p; DVector3 spos; @@ -1052,35 +1052,17 @@ void shoot_d(DDukeActor* actor, int atwith) auto const sect = actor->sector(); + sang = actor->spr.Angles.Yaw; if (actor->isPlayer()) { p = actor->PlayerIndex(); + spos = actor->getPosWithOffsetZ().plusZ(ps[p].pyoff + 4); + + ps[p].crack_time = CRACK_TIME; } else { p = -1; - } - - SetGameVarID(g_iAtWithVarID, atwith, actor, p); - SetGameVarID(g_iReturnVarID, 0, actor, p); - OnEvent(EVENT_SHOOT, p, ps[p].GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, actor, p).safeValue() != 0) - { - return; - } - - - if (actor->isPlayer()) - { - spos = ps[p].GetActor()->getPosWithOffsetZ().plusZ(ps[p].pyoff + 4); - sang = ps[p].GetActor()->spr.Angles.Yaw; - - ps[p].crack_time = CRACK_TIME; - - } - else - { - sang = actor->spr.Angles.Yaw; spos = actor->spr.pos.plusZ(-(actor->spr.scale.Y * tileHeight(actor->spr.picnum) * 0.5) + 4); if (actor->spr.picnum != ROTATEGUN) @@ -1094,6 +1076,16 @@ void shoot_d(DDukeActor* actor, int atwith) } } + if (cls == nullptr) + { + auto info = spawnMap.CheckKey(atwith); + if (info) + { + cls = static_cast(info->Class(atwith)); + } + } + if (cls && cls->IsDescendantOf(RUNTIME_CLASS(DDukeActor)) && CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang)) return; + if (isWorldTour()) { // Twentieth Anniversary World Tour switch (atwith) @@ -1124,13 +1116,6 @@ void shoot_d(DDukeActor* actor, int atwith) switch (atwith) { - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - shootbloodsplat(actor, p, spos, sang, atwith, BIGFORCE); - break; - case KNEE: shootknee(actor, p, spos, sang); break; @@ -1528,7 +1513,7 @@ int doincrements_d(player_struct* p) p->last_quick_kick = p->quick_kick + 1; p->quick_kick--; if (p->quick_kick == 8) - fi.shoot(p->GetActor(), KNEE); + fi.shoot(p->GetActor(), KNEE, nullptr); } else if (p->last_quick_kick > 0) p->last_quick_kick--; @@ -2277,7 +2262,7 @@ static void operateweapon(int snum, ESyncBits actions) case PISTOL_WEAPON: // m-16 in NAM if (p->kickback_pic == 1) { - fi.shoot(pact, SHOTSPARK1); + fi.shoot(pact, SHOTSPARK1, nullptr); S_PlayActorSound(PISTOL_FIRE, pact); lastvisinc = PlayClock + 32; p->visibility = 0; @@ -2328,7 +2313,7 @@ static void operateweapon(int snum, ESyncBits actions) if (p->kickback_pic == 4) { for(int ii = 0; ii < 7; ii++) - fi.shoot(pact, SHOTGUN); + fi.shoot(pact, SHOTGUN, nullptr); p->ammo_amount[SHOTGUN_WEAPON]--; S_PlayActorSound(SHOTGUN_FIRE, pact); @@ -2397,7 +2382,7 @@ static void operateweapon(int snum, ESyncBits actions) } S_PlayActorSound(CHAINGUN_FIRE, pact); - fi.shoot(pact, CHAINGUN); + fi.shoot(pact, CHAINGUN, nullptr); lastvisinc = PlayClock + 32; p->visibility = 0; checkavailweapon(p); @@ -2441,7 +2426,7 @@ static void operateweapon(int snum, ESyncBits actions) else p->okickback_pic = p->kickback_pic = 0; p->ammo_amount[p->curr_weapon]--; - fi.shoot(pact, GROWSPARK); + fi.shoot(pact, GROWSPARK, nullptr); //#ifdef NAM //#else @@ -2476,7 +2461,7 @@ static void operateweapon(int snum, ESyncBits actions) else p->okickback_pic = p->kickback_pic = 0; p->ammo_amount[SHRINKER_WEAPON]--; - fi.shoot(pact, SHRINKER); + fi.shoot(pact, SHRINKER, nullptr); if (!isNam()) { @@ -2509,7 +2494,7 @@ static void operateweapon(int snum, ESyncBits actions) { p->visibility = 0; lastvisinc = PlayClock + 32; - fi.shoot(pact, RPG); + fi.shoot(pact, RPG, nullptr); p->ammo_amount[DEVISTATOR_WEAPON]--; checkavailweapon(p); } @@ -2519,7 +2504,7 @@ static void operateweapon(int snum, ESyncBits actions) { p->visibility = 0; lastvisinc = PlayClock + 32; - fi.shoot(pact, RPG); + fi.shoot(pact, RPG, nullptr); p->ammo_amount[DEVISTATOR_WEAPON]--; checkavailweapon(p); if (p->ammo_amount[DEVISTATOR_WEAPON] <= 0) p->okickback_pic = p->kickback_pic = 0; @@ -2539,7 +2524,7 @@ static void operateweapon(int snum, ESyncBits actions) p->visibility = 0; lastvisinc = PlayClock + 32; - fi.shoot(pact, FREEZEBLAST); + fi.shoot(pact, FREEZEBLAST, nullptr); checkavailweapon(p); } if (pact->spr.scale.X < 0.5) @@ -2567,7 +2552,7 @@ static void operateweapon(int snum, ESyncBits actions) if (p->cursector->lotag != 2) { p->ammo_amount[FLAMETHROWER_WEAPON]--; - fi.shoot(pact, FIREBALL); + fi.shoot(pact, FIREBALL, nullptr); } checkavailweapon(p); } @@ -2589,7 +2574,7 @@ static void operateweapon(int snum, ESyncBits actions) p->GetActor()->restorez(); p->vel.Z = 0; if (p->kickback_pic == 3) - fi.shoot(pact, HANDHOLDINGLASER); + fi.shoot(pact, HANDHOLDINGLASER, nullptr); } if (p->kickback_pic == 16) { @@ -2602,7 +2587,7 @@ static void operateweapon(int snum, ESyncBits actions) case KNEE_WEAPON: p->kickback_pic++; - if (p->kickback_pic == 7) fi.shoot(pact, KNEE); + if (p->kickback_pic == 7) fi.shoot(pact, KNEE, nullptr); else if (p->kickback_pic == 14) { if (actions & SB_FIRE) @@ -2621,7 +2606,7 @@ static void operateweapon(int snum, ESyncBits actions) p->ammo_amount[RPG_WEAPON]--; lastvisinc = PlayClock + 32; p->visibility = 0; - fi.shoot(pact, RPG); + fi.shoot(pact, RPG, nullptr); checkavailweapon(p); } else if (p->kickback_pic == 20) diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index ba0385c67..60199ad4a 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -810,7 +810,7 @@ static void shootmortar(DDukeActor* actor, int p, const DVector3& pos, DAngle an // //--------------------------------------------------------------------------- -void shoot_r(DDukeActor* actor, int atwith) +void shoot_r(DDukeActor* actor, int atwith, PClass* cls) { int p; DVector3 spos; @@ -818,18 +818,17 @@ void shoot_r(DDukeActor* actor, int atwith) auto const sect = actor->sector(); + sang = actor->spr.Angles.Yaw; if (actor->isPlayer()) { p = actor->PlayerIndex(); - spos = ps[p].GetActor()->getPosWithOffsetZ().plusZ(ps[p].pyoff + 4); - sang = ps[p].GetActor()->spr.Angles.Yaw; + spos = actor->getPosWithOffsetZ().plusZ(ps[p].pyoff + 4); if (isRRRA()) ps[p].crack_time = CRACK_TIME; } else { p = -1; - sang = actor->spr.Angles.Yaw; spos = actor->spr.pos.plusZ(-(actor->spr.scale.Y * tileHeight(actor->spr.picnum) * 0.5) - 3); if (badguy(actor)) @@ -839,23 +838,18 @@ void shoot_r(DDukeActor* actor, int atwith) } } - SetGameVarID(g_iAtWithVarID, atwith, actor, p); - SetGameVarID(g_iReturnVarID, 0, actor, p); - OnEvent(EVENT_SHOOT, p, ps[p].GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, actor, p).safeValue() != 0) + if (cls == nullptr) { - return; + auto info = spawnMap.CheckKey(atwith); + if (info) + { + cls = static_cast(info->Class(atwith)); + } } + if (cls && cls->IsDescendantOf(RUNTIME_CLASS(DDukeActor)) && CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang)) return; switch (atwith) { - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - shootbloodsplat(actor, p, spos, sang, atwith, BIGFORCE); - return; - case SLINGBLADE: if (!isRRRA()) break; [[fallthrough]]; @@ -2726,7 +2720,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) case PISTOL_WEAPON: if (p->kickback_pic == 1) { - fi.shoot(pact, SHOTSPARK1); + fi.shoot(pact, SHOTSPARK1, nullptr); S_PlayActorSound(PISTOL_FIRE, pact); p->noise_radius = 512; madenoise(snum); @@ -2791,16 +2785,16 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) if (p->kickback_pic == 4) { - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); p->ammo_amount[SHOTGUN_WEAPON]--; @@ -2817,16 +2811,16 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) { if (p->shotgun_state[1]) { - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); - fi.shoot(pact, SHOTGUN); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); + fi.shoot(pact, SHOTGUN, nullptr); p->ammo_amount[SHOTGUN_WEAPON]--; @@ -2917,7 +2911,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) } S_PlayActorSound(CHAINGUN_FIRE, pact); - fi.shoot(pact, CHAINGUN); + fi.shoot(pact, CHAINGUN, nullptr); p->noise_radius = 512; madenoise(snum); lastvisinc = PlayClock + 32; @@ -2949,7 +2943,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) if (p->kickback_pic > 3) { p->okickback_pic = p->kickback_pic = 0; - fi.shoot(pact, GROWSPARK); + fi.shoot(pact, GROWSPARK, nullptr); p->noise_radius = 64; madenoise(snum); checkavailweapon(p); @@ -2962,7 +2956,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) if (p->kickback_pic == 1) { p->ammo_amount[THROWSAW_WEAPON]--; - fi.shoot(pact, SHRINKSPARK); + fi.shoot(pact, SHRINKSPARK, nullptr); checkavailweapon(p); } p->kickback_pic++; @@ -2977,7 +2971,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) p->visibility = 0; lastvisinc = PlayClock + 32; S_PlayActorSound(CHAINGUN_FIRE, pact); - fi.shoot(pact, SHOTSPARK1); + fi.shoot(pact, SHOTSPARK1, nullptr); p->noise_radius = 1024; madenoise(snum); p->ammo_amount[TIT_WEAPON]--; @@ -3004,7 +2998,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) p->visibility = 0; lastvisinc = PlayClock + 32; S_PlayActorSound(CHAINGUN_FIRE, pact); - fi.shoot(pact, CHAINGUN); + fi.shoot(pact, CHAINGUN, nullptr); p->noise_radius = 1024; madenoise(snum); p->ammo_amount[MOTORCYCLE_WEAPON]--; @@ -3031,7 +3025,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) { p->MotoSpeed -= 20; p->ammo_amount[BOAT_WEAPON]--; - fi.shoot(pact, BOATGRENADE); + fi.shoot(pact, BOATGRENADE, nullptr); } p->kickback_pic++; if (p->kickback_pic > 20) @@ -3048,7 +3042,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) case ALIENBLASTER_WEAPON: p->kickback_pic++; if (p->kickback_pic >= 7 && p->kickback_pic <= 11) - fi.shoot(pact, FIRELASER); + fi.shoot(pact, FIRELASER, nullptr); if (p->kickback_pic == 5) { @@ -3106,7 +3100,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) { p->ammo_amount[BOWLING_WEAPON]--; S_PlayActorSound(354, pact); - fi.shoot(pact, BOWLINGBALL); + fi.shoot(pact, BOWLINGBALL, nullptr); p->noise_radius = 64; madenoise(snum); } @@ -3129,7 +3123,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) S_PlayActorSound(426, pact); if (p->kickback_pic == 12) { - fi.shoot(pact, KNEE); + fi.shoot(pact, KNEE, nullptr); p->noise_radius = 64; madenoise(snum); } @@ -3147,7 +3141,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) S_PlayActorSound(252, pact); if (p->kickback_pic == 8) { - fi.shoot(pact, SLINGBLADE); + fi.shoot(pact, SLINGBLADE, nullptr); p->noise_radius = 64; madenoise(snum); } @@ -3167,7 +3161,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) p->ammo_amount[DYNAMITE_WEAPON]--; lastvisinc = PlayClock + 32; p->visibility = 0; - fi.shoot(pact, RPG); + fi.shoot(pact, RPG, nullptr); p->noise_radius = 2048; madenoise(snum); checkavailweapon(p); @@ -3185,7 +3179,7 @@ static void operateweapon(int snum, ESyncBits actions, sectortype* psectp) p->ammo_amount[CHICKEN_WEAPON]--; lastvisinc = PlayClock + 32; p->visibility = 0; - fi.shoot(pact, RPG2); + fi.shoot(pact, RPG2, nullptr); p->noise_radius = 2048; madenoise(snum); checkavailweapon(p); diff --git a/source/games/duke/src/player_w.cpp b/source/games/duke/src/player_w.cpp index ebff77310..c21b94927 100644 --- a/source/games/duke/src/player_w.cpp +++ b/source/games/duke/src/player_w.cpp @@ -65,10 +65,10 @@ void DoFire(player_struct* p, int snum) SetGameVarID(g_iWeaponVarID, p->curr_weapon, p->GetActor(), snum); SetGameVarID(g_iWorksLikeVarID, aplWeaponWorksLike(p->curr_weapon, snum), p->GetActor(), snum); - fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum)); + fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum), nullptr); for (i = 1; i < aplWeaponShotsPerBurst(p->curr_weapon, snum); i++) { - fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum)); + fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum), nullptr); if (aplWeaponFlags(p->curr_weapon, snum) & WEAPON_FLAG_AMMOPERSHOT) { p->ammo_amount[p->curr_weapon]--; @@ -405,7 +405,7 @@ void operateweapon_ww(int snum, ESyncBits actions) } SetGameVarID(g_iWeaponVarID, p->curr_weapon, p->GetActor(), snum); SetGameVarID(g_iWorksLikeVarID, aplWeaponWorksLike(p->curr_weapon, snum), p->GetActor(), snum); - fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum)); + fi.shoot(p->GetActor(), aplWeaponShoots(p->curr_weapon, snum), nullptr); } } diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp index 4fe24c0f5..038d597f7 100644 --- a/source/games/duke/src/sectors_d.cpp +++ b/source/games/duke/src/sectors_d.cpp @@ -969,10 +969,10 @@ void checkhitdefault_d(DDukeActor* targ, DDukeActor* proj) if (Owner && Owner->isPlayer() && targ->spr.picnum != ROTATEGUN && targ->spr.picnum != DRONE) if (ps[Owner->PlayerIndex()].curr_weapon == SHOTGUN_WEAPON) { - fi.shoot(targ, BLOODSPLAT3); - fi.shoot(targ, BLOODSPLAT1); - fi.shoot(targ, BLOODSPLAT2); - fi.shoot(targ, BLOODSPLAT4); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat3")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat1")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat2")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat4")); } if (!actorflag(targ, SFLAG2_NODAMAGEPUSH) && !bossguy(targ)) // RR does not have this. @@ -1172,7 +1172,7 @@ void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj) case FETUSBROKE: for (j = 0; j < 48; j++) { - fi.shoot(targ, BLOODSPLAT1); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat1")); targ->spr.Angles.Yaw += DAngle1 * 58.5; // Was 333, which really makes no sense. } S_PlayActorSound(GLASS_HEAVYBREAK, targ); @@ -1254,21 +1254,21 @@ void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj) targ->spr.extra -= proj->spr.extra; if (targ->spr.extra > 0) break; targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT1); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat1")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT2); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat2")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT3); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat3")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT4); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat4")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT1); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat1")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT2); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat2")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT3); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat3")); targ->spr.Angles.Yaw = randomAngle(); - fi.shoot(targ, BLOODSPLAT4); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat4")); spawnguts(targ, PClass::FindActor("DukeJibs1"), 1); spawnguts(targ, PClass::FindActor("DukeJibs2"), 2); spawnguts(targ, PClass::FindActor("DukeJibs3"), 3); diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index 6b3b64170..bf92f795e 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -1333,10 +1333,10 @@ void checkhitdefault_r(DDukeActor* targ, DDukeActor* proj) if (Owner && Owner->isPlayer() && targ->spr.picnum != DRONE) if (ps[Owner->PlayerIndex()].curr_weapon == SHOTGUN_WEAPON) { - fi.shoot(targ, BLOODSPLAT3); - fi.shoot(targ, BLOODSPLAT1); - fi.shoot(targ, BLOODSPLAT2); - fi.shoot(targ, BLOODSPLAT4); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat3")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat1")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat2")); + fi.shoot(targ, -1, PClass::FindActor("DukeBloodSplat4")); } if (targ->spr.statnum == STAT_ZOMBIEACTOR) diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 60514c29d..5c7dd5e62 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -251,20 +251,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* ChangeActorStat(act, STAT_MISC); break; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - act->spr.cstat |= CSTAT_SPRITE_ALIGNMENT_WALL; - act->spr.scale.X = (0.109375 + (krand() & 7) * REPEAT_SCALE); - act->spr.scale.Y = (0.109375 + (krand() & 7) * REPEAT_SCALE); - act->spr.pos.Z -= 16; - if (actj && actj->spr.pal == 6) - act->spr.pal = 6; - insertspriteq(act); - ChangeActorStat(act, STAT_MISC); - break; - case SPACEMARINE: act->spr.extra = 20; act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index b4dc139e9..26f79cda4 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -194,20 +194,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* act->spr.cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR; [[fallthrough]]; - case BLOODSPLAT1: - case BLOODSPLAT2: - case BLOODSPLAT3: - case BLOODSPLAT4: - act->spr.cstat |= CSTAT_SPRITE_ALIGNMENT_WALL; - act->spr.scale.X = (0.109375 + (krand() & 7) * REPEAT_SCALE); - act->spr.scale.Y = (0.109375 + (krand() & 7) * REPEAT_SCALE); - act->spr.pos.Z -= 16; - if (actj && actj->spr.pal == 6) - act->spr.pal = 6; - insertspriteq(act); - ChangeActorStat(act, STAT_MISC); - break; - case HYDRENT: case SATELITE: case FUELPOD: diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index bb2a63658..5880b42e5 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -619,12 +619,11 @@ void DukeActor_shoot(DDukeActor* act, int intname) { auto cls = PClass::FindActor(FName(ENamedName(intname))); assert(cls); - picnum = GetDefaultByType(cls)->spr.picnum; - fi.shoot(act, picnum); // for now this crutch must suffice. + fi.shoot(act, -1, cls); } else { - fi.shoot(act, picnum); + fi.shoot(act, picnum, nullptr); } } @@ -1138,16 +1137,17 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, floorflags, duke_floorflags) ACTION_RETURN_INT(duke_floorflags(sect)); } -int duke_wallflags(walltype* wal) +int duke_wallflags(walltype* wal, int which) { - return tileflags(wal->picnum); + return tileflags(which? wal->overpicnum : wal->picnum); } DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, wallflags, duke_wallflags) { PARAM_PROLOGUE; PARAM_POINTER(sect, walltype); - ACTION_RETURN_INT(duke_wallflags(sect)); + PARAM_INT(which); + ACTION_RETURN_INT(duke_wallflags(sect, which)); } int duke_ismirror(walltype* wal) diff --git a/wadsrc/static/filter/dukeengine/engine/defines.def b/wadsrc/static/filter/dukeengine/engine/defines.def index c083b905b..288635735 100644 --- a/wadsrc/static/filter/dukeengine/engine/defines.def +++ b/wadsrc/static/filter/dukeengine/engine/defines.def @@ -9,3 +9,5 @@ define TFLAG_SLIME 16 define TFLAG_DOORWALL 32 define TFLAG_BLOCKDOOR 64 define TFLAG_OUTERSPACE 128 +define TFLAG_NOBLOODSPLAT 256 +define TFLAG_NOCIRCLEREFLECT 512 diff --git a/wadsrc/static/filter/dukelike/engine/engine.def b/wadsrc/static/filter/dukelike/engine/engine.def index 7daba65d5..5bf434ba0 100644 --- a/wadsrc/static/filter/dukelike/engine/engine.def +++ b/wadsrc/static/filter/dukelike/engine/engine.def @@ -51,6 +51,10 @@ spawnclasses 1960 = DukeRecon 2300 = DukeOoz 2309 = DukeOoz2 + 2296 = DukeBloodSplat1 + 2297 = DukeBloodSplat2 + 2298 = DukeBloodSplat3 + 2299 = DukeBloodSplat4 1272 = DukeTrash 634 = DukeBolt1 @@ -233,3 +237,7 @@ tileflag TFLAG_OUTERSPACE { MOONSKY1 BIGORBIT1 } + +tileflag TFLAG_NOBLOODSPLAT { + BIGFORCE + } diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index f52223147..775e669ba 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -52,6 +52,10 @@ spawnclasses 1344 = DukeRat 1759 = DukeForceSphere 1529 = DukeOoz + 1525 = DukeBloodSplat1 + 1526 = DukeBloodSplat2 + 1527 = DukeBloodSplat3 + 1528 = DukeBloodSplat4 285 = RedneckChickenSpawner1 286 = RedneckChickenSpawner2 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index a1107b5ef..79d435830 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -57,6 +57,7 @@ version "4.10" #include "zscript/games/duke/actors/soundcontroller.zs" #include "zscript/games/duke/actors/respawncontroller.zs" #include "zscript/games/duke/actors/respawnmarker.zs" +#include "zscript/games/duke/actors/bloodsplats.zs" #include "zscript/games/duke/actors/rat.zs" #include "zscript/games/duke/actors/jibs.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/bloodsplats.zs b/wadsrc/static/zscript/games/duke/actors/bloodsplats.zs new file mode 100644 index 000000000..b8ea4d7e0 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/bloodsplats.zs @@ -0,0 +1,129 @@ +class DukeBloodSplat1 : DukeActor +{ + default + { + statnum STAT_MISC; + Pic "BLOODSPLAT1"; + } + + override void Initialize() + { + self.cstat |= CSTAT_SPRITE_ALIGNMENT_WALL; + self.scale.X = 0.109375 + random(0, 7) * REPEAT_SCALE; + self.scale.Y = 0.109375 + random(0, 7) * REPEAT_SCALE; + self.pos.Z -= 16; + if (self.ownerActor && self.ownerActor.pal == 6) + self.pal = 6; + self.insertspriteq(); + } + + override void Tick() + { + if (self.temp_data[0] < 14 * 26) + { + let offset = frandom(0, 1); + let lerp = 1. - (double(self.temp_data[0]) / (14 * 26)); + let zadj = (1. / 16.) * lerp; + let sadj = (1. / 12.) * lerp * REPEAT_SCALE; + self.pos.Z += zadj + offset * zadj; + self.scale.Y += sadj + offset * sadj; + self.temp_data[0]++; + } + } + + override bool Animate(tspritetype t) + { + if (t.pal == 6) + t.shade = -127; + else + t.shade = 16; + return true; + } + + override bool shootthis(DukeActor shooter, DukePlayer p, Vector3 pos, double ang) const + { + let sectp = shooter.sector; + double zvel; + HitInfo hit; + + if (p != null) ang += frandom(-11.25, 11.25); + else ang += 180 + frandom(-11.25, 11.25); + + zvel = 4 - frandom(0, 8); + + + Raze.hitscan(pos, sectp, (ang.ToVector() * 1024, zvel * 64), hit, 1); + + let wal = hit.hitWall; + if ( (pos.XY - hit.hitpos.XY).Length() >= 64) + return true; + if (wal == null) + return true; + if (wal.hitag != 0) + return true; + if (dlevel.wallflags(wal, 1) & Duke.TFLAG_NOBLOODSPLAT) + return true; + if ((wal.cstat & CSTAT_WALL_MASKED) != 0) + return true; + if (hit.hitSector.lotag != 0) + return true; + + if (wal.twoSided()) + { + if (wal.nextSectorp().lotag != 0 || (hit.hitSector.floorz - wal.nextSectorp().floorz) <= 16) + return true; + if (hit.hitSector.lotag != 0) + return true; + if (wal.nextWallp().hitag != 0) + return true; + + DukeSectIterator it; + for(let act2 = it.First(wal.nextSectorp()); act2; act2 = it.Next()) + { + if (act2.statnum == STAT_EFFECTOR && act2.lotag == SE_13_EXPLOSIVE) + { + return true; + } + } + } + let spawned = shooter.spawn(self.getclassname()); + if (spawned) + { + spawned.vel.X = -0.75; + spawned.Angle = wal.delta().Angle() - 90; + spawned.pos = hit.hitpos; + spawned.cstat |= randomXFlip(); + spawned.DoMove(CLIPMASK0); + spawned.SetPosition(spawned.pos); + spawned.cstat2 |= CSTAT2_SPRITE_DECAL; + + if (shooter.actorflag2(SFLAG2_GREENBLOOD)) + spawned.pal = 6; + } + return true; + } +} + +class DukeBloodSplat2 : DukeBloodSplat1 +{ + default + { + Pic "BLOODSPLAT2"; + } +} + +class DukeBloodSplat3 : DukeBloodSplat1 +{ + default + { + Pic "BLOODSPLAT3"; + } +} + +class DukeBloodSplat4 : DukeBloodSplat1 +{ + default + { + Pic "BLOODSPLAT4"; + } +} diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 5e43f936e..52f775200 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -189,6 +189,10 @@ class DukeActor : CoreActor native virtual void onRespawn(int tag) { } virtual bool animate(tspritetype tspr) { return false; } virtual void RunState() {} // this is the CON function. + virtual bool shootthis(DukeActor actor, DukePlayer p, Vector3 pos, double ang) const // this gets called on the defaults. + { + return false; + } native void RandomScrap(); native void hitradius(int r, int hp1, int hp2, int hp3, int hp4); @@ -231,7 +235,7 @@ struct DukeLevel native static void operatemasterswitches(int lotag); native static void operateactivators(int lotag, DukePlayer p); native static int floorflags(sectortype s); - native static int wallflags(walltype s); + native static int wallflags(walltype s, int which); native static void AddCycler(sectortype sector, int lotag, int shade, int shade2, int hitag, int state); native static void addtorch(sectortype sector, int shade, int lotag); native static void addlightning(sectortype sector, int shade); diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index c0f906701..a86beda0b 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -70,12 +70,16 @@ struct Duke native enum ETextureFlags { - TFLAG_WALLSWITCH = 1, - TFLAG_ADULT = 2, - TFLAG_ELECTRIC = 4, - TFLAG_CLEARINVENTORY = 8, // really dumb Duke stuff... - TFLAG_SLIME = 16, - TFLAG_NOCIRCLEREFLECT = 32, + TFLAG_WALLSWITCH = 1 << 0, + TFLAG_ADULT = 1 << 1, + TFLAG_ELECTRIC = 1 << 2, + TFLAG_CLEARINVENTORY = 1 << 3, // really dumb Duke stuff... + TFLAG_SLIME = 1 << 4, + TFLAG_DOORWALL = 1 << 5, + TFLAG_BLOCKDOOR = 1 << 6, + TFLAG_OUTERSPACE = 1 << 7, + TFLAG_NOBLOODSPLAT = 1 << 8, + TFLAG_NOCIRCLEREFLECT = 1 << 9, }; enum ESoundFlags diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index beb3fe444..ba87fa4a5 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -150,8 +150,16 @@ struct CollisionData native void setWall(walltype w); native void setActor(CoreActor a); native void setVoid(); - } + +struct HitInfo +{ + Vector3 hitpos; + sectortype hitSector; + walltype hitWall; + CoreActor hitActor; +} + struct Raze { const kAngleMask = 0x7FF; @@ -173,6 +181,7 @@ struct Raze native static sectortype updatesector(Vector2 pos, sectortype lastsect, double maxdist = 96); native static sectortype, Vector3 clipmove(Vector3 pos, sectortype sect, Vector2 move, double walldist, double ceildist, double flordist, uint cliptype, CollisionData coll, int clipmoveboxtracenum = 3); native static bool cansee(Vector3 start, sectortype startsec, Vector3 end, sectortype endsec); + native static int hitscan(Vector3 start, sectortype startsect, Vector3 vect, HitInfo hitinfo, uint cliptype, double maxrange = -1); // game check shortcuts