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-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
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
DDukeActor* EGS(short whatsect, int s_x, int s_y, int s_z, short s_pn, signed char s_s, signed char s_xr, signed char s_yr, short s_a, short s_ve, int s_zv, DDukeActor* s_ow, signed char s_ss)
|
2020-05-15 21:46:18 +00:00
|
|
|
{
|
2020-10-24 05:34:54 +00:00
|
|
|
int const i = insertsprite(whatsect, s_ss);
|
2020-05-15 21:46:18 +00:00
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
I_Error(" Too many sprites spawned.");
|
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
auto act = &hittype[i];
|
|
|
|
auto s = &act->s;
|
|
|
|
act->bposx = s_x;
|
|
|
|
act->bposy = s_y;
|
|
|
|
act->bposz = s_z;
|
2020-05-15 21:46:18 +00:00
|
|
|
|
|
|
|
s->x = s_x;
|
|
|
|
s->y = s_y;
|
|
|
|
s->z = s_z;
|
|
|
|
s->cstat = 0;
|
|
|
|
s->picnum = s_pn;
|
|
|
|
s->shade = s_s;
|
|
|
|
s->xrepeat = s_xr;
|
|
|
|
s->yrepeat = s_yr;
|
|
|
|
s->pal = 0;
|
|
|
|
|
|
|
|
s->ang = s_a;
|
|
|
|
s->xvel = s_ve;
|
|
|
|
s->zvel = s_zv;
|
|
|
|
s->xoffset = 0;
|
|
|
|
s->yoffset = 0;
|
|
|
|
s->yvel = 0;
|
|
|
|
s->clipdist = 0;
|
|
|
|
s->pal = 0;
|
|
|
|
s->lotag = 0;
|
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
act->lastvx = 0;
|
|
|
|
act->lastvy = 0;
|
|
|
|
|
|
|
|
act->timetosleep = 0;
|
|
|
|
act->actorstayput = -1;
|
|
|
|
act->extra = -1;
|
|
|
|
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->picnum = s_ow->s.picnum;
|
|
|
|
act->floorz = s_ow->floorz;
|
|
|
|
act->ceilingz = s_ow->ceilingz;
|
|
|
|
}
|
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-05-15 21:46:18 +00:00
|
|
|
if (actorinfo[s_pn].scriptaddress)
|
|
|
|
{
|
|
|
|
auto sa = &ScriptCode[actorinfo[s_pn].scriptaddress];
|
|
|
|
s->extra = sa[0];
|
2020-10-24 05:34:54 +00:00
|
|
|
act->temp_data[4] = sa[1];
|
|
|
|
act->temp_data[1] = sa[2];
|
2020-05-15 21:46:18 +00:00
|
|
|
s->hitag = sa[3];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s->extra = 0;
|
|
|
|
s->hitag = 0;
|
|
|
|
}
|
|
|
|
|
2020-09-06 10:44:58 +00:00
|
|
|
if (show2dsector[s->sectnum]) show2dsprite.Set(i);
|
|
|
|
else show2dsprite.Clear(i);
|
2020-05-15 21:46:18 +00:00
|
|
|
|
|
|
|
spriteext[i] = {};
|
|
|
|
spritesmooth[i] = {};
|
|
|
|
|
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
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
int initspriteforspawn(DDukeActor* actj, int pn, const std::initializer_list<int> &excludes)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
spritetype* sp;
|
|
|
|
int* t;
|
2020-11-02 20:21:52 +00:00
|
|
|
int i;
|
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
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto spawned = EGS(actj->s.sectnum, actj->s.x, actj->s.y, actj->s.z, pn, 0, 0, 0, 0, 0, 0, actj, 0);
|
|
|
|
spawned->picnum = actj->s.picnum;
|
2020-11-02 20:21:52 +00:00
|
|
|
sp = &spawned->s;
|
|
|
|
t = spawned->temp_data;
|
|
|
|
i = spawned->GetIndex();
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i = pn;
|
2020-10-24 05:34:54 +00:00
|
|
|
auto act = &hittype[i];
|
|
|
|
sp = &act->s;
|
|
|
|
t = act->temp_data;
|
|
|
|
|
|
|
|
act->picnum = sp->picnum;
|
|
|
|
act->timetosleep = 0;
|
|
|
|
act->extra = -1;
|
|
|
|
|
|
|
|
act->bposx = sp->x;
|
|
|
|
act->bposy = sp->y;
|
|
|
|
act->bposz = sp->z;
|
|
|
|
|
2020-11-02 21:39:41 +00:00
|
|
|
act->SetOwner(act);
|
|
|
|
act->SetHitOwner(act);
|
2020-10-24 05:34:54 +00:00
|
|
|
act->cgg = 0;
|
|
|
|
act->movflag = 0;
|
|
|
|
act->tempang = 0;
|
|
|
|
act->dispicnum = 0;
|
|
|
|
act->floorz = sector[sp->sectnum].floorz;
|
|
|
|
act->ceilingz = sector[sp->sectnum].ceilingz;
|
|
|
|
|
|
|
|
act->lastvx = 0;
|
|
|
|
act->lastvy = 0;
|
|
|
|
act->actorstayput = -1;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
t[0] = t[1] = t[2] = t[3] = t[4] = t[5] = 0;
|
2020-10-23 15:38:49 +00:00
|
|
|
hittype[i].temp_actor = nullptr;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (sp->cstat & 48)
|
|
|
|
if (!isIn(sp->picnum, excludes) && (sp->cstat & 48))
|
|
|
|
{
|
|
|
|
if (sp->shade == 127) return i;
|
2020-11-02 22:53:55 +00:00
|
|
|
if (wallswitchcheck(act) && (sp->cstat & 16))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-10-24 05:34:54 +00:00
|
|
|
if (sp->picnum != TILE_ACCESSSWITCH && sp->picnum != TILE_ACCESSSWITCH2 && sp->pal)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
if ((ud.multimode < 2) || (ud.multimode > 1 && ud.coop == 1))
|
|
|
|
{
|
2020-10-24 05:34:54 +00:00
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
|
|
|
sp->cstat = sp->lotag = sp->hitag = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sp->cstat |= 257;
|
2020-10-24 05:34:54 +00:00
|
|
|
if (sp->pal && sp->picnum != TILE_ACCESSSWITCH && sp->picnum != TILE_ACCESSSWITCH2)
|
|
|
|
sp->pal = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp->hitag)
|
|
|
|
{
|
|
|
|
changespritestat(i, 12);
|
|
|
|
sp->cstat |= 257;
|
|
|
|
sp->extra = impact_damage;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int s = sp->picnum;
|
|
|
|
|
|
|
|
if (sp->cstat & 1) sp->cstat |= 256;
|
|
|
|
|
|
|
|
if (actorinfo[s].scriptaddress)
|
|
|
|
{
|
|
|
|
sp->extra = ScriptCode[actorinfo[s].scriptaddress];
|
|
|
|
t[4] = ScriptCode[actorinfo[s].scriptaddress+1];
|
|
|
|
t[1] = ScriptCode[actorinfo[s].scriptaddress+2];
|
2020-06-22 19:07:20 +00:00
|
|
|
int s3 = ScriptCode[actorinfo[s].scriptaddress+3];
|
2020-05-15 20:59:13 +00:00
|
|
|
if (s3 && sp->hitag == 0)
|
|
|
|
sp->hitag = s3;
|
|
|
|
}
|
|
|
|
else t[1] = t[4] = 0;
|
|
|
|
}
|
|
|
|
return i | 0x1000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 17:58:23 +00:00
|
|
|
void spawninitdefault(DDukeActor* actj, DDukeActor *act)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-10-24 05:34:54 +00:00
|
|
|
auto sp = &act->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
auto sect = sp->sectnum;
|
|
|
|
|
|
|
|
if (actorinfo[sp->picnum].scriptaddress)
|
|
|
|
{
|
2020-11-02 17:58:23 +00:00
|
|
|
if (actj == nullptr && sp->lotag > ud.player_skill)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
// make it go away...
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
2020-11-02 17:58:23 +00:00
|
|
|
changespritestat(act, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init the size
|
|
|
|
if (sp->xrepeat == 0 || sp->yrepeat == 0)
|
|
|
|
sp->xrepeat = sp->yrepeat = 1;
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
2020-11-02 17:58:23 +00:00
|
|
|
changespritestat(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))
|
2020-10-24 05:34:54 +00:00
|
|
|
act->actorstayput = sp->sectnum;
|
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++;
|
|
|
|
|
|
|
|
sp->clipdist = 80;
|
2020-11-02 17:58:23 +00:00
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 17:58:23 +00:00
|
|
|
if (actj->s.picnum == RESPAWN)
|
|
|
|
act->tempang = sp->pal = actj->s.pal;
|
|
|
|
changespritestat(act, STAT_ACTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2020-11-02 17:58:23 +00:00
|
|
|
else changespritestat(act, STAT_ZOMBIEACTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sp->clipdist = 40;
|
2020-11-02 17:58:23 +00:00
|
|
|
act->SetOwner(act);
|
|
|
|
changespritestat(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)
|
|
|
|
sp->ang = actj->s.ang;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
void spawntransporter(DDukeActor *actj, DDukeActor* acti, bool beam)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
if (actj == nullptr) return;
|
|
|
|
auto sp = &acti->s;
|
|
|
|
auto spj = &actj->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
if (beam)
|
|
|
|
{
|
|
|
|
sp->xrepeat = 31;
|
|
|
|
sp->yrepeat = 1;
|
2020-11-02 17:58:23 +00:00
|
|
|
sp->z = sector[spj->sectnum].floorz - (40 << 8);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-02 17:58:23 +00:00
|
|
|
if (spj->statnum == 4)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
sp->xrepeat = 8;
|
|
|
|
sp->yrepeat = 8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sp->xrepeat = 48;
|
|
|
|
sp->yrepeat = 64;
|
2020-11-02 17:58:23 +00:00
|
|
|
if (spj->statnum == 10 || badguy(spj))
|
2020-05-15 20:59:13 +00:00
|
|
|
sp->z -= (32 << 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->shade = -127;
|
|
|
|
sp->cstat = 128 | 2;
|
2020-11-02 17:58:23 +00:00
|
|
|
sp->ang = spj->ang;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
sp->xvel = 128;
|
2020-11-02 20:21:52 +00:00
|
|
|
changespritestat(acti, STAT_MISC);
|
|
|
|
ssp(acti, CLIPMASK0);
|
|
|
|
setsprite(acti, sp->x, sp->y, sp->z);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
int spawnbloodpoolpart1(DDukeActor *actj, DDukeActor* acti)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
auto sp = &acti->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
short s1 = sp->sectnum;
|
|
|
|
|
|
|
|
updatesector(sp->x + 108, sp->y + 108, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x - 108, sp->y - 108, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x + 108, sp->y - 108, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x - 108, sp->y + 108, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
|
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-02 20:21:52 +00:00
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2020-11-02 20:21:52 +00:00
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
2020-11-02 20:21:52 +00:00
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return true; }
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (sector[sp->sectnum].lotag == 1)
|
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
changespritestat(acti, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
void initfootprint(DDukeActor* actj, DDukeActor* acti)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
auto sp = &acti->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-11-02 20:21:52 +00:00
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
short s1;
|
|
|
|
s1 = sp->sectnum;
|
|
|
|
|
|
|
|
updatesector(sp->x + 84, sp->y + 84, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x - 84, sp->y - 84, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x + 84, sp->y - 84, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
|
|
|
|
{
|
|
|
|
updatesector(sp->x - 84, sp->y + 84, &s1);
|
|
|
|
if (s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
|
|
|
|
{
|
2020-11-02 20:21:52 +00:00
|
|
|
sp->xrepeat = sp->yrepeat = 0; changespritestat(acti, STAT_MISC); return;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; return; }
|
|
|
|
}
|
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; return; }
|
|
|
|
}
|
|
|
|
else { sp->xrepeat = sp->yrepeat = 0; return; }
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
sp->cstat = 32 + ((ps[actj->s.yvel].footprintcount & 1) << 2);
|
|
|
|
sp->ang = actj->s.ang;
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sp->z = sector[sect].floorz;
|
|
|
|
if (sector[sect].lotag != 1 && sector[sect].lotag != 2)
|
|
|
|
sp->xrepeat = sp->yrepeat = 32;
|
|
|
|
|
2020-11-02 20:21:52 +00:00
|
|
|
insertspriteq(acti);
|
|
|
|
changespritestat(acti, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
void initshell(DDukeActor* actj, DDukeActor* acti, bool isshell)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto sp = &acti->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-11-02 20:37:37 +00:00
|
|
|
auto t = acti->temp_data;
|
|
|
|
if (actj)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto spj = &actj->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
short snum, a;
|
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
if (spj->picnum == TILE_APLAYER)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-10-24 05:34:54 +00:00
|
|
|
snum = spj->yvel;
|
2020-10-07 12:13:21 +00:00
|
|
|
a = ps[snum].angle.ang.asbuild() - (krand() & 63) + 8; //Fine tune
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
t[0] = krand() & 1;
|
2020-10-07 06:12:37 +00:00
|
|
|
sp->z = (3 << 8) + ps[snum].pyoff + ps[snum].posz - (ps[snum].horizon.sum().asq16() >> 12) + (!isshell ? (3 << 8) : 0);
|
2020-05-15 20:59:13 +00:00
|
|
|
sp->zvel = -(krand() & 255);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a = sp->ang;
|
2020-10-24 05:34:54 +00:00
|
|
|
sp->z = spj->z - PHEIGHT + (3 << 8);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-24 05:34:54 +00:00
|
|
|
sp->x = spj->x + (sintable[(a + 512) & 2047] >> 7);
|
|
|
|
sp->y = spj->y + (sintable[a & 2047] >> 7);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
sp->shade = -8;
|
|
|
|
|
|
|
|
if (isNamWW2GI())
|
|
|
|
{
|
|
|
|
// to the right, with feeling
|
|
|
|
sp->ang = a + 512;
|
|
|
|
sp->xvel = 30;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sp->ang = a - 512;
|
|
|
|
sp->xvel = 20;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->xrepeat = sp->yrepeat = isRR() && isshell? 2 : 4;
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
changespritestat(acti, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
void initcrane(DDukeActor* actj, DDukeActor* acti, int CRANEPOLE)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto sp = &acti->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-11-02 20:37:37 +00:00
|
|
|
auto t = acti->temp_data;
|
2020-05-15 20:59:13 +00:00
|
|
|
sp->cstat |= 64 | 257;
|
|
|
|
|
|
|
|
sp->picnum += 2;
|
|
|
|
sp->z = sector[sect].ceilingz + (48 << 8);
|
|
|
|
t[4] = tempwallptr;
|
|
|
|
|
|
|
|
msx[tempwallptr] = sp->x;
|
|
|
|
msy[tempwallptr] = sp->y;
|
|
|
|
msx[tempwallptr + 2] = sp->z;
|
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
DukeStatIterator it(STAT_DEFAULT);
|
|
|
|
while (auto act = it.Next())
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto ss = &act->s;
|
2020-10-14 20:18:10 +00:00
|
|
|
if (ss->picnum == CRANEPOLE && sp->hitag == (ss->hitag))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
msy[tempwallptr + 2] = ActorToScriptIndex(act);
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-14 20:18:10 +00:00
|
|
|
t[1] = ss->sectnum;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-14 20:18:10 +00:00
|
|
|
ss->xrepeat = 48;
|
|
|
|
ss->yrepeat = 128;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-14 20:18:10 +00:00
|
|
|
msx[tempwallptr + 1] = ss->x;
|
|
|
|
msy[tempwallptr + 1] = ss->y;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-10-14 20:18:10 +00:00
|
|
|
ss->x = sp->x;
|
|
|
|
ss->y = sp->y;
|
|
|
|
ss->z = sp->z;
|
|
|
|
ss->shade = sp->shade;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-11-02 20:37:37 +00:00
|
|
|
setsprite(act, ss->pos);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tempwallptr += 3;
|
2020-11-02 21:29:02 +00:00
|
|
|
acti->SetOwner(nullptr);
|
2020-05-15 20:59:13 +00:00
|
|
|
sp->extra = 8;
|
2020-11-02 20:37:37 +00:00
|
|
|
changespritestat(acti, 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
|
|
|
{
|
2020-11-02 20:37:37 +00:00
|
|
|
auto sp = &actor->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-11-02 20:37:37 +00:00
|
|
|
auto t = actor->temp_data;
|
|
|
|
if (actj && (actj->s.statnum == 10 || actj->s.statnum == 1))
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
sp->shade = 32;
|
2020-11-02 20:37:37 +00:00
|
|
|
if (actj->s.pal != 1)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
sp->pal = 2;
|
|
|
|
sp->z -= (18 << 8);
|
|
|
|
}
|
|
|
|
else sp->z -= (13 << 8);
|
|
|
|
sp->ang = getangle(ps[connecthead].posx - sp->x, ps[connecthead].posy - sp->y);
|
|
|
|
sp->xvel = 48 - (krand() & 31);
|
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
|
|
|
{
|
|
|
|
sp->z += (4 << 8);
|
|
|
|
t[0] = sp->z;
|
|
|
|
if (!isRR()) t[1] = krand() & 127;
|
|
|
|
}
|
|
|
|
sp->xrepeat = 24;
|
|
|
|
sp->yrepeat = 24;
|
2020-11-02 20:37:37 +00:00
|
|
|
changespritestat(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
|
|
|
{
|
2020-10-23 17:02:58 +00:00
|
|
|
auto sp = &actor->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-10-23 17:02:58 +00:00
|
|
|
auto t = actor->temp_data;
|
2020-05-15 20:59:13 +00:00
|
|
|
if (isrecon)
|
|
|
|
{
|
|
|
|
if (sp->lotag > ud.player_skill)
|
|
|
|
{
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
2020-10-23 17:02:58 +00:00
|
|
|
changespritestat(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)
|
|
|
|
{
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
2020-10-23 17:02:58 +00:00
|
|
|
changespritestat(actor, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sp->extra = 130;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sp->extra = impact_damage;
|
|
|
|
|
|
|
|
sp->cstat |= 257; // Make it hitable
|
|
|
|
|
|
|
|
if (ud.multimode < 2 && sp->pal != 0)
|
|
|
|
{
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
2020-10-23 17:02:58 +00:00
|
|
|
changespritestat(actor, STAT_MISC);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sp->pal = 0;
|
|
|
|
sp->shade = -17;
|
|
|
|
|
2020-10-23 17:02:58 +00:00
|
|
|
changespritestat(actor, 2);
|
2020-05-15 20:59:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
void spawneffector(DDukeActor* actor)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 21:20:41 +00:00
|
|
|
auto sp = &actor->s;
|
2020-05-15 20:59:13 +00:00
|
|
|
int sect = sp->sectnum;
|
2020-11-02 21:20:41 +00:00
|
|
|
auto t = actor->temp_data;
|
|
|
|
int startwall, endwall, x, y, d, s, clostest;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
sp->yvel = sector[sect].extra;
|
|
|
|
sp->cstat |= 32768;
|
|
|
|
sp->xrepeat = sp->yrepeat = 0;
|
|
|
|
|
|
|
|
switch (sp->lotag)
|
|
|
|
{
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_28_LIGHTNING:
|
2020-05-15 20:59:13 +00:00
|
|
|
if (!isRR()) t[5] = 65;// Delay for lightning
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_7_TELEPORT: // Transporters!!!!
|
|
|
|
case SE_23_ONE_WAY_TELEPORT:// XPTR END
|
2020-05-15 20:59:13 +00:00
|
|
|
if (sp->lotag != 23)
|
|
|
|
{
|
2020-11-02 21:20:41 +00:00
|
|
|
DukeSpriteIterator it;
|
|
|
|
while (auto act2 = it.Next())
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 21:20:41 +00:00
|
|
|
if (act2->s.statnum < MAXSTATUS && act2->s.picnum == SECTOREFFECTOR && (act2->s.lotag == 7 || act2->s.lotag == 23) && actor != act2 && act2->s.hitag == sp->hitag)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
t[4] = sector[sect].floorz == sp->z;
|
|
|
|
sp->cstat = 0;
|
2020-11-02 21:20:41 +00:00
|
|
|
changespritestat(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);
|
2020-05-15 20:59:13 +00:00
|
|
|
t[0] = 1;
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (sp->ang == 512)
|
|
|
|
{
|
|
|
|
t[1] = sector[sect].ceilingz;
|
|
|
|
if (sp->pal)
|
|
|
|
sector[sect].ceilingz = sp->z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t[1] = sector[sect].floorz;
|
|
|
|
if (sp->pal)
|
|
|
|
sector[sect].floorz = sp->z;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->hitag <<= 2;
|
|
|
|
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
|
2020-05-15 20:59:13 +00:00
|
|
|
if (!isRR())
|
|
|
|
{
|
|
|
|
t[3] = sector[sect].ceilingz;
|
|
|
|
t[4] = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
t[4] = sector[sect].ceilingz;
|
|
|
|
|
|
|
|
sector[sect].ceilingz = sp->z;
|
|
|
|
setinterpolation(§or[sect].ceilingz);
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_35:
|
2020-05-15 20:59:13 +00:00
|
|
|
sector[sect].ceilingz = sp->z;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
sp->xrepeat = sp->yrepeat = 64;
|
|
|
|
sp->cstat &= 32767;
|
|
|
|
}
|
|
|
|
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;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_12_LIGHT_SWITCH:
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
t[1] = sector[sect].floorshade;
|
|
|
|
t[2] = sector[sect].ceilingshade;
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_13_EXPLOSIVE:
|
2020-11-02 21:26:32 +00:00
|
|
|
{
|
2020-05-15 20:59:13 +00:00
|
|
|
t[0] = sector[sect].ceilingz;
|
|
|
|
t[1] = sector[sect].floorz;
|
|
|
|
|
2020-11-02 21:26:32 +00:00
|
|
|
bool ceiling = (abs(t[0] - sp->z) < abs(t[1] - sp->z));
|
2020-11-02 21:39:41 +00:00
|
|
|
actor->spriteextra = ceiling;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (sp->ang == 512)
|
|
|
|
{
|
2020-11-02 21:26:32 +00:00
|
|
|
if (ceiling)
|
2020-05-15 20:59:13 +00:00
|
|
|
sector[sect].ceilingz = sp->z;
|
|
|
|
else
|
|
|
|
sector[sect].floorz = sp->z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sector[sect].ceilingz = sector[sect].floorz = sp->z;
|
|
|
|
|
|
|
|
if (sector[sect].ceilingstat & 1)
|
|
|
|
{
|
|
|
|
sector[sect].ceilingstat ^= 1;
|
|
|
|
t[3] = 1;
|
|
|
|
|
2020-11-02 21:26:32 +00:00
|
|
|
if (!ceiling && sp->ang == 512)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
sector[sect].ceilingstat ^= 1;
|
|
|
|
t[3] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sector[sect].ceilingshade =
|
|
|
|
sector[sect].floorshade;
|
|
|
|
|
|
|
|
if (sp->ang == 512)
|
|
|
|
{
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
2020-11-02 21:20:41 +00:00
|
|
|
for (int j = startwall; j < endwall; j++)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
int x = wall[j].nextsector;
|
|
|
|
if (x >= 0)
|
|
|
|
if (!(sector[x].ceilingstat & 1))
|
|
|
|
{
|
|
|
|
sector[sect].ceilingpicnum =
|
|
|
|
sector[x].ceilingpicnum;
|
|
|
|
sector[sect].ceilingshade =
|
|
|
|
sector[x].ceilingshade;
|
|
|
|
break; //Leave earily
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2020-05-15 20:59:13 +00:00
|
|
|
t[2] = sector[sect].floorz; //Stopping loc
|
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
int j = nextsectorneighborz(sect, sector[sect].floorz, -1, -1);
|
2020-05-15 20:59:13 +00:00
|
|
|
t[3] = sector[j].ceilingz;
|
|
|
|
|
|
|
|
j = nextsectorneighborz(sect, sector[sect].ceilingz, 1, 1);
|
|
|
|
t[4] = sector[j].floorz;
|
|
|
|
|
|
|
|
if (numplayers < 2)
|
|
|
|
{
|
|
|
|
setinterpolation(§or[sect].floorz);
|
|
|
|
setinterpolation(§or[sect].ceilingz);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2020-11-02 21:20:41 +00:00
|
|
|
}
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_24_CONVEYOR:
|
2020-05-15 20:59:13 +00:00
|
|
|
sp->yvel <<= 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
|
|
|
{
|
|
|
|
int q;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
//find the two most clostest wall x's and y's
|
|
|
|
q = 0x7fffffff;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
{
|
|
|
|
x = wall[s].x;
|
|
|
|
y = wall[s].y;
|
|
|
|
|
|
|
|
d = FindDistance2D(sp->x - x, sp->y - y);
|
|
|
|
if (d < q)
|
|
|
|
{
|
|
|
|
q = d;
|
|
|
|
clostest = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t[1] = clostest;
|
|
|
|
|
|
|
|
q = 0x7fffffff;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
{
|
|
|
|
x = wall[s].x;
|
|
|
|
y = wall[s].y;
|
|
|
|
|
|
|
|
d = FindDistance2D(sp->x - x, sp->y - y);
|
|
|
|
if (d < q && s != t[1])
|
|
|
|
{
|
|
|
|
q = d;
|
|
|
|
clostest = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t[2] = clostest;
|
|
|
|
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
|
|
|
|
|
|
|
t[3] = sector[sect].floorshade;
|
|
|
|
|
|
|
|
sector[sect].floorshade = sp->shade;
|
|
|
|
sector[sect].ceilingshade = sp->shade;
|
|
|
|
|
2020-11-02 21:39:41 +00:00
|
|
|
actor->palvals = (sector[sect].ceilingpal << 8) | sector[sect].floorpal;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
//fix all the walls;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
{
|
|
|
|
if (!(wall[s].hitag & 1))
|
|
|
|
wall[s].shade = sp->shade;
|
|
|
|
if ((wall[s].cstat & 2) && wall[s].nextwall >= 0)
|
|
|
|
wall[wall[s].nextwall].shade = sp->shade;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_31_FLOOR_RISE_FALL:
|
2020-05-15 20:59:13 +00:00
|
|
|
t[1] = sector[sect].floorz;
|
|
|
|
// t[2] = sp->hitag;
|
|
|
|
if (sp->ang != 1536) sector[sect].floorz = sp->z;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
if (wall[s].hitag == 0) wall[s].hitag = 9999;
|
|
|
|
|
|
|
|
setinterpolation(§or[sect].floorz);
|
|
|
|
|
|
|
|
break;
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_32_CEILING_RISE_FALL:
|
2020-05-15 20:59:13 +00:00
|
|
|
t[1] = sector[sect].ceilingz;
|
|
|
|
t[2] = sp->hitag;
|
|
|
|
if (sp->ang != 1536) sector[sect].ceilingz = sp->z;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
if (wall[s].hitag == 0) wall[s].hitag = 9999;
|
|
|
|
|
|
|
|
setinterpolation(§or[sect].ceilingz);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_4_RANDOM_LIGHTS: //Flashing lights
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
t[2] = sector[sect].floorshade;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
2020-11-02 21:39:41 +00:00
|
|
|
actor->palvals = (sector[sect].ceilingpal << 8) | sector[sect].floorpal;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
if (wall[s].shade > t[3])
|
|
|
|
t[3] = wall[s].shade;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_9_DOWN_OPEN_DOOR_LIGHTS:
|
2020-05-15 20:59:13 +00:00
|
|
|
if (sector[sect].lotag &&
|
|
|
|
labs(sector[sect].ceilingz - sp->z) > 1024)
|
|
|
|
sector[sect].lotag |= 32768; //If its open
|
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
|
|
|
|
|
|
|
|
t[0] = sector[sect].floorshade;
|
|
|
|
t[1] = sector[sect].ceilingshade;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
if (wall[s].shade > t[2])
|
|
|
|
t[2] = wall[s].shade;
|
|
|
|
|
|
|
|
t[3] = 1; //Take Out;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 88:
|
|
|
|
//First, get the ceiling-floor shade
|
|
|
|
if (!isRR()) break;
|
|
|
|
|
|
|
|
t[0] = sector[sect].floorshade;
|
|
|
|
t[1] = sector[sect].ceilingshade;
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
if (wall[s].shade > t[2])
|
|
|
|
t[2] = wall[s].shade;
|
|
|
|
|
|
|
|
t[3] = 1; //Take Out;
|
|
|
|
break;
|
|
|
|
|
2020-11-01 08:00:16 +00:00
|
|
|
case SE_11_SWINGING_DOOR://Pivitor rotater
|
2020-05-15 20:59:13 +00:00
|
|
|
if (sp->ang > 1024) t[3] = 2;
|
|
|
|
else t[3] = -2;
|
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
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
if (sp->lotag == 0)
|
|
|
|
{
|
|
|
|
if (sector[sect].lotag == 30)
|
|
|
|
{
|
2020-11-02 21:20:41 +00:00
|
|
|
if (sp->pal) sp->clipdist = 1;
|
|
|
|
else sp->clipdist = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
t[3] = sector[sect].floorz;
|
2020-11-02 21:20:41 +00:00
|
|
|
sector[sect].hitag = actor->GetIndex(); // hijack
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
DukeSpriteIterator it;
|
|
|
|
bool found = false;
|
|
|
|
while (auto act2 = it.Next())
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
2020-11-02 21:20:41 +00:00
|
|
|
auto spr = &act2->s;
|
2020-11-02 17:58:23 +00:00
|
|
|
if (spr->statnum < MAXSTATUS)
|
|
|
|
if (spr->picnum == SECTOREFFECTOR &&
|
2020-11-02 21:20:41 +00:00
|
|
|
spr->lotag == SE_1_PIVOT &&
|
2020-11-02 17:58:23 +00:00
|
|
|
spr->hitag == sp->hitag)
|
2020-05-15 20:59:13 +00:00
|
|
|
{
|
|
|
|
if (sp->ang == 512)
|
|
|
|
{
|
2020-11-02 17:58:23 +00:00
|
|
|
sp->x = spr->x;
|
|
|
|
sp->y = spr->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
|
|
|
{
|
2020-07-23 14:35:54 +00:00
|
|
|
I_Error("Found lonely Sector Effector (lotag 0) at (%d,%d)\n", sp->x, sp->y);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
t[1] = tempwallptr;
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
{
|
|
|
|
msx[tempwallptr] = wall[s].x - sp->x;
|
|
|
|
msy[tempwallptr] = wall[s].y - sp->y;
|
|
|
|
tempwallptr++;
|
|
|
|
if (tempwallptr > 2047)
|
|
|
|
{
|
2020-07-23 14:35:54 +00:00
|
|
|
I_Error("Too many moving sectors at (%d,%d).\n", wall[s].x, wall[s].y);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sp->lotag == 30 || sp->lotag == 6 || sp->lotag == 14 || sp->lotag == 5)
|
|
|
|
{
|
|
|
|
|
|
|
|
startwall = sector[sect].wallptr;
|
|
|
|
endwall = startwall + sector[sect].wallnum;
|
|
|
|
|
|
|
|
if (sector[sect].hitag == -1)
|
|
|
|
sp->extra = 0;
|
|
|
|
else sp->extra = 1;
|
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
sector[sect].hitag = actor->GetIndex(); // hijack
|
2020-05-15 20:59:13 +00:00
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
int j = 0;
|
2020-05-15 20:59:13 +00:00
|
|
|
|
|
|
|
for (s = startwall; s < endwall; s++)
|
|
|
|
{
|
|
|
|
if (wall[s].nextsector >= 0 &&
|
|
|
|
sector[wall[s].nextsector].hitag == 0 &&
|
|
|
|
(sector[wall[s].nextsector].lotag < 3 || (isRRRA() && sector[wall[s].nextsector].lotag == 160)))
|
|
|
|
{
|
|
|
|
s = wall[s].nextsector;
|
|
|
|
j = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == 0)
|
|
|
|
{
|
2020-07-23 14:35:54 +00:00
|
|
|
I_Error("Subway found no zero'd sectors with locators\nat (%d,%d).\n", sp->x, sp->y);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-02 21:26:32 +00:00
|
|
|
actor->SetOwner(nullptr);
|
2020-05-15 20:59:13 +00:00
|
|
|
t[0] = s;
|
|
|
|
|
|
|
|
if (sp->lotag != 30)
|
|
|
|
t[3] = sp->hitag;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (sp->lotag == 16)
|
|
|
|
t[3] = sector[sect].ceilingz;
|
|
|
|
|
|
|
|
else if (sp->lotag == 26)
|
|
|
|
{
|
|
|
|
t[3] = sp->x;
|
|
|
|
t[4] = sp->y;
|
|
|
|
if (sp->shade == sector[sect].floorshade) //UP
|
|
|
|
sp->zvel = -256;
|
|
|
|
else
|
|
|
|
sp->zvel = 256;
|
|
|
|
|
|
|
|
sp->shade = 0;
|
|
|
|
}
|
|
|
|
else if (sp->lotag == 2)
|
|
|
|
{
|
|
|
|
t[5] = sector[sp->sectnum].floorheinum;
|
|
|
|
sector[sp->sectnum].floorheinum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (sp->lotag)
|
|
|
|
{
|
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
|
|
|
{
|
|
|
|
int j = callsound(sect, actor);
|
2020-05-15 20:59:13 +00:00
|
|
|
if (j == -1)
|
|
|
|
{
|
|
|
|
if (!isRR()) j = SUBWAY; // Duke
|
|
|
|
else if (sector[sp->sectnum].floorpal == 7) j = 456;
|
|
|
|
else j = 75;
|
|
|
|
}
|
2020-11-02 21:20:41 +00:00
|
|
|
actor->lastvx = j;
|
|
|
|
}
|
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;
|
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:
|
2020-11-02 21:20:41 +00:00
|
|
|
setsectinterpolate(actor->s.sectnum);
|
2020-05-15 20:59:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-02 21:20:41 +00:00
|
|
|
if ((!isRR() && actor->s.lotag >= 40 && actor->s.lotag <= 45) ||
|
|
|
|
(isRRRA() && actor->s.lotag >= 150 && actor->s.lotag <= 155))
|
|
|
|
changespritestat(actor, STAT_RAROR);
|
2020-05-15 20:59:13 +00:00
|
|
|
else
|
2020-11-02 21:20:41 +00:00
|
|
|
changespritestat(actor, STAT_EFFECTOR);
|
2020-05-15 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-16 10:47:01 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 21:29:02 +00:00
|
|
|
void lotsofglass(DDukeActor *actor, int wallnum, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
|
|
|
int j, xv, yv, z, x1, y1, a;
|
|
|
|
short sect;
|
2020-11-02 21:29:02 +00:00
|
|
|
auto sp = &actor->s;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
|
|
|
sect = -1;
|
|
|
|
|
|
|
|
if (wallnum < 0)
|
|
|
|
{
|
|
|
|
for (j = n - 1; j >= 0; j--)
|
|
|
|
{
|
|
|
|
a = sp->ang - 256 + (krand() & 511) + 1024;
|
2020-11-02 20:21:52 +00:00
|
|
|
EGS(sp->sectnum, sp->x, sp->y, sp->z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 1023), &hittype[j], 5);
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = n + 1;
|
|
|
|
|
|
|
|
x1 = wall[wallnum].x;
|
|
|
|
y1 = wall[wallnum].y;
|
|
|
|
|
|
|
|
xv = wall[wall[wallnum].point2].x - x1;
|
|
|
|
yv = wall[wall[wallnum].point2].y - y1;
|
|
|
|
|
|
|
|
x1 -= sgn(yv);
|
|
|
|
y1 += sgn(xv);
|
|
|
|
|
|
|
|
xv /= j;
|
|
|
|
yv /= j;
|
|
|
|
|
|
|
|
for (j = n; j > 0; j--)
|
|
|
|
{
|
|
|
|
x1 += xv;
|
|
|
|
y1 += yv;
|
|
|
|
|
|
|
|
updatesector(x1, y1, §);
|
|
|
|
if (sect >= 0)
|
|
|
|
{
|
|
|
|
z = sector[sect].floorz - (krand() & (abs(sector[sect].ceilingz - sector[sect].floorz)));
|
|
|
|
if (z < -(32 << 8) || z >(32 << 8))
|
|
|
|
z = sp->z - (32 << 8) + (krand() & ((64 << 8) - 1));
|
|
|
|
a = sp->ang - 1024;
|
2020-11-02 21:29:02 +00:00
|
|
|
EGS(sp->sectnum, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
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
|
|
|
auto sp = &actor->s;
|
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
|
|
|
{
|
2020-10-25 05:40:05 +00:00
|
|
|
int a = krand() & 2047;
|
|
|
|
int z = sp->z - ((krand() & 16) << 8);
|
|
|
|
auto k = EGS(sp->sectnum, sp->x, sp->y, z, TILE_GLASSPIECES + (j % 3), krand() & 15, 36, 36, a, 32 + (krand() & 63), -512 - (krand() & 2047), actor, 5);
|
|
|
|
k->s.pal = sp->pal;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 19:23:30 +00:00
|
|
|
void ceilingglass(DDukeActor* actor, int sectnum, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
|
|
|
int j, xv, yv, z, x1, y1;
|
|
|
|
int a, s, startwall, endwall;
|
2020-11-02 19:23:30 +00:00
|
|
|
auto sp = &actor->s;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
|
|
|
startwall = sector[sectnum].wallptr;
|
|
|
|
endwall = startwall + sector[sectnum].wallnum;
|
|
|
|
|
|
|
|
for (s = startwall; s < (endwall - 1); s++)
|
|
|
|
{
|
|
|
|
x1 = wall[s].x;
|
|
|
|
y1 = wall[s].y;
|
|
|
|
|
|
|
|
xv = (wall[s + 1].x - x1) / (n + 1);
|
|
|
|
yv = (wall[s + 1].y - y1) / (n + 1);
|
|
|
|
|
|
|
|
for (j = n; j > 0; j--)
|
|
|
|
{
|
|
|
|
x1 += xv;
|
|
|
|
y1 += yv;
|
|
|
|
a = krand() & 2047;
|
|
|
|
z = sector[sectnum].ceilingz + ((krand() & 15) << 8);
|
2020-11-02 19:23:30 +00:00
|
|
|
EGS(sectnum, x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, (krand() & 31), 0, actor, 5);
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-11-02 19:00:15 +00:00
|
|
|
void lotsofcolourglass(DDukeActor* actor, int wallnum, int n)
|
2020-05-16 10:47:01 +00:00
|
|
|
{
|
|
|
|
int j, xv, yv, z, x1, y1;
|
|
|
|
short sect = -1;
|
2020-11-02 19:00:15 +00:00
|
|
|
int a;;
|
|
|
|
auto sp = &actor->s;
|
2020-05-16 10:47:01 +00:00
|
|
|
|
|
|
|
if (wallnum < 0)
|
|
|
|
{
|
|
|
|
for (j = n - 1; j >= 0; j--)
|
|
|
|
{
|
|
|
|
a = krand() & 2047;
|
2020-11-02 19:00:15 +00:00
|
|
|
auto k = EGS(sp->sectnum, sp->x, sp->y, sp->z - (krand() & (63 << 8)), TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), 1024 - (krand() & 2047), actor, 5);
|
|
|
|
k->s.pal = krand() & 15;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = n + 1;
|
|
|
|
x1 = wall[wallnum].x;
|
|
|
|
y1 = wall[wallnum].y;
|
|
|
|
|
|
|
|
xv = (wall[wall[wallnum].point2].x - wall[wallnum].x) / j;
|
|
|
|
yv = (wall[wall[wallnum].point2].y - wall[wallnum].y) / j;
|
|
|
|
|
|
|
|
for (j = n; j > 0; j--)
|
|
|
|
{
|
|
|
|
x1 += xv;
|
|
|
|
y1 += yv;
|
|
|
|
|
|
|
|
updatesector(x1, y1, §);
|
|
|
|
z = sector[sect].floorz - (krand() & (abs(sector[sect].ceilingz - sector[sect].floorz)));
|
|
|
|
if (z < -(32 << 8) || z >(32 << 8))
|
|
|
|
z = sp->z - (32 << 8) + (krand() & ((64 << 8) - 1));
|
|
|
|
a = sp->ang - 1024;
|
2020-11-02 19:00:15 +00:00
|
|
|
auto k = EGS(sp->sectnum, x1, y1, z, TILE_GLASSPIECES + (j % 3), -32, 36, 36, a, 32 + (krand() & 63), -(krand() & 2047), actor, 5);
|
|
|
|
k->s.pal = krand() & 7;
|
2020-05-16 10:47:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-15 20:59:13 +00:00
|
|
|
END_DUKE_NS
|