2020-05-10 10:42:47 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements)
|
2020-05-13 14:19:39 +00:00
|
|
|
Copyright (C) 2020 - Christoph Oelckers
|
2020-05-10 10:42:47 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
#include <utility>
|
2020-05-10 10:42:47 +00:00
|
|
|
#include "ns.h"
|
|
|
|
#include "global.h"
|
2020-06-24 19:21:02 +00:00
|
|
|
#include "sounds.h"
|
2020-10-24 07:35:43 +00:00
|
|
|
#include "dukeactor.h"
|
2020-11-26 15:03:40 +00:00
|
|
|
#include "interpolate.h"
|
2020-05-10 10:42:47 +00:00
|
|
|
|
|
|
|
// PRIMITIVE
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
2020-11-26 15:03:40 +00:00
|
|
|
static int interptype[] = { Interp_Sect_Floorz, Interp_Sect_Ceilingz, Interp_Wall_X, Interp_Wall_Y };
|
|
|
|
|
2022-11-25 16:43:13 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool ceilingspace(sectortype* sectp)
|
|
|
|
{
|
|
|
|
return (sectp && (sectp->ceilingstat & CSTAT_SECTOR_SKY) && sectp->ceilingpal == 0 && (tileflags(sectp->ceilingpicnum) & TFLAG_OUTERSPACE));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool floorspace(sectortype* sectp)
|
|
|
|
{
|
|
|
|
return (sectp && (sectp->floorstat & CSTAT_SECTOR_SKY) && sectp->floorpal == 0 && (tileflags(sectp->floorpicnum) & TFLAG_OUTERSPACE));
|
|
|
|
}
|
|
|
|
|
2020-05-10 10:42:47 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
static bool haltsoundhack;
|
|
|
|
|
2022-01-09 22:03:11 +00:00
|
|
|
int callsound(sectortype* sn, DDukeActor* whatsprite, bool endstate)
|
2020-05-10 10:42:47 +00:00
|
|
|
{
|
2020-05-12 11:43:24 +00:00
|
|
|
if (!isRRRA() && haltsoundhack)
|
|
|
|
{
|
|
|
|
haltsoundhack = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-10-23 15:38:49 +00:00
|
|
|
DukeSectIterator it(sn);
|
|
|
|
while (auto act = it.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-20 07:10:15 +00:00
|
|
|
if (issoundcontroller(act) && act->spr.lotag < 1000)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2020-10-23 15:38:49 +00:00
|
|
|
if (whatsprite == nullptr) whatsprite = act;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-12-21 20:39:57 +00:00
|
|
|
int snum = act->spr.lotag;
|
2020-05-12 11:43:24 +00:00
|
|
|
auto flags = S_GetUserFlags(snum);
|
2020-08-01 09:56:02 +00:00
|
|
|
|
|
|
|
// Reset if the desired actor isn't playing anything.
|
2021-12-21 20:39:57 +00:00
|
|
|
bool hival = S_IsSoundValid(act->spr.hitag);
|
2022-01-09 22:03:11 +00:00
|
|
|
if (act->temp_data[0] == 1 && !hival && !endstate)
|
2020-08-01 09:56:02 +00:00
|
|
|
{
|
2020-10-23 15:38:49 +00:00
|
|
|
if (!S_CheckActorSoundPlaying(act->temp_actor, snum))
|
|
|
|
act->temp_data[0] = 0;
|
2020-08-01 09:56:02 +00:00
|
|
|
}
|
|
|
|
|
2020-10-23 15:38:49 +00:00
|
|
|
if (act->temp_data[0] == 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
if ((flags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL)
|
|
|
|
{
|
|
|
|
if (snum)
|
|
|
|
{
|
2021-12-21 20:39:57 +00:00
|
|
|
if (act->spr.hitag && snum != act->spr.hitag)
|
|
|
|
S_StopSound(act->spr.hitag, act->temp_actor);
|
2020-07-25 07:32:54 +00:00
|
|
|
S_PlayActorSound(snum, whatsprite);
|
2020-10-23 15:38:49 +00:00
|
|
|
act->temp_actor = whatsprite;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
if ((act->sector()->lotag & 0xff) != ST_22_SPLITTING_DOOR)
|
2020-10-23 15:38:49 +00:00
|
|
|
act->temp_data[0] = 1;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-21 20:39:57 +00:00
|
|
|
else if (act->spr.hitag < 1000)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-10-01 10:59:43 +00:00
|
|
|
// The original code performed these two actions in reverse order which in case of a looped sound being stopped
|
|
|
|
// being the same as the sound about to be started, the newly started sound would fall through some cracks in the sound system and be rejected.
|
|
|
|
// Here this case needs to be simulated.
|
|
|
|
bool stopped = false;
|
2021-12-21 20:39:57 +00:00
|
|
|
if ((flags & SF_LOOP) || (act->spr.hitag && act->spr.hitag != act->spr.lotag))
|
2022-10-01 10:59:43 +00:00
|
|
|
{
|
2021-12-21 20:39:57 +00:00
|
|
|
S_StopSound(act->spr.lotag, act->temp_actor);
|
2022-10-01 10:59:43 +00:00
|
|
|
if (act->spr.hitag == act->spr.lotag) stopped = true;
|
|
|
|
}
|
|
|
|
if (act->spr.hitag && !stopped) S_PlayActorSound(act->spr.hitag, whatsprite);
|
2020-10-23 15:38:49 +00:00
|
|
|
act->temp_data[0] = 0;
|
|
|
|
act->temp_actor = whatsprite;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2021-12-21 20:39:57 +00:00
|
|
|
return act->spr.lotag;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
2020-05-10 10:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int check_activator_motion(int lotag)
|
|
|
|
{
|
2020-10-23 15:40:58 +00:00
|
|
|
DukeStatIterator it(STAT_ACTIVATOR);
|
|
|
|
while (auto act = it.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act->spr.lotag == lotag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
for (int j = animates.Size() - 1; j >= 0; j--)
|
|
|
|
if (act->sector() == animates[j].sect)
|
2020-05-12 11:43:24 +00:00
|
|
|
return(1);
|
|
|
|
|
2020-10-23 15:40:58 +00:00
|
|
|
DukeStatIterator it1(STAT_EFFECTOR);
|
|
|
|
while (auto act2 = it1.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
if (act->sector() == act2->sector())
|
2021-12-21 17:19:45 +00:00
|
|
|
switch (act2->spr.lotag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
case SE_11_SWINGING_DOOR:
|
|
|
|
case SE_30_TWO_WAY_TRAIN:
|
2020-10-23 15:40:58 +00:00
|
|
|
if (act2->temp_data[4])
|
2020-05-12 11:43:24 +00:00
|
|
|
return(1);
|
|
|
|
break;
|
|
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
|
|
|
if (isRRRA()) break;
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-05-12 11:43:24 +00:00
|
|
|
case SE_20_STRETCH_BRIDGE:
|
|
|
|
case SE_31_FLOOR_RISE_FALL:
|
|
|
|
case SE_32_CEILING_RISE_FALL:
|
2020-10-23 15:40:58 +00:00
|
|
|
if (act2->temp_data[0])
|
2020-05-12 11:43:24 +00:00
|
|
|
return(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(0);
|
2020-05-10 10:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool isanunderoperator(int lotag)
|
|
|
|
{
|
2020-05-12 11:43:24 +00:00
|
|
|
switch (lotag & 0xff)
|
|
|
|
{
|
|
|
|
case ST_15_WARP_ELEVATOR:
|
|
|
|
case ST_16_PLATFORM_DOWN:
|
|
|
|
case ST_17_PLATFORM_UP:
|
|
|
|
case ST_18_ELEVATOR_DOWN:
|
|
|
|
case ST_19_ELEVATOR_UP:
|
|
|
|
case ST_26_SPLITTING_ST_DOOR:
|
|
|
|
return true;
|
|
|
|
case ST_22_SPLITTING_DOOR:
|
|
|
|
return !isRR();
|
|
|
|
}
|
|
|
|
return false;
|
2020-05-10 10:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool isanearoperator(int lotag)
|
|
|
|
{
|
2020-05-12 11:43:24 +00:00
|
|
|
switch (lotag & 0xff)
|
|
|
|
{
|
|
|
|
case ST_9_SLIDING_ST_DOOR:
|
|
|
|
case ST_15_WARP_ELEVATOR:
|
|
|
|
case ST_16_PLATFORM_DOWN:
|
|
|
|
case ST_17_PLATFORM_UP:
|
|
|
|
case ST_18_ELEVATOR_DOWN:
|
|
|
|
case ST_19_ELEVATOR_UP:
|
|
|
|
case ST_20_CEILING_DOOR:
|
|
|
|
case ST_21_FLOOR_DOOR:
|
|
|
|
case ST_22_SPLITTING_DOOR:
|
|
|
|
case ST_23_SWINGING_DOOR:
|
|
|
|
case ST_25_SLIDING_DOOR:
|
|
|
|
case ST_26_SPLITTING_ST_DOOR:
|
|
|
|
case ST_29_TEETH_DOOR:
|
|
|
|
return true;
|
|
|
|
case 41:
|
|
|
|
return isRR();
|
|
|
|
}
|
|
|
|
return false;
|
2020-05-10 10:42:47 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-12 16:26:27 +00:00
|
|
|
int findplayer(const DDukeActor* actor, double* d)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2021-11-07 13:55:28 +00:00
|
|
|
int j, closest_player;
|
2022-09-12 16:26:27 +00:00
|
|
|
const auto s = actor->spr.pos;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
|
|
|
if (ud.multimode < 2)
|
|
|
|
{
|
2022-11-21 04:24:01 +00:00
|
|
|
if (d) *d = (ps[myconnectindex].GetActor()->getPrevPosWithOffsetZ() - s).plusZ(28).Sum();
|
2020-05-12 11:43:24 +00:00
|
|
|
return myconnectindex;
|
|
|
|
}
|
|
|
|
|
2022-09-12 16:26:27 +00:00
|
|
|
double closest = 0x7fffffff;
|
2020-05-12 11:43:24 +00:00
|
|
|
closest_player = 0;
|
|
|
|
|
|
|
|
for (j = connecthead; j >= 0; j = connectpoint2[j])
|
|
|
|
{
|
2022-11-21 04:24:01 +00:00
|
|
|
double x = (ps[j].GetActor()->getPrevPosWithOffsetZ() - s).plusZ(28).Sum();
|
2021-12-21 17:19:45 +00:00
|
|
|
if (x < closest && ps[j].GetActor()->spr.extra > 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
closest_player = j;
|
|
|
|
closest = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d) *d = closest;
|
|
|
|
return closest_player;
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-12 16:26:27 +00:00
|
|
|
int findotherplayer(int p, double* d)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2021-11-07 13:55:28 +00:00
|
|
|
int j, closest_player;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 16:26:27 +00:00
|
|
|
double closest = 0x7fffffff;
|
2020-05-12 11:43:24 +00:00
|
|
|
closest_player = p;
|
|
|
|
|
|
|
|
for (j = connecthead; j >= 0; j = connectpoint2[j])
|
2021-12-21 17:19:45 +00:00
|
|
|
if (p != j && ps[j].GetActor()->spr.extra > 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-21 04:24:01 +00:00
|
|
|
double x = (ps[j].GetActor()->getPrevPosWithOffsetZ() - ps[p].GetActor()->getPosWithOffsetZ()).Sum();
|
2020-05-12 11:43:24 +00:00
|
|
|
|
|
|
|
if (x < closest)
|
|
|
|
{
|
|
|
|
closest_player = j;
|
|
|
|
closest = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*d = closest;
|
|
|
|
return closest_player;
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-01-27 17:31:08 +00:00
|
|
|
double getanimatevalue(int type, int index)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case anim_floorz:
|
2022-09-12 17:47:07 +00:00
|
|
|
return sector[index].floorz;
|
2022-01-27 17:31:08 +00:00
|
|
|
case anim_ceilingz:
|
2022-09-12 17:47:07 +00:00
|
|
|
return sector[index].ceilingz;
|
2022-01-27 17:31:08 +00:00
|
|
|
case anim_vertexx:
|
2022-09-12 17:47:07 +00:00
|
|
|
return wall[index].pos.X;
|
2022-01-27 17:31:08 +00:00
|
|
|
case anim_vertexy:
|
2022-09-12 17:47:07 +00:00
|
|
|
return wall[index].pos.Y;
|
2022-01-27 17:31:08 +00:00
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double getanimatevalue(int i)
|
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
return getanimatevalue(animates[i].type, animates[i].target);
|
2022-01-27 17:31:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void setanimatevalue(int type, int index, double value)
|
2020-07-20 18:40:29 +00:00
|
|
|
{
|
|
|
|
static int scratch;
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case anim_floorz:
|
2022-09-12 17:47:07 +00:00
|
|
|
sector[index].setfloorz(value);
|
2022-01-27 17:31:08 +00:00
|
|
|
break;
|
2020-07-20 18:40:29 +00:00
|
|
|
case anim_ceilingz:
|
2022-09-12 17:47:07 +00:00
|
|
|
sector[index].setceilingz(value);
|
2022-01-27 17:31:08 +00:00
|
|
|
break;
|
2020-07-20 18:40:29 +00:00
|
|
|
case anim_vertexx:
|
2022-01-28 17:47:53 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
wall[index].pos.X = value;
|
2022-01-28 16:03:14 +00:00
|
|
|
wall[index].moved();
|
2022-01-27 17:31:08 +00:00
|
|
|
break;
|
2020-07-20 18:40:29 +00:00
|
|
|
case anim_vertexy:
|
2022-01-28 17:47:53 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
wall[index].pos.Y = value;
|
2022-01-28 16:03:14 +00:00
|
|
|
wall[index].moved();
|
2022-01-27 17:31:08 +00:00
|
|
|
break;
|
2020-07-20 18:40:29 +00:00
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-27 17:31:08 +00:00
|
|
|
void setanimatevalue(int i, double value)
|
2020-07-20 18:40:29 +00:00
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
return setanimatevalue(animates[i].type, animates[i].target, value);
|
2020-07-20 18:40:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
void doanimations(void)
|
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
for (int i = animates.Size() - 1; i >= 0; i--)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
double a = getanimatevalue(i);
|
2022-09-12 19:06:33 +00:00
|
|
|
double const v = animates[i].vel * TICSPERFRAME;
|
|
|
|
auto dasectp = animates[i].sect;
|
2022-12-10 09:20:01 +00:00
|
|
|
int type = animates[i].type;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 19:06:33 +00:00
|
|
|
if (a == animates[i].goal)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
StopInterpolation(animates[i].target, interptype[animates[i].type]);
|
|
|
|
|
|
|
|
animates[i] = animates.Last();
|
|
|
|
animates.Pop();
|
2021-11-18 18:20:12 +00:00
|
|
|
if (dasectp->lotag == ST_18_ELEVATOR_DOWN || dasectp->lotag == ST_19_ELEVATOR_UP)
|
2022-12-10 09:20:01 +00:00
|
|
|
if (type == anim_ceilingz)
|
2020-05-12 11:43:24 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-18 18:20:12 +00:00
|
|
|
if ((dasectp->lotag & 0xff) != ST_22_SPLITTING_DOOR)
|
2022-01-09 22:03:11 +00:00
|
|
|
callsound(dasectp, nullptr, true);
|
2020-05-12 11:43:24 +00:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-09-12 19:06:33 +00:00
|
|
|
if (v > 0) { a = min(a + v, animates[i].goal); }
|
|
|
|
else { a = max(a + v, animates[i].goal); }
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-12-10 09:20:01 +00:00
|
|
|
if (type == anim_floorz)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
for (auto p = connecthead; p >= 0; p = connectpoint2[p])
|
2021-11-21 07:56:39 +00:00
|
|
|
if (ps[p].cursector == dasectp)
|
2022-11-21 04:20:08 +00:00
|
|
|
if ((dasectp->floorz - ps[p].GetActor()->getOffsetZ()) < 64)
|
2020-10-23 15:40:58 +00:00
|
|
|
if (ps[p].GetActor()->GetOwner() != nullptr)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-20 08:14:51 +00:00
|
|
|
ps[p].GetActor()->spr.pos.Z += v;
|
2022-09-11 22:17:09 +00:00
|
|
|
ps[p].vel.Z = 0;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 18:20:12 +00:00
|
|
|
DukeSectIterator it(dasectp);
|
2020-10-23 15:40:58 +00:00
|
|
|
while (auto act = it.Next())
|
2020-10-14 19:40:15 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act->spr.statnum != STAT_EFFECTOR)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-16 05:33:17 +00:00
|
|
|
if (act->spr.statnum != STAT_PLAYER)
|
|
|
|
{
|
|
|
|
act->backupz();
|
|
|
|
act->spr.pos.Z += v;
|
|
|
|
}
|
2022-09-12 17:47:07 +00:00
|
|
|
act->floorz = dasectp->floorz + v;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-14 19:40:15 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2022-01-27 17:31:08 +00:00
|
|
|
setanimatevalue(i, a);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
int getanimationindex(int animtype, sectortype* animtargetp)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2020-05-12 11:43:24 +00:00
|
|
|
int i, j;
|
|
|
|
|
|
|
|
j = -1;
|
2022-11-15 11:03:44 +00:00
|
|
|
int animtarget = sectindex(animtargetp);
|
2022-09-12 19:06:33 +00:00
|
|
|
for (i = animates.Size() - 1; i >= 0; i--)
|
|
|
|
if (animtype == animates[i].type && animtarget == animates[i].target)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
j = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(j);
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
static int dosetanimation(sectortype* animsect, int animtype, int animtarget, double thegoal, double thevel)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
int j = -1;
|
2020-05-10 14:53:09 +00:00
|
|
|
|
2022-09-12 19:06:33 +00:00
|
|
|
for (unsigned i = 0; i < animates.Size(); i++)
|
|
|
|
if (animtype == animates[i].type && animtarget == animates[i].target)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
j = i;
|
|
|
|
break;
|
|
|
|
}
|
2020-05-10 14:53:09 +00:00
|
|
|
|
2022-09-12 19:06:33 +00:00
|
|
|
if (j == -1) j = animates.Reserve(1);
|
|
|
|
|
|
|
|
auto animval = getanimatevalue(animtype, animtarget);
|
|
|
|
animates[j].sect = animsect;
|
|
|
|
animates[j].type = animtype;
|
|
|
|
animates[j].target = animtarget;
|
|
|
|
animates[j].goal = thegoal;
|
2022-01-27 17:31:08 +00:00
|
|
|
if (thegoal >= animval)
|
2022-09-12 19:06:33 +00:00
|
|
|
animates[j].vel = thevel;
|
2020-05-12 11:43:24 +00:00
|
|
|
else
|
2022-09-12 19:06:33 +00:00
|
|
|
animates[j].vel = -thevel;
|
2020-05-10 14:53:09 +00:00
|
|
|
|
2022-09-12 19:06:33 +00:00
|
|
|
StartInterpolation(animates[j].target, interptype[animates[j].type]);
|
2020-05-12 11:43:24 +00:00
|
|
|
return(j);
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
int setanimation(sectortype* animsect, int animtype, walltype* animtarget, double thegoal, double thevel)
|
2021-11-18 17:35:59 +00:00
|
|
|
{
|
|
|
|
assert(animtype == anim_vertexx || animtype == anim_vertexy);
|
2022-11-15 11:03:44 +00:00
|
|
|
return dosetanimation(animsect, animtype, wallindex(animtarget), thegoal, thevel);
|
2021-11-18 17:35:59 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
int setanimation(sectortype* animsect, int animtype, sectortype* animtarget, double thegoal, double thevel)
|
2021-11-18 17:35:59 +00:00
|
|
|
{
|
|
|
|
assert(animtype == anim_ceilingz || animtype == anim_floorz);
|
2022-11-15 11:03:44 +00:00
|
|
|
return dosetanimation(animsect, animtype, sectindex(animtarget), thegoal, thevel);
|
2021-11-18 17:35:59 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-10-23 15:46:46 +00:00
|
|
|
bool activatewarpelevators(DDukeActor* actor, int d) //Parm = sectoreffectornum
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
auto sect = actor->sector();
|
2020-05-12 11:43:24 +00:00
|
|
|
|
|
|
|
// See if the sector exists
|
|
|
|
|
2020-10-23 15:46:46 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
DDukeActor *act2;
|
|
|
|
while ((act2 = it.Next()))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act2->spr.lotag == SE_17_WARP_ELEVATOR || (isRRRA() && act2->spr.lotag == SE_18_INCREMENTAL_SECTOR_RISE_FALL))
|
|
|
|
if (act2->spr.hitag == actor->spr.hitag)
|
2022-09-14 19:04:07 +00:00
|
|
|
if ((abs(sect->floorz - actor->temp_pos.X) > act2->spr.yint * maptoworld) ||
|
2021-11-20 23:33:17 +00:00
|
|
|
(act2->sector()->hitag == (sect->hitag - d)))
|
2020-05-12 11:43:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-10-23 15:46:46 +00:00
|
|
|
if (act2 == nullptr)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
d = 0;
|
|
|
|
return 1; // No find
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (d == 0)
|
2020-10-23 15:46:46 +00:00
|
|
|
S_PlayActorSound(ELEVATOR_OFF, actor);
|
|
|
|
else S_PlayActorSound(ELEVATOR_ON, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-14 21:28:36 +00:00
|
|
|
it.Reset(STAT_EFFECTOR);
|
2020-10-23 15:46:46 +00:00
|
|
|
while ((act2 = it.Next()))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act2->spr.lotag == SE_17_WARP_ELEVATOR || (isRRRA() && act2->spr.lotag == SE_18_INCREMENTAL_SECTOR_RISE_FALL))
|
|
|
|
if (act2->spr.hitag == actor->spr.hitag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2020-10-23 15:46:46 +00:00
|
|
|
act2->temp_data[0] = d;
|
2022-08-22 17:32:51 +00:00
|
|
|
if (act2->spr.lotag == SE_17_WARP_ELEVATOR) act2->temp_data[1] = d; //Make all check warp (only SE17, in SE18 this is a coordinate)
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:35:59 +00:00
|
|
|
static void handle_st09(sectortype* sptr, DDukeActor* actor)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
double dax, day, dax2, day2, sp;
|
2021-11-17 21:49:27 +00:00
|
|
|
walltype* wallfind[2];
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
sp = (sptr->extra >> 4) / 16.;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//first find center point by averaging all points
|
2022-09-12 17:47:07 +00:00
|
|
|
dax = 0, day = 0;
|
2022-11-15 14:24:17 +00:00
|
|
|
for (auto& wal : sptr->walls)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
dax += wal.pos.X;
|
|
|
|
day += wal.pos.Y;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2022-11-15 13:59:28 +00:00
|
|
|
dax /= sptr->walls.Size();
|
|
|
|
day /= sptr->walls.Size();
|
2020-10-23 17:05:42 +00:00
|
|
|
|
|
|
|
//find any points with either same x or same y coordinate
|
|
|
|
// as center (dax, day) - should be 2 points found.
|
2021-11-17 21:49:27 +00:00
|
|
|
wallfind[0] = nullptr;
|
|
|
|
wallfind[1] = nullptr;
|
2022-11-15 14:24:17 +00:00
|
|
|
for (auto& wal : sptr->walls)
|
2022-09-12 17:47:07 +00:00
|
|
|
// more precise checks won't work here.
|
|
|
|
if (abs(wal.pos.X - dax) <= (1 / 32.) || abs(wal.pos.Y - day) <= (1 / 32.))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-17 21:49:27 +00:00
|
|
|
if (wallfind[0] == nullptr)
|
|
|
|
wallfind[0] = &wal;
|
|
|
|
else wallfind[1] = &wal;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
for (int j = 0; j < 2; j++)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-17 21:49:27 +00:00
|
|
|
auto wal = wallfind[j];
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2021-11-17 21:49:27 +00:00
|
|
|
//find what direction door should open by averaging the
|
|
|
|
// 2 neighboring points of wallfind[0] & wallfind[1].
|
|
|
|
auto prevwall = wal - 1;
|
2022-11-15 14:44:33 +00:00
|
|
|
if (prevwall < sptr->walls.Data()) prevwall += sptr->walls.Size();
|
2021-11-17 21:49:27 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
if ((wal->pos.X == dax) && (wal->pos.Y == day))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
dax2 = ((prevwall->pos.X + wal->point2Wall()->pos.X) * 0.5) - wal->pos.X;
|
|
|
|
day2 = ((prevwall->pos.Y + wal->point2Wall()->pos.Y) * 0.5) - wal->pos.Y;
|
2020-10-23 17:05:42 +00:00
|
|
|
if (dax2 != 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
dax2 = wal->point2Wall()->point2Wall()->pos.X;
|
|
|
|
dax2 -= wal->point2Wall()->pos.X;
|
|
|
|
setanimation(sptr, anim_vertexx, wal, wal->pos.X + dax2, sp);
|
|
|
|
setanimation(sptr, anim_vertexx, prevwall, prevwall->pos.X + dax2, sp);
|
|
|
|
setanimation(sptr, anim_vertexx, wal->point2Wall(), wal->point2Wall()->pos.X + dax2, sp);
|
2021-11-18 17:35:59 +00:00
|
|
|
callsound(sptr, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
else if (day2 != 0)
|
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
day2 = wal->point2Wall()->point2Wall()->pos.Y;
|
|
|
|
day2 -= wal->point2Wall()->pos.Y;
|
|
|
|
setanimation(sptr, anim_vertexy, wal, wal->pos.Y + day2, sp);
|
|
|
|
setanimation(sptr, anim_vertexy, prevwall, prevwall->pos.Y + day2, sp);
|
|
|
|
setanimation(sptr, anim_vertexy, wal->point2Wall(), wal->point2Wall()->pos.Y + day2, sp);
|
2021-11-18 17:35:59 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
dax2 = ((prevwall->pos.X + wal->point2Wall()->pos.X) * 0.5) - wal->pos.X;
|
|
|
|
day2 = ((prevwall->pos.Y + wal->point2Wall()->pos.Y) * 0.5) - wal->pos.Y;
|
2020-10-23 17:05:42 +00:00
|
|
|
if (dax2 != 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-18 17:35:59 +00:00
|
|
|
setanimation(sptr, anim_vertexx, wal, dax, sp);
|
|
|
|
setanimation(sptr, anim_vertexx, prevwall, dax + dax2, sp);
|
|
|
|
setanimation(sptr, anim_vertexx, wal->point2Wall(), dax + dax2, sp);
|
|
|
|
callsound(sptr, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
else if (day2 != 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-18 17:35:59 +00:00
|
|
|
setanimation(sptr, anim_vertexy, wal, day, sp);
|
|
|
|
setanimation(sptr, anim_vertexy, prevwall, day + day2, sp);
|
|
|
|
setanimation(sptr, anim_vertexy, wal->point2Wall(), day + day2, sp);
|
|
|
|
callsound(sptr, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:38:09 +00:00
|
|
|
static void handle_st15(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-31 17:47:00 +00:00
|
|
|
if (!actor->isPlayer()) return;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:38:09 +00:00
|
|
|
DukeSectIterator it(sptr);
|
2020-10-23 17:08:11 +00:00
|
|
|
DDukeActor* a2;
|
|
|
|
while ((a2 = it.Next()))
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-12-01 19:54:41 +00:00
|
|
|
if (iseffector(a2) && a2->spr.lotag == ST_17_PLATFORM_UP) break;
|
2020-10-14 19:40:15 +00:00
|
|
|
}
|
2020-10-23 17:08:11 +00:00
|
|
|
if (!a2) return;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
if (actor->sector() == sptr)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2020-10-23 17:08:11 +00:00
|
|
|
if (activatewarpelevators(a2, -1))
|
|
|
|
activatewarpelevators(a2, 1);
|
|
|
|
else if (activatewarpelevators(a2, 1))
|
|
|
|
activatewarpelevators(a2, -1);
|
2020-05-12 11:43:24 +00:00
|
|
|
return;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-14 16:22:43 +00:00
|
|
|
if (sptr->floorz > a2->spr.pos.Z)
|
2020-10-23 17:08:11 +00:00
|
|
|
activatewarpelevators(a2, -1);
|
2020-10-23 17:05:42 +00:00
|
|
|
else
|
2020-10-23 17:08:11 +00:00
|
|
|
activatewarpelevators(a2, 1);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:38:09 +00:00
|
|
|
static void handle_st16(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
int i = getanimationindex(anim_floorz, sptr);
|
2021-11-17 23:29:46 +00:00
|
|
|
sectortype* sectp;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
if (i == -1)
|
|
|
|
{
|
2022-09-03 15:27:41 +00:00
|
|
|
sectp = nextsectorneighborzptr(sptr, sptr->floorz, Find_FloorDown);
|
2021-11-17 23:29:46 +00:00
|
|
|
if (sectp == nullptr)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-03 15:27:41 +00:00
|
|
|
sectp = nextsectorneighborzptr(sptr, sptr->floorz, Find_FloorUp);
|
2021-11-17 23:29:46 +00:00
|
|
|
if (sectp == nullptr) return;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2022-09-12 17:47:07 +00:00
|
|
|
setanimation(sptr, anim_floorz, sptr, sectp->floorz, sptr->extra / 256.);
|
2021-11-18 17:38:09 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
static void handle_st18(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
int i = getanimationindex(anim_floorz, sptr);
|
2020-10-23 17:05:42 +00:00
|
|
|
|
|
|
|
if (i == -1)
|
2020-10-14 21:28:36 +00:00
|
|
|
{
|
2022-09-03 15:27:41 +00:00
|
|
|
auto sectp = nextsectorneighborzptr(sptr, sptr->floorz, Find_FloorUp);
|
|
|
|
if (sectp == nullptr) sectp = nextsectorneighborzptr(sptr, sptr->floorz, Find_FloorDown);
|
2021-11-17 23:29:46 +00:00
|
|
|
if (sectp == nullptr) return;
|
2022-09-12 17:47:07 +00:00
|
|
|
double speed = sptr->extra / 256.;
|
|
|
|
setanimation(sptr, anim_floorz, sptr, sectp->floorz, speed);
|
2022-11-07 17:16:41 +00:00
|
|
|
setanimation(sptr, anim_ceilingz, sptr, sectp->floorz + sptr->ceilingz - sptr->floorz, speed);
|
2021-11-18 17:43:25 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
static void handle_st29(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
double j;
|
2020-10-23 17:05:42 +00:00
|
|
|
|
|
|
|
if (sptr->lotag & 0x8000)
|
2022-09-12 17:47:07 +00:00
|
|
|
j = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_FloorDown | Find_Safe)->floorz;
|
2020-10-23 17:05:42 +00:00
|
|
|
else
|
2022-09-12 17:47:07 +00:00
|
|
|
j = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_CeilingUp | Find_Safe)->ceilingz;
|
2020-10-23 17:05:42 +00:00
|
|
|
|
2020-10-23 17:09:27 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
while (auto act2 = it.Next())
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if ((act2->spr.lotag == 22) &&
|
|
|
|
(act2->spr.hitag == sptr->hitag))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-20 23:33:17 +00:00
|
|
|
act2->sector()->extra = -act2->sector()->extra;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-11-15 11:03:44 +00:00
|
|
|
act2->temp_data[0] = sectindex(sptr);
|
2020-10-23 17:09:27 +00:00
|
|
|
act2->temp_data[1] = 1;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag ^= 0x8000;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
setanimation(sptr, anim_ceilingz, sptr, j, sptr->extra / 256.);
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
static void handle_st20(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
double j = 0;
|
2020-10-23 17:05:42 +00:00
|
|
|
REDODOOR:
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
if (sptr->lotag & 0x8000)
|
|
|
|
{
|
2020-10-23 17:10:40 +00:00
|
|
|
DDukeActor* a2;
|
2021-11-18 17:43:25 +00:00
|
|
|
DukeSectIterator it(sptr);
|
2020-10-23 17:10:40 +00:00
|
|
|
while ((a2 = it.Next()))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
if (a2->spr.statnum == STAT_EFFECTOR && a2->spr.lotag == SE_9_DOWN_OPEN_DOOR_LIGHTS)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
j = a2->spr.pos.Z;
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-23 17:10:40 +00:00
|
|
|
if (a2 == nullptr)
|
2022-09-12 17:47:07 +00:00
|
|
|
j = sptr->floorz;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-03 15:27:41 +00:00
|
|
|
auto sectp = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_CeilingUp);
|
2020-10-23 17:05:42 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
if (sectp) j = sectp->ceilingz;
|
2020-05-12 11:43:24 +00:00
|
|
|
else
|
|
|
|
{
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag |= 32768;
|
|
|
|
goto REDODOOR;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag ^= 0x8000;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
setanimation(sptr, anim_ceilingz, sptr, j, sptr->extra / 256.);
|
2021-11-18 17:43:25 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
static void handle_st21(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
int i = getanimationindex(anim_floorz, sptr);
|
|
|
|
double j;
|
2020-10-23 17:05:42 +00:00
|
|
|
if (i >= 0)
|
|
|
|
{
|
2022-09-12 19:06:33 +00:00
|
|
|
if (animates[i].goal == sptr->ceilingz)
|
|
|
|
animates[i].goal = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_FloorDown | Find_Safe)->floorz;
|
|
|
|
else animates[i].goal = sptr->ceilingz;
|
|
|
|
j = animates[i].goal;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-28 09:35:03 +00:00
|
|
|
if (sptr->ceilingz == sptr->floorz)
|
2022-09-12 17:47:07 +00:00
|
|
|
j = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_FloorDown | Find_Safe)->floorz;
|
|
|
|
else j = sptr->ceilingz;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag ^= 0x8000;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-09-12 17:47:07 +00:00
|
|
|
if (setanimation(sptr, anim_floorz, sptr, j, sptr->extra / 256.) >= 0)
|
2021-11-18 17:43:25 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
static void handle_st22(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
int j;
|
|
|
|
double z;
|
|
|
|
double speed = sptr->extra / 256.;
|
2020-10-23 17:05:42 +00:00
|
|
|
if ((sptr->lotag & 0x8000))
|
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
z = (sptr->ceilingz + sptr->floorz) * 0.5;
|
|
|
|
j = setanimation(sptr, anim_floorz, sptr, z, speed);
|
|
|
|
j = setanimation(sptr, anim_ceilingz, sptr, z, speed);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
z = nextsectorneighborzptr(sptr, sptr->floorz, Find_FloorDown | Find_Safe)->floorz;
|
|
|
|
j = setanimation(sptr, anim_floorz, sptr, z, speed);
|
|
|
|
z = nextsectorneighborzptr(sptr, sptr->ceilingz, Find_CeilingUp | Find_Safe)->ceilingz;
|
|
|
|
j = setanimation(sptr, anim_ceilingz, sptr, z, speed);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag ^= 0x8000;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:43:25 +00:00
|
|
|
callsound(sptr, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-18 17:46:04 +00:00
|
|
|
static void handle_st23(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
|
|
|
int q = 0;
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2020-10-23 17:15:18 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
DDukeActor* act2;
|
|
|
|
while ((act2 = it.Next()))
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
if (act2->spr.lotag == SE_11_SWINGING_DOOR && act2->sector() == sptr && !act2->temp_data[4])
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-10-23 17:15:18 +00:00
|
|
|
if (!act2) return;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-20 23:33:17 +00:00
|
|
|
int l = act2->sector()->lotag & 0x8000;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:15:18 +00:00
|
|
|
if (act2)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-24 09:53:27 +00:00
|
|
|
DukeStatIterator itr(STAT_EFFECTOR);
|
2021-01-03 04:44:57 +00:00
|
|
|
|
2021-12-24 09:53:27 +00:00
|
|
|
while (auto act3 = itr.Next())
|
2021-01-03 04:44:57 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (l == (act3->sector()->lotag & 0x8000) && act3->spr.lotag == SE_11_SWINGING_DOOR && act2->spr.hitag == act3->spr.hitag && act3->temp_data[4])
|
2021-01-03 04:44:57 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-24 09:53:27 +00:00
|
|
|
itr.Reset(STAT_EFFECTOR);
|
|
|
|
while (auto act3 = itr.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (l == (act3->sector()->lotag & 0x8000) && act3->spr.lotag == SE_11_SWINGING_DOOR && act2->spr.hitag == act3->spr.hitag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-20 23:33:17 +00:00
|
|
|
if (act3->sector()->lotag & 0x8000) act3->sector()->lotag &= 0x7fff;
|
|
|
|
else act3->sector()->lotag |= 0x8000;
|
2020-10-23 17:15:18 +00:00
|
|
|
act3->temp_data[4] = 1;
|
|
|
|
act3->temp_data[3] = -act3->temp_data[3];
|
2020-10-23 17:05:42 +00:00
|
|
|
if (q == 0)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-18 17:46:04 +00:00
|
|
|
callsound(sptr, act3);
|
2020-10-23 17:05:42 +00:00
|
|
|
q = 1;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-14 21:28:36 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:46:04 +00:00
|
|
|
static void handle_st25(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2020-10-23 17:16:39 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
DDukeActor* act2;
|
|
|
|
while ((act2 = it.Next()))
|
2020-10-14 21:28:36 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
if (act2->spr.lotag == 15 && act2->sector() == sptr)
|
2020-10-23 17:16:39 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2020-10-23 17:16:39 +00:00
|
|
|
if (act2 == nullptr)
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
it.Reset(STAT_EFFECTOR);
|
2020-10-23 17:16:39 +00:00
|
|
|
while (auto act3 = it.Next())
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act3->spr.hitag == act2->spr.hitag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act3->spr.lotag == 15)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-20 23:33:17 +00:00
|
|
|
act3->sector()->lotag ^= 0x8000; // Toggle the open or close
|
2022-11-25 12:13:50 +00:00
|
|
|
act3->spr.Angles.Yaw += DAngle180;
|
2021-11-20 23:33:17 +00:00
|
|
|
if (act3->temp_data[4]) callsound(act3->sector(), act3);
|
|
|
|
callsound(act3->sector(), act3);
|
|
|
|
if (act3->sector()->lotag & 0x8000) act3->temp_data[4] = 1;
|
2020-10-23 17:16:39 +00:00
|
|
|
else act3->temp_data[4] = 2;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-14 21:28:36 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:46:04 +00:00
|
|
|
static void handle_st27(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2020-10-23 17:17:30 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
while (auto act2 = it.Next())
|
2020-10-14 21:28:36 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
if ((act2->spr.lotag & 0xff) == 20 && act2->sector() == sptr) //Bridge
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
|
2021-11-18 17:46:04 +00:00
|
|
|
sptr->lotag ^= 0x8000;
|
|
|
|
if (sptr->lotag & 0x8000) //OPENING
|
2020-10-23 17:17:30 +00:00
|
|
|
act2->temp_data[0] = 1;
|
|
|
|
else act2->temp_data[0] = 2;
|
2021-11-18 17:46:04 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-14 21:28:36 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:46:04 +00:00
|
|
|
static void handle_st28(sectortype* sptr, DDukeActor* actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
|
|
|
//activate the rest of them
|
2020-10-23 17:19:30 +00:00
|
|
|
int j = -1;
|
2021-11-18 17:46:04 +00:00
|
|
|
DukeSectIterator it(sptr);
|
2020-10-23 17:19:30 +00:00
|
|
|
while (auto a2 = it.Next())
|
2020-10-14 19:40:15 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (a2->spr.statnum == 3 && (a2->spr.lotag & 0xff) == 21)
|
2020-10-23 17:19:30 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
j = a2->spr.hitag;
|
2020-10-23 17:05:42 +00:00
|
|
|
break; //Found it
|
2020-10-23 17:19:30 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:19:30 +00:00
|
|
|
if (j == -1) return;
|
|
|
|
DukeStatIterator it1(STAT_EFFECTOR);
|
|
|
|
while (auto act3 = it.Next())
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if ((act3->spr.lotag & 0xff) == 21 && !act3->temp_data[0] &&
|
|
|
|
(act3->spr.hitag) == j)
|
2020-10-23 17:19:30 +00:00
|
|
|
act3->temp_data[0] = 1;
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
2021-11-18 17:46:04 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2021-11-18 17:51:19 +00:00
|
|
|
void operatesectors(sectortype* sptr, DDukeActor *actor)
|
2020-10-23 17:05:42 +00:00
|
|
|
{
|
2021-11-17 22:31:08 +00:00
|
|
|
int j=0;
|
2020-10-23 17:05:42 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (sptr->lotag & (0x3fff))
|
|
|
|
{
|
|
|
|
|
|
|
|
case 41:
|
|
|
|
if (isRR()) operatejaildoors(sptr->hitag);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
if (!isRR()) break;
|
2022-11-15 14:24:17 +00:00
|
|
|
for (auto& wal : sptr->walls)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-09-12 17:47:07 +00:00
|
|
|
setanimation(sptr, anim_vertexx, &wal, wal.pos.X + 64, 1 / 4.);
|
|
|
|
if (wal.twoSided()) setanimation(sptr, anim_vertexx, wal.nextWall(), wal.nextWall()->pos.X + 64, 1 / 4.);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ST_30_ROTATE_RISE_BRIDGE:
|
2020-10-23 17:20:46 +00:00
|
|
|
{
|
2021-12-05 23:50:33 +00:00
|
|
|
auto act = barrier_cast<DDukeActor*>(sptr->hitagactor);
|
2020-11-04 18:15:44 +00:00
|
|
|
if (!act) break;
|
2022-09-14 21:30:10 +00:00
|
|
|
if (act->tempval == 0 || act->tempval == 256) callsound(sptr, actor);
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act->spr.extra == 1) act->spr.extra = 3;
|
|
|
|
else act->spr.extra = 1;
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
2020-10-23 17:20:46 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
|
|
|
|
case ST_31_TWO_WAY_TRAIN:
|
2020-10-23 17:20:46 +00:00
|
|
|
{
|
2021-12-05 23:50:33 +00:00
|
|
|
auto act = barrier_cast<DDukeActor*>(sptr->hitagactor);
|
2020-11-04 18:15:44 +00:00
|
|
|
if (!act) break;
|
2020-10-23 17:20:46 +00:00
|
|
|
if (act->temp_data[4] == 0)
|
|
|
|
act->temp_data[4] = 1;
|
2020-10-23 17:05:42 +00:00
|
|
|
|
2021-11-18 17:51:19 +00:00
|
|
|
callsound(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
break;
|
2020-10-23 17:20:46 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
case ST_26_SPLITTING_ST_DOOR: //The split doors
|
2022-09-12 17:47:07 +00:00
|
|
|
i = getanimationindex(anim_ceilingz, sptr);
|
2020-10-23 17:05:42 +00:00
|
|
|
if (i == -1) //if the door has stopped
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2020-10-23 17:05:42 +00:00
|
|
|
haltsoundhack = 1;
|
|
|
|
sptr->lotag &= 0xff00;
|
|
|
|
sptr->lotag |= ST_22_SPLITTING_DOOR;
|
2021-11-18 17:51:19 +00:00
|
|
|
operatesectors(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag &= 0xff00;
|
|
|
|
sptr->lotag |= ST_9_SLIDING_ST_DOOR;
|
2021-11-18 17:51:19 +00:00
|
|
|
operatesectors(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
sptr->lotag &= 0xff00;
|
|
|
|
sptr->lotag |= ST_26_SPLITTING_ST_DOOR;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2020-10-23 17:05:42 +00:00
|
|
|
case ST_9_SLIDING_ST_DOOR:
|
2021-11-18 17:35:59 +00:00
|
|
|
handle_st09(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_15_WARP_ELEVATOR://Warping elevators
|
2021-11-18 17:38:09 +00:00
|
|
|
handle_st15(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_16_PLATFORM_DOWN:
|
|
|
|
case ST_17_PLATFORM_UP:
|
2021-11-18 17:38:09 +00:00
|
|
|
handle_st16(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_18_ELEVATOR_DOWN:
|
|
|
|
case ST_19_ELEVATOR_UP:
|
2021-11-18 17:43:25 +00:00
|
|
|
handle_st18(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_29_TEETH_DOOR:
|
2021-11-18 17:43:25 +00:00
|
|
|
handle_st29(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
case ST_20_CEILING_DOOR:
|
2021-11-18 17:43:25 +00:00
|
|
|
handle_st20(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_21_FLOOR_DOOR:
|
2021-11-18 17:43:25 +00:00
|
|
|
handle_st21(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_22_SPLITTING_DOOR:
|
2021-11-18 17:43:25 +00:00
|
|
|
handle_st22(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_23_SWINGING_DOOR: //Swingdoor
|
2021-11-18 17:46:04 +00:00
|
|
|
handle_st23(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_25_SLIDING_DOOR: //Subway type sliding doors
|
|
|
|
{
|
2021-11-18 17:46:04 +00:00
|
|
|
handle_st25(sptr, actor);
|
2020-05-12 11:43:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-10-23 17:05:42 +00:00
|
|
|
case ST_27_STRETCH_BRIDGE: //Extended bridge
|
2021-11-18 17:46:04 +00:00
|
|
|
handle_st27(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case ST_28_DROP_FLOOR:
|
2021-11-18 17:46:04 +00:00
|
|
|
handle_st28(sptr, actor);
|
2020-10-23 17:05:42 +00:00
|
|
|
return;
|
2020-10-14 19:40:15 +00:00
|
|
|
}
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-11-19 14:40:35 +00:00
|
|
|
void operateactivators(int low, player_struct* plr)
|
2020-05-10 14:53:09 +00:00
|
|
|
{
|
2020-05-12 11:43:24 +00:00
|
|
|
int i, j, k;
|
2021-11-06 20:53:15 +00:00
|
|
|
Cycler * p;
|
2020-05-12 11:43:24 +00:00
|
|
|
walltype* wal;
|
|
|
|
|
2022-11-20 13:13:11 +00:00
|
|
|
for (i = cyclers.Size() - 1; i >= 0; i--)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-06 20:53:15 +00:00
|
|
|
p = &cyclers[i];
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-06 20:53:15 +00:00
|
|
|
|
|
|
|
if (p->hitag == low)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-18 19:17:47 +00:00
|
|
|
auto sect = p->sector;
|
2021-11-06 20:53:15 +00:00
|
|
|
p->state = !p->state;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-06 20:53:15 +00:00
|
|
|
sect->floorshade = sect->ceilingshade = (int8_t)p->shade2;
|
2022-11-15 14:44:33 +00:00
|
|
|
wal = sect->walls.Data();
|
2022-11-15 13:59:28 +00:00
|
|
|
for (j = sect->walls.Size(); j > 0; j--, wal++)
|
2021-11-06 20:53:15 +00:00
|
|
|
wal->shade = (int8_t)p->shade2;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
k = -1;
|
2020-10-23 17:35:59 +00:00
|
|
|
DukeStatIterator it(STAT_ACTIVATOR);
|
|
|
|
while (auto act = it.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act->spr.lotag == low)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-20 11:43:24 +00:00
|
|
|
if (islockedactivator(act))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-20 23:33:17 +00:00
|
|
|
act->sector()->lotag ^= 16384;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-11-19 14:40:35 +00:00
|
|
|
if (plr)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-20 23:33:17 +00:00
|
|
|
if (act->sector()->lotag & 16384)
|
2022-11-19 14:40:35 +00:00
|
|
|
FTA(4, plr);
|
|
|
|
else FTA(8, plr);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
switch (act->spr.hitag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
2022-08-28 09:35:03 +00:00
|
|
|
if (act->sector()->floorz != act->sector()->ceilingz)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2022-08-28 09:35:03 +00:00
|
|
|
if (act->sector()->floorz == act->sector()->ceilingz)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-20 23:33:17 +00:00
|
|
|
if (act->sector()->lotag < 3)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-24 09:53:27 +00:00
|
|
|
DukeSectIterator itr(act->sector());
|
|
|
|
while (auto a2 = itr.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (a2->spr.statnum == 3) switch (a2->spr.lotag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
|
|
|
if (isRRRA()) break;
|
2021-11-14 11:25:25 +00:00
|
|
|
[[fallthrough]];
|
2020-05-12 11:43:24 +00:00
|
|
|
case SE_36_PROJ_SHOOTER:
|
|
|
|
case SE_31_FLOOR_RISE_FALL:
|
|
|
|
case SE_32_CEILING_RISE_FALL:
|
2020-10-23 17:35:59 +00:00
|
|
|
a2->temp_data[0] = 1 - a2->temp_data[0];
|
2021-11-20 23:33:17 +00:00
|
|
|
callsound(act->sector(), a2);
|
2020-05-12 11:43:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-09 22:03:11 +00:00
|
|
|
if (k == -1 && (act->sector()->lotag & 0xff) == SE_22_TEETH_DOOR)
|
2021-11-20 23:33:17 +00:00
|
|
|
k = callsound(act->sector(), act);
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-20 23:33:17 +00:00
|
|
|
operatesectors(act->sector(), act);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-20 10:58:19 +00:00
|
|
|
operaterespawns(low);
|
2020-05-10 14:53:09 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 16:05:36 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void operatemasterswitches(int low)
|
|
|
|
{
|
2020-10-23 17:35:59 +00:00
|
|
|
DukeStatIterator it(STAT_STANDABLE);
|
|
|
|
while (auto act2 = it.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-11-19 08:02:40 +00:00
|
|
|
if (ismasterswitch(act2) && act2->spr.lotag == low && act2->spr.yint == 0)
|
2022-11-19 09:58:35 +00:00
|
|
|
{
|
2022-09-01 16:15:52 +00:00
|
|
|
act2->spr.yint = 1;
|
2022-11-19 09:58:35 +00:00
|
|
|
}
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
2020-05-10 16:05:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-10-23 18:02:57 +00:00
|
|
|
void operateforcefields_common(DDukeActor *effector, int low, const std::initializer_list<int> &tiles)
|
2020-05-10 16:05:36 +00:00
|
|
|
{
|
2021-11-17 23:30:37 +00:00
|
|
|
for (int p = numanimwalls-1; p >= 0; p--)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-17 23:30:37 +00:00
|
|
|
auto wal = animwall[p].wall;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2021-11-17 21:50:56 +00:00
|
|
|
if (low == wal->lotag || low == -1)
|
|
|
|
if (isIn(wal->overpicnum, tiles))
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
|
|
|
animwall[p].tag = 0;
|
|
|
|
|
2021-11-17 21:50:56 +00:00
|
|
|
if (wal->cstat)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-11-17 21:50:56 +00:00
|
|
|
wal->cstat = 0;
|
2020-05-12 11:43:24 +00:00
|
|
|
|
2022-12-05 10:27:25 +00:00
|
|
|
if (effector && iseffector(effector) && effector->spr.lotag == SE_30_TWO_WAY_TRAIN)
|
2021-11-17 21:50:56 +00:00
|
|
|
wal->lotag = 0;
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
else
|
2021-12-18 14:16:31 +00:00
|
|
|
wal->cstat = (CSTAT_WALL_BLOCK | CSTAT_WALL_ALIGN_BOTTOM | CSTAT_WALL_MASKED | CSTAT_WALL_BLOCK_HITSCAN);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-10 16:05:36 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 18:59:38 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-12-05 10:27:25 +00:00
|
|
|
void checkhitwall(DDukeActor* spr, walltype* wal, const DVector3& pos)
|
2020-05-10 18:59:38 +00:00
|
|
|
{
|
2022-12-05 10:27:25 +00:00
|
|
|
if (wal->overpicnum == TILE_MIRROR && actorflag(spr, SFLAG2_BREAKMIRRORS))
|
|
|
|
{
|
|
|
|
lotsofglass(spr, wal, 70);
|
|
|
|
wal->cstat &= ~CSTAT_WALL_MASKED;
|
|
|
|
wal->overpicnum = TILE_MIRRORBROKE;
|
|
|
|
wal->portalflags = 0;
|
|
|
|
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto handler = [=](const BreakWallRec* data, int16_t* pic)
|
|
|
|
{
|
|
|
|
if (!data->handler)
|
|
|
|
{
|
|
|
|
*pic = data->brokentex;
|
|
|
|
S_PlayActorSound(data->breaksound, spr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VMValue args[7] = { wal, data->brokentex, data->breaksound.index(), spr, pos.X, pos.Y, pos.Z };
|
|
|
|
VMCall(data->handler, args, 7, nullptr, 0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (wal->twoSided() && wal->nextSector()->floorz > pos.Z && wal->nextSector()->floorz - wal->nextSector()->ceilingz)
|
|
|
|
{
|
|
|
|
auto data = breakWallMap.CheckKey(wal->overpicnum);
|
|
|
|
if (data && (data->flags & 1) && (!(data->flags & 2) || wal->cstat & CSTAT_WALL_MASKED))
|
|
|
|
{
|
|
|
|
handler(data, &wal->overpicnum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto data = breakWallMap.CheckKey(wal->picnum);
|
|
|
|
if (data && !(data->flags & 1))
|
|
|
|
{
|
|
|
|
handler(data, &wal->picnum);
|
|
|
|
}
|
2020-05-10 18:59:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-12-05 14:29:45 +00:00
|
|
|
bool checkhitceiling(sectortype* sectp)
|
|
|
|
{
|
|
|
|
auto data = breakCeilingMap.CheckKey(sectp->ceilingpicnum);
|
|
|
|
if (data && !(data->flags & 1))
|
|
|
|
{
|
|
|
|
if (!data->handler)
|
|
|
|
{
|
|
|
|
sectp->ceilingpicnum = data->brokentex;
|
|
|
|
S_PlayActorSound(data->breaksound, ps[screenpeek].GetActor()); // this is nonsense but what the original code did.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VMValue args[7] = { sectp, data->brokentex, data->breaksound.index() };
|
|
|
|
VMCall(data->handler, args, 3, nullptr, 0);
|
|
|
|
}
|
|
|
|
if (data->flags & 1)
|
|
|
|
{
|
|
|
|
if (!sectp->hitag)
|
|
|
|
{
|
|
|
|
DukeSectIterator it(sectp);
|
|
|
|
while (auto act = it.Next())
|
|
|
|
{
|
|
|
|
if (iseffector(act) && act->spr.lotag == SE_12_LIGHT_SWITCH)
|
|
|
|
{
|
|
|
|
DukeStatIterator it1(STAT_EFFECTOR);
|
|
|
|
while (auto act2 = it1.Next())
|
|
|
|
{
|
|
|
|
if (act2->spr.hitag == act->spr.hitag)
|
|
|
|
act2->temp_data[3] = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int j = krand() & 1;
|
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
while (auto act = it.Next())
|
|
|
|
{
|
|
|
|
if (act->spr.hitag == (sectp->hitag) && act->spr.lotag == SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT)
|
|
|
|
{
|
|
|
|
act->temp_data[2] = j;
|
|
|
|
act->temp_data[4] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (data->flags & 2)
|
|
|
|
{
|
|
|
|
ceilingglass(ps[myconnectindex].GetActor(), sectp, 10);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-05-10 18:59:38 +00:00
|
|
|
void allignwarpelevators(void)
|
|
|
|
{
|
2020-10-23 18:02:57 +00:00
|
|
|
DukeStatIterator it(STAT_EFFECTOR);
|
|
|
|
while (auto act = it.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if (act->spr.lotag == SE_17_WARP_ELEVATOR && act->spr.shade > 16)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2020-10-23 18:02:57 +00:00
|
|
|
DukeStatIterator it1(STAT_EFFECTOR);
|
|
|
|
while (auto act2 = it1.Next())
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2021-12-21 17:19:45 +00:00
|
|
|
if ((act2->spr.lotag) == SE_17_WARP_ELEVATOR && act != act2 && act->spr.hitag == act2->spr.hitag)
|
2020-05-12 11:43:24 +00:00
|
|
|
{
|
2022-10-09 07:31:51 +00:00
|
|
|
act2->sector()->setfloorz(act->sector()->floorz);
|
|
|
|
act2->sector()->setceilingz(act->sector()->ceilingz);
|
2020-05-12 11:43:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-10 18:59:38 +00:00
|
|
|
}
|
2020-05-10 16:05:36 +00:00
|
|
|
|
2020-07-06 00:05:31 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-09-08 11:16:27 +00:00
|
|
|
void moveclouds(double interpfrac)
|
2020-07-06 00:05:31 +00:00
|
|
|
{
|
2020-10-23 17:05:42 +00:00
|
|
|
// The math here is very messy.. :(
|
2022-09-08 11:16:27 +00:00
|
|
|
int myclock = interpfrac < 0.5 ? PlayClock-2 : PlayClock;
|
2020-08-31 17:22:21 +00:00
|
|
|
if (myclock > cloudclock || myclock < (cloudclock - 7))
|
2020-07-06 00:05:31 +00:00
|
|
|
{
|
2020-08-31 17:22:21 +00:00
|
|
|
cloudclock = myclock + 6;
|
2020-07-06 00:05:31 +00:00
|
|
|
|
|
|
|
// cloudx/y were an array, but all entries were always having the same value so a single pair is enough.
|
2022-11-25 11:30:40 +00:00
|
|
|
cloudx += (float)ps[screenpeek].GetActor()->spr.Angles.Yaw.Cos() * 0.5f;
|
|
|
|
cloudy += (float)ps[screenpeek].GetActor()->spr.Angles.Yaw.Sin() * 0.5f;
|
2020-07-06 00:05:31 +00:00
|
|
|
for (int i = 0; i < numclouds; i++)
|
|
|
|
{
|
2022-08-03 13:50:27 +00:00
|
|
|
// no clamping here!
|
|
|
|
clouds[i]->ceilingxpan_ = cloudx;
|
|
|
|
clouds[i]->ceilingypan_ = cloudy;
|
2021-11-17 23:04:52 +00:00
|
|
|
clouds[i]->exflags |= SECTOREX_CLOUDSCROLL;
|
2020-07-06 00:05:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-10 14:53:09 +00:00
|
|
|
|
2020-05-10 10:42:47 +00:00
|
|
|
|
|
|
|
END_DUKE_NS
|