2020-05-15 20:59:13 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
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 <utility>
|
|
|
|
#include "ns.h"
|
|
|
|
#include "global.h"
|
2020-06-24 19:21:02 +00:00
|
|
|
#include "sounds.h"
|
2020-09-06 10:44:58 +00:00
|
|
|
#include "automap.h"
|
2020-10-21 17:38:53 +00:00
|
|
|
#include "dukeactor.h"
|
2020-11-26 15:03:40 +00:00
|
|
|
#include "interpolate.h"
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
2020-10-24 07:40:10 +00:00
|
|
|
|
2020-05-15 21:46:18 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2022-02-12 11:37:27 +00:00
|
|
|
// this creates a new actor but does not run any init code on it
|
|
|
|
// direct calls should only be done for very simple things.
|
2020-05-15 21:46:18 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-14 18:10:41 +00:00
|
|
|
DDukeActor* CreateActor(sectortype* whatsectp, const DVector3& pos, int s_pn, int8_t s_shd, int8_t s_xr, int8_t s_yr, DAngle s_ang, double s_vel, double s_zvel, DDukeActor* s_ow, int8_t s_stat)
|
2020-05-15 21:46:18 +00:00
|
|
|
{
|
2021-11-19 08:47:17 +00:00
|
|
|
// sector pointer must be strictly validated here or the engine will crash.
|
|
|
|
if (whatsectp == nullptr || !validSectorIndex(sectnum(whatsectp))) return nullptr;
|
2022-08-26 18:05:28 +00:00
|
|
|
// spawning out of range sprites will also crash.
|
|
|
|
if (s_pn < 0 || s_pn >= MAXTILES) return nullptr;
|
2022-09-14 18:10:41 +00:00
|
|
|
auto act = static_cast<DDukeActor*>(::InsertActor(RUNTIME_CLASS(DDukeActor), whatsectp, s_stat));
|
2020-05-15 21:46:18 +00:00
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
if (act == nullptr) return nullptr;
|
2021-12-05 12:43:31 +00:00
|
|
|
SetupGameVarsForActor(act);
|
|
|
|
|
2020-05-15 21:46:18 +00:00
|
|
|
|
2022-02-12 11:37:27 +00:00
|
|
|
act->spr.pos = pos;
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.cstat = 0;
|
|
|
|
act->spr.picnum = s_pn;
|
2022-09-14 18:10:41 +00:00
|
|
|
act->spr.shade = s_shd;
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = s_xr;
|
|
|
|
act->spr.yrepeat = s_yr;
|
|
|
|
act->spr.pal = 0;
|
|
|
|
|
2022-09-14 18:10:41 +00:00
|
|
|
act->spr.angle = s_ang;
|
|
|
|
act->vel.X = s_vel;
|
|
|
|
act->vel.Z = s_zvel;
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xoffset = 0;
|
|
|
|
act->spr.yoffset = 0;
|
2022-09-01 16:15:52 +00:00
|
|
|
act->spr.yint = 0;
|
2022-09-09 16:24:22 +00:00
|
|
|
act->set_const_clipdist(0);
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.pal = 0;
|
|
|
|
act->spr.lotag = 0;
|
2021-12-30 16:10:08 +00:00
|
|
|
act->backuploc();
|
2020-05-15 21:46:18 +00:00
|
|
|
|
2022-09-12 20:58:52 +00:00
|
|
|
act->ovel.Zero();
|
2020-10-24 05:34:54 +00:00
|
|
|
|
|
|
|
act->timetosleep = 0;
|
2021-11-18 19:55:22 +00:00
|
|
|
act->actorstayput = nullptr;
|
2022-01-23 23:10:25 +00:00
|
|
|
act->hitextra = -1;
|
2020-10-24 05:34:54 +00:00
|
|
|
act->cgg = 0;
|
|
|
|
act->movflag = 0;
|
2022-09-14 21:30:10 +00:00
|
|
|
act->tempval = 0;
|
2020-10-24 05:34:54 +00:00
|
|
|
act->dispicnum = 0;
|
2020-11-02 20:21:52 +00:00
|
|
|
act->SetHitOwner(s_ow);
|
|
|
|
act->SetOwner(s_ow);
|
|
|
|
|
|
|
|
if (s_ow)
|
|
|
|
{
|
2021-12-27 22:52:16 +00:00
|
|
|
act->attackertype = s_ow->spr.picnum;
|
2022-02-03 23:44:13 +00:00
|
|
|
act->floorz = s_ow->floorz;
|
|
|
|
act->ceilingz = s_ow->ceilingz;
|
2020-11-02 20:21:52 +00:00
|
|
|
}
|
2020-11-02 20:37:37 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2020-11-02 20:21:52 +00:00
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
memset(act->temp_data, 0, sizeof(act->temp_data));
|
2020-11-29 12:54:58 +00:00
|
|
|
if (gs.actorinfo[s_pn].scriptaddress)
|
2020-05-15 21:46:18 +00:00
|
|
|
{
|
2020-11-29 12:54:58 +00:00
|
|
|
auto sa = &ScriptCode[gs.actorinfo[s_pn].scriptaddress];
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.extra = sa[0];
|
2020-10-24 05:34:54 +00:00
|
|
|
act->temp_data[4] = sa[1];
|
|
|
|
act->temp_data[1] = sa[2];
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.hitag = sa[3];
|
2020-05-15 21:46:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.extra = 0;
|
|
|
|
act->spr.hitag = 0;
|
2020-05-15 21:46:18 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 15:39:43 +00:00
|
|
|
if (show2dsector[act->sectno()]) act->spr.cstat2 |= CSTAT2_SPRITE_MAPPED;
|
2021-12-21 17:19:45 +00:00
|
|
|
else act->spr.cstat2 &= ~CSTAT2_SPRITE_MAPPED;
|
2020-05-15 21:46:18 +00:00
|
|
|
|
2021-12-22 20:06:31 +00:00
|
|
|
act->sprext = {};
|
|
|
|
act->spsmooth = {};
|
2020-05-15 21:46:18 +00:00
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
return act;
|
2020-05-15 21:46:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-15 20:59:13 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-01-19 08:41:48 +00:00
|
|
|
bool initspriteforspawn(DDukeActor* act)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-01-24 22:05:22 +00:00
|
|
|
SetupGameVarsForActor(act);
|
2021-12-27 22:52:16 +00:00
|
|
|
act->attackertype = act->spr.picnum;
|
2021-11-19 09:41:50 +00:00
|
|
|
act->timetosleep = 0;
|
2022-01-23 23:10:25 +00:00
|
|
|
act->hitextra = -1;
|
2020-10-24 05:34:54 +00:00
|
|
|
|
2021-12-30 16:10:08 +00:00
|
|
|
act->backuppos();
|
2020-10-24 05:34:54 +00:00
|
|
|
|
2021-11-19 09:41:50 +00:00
|
|
|
act->SetOwner(act);
|
|
|
|
act->SetHitOwner(act);
|
|
|
|
act->cgg = 0;
|
|
|
|
act->movflag = 0;
|
2022-09-14 21:30:10 +00:00
|
|
|
act->tempval = 0;
|
2021-11-19 09:41:50 +00:00
|
|
|
act->dispicnum = 0;
|
2022-02-03 23:44:13 +00:00
|
|
|
act->floorz = act->sector()->floorz;
|
|
|
|
act->ceilingz = act->sector()->ceilingz;
|
2020-10-24 05:34:54 +00:00
|
|
|
|
2022-09-12 20:58:52 +00:00
|
|
|
act->ovel.Zero();
|
2021-11-19 09:41:50 +00:00
|
|
|
act->actorstayput = nullptr;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
act->temp_data[0] = act->temp_data[1] = act->temp_data[2] = act->temp_data[3] = act->temp_data[4] = act->temp_data[5] = 0;
|
2021-11-19 09:41:50 +00:00
|
|
|
act->temp_actor = nullptr;
|
2022-08-29 21:12:39 +00:00
|
|
|
act->temp_angle = nullAngle;
|
2022-08-29 21:13:16 +00:00
|
|
|
act->temp_pos = DVector3(0, 0, 0);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-01-19 08:41:48 +00:00
|
|
|
if (wallswitchcheck(act) && (act->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL))
|
|
|
|
{
|
|
|
|
if (act->spr.picnum != TILE_ACCESSSWITCH && act->spr.picnum != TILE_ACCESSSWITCH2 && act->spr.pal)
|
2021-11-19 09:41:50 +00:00
|
|
|
{
|
2022-01-19 08:41:48 +00:00
|
|
|
if ((ud.multimode < 2) || (ud.multimode > 1 && ud.coop == 1))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-01-19 08:41:48 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 0;
|
|
|
|
act->spr.cstat = 0;
|
|
|
|
act->spr.lotag = act->spr.hitag = 0;
|
2021-12-04 12:02:38 +00:00
|
|
|
return false;
|
2021-11-19 09:41:50 +00:00
|
|
|
}
|
2022-01-19 08:41:48 +00:00
|
|
|
}
|
|
|
|
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
|
|
|
|
if (act->spr.pal && act->spr.picnum != TILE_ACCESSSWITCH && act->spr.picnum != TILE_ACCESSSWITCH2)
|
|
|
|
act->spr.pal = 0;
|
|
|
|
return false;
|
|
|
|
}
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-01-19 08:41:48 +00:00
|
|
|
if (!actorflag(act, SFLAG_NOFALLER) && (act->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK))
|
|
|
|
{
|
|
|
|
if (act->spr.shade == 127) return false;
|
|
|
|
|
|
|
|
if (act->spr.hitag)
|
|
|
|
{
|
|
|
|
ChangeActorStat(act, STAT_FALLER);
|
|
|
|
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
|
|
|
|
act->spr.extra = gs.impact_damage;
|
|
|
|
return false;
|
2021-11-19 09:41:50 +00:00
|
|
|
}
|
2022-01-19 08:41:48 +00:00
|
|
|
}
|
2021-11-19 09:41:50 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
int s = act->spr.picnum;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
if (act->spr.cstat & CSTAT_SPRITE_BLOCK) act->spr.cstat |= CSTAT_SPRITE_BLOCK_HITSCAN;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-19 09:41:50 +00:00
|
|
|
if (gs.actorinfo[s].scriptaddress)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.extra = ScriptCode[gs.actorinfo[s].scriptaddress];
|
2021-12-23 15:24:11 +00:00
|
|
|
act->temp_data[4] = ScriptCode[gs.actorinfo[s].scriptaddress+1];
|
|
|
|
act->temp_data[1] = ScriptCode[gs.actorinfo[s].scriptaddress+2];
|
2021-11-19 09:41:50 +00:00
|
|
|
int s3 = ScriptCode[gs.actorinfo[s].scriptaddress+3];
|
2021-12-21 20:57:23 +00:00
|
|
|
if (s3 && act->spr.hitag == 0)
|
|
|
|
act->spr.hitag = s3;
|
2021-11-19 09:41:50 +00:00
|
|
|
}
|
2021-12-23 15:24:11 +00:00
|
|
|
else act->temp_data[1] = act->temp_data[4] = 0;
|
2021-12-04 12:02:38 +00:00
|
|
|
return true;
|
2021-11-19 09:41:50 +00:00
|
|
|
}
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-19 09:41:50 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
DDukeActor* spawn(DDukeActor* actj, int pn)
|
|
|
|
{
|
|
|
|
if (actj)
|
|
|
|
{
|
2022-09-14 18:53:34 +00:00
|
|
|
auto spawned = CreateActor(actj->sector(), actj->spr.pos, pn, 0, 0, 0, nullAngle, 0., 0., actj, 0);
|
2021-11-19 09:41:50 +00:00
|
|
|
if (spawned)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-27 22:52:16 +00:00
|
|
|
spawned->attackertype = actj->spr.picnum;
|
2021-12-04 12:02:38 +00:00
|
|
|
return fi.spawninit(actj, spawned, nullptr);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-19 09:41:50 +00:00
|
|
|
return nullptr;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 17:58:23 +00:00
|
|
|
void spawninitdefault(DDukeActor* actj, DDukeActor *act)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
if (gs.actorinfo[act->spr.picnum].scriptaddress)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actj == nullptr && act->spr.lotag > ud.player_skill)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
// make it go away...
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init the size
|
2021-12-21 20:57:23 +00:00
|
|
|
if (act->spr.xrepeat == 0 || act->spr.yrepeat == 0)
|
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 1;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-23 17:02:58 +00:00
|
|
|
if (actorflag(act, SFLAG_BADGUY))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
if (ud.monsters_off == 1)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-02 17:58:23 +00:00
|
|
|
makeitfall(act);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-23 17:02:58 +00:00
|
|
|
if (actorflag(act, SFLAG_BADGUYSTAYPUT))
|
2021-12-30 15:51:56 +00:00
|
|
|
act->actorstayput = act->sector();
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-23 17:02:58 +00:00
|
|
|
if (!isRR() || actorflag(act, SFLAG_KILLCOUNT)) // Duke is just like Doom - Bad guys always count as kill.
|
2020-05-15 20:59:13 +00:00
|
|
|
ps[myconnectindex].max_actors_killed++;
|
|
|
|
|
2022-09-09 16:24:22 +00:00
|
|
|
act->set_const_clipdist(80);
|
2020-11-02 17:58:23 +00:00
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (actj->spr.picnum == RESPAWN)
|
2022-09-14 21:30:10 +00:00
|
|
|
act->tempval = act->spr.pal = actj->spr.pal;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(act, STAT_ACTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2021-11-26 20:52:01 +00:00
|
|
|
else ChangeActorStat(act, STAT_ZOMBIEACTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-09 16:24:22 +00:00
|
|
|
act->set_const_clipdist(40);
|
2020-11-02 17:58:23 +00:00
|
|
|
act->SetOwner(act);
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(act, STAT_ACTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
act->timetosleep = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-11-02 17:58:23 +00:00
|
|
|
if (actj)
|
2022-08-28 03:15:31 +00:00
|
|
|
act->spr.angle = actj->spr.angle;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
void spawntransporter(DDukeActor *actj, DDukeActor* act, bool beam)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
if (actj == nullptr) return;
|
2020-05-15 20:59:13 +00:00
|
|
|
if (beam)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = 31;
|
|
|
|
act->spr.yrepeat = 1;
|
2022-02-06 21:56:25 +00:00
|
|
|
act->spr.pos.Z = actj->sector()->floorz - gs.playerheight;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actj->spr.statnum == 4)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = 8;
|
|
|
|
act->spr.yrepeat = 8;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = 48;
|
|
|
|
act->spr.yrepeat = 64;
|
|
|
|
if (actj->spr.statnum == 10 || badguy(actj))
|
2022-08-20 15:59:15 +00:00
|
|
|
act->spr.pos.Z -= 32;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.shade = -127;
|
|
|
|
act->spr.cstat = CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_TRANSLUCENT;
|
2022-08-28 03:15:31 +00:00
|
|
|
act->spr.angle = actj->spr.angle;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-03 08:05:20 +00:00
|
|
|
act->vel.X = 8;
|
2021-12-21 20:57:23 +00:00
|
|
|
ChangeActorStat(act, STAT_MISC);
|
|
|
|
ssp(act, CLIPMASK0);
|
2022-08-22 16:34:01 +00:00
|
|
|
SetActor(act, act->spr.pos);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
int spawnbloodpoolpart1(DDukeActor* act)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-13 17:40:32 +00:00
|
|
|
bool away = isAwayFromWall(act, 6.75);
|
|
|
|
|
|
|
|
if (!away)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-13 17:40:32 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 0; ChangeActorStat(act, STAT_MISC); return true;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
if (act->sector()->lotag == 1)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
ChangeActorStat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
void initfootprint(DDukeActor* actj, DDukeActor* act)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
auto sect = act->sector();
|
2020-11-02 20:21:52 +00:00
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-13 17:40:32 +00:00
|
|
|
bool away = isAwayFromWall(act, 5.25);
|
|
|
|
if (!away)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-13 17:40:32 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 0;
|
|
|
|
return;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.cstat = CSTAT_SPRITE_ALIGNMENT_FLOOR;
|
2022-09-01 14:42:23 +00:00
|
|
|
if ((ps[actj->PlayerIndex()].footprintcount & 1)) act->spr.cstat |= CSTAT_SPRITE_XFLIP;
|
2022-08-28 03:15:31 +00:00
|
|
|
act->spr.angle = actj->spr.angle;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2022-09-13 20:49:32 +00:00
|
|
|
act->spr.pos.Z = sect->floorz;
|
2021-11-17 23:47:46 +00:00
|
|
|
if (sect->lotag != 1 && sect->lotag != 2)
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = 32;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
insertspriteq(act);
|
|
|
|
ChangeActorStat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
void initshell(DDukeActor* actj, DDukeActor* act, bool isshell)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-08-29 20:31:29 +00:00
|
|
|
int snum;
|
|
|
|
DAngle ang;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-31 17:47:00 +00:00
|
|
|
if (actj->isPlayer())
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-01 15:26:46 +00:00
|
|
|
snum = actj->PlayerIndex();
|
2022-09-11 12:02:04 +00:00
|
|
|
ang = ps[snum].angle.ang - mapangle((krand() & 63) + 8); //Fine tune
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
act->temp_data[0] = krand() & 1;
|
2022-10-11 06:46:56 +00:00
|
|
|
act->spr.pos.Z = 3 + ps[snum].pos.Z + ps[snum].pyoff + (ps[snum].horizon.sum().Tan() * 8.) + (!isshell ? 3 : 0);
|
2022-09-13 17:56:37 +00:00
|
|
|
act->vel.Z = -krandf(1);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-29 20:31:29 +00:00
|
|
|
ang = act->spr.angle;
|
2022-02-06 21:56:25 +00:00
|
|
|
act->spr.pos.Z = actj->spr.pos.Z - gs.playerheight + 3;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 20:59:44 +00:00
|
|
|
act->spr.pos.XY() = actj->spr.pos.XY() + ang.ToVector() * 8;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.shade = -8;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (isNamWW2GI())
|
|
|
|
{
|
|
|
|
// to the right, with feeling
|
2022-08-29 20:31:29 +00:00
|
|
|
act->spr.angle = ang + DAngle90;
|
2022-09-13 17:56:37 +00:00
|
|
|
act->vel.X = 1.875;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-29 20:31:29 +00:00
|
|
|
act->spr.angle = ang - DAngle90;
|
2022-09-13 17:56:37 +00:00
|
|
|
act->vel.X = 1.25;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.xrepeat = act->spr.yrepeat = isRR() && isshell? 2 : 4;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
ChangeActorStat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
void initcrane(DDukeActor* actj, DDukeActor* act, int CRANEPOLE)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
auto sect = act->sector();
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_ONE_SIDE;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->spr.picnum += 2;
|
2022-02-07 10:00:15 +00:00
|
|
|
act->spr.pos.Z = sect->ceilingz + 48;
|
2021-12-23 15:24:11 +00:00
|
|
|
act->temp_data[4] = cranes.Reserve(1);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
auto& apt = cranes[act->temp_data[4]];
|
2022-02-07 10:00:15 +00:00
|
|
|
apt.pos = act->spr.pos;
|
2021-12-07 16:09:28 +00:00
|
|
|
apt.poleactor = nullptr;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
DukeStatIterator it(STAT_DEFAULT);
|
2021-12-24 00:24:26 +00:00
|
|
|
while (auto actk = it.Next())
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-24 00:24:26 +00:00
|
|
|
if (actk->spr.picnum == CRANEPOLE && act->spr.hitag == actk->spr.hitag)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-24 00:24:26 +00:00
|
|
|
apt.poleactor = actk;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
act->temp_sect = actk->sector();
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-24 00:24:26 +00:00
|
|
|
actk->spr.xrepeat = 48;
|
|
|
|
actk->spr.yrepeat = 128;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-02-07 10:00:15 +00:00
|
|
|
apt.pole = actk->spr.pos.XY();
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-02-07 10:00:15 +00:00
|
|
|
actk->spr.pos = act->spr.pos;
|
2021-12-24 00:24:26 +00:00
|
|
|
actk->spr.shade = act->spr.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-02-07 10:00:15 +00:00
|
|
|
SetActor(actk, actk->spr.pos);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
act->SetOwner(nullptr);
|
|
|
|
act->spr.extra = 8;
|
|
|
|
ChangeActorStat(act, STAT_STANDABLE);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
void initwaterdrip(DDukeActor* actj, DDukeActor* actor)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (actj && (actj->spr.statnum == 10 || actj->spr.statnum == 1))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.shade = 32;
|
2021-12-21 17:19:45 +00:00
|
|
|
if (actj->spr.pal != 1)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.pal = 2;
|
2022-08-20 15:59:15 +00:00
|
|
|
actor->spr.pos.Z -= 18;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2022-08-20 15:59:15 +00:00
|
|
|
else actor->spr.pos.Z -= 13;
|
2022-09-30 11:38:21 +00:00
|
|
|
actor->spr.angle = (ps[connecthead].pos.XY() - actor->spr.pos.XY()).Angle();
|
2022-09-13 17:56:37 +00:00
|
|
|
actor->vel.X = 3 - krandf(2);
|
2020-11-02 20:37:37 +00:00
|
|
|
ssp(actor, CLIPMASK0);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2020-11-02 20:37:37 +00:00
|
|
|
else if (!actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-02-07 07:47:18 +00:00
|
|
|
actor->spr.pos.Z += 4;
|
2022-09-13 20:49:32 +00:00
|
|
|
actor->temp_pos.Z = actor->spr.pos.Z;
|
2021-12-23 15:24:11 +00:00
|
|
|
if (!isRR()) actor->temp_data[1] = krand() & 127;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.xrepeat = 24;
|
|
|
|
actor->spr.yrepeat = 24;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_STANDABLE);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
int initreactor(DDukeActor* actj, DDukeActor* actor, bool isrecon)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
if (isrecon)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.lotag > ud.player_skill)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.xrepeat = actor->spr.yrepeat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return true;
|
|
|
|
}
|
2020-10-23 17:02:58 +00:00
|
|
|
if (!isRR() || actorflag(actor, SFLAG_KILLCOUNT)) // Duke is just like Doom - Bad guys always count as kill.
|
2020-05-15 20:59:13 +00:00
|
|
|
ps[myconnectindex].max_actors_killed++;
|
2020-10-23 17:02:58 +00:00
|
|
|
actor->temp_data[5] = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
if (ud.monsters_off == 1)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.xrepeat = actor->spr.yrepeat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.extra = 130;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.extra = gs.impact_damage;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
if (ud.multimode < 2 && actor->spr.pal != 0)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.xrepeat = actor->spr.yrepeat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.pal = 0;
|
|
|
|
actor->spr.shade = -17;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, 2);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-12-04 12:02:38 +00:00
|
|
|
void spawneffector(DDukeActor* actor, TArray<DDukeActor*>* actors)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
auto sectp = actor->sector();
|
2022-09-11 22:56:23 +00:00
|
|
|
int clostest = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-01 16:15:52 +00:00
|
|
|
actor->spr.yint = sectp->extra;
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
|
|
|
actor->spr.xrepeat = actor->spr.yrepeat = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
switch (actor->spr.lotag)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_28_LIGHTNING:
|
2021-12-23 15:24:11 +00:00
|
|
|
if (!isRR()) actor->temp_data[5] = 65;// Delay for lightning
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_7_TELEPORT: // Transporters!!!!
|
|
|
|
case SE_23_ONE_WAY_TELEPORT:// XPTR END
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.lotag != SE_23_ONE_WAY_TELEPORT && actors)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2021-12-04 12:02:38 +00:00
|
|
|
for(auto act2 : *actors)
|
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act2->spr.statnum < MAXSTATUS && act2->spr.picnum == SECTOREFFECTOR && (act2->spr.lotag == SE_7_TELEPORT || act2->spr.lotag == SE_23_ONE_WAY_TELEPORT) &&
|
2021-12-21 20:57:23 +00:00
|
|
|
actor != act2 && act2->spr.hitag == actor->spr.hitag)
|
2020-11-02 21:20:41 +00:00
|
|
|
{
|
|
|
|
actor->SetOwner(act2);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-12-04 12:02:38 +00:00
|
|
|
}
|
2020-11-02 21:20:41 +00:00
|
|
|
}
|
|
|
|
else actor->SetOwner(actor);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-08-28 09:35:03 +00:00
|
|
|
actor->temp_data[4] = sectp->floorz == actor->spr.pos.Z;
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.cstat = 0;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_TRANSPORT);
|
2020-05-15 20:59:13 +00:00
|
|
|
return;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_1_PIVOT:
|
2020-11-02 21:26:32 +00:00
|
|
|
actor->SetOwner(nullptr);
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[0] = 1;
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-08-22 17:32:51 +00:00
|
|
|
if (actor->spr.intangle == 512)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-08-22 17:32:51 +00:00
|
|
|
actor->temp_data[1] = FloatToFixed<8>(sectp->ceilingz);
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.pal)
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setceilingz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-22 17:32:51 +00:00
|
|
|
actor->temp_data[1] = FloatToFixed<8>(sectp->floorz);
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.pal)
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setfloorz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.hitag <<= 2;
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_19_EXPLOSION_LOWERS_CEILING:
|
2020-11-02 21:26:32 +00:00
|
|
|
actor->SetOwner(nullptr);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_25_PISTON: // Pistons
|
2022-09-12 21:35:48 +00:00
|
|
|
actor->temp_pos.Z = sectp->ceilingz;
|
|
|
|
actor->temp_data[4] = 1;
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setceilingz(actor->spr.pos.Z);
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_Ceilingz);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_35:
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setceilingz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_27_DEMO_CAM:
|
2020-05-15 20:59:13 +00:00
|
|
|
if (ud.recstat == 1)
|
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.xrepeat = actor->spr.yrepeat = 64;
|
|
|
|
actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_47_LIGHT_SWITCH:
|
|
|
|
case SE_48_LIGHT_SWITCH:
|
2020-05-15 20:59:13 +00:00
|
|
|
if (!isRRRA()) break;
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_12_LIGHT_SWITCH:
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[1] = sectp->floorshade;
|
|
|
|
actor->temp_data[2] = sectp->ceilingshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_13_EXPLOSIVE:
|
2020-11-02 21:26:32 +00:00
|
|
|
{
|
2022-09-11 20:28:05 +00:00
|
|
|
actor->temp_pos.Y = sectp->ceilingz;
|
|
|
|
actor->temp_pos.Z = sectp->floorz;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-11 20:28:05 +00:00
|
|
|
bool ceiling = (abs(sectp->ceilingz - actor->spr.pos.Z) < abs(sectp->floorz - actor->spr.pos.Z));
|
2020-11-02 21:39:41 +00:00
|
|
|
actor->spriteextra = ceiling;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-11 20:28:05 +00:00
|
|
|
if (actor->spr.intangle == 512)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 21:26:32 +00:00
|
|
|
if (ceiling)
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setceilingz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
else
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setfloorz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
2021-12-27 21:32:26 +00:00
|
|
|
{
|
2022-02-07 07:59:20 +00:00
|
|
|
sectp->setceilingz(actor->spr.pos.Z);
|
|
|
|
sectp->setfloorz(actor->spr.pos.Z);
|
2021-12-27 21:32:26 +00:00
|
|
|
}
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-18 12:14:56 +00:00
|
|
|
if (sectp->ceilingstat & CSTAT_SECTOR_SKY)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-18 12:23:08 +00:00
|
|
|
sectp->ceilingstat ^= CSTAT_SECTOR_SKY;
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = 1;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-11 20:28:05 +00:00
|
|
|
if (!ceiling && actor->spr.intangle == 512)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-18 12:23:08 +00:00
|
|
|
sectp->ceilingstat ^= CSTAT_SECTOR_SKY;
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-11-06 23:11:17 +00:00
|
|
|
sectp->ceilingshade =
|
|
|
|
sectp->floorshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-11 20:28:05 +00:00
|
|
|
if (actor->spr.intangle == 512)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-17 23:42:52 +00:00
|
|
|
for (auto& wl : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-21 07:42:36 +00:00
|
|
|
if (wl.twoSided())
|
2021-11-17 23:42:52 +00:00
|
|
|
{
|
|
|
|
auto nsec = wl.nextSector();
|
2021-12-18 12:14:56 +00:00
|
|
|
if (!(nsec->ceilingstat & CSTAT_SECTOR_SKY))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-17 23:42:52 +00:00
|
|
|
sectp->ceilingpicnum = nsec->ceilingpicnum;
|
|
|
|
sectp->ceilingshade = nsec->ceilingshade;
|
|
|
|
break; //Leave early
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2021-11-17 23:42:52 +00:00
|
|
|
}
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2020-11-02 21:26:32 +00:00
|
|
|
}
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_17_WARP_ELEVATOR:
|
2020-11-02 21:20:41 +00:00
|
|
|
{
|
2022-09-14 19:04:07 +00:00
|
|
|
actor->temp_pos.X = sectp->floorz; //Stopping loc
|
|
|
|
actor->temp_pos.Y = nextsectorneighborzptr(sectp, sectp->floorz, Find_CeilingUp | Find_Safe)->ceilingz;
|
|
|
|
actor->temp_pos.Z = nextsectorneighborzptr(sectp, sectp->ceilingz, Find_FloorDown | Find_Safe)->floorz;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (numplayers < 2)
|
|
|
|
{
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_Floorz);
|
|
|
|
StartInterpolation(sectp, Interp_Sect_Ceilingz);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2020-11-02 21:20:41 +00:00
|
|
|
}
|
2020-11-26 15:03:40 +00:00
|
|
|
case 156:
|
2021-04-07 16:12:25 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-26 15:03:40 +00:00
|
|
|
case 34:
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_FloorPanX);
|
2020-11-26 15:03:40 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_24_CONVEYOR:
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_FloorPanX);
|
2022-09-01 16:15:52 +00:00
|
|
|
actor->spr.yint <<= 1;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_36_PROJ_SHOOTER:
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_20_STRETCH_BRIDGE:
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-15 22:32:41 +00:00
|
|
|
walltype* closewall = nullptr;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
//find the two most clostest wall x's and y's
|
2022-09-11 22:56:23 +00:00
|
|
|
double maxdist = 0x7fffffff;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-15 22:32:41 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 22:56:23 +00:00
|
|
|
double dist = (actor->spr.pos.XY() - wal.pos).LengthSquared();
|
|
|
|
if (dist < maxdist)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 22:56:23 +00:00
|
|
|
maxdist = dist;
|
2021-11-15 22:32:41 +00:00
|
|
|
closewall = &wal;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:32:41 +00:00
|
|
|
actor->temp_walls[0] = closewall;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2022-09-11 22:56:23 +00:00
|
|
|
maxdist = 0x7fffffff;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-15 22:32:41 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 22:56:23 +00:00
|
|
|
double dist = (actor->spr.pos.XY() - wal.pos).LengthSquared();
|
|
|
|
if (dist < maxdist && &wal != actor->temp_walls[0])
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 22:56:23 +00:00
|
|
|
maxdist = dist;
|
2021-11-15 22:32:41 +00:00
|
|
|
closewall = &wal;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:32:41 +00:00
|
|
|
actor->temp_walls[1] = closewall;
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_FloorPanX);
|
|
|
|
StartInterpolation(sectp, Interp_Sect_FloorPanY);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT:
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = sectp->floorshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
sectp->floorshade = actor->spr.shade;
|
|
|
|
sectp->ceilingshade = actor->spr.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-06 23:11:17 +00:00
|
|
|
actor->palvals = (sectp->ceilingpal << 8) | sectp->floorpal;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
//fix all the walls;
|
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-17 22:31:08 +00:00
|
|
|
if (!(wal.hitag & 1))
|
2021-12-21 20:57:23 +00:00
|
|
|
wal.shade = actor->spr.shade;
|
2021-12-18 14:11:21 +00:00
|
|
|
if ((wal.cstat & CSTAT_WALL_BOTTOM_SWAP) && wal.twoSided())
|
2021-12-21 20:57:23 +00:00
|
|
|
wal.nextWall()->shade = actor->spr.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_31_FLOOR_RISE_FALL:
|
2022-09-09 17:30:18 +00:00
|
|
|
actor->temp_pos.Z = actor->spr.yint * zmaptoworld;
|
|
|
|
actor->temp_pos.Y = sectp->floorz;
|
2021-12-23 15:24:11 +00:00
|
|
|
// actor->temp_data[2] = actor->spr.hitag;
|
2022-09-09 17:30:18 +00:00
|
|
|
if (actor->spr.intangle != 1536) sectp->setfloorz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
|
|
|
if (wal.hitag == 0) wal.hitag = 9999;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_Floorz);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_32_CEILING_RISE_FALL:
|
2022-09-12 19:52:47 +00:00
|
|
|
actor->temp_pos.Z = sectp->ceilingz;
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[2] = actor->spr.hitag;
|
2022-09-12 19:52:47 +00:00
|
|
|
if (actor->spr.intangle != 1536) sectp->setceilingz(actor->spr.pos.Z);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
|
|
|
if (wal.hitag == 0) wal.hitag = 9999;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-18 15:56:40 +00:00
|
|
|
StartInterpolation(sectp, Interp_Sect_Ceilingz);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_4_RANDOM_LIGHTS: //Flashing lights
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[2] = sectp->floorshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-06 23:11:17 +00:00
|
|
|
actor->palvals = (sectp->ceilingpal << 8) | sectp->floorpal;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2021-12-23 15:24:11 +00:00
|
|
|
if (wal.shade > actor->temp_data[3])
|
|
|
|
actor->temp_data[3] = wal.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_9_DOWN_OPEN_DOOR_LIGHTS:
|
2021-11-06 23:11:17 +00:00
|
|
|
if (sectp->lotag &&
|
2022-09-02 22:00:28 +00:00
|
|
|
abs(sectp->ceilingz - actor->spr.pos.Z) > 4)
|
2021-11-06 23:11:17 +00:00
|
|
|
sectp->lotag |= 32768; //If its open
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_8_UP_OPEN_DOOR_LIGHTS:
|
2020-05-15 20:59:13 +00:00
|
|
|
//First, get the ceiling-floor shade
|
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[0] = sectp->floorshade;
|
|
|
|
actor->temp_data[1] = sectp->ceilingshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2021-12-23 15:24:11 +00:00
|
|
|
if (wal.shade > actor->temp_data[2])
|
|
|
|
actor->temp_data[2] = wal.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = 1; //Take Out;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 88:
|
|
|
|
//First, get the ceiling-floor shade
|
|
|
|
if (!isRR()) break;
|
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[0] = sectp->floorshade;
|
|
|
|
actor->temp_data[1] = sectp->ceilingshade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-17 22:31:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2021-12-23 15:24:11 +00:00
|
|
|
if (wal.shade > actor->temp_data[2])
|
|
|
|
actor->temp_data[2] = wal.shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = 1; //Take Out;
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_11_SWINGING_DOOR://Pivitor rotater
|
2022-09-14 20:57:42 +00:00
|
|
|
if (actor->spr.intangle > 1024) actor->temp_data[3] = 2;
|
2021-12-23 15:24:11 +00:00
|
|
|
else actor->temp_data[3] = -2;
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_0_ROTATING_SECTOR:
|
|
|
|
case SE_2_EARTHQUAKE://Earthquakemakers
|
|
|
|
case SE_5_BOSS://Boss Creature
|
|
|
|
case SE_6_SUBWAY://Subway
|
|
|
|
case SE_14_SUBWAY_CAR://Caboos
|
|
|
|
case SE_15_SLIDING_DOOR://Subwaytype sliding door
|
|
|
|
case SE_16_REACTOR://That rotating blocker reactor thing
|
|
|
|
case SE_26://ESCELATOR
|
|
|
|
case SE_30_TWO_WAY_TRAIN://No rotational subways
|
2022-01-07 15:36:02 +00:00
|
|
|
{
|
2022-09-11 18:18:33 +00:00
|
|
|
if (actor->spr.lotag == SE_0_ROTATING_SECTOR)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 18:18:33 +00:00
|
|
|
if (sectp->lotag == 30)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-09 16:24:22 +00:00
|
|
|
if (actor->spr.pal) actor->set_const_clipdist(1);
|
|
|
|
else actor->set_const_clipdist(0);
|
2022-09-11 18:18:33 +00:00
|
|
|
actor->temp_pos.Z = sectp->floorz;
|
2021-12-05 16:35:23 +00:00
|
|
|
sectp->hitagactor = actor;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
bool found = false;
|
2022-01-07 15:36:02 +00:00
|
|
|
if (actors) for (auto act2 : *actors)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
if (act2->spr.statnum < MAXSTATUS)
|
|
|
|
if (act2->spr.picnum == SECTOREFFECTOR &&
|
|
|
|
act2->spr.lotag == SE_1_PIVOT &&
|
|
|
|
act2->spr.hitag == actor->spr.hitag)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-03 16:18:43 +00:00
|
|
|
if (actor->spr.angle == DAngle90)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-08-29 17:27:52 +00:00
|
|
|
actor->spr.pos.XY() = act2->spr.pos.XY();
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2020-11-02 21:20:41 +00:00
|
|
|
found = true;
|
|
|
|
actor->SetOwner(act2);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-11-02 21:20:41 +00:00
|
|
|
if (!found)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.picnum = 0;
|
|
|
|
actor->spr.cstat2 = CSTAT2_SPRITE_NOFIND;
|
|
|
|
actor->spr.cstat = CSTAT_SPRITE_INVISIBLE;
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_REMOVED);
|
2022-09-11 16:41:52 +00:00
|
|
|
Printf("Found lonely Sector Effector (lotag 0) at (%d,%d)\n", int(actor->spr.pos.X), int(actor->spr.pos.Y));
|
2021-05-08 13:41:49 +00:00
|
|
|
return;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-11 14:41:17 +00:00
|
|
|
actor->temp_data[1] = mspos.Size();
|
2021-11-17 22:35:20 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-09-11 14:41:17 +00:00
|
|
|
mspos.Push(wal.pos - actor->spr.pos);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.lotag == SE_30_TWO_WAY_TRAIN || actor->spr.lotag == SE_6_SUBWAY || actor->spr.lotag == SE_14_SUBWAY_CAR || actor->spr.lotag == SE_5_BOSS)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
|
2021-11-06 23:11:17 +00:00
|
|
|
if (sectp->hitag == -1)
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.extra = 0;
|
|
|
|
else actor->spr.extra = 1;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-05 16:35:23 +00:00
|
|
|
sectp->hitagactor = actor;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-11-18 19:51:09 +00:00
|
|
|
sectortype* s = nullptr;
|
2021-11-17 22:35:20 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-21 07:42:36 +00:00
|
|
|
if (wal.twoSided() &&
|
2021-11-17 22:35:20 +00:00
|
|
|
wal.nextSector()->hitag == 0 &&
|
|
|
|
(wal.nextSector()->lotag < 3 || (isRRRA() && wal.nextSector()->lotag == 160)))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2021-11-18 19:51:09 +00:00
|
|
|
s = wal.nextSector();
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 19:51:09 +00:00
|
|
|
if (s == nullptr)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-08-23 20:52:22 +00:00
|
|
|
I_Error("Subway found no zero'd sectors with locators\nat (%d,%d).\n", int(actor->spr.pos.X), int(actor->spr.pos.Y));
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-02 21:26:32 +00:00
|
|
|
actor->SetOwner(nullptr);
|
2022-01-13 21:34:43 +00:00
|
|
|
actor->temp_data[0] = sectnum(s);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.lotag != SE_30_TWO_WAY_TRAIN)
|
2021-12-23 15:24:11 +00:00
|
|
|
actor->temp_data[3] = actor->spr.hitag;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
else if (actor->spr.lotag == SE_16_REACTOR)
|
2022-09-14 19:08:27 +00:00
|
|
|
actor->temp_pos.Z = sectp->ceilingz;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
else if (actor->spr.lotag == SE_26)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-08-29 21:13:54 +00:00
|
|
|
actor->temp_pos.XY() = actor->spr.pos.XY();
|
2021-12-21 20:57:23 +00:00
|
|
|
if (actor->spr.shade == sectp->floorshade) //UP
|
2022-09-03 08:05:20 +00:00
|
|
|
actor->vel.Z = -1;
|
2020-05-15 20:59:13 +00:00
|
|
|
else
|
2022-09-03 08:04:16 +00:00
|
|
|
actor->vel.Z = 1;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
actor->spr.shade = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2021-12-21 20:57:23 +00:00
|
|
|
else if (actor->spr.lotag == SE_2_EARTHQUAKE)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2022-01-09 12:38:10 +00:00
|
|
|
actor->temp_data[5] = actor->sector()->getfloorslope();
|
2021-12-30 15:51:56 +00:00
|
|
|
actor->sector()->setfloorslope(0);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2022-01-07 15:36:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SE_49_POINT_LIGHT:
|
|
|
|
case SE_50_SPOT_LIGHT:
|
|
|
|
{
|
|
|
|
DukeSectIterator it(actor->sector());
|
|
|
|
while (auto itActor = it.Next())
|
|
|
|
{
|
|
|
|
if (itActor->spr.picnum == ACTIVATOR || itActor->spr.picnum == ACTIVATORLOCKED)
|
2022-01-23 23:10:25 +00:00
|
|
|
actor->flags2 |= SFLAG2_USEACTIVATOR;
|
2022-01-07 15:36:02 +00:00
|
|
|
}
|
|
|
|
ChangeActorStat(actor, STAT_LIGHT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 20:57:23 +00:00
|
|
|
switch (actor->spr.lotag)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_6_SUBWAY:
|
|
|
|
case SE_14_SUBWAY_CAR:
|
2020-11-02 21:20:41 +00:00
|
|
|
{
|
2021-11-18 20:00:54 +00:00
|
|
|
int j = callsound(sectp, actor);
|
2020-05-15 20:59:13 +00:00
|
|
|
if (j == -1)
|
|
|
|
{
|
|
|
|
if (!isRR()) j = SUBWAY; // Duke
|
2021-12-30 15:51:56 +00:00
|
|
|
else if (actor->sector()->floorpal == 7) j = 456;
|
2020-05-15 20:59:13 +00:00
|
|
|
else j = 75;
|
|
|
|
}
|
2022-02-06 21:59:30 +00:00
|
|
|
actor->tempsound = j;
|
2020-11-02 21:20:41 +00:00
|
|
|
}
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_30_TWO_WAY_TRAIN:
|
2020-05-15 20:59:13 +00:00
|
|
|
if (numplayers > 1) break;
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_0_ROTATING_SECTOR:
|
|
|
|
case SE_1_PIVOT:
|
|
|
|
case SE_5_BOSS:
|
|
|
|
case SE_11_SWINGING_DOOR:
|
|
|
|
case SE_15_SLIDING_DOOR:
|
|
|
|
case SE_16_REACTOR:
|
|
|
|
case SE_26:
|
2021-12-30 15:51:56 +00:00
|
|
|
setsectinterpolate(actor->sector());
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
2020-11-27 19:06:38 +00:00
|
|
|
|
|
|
|
case SE_29_WAVES:
|
2021-12-30 15:51:56 +00:00
|
|
|
StartInterpolation(actor->sector(), Interp_Sect_Floorheinum);
|
|
|
|
StartInterpolation(actor->sector(), Interp_Sect_Floorz);
|
2020-11-27 19:06:38 +00:00
|
|
|
break;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 17:19:45 +00:00
|
|
|
if ((!isRR() && actor->spr.lotag >= 40 && actor->spr.lotag <= 45) ||
|
|
|
|
(isRRRA() && actor->spr.lotag >= 150 && actor->spr.lotag <= 155))
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_RAROR);
|
2020-05-15 20:59:13 +00:00
|
|
|
else
|
2021-11-26 20:52:01 +00:00
|
|
|
ChangeActorStat(actor, STAT_EFFECTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-16 10:47:01 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-17 23:38:20 +00:00
|
|
|
void lotsofglass(DDukeActor *actor, walltype* wal, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-14 18:53:34 +00:00
|
|
|
int j, z;
|
2021-11-17 23:47:46 +00:00
|
|
|
sectortype* sect = nullptr;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
2021-11-17 23:38:20 +00:00
|
|
|
if (wal == nullptr)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
|
|
|
for (j = n - 1; j >= 0; j--)
|
|
|
|
{
|
2022-09-14 18:53:34 +00:00
|
|
|
auto a = actor->spr.angle - DAngle45 + DAngle180 + randomAngle(90);
|
|
|
|
auto vel = krandf(4) + 2;
|
|
|
|
auto zvel = 4 - krandf(4);
|
|
|
|
|
|
|
|
CreateActor(actor->sector(), actor->spr.pos, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, vel, zvel, actor, 5);
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2022-09-13 18:25:33 +00:00
|
|
|
|
2020-05-16 10:47:01 +00:00
|
|
|
|
2022-09-13 18:25:33 +00:00
|
|
|
auto pos = wal->pos;
|
|
|
|
auto delta = wal->delta() / (n + 1);
|
2020-05-16 10:47:01 +00:00
|
|
|
|
2022-09-13 18:25:33 +00:00
|
|
|
pos.X -= Sgn(delta.Y) * maptoworld;
|
|
|
|
pos.Y += Sgn(delta.X) * maptoworld;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
for (j = n; j > 0; j--)
|
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
pos += delta;
|
|
|
|
sect = wal->sectorp();
|
|
|
|
updatesector(DVector3(pos, sect->floorz), §);
|
2021-11-17 23:47:46 +00:00
|
|
|
if (sect)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
z = sect->floorz - krandf(abs(sect->ceilingz - sect->floorz));
|
|
|
|
if (fabs(z) > 32)
|
|
|
|
z = actor->spr.pos.Z - 32 + krandf(64);
|
2022-09-13 20:52:30 +00:00
|
|
|
DAngle angl = actor->spr.angle - DAngle180;
|
2022-09-14 18:53:34 +00:00
|
|
|
auto vel = krandf(4) + 2;
|
|
|
|
auto zvel = 4 - krandf(4);
|
|
|
|
|
|
|
|
CreateActor(actor->sector(), DVector3(pos, z), TILE_GLASSPIECES + (j % 3), -32, 36, 36, angl, vel, zvel, actor, 5);
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-10-25 05:40:05 +00:00
|
|
|
void spriteglass(DDukeActor* actor, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2020-10-25 05:40:05 +00:00
|
|
|
for (int j = n; j > 0; j--)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-14 18:53:34 +00:00
|
|
|
auto a = randomAngle();
|
|
|
|
auto vel = krandf(4) + 2;
|
|
|
|
auto zvel = -2 - krandf(8);
|
|
|
|
|
|
|
|
auto k = CreateActor(actor->sector(), actor->spr.pos.plusZ(-(krand() & 16)), TILE_GLASSPIECES + (j % 3), krand() & 15, 36, 36, a, vel, zvel, actor, 5);
|
2021-12-21 20:57:23 +00:00
|
|
|
if (k) k->spr.pal = actor->spr.pal;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 16:55:08 +00:00
|
|
|
void ceilingglass(DDukeActor* actor, sectortype* sectp, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2021-11-18 16:55:08 +00:00
|
|
|
for (auto& wal : wallsofsector(sectp))
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
auto pos = wal.pos;
|
|
|
|
auto delta = wal.delta() / (n + 1);
|
2020-05-16 10:47:01 +00:00
|
|
|
|
2022-09-13 18:25:33 +00:00
|
|
|
for (int j = n; j > 0; j--)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
pos += delta;
|
|
|
|
DAngle a = randomAngle();
|
2022-09-14 18:53:34 +00:00
|
|
|
auto vel = krandf(2);
|
|
|
|
|
2022-09-13 18:25:33 +00:00
|
|
|
double z = sectp->ceilingz + krandf(16);
|
2022-09-14 18:53:34 +00:00
|
|
|
CreateActor(sectp, DVector3(pos, z), TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, vel, 0, actor, 5);
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-17 23:38:20 +00:00
|
|
|
void lotsofcolourglass(DDukeActor* actor, walltype* wal, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
int j;
|
2021-11-17 23:47:46 +00:00
|
|
|
sectortype* sect = nullptr;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
2021-11-17 23:38:20 +00:00
|
|
|
if (wal == nullptr)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
|
|
|
for (j = n - 1; j >= 0; j--)
|
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
DAngle a = randomAngle();
|
2022-09-14 18:53:34 +00:00
|
|
|
auto vel = krandf(4) + 2;
|
|
|
|
auto zvel = 4 - krandf(4);
|
|
|
|
|
|
|
|
auto k = CreateActor(actor->sector(), actor->spr.pos.plusZ(-(krand() & 63)), TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, vel, zvel, actor, 5);
|
2021-12-21 17:19:45 +00:00
|
|
|
if (k) k->spr.pal = krand() & 15;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2022-09-13 18:25:33 +00:00
|
|
|
auto pos = wal->pos;
|
|
|
|
auto delta = wal->delta() / (n + 1);
|
2020-05-16 10:47:01 +00:00
|
|
|
|
|
|
|
for (j = n; j > 0; j--)
|
|
|
|
{
|
2022-09-13 18:25:33 +00:00
|
|
|
pos += delta;
|
|
|
|
|
|
|
|
sect = wal->sectorp();
|
|
|
|
updatesector(DVector3(pos, sect->floorz), §);
|
|
|
|
if (!sect) continue;
|
|
|
|
double z = sect->floorz - krandf(abs(sect->ceilingz - sect->floorz));
|
|
|
|
if (abs(z) > 32)
|
|
|
|
z = actor->spr.pos.Z - 32 + krandf(64);
|
|
|
|
|
|
|
|
DAngle a = actor->spr.angle - DAngle180;
|
2022-09-14 18:53:34 +00:00
|
|
|
auto vel = krandf(4) + 2;
|
|
|
|
auto zvel = - krandf(8);
|
|
|
|
|
|
|
|
auto k = CreateActor(actor->sector(), DVector3(pos, z), TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, vel, zvel, actor, 5);
|
2021-12-21 17:19:45 +00:00
|
|
|
if (k) k->spr.pal = krand() & 7;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-15 20:59:13 +00:00
|
|
|
END_DUKE_NS
|