diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 2b5600f4b..bb9bcd49f 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -1363,49 +1363,6 @@ void reactor(DDukeActor* const actor, int REACTOR, int REACTOR2, int REACTORBURN } } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void camera(DDukeActor *actor) -{ - if (actor->temp_data[0] == 0) - { - actor->temp_data[1] += 8; - - if (gs.camerashitable) - { - if (fi.ifhitbyweapon(actor) >= 0) - { - actor->temp_data[0] = 1; // static - actor->spr.cstat = CSTAT_SPRITE_INVISIBLE; - for (int x = 0; x < 5; x++) - RANDOMSCRAP(actor); - return; - } - } - - if (actor->spr.hitag > 0) - { - auto const angle = mapangle(8); - - if (actor->temp_data[1] < actor->spr.hitag) - actor->spr.angle += angle; - else if (actor->temp_data[1] < (actor->spr.hitag * 3)) - actor->spr.angle -= angle; - else if (actor->temp_data[1] < (actor->spr.hitag << 2)) - actor->spr.angle += angle; - else - { - actor->spr.angle += angle; - actor->temp_data[1] = 0; - } - } - } -} - //--------------------------------------------------------------------------- // // diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 10a52132e..074bc31bb 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -790,38 +790,7 @@ void movefallers_d(void) //--------------------------------------------------------------------------- // -// split out of movestandables // -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void moveviewscreen(DDukeActor* actor) -{ - const double VIEWSCR_DIST = 1024; // was originally 2048, was increased to 8192 by EDuke32 and RedNukem, but with high resolutions the resulting 512 map units are still too low. - if (actor->spr.scale.X == 0) deletesprite(actor); - else - { - double a; - int p = findplayer(actor, &a); - - double x = (actor->spr.pos - ps[p].GetActor()->spr.pos).Length(); // the result from findplayer is not really useful. - if (x >= VIEWSCR_DIST && camsprite == actor) - { - camsprite = nullptr; - actor->spr.yint = 0; - actor->temp_data[0] = 0; - } - } -} - -//--------------------------------------------------------------------------- -// -// this has been broken up into lots of smaller subfunctions // //--------------------------------------------------------------------------- @@ -844,11 +813,6 @@ void movestandables_d(void) continue; } - else if (picnum == VIEWSCREEN || picnum == VIEWSCREEN2) - { - moveviewscreen(act); - } - else if (isIn(picnum, CANWITHSOMETHING, CANWITHSOMETHING2, CANWITHSOMETHING3, CANWITHSOMETHING4)) { movecanwithsomething(act); @@ -2367,8 +2331,11 @@ void moveactors_d(void) int *t = &act->temp_data[0]; - - switch (act->spr.picnum) + if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + { + CallTick(act); + } + else switch (act->spr.picnum) { case FLAMETHROWERFLAME: if (isWorldTour()) flamethrowerflame(act); @@ -2495,10 +2462,6 @@ void moveactors_d(void) case REACTOR2: reactor(act, REACTOR, REACTOR2, REACTORBURNT, REACTOR2BURNT, REACTORSPARK, REACTOR2SPARK); continue; - - case CAMERA1: - camera(act); - continue; } diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 0def1e04d..a79d4d550 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -2481,7 +2481,11 @@ void moveactors_r(void) auto sectp = act->sector(); - switch(act->spr.picnum) + if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) + { + CallTick(act); + } + else switch(act->spr.picnum) { case RESPAWNMARKERRED: case RESPAWNMARKERYELLOW: @@ -2684,10 +2688,6 @@ void moveactors_r(void) case REACTOR2: reactor(act, REACTOR, REACTOR2, REACTORBURNT, REACTOR2BURNT, REACTORSPARK, REACTOR2SPARK); continue; - - case CAMERA1: - camera(act); - continue; } diff --git a/source/games/duke/src/animatesprites_d.cpp b/source/games/duke/src/animatesprites_d.cpp index 039f6d781..9a04a9be0 100644 --- a/source/games/duke/src/animatesprites_d.cpp +++ b/source/games/duke/src/animatesprites_d.cpp @@ -177,10 +177,13 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi t->angle = h->interpolatedangle(interpfrac); } + auto sectp = h->sector(); if (h->GetClass() != RUNTIME_CLASS(DDukeActor)) { bool res = CallAnimate(h, t); + if (actorflag(h, SFLAG2_ALWAYSROTATE1)) + applyRotation1(h, t, viewang); if (sectp->floorpal && !actorflag(h, SFLAG2_NOFLOORPAL)) copyfloorpal(t, sectp); @@ -246,21 +249,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi case CRYSTALAMMO: t->shade = int(BobVal(PlayClock << 4) * 16); continue; - case VIEWSCREEN: - case VIEWSCREEN2: - if (camsprite != nullptr && h->GetHitOwner() && h->GetHitOwner()->temp_data[0] == 1) - { - t->picnum = STATIC; - t->cstat |= randomFlip(); - t->scale.X += (0.125); - t->scale.Y += (0.125); - } - else if (camsprite && camsprite == h->GetHitOwner()) - { - t->picnum = TILE_VIEWSCR; - } - break; - case SHRINKSPARK: t->picnum = SHRINKSPARK + ((PlayClock >> 4) & 3); break; @@ -685,7 +673,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi } break; - case CAMERA1: case RAT: if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index cac8b4aeb..03658ebf9 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -157,10 +157,13 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi t->angle = h->interpolatedangle(interpfrac); } + auto sectp = h->sector(); if (h->GetClass() != RUNTIME_CLASS(DDukeActor)) { bool res = CallAnimate(h, t); + if (actorflag(h, SFLAG2_ALWAYSROTATE1)) + applyRotation1(h, t, viewang); if (sectp->floorpal && !actorflag(h, SFLAG2_NOFLOORPAL)) copyfloorpal(t, sectp); @@ -920,7 +923,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi } break; - case CAMERA1: case RAT: k = angletorotation1(t->angle, viewang); if (k > 4) diff --git a/source/games/duke/src/constants.h b/source/games/duke/src/constants.h index 8bcdb86af..6bb2ace63 100644 --- a/source/games/duke/src/constants.h +++ b/source/games/duke/src/constants.h @@ -360,6 +360,7 @@ enum sflags2_t SFLAG2_DONTANIMATE = 0x00000200, SFLAG2_INTERPOLATEANGLE = 0x00000400, SFLAG2_GREENBLOOD = 0x00000800, + SFLAG2_ALWAYSROTATE1 = 0x00001000, }; using EDukeFlags2 = TFlags; diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 3c1ec3495..ef4dd110b 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -116,10 +116,11 @@ extern Dispatcher fi; void CallInitialize(DDukeActor* actor); void CallTick(DDukeActor* actor); +bool CallOperate(DDukeActor* actor, int plnum); void CallAction(DDukeActor* actor); void CallOnHit(DDukeActor* actor, DDukeActor* hitter); void CallOnHurt(DDukeActor* actor, player_struct* hitter); -void CallOnUse(DDukeActor* actor, player_struct* user); +bool CallOnUse(DDukeActor* actor, player_struct* user); bool CallAnimate(DDukeActor* actor, tspritetype* hitter); diff --git a/source/games/duke/src/flags_d.cpp b/source/games/duke/src/flags_d.cpp index 26980d81e..1b2a0805d 100644 --- a/source/games/duke/src/flags_d.cpp +++ b/source/games/duke/src/flags_d.cpp @@ -225,6 +225,7 @@ void initactorflags_d() setflag(SFLAG2_DONTANIMATE, { TRIPBOMB, LASERLINE }); setflag(SFLAG2_INTERPOLATEANGLE, { BEARINGPLATE }); setflag(SFLAG2_GREENBLOOD, { OOZFILTER, NEWBEAST }); + setflag(SFLAG2_ALWAYSROTATE1, { RAT, CAMERA1 }); if (isWorldTour()) { diff --git a/source/games/duke/src/flags_r.cpp b/source/games/duke/src/flags_r.cpp index ccbac965b..1b06cd13f 100644 --- a/source/games/duke/src/flags_r.cpp +++ b/source/games/duke/src/flags_r.cpp @@ -252,6 +252,7 @@ void initactorflags_r() if (isRRRA()) setflag(SFLAG2_BREAKMIRRORS, { RPG2 }); setflag(SFLAG2_CAMERA, { CAMERA1 }); setflag(SFLAG2_GREENBLOOD, { OOZFILTER }); + setflag(SFLAG2_ALWAYSROTATE1, { RAT, CAMERA1 }); // Animals were not supposed to have this, but due to a coding bug the logic was unconditional for everything in the game. for (auto& ainf : gs.actorinfo) diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 68e627933..fe8fb0f1a 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -29,7 +29,7 @@ void movefx(); void moveclouds(double interpfrac); void movefta(); -void clearcameras(int i, player_struct* p); +void clearcameras(player_struct* p); void RANDOMSCRAP(DDukeActor* i); void detonate(DDukeActor* i, int explosion); void movecanwithsomething(DDukeActor* i); @@ -44,7 +44,6 @@ 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 ooz(DDukeActor* i); void reactor(DDukeActor* i, int REACTOR, int REACTOR2, int REACTORBURNT, int REACTOR2BURNT, int REACTORSPARK, int REACTOR2SPARK); -void camera(DDukeActor* i); void bloodsplats(DDukeActor* actor); void forcesphereexplode(DDukeActor* i); void watersplash2(DDukeActor* i); diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index c9d748c5a..5f239fdbc 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -446,13 +446,16 @@ void CallOnHurt(DDukeActor* actor, player_struct* hitter) -void CallOnUse(DDukeActor* actor, player_struct* user) +bool CallOnUse(DDukeActor* actor, player_struct* user) { + int nval = false; IFVIRTUALPTR(actor, DDukeActor, onUse) { VMValue val[2] = { actor, user }; - VMCall(func, val, 2, nullptr, 0); + VMReturn ret(&nval); + VMCall(func, val, 2, &ret, 1); } + return nval; } bool CallAnimate(DDukeActor* actor, tspritetype* tspr) @@ -461,8 +464,8 @@ bool CallAnimate(DDukeActor* actor, tspritetype* tspr) IFVIRTUALPTR(actor, DDukeActor, animate) { VMReturn ret(& nval); - VMValue val[2] = { actor, tspr }; - VMCall(func, val, 2, &ret, 1); + VMValue val[3] = { actor, tspr }; + VMCall(func, val, 3, &ret, 1); } return nval; } diff --git a/source/games/duke/src/inlines.h b/source/games/duke/src/inlines.h index 8b198cdf9..6e52ff5b7 100644 --- a/source/games/duke/src/inlines.h +++ b/source/games/duke/src/inlines.h @@ -2,6 +2,7 @@ #include "gamehud.h" #include "global.h" +#include "models/modeldata.h" // all inline functions. BEGIN_DUKE_NS @@ -244,4 +245,22 @@ inline int angletorotation2(DAngle sprang, DAngle viewang) return ((sprang.Buildang() + 3072 + 128 - viewang.Buildang()) & 2047) / 170; } +inline void applyRotation1(DDukeActor* h, tspritetype* t, DAngle viewang) +{ + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) + { + t->cstat &= ~CSTAT_SPRITE_XFLIP; + return; + } + + int k = angletorotation1(t->angle, viewang); + if (k > 4) + { + k = 8 - k; + t->cstat |= CSTAT_SPRITE_XFLIP; + } + else t->cstat &= ~CSTAT_SPRITE_XFLIP; + t->picnum = h->spr.picnum + k; +} + END_DUKE_NS diff --git a/source/games/duke/src/namelist_d.h b/source/games/duke/src/namelist_d.h index ee3f59efa..9c69fa427 100644 --- a/source/games/duke/src/namelist_d.h +++ b/source/games/duke/src/namelist_d.h @@ -849,4 +849,5 @@ x(DEVELOPERCOMMENTARY, 5294) x(BOSS5, 5310) x(BOSS5STAYPUT, 5311) x(SERIOUSSAM, 5846) +x(VIEWSCR, 30715) // MAXTILES-5 diff --git a/source/games/duke/src/namelist_r.h b/source/games/duke/src/namelist_r.h index 155eccb11..77bf9c5a0 100644 --- a/source/games/duke/src/namelist_r.h +++ b/source/games/duke/src/namelist_r.h @@ -1434,3 +1434,4 @@ x(MAMACLOUD, 8663) x(MAMA, 8705) x(MAMAJIBA, 8890) x(MAMAJIBB, 8895) +x(VIEWSCR, 30715) // MAXTILES-5 diff --git a/source/games/duke/src/premap_d.cpp b/source/games/duke/src/premap_d.cpp index 81a4f1c3a..b5d6d8617 100644 --- a/source/games/duke/src/premap_d.cpp +++ b/source/games/duke/src/premap_d.cpp @@ -158,7 +158,6 @@ static void cachespritenum(DDukeActor* actor) maxc = 3; break; case NUKEBARREL: - case CAMERA1: maxc = 5; break; } diff --git a/source/games/duke/src/premap_r.cpp b/source/games/duke/src/premap_r.cpp index 3ef86e172..5b6e47200 100644 --- a/source/games/duke/src/premap_r.cpp +++ b/source/games/duke/src/premap_r.cpp @@ -266,7 +266,6 @@ static void cachespritenum(DDukeActor* actor) maxc = 3; break; case NUKEBARREL: - case CAMERA1: maxc = 5; break; case VIXEN: diff --git a/source/games/duke/src/sectors_d.cpp b/source/games/duke/src/sectors_d.cpp index 5e5de2f29..2afb813fd 100644 --- a/source/games/duke/src/sectors_d.cpp +++ b/source/games/duke/src/sectors_d.cpp @@ -1438,23 +1438,18 @@ void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj) // //--------------------------------------------------------------------------- -void clearcameras(int i, player_struct* p) +void clearcameras(player_struct* p) { - if (i < 0) + p->restorexyz(); + p->newOwner = nullptr; + + updatesector(p->pos, &p->cursector); + + DukeStatIterator it(STAT_ACTOR); + while (auto act = it.Next()) { - p->restorexyz(); - p->newOwner = nullptr; - - updatesector(p->pos, &p->cursector); - - DukeStatIterator it(STAT_ACTOR); - while (auto act = it.Next()) - { - if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0; - } + if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0; } - else if (p->newOwner != nullptr) - p->newOwner = nullptr; } //--------------------------------------------------------------------------- @@ -1515,7 +1510,7 @@ void checksectors_d(int snum) { if (abs(PlayerInputSideVel(snum)) > 1.5 || abs(PlayerInputForwardVel(snum)) > 1.5) { - clearcameras(-1, p); + clearcameras(p); return; } } @@ -1530,7 +1525,7 @@ void checksectors_d(int snum) { if (p->newOwner != nullptr) { - clearcameras(-1, p); + clearcameras(p); } return; } @@ -1616,91 +1611,67 @@ void checksectors_d(int snum) if (neartagsprite->GetClass() != RUNTIME_CLASS(DDukeActor)) { - CallOnUse(neartagsprite, p); + if (CallOnUse(neartagsprite, p)) + return; } else - switch (neartagsprite->spr.picnum) - { - case TOILET: - case STALL: - if (p->last_pissed_time == 0) + switch (neartagsprite->spr.picnum) { - S_PlayActorSound(DUKE_URINATE, p->GetActor()); + case TOILET: + case STALL: + if (p->last_pissed_time == 0) + { + S_PlayActorSound(DUKE_URINATE, p->GetActor()); - p->last_pissed_time = 26 * 220; - p->transporter_hold = 29 * 2; - if (p->holster_weapon == 0) - { - p->holster_weapon = 1; - p->weapon_pos = -1; + p->last_pissed_time = 26 * 220; + p->transporter_hold = 29 * 2; + if (p->holster_weapon == 0) + { + p->holster_weapon = 1; + p->weapon_pos = -1; + } + if (p->GetActor()->spr.extra <= (gs.max_player_health - (gs.max_player_health / 10))) + { + p->GetActor()->spr.extra += gs.max_player_health / 10; + p->last_extra = p->GetActor()->spr.extra; + } + else if (p->GetActor()->spr.extra < gs.max_player_health) + p->GetActor()->spr.extra = gs.max_player_health; } - if (p->GetActor()->spr.extra <= (gs.max_player_health - (gs.max_player_health / 10))) - { - p->GetActor()->spr.extra += gs.max_player_health / 10; - p->last_extra = p->GetActor()->spr.extra; - } - else if (p->GetActor()->spr.extra < gs.max_player_health) - p->GetActor()->spr.extra = gs.max_player_health; - } - else if (S_CheckActorSoundPlaying(neartagsprite, FLUSH_TOILET) == 0) - S_PlayActorSound(FLUSH_TOILET, neartagsprite); - return; + else if (S_CheckActorSoundPlaying(neartagsprite, FLUSH_TOILET) == 0) + S_PlayActorSound(FLUSH_TOILET, neartagsprite); + return; - case NUKEBUTTON: - { - walltype* wal; - hitawall(p, &wal); - if (wal != nullptr && wal->overpicnum == 0) - if (neartagsprite->temp_data[0] == 0) - { - neartagsprite->temp_data[0] = 1; - neartagsprite->SetOwner(p->GetActor()); - p->buttonpalette = neartagsprite->spr.pal; - if (p->buttonpalette) - ud.secretlevel = neartagsprite->spr.lotag; - else ud.secretlevel = 0; - } - return; - } - case PLUG: - S_PlayActorSound(SHORT_CIRCUIT, pact); - p->GetActor()->spr.extra -= 2 + (krand() & 3); - SetPlayerPal(p, PalEntry(32, 48, 48, 64)); - break; - case VIEWSCREEN: - case VIEWSCREEN2: - { - i = 0; - DukeStatIterator it(STAT_ACTOR); - while (auto acti = it.Next()) + case NUKEBUTTON: { - if (actorflag(acti, SFLAG2_CAMERA) && acti->spr.yint == 0 && neartagsprite->spr.hitag == acti->spr.lotag) - { - acti->spr.yint = 1; //Using this camera - if (snum == screenpeek) S_PlaySound(MONITOR_ACTIVE); - - neartagsprite->SetOwner(acti); - neartagsprite->spr.yint = 1; - camsprite = neartagsprite; - - p->newOwner = acti; - return; - } + walltype* wal; + hitawall(p, &wal); + if (wal != nullptr && wal->overpicnum == 0) + if (neartagsprite->temp_data[0] == 0) + { + neartagsprite->temp_data[0] = 1; + neartagsprite->SetOwner(p->GetActor()); + p->buttonpalette = neartagsprite->spr.pal; + if (p->buttonpalette) + ud.secretlevel = neartagsprite->spr.lotag; + else ud.secretlevel = 0; + } + return; } - i = -1; - } - - clearcameras(i, p); - return; + case PLUG: + S_PlayActorSound(SHORT_CIRCUIT, pact); + p->GetActor()->spr.extra -= 2 + (krand() & 3); + SetPlayerPal(p, PalEntry(32, 48, 48, 64)); + break; } - } + } if (!PlayerInput(snum, SB_OPEN)) return; - else if (p->newOwner != nullptr) + else if (p->newOwner != nullptr) { - clearcameras(-1, p); + clearcameras(p); return; - } + } if (near.hitWall == nullptr && near.hitSector == nullptr && near.actor() == nullptr) if (hits(p->GetActor()) < 32) @@ -1721,7 +1692,7 @@ void checksectors_d(int snum) } else if (p->newOwner != nullptr) { - clearcameras(-1, p); + clearcameras(p); return; } } diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index a552cb720..d8f6c771f 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -2552,7 +2552,8 @@ void checksectors_r(int snum) if (neartagsprite->GetClass() != RUNTIME_CLASS(DDukeActor)) { - CallOnUse(neartagsprite, p); + if (CallOnUse(neartagsprite, p)) + return; } else switch (neartagsprite->spr.picnum) diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 0e3884abe..e01e096e6 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -515,14 +515,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* ChangeActorStat(act, STAT_MISC); break; - case VIEWSCREEN: - case VIEWSCREEN2: - act->SetOwner(act); - act->spr.lotag = 1; - act->spr.extra = 1; - ChangeActorStat(act, STAT_STANDABLE); - break; - case SHELL: //From the player case SHOTGUNSHELL: initshell(actj, act, act->spr.picnum == SHELL); @@ -965,11 +957,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* ChangeActorStat(act, STAT_ZOMBIEACTOR); break; - case CAMERA1: - case CAMERA1 + 1: - case CAMERA1 + 2: - case CAMERA1 + 3: - case CAMERA1 + 4: case CAMERAPOLE: act->spr.extra = 1; @@ -986,9 +973,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* break; } else act->spr.pal = 0; - if (act->spr.picnum == CAMERAPOLE || act->spr.picnum == GENERICPOLE) break; - act->spr.picnum = CAMERA1; - ChangeActorStat(act, STAT_ACTOR); break; case STEAM: if (actj) diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index 6ccadf792..7f822affa 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -1201,11 +1201,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* } act->spr.shade = act->sector()->floorshade; break; - case CAMERA1: - case CAMERA1 + 1: - case CAMERA1 + 2: - case CAMERA1 + 3: - case CAMERA1 + 4: case CAMERAPOLE: act->spr.extra = 1; @@ -1219,9 +1214,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* break; } else act->spr.pal = 0; - if (act->spr.picnum == CAMERAPOLE) break; - act->spr.picnum = CAMERA1; - ChangeActorStat(act, STAT_ACTOR); break; case STEAM: if (actj) diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 831e0cad2..baab9ec1f 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -108,6 +108,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, global_random, duke_global_random) } DEFINE_GLOBAL_UNSIZED(dlevel) +DEFINE_GLOBAL(camsprite) //--------------------------------------------------------------------------- // @@ -694,6 +695,14 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, angle, dukeplayer_angle) ACTION_RETURN_FLOAT(dukeplayer_angle(self)); } +DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, clearcameras, clearcameras) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_struct); + clearcameras(self); + return 0; +} + + static DDukeActor* duke_firstStat(DukeStatIterator* it, int statnum) { it->Reset(statnum); diff --git a/wadsrc/static/filter/duke/engine/engine.def b/wadsrc/static/filter/duke/engine/engine.def index 077ea46a8..8bc7060a1 100644 --- a/wadsrc/static/filter/duke/engine/engine.def +++ b/wadsrc/static/filter/duke/engine/engine.def @@ -26,6 +26,14 @@ spawnclasses 916 = DukeFireext 1079 = DukeOozFilter 1247 = DukeSeenine + 502 = DukeViewscreen + 499 = DukeViewscreen2 + 621 = DukeCamera // yes, they are all the same! + 622 = DukeCamera + 623 = DukeCamera + 624 = DukeCamera + 625 = DukeCamera + 1272 = DukeTrash 634 = DukeBolt1 635 = DukeBolt2 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 624840223..a8d215398 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -65,6 +65,7 @@ version "4.10" #include "zscript/games/duke/actors/bolt.zs" #include "zscript/games/duke/actors/waterdrip.zs" #include "zscript/games/duke/actors/doorshock.zs" +#include "zscript/games/duke/actors/viewscreen.zs" #include "zscript/games/blood/bloodgame.zs" #include "zscript/games/blood/ui/menu.zs" diff --git a/wadsrc/static/zscript/coreactor.zs b/wadsrc/static/zscript/coreactor.zs index eb05721e8..141d6f5e5 100644 --- a/wadsrc/static/zscript/coreactor.zs +++ b/wadsrc/static/zscript/coreactor.zs @@ -56,4 +56,15 @@ class CoreActor native native void backuppos(); native void setPosition(Vector3 pos); native void setPositionZ(Vector3 pos); + + int randomFlip() + { + int r = random(0, 3); + if (r == 0) return 0; + if (r == 1) return CSTAT_SPRITE_XFLIP; + if (r == 2) return CSTAT_SPRITE_YFLIP; + return CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP; + } + + } diff --git a/wadsrc/static/zscript/games/duke/actors/viewscreen.zs b/wadsrc/static/zscript/games/duke/actors/viewscreen.zs new file mode 100644 index 000000000..2809381b4 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/viewscreen.zs @@ -0,0 +1,151 @@ +class DukeViewscreen : DukeActor +{ + default + { + lotag 1; + extra 1; + statnum STAT_STANDABLE; + spriteset "VIEWSCREEN", "STATIC", "VIEWSCR"; + } + + const VIEWSCR_DIST = 1024; // was originally 2048, was increased to 8192 by EDuke32 and RedNukem, but with high resolutions the resulting 512 map units are still too low. + + override void Initialize() + { + self.ownerActor = self; + } + + override void Tick() + { + if (self.scale.X == 0) self.Destroy(); + else + { + let p = self.findplayer(); + + double x = (self.pos - p.actor.pos).LengthSquared(); // the result from findplayer is not really useful. + if (x >= VIEWSCR_DIST * VIEWSCR_DIST && camsprite == self) + { + camsprite = null; + self.yint = 0; + self.temp_data[0] = 0; + } + } + } + + override bool onUse(DukePlayer user) + { + DukeStatIterator it; + for(let acti = it.First(STAT_ACTOR); acti; acti = it.Next()) + { + if (acti.actorflag2(SFLAG2_CAMERA) && acti.yint == 0 && self.hitag == acti.lotag) + { + acti.yint = 1; //Using this camera + if (user == Duke.GetViewPlayer()) Duke.PlaySound(DukeSnd.MONITOR_ACTIVE); + + self.ownerActor = acti; + self.yint = 1; + camsprite = self; + + user.newOwner = acti; + return true; + } + } + user.clearcameras(); + return true; + } + + override bool animate(tspritetype tspr) + { + let actor = DukeActor(tspr.ownerActor); + let hitowner = actor.hitOwnerActor; + if (camsprite != null && hitowner && hitowner.temp_data[0] == 1) + { + tspr.SetSpritePic(self, 1); + tspr.cstat &= ~ (CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP); + tspr.cstat |= randomFlip(); + tspr.scale.X += (0.125); + tspr.scale.Y += (0.125); + } + else if (camsprite && camsprite == hitowner) + { + tspr.SetSpritePic(self, 2); + } + return true; + } +} + +class DukeViewscreen2 : DukeViewscreen +{ + default + { + spriteset "VIEWSCREEN", "STATIC", "VIEWSCR"; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class DukeCamera : DukeActor +{ + default + { + pic "CAMERA1"; + statnum STAT_ACTOR; + extra 1; + } + + override void Initialize() + { + if (gs.camerashitable) self.cstat = CSTAT_SPRITE_BLOCK_ALL; + else self.cstat = 0; + + if (ud.multimode < 2 && self.pal != 0) + { + self.scale = (0, 0); + self.ChangeStat(STAT_MISC); + return; + } + else self.pal = 0; + } + + override void Tick() + { + if (self.temp_data[0] == 0) + { + self.temp_data[1] += 8; + if (gs.camerashitable) + { + int j = self.ifhitbyweapon(); + if (j >= 0) + { + self.temp_data[0] = 1; // static + self.cstat = CSTAT_SPRITE_INVISIBLE; + for (int x = 0; x < 5; x++) + self.RANDOMSCRAP(); + return; + } + } + + if (self.hitag > 0) + { + let angle = 360. / 256; + + if (self.temp_data[1] < self.hitag) + self.angle += angle; + else if (self.temp_data[1] < (self.hitag * 3)) + self.angle -= angle; + else if (self.temp_data[1] < (self.hitag * 4)) + self.angle += angle; + else + { + self.angle += angle; + self.temp_data[1] = 0; + } + } + } + } +} + \ No newline at end of file diff --git a/wadsrc/static/zscript/games/duke/actors/waterfountain.zs b/wadsrc/static/zscript/games/duke/actors/waterfountain.zs index 1601da673..9c6820fe6 100644 --- a/wadsrc/static/zscript/games/duke/actors/waterfountain.zs +++ b/wadsrc/static/zscript/games/duke/actors/waterfountain.zs @@ -69,7 +69,7 @@ class DukeWaterFountain : DukeActor } } - override void onUse(DukePlayer user) + override bool onUse(DukePlayer user) { if (self.temp_data[0] != 1) { @@ -83,6 +83,7 @@ class DukeWaterFountain : DukeActor act.PlayActorSound(DukeSnd.DUKE_DRINKING); } } + return true; } } diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index bd1ec7f67..6c276e215 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -140,7 +140,7 @@ class DukeActor : CoreActor native virtual void Tick() {} virtual void onHit(DukeActor hitter) { checkhitdefault(hitter); } virtual void onHurt(DukePlayer p) {} - virtual void onUse(DukePlayer user) {} + virtual bool onUse(DukePlayer user) { return false; } virtual bool animate(tspritetype tspr) { return false; } virtual void RunState() {} // this is the CON function. @@ -165,6 +165,7 @@ extend struct _ native @DukeGameInfo gs; native @DukeUserDefs ud; native DukeLevel dlevel; + native DukeActor camsprite; } // The level struct is a wrapper to group all level related global variables and static functions into one object. diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index 7e318f743..b2cf9ce02 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -280,6 +280,7 @@ struct DukePlayer native native void addpos(Vector3 pos); native void settargetangle(double angle, bool backup = false); native double angle(); + native void clearcameras(); }