raze/source/games/duke/src/sectors_d.cpp

826 lines
21 KiB
C++
Raw Normal View History

//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements)
2020-05-13 14:19:39 +00:00
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"
2020-06-24 19:21:02 +00:00
#include "sounds.h"
#include "names_d.h"
2020-07-07 15:56:20 +00:00
#include "mapinfo.h"
#include "dukeactor.h"
#include "secrets.h"
// PRIMITIVE
BEGIN_DUKE_NS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void animatewalls_d(void)
{
2021-11-17 21:52:57 +00:00
int t;
2021-11-17 21:52:57 +00:00
for (int p = 0; p < numanimwalls; p++)
{
2021-11-17 23:30:37 +00:00
auto wal = animwall[p].wall;
int j = wal->wallpicnum;
switch (j)
{
case DTILE_SCREENBREAK1:
case DTILE_SCREENBREAK2:
case DTILE_SCREENBREAK3:
case DTILE_SCREENBREAK4:
case DTILE_SCREENBREAK5:
case DTILE_SCREENBREAK9:
case DTILE_SCREENBREAK10:
case DTILE_SCREENBREAK11:
case DTILE_SCREENBREAK12:
case DTILE_SCREENBREAK13:
case DTILE_SCREENBREAK14:
case DTILE_SCREENBREAK15:
case DTILE_SCREENBREAK16:
case DTILE_SCREENBREAK17:
case DTILE_SCREENBREAK18:
case DTILE_SCREENBREAK19:
if ((krand() & 255) < 16)
{
animwall[p].tag = wal->wallpicnum;
wal->wallpicnum = DTILE_SCREENBREAK6;
}
continue;
case DTILE_SCREENBREAK6:
case DTILE_SCREENBREAK7:
case DTILE_SCREENBREAK8:
if (animwall[p].tag >= 0 && wal->extra != DTILE_FEMPIC2 && wal->extra != DTILE_FEMPIC3)
wal->wallpicnum = animwall[p].tag;
else
{
wal->wallpicnum++;
if (wal->wallpicnum == (DTILE_SCREENBREAK6 + 3))
wal->wallpicnum = DTILE_SCREENBREAK6;
}
continue;
}
if (wal->cstat & CSTAT_WALL_MASKED)
2021-11-17 21:52:57 +00:00
switch (wal->overpicnum)
{
case DTILE_W_FORCEFIELD:
case DTILE_W_FORCEFIELD2:
case DTILE_W_FORCEFIELD3:
t = animwall[p].tag;
if (wal->cstat & CSTAT_WALL_ANY_EXCEPT_BLOCK)
{
2022-09-15 16:12:09 +00:00
wal->addxpan(-t / 4096.f);
wal->addypan(-t / 4096.f);
2021-11-17 21:52:57 +00:00
if (wal->extra == 1)
{
2021-11-17 21:52:57 +00:00
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 = DTILE_W_FORCEFIELD;
else wal->overpicnum = DTILE_W_FORCEFIELD2;
}
else
{
if ((krand() & 255) < 32)
animwall[p].tag = 128 << (krand() & 3);
else wal->overpicnum = DTILE_W_FORCEFIELD2;
}
}
break;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-11-02 18:53:04 +00:00
void operateforcefields_d(DDukeActor* act, int low)
{
operateforcefields_common(act, low, { DTILE_W_FORCEFIELD, DTILE_W_FORCEFIELD2, DTILE_W_FORCEFIELD3, DTILE_BIGFORCE });
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool checkaccessswitch_d(int snum, int switchpal, DDukeActor* act, walltype* wwal)
{
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 1;
}
return 0;
}
//---------------------------------------------------------------------------
//
// how NOT to implement switch animations...
//
//---------------------------------------------------------------------------
void togglespriteswitches(DDukeActor* act, const TexExtInfo& ext, int lotag, int& correctdips, int& numdips);
2022-12-11 14:16:19 +00:00
void togglewallswitches(walltype* wwal, const TexExtInfo& ext, int lotag, int& correctdips, int& numdips);
bool checkhitswitch_d(int snum, walltype* wwal, DDukeActor *act)
{
uint8_t switchpal;
2021-11-17 22:01:27 +00:00
int lotag, hitag, picnum, correctdips, numdips;
DVector2 spos;
FTextureID texid;
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;
// custom switches that maintain themselves can immediately abort.
if (CallTriggerSwitch(act, &ps[snum])) return true;
}
else
{
2021-11-17 22:01:27 +00:00
lotag = wwal->lotag;
if (lotag == 0) return 0;
2021-11-17 22:01:27 +00:00
hitag = wwal->hitag;
spos = wwal->pos;
picnum = wwal->wallpicnum;
2021-11-17 22:01:27 +00:00
switchpal = wwal->pal;
}
texid = tileGetTextureID(picnum);
auto& ext = GetExtInfo(texid);
auto& swdef = switches[ext.switchindex];
switch (swdef.type)
{
case SwitchDef::Combo:
break;
case SwitchDef::Access:
if (checkaccessswitch_d(snum, switchpal, act, wwal))
return 0;
[[fallthrough]];
case SwitchDef::Regular:
case SwitchDef::Multi:
if (check_activator_motion(lotag)) return 0;
break;
default:
if (isadoorwall(texid) == 0) return 0;
break;
}
togglespriteswitches(act, ext, lotag, correctdips, numdips);
2022-12-11 14:16:19 +00:00
togglewallswitches(wwal, ext, lotag, correctdips, numdips);
if (lotag == -1)
{
2020-07-07 15:56:20 +00:00
setnextmap(false);
return 1;
}
DVector3 v(spos, ps[snum].GetActor()->getOffsetZ());
switch (picnum)
{
default:
if (isadoorwall(texid) == 0) break;
[[fallthrough]];
case DTILE_DIPSWITCH:
case DTILE_DIPSWITCHON:
case DTILE_TECHSWITCH:
case DTILE_TECHSWITCHON:
case DTILE_ALIENSWITCH:
case DTILE_ALIENSWITCHON:
if (picnum == DTILE_DIPSWITCH || picnum == DTILE_DIPSWITCHON ||
picnum == DTILE_ALIENSWITCH || picnum == DTILE_ALIENSWITCHON ||
picnum == DTILE_TECHSWITCH || picnum == DTILE_TECHSWITCHON)
{
if (picnum == DTILE_ALIENSWITCH || picnum == DTILE_ALIENSWITCHON)
{
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 DTILE_DIPSWITCH2:
case DTILE_DIPSWITCH2ON:
case DTILE_DIPSWITCH3:
case DTILE_DIPSWITCH3ON:
case DTILE_MULTISWITCH:
case DTILE_MULTISWITCH_2:
case DTILE_MULTISWITCH_3:
case DTILE_MULTISWITCH_4:
case DTILE_ACCESSSWITCH:
case DTILE_ACCESSSWITCH2:
case DTILE_SLOTDOOR:
case DTILE_SLOTDOORON:
case DTILE_LIGHTSWITCH:
case DTILE_LIGHTSWITCHON:
case DTILE_SPACELIGHTSWITCH:
case DTILE_SPACELIGHTSWITCHON:
case DTILE_SPACEDOORSWITCH:
case DTILE_SPACEDOORSWITCHON:
case DTILE_FRANKENSTINESWITCH:
case DTILE_FRANKENSTINESWITCHON:
case DTILE_LIGHTSWITCH2:
case DTILE_LIGHTSWITCH2ON:
case DTILE_POWERSWITCH1:
case DTILE_POWERSWITCH1ON:
case DTILE_LOCKSWITCH1:
case DTILE_LOCKSWITCH1ON:
case DTILE_POWERSWITCH2:
case DTILE_POWERSWITCH2ON:
case DTILE_HANDSWITCH:
case DTILE_HANDSWITCHON:
case DTILE_PULLSWITCH:
case DTILE_PULLSWITCHON:
if (picnum == DTILE_MULTISWITCH || picnum == (DTILE_MULTISWITCH_2) ||
picnum == (DTILE_MULTISWITCH_3) || picnum == (DTILE_MULTISWITCH_4))
lotag += picnum - DTILE_MULTISWITCH;
DukeStatIterator itr(STAT_EFFECTOR);
while (auto other = itr.Next())
{
if (other->spr.hitag == lotag)
{
switch (other->spr.lotag)
{
case SE_12_LIGHT_SWITCH:
2021-11-20 23:33:17 +00:00
other->sector()->floorpal = 0;
2020-10-26 05:45:28 +00:00
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:
2020-10-26 05:45:28 +00:00
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;
}
}
}
2022-11-19 14:40:35 +00:00
operateactivators(lotag, &ps[snum]);
2020-11-02 18:53:04 +00:00
fi.operateforcefields(ps[snum].GetActor(), lotag);
operatemasterswitches(lotag);
if (picnum == DTILE_DIPSWITCH || picnum == DTILE_DIPSWITCHON ||
picnum == DTILE_ALIENSWITCH || picnum == DTILE_ALIENSWITCHON ||
picnum == DTILE_TECHSWITCH || picnum == DTILE_TECHSWITCHON) return 1;
if (hitag == 0 && isadoorwall(texid) == 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;
}
2020-05-10 18:59:38 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-18 17:51:19 +00:00
void activatebysector_d(sectortype* sect, DDukeActor* activator)
2020-05-10 18:59:38 +00:00
{
int didit = 0;
2020-11-02 18:28:59 +00:00
DukeSectIterator it(sect);
while (auto act = it.Next())
{
2022-11-20 11:43:24 +00:00
if (isactivator(act))
{
2022-11-19 14:40:35 +00:00
operateactivators(act->spr.lotag, nullptr);
didit = 1;
// return;
}
}
if (didit == 0)
2020-11-02 18:28:59 +00:00
operatesectors(sect, activator);
2020-05-10 18:59:38 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-02-07 10:04:19 +00:00
void checkplayerhurt_d(player_struct* p, const Collision& coll)
2020-05-10 18:59:38 +00:00
{
if (coll.type == kHitSprite)
{
2022-11-15 09:17:23 +00:00
CallOnHurt(coll.actor(), p);
return;
}
if (coll.type != kHitWall) return;
auto wal = coll.hitWall;
if (p->hurt_delay > 0) p->hurt_delay--;
2021-12-18 14:16:31 +00:00
else if (wal->cstat & (CSTAT_WALL_BLOCK | CSTAT_WALL_ALIGN_BOTTOM | CSTAT_WALL_MASKED | CSTAT_WALL_BLOCK_HITSCAN)) switch (wal->overpicnum)
{
case DTILE_W_FORCEFIELD:
case DTILE_W_FORCEFIELD + 1:
case DTILE_W_FORCEFIELD + 2:
p->GetActor()->spr.extra -= 5;
p->hurt_delay = 16;
SetPlayerPal(p, PalEntry(32, 32, 0, 0));
p->vel.XY() = -p->GetActor()->spr.Angles.Yaw.ToVector() * 16;
S_PlayActorSound(DUKE_LONGTERM_PAIN, p->GetActor());
checkhitwall(p->GetActor(), wal, p->GetActor()->getPosWithOffsetZ() + p->GetActor()->spr.Angles.Yaw.ToVector() * 2);
break;
case DTILE_BIGFORCE:
p->hurt_delay = 26;
checkhitwall(p->GetActor(), wal, p->GetActor()->getPosWithOffsetZ() + p->GetActor()->spr.Angles.Yaw.ToVector() * 2);
break;
}
2020-05-10 18:59:38 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void checkhitdefault_d(DDukeActor* targ, DDukeActor* proj)
{
2022-11-24 06:42:17 +00:00
if ((targ->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL) && targ->spr.hitag == 0 && targ->spr.lotag == 0 && targ->spr.statnum == STAT_DEFAULT)
return;
if ((proj->spr.picnum == DTILE_FREEZEBLAST || proj->GetOwner() != targ) && targ->spr.statnum != STAT_PROJECTILE)
{
if (badguy(targ) == 1)
{
if (isWorldTour() && targ->spr.picnum == DTILE_FIREFLY && targ->spr.scale.X < 0.75)
return;
if (proj->spr.picnum == DTILE_RPG) proj->spr.extra <<= 1;
if ((targ->spr.picnum != DTILE_DRONE) && (targ->spr.picnum != DTILE_ROTATEGUN) && (targ->spr.picnum != DTILE_COMMANDER) && targ->spr.picnum != DTILE_GREENSLIME)
if (proj->spr.picnum != DTILE_FREEZEBLAST)
2022-11-29 16:36:01 +00:00
//if (actortype[targ->spr.picnum] == 0) //TRANSITIONAL.
{
auto spawned = spawn(proj, DTILE_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.Angles.Yaw = DAngle22_5 / 4 - randomAngle(22.5 / 2);
}
}
auto Owner = proj->GetOwner();
if (Owner && Owner->isPlayer() && targ->spr.picnum != DTILE_ROTATEGUN && targ->spr.picnum != DTILE_DRONE)
if (ps[Owner->PlayerIndex()].curr_weapon == SHOTGUN_WEAPON)
{
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"));
}
2022-11-28 09:32:55 +00:00
if (!actorflag(targ, SFLAG2_NODAMAGEPUSH) && !bossguy(targ)) // RR does not have this.
{
if ((targ->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == 0)
targ->spr.Angles.Yaw = proj->spr.Angles.Yaw + 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);
}
2022-11-28 09:32:55 +00:00
if (targ->spr.statnum == STAT_ZOMBIEACTOR)
{
2022-11-28 09:32:55 +00:00
ChangeActorStat(targ, STAT_ACTOR);
targ->timetosleep = SLEEPTIME;
}
if ((targ->spr.scale.X < 0.375 || targ->spr.picnum == DTILE_SHARK) && proj->spr.picnum == DTILE_SHRINKSPARK) return;
}
2022-11-24 06:42:17 +00:00
if (targ->spr.statnum != STAT_ZOMBIEACTOR)
{
if (proj->spr.picnum == DTILE_FREEZEBLAST && ((targ->isPlayer() && targ->spr.pal == 1) || (gs.freezerhurtowner == 0 && proj->GetOwner() == targ)))
return;
int hitpic = proj->spr.picnum;
auto Owner = proj->GetOwner();
if (Owner && Owner->isPlayer())
{
if (targ->isPlayer() && ud.coop != 0 && ud.ffire == 0)
return;
auto tOwner = targ->GetOwner();
if (isWorldTour() && hitpic == DTILE_FIREBALL && tOwner && tOwner->spr.picnum != DTILE_FIREBALL)
hitpic = DTILE_FLAMETHROWERFLAME;
}
targ->attackertype = hitpic;
targ->hitextra += proj->spr.extra;
targ->hitang = proj->spr.Angles.Yaw;
targ->SetHitOwner(Owner);
}
2022-11-24 06:42:17 +00:00
if (targ->spr.statnum == STAT_PLAYER)
{
auto p = targ->spr.yint;
if (ps[p].newOwner != nullptr)
{
ps[p].newOwner = nullptr;
ps[p].GetActor()->restoreloc();
updatesector(ps[p].GetActor()->getPosWithOffsetZ(), &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 == DTILE_SHRINKSPARK)
return;
auto hitowner = targ->GetHitOwner();
if (!hitowner || !hitowner->isPlayer())
if (ud.player_skill >= 3)
proj->spr.extra += (proj->spr.extra >> 1);
}
}
}
void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj)
2020-05-10 18:59:38 +00:00
{
2022-01-17 23:30:43 +00:00
if (targ->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallOnHit(targ, proj);
return;
}
if (targ->spr.picnum == DTILE_PLAYERONWATER)
{
targ = targ->GetOwner();
2022-12-02 23:42:42 +00:00
if (!targ) return;
}
2022-12-02 23:42:42 +00:00
checkhitdefault_d(targ, proj);
2020-05-10 18:59:38 +00:00
}
//---------------------------------------------------------------------------
//
// taken out of checksectors to eliminate some gotos.
//
//---------------------------------------------------------------------------
2022-01-21 00:04:08 +00:00
void clearcameras(player_struct* p)
{
p->GetActor()->restorepos();
2022-01-21 00:04:08 +00:00
p->newOwner = nullptr;
updatesector(p->GetActor()->getPosWithOffsetZ(), &p->cursector);
2022-01-21 00:04:08 +00:00
DukeStatIterator it(STAT_ACTOR);
while (auto act = it.Next())
{
if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void checksectors_d(int snum)
{
2022-09-13 22:11:16 +00:00
int i = -1;
2022-02-07 10:04:19 +00:00
player_struct* p;
2021-11-17 23:04:36 +00:00
walltype* hitscanwall;
2021-11-26 17:59:28 +00:00
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(sectindex(p->cursector));
return;
case -1:
p->cursector->lotag = 0;
2020-07-07 15:56:20 +00:00
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))
2020-11-02 18:53:04 +00:00
fi.lotsofmoney(p->GetActor(), 2);
2020-11-02 23:20:51 +00:00
if (p->newOwner != nullptr)
{
if (abs(PlayerInputSideVel(snum)) > 0.75 || abs(PlayerInputForwardVel(snum)) > 0.75)
{
clearcameras(p);
return;
}
else if (PlayerInput(snum, SB_ESCAPE))
{
2022-01-21 00:04:08 +00:00
clearcameras(p);
return;
}
}
if (!(PlayerInput(snum, SB_OPEN)))
p->toggle_key_flag = 0;
else if (!p->toggle_key_flag)
{
2021-11-26 17:59:28 +00:00
near.hitActor = nullptr;
p->toggle_key_flag = 1;
2021-11-17 23:04:36 +00:00
hitscanwall = nullptr;
2022-09-13 22:20:58 +00:00
double dist = hitawall(p, &hitscanwall);
2021-11-17 23:04:36 +00:00
if (hitscanwall != nullptr)
2021-11-17 22:40:10 +00:00
{
if (dist < 80 && hitscanwall->overtexture() == mirrortex)
2021-11-17 23:04:36 +00:00
if (hitscanwall->lotag > 0 && S_CheckSoundPlaying(hitscanwall->lotag) == 0 && snum == screenpeek)
2021-11-17 22:40:10 +00:00
{
2021-11-17 23:04:36 +00:00
S_PlayActorSound(hitscanwall->lotag, pact);
2021-11-17 22:40:10 +00:00
return;
}
if (hitscanwall != nullptr && (hitscanwall->cstat & CSTAT_WALL_MASKED))
2021-11-17 23:04:36 +00:00
if (hitscanwall->lotag)
2021-11-17 22:40:10 +00:00
return;
}
2020-11-02 23:20:51 +00:00
if (p->newOwner != nullptr)
neartag(p->GetActor()->getPrevPosWithOffsetZ(), p->GetActor()->sector(), p->GetActor()->PrevAngles.Yaw, near, 80., NT_Lotag);
else
{
neartag(p->GetActor()->getPosWithOffsetZ(), p->GetActor()->sector(), p->GetActor()->PrevAngles.Yaw, near, 80., NT_Lotag);
2021-11-26 17:59:28 +00:00
if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr)
neartag(p->GetActor()->getPosWithOffsetZ().plusZ(8), p->GetActor()->sector(), p->GetActor()->PrevAngles.Yaw, near, 80., NT_Lotag);
2021-11-26 17:59:28 +00:00
if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr)
neartag(p->GetActor()->getPosWithOffsetZ().plusZ(16), p->GetActor()->sector(), p->GetActor()->PrevAngles.Yaw, near, 80., NT_Lotag);
2021-11-26 17:59:28 +00:00
if (near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr)
{
neartag(p->GetActor()->getPosWithOffsetZ().plusZ(16), p->GetActor()->sector(), p->GetActor()->PrevAngles.Yaw, near, 80., NT_Lotag | NT_Hitag);
2021-11-26 17:59:28 +00:00
if (near.actor() != nullptr)
{
if (actorflag(near.actor(), SFLAG2_TRIGGERRESPAWN))
return;
}
2021-11-26 17:59:28 +00:00
near.clearObj();
}
}
2021-11-26 17:59:28 +00:00
if (p->newOwner == nullptr && near.actor() == nullptr && near.hitWall == nullptr && near.hitSector == nullptr)
2021-11-20 23:33:17 +00:00
if (isanunderoperator(p->GetActor()->sector()->lotag))
near.hitSector = p->GetActor()->sector();
2021-11-26 17:59:28 +00:00
if (near.hitSector && (near.hitSector->lotag & 16384))
return;
2021-11-26 17:59:28 +00:00
if (near.actor() == nullptr && near.hitWall == nullptr)
if (p->cursector->lotag == 2)
{
DDukeActor* hit;
2022-09-13 22:30:08 +00:00
dist = hitasprite(p->GetActor(), &hit);
2021-11-26 17:59:28 +00:00
if (hit) near.hitActor = hit;
2022-09-13 22:11:16 +00:00
if (dist > 80) near.hitActor = nullptr;
}
2021-11-26 17:59:28 +00:00
auto const neartagsprite = near.actor();
2020-10-27 06:00:39 +00:00
if (neartagsprite != nullptr)
{
if (fi.checkhitswitch(snum, nullptr, neartagsprite)) return;
if (CallOnUse(neartagsprite, p))
return;
2022-01-21 00:04:08 +00:00
}
if (!PlayerInput(snum, SB_OPEN)) return;
2022-01-21 00:04:08 +00:00
else if (p->newOwner != nullptr)
{
2022-01-21 00:04:08 +00:00
clearcameras(p);
return;
2022-01-21 00:04:08 +00:00
}
2021-11-26 17:59:28 +00:00
if (near.hitWall == nullptr && near.hitSector == nullptr && near.actor() == nullptr)
2022-09-13 22:05:32 +00:00
if (hits(p->GetActor()) < 32)
{
if ((krand() & 255) < 16)
S_PlayActorSound(DUKE_SEARCH2, pact);
else S_PlayActorSound(DUKE_SEARCH, pact);
return;
}
2021-11-26 17:59:28 +00:00
if (near.hitWall)
{
if (near.hitWall->lotag > 0 && isadoorwall(near.hitWall->walltexture()))
{
2021-11-26 17:59:28 +00:00
if (hitscanwall == near.hitWall || hitscanwall == nullptr)
fi.checkhitswitch(snum, near.hitWall, nullptr);
return;
}
2020-11-02 23:20:51 +00:00
else if (p->newOwner != nullptr)
{
2022-01-21 00:04:08 +00:00
clearcameras(p);
return;
}
}
2021-11-26 17:59:28 +00:00
if (near.hitSector && (near.hitSector->lotag & 16384) == 0 && isanearoperator(near.hitSector->lotag))
{
2021-11-26 17:59:28 +00:00
DukeSectIterator it(near.hitSector);
2020-11-02 18:41:06 +00:00
while (auto act = it.Next())
{
2022-11-20 11:43:24 +00:00
if (isactivator(act) || ismasterswitch(act))
return;
}
2021-11-26 17:59:28 +00:00
operatesectors(near.hitSector, p->GetActor());
}
2021-11-20 23:33:17 +00:00
else if ((p->GetActor()->sector()->lotag & 16384) == 0)
{
2021-11-20 23:33:17 +00:00
if (isanunderoperator(p->GetActor()->sector()->lotag))
{
DukeSectIterator it(p->GetActor()->sector());
2020-11-02 18:41:06 +00:00
while (auto act = it.Next())
{
2022-11-20 11:43:24 +00:00
if (isactivator(act) || ismasterswitch(act)) return;
}
operatesectors(p->GetActor()->sector(), p->GetActor());
}
2021-11-26 17:59:28 +00:00
else fi.checkhitswitch(snum, near.hitWall, nullptr);
}
}
}
END_DUKE_NS