//------------------------------------------------------------------------- /* Copyright (C) 1996, 2003 - 3D Realms Entertainment Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements) Copyright (C) 2020 - Christoph Oelckers This file is part of Enhanced Duke Nukem 3D version 1.5 - Atomic Edition Duke Nukem 3D is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Original Source: 1996 - Todd Replogle Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms EDuke enhancements integrated: 04/13/2003 - Matt Saettler Note: EDuke source was in transition. Changes are in-progress in the source as it is released. */ //------------------------------------------------------------------------- #include "ns.h" #include "global.h" #include "sounds.h" #include "names_d.h" #include "mapinfo.h" #include "dukeactor.h" #include "secrets.h" // PRIMITIVE BEGIN_DUKE_NS //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- bool isadoorwall_d(int dapic) { switch(dapic) { case DOORTILE1: case DOORTILE2: case DOORTILE3: case DOORTILE4: case DOORTILE5: case DOORTILE6: case DOORTILE7: case DOORTILE8: case DOORTILE9: case DOORTILE10: case DOORTILE11: case DOORTILE12: case DOORTILE14: case DOORTILE15: case DOORTILE16: case DOORTILE17: case DOORTILE18: case DOORTILE19: case DOORTILE20: case DOORTILE21: case DOORTILE22: case DOORTILE23: return 1; } return 0; } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void animatewalls_d(void) { int t; for (int p = 0; p < numanimwalls; p++) { auto wal = animwall[p].wall; int j = wal->picnum; switch (j) { case SCREENBREAK1: case SCREENBREAK2: case SCREENBREAK3: case SCREENBREAK4: case SCREENBREAK5: case SCREENBREAK9: case SCREENBREAK10: case SCREENBREAK11: case SCREENBREAK12: case SCREENBREAK13: case SCREENBREAK14: case SCREENBREAK15: case SCREENBREAK16: case SCREENBREAK17: case SCREENBREAK18: case SCREENBREAK19: if ((krand() & 255) < 16) { animwall[p].tag = wal->picnum; wal->picnum = SCREENBREAK6; } continue; case SCREENBREAK6: case SCREENBREAK7: case SCREENBREAK8: if (animwall[p].tag >= 0 && wal->extra != FEMPIC2 && wal->extra != FEMPIC3) wal->picnum = animwall[p].tag; else { wal->picnum++; if (wal->picnum == (SCREENBREAK6 + 3)) wal->picnum = SCREENBREAK6; } continue; } if (wal->cstat & CSTAT_WALL_MASKED) switch (wal->overpicnum) { case W_FORCEFIELD: case W_FORCEFIELD + 1: case W_FORCEFIELD + 2: t = animwall[p].tag; if (wal->cstat & CSTAT_WALL_ANY_EXCEPT_BLOCK) { wal->addxpan(-t / 4096.f); wal->addypan(-t / 4096.f); if (wal->extra == 1) { wal->extra = 0; animwall[p].tag = 0; } else animwall[p].tag += 128; if (animwall[p].tag < (128 << 4)) { if (animwall[p].tag & 128) wal->overpicnum = W_FORCEFIELD; else wal->overpicnum = W_FORCEFIELD + 1; } else { if ((krand() & 255) < 32) animwall[p].tag = 128 << (krand() & 3); else wal->overpicnum = W_FORCEFIELD + 1; } } break; } } } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void operaterespawns_d(int low) { DukeStatIterator it(STAT_FX); while (auto act = it.Next()) { if (act->spr.lotag == low) switch (act->spr.picnum) { case RESPAWN: if (badguypic(act->spr.hitag) && ud.monsters_off) break; auto star = spawn(act, TRANSPORTERSTAR); if (star) { star->spr.pos.Z -= 32; act->spr.extra = 66 - 12; // Just a way to killit } break; } } } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void operateforcefields_d(DDukeActor* act, int low) { operateforcefields_common(act, low, { W_FORCEFIELD, W_FORCEFIELD + 1, W_FORCEFIELD + 2, BIGFORCE }); } //--------------------------------------------------------------------------- // // how NOT to implement switch animations... // //--------------------------------------------------------------------------- bool checkhitswitch_d(int snum, walltype* wwal, DDukeActor *act) { uint8_t switchpal; int lotag, hitag, picnum, correctdips, numdips; DVector2 spos; if (wwal == nullptr && act == nullptr) return 0; correctdips = 1; numdips = 0; if (act) { lotag = act->spr.lotag; if (lotag == 0) return 0; hitag = act->spr.hitag; spos = act->spr.pos.XY(); picnum = act->spr.picnum; switchpal = act->spr.pal; } else { lotag = wwal->lotag; if (lotag == 0) return 0; hitag = wwal->hitag; spos = wwal->pos; picnum = wwal->picnum; switchpal = wwal->pal; } switch (picnum) { case DIPSWITCH: case DIPSWITCH + 1: case TECHSWITCH: case TECHSWITCH + 1: case ALIENSWITCH: case ALIENSWITCH + 1: break; case DEVELOPERCOMMENTARY + 1: //Twentieth Anniversary World Tour if (act) { StopCommentary(); act->spr.picnum = DEVELOPERCOMMENTARY; return true; } return false; case DEVELOPERCOMMENTARY: //Twentieth Anniversary World Tour if (act) { if (StartCommentary(lotag, act)) act->spr.picnum = DEVELOPERCOMMENTARY+1; return true; } return false; case ACCESSSWITCH: case ACCESSSWITCH2: if (ps[snum].access_incs == 0) { if (switchpal == 0) { if ((ps[snum].got_access & 1)) ps[snum].access_incs = 1; else FTA(70, &ps[snum]); } else if (switchpal == 21) { if (ps[snum].got_access & 2) ps[snum].access_incs = 1; else FTA(71, &ps[snum]); } else if (switchpal == 23) { if (ps[snum].got_access & 4) ps[snum].access_incs = 1; else FTA(72, &ps[snum]); } if (ps[snum].access_incs == 1) { if (!act) ps[snum].access_wall = wwal; else ps[snum].access_spritenum = act; } return 0; } [[fallthrough]]; case DIPSWITCH2: case DIPSWITCH2 + 1: case DIPSWITCH3: case DIPSWITCH3 + 1: case MULTISWITCH: case MULTISWITCH + 1: case MULTISWITCH + 2: case MULTISWITCH + 3: case PULLSWITCH: case PULLSWITCH + 1: case HANDSWITCH: case HANDSWITCH + 1: case SLOTDOOR: case SLOTDOOR + 1: case LIGHTSWITCH: case LIGHTSWITCH + 1: case SPACELIGHTSWITCH: case SPACELIGHTSWITCH + 1: case SPACEDOORSWITCH: case SPACEDOORSWITCH + 1: case FRANKENSTINESWITCH: case FRANKENSTINESWITCH + 1: case LIGHTSWITCH2: case LIGHTSWITCH2 + 1: case POWERSWITCH1: case POWERSWITCH1 + 1: case LOCKSWITCH1: case LOCKSWITCH1 + 1: case POWERSWITCH2: case POWERSWITCH2 + 1: if (check_activator_motion(lotag)) return 0; break; default: if (fi.isadoorwall(picnum) == 0) return 0; break; } DukeStatIterator it(STAT_DEFAULT); while (auto other = it.Next()) { if (lotag == other->spr.lotag) switch (other->spr.picnum) { case DIPSWITCH: case TECHSWITCH: case ALIENSWITCH: if (act && act == other) other->spr.picnum++; else if (other->spr.hitag == 0) correctdips++; numdips++; break; case TECHSWITCH + 1: case DIPSWITCH + 1: case ALIENSWITCH + 1: if (act && act == other) other->spr.picnum--; else if (other->spr.hitag == 1) correctdips++; numdips++; break; case MULTISWITCH: case MULTISWITCH + 1: case MULTISWITCH + 2: case MULTISWITCH + 3: other->spr.picnum++; if (other->spr.picnum > (MULTISWITCH + 3)) other->spr.picnum = MULTISWITCH; break; case ACCESSSWITCH: case ACCESSSWITCH2: case SLOTDOOR: case LIGHTSWITCH: case SPACELIGHTSWITCH: case SPACEDOORSWITCH: case FRANKENSTINESWITCH: case LIGHTSWITCH2: case POWERSWITCH1: case LOCKSWITCH1: case POWERSWITCH2: case HANDSWITCH: case PULLSWITCH: case DIPSWITCH2: case DIPSWITCH3: other->spr.picnum++; break; case PULLSWITCH + 1: case HANDSWITCH + 1: case LIGHTSWITCH2 + 1: case POWERSWITCH1 + 1: case LOCKSWITCH1 + 1: case POWERSWITCH2 + 1: case SLOTDOOR + 1: case LIGHTSWITCH + 1: case SPACELIGHTSWITCH + 1: case SPACEDOORSWITCH + 1: case FRANKENSTINESWITCH + 1: case DIPSWITCH2 + 1: case DIPSWITCH3 + 1: other->spr.picnum--; break; } } for (auto& wal : wall) { if (lotag == wal.lotag) switch (wal.picnum) { case DIPSWITCH: case TECHSWITCH: case ALIENSWITCH: if (!act && &wal == wwal) wal.picnum++; else if (wal.hitag == 0) correctdips++; numdips++; break; case DIPSWITCH + 1: case TECHSWITCH + 1: case ALIENSWITCH + 1: if (!act && &wal == wwal) wal.picnum--; else if (wal.hitag == 1) correctdips++; numdips++; break; case MULTISWITCH: case MULTISWITCH + 1: case MULTISWITCH + 2: case MULTISWITCH + 3: wal.picnum++; if (wal.picnum > (MULTISWITCH + 3)) wal.picnum = MULTISWITCH; break; case ACCESSSWITCH: case ACCESSSWITCH2: case SLOTDOOR: case LIGHTSWITCH: case SPACELIGHTSWITCH: case SPACEDOORSWITCH: case LIGHTSWITCH2: case POWERSWITCH1: case LOCKSWITCH1: case POWERSWITCH2: case PULLSWITCH: case HANDSWITCH: case DIPSWITCH2: case DIPSWITCH3: wal.picnum++; break; case HANDSWITCH + 1: case PULLSWITCH + 1: case LIGHTSWITCH2 + 1: case POWERSWITCH1 + 1: case LOCKSWITCH1 + 1: case POWERSWITCH2 + 1: case SLOTDOOR + 1: case LIGHTSWITCH + 1: case SPACELIGHTSWITCH + 1: case SPACEDOORSWITCH + 1: case DIPSWITCH2 + 1: case DIPSWITCH3 + 1: wal.picnum--; break; } } if (lotag == -1) { setnextmap(false); return 1; } DVector3 v(spos, ps[snum].pos.Z); switch (picnum) { default: if (fi.isadoorwall(picnum) == 0) break; [[fallthrough]]; case DIPSWITCH: case DIPSWITCH + 1: case TECHSWITCH: case TECHSWITCH + 1: case ALIENSWITCH: case ALIENSWITCH + 1: if (picnum == DIPSWITCH || picnum == DIPSWITCH + 1 || picnum == ALIENSWITCH || picnum == ALIENSWITCH + 1 || picnum == TECHSWITCH || picnum == TECHSWITCH + 1) { if (picnum == ALIENSWITCH || picnum == ALIENSWITCH + 1) { if (act) S_PlaySound3D(ALIEN_SWITCH1, act, v); else S_PlaySound3D(ALIEN_SWITCH1, ps[snum].GetActor(), v); } else { if (act) S_PlaySound3D(SWITCH_ON, act, v); else S_PlaySound3D(SWITCH_ON, ps[snum].GetActor(), v); } if (numdips != correctdips) break; S_PlaySound3D(END_OF_LEVEL_WARN, ps[snum].GetActor(), v); } [[fallthrough]]; case DIPSWITCH2: case DIPSWITCH2 + 1: case DIPSWITCH3: case DIPSWITCH3 + 1: case MULTISWITCH: case MULTISWITCH + 1: case MULTISWITCH + 2: case MULTISWITCH + 3: case ACCESSSWITCH: case ACCESSSWITCH2: case SLOTDOOR: case SLOTDOOR + 1: case LIGHTSWITCH: case LIGHTSWITCH + 1: case SPACELIGHTSWITCH: case SPACELIGHTSWITCH + 1: case SPACEDOORSWITCH: case SPACEDOORSWITCH + 1: case FRANKENSTINESWITCH: case FRANKENSTINESWITCH + 1: case LIGHTSWITCH2: case LIGHTSWITCH2 + 1: case POWERSWITCH1: case POWERSWITCH1 + 1: case LOCKSWITCH1: case LOCKSWITCH1 + 1: case POWERSWITCH2: case POWERSWITCH2 + 1: case HANDSWITCH: case HANDSWITCH + 1: case PULLSWITCH: case PULLSWITCH + 1: if (picnum == MULTISWITCH || picnum == (MULTISWITCH + 1) || picnum == (MULTISWITCH + 2) || picnum == (MULTISWITCH + 3)) lotag += picnum - MULTISWITCH; DukeStatIterator itr(STAT_EFFECTOR); while (auto other = itr.Next()) { if (other->spr.hitag == lotag) { switch (other->spr.lotag) { case SE_12_LIGHT_SWITCH: other->sector()->floorpal = 0; other->temp_data[0]++; if (other->temp_data[0] == 2) other->temp_data[0]++; break; case SE_24_CONVEYOR: case SE_34: case SE_25_PISTON: other->temp_data[4] = !other->temp_data[4]; if (other->temp_data[4]) FTA(15, &ps[snum]); else FTA(2, &ps[snum]); break; case SE_21_DROP_FLOOR: FTA(2, &ps[screenpeek]); break; } } } operateactivators(lotag, snum); fi.operateforcefields(ps[snum].GetActor(), lotag); operatemasterswitches(lotag); if (picnum == DIPSWITCH || picnum == DIPSWITCH + 1 || picnum == ALIENSWITCH || picnum == ALIENSWITCH + 1 || picnum == TECHSWITCH || picnum == TECHSWITCH + 1) return 1; if (hitag == 0 && fi.isadoorwall(picnum) == 0) { if (act) S_PlaySound3D(SWITCH_ON, act, v); else S_PlaySound3D(SWITCH_ON, ps[snum].GetActor(), v); } else if (hitag != 0) { auto flags = S_GetUserFlags(hitag); if (act && (flags & SF_TALK) == 0) S_PlaySound3D(hitag, act, v); else S_PlayActorSound(hitag, ps[snum].GetActor()); } return 1; } return 0; } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void activatebysector_d(sectortype* sect, DDukeActor* activator) { int didit = 0; DukeSectIterator it(sect); while (auto act = it.Next()) { if (act->spr.picnum == ACTIVATOR) { operateactivators(act->spr.lotag, -1); didit = 1; // return; } } if (didit == 0) operatesectors(sect, activator); } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void checkhitwall_d(DDukeActor* spr, walltype* wal, const DVector3& pos, int atwith) { int j, sn = -1, darkestwall; if (wal->overpicnum == MIRROR && gs.actorinfo[atwith].flags2 & SFLAG2_BREAKMIRRORS) { lotsofglass(spr, wal, 70); wal->cstat &= ~CSTAT_WALL_MASKED; wal->overpicnum = MIRRORBROKE; wal->portalflags = 0; S_PlayActorSound(GLASS_HEAVYBREAK, spr); return; } if (((wal->cstat & CSTAT_WALL_MASKED) || wal->overpicnum == BIGFORCE) && wal->twoSided()) if (wal->nextSector()->floorz> pos.Z) if (wal->nextSector()->floorz - wal->nextSector()->ceilingz) switch (wal->overpicnum) { case W_FORCEFIELD: case W_FORCEFIELD + 1: case W_FORCEFIELD + 2: wal->extra = 1; // tell the forces to animate [[fallthrough]]; case BIGFORCE: { sectortype* sptr = nullptr; updatesector(pos, &sptr); if (sptr == nullptr) return; DDukeActor* spawned; if (atwith == -1) spawned = CreateActor(sptr, pos, FORCERIPPLE, -127, DVector2(0.125, 0.125), nullAngle, 0., 0., spr, 5); else { if (atwith == CHAINGUN) spawned = CreateActor(sptr, pos, FORCERIPPLE, -127, DVector2(0.25, 0.25) + spr->spr.scale, nullAngle, 0., 0., spr, 5); else spawned = CreateActor(sptr, pos, FORCERIPPLE, -127, DVector2(0.5, 0.5), nullAngle, 0., 0., spr, 5); } if (spawned) { spawned->spr.cstat |= CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_YCENTER; spawned->spr.angle = wal->delta().Angle() + DAngle90; S_PlayActorSound(SOMETHINGHITFORCE, spawned); } return; } case FANSPRITE: wal->overpicnum = FANSPRITEBROKE; wal->cstat &= ~(CSTAT_WALL_BLOCK | CSTAT_WALL_BLOCK_HITSCAN); if (wal->twoSided()) { wal->nextWall()->overpicnum = FANSPRITEBROKE; wal->nextWall()->cstat &= ~(CSTAT_WALL_BLOCK | CSTAT_WALL_BLOCK_HITSCAN); } S_PlayActorSound(VENT_BUST, spr); S_PlayActorSound(GLASS_BREAKING, spr); return; case GLASS: { sectortype* sptr = nullptr; updatesector(pos, &sptr); if (sptr == nullptr) return; wal->overpicnum = GLASS2; lotsofglass(spr, wal, 10); wal->cstat = 0; if (wal->twoSided()) wal->nextWall()->cstat = 0; auto spawned = CreateActor(sptr, pos, SECTOREFFECTOR, 0, DVector2(0, 0), ps[0].angle.ang, 0., 0., spr, 3); if (spawned) { spawned->spr.lotag = SE_128_GLASS_BREAKING; spawned->temp_data[1] = 5; spawned->temp_walls[0] = wal; S_PlayActorSound(GLASS_BREAKING, spawned); } return; } case STAINGLASS1: sectortype* sptr = nullptr; updatesector(pos, &sptr); if (sptr == nullptr) return; lotsofcolourglass(spr, wal, 80); wal->cstat = 0; if (wal->twoSided()) wal->nextWall()->cstat = 0; S_PlayActorSound(VENT_BUST, spr); S_PlayActorSound(GLASS_BREAKING, spr); return; } switch (wal->picnum) { case COLAMACHINE: case VENDMACHINE: breakwall(wal->picnum + 2, spr, wal); S_PlayActorSound(VENT_BUST, spr); return; case OJ: case FEMPIC2: case FEMPIC3: case SCREENBREAK6: case SCREENBREAK7: case SCREENBREAK8: case SCREENBREAK1: case SCREENBREAK2: case SCREENBREAK3: case SCREENBREAK4: case SCREENBREAK5: case SCREENBREAK9: case SCREENBREAK10: case SCREENBREAK11: case SCREENBREAK12: case SCREENBREAK13: case SCREENBREAK14: case SCREENBREAK15: case SCREENBREAK16: case SCREENBREAK17: case SCREENBREAK18: case SCREENBREAK19: case BORNTOBEWILDSCREEN: lotsofglass(spr, wal, 30); wal->picnum = W_SCREENBREAK + (krand() % 3); S_PlayActorSound(GLASS_HEAVYBREAK, spr); return; case W_TECHWALL5: case W_TECHWALL6: case W_TECHWALL7: case W_TECHWALL8: case W_TECHWALL9: breakwall(wal->picnum + 1, spr, wal); return; case W_MILKSHELF: breakwall(W_MILKSHELFBROKE, spr, wal); return; case W_TECHWALL10: breakwall(W_HITTECHWALL10, spr, wal); return; case W_TECHWALL1: case W_TECHWALL11: case W_TECHWALL12: case W_TECHWALL13: case W_TECHWALL14: breakwall(W_HITTECHWALL1, spr, wal); return; case W_TECHWALL15: breakwall(W_HITTECHWALL15, spr, wal); return; case W_TECHWALL16: breakwall(W_HITTECHWALL16, spr, wal); return; case W_TECHWALL2: breakwall(W_HITTECHWALL2, spr, wal); return; case W_TECHWALL3: breakwall(W_HITTECHWALL3, spr, wal); return; case W_TECHWALL4: breakwall(W_HITTECHWALL4, spr, wal); return; case ATM: wal->picnum = ATMBROKE; fi.lotsofmoney(spr, 1 + (krand() & 7)); S_PlayActorSound(GLASS_HEAVYBREAK, spr); break; case WALLLIGHT1: case WALLLIGHT2: case WALLLIGHT3: case WALLLIGHT4: case TECHLIGHT2: case TECHLIGHT4: if (rnd(128)) S_PlayActorSound(GLASS_HEAVYBREAK, spr); else S_PlayActorSound(GLASS_BREAKING, spr); lotsofglass(spr, wal, 30); if (wal->picnum == WALLLIGHT1) wal->picnum = WALLLIGHTBUST1; if (wal->picnum == WALLLIGHT2) wal->picnum = WALLLIGHTBUST2; if (wal->picnum == WALLLIGHT3) wal->picnum = WALLLIGHTBUST3; if (wal->picnum == WALLLIGHT4) wal->picnum = WALLLIGHTBUST4; if (wal->picnum == TECHLIGHT2) wal->picnum = TECHLIGHTBUST2; if (wal->picnum == TECHLIGHT4) wal->picnum = TECHLIGHTBUST4; if (!wal->lotag) return; if (!wal->twoSided()) return; darkestwall = 0; for (auto& wl : wallsofsector(wal->nextSector())) if (wl.shade > darkestwall) darkestwall = wl.shade; j = krand() & 1; DukeStatIterator it(STAT_EFFECTOR); while (auto effector = it.Next()) { if (effector->spr.hitag == wal->lotag && effector->spr.lotag == SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT) { effector->temp_data[2] = j; effector->temp_data[3] = darkestwall; effector->temp_data[4] = 1; } } break; } } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void checkplayerhurt_d(player_struct* p, const Collision& coll) { if (coll.type == kHitSprite) { switch (coll.actor()->spr.picnum) { case CACTUS: if (p->hurt_delay < 8) { p->GetActor()->spr.extra -= 5; p->hurt_delay = 16; SetPlayerPal(p, PalEntry(32, 32, 0, 0)); S_PlayActorSound(DUKE_LONGTERM_PAIN, p->GetActor()); } break; } return; } if (coll.type != kHitWall) return; auto wal = coll.hitWall; if (p->hurt_delay > 0) p->hurt_delay--; else if (wal->cstat & (CSTAT_WALL_BLOCK | CSTAT_WALL_ALIGN_BOTTOM | CSTAT_WALL_MASKED | CSTAT_WALL_BLOCK_HITSCAN)) switch (wal->overpicnum) { case W_FORCEFIELD: case W_FORCEFIELD + 1: case W_FORCEFIELD + 2: p->GetActor()->spr.extra -= 5; p->hurt_delay = 16; SetPlayerPal(p, PalEntry(32, 32, 0, 0)); p->vel.XY() = -p->angle.ang.ToVector() * 16; S_PlayActorSound(DUKE_LONGTERM_PAIN, p->GetActor()); fi.checkhitwall(p->GetActor(), wal, p->pos + p->angle.ang.ToVector() * 2, -1); break; case BIGFORCE: p->hurt_delay = 26; fi.checkhitwall(p->GetActor(), wal, p->pos + p->angle.ang.ToVector() * 2, -1); break; } } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- bool checkhitceiling_d(sectortype* sectp) { int j; switch (sectp->ceilingpicnum) { case WALLLIGHT1: case WALLLIGHT2: case WALLLIGHT3: case WALLLIGHT4: case TECHLIGHT2: case TECHLIGHT4: ceilingglass(ps[myconnectindex].GetActor(), sectp, 10); S_PlayActorSound(GLASS_BREAKING, ps[screenpeek].GetActor()); if (sectp->ceilingpicnum == WALLLIGHT1) sectp->ceilingpicnum = WALLLIGHTBUST1; if (sectp->ceilingpicnum == WALLLIGHT2) sectp->ceilingpicnum = WALLLIGHTBUST2; if (sectp->ceilingpicnum == WALLLIGHT3) sectp->ceilingpicnum = WALLLIGHTBUST3; if (sectp->ceilingpicnum == WALLLIGHT4) sectp->ceilingpicnum = WALLLIGHTBUST4; if (sectp->ceilingpicnum == TECHLIGHT2) sectp->ceilingpicnum = TECHLIGHTBUST2; if (sectp->ceilingpicnum == TECHLIGHT4) sectp->ceilingpicnum = TECHLIGHTBUST4; if (!sectp->hitag) { DukeSectIterator it(sectp); while (auto act = it.Next()) { if (act->spr.picnum == SECTOREFFECTOR && act->spr.lotag == SE_12_LIGHT_SWITCH) { DukeStatIterator it1(STAT_EFFECTOR); while (auto act2 = it1.Next()) { if (act2->spr.hitag == act->spr.hitag) act2->temp_data[3] = 1; } break; } } } j = krand() & 1; DukeStatIterator it(STAT_EFFECTOR); while (auto act = it.Next()) { if (act->spr.hitag == (sectp->hitag) && act->spr.lotag == 3) { act->temp_data[2] = j; act->temp_data[4] = 1; } } return 1; } return 0; } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj) { int j, k, p; switch (targ->spr.picnum) { case WTGLASS1: case WTGLASS2: if (!isWorldTour()) break; S_PlayActorSound(GLASS_BREAKING, targ); lotsofglass(targ, nullptr, 10); deletesprite(targ); return; case OCEANSPRITE1: case OCEANSPRITE2: case OCEANSPRITE3: case OCEANSPRITE4: case OCEANSPRITE5: spawn(targ, SMALLSMOKE); deletesprite(targ); break; case QUEBALL: case STRIPEBALL: if (proj->spr.picnum == QUEBALL || proj->spr.picnum == STRIPEBALL) { proj->vel.X = targ->vel.X * 0.75; proj->spr.angle -= targ->spr.angle.Normalized180() * 2 + DAngle180; targ->spr.angle = (targ->spr.pos.XY() - proj->spr.pos.XY()).Angle() - DAngle90; if (S_CheckSoundPlaying(POOLBALLHIT) < 2) S_PlayActorSound(POOLBALLHIT, targ); } else { if (krand() & 3) { targ->vel.X = 10.25; targ->spr.angle = proj->spr.angle; } else { lotsofglass(targ, nullptr, 3); deletesprite(targ); } } break; case TREE1: case TREE2: case TIRE: case CONE: case BOX: if (actorflag(proj, SFLAG_INFLAME)) { if (targ->temp_data[0] == 0) { targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; targ->temp_data[0] = 1; spawn(targ, BURNING); } } break; case CACTUS: // case CACTUSBROKE: if (actorflag(proj, SFLAG_INFLAME)) { for (k = 0; k < 64; k++) { auto a = randomAngle(); auto vel = krandf(4) + 4; auto zvel = -krandf(16) - targ->vel.Z * 0.25; auto spawned = CreateActor(targ->sector(), targ->spr.pos.plusZ(-48), SCRAP3 + (krand() & 3), -8, DVector2(0.75, 0.75), a, vel, zvel, targ, 5); spawned->spr.pal = 8; } if (targ->spr.picnum == CACTUS) targ->spr.picnum = CACTUSBROKE; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; } break; case HANGLIGHT: case GENERICPOLE2: for (k = 0; k < 6; k++) { auto a = randomAngle(); auto vel = krandf(4) + 4; auto zvel = -krandf(16) - targ->vel.Z * 0.25; CreateActor(targ->sector(), targ->spr.pos.plusZ(-8), SCRAP1 + (krand() & 15), -8, DVector2(0.75, 0.75), a, vel, zvel, targ, 5); } S_PlayActorSound(GLASS_HEAVYBREAK, targ); deletesprite(targ); break; case FANSPRITE: targ->spr.picnum = FANSPRITEBROKE; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; if (targ->sector()->floorpicnum == FANSHADOW) targ->sector()->floorpicnum = FANSHADOWBROKE; S_PlayActorSound(GLASS_HEAVYBREAK, targ); for (j = 0; j < 16; j++) RANDOMSCRAP(targ); break; case WATERFOUNTAIN: case WATERFOUNTAIN + 1: case WATERFOUNTAIN + 2: case WATERFOUNTAIN + 3: targ->spr.picnum = WATERFOUNTAINBROKE; spawn(targ, TOILETWATER); break; case SATELITE: case FUELPOD: case SOLARPANNEL: case ANTENNA: if (gs.actorinfo[SHOTSPARK1].scriptaddress && proj->spr.extra != ScriptCode[gs.actorinfo[SHOTSPARK1].scriptaddress]) { for (j = 0; j < 15; j++) { auto a = randomAngle(); auto vel = krandf(8) + 4; auto zvel = -krandf(2) - 1; CreateActor(targ->sector(), DVector3(targ->spr.pos.XY(), targ->sector()->floorz - 12 - j * 2), SCRAP1 + (krand() & 15), -8, DVector2(1, 1), a, vel, zvel, targ, 5); } spawn(targ, EXPLOSION2); deletesprite(targ); } break; case BOTTLE1: case BOTTLE2: case BOTTLE3: case BOTTLE4: case BOTTLE5: case BOTTLE6: case BOTTLE8: case BOTTLE10: case BOTTLE11: case BOTTLE12: case BOTTLE13: case BOTTLE14: case BOTTLE15: case BOTTLE16: case BOTTLE17: case BOTTLE18: case BOTTLE19: case WATERFOUNTAINBROKE: case DOMELITE: case SUSHIPLATE1: case SUSHIPLATE2: case SUSHIPLATE3: case SUSHIPLATE4: case SUSHIPLATE5: case WAITTOBESEATED: case VASE: case STATUEFLASH: case STATUE: if (targ->spr.picnum == BOTTLE10) fi.lotsofmoney(targ, 4 + (krand() & 3)); else if (targ->spr.picnum == STATUE || targ->spr.picnum == STATUEFLASH) { lotsofcolourglass(targ, nullptr, 40); S_PlayActorSound(GLASS_HEAVYBREAK, targ); } else if (targ->spr.picnum == VASE) lotsofglass(targ, nullptr, 40); S_PlayActorSound(GLASS_BREAKING, targ); targ->spr.angle = randomAngle(); lotsofglass(targ, nullptr, 8); deletesprite(targ); break; case FETUS: targ->spr.picnum = FETUSBROKE; S_PlayActorSound(GLASS_BREAKING, targ); lotsofglass(targ, nullptr, 10); break; case FETUSBROKE: for (j = 0; j < 48; j++) { fi.shoot(targ, BLOODSPLAT1); targ->spr.angle += DAngle1 * 58.5; // Was 333, which really makes no sense. } S_PlayActorSound(GLASS_HEAVYBREAK, targ); S_PlayActorSound(SQUISHED, targ); [[fallthrough]]; case BOTTLE7: S_PlayActorSound(GLASS_BREAKING, targ); lotsofglass(targ, nullptr, 10); deletesprite(targ); break; case HYDROPLANT: targ->spr.picnum = BROKEHYDROPLANT; S_PlayActorSound(GLASS_BREAKING, targ); lotsofglass(targ, nullptr, 10); break; case FORCESPHERE: targ->spr.scale.X = (0); if (targ->GetOwner()) { targ->GetOwner()->temp_data[0] = 32; targ->GetOwner()->temp_data[1] = !targ->GetOwner()->temp_data[1]; targ->GetOwner()->temp_data[2] ++; } spawn(targ, EXPLOSION2); break; case BROKEHYDROPLANT: if (targ->spr.cstat & CSTAT_SPRITE_BLOCK) { S_PlayActorSound(GLASS_BREAKING, targ); targ->spr.pos.Z += 16; targ->spr.cstat = 0; lotsofglass(targ, nullptr, 5); } break; case TOILET: targ->spr.picnum = TOILETBROKE; if (krand() & 1) targ->spr.cstat |= CSTAT_SPRITE_XFLIP; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; spawn(targ, TOILETWATER); S_PlayActorSound(GLASS_BREAKING, targ); break; case STALL: targ->spr.picnum = STALLBROKE; if (krand() & 1) targ->spr.cstat |= CSTAT_SPRITE_XFLIP; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; spawn(targ, TOILETWATER); S_PlayActorSound(GLASS_HEAVYBREAK, targ); break; case HYDRENT: targ->spr.picnum = BROKEFIREHYDRENT; spawn(targ, TOILETWATER); S_PlayActorSound(GLASS_HEAVYBREAK, targ); break; case GRATE1: targ->spr.picnum = BGRATE1; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; S_PlayActorSound(VENT_BUST, targ); break; case CIRCLEPANNEL: targ->spr.picnum = CIRCLEPANNELBROKE; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; S_PlayActorSound(VENT_BUST, targ); break; case PANNEL1: case PANNEL2: targ->spr.picnum = BPANNEL1; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; S_PlayActorSound(VENT_BUST, targ); break; case PANNEL3: targ->spr.picnum = BPANNEL3; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; S_PlayActorSound(VENT_BUST, targ); break; case PIPE1: case PIPE2: case PIPE3: case PIPE4: case PIPE5: case PIPE6: switch (targ->spr.picnum) { case PIPE1:targ->spr.picnum = PIPE1B; break; case PIPE2:targ->spr.picnum = PIPE2B; break; case PIPE3:targ->spr.picnum = PIPE3B; break; case PIPE4:targ->spr.picnum = PIPE4B; break; case PIPE5:targ->spr.picnum = PIPE5B; break; case PIPE6:targ->spr.picnum = PIPE6B; break; } { auto spawned = spawn(targ, STEAM); if (spawned) spawned->spr.pos.Z = targ->sector()->floorz - 32; } break; case MONK: case LUKE: case INDY: case JURYGUY: S_PlayActorSound(targ->spr.lotag, targ); spawn(targ, targ->spr.hitag); [[fallthrough]]; case SPACEMARINE: { targ->spr.extra -= proj->spr.extra; if (targ->spr.extra > 0) break; targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT1); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT2); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT3); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT4); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT1); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT2); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT3); targ->spr.angle = randomAngle(); fi.shoot(targ, BLOODSPLAT4); fi.guts(targ, JIBS1, 1, myconnectindex); fi.guts(targ, JIBS2, 2, myconnectindex); fi.guts(targ, JIBS3, 3, myconnectindex); fi.guts(targ, JIBS4, 4, myconnectindex); fi.guts(targ, JIBS5, 1, myconnectindex); fi.guts(targ, JIBS3, 6, myconnectindex); S_PlaySound(SQUISHED); deletesprite(targ); break; } case CHAIR1: case CHAIR2: targ->spr.picnum = BROKENCHAIR; targ->spr.cstat = 0; break; case CHAIR3: case MOVIECAMERA: case SCALE: case VACUUM: case CAMERALIGHT: case IVUNIT: case POT1: case POT2: case POT3: case TRIPODCAMERA: S_PlayActorSound(GLASS_HEAVYBREAK, targ); for (j = 0; j < 16; j++) RANDOMSCRAP(targ); deletesprite(targ); break; case PLAYERONWATER: targ = targ->GetOwner(); if (!targ) break; [[fallthrough]]; default: if ((targ->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL) && targ->spr.hitag == 0 && targ->spr.lotag == 0 && targ->spr.statnum == 0) break; if ((proj->spr.picnum == FREEZEBLAST || proj->GetOwner() != targ) && targ->spr.statnum != 4) { if (badguy(targ) == 1) { if (isWorldTour() && targ->spr.picnum == FIREFLY && targ->spr.scale.X < 0.75) break; if (proj->spr.picnum == RPG) proj->spr.extra <<= 1; if ((targ->spr.picnum != DRONE) && (targ->spr.picnum != ROTATEGUN) && (targ->spr.picnum != COMMANDER) && (targ->spr.picnum < GREENSLIME || targ->spr.picnum > GREENSLIME + 7)) if (proj->spr.picnum != FREEZEBLAST) //if (actortype[targ->spr.picnum] == 0) //TRANSITIONAL. Cannot be done right with EDuke mess backing the engine. { auto spawned = spawn(proj, JIBS6); if (spawned) { if (proj->spr.pal == 6) spawned->spr.pal = 6; spawned->spr.pos.Z += 4; spawned->vel.X = 1; spawned->spr.scale = DVector2(0.375, 0.375); spawned->spr.angle = DAngle22_5 / 4 - randomAngle(22.5 / 2); } } auto Owner = proj->GetOwner(); if (Owner && Owner->spr.picnum == APLAYER && 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); } if (targ->spr.picnum != TANK && !bossguy(targ) && targ->spr.picnum != RECON && targ->spr.picnum != ROTATEGUN) { if ((targ->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == 0) targ->spr.angle = proj->spr.angle + DAngle180; targ->vel.X = -proj->spr.extra * 0.25; auto sp = targ->sector(); pushmove(targ->spr.pos, &sp, 8, 4, 4, CLIPMASK0); if (sp != targ->sector() && sp != nullptr) ChangeActorSect(targ, sp); } if (targ->spr.statnum == 2) { ChangeActorStat(targ, 1); targ->timetosleep = SLEEPTIME; } if ((targ->spr.scale.X < 0.375 || targ->spr.picnum == SHARK) && proj->spr.picnum == SHRINKSPARK) return; } if (targ->spr.statnum != 2) { if (proj->spr.picnum == FREEZEBLAST && ((targ->spr.picnum == APLAYER && targ->spr.pal == 1) || (gs.freezerhurtowner == 0 && proj->GetOwner() == targ))) return; int hitpic = proj->spr.picnum; auto Owner = proj->GetOwner(); if (Owner && Owner->spr.picnum == APLAYER) { if (targ->spr.picnum == APLAYER && ud.coop != 0 && ud.ffire == 0) return; auto tOwner = targ->GetOwner(); if (isWorldTour() && hitpic == FIREBALL && tOwner && tOwner->spr.picnum != FIREBALL) hitpic = FLAMETHROWERFLAME; } targ->attackertype = hitpic; targ->hitextra += proj->spr.extra; targ->hitang = proj->spr.angle; targ->SetHitOwner(Owner); } if (targ->spr.statnum == 10) { p = targ->spr.yint; if (ps[p].newOwner != nullptr) { ps[p].newOwner = nullptr; ps[p].restorexyz(); ps[p].angle.restore(); updatesector(ps[p].pos, &ps[p].cursector); DukeStatIterator it(STAT_ACTOR); while (auto itActor = it.Next()) { if (actorflag(itActor, SFLAG2_CAMERA)) itActor->spr.yint = 0; } } if (targ->spr.scale.X < 0.375 && proj->spr.picnum == SHRINKSPARK) return; auto hitowner = targ->GetHitOwner(); if (!hitowner || hitowner->spr.picnum != APLAYER) if (ud.player_skill >= 3) proj->spr.extra += (proj->spr.extra >> 1); } } break; } } //--------------------------------------------------------------------------- // // taken out of checksectors to eliminate some gotos. // //--------------------------------------------------------------------------- void clearcameras(int i, 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()) { if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0; } } else if (p->newOwner != nullptr) p->newOwner = nullptr; } //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- void checksectors_d(int snum) { int i = -1; player_struct* p; walltype* hitscanwall; HitInfo near; p = &ps[snum]; auto pact = p->GetActor(); if (!p->insector()) return; switch (p->cursector->lotag) { case 32767: p->cursector->lotag = 0; FTA(9, p); p->secret_rooms++; SECRET_Trigger(sectnum(p->cursector)); return; case -1: p->cursector->lotag = 0; setnextmap(false); return; case -2: p->cursector->lotag = 0; p->timebeforeexit = 26 * 8; p->customexitsound = p->cursector->hitag; return; default: if (p->cursector->lotag >= 10000 && p->cursector->lotag < 16383) { if (snum == screenpeek || ud.coop == 1) S_PlayActorSound(p->cursector->lotag - 10000, pact); p->cursector->lotag = 0; } break; } //After this point the the player effects the map with space if (chatmodeon || p->GetActor()->spr.extra <= 0) return; if (ud.cashman && PlayerInput(snum, SB_OPEN)) fi.lotsofmoney(p->GetActor(), 2); if (p->newOwner != nullptr) { if (abs(PlayerInputSideVel(snum)) > 1.5 || abs(PlayerInputForwardVel(snum)) > 1.5) { clearcameras(-1, p); return; } } if (!(PlayerInput(snum, SB_OPEN))) p->toggle_key_flag = 0; else if (!p->toggle_key_flag) { if (PlayerInput(snum, SB_ESCAPE)) { if (p->newOwner != nullptr) { clearcameras(-1, p); } return; } near.hitActor = nullptr; p->toggle_key_flag = 1; hitscanwall = nullptr; double dist = hitawall(p, &hitscanwall); if (hitscanwall != nullptr) { if (dist < 80 && hitscanwall->overpicnum == MIRROR) if (hitscanwall->lotag > 0 && S_CheckSoundPlaying(hitscanwall->lotag) == 0 && snum == screenpeek) { S_PlayActorSound(hitscanwall->lotag, pact); return; } if (hitscanwall != nullptr && (hitscanwall->cstat & CSTAT_WALL_MASKED)) if (hitscanwall->lotag) return; } if (p->newOwner != nullptr) neartag(p->opos, p->GetActor()->sector(), p->angle.oang, near, 80., NT_Lotag); else { neartag(p->pos, p->GetActor()->sector(), p->angle.oang, near, 80., NT_Lotag); if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr) neartag(p->pos.plusZ(8), p->GetActor()->sector(), p->angle.oang, near, 80., NT_Lotag); if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr) neartag(p->pos.plusZ(16), p->GetActor()->sector(), p->angle.oang, near, 80., NT_Lotag); if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr) { neartag(p->pos.plusZ(16), p->GetActor()->sector(), p->angle.oang, near, 80., NT_Lotag | NT_Hitag); if (near.actor() != nullptr) { switch (near.actor()->spr.picnum) { case FEM1: case FEM2: case FEM3: case FEM4: case FEM5: case FEM6: case FEM7: case FEM8: case FEM9: case FEM10: case PODFEM1: case NAKED1: case STATUE: case TOUGHGAL: return; } } near.clearObj(); } } if (p->newOwner == nullptr && near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr) if (isanunderoperator(p->GetActor()->sector()->lotag)) near.hitSector = p->GetActor()->sector(); if (near.hitSector && (near.hitSector->lotag & 16384)) return; if (near.actor() == nullptr && near.hitWall == nullptr) if (p->cursector->lotag == 2) { DDukeActor* hit; dist = hitasprite(p->GetActor(), &hit); if (hit) near.hitActor = hit; if (dist > 80) near.hitActor = nullptr; } auto const neartagsprite = near.actor(); if (neartagsprite != nullptr) { if (fi.checkhitswitch(snum, nullptr, neartagsprite)) return; switch (neartagsprite->spr.picnum) { 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; } 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; 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 WATERFOUNTAIN: if (neartagsprite->temp_data[0] != 1) { neartagsprite->temp_data[0] = 1; neartagsprite->SetOwner(p->GetActor()); if (p->GetActor()->spr.extra < gs.max_player_health) { p->GetActor()->spr.extra++; S_PlayActorSound(DUKE_DRINKING, p->GetActor()); } } 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()) { 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; } } i = -1; } clearcameras(i, p); return; } } if (!PlayerInput(snum, SB_OPEN)) return; else if (p->newOwner != nullptr) { clearcameras(-1, p); return; } if (near.hitWall == nullptr && near.hitSector == nullptr && near.actor() == nullptr) if (hits(p->GetActor()) < 32) { if ((krand() & 255) < 16) S_PlayActorSound(DUKE_SEARCH2, pact); else S_PlayActorSound(DUKE_SEARCH, pact); return; } if (near.hitWall) { if (near.hitWall->lotag > 0 && fi.isadoorwall(near.hitWall->picnum)) { if (hitscanwall == near.hitWall || hitscanwall == nullptr) fi.checkhitswitch(snum, near.hitWall, nullptr); return; } else if (p->newOwner != nullptr) { clearcameras(-1, p); return; } } if (near.hitSector && (near.hitSector->lotag & 16384) == 0 && isanearoperator(near.hitSector->lotag)) { DukeSectIterator it(near.hitSector); while (auto act = it.Next()) { if (act->spr.picnum == ACTIVATOR || act->spr.picnum == MASTERSWITCH) return; } operatesectors(near.hitSector, p->GetActor()); } else if ((p->GetActor()->sector()->lotag & 16384) == 0) { if (isanunderoperator(p->GetActor()->sector()->lotag)) { DukeSectIterator it(p->GetActor()->sector()); while (auto act = it.Next()) { if (act->spr.picnum == ACTIVATOR || act->spr.picnum == MASTERSWITCH) return; } operatesectors(p->GetActor()->sector(), p->GetActor()); } else fi.checkhitswitch(snum, near.hitWall, nullptr); } } } END_DUKE_NS