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

1214 lines
31 KiB
C++
Raw Normal View History

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"
#include "interpolate.h"
2020-05-15 20:59:13 +00:00
BEGIN_DUKE_NS
2020-05-15 21:46:18 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-18 18:06:08 +00:00
DDukeActor* EGS(sectortype* whatsectp, int s_x, int s_y, int s_z, int s_pn, int8_t s_s, int8_t s_xr, int8_t s_yr, int s_a, int s_ve, int s_zv, DDukeActor* s_ow, int8_t s_ss)
2020-05-15 21:46:18 +00:00
{
// sector pointer must be strictly validated here or the engine will crash.
if (whatsectp == nullptr || !validSectorIndex(sectnum(whatsectp))) return nullptr;
// spawning out of range sprites will also crash.
if (s_pn < 0 || s_pn >= MAXTILES) return nullptr;
auto act = static_cast<DDukeActor*>(::InsertActor(RUNTIME_CLASS(DDukeActor), whatsectp, s_ss));
2020-05-15 21:46:18 +00:00
if (act == nullptr) return nullptr;
SetupGameVarsForActor(act);
2020-05-15 21:46:18 +00:00
2022-01-30 23:02:46 +00:00
act->set_int_pos({ s_x, s_y, s_z });
2021-12-21 20:57:23 +00:00
act->spr.cstat = 0;
act->spr.picnum = s_pn;
act->spr.shade = s_s;
act->spr.xrepeat = s_xr;
act->spr.yrepeat = s_yr;
act->spr.pal = 0;
act->spr.ang = s_a;
act->spr.xvel = s_ve;
act->spr.zvel = s_zv;
act->spr.xoffset = 0;
act->spr.yoffset = 0;
act->spr.yvel = 0;
act->spr.clipdist = 0;
act->spr.pal = 0;
act->spr.lotag = 0;
act->backuploc();
2020-05-15 21:46:18 +00:00
act->ovel.X = 0;
act->ovel.Y = 0;
2020-10-24 05:34:54 +00:00
act->timetosleep = 0;
2021-11-18 19:55:22 +00:00
act->actorstayput = nullptr;
act->hitextra = -1;
2020-10-24 05:34:54 +00:00
act->cgg = 0;
act->movflag = 0;
act->tempang = 0;
act->dispicnum = 0;
2020-11-02 20:21:52 +00:00
act->SetHitOwner(s_ow);
act->SetOwner(s_ow);
if (s_ow)
{
act->attackertype = s_ow->spr.picnum;
2020-11-02 20:21:52 +00:00
act->floorz = s_ow->floorz;
act->ceilingz = s_ow->ceilingz;
}
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));
if (gs.actorinfo[s_pn].scriptaddress)
2020-05-15 21:46:18 +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;
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
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool initspriteforspawn(DDukeActor* act)
2020-05-15 20:59:13 +00:00
{
SetupGameVarsForActor(act);
act->attackertype = act->spr.picnum;
act->timetosleep = 0;
act->hitextra = -1;
2020-10-24 05:34:54 +00:00
act->backuppos();
2020-10-24 05:34:54 +00:00
act->SetOwner(act);
act->SetHitOwner(act);
act->cgg = 0;
act->movflag = 0;
act->tempang = 0;
act->dispicnum = 0;
act->floorz = act->sector()->__int_floorz;
act->ceilingz = act->sector()->__int_ceilingz;
2020-10-24 05:34:54 +00:00
act->ovel.X = 0;
act->ovel.Y = 0;
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;
act->temp_actor = nullptr;
2020-05-15 20:59:13 +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)
{
if ((ud.multimode < 2) || (ud.multimode > 1 && ud.coop == 1))
2020-05-15 20:59:13 +00:00
{
act->spr.xrepeat = act->spr.yrepeat = 0;
act->spr.cstat = 0;
act->spr.lotag = act->spr.hitag = 0;
return false;
}
}
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
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-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
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];
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-12-23 15:24:11 +00:00
else act->temp_data[1] = act->temp_data[4] = 0;
return true;
}
2020-05-15 20:59:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
DDukeActor* spawn(DDukeActor* actj, int pn)
{
if (actj)
{
auto spawned = EGS(actj->sector(), actj->int_pos().X, actj->int_pos().Y, actj->int_pos().Z, pn, 0, 0, 0, 0, 0, 0, actj, 0);
if (spawned)
2020-05-15 20:59:13 +00:00
{
spawned->attackertype = actj->spr.picnum;
return fi.spawninit(actj, spawned, nullptr);
2020-05-15 20:59:13 +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;
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
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;
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
if (actorflag(act, SFLAG_BADGUYSTAYPUT))
act->actorstayput = act->sector();
2020-05-15 20:59:13 +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++;
2021-12-21 20:57:23 +00:00
act->spr.clipdist = 80;
2020-11-02 17:58:23 +00:00
if (actj)
2020-05-15 20:59:13 +00:00
{
if (actj->spr.picnum == RESPAWN)
2021-12-21 20:57:23 +00:00
act->tempang = act->spr.pal = actj->spr.pal;
ChangeActorStat(act, STAT_ACTOR);
2020-05-15 20:59:13 +00:00
}
else ChangeActorStat(act, STAT_ZOMBIEACTOR);
2020-05-15 20:59:13 +00:00
}
else
{
2021-12-21 20:57:23 +00:00
act->spr.clipdist = 40;
2020-11-02 17:58:23 +00:00
act->SetOwner(act);
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)
2021-12-21 20:57:23 +00:00
act->spr.ang = actj->spr.ang;
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;
act->set_int_z(actj->sector()->__int_floorz - (isRR() ? PHEIGHT_RR : PHEIGHT_DUKE));
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))
act->add_int_z(-(32 << 8));
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;
act->spr.ang = actj->spr.ang;
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:23 +00:00
act->spr.xvel = 128;
ChangeActorStat(act, STAT_MISC);
ssp(act, CLIPMASK0);
SetActor(act, act->int_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
{
auto s1 = act->sector();
2020-05-15 20:59:13 +00:00
updatesector(act->int_pos().X + 108, act->int_pos().Y + 108, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X - 108, act->int_pos().Y - 108, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X + 108, act->int_pos().Y - 108, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X - 108, act->int_pos().Y + 108, &s1);
if (s1 && s1->__int_floorz != act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
2021-12-21 20:57:23 +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-21 20:57:23 +00:00
else { act->spr.xrepeat = act->spr.yrepeat = 0; ChangeActorStat(act, STAT_MISC); return true; }
2020-05-15 20:59:13 +00:00
}
2021-12-21 20:57:23 +00:00
else { act->spr.xrepeat = act->spr.yrepeat = 0; ChangeActorStat(act, STAT_MISC); return true; }
2020-05-15 20:59:13 +00:00
}
2021-12-21 20:57:23 +00:00
else { act->spr.xrepeat = act->spr.yrepeat = 0; ChangeActorStat(act, STAT_MISC); return true; }
2020-05-15 20:59:13 +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
{
auto sect = act->sector();
2020-11-02 20:21:52 +00:00
if (actj)
2020-05-15 20:59:13 +00:00
{
auto s1 = act->sector();
2020-05-15 20:59:13 +00:00
updatesector(act->int_pos().X + 84, act->int_pos().Y + 84, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X - 84, act->int_pos().Y - 84, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X + 84, act->int_pos().Y - 84, &s1);
if (s1 && s1->__int_floorz == act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
updatesector(act->int_pos().X - 84, act->int_pos().Y + 84, &s1);
if (s1 && s1->__int_floorz != act->sector()->__int_floorz)
2020-05-15 20:59:13 +00:00
{
2021-12-21 20:57:23 +00:00
act->spr.xrepeat = act->spr.yrepeat = 0; ChangeActorStat(act, STAT_MISC); return;
2020-05-15 20:59:13 +00:00
}
}
2021-12-21 20:57:23 +00:00
else { act->spr.xrepeat = act->spr.yrepeat = 0; return; }
2020-05-15 20:59:13 +00:00
}
2021-12-21 20:57:23 +00:00
else { act->spr.xrepeat = act->spr.yrepeat = 0; return; }
2020-05-15 20:59:13 +00:00
}
2021-12-21 20:57:23 +00:00
else { 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;
if ((ps[actj->spr.yvel].footprintcount & 1)) act->spr.cstat |= CSTAT_SPRITE_XFLIP;
act->spr.ang = actj->spr.ang;
2020-05-15 20:59:13 +00:00
}
act->set_int_z(sect->__int_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
{
if (actj)
2020-05-15 20:59:13 +00:00
{
int snum, a;
2020-05-15 20:59:13 +00:00
if (actj->isPlayer())
2020-05-15 20:59:13 +00:00
{
2021-12-21 20:57:23 +00:00
snum = actj->spr.yvel;
a = ps[snum].angle.ang.asbuild() - (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-01-30 23:02:46 +00:00
act->set_int_z((3 << 8) + ps[snum].pyoff + ps[snum].pos.Z - (ps[snum].horizon.sum().asq16() >> 12) + (!isshell ? (3 << 8) : 0));
2021-12-21 20:57:23 +00:00
act->spr.zvel = -(krand() & 255);
2020-05-15 20:59:13 +00:00
}
else
{
2021-12-21 20:57:23 +00:00
a = act->spr.ang;
act->set_int_z(actj->int_pos().Z - gs.playerheight + (3 << 8));
2020-05-15 20:59:13 +00:00
}
act->set_int_xy(actj->int_pos().X + bcos(a, -7), actj->int_pos().Y + bsin(a, -7));
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
2021-12-21 20:57:23 +00:00
act->spr.ang = a + 512;
act->spr.xvel = 30;
2020-05-15 20:59:13 +00:00
}
else
{
2021-12-21 20:57:23 +00:00
act->spr.ang = a - 512;
act->spr.xvel = 20;
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
{
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;
act->set_int_z(sect->__int_ceilingz + (48 << 8));
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]];
apt.pos = act->int_pos();
apt.poleactor = nullptr;
2020-05-15 20:59:13 +00:00
DukeStatIterator it(STAT_DEFAULT);
while (auto actk = it.Next())
2020-05-15 20:59:13 +00:00
{
if (actk->spr.picnum == CRANEPOLE && act->spr.hitag == actk->spr.hitag)
2020-05-15 20:59:13 +00:00
{
apt.poleactor = actk;
2020-05-15 20:59:13 +00:00
act->temp_sect = actk->sector();
2020-05-15 20:59:13 +00:00
actk->spr.xrepeat = 48;
actk->spr.yrepeat = 128;
2020-05-15 20:59:13 +00:00
apt.pole.X = actk->int_pos().X;
apt.pole.Y = actk->int_pos().Y;
2020-05-15 20:59:13 +00:00
actk->set_int_pos(act->int_pos());
actk->spr.shade = act->spr.shade;
2020-05-15 20:59:13 +00:00
SetActor(actk, actk->int_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
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void initwaterdrip(DDukeActor* actj, DDukeActor* actor)
2020-05-15 20:59:13 +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;
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-01-30 23:02:46 +00:00
actor->add_int_z(-(18 << 8));
2020-05-15 20:59:13 +00:00
}
2022-01-30 23:02:46 +00:00
else actor->add_int_z(-(13 << 8));
actor->spr.ang = getangle(ps[connecthead].pos.X - actor->int_pos().X, ps[connecthead].pos.Y - actor->int_pos().Y);
2021-12-21 20:57:23 +00:00
actor->spr.xvel = 48 - (krand() & 31);
ssp(actor, CLIPMASK0);
2020-05-15 20:59:13 +00:00
}
else if (!actj)
2020-05-15 20:59:13 +00:00
{
2022-01-30 23:02:46 +00:00
actor->add_int_z(4 << 8);
actor->temp_data[0] = actor->int_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;
ChangeActorStat(actor, STAT_STANDABLE);
2020-05-15 20:59:13 +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;
ChangeActorStat(actor, STAT_MISC);
2020-05-15 20:59:13 +00:00
return true;
}
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++;
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;
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;
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
ChangeActorStat(actor, 2);
2020-05-15 20:59:13 +00:00
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void spawneffector(DDukeActor* actor, TArray<DDukeActor*>* actors)
2020-05-15 20:59:13 +00:00
{
auto sectp = actor->sector();
int d, clostest = 0;
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:23 +00:00
actor->spr.yvel = sectp->extra;
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
{
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;
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
{
for(auto act2 : *actors)
{
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;
}
}
2020-11-02 21:20:41 +00:00
}
else actor->SetOwner(actor);
2020-05-15 20:59:13 +00:00
actor->temp_data[4] = sectp->__int_floorz == actor->int_pos().Z;
2021-12-21 20:57:23 +00:00
actor->spr.cstat = 0;
ChangeActorStat(actor, STAT_TRANSPORT);
2020-05-15 20:59:13 +00:00
return;
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;
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:23 +00:00
if (actor->spr.ang == 512)
2020-05-15 20:59:13 +00:00
{
actor->temp_data[1] = sectp->__int_ceilingz;
2021-12-21 20:57:23 +00:00
if (actor->spr.pal)
sectp->set_int_ceilingz(actor->int_pos().Z);
2020-05-15 20:59:13 +00:00
}
else
{
actor->temp_data[1] = sectp->__int_floorz;
2021-12-21 20:57:23 +00:00
if (actor->spr.pal)
sectp->set_int_floorz(actor->int_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;
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;
case SE_25_PISTON: // Pistons
2020-05-15 20:59:13 +00:00
if (!isRR())
{
actor->temp_data[3] = sectp->__int_ceilingz;
2021-12-23 15:24:11 +00:00
actor->temp_data[4] = 1;
2020-05-15 20:59:13 +00:00
}
else
actor->temp_data[4] = sectp->__int_ceilingz;
2020-05-15 20:59:13 +00:00
sectp->set_int_ceilingz(actor->int_pos().Z);
StartInterpolation(sectp, Interp_Sect_Ceilingz);
2020-05-15 20:59:13 +00:00
break;
case SE_35:
sectp->set_int_ceilingz(actor->int_pos().Z);
2020-05-15 20:59:13 +00:00
break;
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;
case SE_47_LIGHT_SWITCH:
case SE_48_LIGHT_SWITCH:
2020-05-15 20:59:13 +00:00
if (!isRRRA()) break;
[[fallthrough]];
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;
case SE_13_EXPLOSIVE:
2020-11-02 21:26:32 +00:00
{
actor->temp_data[0] = sectp->__int_ceilingz;
actor->temp_data[1] = sectp->__int_floorz;
2020-05-15 20:59:13 +00:00
bool ceiling = (abs(actor->temp_data[0] - actor->int_pos().Z) < abs(actor->temp_data[1] - actor->int_pos().Z));
actor->spriteextra = ceiling;
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:23 +00:00
if (actor->spr.ang == 512)
2020-05-15 20:59:13 +00:00
{
2020-11-02 21:26:32 +00:00
if (ceiling)
sectp->set_int_ceilingz(actor->int_pos().Z);
2020-05-15 20:59:13 +00:00
else
sectp->set_int_floorz(actor->int_pos().Z);
2020-05-15 20:59:13 +00:00
}
else
{
sectp->set_int_ceilingz(actor->int_pos().Z);
sectp->set_int_floorz(actor->int_pos().Z);
}
2020-05-15 20:59:13 +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
2021-12-21 20:57:23 +00:00
if (!ceiling && actor->spr.ang == 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
}
sectp->ceilingshade =
sectp->floorshade;
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:23 +00:00
if (actor->spr.ang == 512)
2020-05-15 20:59:13 +00:00
{
for (auto& wl : wallsofsector(sectp))
2020-05-15 20:59:13 +00:00
{
if (wl.twoSided())
{
auto nsec = wl.nextSector();
if (!(nsec->ceilingstat & CSTAT_SECTOR_SKY))
2020-05-15 20:59:13 +00:00
{
sectp->ceilingpicnum = nsec->ceilingpicnum;
sectp->ceilingshade = nsec->ceilingshade;
break; //Leave early
2020-05-15 20:59:13 +00:00
}
}
2020-05-15 20:59:13 +00:00
}
}
}
break;
2020-11-02 21:26:32 +00:00
}
case SE_17_WARP_ELEVATOR:
2020-11-02 21:20:41 +00:00
{
actor->temp_data[2] = sectp->__int_floorz; //Stopping loc
actor->temp_data[3] = nextsectorneighborzptr(sectp, sectp->__int_floorz, Find_CeilingUp | Find_Safe)->__int_ceilingz;
actor->temp_data[4] = nextsectorneighborzptr(sectp, sectp->__int_ceilingz, Find_FloorDown | Find_Safe)->__int_floorz;
2020-05-15 20:59:13 +00:00
if (numplayers < 2)
{
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
}
case 156:
break;
case 34:
StartInterpolation(sectp, Interp_Sect_FloorPanX);
break;
case SE_24_CONVEYOR:
StartInterpolation(sectp, Interp_Sect_FloorPanX);
2021-12-21 20:57:23 +00:00
actor->spr.yvel <<= 1;
case SE_36_PROJ_SHOOTER:
2020-05-15 20:59:13 +00:00
break;
case SE_20_STRETCH_BRIDGE:
2020-05-15 20:59:13 +00:00
{
int q;
walltype* closewall = nullptr;
2020-05-15 20:59:13 +00:00
//find the two most clostest wall x's and y's
q = 0x7fffffff;
for (auto& wal : wallsofsector(sectp))
2020-05-15 20:59:13 +00:00
{
d = FindDistance2D(actor->int_pos().vec2 - wal.wall_int_pos());
2020-05-15 20:59:13 +00:00
if (d < q)
{
q = d;
closewall = &wal;
2020-05-15 20:59:13 +00:00
}
}
actor->temp_walls[0] = closewall;
2020-05-15 20:59:13 +00:00
q = 0x7fffffff;
for (auto& wal : wallsofsector(sectp))
2020-05-15 20:59:13 +00:00
{
d = FindDistance2D(actor->int_pos().vec2 - wal.wall_int_pos());
if (d < q && &wal != actor->temp_walls[0])
2020-05-15 20:59:13 +00:00
{
q = d;
closewall = &wal;
2020-05-15 20:59:13 +00:00
}
}
actor->temp_walls[1] = closewall;
StartInterpolation(sectp, Interp_Sect_FloorPanX);
StartInterpolation(sectp, Interp_Sect_FloorPanY);
2020-05-15 20:59:13 +00:00
break;
}
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
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;
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;
case SE_31_FLOOR_RISE_FALL:
actor->temp_data[1] = sectp->__int_floorz;
2021-12-23 15:24:11 +00:00
// actor->temp_data[2] = actor->spr.hitag;
if (actor->spr.ang != 1536) sectp->set_int_floorz(actor->int_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
StartInterpolation(sectp, Interp_Sect_Floorz);
2020-05-15 20:59:13 +00:00
break;
case SE_32_CEILING_RISE_FALL:
actor->temp_data[1] = sectp->__int_ceilingz;
2021-12-23 15:24:11 +00:00
actor->temp_data[2] = actor->spr.hitag;
if (actor->spr.ang != 1536) sectp->set_int_ceilingz(actor->int_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
StartInterpolation(sectp, Interp_Sect_Ceilingz);
2020-05-15 20:59:13 +00:00
break;
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
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;
case SE_9_DOWN_OPEN_DOOR_LIGHTS:
if (sectp->lotag &&
labs(sectp->__int_ceilingz - actor->int_pos().Z) > 1024)
sectp->lotag |= 32768; //If its open
[[fallthrough]];
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;
case SE_11_SWINGING_DOOR://Pivitor rotater
2021-12-23 15:24:11 +00:00
if (actor->spr.ang > 1024) actor->temp_data[3] = 2;
else actor->temp_data[3] = -2;
[[fallthrough]];
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
{
2021-12-21 20:57:23 +00:00
if (actor->spr.lotag == 0)
2020-05-15 20:59:13 +00:00
{
if (sectp->lotag == 30)
2020-05-15 20:59:13 +00:00
{
2021-12-21 20:57:23 +00:00
if (actor->spr.pal) actor->spr.clipdist = 1;
else actor->spr.clipdist = 0;
actor->temp_data[3] = sectp->__int_floorz;
sectp->hitagactor = actor;
2020-05-15 20:59:13 +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
{
2021-12-21 20:57:23 +00:00
if (actor->spr.ang == 512)
2020-05-15 20:59:13 +00:00
{
actor->set_int_xy(act2->int_pos().X, act2->int_pos().Y);
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;
ChangeActorStat(actor, STAT_REMOVED);
Printf("Found lonely Sector Effector (lotag 0) at (%d,%d)\n", actor->int_pos().X, actor->int_pos().Y);
return;
2020-05-15 20:59:13 +00:00
}
}
2021-12-23 15:24:11 +00:00
actor->temp_data[1] = tempwallptr;
2021-11-17 22:35:20 +00:00
for (auto& wal : wallsofsector(sectp))
2020-05-15 20:59:13 +00:00
{
msx[tempwallptr] = wal.wall_int_pos().X - actor->int_pos().X;
msy[tempwallptr] = wal.wall_int_pos().Y - actor->int_pos().Y;
2020-05-15 20:59:13 +00:00
tempwallptr++;
if (tempwallptr > 2047)
{
I_Error("Too many moving sectors at (%d,%d).\n", wal.wall_int_pos().X, wal.wall_int_pos().Y);
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
{
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
sectp->hitagactor = actor;
2020-05-15 20:59:13 +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
{
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
{
s = wal.nextSector();
2020-05-15 20:59:13 +00:00
break;
}
}
if (s == nullptr)
2020-05-15 20:59:13 +00:00
{
I_Error("Subway found no zero'd sectors with locators\nat (%d,%d).\n", actor->int_pos().X, actor->int_pos().Y);
2020-05-15 20:59:13 +00:00
}
2020-11-02 21:26:32 +00:00
actor->SetOwner(nullptr);
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)
actor->temp_data[3] = sectp->__int_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
{
actor->temp_data[3] = actor->int_pos().X;
actor->temp_data[4] = actor->int_pos().Y;
2021-12-21 20:57:23 +00:00
if (actor->spr.shade == sectp->floorshade) //UP
actor->spr.zvel = -256;
2020-05-15 20:59:13 +00:00
else
2021-12-21 20:57:23 +00:00
actor->spr.zvel = 256;
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
{
actor->temp_data[5] = actor->sector()->getfloorslope();
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)
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
{
case SE_6_SUBWAY:
case SE_14_SUBWAY_CAR:
2020-11-02 21:20:41 +00:00
{
int j = callsound(sectp, actor);
2020-05-15 20:59:13 +00:00
if (j == -1)
{
if (!isRR()) j = SUBWAY; // Duke
else if (actor->sector()->floorpal == 7) j = 456;
2020-05-15 20:59:13 +00:00
else j = 75;
}
actor->ovel.X = j;
2020-11-02 21:20:41 +00:00
}
[[fallthrough]];
case SE_30_TWO_WAY_TRAIN:
2020-05-15 20:59:13 +00:00
if (numplayers > 1) break;
[[fallthrough]];
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:
setsectinterpolate(actor->sector());
2020-05-15 20:59:13 +00:00
break;
2020-11-27 19:06:38 +00:00
case SE_29_WAVES:
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
}
if ((!isRR() && actor->spr.lotag >= 40 && actor->spr.lotag <= 45) ||
(isRRRA() && actor->spr.lotag >= 150 && actor->spr.lotag <= 155))
ChangeActorStat(actor, STAT_RAROR);
2020-05-15 20:59:13 +00:00
else
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
{
2021-11-17 22:45:41 +00:00
int j, z, a;
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--)
{
2021-12-21 20:57:23 +00:00
a = actor->spr.ang - 256 + (krand() & 511) + 1024;
EGS(actor->sector(), actor->int_pos().X, actor->int_pos().Y, actor->int_pos().Z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 1023), actor, 5);
2020-05-16 10:47:01 +00:00
}
return;
}
int x1 = wal->wall_int_pos().X;
int y1 = wal->wall_int_pos().Y;
2021-11-17 22:45:41 +00:00
auto delta = wal->delta() / (n + 1);
2020-05-16 10:47:01 +00:00
2021-12-22 09:28:51 +00:00
x1 -= Sgn(delta.Y);
2021-12-22 09:26:51 +00:00
y1 += Sgn(delta.X);
2020-05-16 10:47:01 +00:00
for (j = n; j > 0; j--)
{
2021-12-22 09:26:51 +00:00
x1 += delta.X;
2021-12-22 09:28:51 +00:00
y1 += delta.Y;
2020-05-16 10:47:01 +00:00
updatesector(x1, y1, &sect);
2021-11-17 23:47:46 +00:00
if (sect)
2020-05-16 10:47:01 +00:00
{
z = sect->__int_floorz - (krand() & (abs(sect->__int_ceilingz - sect->__int_floorz)));
2020-05-16 10:47:01 +00:00
if (z < -(32 << 8) || z >(32 << 8))
z = actor->int_pos().Z - (32 << 8) + (krand() & ((64 << 8) - 1));
2021-12-21 20:57:23 +00:00
a = actor->spr.ang - 1024;
EGS(actor->sector(), x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), -(krand() & 1023), actor, 5);
2020-05-16 10:47:01 +00:00
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void spriteglass(DDukeActor* actor, int n)
2020-05-16 10:47:01 +00:00
{
for (int j = n; j > 0; j--)
2020-05-16 10:47:01 +00:00
{
int a = krand() & 2047;
int z = actor->int_pos().Z - ((krand() & 16) << 8);
auto k = EGS(actor->sector(), actor->int_pos().X, actor->int_pos().Y, z, TILE_GLASSPIECES + (j % 3), krand() & 15, 36, 36, a, 32 + (krand() & 63), -512 - (krand() & 2047), 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
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ceilingglass(DDukeActor* actor, sectortype* sectp, int n)
2020-05-16 10:47:01 +00:00
{
2021-11-17 22:45:41 +00:00
int j, z;
int a;
2020-05-16 10:47:01 +00:00
for (auto& wal : wallsofsector(sectp))
2020-05-16 10:47:01 +00:00
{
int x1 = wal.wall_int_pos().X;
int y1 = wal.wall_int_pos().Y;
2020-05-16 10:47:01 +00:00
2021-11-17 22:45:41 +00:00
auto delta = wal.delta() / (n + 1);
2020-05-16 10:47:01 +00:00
for (j = n; j > 0; j--)
{
2021-12-22 09:26:51 +00:00
x1 += delta.X;
2021-12-22 09:28:51 +00:00
y1 += delta.Y;
2020-05-16 10:47:01 +00:00
a = krand() & 2047;
z = sectp->__int_ceilingz + ((krand() & 15) << 8);
2021-11-18 18:06:08 +00:00
EGS(sectp, x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, (krand() & 31), 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
{
2021-11-17 22:45:41 +00:00
int j, z;
2021-11-17 23:47:46 +00:00
sectortype* sect = nullptr;
2020-11-02 19:00:15 +00:00
int a;;
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--)
{
a = krand() & 2047;
auto k = EGS(actor->sector(), actor->int_pos().X, actor->int_pos().Y, actor->int_pos().Z - (krand() & (63 << 8)), TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 2047), actor, 5);
if (k) k->spr.pal = krand() & 15;
2020-05-16 10:47:01 +00:00
}
return;
}
int x1 = wal->wall_int_pos().X;
int y1 = wal->wall_int_pos().Y;
2020-05-16 10:47:01 +00:00
2021-11-17 23:38:20 +00:00
auto delta = wal->delta() / (n + 1);
2020-05-16 10:47:01 +00:00
for (j = n; j > 0; j--)
{
2021-12-22 09:26:51 +00:00
x1 += delta.X;
2021-12-22 09:28:51 +00:00
y1 += delta.Y;
2020-05-16 10:47:01 +00:00
updatesector(x1, y1, &sect);
z = sect->__int_floorz - (krand() & (abs(sect->__int_ceilingz - sect->__int_floorz)));
2020-05-16 10:47:01 +00:00
if (z < -(32 << 8) || z >(32 << 8))
z = actor->int_pos().Z - (32 << 8) + (krand() & ((64 << 8) - 1));
2021-12-21 20:57:23 +00:00
a = actor->spr.ang - 1024;
auto k = EGS(actor->sector(), x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), -(krand() & 2047), actor, 5);
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