2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#include "names2.h"
|
|
|
|
#include "panel.h"
|
|
|
|
#include "tags.h"
|
|
|
|
#include "sector.h"
|
|
|
|
#include "ai.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "game.h"
|
2020-05-01 11:29:12 +00:00
|
|
|
#include "interpso.h"
|
2019-03-21 02:24:19 +00:00
|
|
|
#include "network.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "sprite.h"
|
2020-08-05 22:18:45 +00:00
|
|
|
#include "misc.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "weapon.h"
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void DoTrack(SECTOR_OBJECTp sop, short locktics, int *nx, int *ny);
|
2015-05-19 21:54:34 +00:00
|
|
|
void DoAutoTurretObject(SECTOR_OBJECTp sop);
|
|
|
|
void DoTornadoObject(SECTOR_OBJECTp sop);
|
2021-11-02 17:56:26 +00:00
|
|
|
int PickJumpSpeed(DSWActor*, int pix_height);
|
2021-11-01 20:14:05 +00:00
|
|
|
DSWActor* FindNearSprite(DSWActor, short);
|
2019-10-09 17:58:09 +00:00
|
|
|
ANIMATOR NinjaJumpActionFunc;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#define ACTOR_STD_JUMP (-384)
|
|
|
|
int GlobSpeedSO;
|
|
|
|
|
|
|
|
// determine if moving down the track will get you closer to the player
|
2021-11-05 23:37:16 +00:00
|
|
|
short TrackTowardPlayer(DSWActor* actor, TRACKp t, TRACK_POINTp start_point)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
auto sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp end_point;
|
|
|
|
int end_dist, start_dist;
|
|
|
|
|
|
|
|
// determine which end of the Track we are starting from
|
|
|
|
if (start_point == t->TrackPoint)
|
|
|
|
{
|
|
|
|
end_point = t->TrackPoint + t->NumPoints - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end_point = t->TrackPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
end_dist = Distance(end_point->x, end_point->y, sp->x, sp->y);
|
|
|
|
start_dist = Distance(start_point->x, start_point->y, sp->x, sp->y);
|
|
|
|
|
|
|
|
if (end_dist < start_dist)
|
|
|
|
{
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
short TrackStartCloserThanEnd(DSWActor* actor, TRACKp t, TRACK_POINTp start_point)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
TRACK_POINTp end_point;
|
|
|
|
int end_dist, start_dist;
|
|
|
|
|
|
|
|
// determine which end of the Track we are starting from
|
|
|
|
if (start_point == t->TrackPoint)
|
|
|
|
{
|
|
|
|
end_point = t->TrackPoint + t->NumPoints - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end_point = t->TrackPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
end_dist = Distance(end_point->x, end_point->y, sp->x, sp->y);
|
|
|
|
start_dist = Distance(start_point->x, start_point->y, sp->x, sp->y);
|
|
|
|
|
|
|
|
if (start_dist < end_dist)
|
|
|
|
{
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
!AIC - Looks at endpoints to figure direction of the track and the closest
|
|
|
|
point to the sprite.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2021-11-25 17:16:56 +00:00
|
|
|
short ActorFindTrack(DSWActor* actor, int8_t player_dir, int track_type, int* track_point_num, int* track_dir)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 10:47:52 +00:00
|
|
|
USERp u = actor->u();
|
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
int dist, near_dist = 999999, zdiff;
|
|
|
|
|
2021-11-21 20:45:12 +00:00
|
|
|
int i;
|
2021-11-25 17:16:56 +00:00
|
|
|
short end_point[2] = { 0,0 };
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
TRACKp t, near_track = nullptr;
|
|
|
|
TRACK_POINTp tp, near_tp = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
TOWARD_PLAYER = 1,
|
|
|
|
AWAY_FROM_PLAYER = -1
|
|
|
|
};
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// look at all tracks finding the closest endpoint
|
|
|
|
for (t = &Track[0]; t < &Track[MAX_TRACKS]; t++)
|
|
|
|
{
|
|
|
|
tp = t->TrackPoint;
|
|
|
|
|
|
|
|
// Skip if high tag is not ONE of the track type we are looking for
|
|
|
|
if (!TEST(t->ttflags, track_type))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip if already someone on this track
|
|
|
|
if (TEST(t->flags, TF_TRACK_OCCUPIED))
|
|
|
|
{
|
|
|
|
//DSPRINTF(ds,"occupied!");
|
|
|
|
MONO_PRINT(ds);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (track_type)
|
|
|
|
{
|
|
|
|
case BIT(TT_DUCK_N_SHOOT):
|
|
|
|
{
|
|
|
|
if (!u->ActorActionSet->Duck)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
end_point[1] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for ladders only look at first track point
|
|
|
|
case BIT(TT_LADDER):
|
|
|
|
{
|
|
|
|
if (!u->ActorActionSet->Climb)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
end_point[1] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case BIT(TT_JUMP_UP):
|
|
|
|
case BIT(TT_JUMP_DOWN):
|
|
|
|
{
|
|
|
|
if (!u->ActorActionSet->Jump)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
end_point[1] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case BIT(TT_TRAVERSE):
|
|
|
|
{
|
|
|
|
if (!u->ActorActionSet->Crawl || !u->ActorActionSet->Jump)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// look at end point also
|
|
|
|
default:
|
|
|
|
end_point[1] = t->NumPoints - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
zdiff = Z(16);
|
|
|
|
|
|
|
|
// Look at both track end points to see wich is closer
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
tp = t->TrackPoint + end_point[i];
|
|
|
|
|
|
|
|
dist = Distance(tp->x, tp->y, sp->x, sp->y);
|
|
|
|
|
|
|
|
if (dist < 15000 && dist < near_dist)
|
|
|
|
{
|
|
|
|
// make sure track start is on approximate z level - skip if
|
|
|
|
// not
|
|
|
|
if (labs(sp->z - tp->z) > zdiff)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine if the track leads in the direction we want it
|
|
|
|
// to
|
|
|
|
if (player_dir == TOWARD_PLAYER)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
if (!TrackTowardPlayer(u->targetActor, t, tp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (player_dir == AWAY_FROM_PLAYER)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
if (TrackTowardPlayer(u->targetActor, t, tp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure the start distance is closer than the end
|
|
|
|
// distance
|
2021-11-05 23:37:16 +00:00
|
|
|
if (!TrackStartCloserThanEnd(actor, t, tp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
near_dist = dist;
|
|
|
|
near_track = t;
|
|
|
|
near_tp = tp;
|
|
|
|
|
|
|
|
*track_point_num = end_point[i];
|
|
|
|
*track_dir = i ? -1 : 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-25 17:16:56 +00:00
|
|
|
auto track_sect = §or[0];
|
2015-05-19 21:54:34 +00:00
|
|
|
if (near_dist < 15000)
|
|
|
|
{
|
|
|
|
// get the sector number of the point
|
2021-11-07 17:55:55 +00:00
|
|
|
updatesector(near_tp->x, near_tp->y, &track_sect);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// if can see the point, return the track number
|
2021-11-25 17:16:56 +00:00
|
|
|
if (track_sect && FAFcansee(sp->x, sp->y, sp->z - Z(16), sp->sector(), near_tp->x, near_tp->y, track_sect->floorz - Z(32), track_sect))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-05-12 14:50:20 +00:00
|
|
|
return short(near_track - &Track[0]);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-25 17:16:56 +00:00
|
|
|
return -1;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void NextTrackPoint(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
sop->point += sop->dir;
|
|
|
|
|
|
|
|
if (sop->point > Track[sop->track].NumPoints - 1)
|
|
|
|
sop->point = 0;
|
|
|
|
|
|
|
|
if (sop->point < 0)
|
|
|
|
sop->point = Track[sop->track].NumPoints - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void NextActorTrackPoint(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->point += u->track_dir;
|
|
|
|
|
|
|
|
if (u->point > Track[u->track].NumPoints - 1)
|
|
|
|
u->point = 0;
|
|
|
|
|
|
|
|
if (u->point < 0)
|
|
|
|
u->point = Track[u->track].NumPoints - 1;
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
void TrackAddPoint(TRACKp t, TRACK_POINTp tp, DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 20:53:24 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tpoint = (tp + t->NumPoints);
|
|
|
|
|
|
|
|
tpoint->x = sp->x;
|
|
|
|
tpoint->y = sp->y;
|
|
|
|
tpoint->z = sp->z;
|
|
|
|
tpoint->ang = sp->ang;
|
|
|
|
tpoint->tag_low = sp->lotag;
|
|
|
|
tpoint->tag_high = sp->hitag;
|
|
|
|
|
|
|
|
t->NumPoints++;
|
|
|
|
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
DSWActor* TrackClonePoint(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
SPRITEp sp = &actor->s(), np;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 18:13:20 +00:00
|
|
|
auto actorNew = InsertActor(sp->sector(), sp->statnum);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-04 23:03:08 +00:00
|
|
|
np = &actorNew->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
np->cstat = np->extra = 0;
|
|
|
|
np->x = sp->x;
|
|
|
|
np->y = sp->y;
|
|
|
|
np->z = sp->z;
|
|
|
|
np->ang = sp->ang;
|
|
|
|
np->lotag = sp->lotag;
|
|
|
|
np->hitag = sp->hitag;
|
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
return actorNew;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QuickJumpSetup(short stat, short lotag, short type)
|
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
int ndx;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tp;
|
|
|
|
TRACKp t;
|
|
|
|
SPRITEp nsp;
|
2021-11-05 23:20:27 +00:00
|
|
|
DSWActor* start_sprite,* end_sprite;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// make short quick jump tracks
|
2021-11-05 23:20:27 +00:00
|
|
|
SWStatIterator it(stat);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// find an open track
|
|
|
|
for (ndx = 0; ndx < MAX_TRACKS; ndx++)
|
|
|
|
{
|
|
|
|
if (Track[ndx].NumPoints == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(ndx < MAX_TRACKS);
|
|
|
|
|
2020-12-01 15:53:29 +00:00
|
|
|
Track[ndx].SetTrackSize(4);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tp = Track[ndx].TrackPoint;
|
|
|
|
t = &Track[ndx];
|
|
|
|
|
|
|
|
// set track type
|
|
|
|
SET(t->ttflags, BIT(type));
|
|
|
|
t->flags = 0;
|
|
|
|
|
|
|
|
// clone point
|
2021-11-05 23:20:27 +00:00
|
|
|
end_sprite = TrackClonePoint(actor);
|
|
|
|
start_sprite = TrackClonePoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add start point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &start_sprite->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_START;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, start_sprite);
|
|
|
|
|
|
|
|
// add jump point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &actor->s();
|
2021-01-04 11:36:54 +00:00
|
|
|
nsp->x += MulScale(64, bcos(nsp->ang), 14);
|
|
|
|
nsp->y += MulScale(64, bsin(nsp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = lotag;
|
2021-11-05 23:20:27 +00:00
|
|
|
TrackAddPoint(t, tp, actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add end point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &end_sprite->s();
|
2021-01-04 11:36:54 +00:00
|
|
|
nsp->x += MulScale(2048, bcos(nsp->ang), 14);
|
|
|
|
nsp->y += MulScale(2048, bsin(nsp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_END;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, end_sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QuickScanSetup(short stat, short lotag, short type)
|
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
int ndx;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tp;
|
|
|
|
TRACKp t;
|
|
|
|
SPRITEp nsp;
|
2021-11-05 23:20:27 +00:00
|
|
|
DSWActor* start_sprite,* end_sprite;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// make short quick jump tracks
|
2021-11-05 23:20:27 +00:00
|
|
|
SWStatIterator it(stat);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
// find an open track
|
|
|
|
for (ndx = 0; ndx < MAX_TRACKS; ndx++)
|
|
|
|
{
|
|
|
|
if (Track[ndx].NumPoints == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(ndx < MAX_TRACKS);
|
|
|
|
|
|
|
|
// save space for 3 points
|
2020-12-01 15:53:29 +00:00
|
|
|
Track[ndx].SetTrackSize(4);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tp = Track[ndx].TrackPoint;
|
|
|
|
t = &Track[ndx];
|
|
|
|
|
|
|
|
// set track type
|
|
|
|
SET(t->ttflags, BIT(type));
|
|
|
|
t->flags = 0;
|
|
|
|
|
|
|
|
// clone point
|
2021-11-05 23:20:27 +00:00
|
|
|
end_sprite = TrackClonePoint(actor);
|
|
|
|
start_sprite = TrackClonePoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add start point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &start_sprite->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_START;
|
|
|
|
nsp->hitag = 0;
|
2021-01-04 11:36:54 +00:00
|
|
|
nsp->x += MulScale(64, -bcos(nsp->ang), 14);
|
|
|
|
nsp->y += MulScale(64, -bsin(nsp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
TrackAddPoint(t, tp, start_sprite);
|
|
|
|
|
|
|
|
// add jump point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = lotag;
|
2021-11-05 23:20:27 +00:00
|
|
|
TrackAddPoint(t, tp, actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add end point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &end_sprite->s();
|
2021-01-04 11:36:54 +00:00
|
|
|
nsp->x += MulScale(64, bcos(nsp->ang), 14);
|
|
|
|
nsp->y += MulScale(64, bsin(nsp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_END;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, end_sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickExitSetup(short stat, short type)
|
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
int ndx;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tp;
|
|
|
|
TRACKp t;
|
|
|
|
SPRITEp nsp;
|
2021-11-05 23:20:27 +00:00
|
|
|
DSWActor* start_sprite,* end_sprite;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
SWStatIterator it(stat);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// find an open track
|
|
|
|
for (ndx = 0; ndx < MAX_TRACKS; ndx++)
|
|
|
|
{
|
|
|
|
if (Track[ndx].NumPoints == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(ndx < MAX_TRACKS);
|
|
|
|
|
|
|
|
// save space for 3 points
|
2020-12-01 15:53:29 +00:00
|
|
|
Track[ndx].SetTrackSize(4);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tp = Track[ndx].TrackPoint;
|
|
|
|
t = &Track[ndx];
|
|
|
|
|
|
|
|
// set track type
|
|
|
|
SET(t->ttflags, BIT(type));
|
|
|
|
t->flags = 0;
|
|
|
|
|
|
|
|
// clone point
|
2021-11-05 23:20:27 +00:00
|
|
|
end_sprite = TrackClonePoint(actor);
|
|
|
|
start_sprite = TrackClonePoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add start point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &start_sprite->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_START;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, start_sprite);
|
|
|
|
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add end point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &end_sprite->s();
|
2021-01-04 11:36:54 +00:00
|
|
|
nsp->x += MulScale(1024, bcos(nsp->ang), 14);
|
|
|
|
nsp->y += MulScale(1024, bsin(nsp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_END;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, end_sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickLadderSetup(short stat, short lotag, short type)
|
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
int ndx;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tp;
|
|
|
|
TRACKp t;
|
|
|
|
SPRITEp nsp;
|
2021-11-05 23:20:27 +00:00
|
|
|
DSWActor* start_sprite,* end_sprite;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
SWStatIterator it(stat);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// find an open track
|
|
|
|
for (ndx = 0; ndx < MAX_TRACKS; ndx++)
|
|
|
|
{
|
|
|
|
if (Track[ndx].NumPoints == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(ndx < MAX_TRACKS);
|
|
|
|
|
|
|
|
// save space for 3 points
|
2020-12-01 15:53:29 +00:00
|
|
|
Track[ndx].SetTrackSize(4);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tp = Track[ndx].TrackPoint;
|
|
|
|
t = &Track[ndx];
|
|
|
|
|
|
|
|
// set track type
|
|
|
|
SET(t->ttflags, BIT(type));
|
|
|
|
t->flags = 0;
|
|
|
|
|
|
|
|
// clone point
|
2021-11-05 23:20:27 +00:00
|
|
|
end_sprite = TrackClonePoint(actor);
|
|
|
|
start_sprite = TrackClonePoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add start point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &start_sprite->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = TRACK_START;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
nsp->x += MOVEx(256,nsp->ang + 1024);
|
|
|
|
nsp->y += MOVEy(256,nsp->ang + 1024);
|
|
|
|
TrackAddPoint(t, tp, start_sprite);
|
|
|
|
|
|
|
|
// add climb point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->lotag = lotag;
|
2021-11-05 23:20:27 +00:00
|
|
|
TrackAddPoint(t, tp, actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// add end point
|
2021-11-05 23:20:27 +00:00
|
|
|
nsp = &end_sprite->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
nsp->x += MOVEx(512,nsp->ang);
|
|
|
|
nsp->y += MOVEy(512,nsp->ang);
|
|
|
|
nsp->lotag = TRACK_END;
|
|
|
|
nsp->hitag = 0;
|
|
|
|
TrackAddPoint(t, tp, end_sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:10:04 +00:00
|
|
|
void TrackSetup(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
int ndx;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRACK_POINTp tp;
|
|
|
|
TRACKp t;
|
2017-01-23 11:21:32 +00:00
|
|
|
TRACK_POINTp New;
|
2015-05-19 21:54:34 +00:00
|
|
|
int size;
|
|
|
|
|
|
|
|
// put points on track
|
|
|
|
for (ndx = 0; ndx < MAX_TRACKS; ndx++)
|
|
|
|
{
|
2021-11-05 23:10:04 +00:00
|
|
|
SWStatIterator it(STAT_TRACK + ndx);
|
|
|
|
|
|
|
|
if (!it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// for some reason I need at least one record allocated
|
|
|
|
// can't remember why at this point
|
2019-04-08 06:25:59 +00:00
|
|
|
Track[ndx].TrackPoint = (TRACK_POINTp)CallocMem(sizeof(TRACK_POINT) * 1, 1);
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint == nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// make the track array rather large. I'll resize it to correct size
|
|
|
|
// later.
|
2019-04-08 06:25:59 +00:00
|
|
|
Track[ndx].TrackPoint = (TRACK_POINTp)CallocMem(sizeof(TRACK_POINT) * 500, 1);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tp = Track[ndx].TrackPoint;
|
|
|
|
t = &Track[ndx];
|
|
|
|
|
|
|
|
// find the first point and save it
|
2021-11-05 23:10:04 +00:00
|
|
|
it.Reset(STAT_TRACK + ndx);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:10:04 +00:00
|
|
|
if (actor->s().lotag == TRACK_START)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ASSERT(t->NumPoints == 0);
|
|
|
|
|
2021-11-05 23:20:27 +00:00
|
|
|
TrackAddPoint(t, tp, actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// didn't find the start point of the track
|
|
|
|
if (t->NumPoints == 0)
|
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2021-11-05 23:10:04 +00:00
|
|
|
it.Reset(STAT_TRACK + ndx);
|
|
|
|
auto itActor = it.Next();
|
|
|
|
auto const sp = &itActor->s();
|
2020-04-11 21:45:45 +00:00
|
|
|
Printf("WARNING: Did not find first point of Track Number %d, x %d, y %d\n", ndx, sp->x, sp->y);
|
2021-11-05 23:10:04 +00:00
|
|
|
it.Reset(STAT_TRACK + ndx);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// neuter the track's sprite list
|
2021-11-05 23:20:27 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set up flags for track types
|
|
|
|
if (tp->tag_low == TRACK_START && tp->tag_high)
|
|
|
|
SET(t->ttflags, BIT(tp->tag_high));
|
|
|
|
|
|
|
|
// while there are still sprites on this status list
|
2021-11-05 23:10:04 +00:00
|
|
|
|
|
|
|
while (it.Reset(STAT_TRACK + ndx), it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:10:04 +00:00
|
|
|
DSWActor* next_actor = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
int dist, low_dist = 999999;
|
|
|
|
|
|
|
|
// find the closest point to the last point
|
2021-11-05 23:10:04 +00:00
|
|
|
it.Reset(STAT_TRACK + ndx);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:10:04 +00:00
|
|
|
dist = Distance((tp + t->NumPoints - 1)->x, (tp + t->NumPoints - 1)->y, actor->s().x, actor->s().y);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dist < low_dist)
|
|
|
|
{
|
2021-11-05 23:10:04 +00:00
|
|
|
next_actor = actor;
|
2015-05-19 21:54:34 +00:00
|
|
|
low_dist = dist;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// save the closest one off and kill it
|
2021-11-05 23:10:04 +00:00
|
|
|
if (next_actor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:20:27 +00:00
|
|
|
TrackAddPoint(t, tp, next_actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
size = (Track[ndx].NumPoints + 1) * sizeof(TRACK_POINT);
|
2019-04-08 06:25:59 +00:00
|
|
|
New = (TRACK_POINTp)CallocMem(size, 1);
|
2017-01-23 11:21:32 +00:00
|
|
|
memcpy(New, Track[ndx].TrackPoint, size);
|
2015-05-19 21:54:34 +00:00
|
|
|
FreeMem(Track[ndx].TrackPoint);
|
2017-01-23 11:21:32 +00:00
|
|
|
Track[ndx].TrackPoint = New;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
ASSERT(Track[ndx].TrackPoint != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QuickJumpSetup(STAT_QUICK_JUMP, TRACK_ACTOR_QUICK_JUMP, TT_JUMP_UP);
|
|
|
|
QuickJumpSetup(STAT_QUICK_JUMP_DOWN, TRACK_ACTOR_QUICK_JUMP_DOWN, TT_JUMP_DOWN);
|
|
|
|
QuickJumpSetup(STAT_QUICK_SUPER_JUMP, TRACK_ACTOR_QUICK_SUPER_JUMP, TT_SUPER_JUMP_UP);
|
|
|
|
QuickScanSetup(STAT_QUICK_SCAN, TRACK_ACTOR_QUICK_SCAN, TT_SCAN);
|
|
|
|
QuickLadderSetup(STAT_QUICK_LADDER, TRACK_ACTOR_CLIMB_LADDER, TT_LADDER);
|
|
|
|
QuickExitSetup(STAT_QUICK_EXIT, TT_EXIT);
|
|
|
|
QuickJumpSetup(STAT_QUICK_OPERATE, TRACK_ACTOR_QUICK_OPERATE, TT_OPERATE);
|
|
|
|
QuickJumpSetup(STAT_QUICK_DUCK, TRACK_ACTOR_QUICK_DUCK, TT_DUCK_N_SHOOT);
|
|
|
|
QuickJumpSetup(STAT_QUICK_DEFEND, TRACK_ACTOR_QUICK_DEFEND, TT_HIDE_N_SHOOT);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-05 22:59:45 +00:00
|
|
|
DSWActor* FindBoundSprite(int tag)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 22:59:45 +00:00
|
|
|
SWStatIterator it(STAT_ST1);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 22:59:45 +00:00
|
|
|
if (actor->s().hitag == tag)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 22:59:45 +00:00
|
|
|
return actor;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void SectorObjectSetupBounds(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int xlow, ylow, xhigh, yhigh;
|
2021-11-02 18:07:05 +00:00
|
|
|
int startwall, endwall;
|
2015-05-19 21:54:34 +00:00
|
|
|
int i, k, j;
|
2021-11-05 22:59:45 +00:00
|
|
|
DSWActor* BoundActor = nullptr;
|
2020-09-09 18:32:24 +00:00
|
|
|
bool FoundOutsideLoop = false;
|
|
|
|
bool SectorInBounds;
|
2015-05-19 21:54:34 +00:00
|
|
|
SECTORp *sectp;
|
2021-11-01 19:07:53 +00:00
|
|
|
USERp u = sop->sp_child->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
static const uint8_t StatList[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
STAT_DEFAULT, STAT_MISC, STAT_ITEM, STAT_TRAP,
|
|
|
|
STAT_SPAWN_SPOT, STAT_SOUND_SPOT, STAT_WALL_MOVE,
|
|
|
|
STAT_WALLBLOOD_QUEUE,
|
|
|
|
STAT_SPRITE_HIT_MATCH,
|
|
|
|
STAT_AMBIENT,
|
|
|
|
STAT_DELETE_SPRITE,
|
|
|
|
STAT_SPAWN_TRIGGER, // spawing monster trigger - for Randy's bullet train.
|
|
|
|
//STAT_FLOOR_PAN, STAT_CEILING_PAN
|
|
|
|
};
|
|
|
|
|
|
|
|
// search for 2 sprite bounding tags
|
|
|
|
|
2021-11-05 22:59:45 +00:00
|
|
|
BoundActor = FindBoundSprite(500 + (int(sop - SectorObject) * 5));
|
|
|
|
if (BoundActor == nullptr)
|
|
|
|
{
|
|
|
|
I_Error("SOP bound sprite with hitag %d not found", 500 + (int(sop - SectorObject) * 5));
|
|
|
|
}
|
|
|
|
auto BoundSprite = &BoundActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
xlow = BoundSprite->x;
|
|
|
|
ylow = BoundSprite->y;
|
|
|
|
|
2021-11-05 22:59:45 +00:00
|
|
|
KillActor(BoundActor);
|
|
|
|
|
|
|
|
BoundActor = FindBoundSprite(501 + (int(sop - SectorObject) * 5));
|
|
|
|
if (BoundActor == nullptr)
|
|
|
|
{
|
|
|
|
I_Error("SOP bound sprite with hitag %d not found", 501 + (int(sop - SectorObject) * 5));
|
|
|
|
}
|
|
|
|
BoundSprite = &BoundActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
xhigh = BoundSprite->x;
|
|
|
|
yhigh = BoundSprite->y;
|
|
|
|
|
2021-11-05 22:59:45 +00:00
|
|
|
KillActor(BoundActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// set radius for explosion checking - based on bounding box
|
2021-11-19 20:47:04 +00:00
|
|
|
u->Radius = ((xhigh - xlow) + (yhigh - ylow)) >> 2;
|
|
|
|
u->Radius -= (u->Radius >> 2); // trying to get it a good size
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// search for center sprite if it exists
|
|
|
|
|
2021-11-05 22:59:45 +00:00
|
|
|
BoundActor = FindBoundSprite(SECT_SO_CENTER);
|
|
|
|
if (BoundActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 22:59:45 +00:00
|
|
|
auto BoundSprite = &BoundActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->xmid = BoundSprite->x;
|
|
|
|
sop->ymid = BoundSprite->y;
|
|
|
|
sop->zmid = BoundSprite->z;
|
2021-11-05 22:59:45 +00:00
|
|
|
KillActor(BoundActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// look for players on sector object
|
2020-03-06 15:49:55 +00:00
|
|
|
PLAYERp pp;
|
|
|
|
short pnum;
|
2015-05-19 21:54:34 +00:00
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
pp = &Player[pnum];
|
|
|
|
|
|
|
|
if (pp->posx > xlow && pp->posx < xhigh && pp->posy > ylow && pp->posy < yhigh)
|
|
|
|
{
|
2020-10-08 03:23:29 +00:00
|
|
|
pp->RevolveAng = pp->angle.ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
pp->RevolveX = pp->posx;
|
|
|
|
pp->RevolveY = pp->posy;
|
|
|
|
pp->RevolveDeltaAng = 0;
|
|
|
|
SET(pp->Flags, PF_PLAYER_RIDING);
|
|
|
|
|
|
|
|
pp->sop_riding = sop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// look through all sectors for whole sectors that are IN bounds
|
2021-11-25 16:27:41 +00:00
|
|
|
for (auto&sec : sectors())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-25 16:27:41 +00:00
|
|
|
auto sect = &sec;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
SectorInBounds = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-25 16:27:41 +00:00
|
|
|
for(auto& wal : wallsofsector(sect))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// all walls have to be in bounds to be in sector object
|
2021-11-24 21:04:11 +00:00
|
|
|
if (!(wal.x > xlow && wal.x < xhigh && wal.y > ylow && wal.y < yhigh))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-09 17:52:52 +00:00
|
|
|
SectorInBounds = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SectorInBounds)
|
|
|
|
{
|
2021-11-19 22:20:58 +00:00
|
|
|
sop->sectp[sop->num_sectors] = sect;
|
2021-11-24 22:01:43 +00:00
|
|
|
sop->sectp[sop->num_sectors+1] = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// all sectors in sector object have this flag set - for colision
|
|
|
|
// detection and recognition
|
2021-11-19 22:20:58 +00:00
|
|
|
SET(sect->extra, SECTFX_SECTOR_OBJECT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-19 22:20:58 +00:00
|
|
|
sop->zorig_floor[sop->num_sectors] = sect->floorz;
|
|
|
|
sop->zorig_ceiling[sop->num_sectors] = sect->ceilingz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-19 22:20:58 +00:00
|
|
|
if (TEST(sect->extra, SECTFX_SINK))
|
2021-11-20 22:20:43 +00:00
|
|
|
sop->zorig_floor[sop->num_sectors] += Z(FixedToInt(sect->depth_fixed));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// lowest and highest floorz's
|
2021-11-19 22:20:58 +00:00
|
|
|
if (sect->floorz > sop->floor_loz)
|
|
|
|
sop->floor_loz = sect->floorz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-19 22:20:58 +00:00
|
|
|
if (sect->floorz < sop->floor_hiz)
|
|
|
|
sop->floor_hiz = sect->floorz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->num_sectors++;
|
|
|
|
}
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
ASSERT((uint16_t)sop->num_sectors < SIZ(SectorObject[0].sectp));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make sure every sector object has an outer loop tagged - important
|
|
|
|
//
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
FoundOutsideLoop = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
|
|
|
// move all walls in sectors
|
2021-11-24 19:59:19 +00:00
|
|
|
for(auto& wal : wallsofsector(*sectp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// for morph point - tornado style
|
2021-11-24 19:59:19 +00:00
|
|
|
if (wal.lotag == TAG_WALL_ALIGN_SLOPE_TO_POINT)
|
2021-11-25 17:16:56 +00:00
|
|
|
sop->morph_wall_point = &wal;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 19:59:19 +00:00
|
|
|
if (wal.extra && TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2020-09-09 17:52:52 +00:00
|
|
|
FoundOutsideLoop = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// each wall has this set - for collision detection
|
2021-11-24 19:59:19 +00:00
|
|
|
SET(wal.extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
|
|
|
|
if (wal.twoSided())
|
|
|
|
SET(wal.nextWall()->extra, WALLFX_SECTOR_OBJECT|WALLFX_DONT_STICK);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!FoundOutsideLoop)
|
|
|
|
{
|
2019-12-25 10:26:19 +00:00
|
|
|
I_Error("Forgot to tag outer loop for Sector Object #%d", (int)(sop - SectorObject));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-05-01 11:29:12 +00:00
|
|
|
so_addinterpolation(sop);
|
2020-04-15 10:21:11 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
for (i = 0; i < (int)SIZ(StatList); i++)
|
|
|
|
{
|
2021-11-02 17:42:25 +00:00
|
|
|
SWStatIterator it(StatList[i]);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:42:25 +00:00
|
|
|
SPRITEp sp = &itActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp u;
|
|
|
|
|
|
|
|
if (sp->x > xlow && sp->x < xhigh && sp->y > ylow && sp->y < yhigh)
|
|
|
|
{
|
|
|
|
// some delete sprites ride others don't
|
|
|
|
if (sp->statnum == STAT_DELETE_SPRITE)
|
|
|
|
{
|
|
|
|
if (!TEST_BOOL2(sp))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-11-02 17:42:25 +00:00
|
|
|
if (!itActor->hasU())
|
|
|
|
u = SpawnUser(itActor, 0, nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-11-02 17:42:25 +00:00
|
|
|
u = itActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->RotNum = 0;
|
|
|
|
|
2021-01-05 12:43:49 +00:00
|
|
|
sp->backuppos();
|
2021-02-28 11:35:34 +00:00
|
|
|
u->oz = sp->oz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
switch (sp->statnum)
|
|
|
|
{
|
|
|
|
case STAT_WALL_MOVE:
|
|
|
|
////DSPRINTF(ds,"Damage Wall attached ");
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
break;
|
|
|
|
case STAT_DEFAULT:
|
|
|
|
switch (sp->hitag)
|
|
|
|
{
|
|
|
|
case SO_CLIP_BOX:
|
|
|
|
{
|
|
|
|
short ang2;
|
|
|
|
sop->clipdist = 0;
|
|
|
|
sop->clipbox_dist[sop->clipbox_num] = sp->lotag;
|
|
|
|
sop->clipbox_xoff[sop->clipbox_num] = sop->xmid - sp->x;
|
|
|
|
sop->clipbox_yoff[sop->clipbox_num] = sop->ymid - sp->y;
|
|
|
|
|
|
|
|
sop->clipbox_vdist[sop->clipbox_num] = ksqrt(SQ(sop->xmid - sp->x) + SQ(sop->ymid - sp->y));
|
|
|
|
|
|
|
|
ang2 = getangle(sp->x - sop->xmid, sp->y - sop->ymid);
|
2020-09-16 11:46:03 +00:00
|
|
|
sop->clipbox_ang[sop->clipbox_num] = getincangle(ang2, sop->ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->clipbox_num++;
|
2021-11-02 17:42:25 +00:00
|
|
|
KillActor(itActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
goto cont;
|
|
|
|
}
|
|
|
|
case SO_SHOOT_POINT:
|
2021-11-02 17:42:25 +00:00
|
|
|
ClearOwner(itActor);
|
|
|
|
change_actor_stat(itActor, STAT_SO_SHOOT_POINT);
|
2015-05-19 21:54:34 +00:00
|
|
|
RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u->sx = sop->xmid - sp->x;
|
|
|
|
u->sy = sop->ymid - sp->y;
|
2021-11-24 21:49:00 +00:00
|
|
|
u->sz = sop->mid_sector->floorz - sp->z;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(u->Flags, SPR_SO_ATTACHED);
|
|
|
|
|
|
|
|
u->sang = sp->ang;
|
|
|
|
u->spal = sp->pal;
|
|
|
|
|
|
|
|
// search SO's sectors to make sure that it is not on a
|
|
|
|
// sector
|
|
|
|
|
|
|
|
// place all sprites on list
|
2020-02-10 19:33:48 +00:00
|
|
|
int sn;
|
2021-11-02 17:45:21 +00:00
|
|
|
for (sn = 0; sn < (int)SIZ(sop->so_actors); sn++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
if (sop->so_actors[sn] == nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
sop->so_actors[sn] = itActor;
|
2021-11-02 17:42:25 +00:00
|
|
|
so_setspriteinterpolation(sop, itActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (!TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
// determine if sprite is on a SO sector - set flag if
|
|
|
|
// true
|
|
|
|
for (j = 0; j < sop->num_sectors; j++)
|
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
if (sop->sectp[j] == sp->sector())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_ON_SO_SECTOR);
|
2021-11-19 21:03:18 +00:00
|
|
|
u->sz = sp->sector()->floorz - sp->z;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cont:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for SPRITE OBJECT sprites, set the u->sz value to the difference
|
|
|
|
// between the zmid and the sp->z
|
|
|
|
if (TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
|
|
|
int zmid = -9999999;
|
|
|
|
|
|
|
|
// choose the lowest sprite for the zmid
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
sp = &sop->so_actors[i]->s();
|
|
|
|
u = sop->so_actors[i]->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (sp->z > zmid)
|
|
|
|
zmid = sp->z;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(zmid != -9999999);
|
|
|
|
|
|
|
|
sop->zmid = zmid;
|
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
|
|
|
{
|
|
|
|
sp = &sop->so_actors[i]->s();
|
|
|
|
u = sop->so_actors[i]->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->sz = sop->zmid - sp->z;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-24 21:39:01 +00:00
|
|
|
void SetupSectorObject(sectortype* sectp, short tag)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp;
|
|
|
|
SECTOR_OBJECTp sop;
|
2021-10-30 18:00:02 +00:00
|
|
|
int object_num;
|
2020-03-06 15:49:49 +00:00
|
|
|
short j;
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp u;
|
|
|
|
|
|
|
|
tag -= (TAG_OBJECT_CENTER - 1);
|
|
|
|
|
|
|
|
object_num = tag / 5;
|
|
|
|
sop = &SectorObject[object_num];
|
|
|
|
|
|
|
|
// initialize stuff first time through
|
|
|
|
if (sop->num_sectors == -1)
|
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
void DoTornadoObject(SECTOR_OBJECTp sop);
|
|
|
|
void MorphTornado(SECTOR_OBJECTp sop);
|
|
|
|
void MorphFloor(SECTOR_OBJECTp sop);
|
|
|
|
void ScaleSectorObject(SECTOR_OBJECTp sop);
|
|
|
|
void DoAutoTurretObject(SECTOR_OBJECTp sop);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
memset(sop->sectp, 0, sizeof(sop->sectp));
|
2021-11-02 17:45:21 +00:00
|
|
|
memset(sop->so_actors, 0, sizeof(sop->so_actors));
|
2021-11-25 17:16:56 +00:00
|
|
|
sop->morph_wall_point = nullptr;
|
|
|
|
sop->op_main_sector = nullptr;
|
2021-11-24 22:07:02 +00:00
|
|
|
sop->scratch = nullptr; // this is a guard field for sectp, because several loops do not test the end properly.
|
2021-11-02 17:52:59 +00:00
|
|
|
sop->match_event_actor = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->crush_z = 0;
|
|
|
|
sop->drive_angspeed = 0;
|
|
|
|
sop->drive_angslide = 0;
|
|
|
|
sop->drive_slide = 0;
|
|
|
|
sop->drive_speed = 0;
|
|
|
|
sop->num_sectors = 0;
|
|
|
|
sop->update = 15000;
|
|
|
|
sop->flags = 0;
|
|
|
|
sop->clipbox_num = 0;
|
|
|
|
sop->bob_amt = 0;
|
|
|
|
sop->vel_rate = 6;
|
|
|
|
sop->z_rate = 256;
|
|
|
|
sop->zdelta = sop->z_tgt = 0;
|
|
|
|
sop->wait_tics = 0;
|
|
|
|
sop->spin_speed = 0;
|
|
|
|
sop->spin_ang = 0;
|
|
|
|
sop->ang_orig = 0;
|
|
|
|
sop->clipdist = 1024;
|
|
|
|
sop->target_dist = 0;
|
|
|
|
sop->turn_speed = 4;
|
|
|
|
sop->floor_loz = -9999999;
|
|
|
|
sop->floor_hiz = 9999999;
|
|
|
|
sop->player_xoff = sop->player_yoff = 0;
|
|
|
|
sop->ang_tgt = sop->ang = sop->ang_moving = 0;
|
2021-11-24 22:07:02 +00:00
|
|
|
sop->op_main_sector = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->ram_damage = 0;
|
|
|
|
sop->max_damage = -9999;
|
|
|
|
|
|
|
|
sop->scale_type = SO_SCALE_NONE;
|
|
|
|
sop->scale_dist = 0;
|
|
|
|
sop->scale_speed = 20;
|
|
|
|
sop->scale_dist_min = -1024;
|
|
|
|
sop->scale_dist_max = 1024;
|
|
|
|
sop->scale_rand_freq = 64>>3;
|
|
|
|
|
|
|
|
sop->scale_x_mult = 256;
|
|
|
|
sop->scale_y_mult = 256;
|
|
|
|
|
|
|
|
sop->morph_ang = RANDOM_P2(2048);
|
|
|
|
sop->morph_z_speed = 20;
|
|
|
|
sop->morph_speed = 32;
|
|
|
|
sop->morph_dist_max = 1024;
|
|
|
|
sop->morph_rand_freq = 64;
|
|
|
|
sop->morph_dist = 0;
|
|
|
|
sop->morph_xoff = 0;
|
|
|
|
sop->morph_yoff = 0;
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
sop->PreMoveAnimator = nullptr;
|
|
|
|
sop->PostMoveAnimator = nullptr;
|
|
|
|
sop->Animator = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (tag % 5)
|
|
|
|
{
|
|
|
|
case TAG_OBJECT_CENTER - 500:
|
|
|
|
|
2021-11-24 21:49:00 +00:00
|
|
|
sop->mid_sector = sectp;
|
2021-11-24 21:39:01 +00:00
|
|
|
SectorMidPoint(sectp, &sop->xmid, &sop->ymid, &sop->zmid);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->dir = 1;
|
2021-11-24 21:39:01 +00:00
|
|
|
sop->track = sectp->hitag;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// spawn a sprite to make it easier to integrate with sprite routines
|
2021-11-24 21:39:01 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_SO_SP_CHILD, 0, nullptr, sectp,
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->xmid, sop->ymid, sop->zmid, 0, 0);
|
2021-11-01 19:07:53 +00:00
|
|
|
sop->sp_child = actorNew;
|
|
|
|
u = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->sop_parent = sop;
|
|
|
|
SET(u->Flags2, SPR2_SPRITE_FAKE_BLOCK); // for damage test
|
|
|
|
|
|
|
|
// check for any ST1 sprites laying on the center sector
|
2021-11-24 21:39:01 +00:00
|
|
|
SWSectIterator it(sectp);
|
2021-10-30 18:00:02 +00:00
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 18:00:02 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (sp->statnum == STAT_ST1)
|
|
|
|
{
|
|
|
|
switch (sp->hitag)
|
|
|
|
{
|
|
|
|
case SO_SCALE_XY_MULT:
|
|
|
|
if (SP_TAG5(sp))
|
|
|
|
sop->scale_x_mult = SP_TAG5(sp);
|
|
|
|
if (SP_TAG6(sp))
|
|
|
|
sop->scale_y_mult = SP_TAG6(sp);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_SCALE_POINT_INFO:
|
|
|
|
|
|
|
|
memset(sop->scale_point_dist,0,sizeof(sop->scale_point_dist));
|
|
|
|
sop->scale_point_base_speed = SP_TAG2(sp);
|
|
|
|
for (j = 0; j < (int)SIZ(sop->scale_point_speed); j++)
|
|
|
|
{
|
|
|
|
sop->scale_point_speed[j] = SP_TAG2(sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SP_TAG4(sp))
|
2015-05-19 21:58:29 +00:00
|
|
|
sop->scale_point_rand_freq = (uint8_t)SP_TAG4(sp);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
sop->scale_point_rand_freq = 64;
|
|
|
|
|
|
|
|
sop->scale_point_dist_min = -SP_TAG5(sp);
|
|
|
|
sop->scale_point_dist_max = SP_TAG6(sp);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_SCALE_INFO:
|
|
|
|
SET(sop->flags, SOBJ_DYNAMIC);
|
|
|
|
sop->scale_speed = SP_TAG2(sp);
|
|
|
|
sop->scale_dist_min = -SP_TAG5(sp);
|
|
|
|
sop->scale_dist_max = SP_TAG6(sp);
|
|
|
|
|
|
|
|
sop->scale_type = SP_TAG4(sp);
|
|
|
|
sop->scale_active_type = SP_TAG7(sp);
|
|
|
|
|
|
|
|
if (SP_TAG8(sp))
|
2015-05-19 21:58:29 +00:00
|
|
|
sop->scale_rand_freq = (uint8_t)SP_TAG8(sp);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
sop->scale_rand_freq = 64>>3;
|
|
|
|
|
|
|
|
if (SP_TAG3(sp) == 0)
|
|
|
|
sop->scale_dist = sop->scale_dist_min;
|
|
|
|
else if (SP_TAG3(sp) == 1)
|
|
|
|
sop->scale_dist = sop->scale_dist_max;
|
|
|
|
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPAWN_SPOT:
|
|
|
|
if (sp->clipdist == 3)
|
|
|
|
{
|
|
|
|
USERp u;
|
2021-10-30 18:00:02 +00:00
|
|
|
change_actor_stat(actor, STAT_NO_STATE);
|
2021-11-03 19:51:21 +00:00
|
|
|
u = SpawnUser(actor, 0, nullptr);
|
2021-07-10 12:25:18 +00:00
|
|
|
u->ActorActionFunc = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_AUTO_TURRET:
|
|
|
|
sop->Animator = DoAutoTurretObject;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_TORNADO:
|
|
|
|
if (SW_SHAREWARE) break;
|
|
|
|
sop->vel = 120;
|
|
|
|
SET(sop->flags, SOBJ_DYNAMIC);
|
|
|
|
sop->scale_type = SO_SCALE_CYCLE;
|
|
|
|
// spin stuff
|
|
|
|
sop->spin_speed = 16;
|
|
|
|
sop->last_ang = sop->ang;
|
|
|
|
// animators
|
|
|
|
sop->Animator = DoTornadoObject;
|
|
|
|
sop->PreMoveAnimator = ScaleSectorObject;
|
|
|
|
sop->PostMoveAnimator = MorphTornado;
|
|
|
|
// clip
|
|
|
|
sop->clipdist = 2500;
|
|
|
|
// morph point
|
|
|
|
sop->morph_speed = 16;
|
|
|
|
sop->morph_z_speed = 6;
|
|
|
|
sop->morph_dist_max = 1024;
|
|
|
|
sop->morph_rand_freq = 8;
|
|
|
|
sop->scale_dist_min = -768;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_FLOOR_MORPH:
|
|
|
|
if (SW_SHAREWARE) break;
|
|
|
|
SET(sop->flags, SOBJ_DYNAMIC);
|
|
|
|
sop->scale_type = SO_SCALE_NONE;
|
|
|
|
sop->morph_speed = 120;
|
|
|
|
sop->morph_z_speed = 7;
|
|
|
|
sop->PostMoveAnimator = MorphFloor;
|
|
|
|
sop->morph_dist_max = 4000;
|
|
|
|
sop->morph_rand_freq = 8;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_AMOEBA:
|
|
|
|
SET(sop->flags, SOBJ_DYNAMIC);
|
|
|
|
//sop->scale_type = SO_SCALE_CYCLE;
|
|
|
|
sop->scale_type = SO_SCALE_RANDOM_POINT;
|
|
|
|
sop->PreMoveAnimator = ScaleSectorObject;
|
|
|
|
|
|
|
|
memset(sop->scale_point_dist,0,sizeof(sop->scale_point_dist));;
|
|
|
|
sop->scale_point_base_speed = SCALE_POINT_SPEED;
|
|
|
|
for (j = 0; j < (int)SIZ(sop->scale_point_speed); j++)
|
|
|
|
sop->scale_point_speed[j] = SCALE_POINT_SPEED;
|
|
|
|
|
|
|
|
sop->scale_point_dist_min = -256;
|
|
|
|
sop->scale_point_dist_max = 256;
|
|
|
|
sop->scale_point_rand_freq = 32;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_MAX_DAMAGE:
|
|
|
|
u->MaxHealth = SP_TAG2(sp);
|
|
|
|
if (SP_TAG5(sp) != 0)
|
|
|
|
sop->max_damage = SP_TAG5(sp);
|
|
|
|
else
|
|
|
|
sop->max_damage = u->MaxHealth;
|
|
|
|
|
|
|
|
switch (sp->clipdist)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
SET(sop->flags, SOBJ_DIE_HARD);
|
|
|
|
break;
|
|
|
|
}
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_DRIVABLE_ATTRIB:
|
|
|
|
|
2020-09-08 10:48:01 +00:00
|
|
|
sop->drive_angspeed = SP_TAG2(sp);
|
|
|
|
sop->drive_angspeed <<= 5;
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->drive_angslide = SP_TAG3(sp);
|
|
|
|
if (sop->drive_angslide <= 0 || sop->drive_angslide == 32)
|
|
|
|
sop->drive_angslide = 1;
|
|
|
|
|
|
|
|
sop->drive_speed = SP_TAG6(sp);
|
|
|
|
sop->drive_speed <<= 5;
|
|
|
|
sop->drive_slide = SP_TAG7(sp);
|
|
|
|
if (sop->drive_slide <= 0)
|
|
|
|
sop->drive_slide = 1;
|
|
|
|
|
|
|
|
if (TEST_BOOL1(sp))
|
|
|
|
SET(sop->flags, SOBJ_NO_QUAKE);
|
|
|
|
|
|
|
|
if (TEST_BOOL3(sp))
|
|
|
|
SET(sop->flags, SOBJ_REMOTE_ONLY);
|
|
|
|
|
|
|
|
if (TEST_BOOL4(sp))
|
|
|
|
{
|
|
|
|
sop->crush_z = sp->z;
|
|
|
|
SET(sop->flags, SOBJ_RECT_CLIP);
|
|
|
|
}
|
|
|
|
|
2021-10-30 20:53:24 +00:00
|
|
|
//KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SO_RAM_DAMAGE:
|
|
|
|
sop->ram_damage = sp->lotag;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SECT_SO_CLIP_DIST:
|
|
|
|
sop->clipdist = sp->lotag;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SECT_SO_SPRITE_OBJ:
|
|
|
|
SET(sop->flags, SOBJ_SPRITE_OBJ);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SECT_SO_DONT_ROTATE:
|
|
|
|
SET(sop->flags, SOBJ_DONT_ROTATE);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_LIMIT_TURN:
|
|
|
|
sop->limit_ang_center = sp->ang;
|
|
|
|
sop->limit_ang_delta = sp->lotag;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_MATCH_EVENT:
|
|
|
|
sop->match_event = sp->lotag;
|
2021-11-02 17:52:59 +00:00
|
|
|
sop->match_event_actor = actor;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_SET_SPEED:
|
|
|
|
sop->vel = sp->lotag * 256;
|
|
|
|
sop->vel_tgt = sop->vel;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_SPIN:
|
|
|
|
if (sop->spin_speed)
|
|
|
|
break;
|
|
|
|
sop->spin_speed = sp->lotag;
|
|
|
|
sop->last_ang = sop->ang;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_ANGLE:
|
|
|
|
sop->ang = sop->ang_moving = sp->ang;
|
|
|
|
sop->last_ang = sop->ang_orig = sop->ang;
|
|
|
|
sop->spin_ang = 0;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_SPIN_REVERSE:
|
|
|
|
|
|
|
|
sop->spin_speed = sp->lotag;
|
|
|
|
sop->last_ang = sop->ang;
|
|
|
|
|
|
|
|
if (sop->spin_speed >= 0)
|
|
|
|
sop->spin_speed = -sop->spin_speed;
|
|
|
|
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_BOB_START:
|
|
|
|
sop->bob_amt = Z(sp->lotag);
|
|
|
|
sop->bob_sine_ndx = 0;
|
|
|
|
sop->bob_speed = 4;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_TURN_SPEED:
|
|
|
|
sop->turn_speed = sp->lotag;
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_SYNC1:
|
|
|
|
SET(sop->flags, SOBJ_SYNC1);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_SYNC2:
|
|
|
|
SET(sop->flags, SOBJ_SYNC2);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SO_KILLABLE:
|
|
|
|
SET(sop->flags, SOBJ_KILLABLE);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sop->vel == -1)
|
|
|
|
sop->vel = sop->vel_tgt = 8 * 256;
|
|
|
|
|
|
|
|
SectorObjectSetupBounds(sop);
|
|
|
|
|
|
|
|
if (sop->track >= SO_OPERATE_TRACK_START)
|
|
|
|
{
|
|
|
|
switch (sop->track)
|
|
|
|
{
|
|
|
|
case SO_TURRET_MGUN:
|
|
|
|
case SO_TURRET:
|
2020-09-08 11:54:48 +00:00
|
|
|
case SO_VEHICLE:
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->vel = 0;
|
|
|
|
SET(sop->flags, SOBJ_OPERATIONAL);
|
|
|
|
break;
|
2020-09-08 11:40:20 +00:00
|
|
|
#if 0
|
2015-05-19 21:54:34 +00:00
|
|
|
case SO_SPEED_BOAT:
|
|
|
|
sop->vel = 0;
|
|
|
|
sop->bob_amt = Z(2);
|
|
|
|
sop->bob_speed = 4;
|
|
|
|
SET(sop->flags, SOBJ_OPERATIONAL);
|
|
|
|
break;
|
2020-09-08 11:40:20 +00:00
|
|
|
#endif
|
2015-05-19 21:54:34 +00:00
|
|
|
default:
|
|
|
|
SET(sop->flags, SOBJ_OPERATIONAL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 21:39:01 +00:00
|
|
|
sectp->lotag = 0;
|
|
|
|
sectp->hitag = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (sop->max_damage <= 0)
|
|
|
|
VehicleSetSmoke(sop, SpawnVehicleSmoke);
|
|
|
|
|
|
|
|
// find radius
|
|
|
|
//u->Radius = sop->
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void PostSetupSectorObject(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SECTOR_OBJECTp sop;
|
|
|
|
|
|
|
|
for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++)
|
|
|
|
{
|
2020-05-22 12:11:03 +00:00
|
|
|
if (SO_EMPTY(sop))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
FindMainSector(sop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-25 17:16:56 +00:00
|
|
|
SECTOR_OBJECTp PlayerOnObject(sectortype* match)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short i, j;
|
|
|
|
SECTOR_OBJECTp sop;
|
|
|
|
|
|
|
|
// place each sector object on the track
|
2020-05-22 12:11:03 +00:00
|
|
|
//for (i = 0; !SO_EMPTY(&SectorObject[i]) && (i < MAX_SECTOR_OBJECTS); i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
for (i = 0; (i < MAX_SECTOR_OBJECTS); i++)
|
|
|
|
{
|
|
|
|
sop = &SectorObject[i];
|
|
|
|
|
|
|
|
if (sop->track < SO_OPERATE_TRACK_START)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (j = 0; j < sop->num_sectors; j++)
|
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
if (sop->sectp[j] == match && TEST(match->extra, SECTFX_OPERATIONAL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
return sop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void PlaceSectorObjectsOnTracks(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short i, j, k, startwall, endwall;
|
2020-09-09 18:32:24 +00:00
|
|
|
bool found;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// place each sector object on the track
|
|
|
|
for (i = 0; i < MAX_SECTOR_OBJECTS; i++)
|
|
|
|
{
|
|
|
|
int low_dist = 999999, dist;
|
|
|
|
SECTOR_OBJECTp sop = &SectorObject[i];
|
2021-07-10 12:25:18 +00:00
|
|
|
TRACK_POINTp tpoint = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-05-22 12:11:03 +00:00
|
|
|
if (SO_EMPTY(sop))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// save off the original x and y locations of the walls AND sprites
|
|
|
|
sop->num_walls = 0;
|
2021-11-24 22:01:43 +00:00
|
|
|
for (j = 0; sop->sectp[j] != nullptr; j++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
// move all walls in sectors
|
2021-11-24 22:01:43 +00:00
|
|
|
for (auto& wal : wallsofsector(sop->sectp[j]))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
sop->xorig[sop->num_walls] = sop->xmid - wal.x;
|
|
|
|
sop->yorig[sop->num_walls] = sop->ymid - wal.y;
|
2015-05-19 21:54:34 +00:00
|
|
|
sop->num_walls++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 09:44:56 +00:00
|
|
|
ASSERT((uint16_t)sop->num_walls < SIZ(sop->xorig));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (sop->track <= -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sop->track >= SO_OPERATE_TRACK_START)
|
|
|
|
continue;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
found = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
// find the closest point on the track and put SOBJ on it
|
|
|
|
for (j = 0; j < Track[sop->track].NumPoints; j++)
|
|
|
|
{
|
|
|
|
tpoint = Track[sop->track].TrackPoint;
|
|
|
|
|
|
|
|
dist = Distance((tpoint + j)->x, (tpoint + j)->y, sop->xmid, sop->ymid);
|
|
|
|
|
|
|
|
if (dist < low_dist)
|
|
|
|
{
|
|
|
|
low_dist = dist;
|
|
|
|
sop->point = j;
|
2020-09-09 17:52:52 +00:00
|
|
|
found = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
{
|
|
|
|
sop->track = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
NextTrackPoint(sop);
|
|
|
|
|
|
|
|
sop->ang = getangle((tpoint + sop->point)->x - sop->xmid, (tpoint + sop->point)->y - sop->ymid);
|
|
|
|
|
|
|
|
sop->ang_moving = sop->ang_tgt = sop->ang;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void PlaceActorsOnTracks(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
short j, tag;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
2021-07-10 12:25:18 +00:00
|
|
|
TRACK_POINTp tpoint = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// place each actor on the track
|
2021-11-05 23:37:16 +00:00
|
|
|
SWStatIterator it(STAT_ENEMY);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int low_dist = 999999, dist;
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
sp = &actor->s();
|
|
|
|
u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:37:57 +00:00
|
|
|
tag = sp->lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (tag < TAG_ACTOR_TRACK_BEGIN || tag > TAG_ACTOR_TRACK_END)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// setup sprite track defaults
|
|
|
|
u->track = tag - TAG_ACTOR_TRACK_BEGIN;
|
|
|
|
|
|
|
|
// if facing left go backward
|
2020-09-04 19:17:24 +00:00
|
|
|
if (sp->ang >= 513 && sp->ang <= 1535)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
u->track_dir = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->track_dir = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
u->track_vel = sp->xvel * 256;
|
|
|
|
u->vel_tgt = u->track_vel;
|
|
|
|
u->vel_rate = 6;
|
|
|
|
|
|
|
|
// find the closest point on the track and put SOBJ on it
|
|
|
|
for (j = 0; j < Track[u->track].NumPoints; j++)
|
|
|
|
{
|
|
|
|
tpoint = Track[u->track].TrackPoint;
|
|
|
|
|
|
|
|
dist = Distance((tpoint + j)->x, (tpoint + j)->y, sp->x, sp->y);
|
|
|
|
|
|
|
|
if (dist < low_dist)
|
|
|
|
{
|
|
|
|
low_dist = dist;
|
|
|
|
u->point = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
NextActorTrackPoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-22 10:21:22 +00:00
|
|
|
if (Track[u->track].NumPoints == 0)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
Printf("WARNING: Sprite %d (%d, %d) placed on track %d with no points!\n", actor->GetIndex(), sp->x, sp->y, u->track);
|
2019-12-22 10:21:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
// check angle in the "forward" direction
|
|
|
|
sp->ang = getangle((tpoint + u->point)->x - sp->x, (tpoint + u->point)->y - sp->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void MovePlayer(PLAYERp pp, SECTOR_OBJECTp sop, int nx, int ny)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
void DoPlayerZrange(PLAYERp pp);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// make sure your standing on the so
|
|
|
|
if (TEST(pp->Flags, PF_JUMPING | PF_FALLING | PF_FLYING))
|
|
|
|
return;
|
|
|
|
|
|
|
|
pp->sop_riding = sop;
|
|
|
|
|
|
|
|
// if player has NOT moved and player is NOT riding
|
|
|
|
// set up the player for riding
|
|
|
|
if (!TEST(pp->Flags, PF_PLAYER_MOVED) && !TEST(pp->Flags, PF_PLAYER_RIDING))
|
|
|
|
{
|
|
|
|
SET(pp->Flags, PF_PLAYER_RIDING);
|
|
|
|
|
2020-10-08 03:23:29 +00:00
|
|
|
pp->RevolveAng = pp->angle.ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
pp->RevolveX = pp->posx;
|
|
|
|
pp->RevolveY = pp->posy;
|
|
|
|
|
|
|
|
// set the delta angle to 0 when moving
|
|
|
|
pp->RevolveDeltaAng = 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 06:57:22 +00:00
|
|
|
pp->posx += nx;
|
|
|
|
pp->posy += ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_DONT_ROTATE))
|
|
|
|
{
|
|
|
|
UpdatePlayerSprite(pp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(pp->Flags, PF_PLAYER_MOVED))
|
|
|
|
{
|
|
|
|
// Player is moving
|
|
|
|
|
|
|
|
// save the current information so when Player stops
|
|
|
|
// moving then you
|
|
|
|
// know where he was last
|
2020-10-08 03:23:29 +00:00
|
|
|
pp->RevolveAng = pp->angle.ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
pp->RevolveX = pp->posx;
|
|
|
|
pp->RevolveY = pp->posy;
|
|
|
|
|
|
|
|
// set the delta angle to 0 when moving
|
|
|
|
pp->RevolveDeltaAng = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Player is NOT moving
|
|
|
|
|
|
|
|
// Move saved x&y variables
|
2021-09-20 06:57:22 +00:00
|
|
|
pp->RevolveX += nx;
|
|
|
|
pp->RevolveY += ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Last known angle is now adjusted by the delta angle
|
2020-10-08 03:23:29 +00:00
|
|
|
pp->RevolveAng = pp->angle.ang - buildang(pp->RevolveDeltaAng);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// increment Players delta angle
|
2020-05-19 11:44:52 +00:00
|
|
|
pp->RevolveDeltaAng = NORM_ANGLE(pp->RevolveDeltaAng + GlobSpeedSO);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-12-01 18:01:38 +00:00
|
|
|
rotatepoint(sop->pmid.vec2, *(vec2_t *)&pp->RevolveX, pp->RevolveDeltaAng, &pp->pos.vec2);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// THIS WAS CAUSING PROLEMS!!!!
|
|
|
|
// Sectors are still being manipulated so you can end up in a void (-1) sector
|
|
|
|
|
|
|
|
// New angle is formed by taking last known angle and
|
|
|
|
// adjusting by the delta angle
|
2020-11-22 09:50:03 +00:00
|
|
|
pp->angle.addadjustment(pp->angle.ang - (pp->RevolveAng + buildang(pp->RevolveDeltaAng)));
|
2020-04-15 11:45:19 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
UpdatePlayerSprite(pp);
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void MovePoints(SECTOR_OBJECTp sop, short delta_ang, int nx, int ny)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
int j;
|
2016-05-23 04:46:30 +00:00
|
|
|
vec2_t rxy;
|
2021-11-24 21:04:11 +00:00
|
|
|
int pnum;
|
2015-05-19 21:54:34 +00:00
|
|
|
PLAYERp pp;
|
|
|
|
SECTORp *sectp;
|
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
2021-11-24 21:04:11 +00:00
|
|
|
int i, rot_ang;
|
2020-09-09 18:32:24 +00:00
|
|
|
bool PlayerMove = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-11-08 04:22:58 +00:00
|
|
|
if (sop->xmid >= MAXSO)
|
2020-09-09 17:52:52 +00:00
|
|
|
PlayerMove = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// move along little midpoint
|
2021-09-20 06:57:22 +00:00
|
|
|
sop->xmid += nx;
|
|
|
|
sop->ymid += ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-11-08 04:22:58 +00:00
|
|
|
if (sop->xmid >= MAXSO)
|
2020-09-09 17:52:52 +00:00
|
|
|
PlayerMove = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// move child sprite along also
|
2021-11-01 19:07:53 +00:00
|
|
|
sop->sp_child->s().x = sop->xmid;
|
|
|
|
sop->sp_child->s().y = sop->ymid;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
// setting floorz if need be
|
|
|
|
if (TEST(sop->flags, SOBJ_ZMID_FLOOR))
|
2021-11-24 21:49:00 +00:00
|
|
|
sop->zmid = sop->mid_sector->floorz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
|
|
|
if (TEST(sop->flags, SOBJ_SPRITE_OBJ | SOBJ_DONT_ROTATE))
|
|
|
|
goto PlayerPart;
|
|
|
|
|
|
|
|
// move all walls in sectors
|
2021-11-24 21:04:11 +00:00
|
|
|
for(auto& wal : wallsofsector(*sectp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_LOOP_DONT_SPIN | WALLFX_DONT_MOVE))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wal.extra && TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
dragpoint(&wal, wal.x += nx, wal.y += ny);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
wal.x += nx;
|
|
|
|
wal.y += ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rot_ang = delta_ang;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_LOOP_REVERSE_SPIN))
|
2015-05-19 21:54:34 +00:00
|
|
|
rot_ang = -delta_ang;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_LOOP_SPIN_2X))
|
2015-05-19 21:54:34 +00:00
|
|
|
rot_ang = NORM_ANGLE(rot_ang * 2);
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_LOOP_SPIN_4X))
|
2015-05-19 21:54:34 +00:00
|
|
|
rot_ang = NORM_ANGLE(rot_ang * 4);
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
rotatepoint(sop->pmid.vec2, wal.pos, rot_ang, &rxy);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wal.extra && TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
dragpoint(&wal, rxy.x, rxy.y);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
wal.x = rxy.x;
|
|
|
|
wal.y = rxy.y;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PlayerPart:
|
|
|
|
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
pp = Player + pnum;
|
|
|
|
|
|
|
|
// if controlling a sector object
|
|
|
|
if (pp->sop)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!pp->lo_sectp)
|
|
|
|
continue;
|
|
|
|
|
2021-11-24 21:43:32 +00:00
|
|
|
if (TEST(pp->lo_sectp->extra, SECTFX_NO_RIDE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move the player
|
2021-11-24 22:01:43 +00:00
|
|
|
if (pp->lo_sectp == sop->sectp[j])
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (PlayerMove)
|
|
|
|
MovePlayer(pp, sop, nx, ny);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
|
|
|
{
|
|
|
|
auto actor = sop->so_actors[i];
|
|
|
|
sp = &actor->s();
|
|
|
|
u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// if its a player sprite || NOT attached
|
|
|
|
if (!u || u->PlayerP || !TEST(u->Flags, SPR_SO_ATTACHED))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// move the player
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
pp = Player + pnum;
|
|
|
|
|
2021-10-30 22:29:54 +00:00
|
|
|
if (pp->lowActor && pp->lowActor == actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (PlayerMove)
|
|
|
|
MovePlayer(pp, sop, nx, ny);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->x = sop->xmid - u->sx;
|
|
|
|
sp->y = sop->ymid - u->sy;
|
|
|
|
|
|
|
|
// sprites z update
|
|
|
|
if (TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
// Sprite Objects follow zmid
|
|
|
|
sp->z = sop->zmid - u->sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Sector Objects can either have sprites ON or OFF of the sector
|
|
|
|
if (TEST(u->Flags, SPR_ON_SO_SECTOR))
|
|
|
|
{
|
|
|
|
// move with sector its on
|
2021-11-19 21:03:18 +00:00
|
|
|
sp->z = sp->sector()->floorz - u->sz;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// move with the mid sector
|
2021-11-24 21:49:00 +00:00
|
|
|
sp->z = sop->mid_sector->floorz - u->sz;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-30 21:56:26 +00:00
|
|
|
int16_t oldang = sp->ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = u->sang;
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_ON_SO_SECTOR))
|
|
|
|
{
|
|
|
|
if (TEST(sop->flags, SOBJ_DONT_ROTATE))
|
|
|
|
continue;
|
|
|
|
|
2021-11-04 23:03:08 +00:00
|
|
|
// IS part of a sector, sprite can do things based on the
|
2015-05-19 21:54:34 +00:00
|
|
|
// current sector it is in
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(sp->sector()->firstWall()->extra, WALLFX_LOOP_DONT_SPIN))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(sp->sector()->firstWall()->extra, WALLFX_LOOP_REVERSE_SPIN))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-12-01 18:01:38 +00:00
|
|
|
rotatepoint(sop->pmid.vec2, sp->pos.vec2, -delta_ang, &sp->pos.vec2);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = NORM_ANGLE(sp->ang - delta_ang);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-12-06 08:16:59 +00:00
|
|
|
rotatepoint(sop->pmid.vec2, sp->pos.vec2, delta_ang, &sp->pos.vec2);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = NORM_ANGLE(sp->ang + delta_ang);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!TEST(sop->flags, SOBJ_DONT_ROTATE))
|
|
|
|
{
|
|
|
|
// NOT part of a sector - independant of any sector
|
2020-12-06 09:11:26 +00:00
|
|
|
rotatepoint(sop->pmid.vec2, sp->pos.vec2, delta_ang, &sp->pos.vec2);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = NORM_ANGLE(sp->ang + delta_ang);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Does not necessarily move with the sector so must accout for
|
|
|
|
// moving across sectors
|
2019-11-08 04:22:58 +00:00
|
|
|
if (sop->xmid < MAXSO) // special case for operating SO's
|
2021-11-02 17:45:21 +00:00
|
|
|
SetActorZ(sop->so_actors[i], &sp->pos);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 11:46:03 +00:00
|
|
|
u->oangdiff += getincangle(oldang, sp->ang);
|
2020-04-30 21:56:26 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
if (TEST(sp->extra, SPRX_BLADE))
|
|
|
|
{
|
2021-11-04 20:26:08 +00:00
|
|
|
DoBladeDamage(sop->so_actors[i]);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
pp = Player + pnum;
|
|
|
|
|
|
|
|
// if player was on a sector object
|
|
|
|
if (pp->sop_riding)
|
|
|
|
{
|
|
|
|
// update here AFTER sectors/player has been manipulated
|
|
|
|
// prevents you from falling into map HOLEs created by moving
|
|
|
|
// Sectors and sprites around.
|
2019-11-08 04:22:58 +00:00
|
|
|
//if (sop->xmid < MAXSO)
|
2021-11-26 16:50:49 +00:00
|
|
|
updatesector(pp->posx, pp->posy, &pp->cursector);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// in case you are in a whirlpool
|
|
|
|
// move perfectly with the ride in the z direction
|
|
|
|
if TEST(pp->Flags, PF_CRAWLING)
|
|
|
|
{
|
|
|
|
// move up some for really fast moving plats
|
|
|
|
//pp->posz -= PLAYER_HEIGHT + Z(12);
|
|
|
|
DoPlayerZrange(pp);
|
|
|
|
pp->posz = pp->loz - PLAYER_CRAWL_HEIGHT;
|
2021-11-05 23:37:16 +00:00
|
|
|
pp->Actor()->s().z = pp->loz;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// move up some for really fast moving plats
|
|
|
|
//pp->posz -= Z(24);
|
|
|
|
DoPlayerZrange(pp);
|
|
|
|
|
|
|
|
if (!TEST(pp->Flags, PF_JUMPING | PF_FALLING | PF_FLYING))
|
|
|
|
{
|
|
|
|
pp->posz = pp->loz - PLAYER_HEIGHT;
|
2021-11-05 23:37:16 +00:00
|
|
|
pp->Actor()->s().z = pp->loz;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// if player was not on any sector object set Riding flag to false
|
|
|
|
RESET(pp->Flags, PF_PLAYER_RIDING);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 18:32:24 +00:00
|
|
|
void RefreshPoints(SECTOR_OBJECTp sop, int nx, int ny, bool dynamic)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
short wallcount = 0, delta_ang_from_orig;
|
2015-05-19 21:54:34 +00:00
|
|
|
short ang;
|
|
|
|
int dx,dy,x,y;
|
|
|
|
|
|
|
|
// do scaling
|
|
|
|
if (dynamic && sop->PreMoveAnimator)
|
|
|
|
(*sop->PreMoveAnimator)(sop);
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
SECTORp* sectp;
|
|
|
|
int j;
|
2015-05-19 21:54:34 +00:00
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
|
|
|
if (!TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
// move all walls in sectors back to the original position
|
2021-11-24 21:04:11 +00:00
|
|
|
for (auto& wal : wallsofsector(*sectp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
if (!(wal.extra && TEST(wal.extra, WALLFX_DONT_MOVE)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
dx = x = sop->xmid - sop->xorig[wallcount];
|
|
|
|
dy = y = sop->ymid - sop->yorig[wallcount];
|
|
|
|
|
|
|
|
if (dynamic && sop->scale_type)
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
if (!TEST(wal.extra, WALLFX_DONT_SCALE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ang = NORM_ANGLE(getangle(x - sop->xmid, y - sop->ymid));
|
|
|
|
|
|
|
|
if (sop->scale_type == SO_SCALE_RANDOM_POINT)
|
|
|
|
{
|
|
|
|
// was causing memory overwrites
|
|
|
|
//ScaleRandomPoint(sop, k, ang, x, y, &dx, &dy);
|
|
|
|
ScaleRandomPoint(sop, wallcount, ang, x, y, &dx, &dy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int xmul = (sop->scale_dist * sop->scale_x_mult)>>8;
|
|
|
|
int ymul = (sop->scale_dist * sop->scale_y_mult)>>8;
|
|
|
|
|
2021-01-04 11:36:54 +00:00
|
|
|
dx = x + MulScale(xmul, bcos(ang), 14);
|
|
|
|
dy = y + MulScale(ymul, bsin(ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wal.extra && TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
dragpoint(&wal, dx, dy);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
wal.x = dx;
|
|
|
|
wal.y = dy;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wallcount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sop->spin_speed)
|
|
|
|
{
|
|
|
|
// same as below - ignore the objects angle
|
|
|
|
// last_ang is the last true angle before SO started spinning
|
|
|
|
delta_ang_from_orig = NORM_ANGLE(sop->last_ang + sop->spin_ang - sop->ang_orig);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// angle traveling + the new spin angle all offset from the original
|
|
|
|
// angle
|
|
|
|
delta_ang_from_orig = NORM_ANGLE(sop->ang + sop->spin_ang - sop->ang_orig);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note that this delta angle is from the original angle
|
|
|
|
// nx,ny are 0 so the points are not moved, just rotated
|
|
|
|
MovePoints(sop, delta_ang_from_orig, nx, ny);
|
|
|
|
|
|
|
|
// do morphing - angle independent
|
|
|
|
if (dynamic && sop->PostMoveAnimator)
|
|
|
|
(*sop->PostMoveAnimator)(sop);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void KillSectorObjectSprites(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
|
|
|
int i;
|
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
auto actor = sop->so_actors[i];
|
2021-11-02 17:42:25 +00:00
|
|
|
sp = &actor->s();
|
|
|
|
u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// not a part of the so anymore
|
|
|
|
RESET(u->Flags, SPR_SO_ATTACHED);
|
|
|
|
|
|
|
|
if (sp->picnum == ST1 && sp->hitag == SPAWN_SPOT)
|
|
|
|
continue;
|
|
|
|
|
2021-11-02 17:42:25 +00:00
|
|
|
so_stopspriteinterpolation(sop, actor);
|
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clear the list
|
2021-11-02 17:45:21 +00:00
|
|
|
sop->so_actors[0] = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void UpdateSectorObjectSprites(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp;
|
|
|
|
int i;
|
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
|
|
|
{
|
|
|
|
auto actor = sop->so_actors[i];
|
|
|
|
sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
SetActorZ(actor, &sp->pos);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
SECTOR_OBJECTp DetectSectorObject(SECTORp sectph)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short j;
|
|
|
|
SECTORp *sectp;
|
|
|
|
SECTOR_OBJECTp sop;
|
|
|
|
|
|
|
|
|
|
|
|
// collapse the SO to a single point
|
|
|
|
// move all points to nx,ny
|
|
|
|
for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++)
|
|
|
|
{
|
2020-05-22 12:11:03 +00:00
|
|
|
if (SO_EMPTY(sop))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
|
|
|
if (sectph == *sectp)
|
|
|
|
return sop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
SECTOR_OBJECTp DetectSectorObjectByWall(WALLp wph)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SECTOR_OBJECTp sop;
|
|
|
|
|
|
|
|
// collapse the SO to a single point
|
|
|
|
// move all points to nx,ny
|
|
|
|
for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++)
|
|
|
|
{
|
2020-05-22 12:11:03 +00:00
|
|
|
if (SO_EMPTY(sop))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
SECTORp* sectp;
|
|
|
|
int j;
|
2015-05-19 21:54:34 +00:00
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
for (auto& wal : wallsofsector(*sectp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// if outer wall check the NEXTWALL also
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wal.twoSided() && wph == wal.nextWall())
|
2015-05-19 21:54:34 +00:00
|
|
|
return sop;
|
|
|
|
}
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wph == &wal)
|
2015-05-19 21:54:34 +00:00
|
|
|
return sop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void CollapseSectorObject(SECTOR_OBJECTp sop, int nx, int ny)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
int j;
|
2015-05-19 21:54:34 +00:00
|
|
|
SECTORp *sectp;
|
|
|
|
|
|
|
|
// collapse the SO to a single point
|
|
|
|
// move all points to nx,ny
|
|
|
|
for (sectp = sop->sectp, j = 0; *sectp; sectp++, j++)
|
|
|
|
{
|
|
|
|
if (!TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
// move all walls in sectors back to the original position
|
2021-11-24 21:04:11 +00:00
|
|
|
for (auto& wal : wallsofsector(*sectp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
if (TEST(wal.extra, WALLFX_DONT_MOVE))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
if (wal.extra && TEST(wal.extra, WALLFX_LOOP_OUTER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
dragpoint(&wal, nx, ny);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
wal.x = nx;
|
|
|
|
wal.y = ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void MoveZ(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short i;
|
|
|
|
SECTORp *sectp;
|
|
|
|
|
|
|
|
if (sop->bob_amt)
|
|
|
|
{
|
2020-09-02 18:56:09 +00:00
|
|
|
sop->bob_sine_ndx = (PlayClock << sop->bob_speed) & 2047;
|
2021-01-04 11:36:54 +00:00
|
|
|
sop->bob_diff = MulScale(sop->bob_amt, bsin(sop->bob_sine_ndx), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// for all sectors
|
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (sop->sectp[i]->hasU() && TEST(sop->sectp[i]->flags, SECTFU_SO_DONT_BOB))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
(*sectp)->floorz = sop->zorig_floor[i] + sop->bob_diff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_MOVE_VERTICAL))
|
|
|
|
{
|
2021-11-02 17:39:27 +00:00
|
|
|
i = AnimGetGoal (ANIM_SopZ, int(sop - SectorObject), nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
if (i < 0)
|
|
|
|
RESET(sop->flags, SOBJ_MOVE_VERTICAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_ZDIFF_MODE))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move all floors
|
|
|
|
if (TEST(sop->flags, SOBJ_ZDOWN))
|
|
|
|
{
|
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-24 21:49:00 +00:00
|
|
|
AnimSet(ANIM_Floorz, *sectp, sop->zorig_floor[i] + sop->z_tgt, sop->z_rate);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RESET(sop->flags, SOBJ_ZDOWN);
|
|
|
|
}
|
|
|
|
else if (TEST(sop->flags, SOBJ_ZUP))
|
|
|
|
{
|
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-24 21:49:00 +00:00
|
|
|
AnimSet(ANIM_Floorz, *sectp, sop->zorig_floor[i] + sop->z_tgt, sop->z_rate);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RESET(sop->flags, SOBJ_ZUP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CallbackSOsink(ANIMp ap, void *data)
|
|
|
|
{
|
|
|
|
SECTOR_OBJECTp sop;
|
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
2021-11-16 17:53:40 +00:00
|
|
|
int i, ndx;
|
|
|
|
bool found = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
int tgt_depth;
|
2021-11-24 22:01:43 +00:00
|
|
|
sectortype* srcsect = nullptr;
|
|
|
|
sectortype* destsect = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-04-08 06:25:59 +00:00
|
|
|
sop = (SECTOR_OBJECTp)data;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
for (i = 0; sop->sectp[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (sop->sectp[i]->hasU() && TEST(sop->sectp[i]->flags, SECTFU_SO_SINK_DEST))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
srcsect = sop->sectp[i];
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
ASSERT(srcsect != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
for (i = 0; sop->sectp[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
if (ap->animtype == ANIM_Floorz && ap->animindex == sectnum(sop->sectp[i]))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
destsect = sop->sectp[i];
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
ASSERT(destsect != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
destsect->floorpicnum = srcsect->floorpicnum;
|
|
|
|
destsect->floorshade = srcsect->floorshade;
|
|
|
|
// destsect->floorz = srcsect->floorz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
RESET(destsect->floorstat, FLOOR_STAT_RELATIVE);
|
|
|
|
ASSERT(destsect->hasU() && srcsect->hasU());
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 21:04:11 +00:00
|
|
|
tgt_depth = FixedToInt(srcsect->depth_fixed);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
for(auto& sect : sectors())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
if (§ == destsect)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
ndx = AnimSet(ANIM_SUdepth, destsect, IntToFixed(tgt_depth), (ap->vel << 8) >> 8);
|
2015-05-19 21:54:34 +00:00
|
|
|
AnimSetVelAdj(ndx, ap->vel_adj);
|
2020-09-09 17:52:52 +00:00
|
|
|
found = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(found);
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
SWSectIterator it(destsect);
|
2021-11-02 17:39:27 +00:00
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:39:27 +00:00
|
|
|
sp = &actor->s();
|
|
|
|
u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (!u || u->PlayerP || !TEST(u->Flags, SPR_SO_ATTACHED))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// move sprite WAY down in water
|
2021-11-02 17:39:27 +00:00
|
|
|
ndx = AnimSet(ANIM_Userz, 0, actor, -u->sz - SPRITEp_SIZE_Z(sp) - Z(100), ap->vel>>8);
|
2015-05-19 21:54:34 +00:00
|
|
|
AnimSetVelAdj(ndx, ap->vel_adj);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Take out any blocking walls
|
2021-11-24 21:04:11 +00:00
|
|
|
for(auto& wal : wallsofsector(destsect))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 21:04:11 +00:00
|
|
|
RESET(wal.cstat, CSTAT_WALL_BLOCK);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void MoveSectorObjects(SECTOR_OBJECTp sop, short locktics)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
int nx, ny;
|
2015-05-19 21:54:34 +00:00
|
|
|
short speed;
|
|
|
|
short delta_ang;
|
|
|
|
|
2020-05-01 11:29:12 +00:00
|
|
|
so_setinterpolationtics(sop, locktics);
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
if (sop->track >= SO_OPERATE_TRACK_START)
|
|
|
|
{
|
|
|
|
if (TEST(sop->flags, SOBJ_UPDATE_ONCE))
|
|
|
|
{
|
|
|
|
RESET(sop->flags, SOBJ_UPDATE_ONCE);
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, 0, 0, false);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nx = 0;
|
|
|
|
ny = 0;
|
|
|
|
|
|
|
|
// if pausing the return
|
|
|
|
if (sop->wait_tics)
|
|
|
|
{
|
|
|
|
sop->wait_tics -= locktics;
|
|
|
|
if (sop->wait_tics <= 0)
|
|
|
|
sop->wait_tics = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
delta_ang = 0;
|
|
|
|
|
|
|
|
if (sop->track > -1)
|
|
|
|
DoTrack(sop, locktics, &nx, &ny);
|
|
|
|
|
|
|
|
// get delta to target angle
|
2020-09-16 11:46:03 +00:00
|
|
|
delta_ang = getincangle(sop->ang, sop->ang_tgt);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->ang = NORM_ANGLE(sop->ang + (delta_ang >> sop->turn_speed));
|
|
|
|
delta_ang = delta_ang >> sop->turn_speed;
|
|
|
|
|
|
|
|
// move z values
|
|
|
|
MoveZ(sop);
|
|
|
|
|
|
|
|
// calculate the spin speed
|
|
|
|
speed = sop->spin_speed * locktics;
|
|
|
|
// spin_ang is incremented by the spin_speed
|
|
|
|
sop->spin_ang = NORM_ANGLE(sop->spin_ang + speed);
|
|
|
|
|
|
|
|
if (sop->spin_speed)
|
|
|
|
{
|
|
|
|
// ignore delta angle if spinning
|
|
|
|
GlobSpeedSO = speed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The actual delta from the last frame
|
|
|
|
GlobSpeedSO = speed;
|
|
|
|
GlobSpeedSO += delta_ang;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_DYNAMIC))
|
|
|
|
{
|
|
|
|
// trick tricks
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, nx, ny, true);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Update the points so there will be no warping
|
|
|
|
if (TEST(sop->flags, SOBJ_UPDATE|SOBJ_UPDATE_ONCE) ||
|
|
|
|
sop->vel ||
|
|
|
|
(sop->ang != sop->ang_tgt) ||
|
|
|
|
GlobSpeedSO)
|
|
|
|
{
|
|
|
|
RESET(sop->flags, SOBJ_UPDATE_ONCE);
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, nx, ny, false);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void DoTrack(SECTOR_OBJECTp sop, short locktics, int *nx, int *ny)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
TRACK_POINTp tpoint;
|
|
|
|
int dx, dy, dz;
|
|
|
|
int dist;
|
|
|
|
|
|
|
|
tpoint = Track[sop->track].TrackPoint + sop->point;
|
|
|
|
|
|
|
|
// calculate an angle to the target
|
|
|
|
|
|
|
|
if (sop->vel)
|
|
|
|
sop->ang_moving = sop->ang_tgt = getangle(tpoint->x - sop->xmid, tpoint->y - sop->ymid);
|
|
|
|
|
|
|
|
// NOTE: Jittery ride - try new value out here
|
|
|
|
// NOTE: Put a loop around this (locktics) to make it more acuruate
|
2021-11-05 23:37:16 +00:00
|
|
|
const int TRACK_POINT_SIZE = 200;
|
2015-05-19 21:54:34 +00:00
|
|
|
if (sop->target_dist < 100)
|
|
|
|
{
|
|
|
|
switch (tpoint->tag_low)
|
|
|
|
{
|
|
|
|
case TRACK_MATCH_EVERYTHING:
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, tpoint->tag_high, -1);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_MATCH_EVERYTHING_ONCE:
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, tpoint->tag_high, -1);
|
2015-05-19 21:54:34 +00:00
|
|
|
tpoint->tag_low = 0;
|
|
|
|
tpoint->tag_high = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_SPIN:
|
|
|
|
if (sop->spin_speed)
|
|
|
|
break;
|
|
|
|
|
|
|
|
sop->spin_speed = tpoint->tag_high;
|
|
|
|
sop->last_ang = sop->ang;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_SPIN_REVERSE:
|
|
|
|
{
|
|
|
|
if (!sop->spin_speed)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (sop->spin_speed >= 0)
|
|
|
|
{
|
|
|
|
sop->spin_speed = -sop->spin_speed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_SPIN_STOP:
|
|
|
|
if (!sop->spin_speed)
|
|
|
|
break;
|
|
|
|
|
|
|
|
sop->spin_speed = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_BOB_START:
|
|
|
|
SET(sop->flags, SOBJ_ZMID_FLOOR);
|
|
|
|
sop->bob_amt = Z(tpoint->tag_high);
|
|
|
|
sop->bob_sine_ndx = 0;
|
|
|
|
sop->bob_speed = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_BOB_STOP:
|
|
|
|
sop->bob_speed = 0;
|
|
|
|
sop->bob_sine_ndx = 0;
|
|
|
|
sop->bob_amt = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_BOB_SPEED:
|
|
|
|
sop->bob_speed = tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_REVERSE:
|
|
|
|
sop->dir *= -1;
|
|
|
|
break;
|
|
|
|
case TRACK_STOP:
|
|
|
|
sop->vel = 0;
|
|
|
|
sop->wait_tics = tpoint->tag_high * 128;
|
|
|
|
break;
|
|
|
|
case TRACK_SET_SPEED:
|
|
|
|
sop->vel = tpoint->tag_high * 256;
|
|
|
|
sop->vel_tgt = sop->vel;
|
|
|
|
break;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Controls the velocity
|
|
|
|
//
|
|
|
|
|
|
|
|
case TRACK_VEL_RATE:
|
|
|
|
sop->vel_rate = tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
case TRACK_SPEED_UP:
|
|
|
|
RESET(sop->flags, SOBJ_SLOW_DOWN | SOBJ_SPEED_UP);
|
|
|
|
if (sop->dir < 0)
|
|
|
|
{
|
|
|
|
// set target to new slower target
|
|
|
|
sop->vel_tgt = sop->vel_tgt - (tpoint->tag_high * 256);
|
|
|
|
SET(sop->flags, SOBJ_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sop->vel_tgt = sop->vel_tgt + (tpoint->tag_high * 256);
|
|
|
|
SET(sop->flags, SOBJ_SPEED_UP);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_SLOW_DOWN:
|
|
|
|
RESET(sop->flags, SOBJ_SLOW_DOWN | SOBJ_SPEED_UP);
|
|
|
|
if (sop->dir > 0)
|
|
|
|
{
|
|
|
|
sop->vel_tgt = sop->vel_tgt - (tpoint->tag_high * 256);
|
|
|
|
SET(sop->flags, SOBJ_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sop->vel_tgt = sop->vel_tgt + (tpoint->tag_high * 256);
|
|
|
|
SET(sop->flags, SOBJ_SPEED_UP);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Controls z
|
|
|
|
//
|
|
|
|
|
|
|
|
case TRACK_SO_SINK:
|
|
|
|
{
|
|
|
|
SECTORp *sectp;
|
2021-11-24 22:01:43 +00:00
|
|
|
sectortype* dest_sector = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
short i,ndx;
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
for (i = 0; sop->sectp[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (sop->sectp[i]->hasU() && TEST(sop->sectp[i]->flags, SECTFU_SO_SINK_DEST))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
dest_sector = sop->sectp[i];
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
ASSERT(dest_sector != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->bob_speed = 0;
|
|
|
|
sop->bob_sine_ndx = 0;
|
|
|
|
sop->bob_amt = 0;
|
|
|
|
|
|
|
|
//DSPRINTF(ds,"dest sector %d",dest_sector);
|
|
|
|
MONO_PRINT(ds);
|
|
|
|
|
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (sop->sectp[i]->hasU() && TEST(sop->sectp[i]->flags, SECTFU_SO_DONT_SINK))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-24 22:01:43 +00:00
|
|
|
ndx = AnimSet(ANIM_Floorz, *sectp, dest_sector->floorz, tpoint->tag_high);
|
2015-05-19 21:54:34 +00:00
|
|
|
AnimSetCallback(ndx, CallbackSOsink, sop);
|
|
|
|
AnimSetVelAdj(ndx, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_SO_FORM_WHIRLPOOL:
|
|
|
|
{
|
|
|
|
// for lowering the whirlpool in level 1
|
|
|
|
SECTORp *sectp;
|
2021-11-20 22:35:14 +00:00
|
|
|
int i;
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-19 22:20:58 +00:00
|
|
|
if ((*sectp)->hasU())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if ((*sectp) && (*sectp)->stag == SECT_SO_FORM_WHIRLPOOL)
|
2021-11-19 22:20:58 +00:00
|
|
|
{
|
2021-11-24 21:49:00 +00:00
|
|
|
AnimSet(ANIM_Floorz, *sectp, (*sectp)->floorz + Z((*sectp)->height), 128);
|
2021-11-20 22:20:43 +00:00
|
|
|
(*sectp)->floorshade += (*sectp)->height / 6;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-19 22:20:58 +00:00
|
|
|
RESET((*sectp)->extra, SECTFX_NO_RIDE);
|
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_MOVE_VERTICAL:
|
|
|
|
{
|
|
|
|
int zr;
|
|
|
|
SET(sop->flags, SOBJ_MOVE_VERTICAL);
|
|
|
|
|
|
|
|
if (tpoint->tag_high > 0)
|
|
|
|
zr = tpoint->tag_high;
|
|
|
|
else
|
|
|
|
zr = 256;
|
|
|
|
|
|
|
|
// look at the next point
|
|
|
|
NextTrackPoint(sop);
|
|
|
|
tpoint = Track[sop->track].TrackPoint + sop->point;
|
|
|
|
|
|
|
|
// set anim
|
2021-11-02 17:39:27 +00:00
|
|
|
AnimSet(ANIM_SopZ, int(sop-SectorObject), nullptr, tpoint->z, zr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// move back to current point by reversing direction
|
|
|
|
sop->dir *= -1;
|
|
|
|
NextTrackPoint(sop);
|
|
|
|
tpoint = Track[sop->track].TrackPoint + sop->point;
|
|
|
|
sop->dir *= -1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_WAIT_FOR_EVENT:
|
|
|
|
{
|
|
|
|
if (tpoint->tag_high == -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
SET(sop->flags, SOBJ_WAIT_FOR_EVENT);
|
|
|
|
sop->save_vel = sop->vel;
|
|
|
|
sop->save_spin_speed = sop->spin_speed;
|
|
|
|
|
|
|
|
sop->vel = sop->spin_speed = 0;
|
|
|
|
// only set event if non-zero
|
|
|
|
if (tpoint->tag_high)
|
|
|
|
sop->match_event = tpoint->tag_high;
|
|
|
|
tpoint->tag_high = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_ZDIFF_MODE:
|
|
|
|
SET(sop->flags, SOBJ_ZDIFF_MODE);
|
|
|
|
sop->zdelta = Z(tpoint->tag_high);
|
|
|
|
break;
|
|
|
|
case TRACK_ZRATE:
|
|
|
|
sop->z_rate = Z(tpoint->tag_high);
|
|
|
|
break;
|
|
|
|
case TRACK_ZUP:
|
|
|
|
RESET(sop->flags, SOBJ_ZDOWN | SOBJ_ZUP);
|
|
|
|
if (sop->dir < 0)
|
|
|
|
{
|
|
|
|
sop->z_tgt = sop->z_tgt + Z(tpoint->tag_high);
|
|
|
|
SET(sop->flags, SOBJ_ZDOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sop->z_tgt = sop->z_tgt - Z(tpoint->tag_high);
|
|
|
|
SET(sop->flags, SOBJ_ZUP);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TRACK_ZDOWN:
|
|
|
|
RESET(sop->flags, SOBJ_ZDOWN | SOBJ_ZUP);
|
|
|
|
if (sop->dir > 0)
|
|
|
|
{
|
|
|
|
sop->z_tgt = sop->z_tgt + Z(tpoint->tag_high);
|
|
|
|
SET(sop->flags, SOBJ_ZDOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sop->z_tgt = sop->z_tgt - Z(tpoint->tag_high);
|
|
|
|
SET(sop->flags, SOBJ_ZUP);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the next point
|
|
|
|
NextTrackPoint(sop);
|
|
|
|
tpoint = Track[sop->track].TrackPoint + sop->point;
|
|
|
|
|
|
|
|
// calculate distance to target poing
|
|
|
|
sop->target_dist = Distance(sop->xmid, sop->ymid, tpoint->x, tpoint->y);
|
|
|
|
|
|
|
|
// calculate a new angle to the target
|
|
|
|
sop->ang_moving = sop->ang_tgt = getangle(tpoint->x - sop->xmid, tpoint->y - sop->ymid);
|
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_ZDIFF_MODE))
|
|
|
|
{
|
|
|
|
int dist;
|
|
|
|
short i;
|
|
|
|
|
|
|
|
// set dx,dy,dz up for finding the z magnitude
|
|
|
|
dx = tpoint->x;
|
|
|
|
dy = tpoint->y;
|
|
|
|
dz = tpoint->z - sop->zdelta;
|
|
|
|
|
|
|
|
// find the distance to the target (player)
|
|
|
|
dist = DIST(dx, dy, sop->xmid, sop->ymid);
|
|
|
|
|
|
|
|
// (velocity * difference between the target and the object)
|
|
|
|
// / distance
|
|
|
|
sop->z_rate = (sop->vel * (sop->zmid - dz)) / dist;
|
|
|
|
|
|
|
|
// take absolute value and convert to pixels (divide by 256)
|
|
|
|
sop->z_rate = PIXZ(labs(sop->z_rate));
|
|
|
|
|
|
|
|
if (TEST(sop->flags, SOBJ_SPRITE_OBJ))
|
|
|
|
{
|
|
|
|
// only modify zmid for sprite_objects
|
2021-11-02 17:39:27 +00:00
|
|
|
AnimSet(ANIM_SopZ, int(sop - SectorObject), nullptr, dz, sop->z_rate);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// churn through sectors setting their new z values
|
2021-11-24 22:01:43 +00:00
|
|
|
for (i = 0; sop->sectp[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 22:01:43 +00:00
|
|
|
AnimSet(ANIM_Floorz, sop->sectp[i], dz - (sop->mid_sector->floorz - sop->sectp[i]->floorz), sop->z_rate);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
// make velocity approach the target velocity
|
|
|
|
if (TEST(sop->flags, SOBJ_SPEED_UP))
|
|
|
|
{
|
|
|
|
if ((sop->vel += (locktics << sop->vel_rate)) >= sop->vel_tgt)
|
|
|
|
{
|
|
|
|
sop->vel = sop->vel_tgt;
|
|
|
|
RESET(sop->flags, SOBJ_SPEED_UP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TEST(sop->flags, SOBJ_SLOW_DOWN))
|
|
|
|
{
|
|
|
|
if ((sop->vel -= (locktics << sop->vel_rate)) <= sop->vel_tgt)
|
|
|
|
{
|
|
|
|
sop->vel = sop->vel_tgt;
|
|
|
|
RESET(sop->flags, SOBJ_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate a new x and y
|
|
|
|
if (sop->vel && !TEST(sop->flags,SOBJ_MOVE_VERTICAL))
|
|
|
|
{
|
2021-11-19 20:47:04 +00:00
|
|
|
*nx = ((sop->vel) >> 8) * locktics * bcos(sop->ang_moving) >> 14;
|
|
|
|
*ny = ((sop->vel) >> 8) * locktics * bsin(sop->ang_moving) >> 14;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
dist = Distance(sop->xmid, sop->ymid, sop->xmid + *nx, sop->ymid + *ny);
|
|
|
|
sop->target_dist -= dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void OperateSectorObjectForTics(SECTOR_OBJECTp sop, short newang, int newx, int newy, short locktics)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
SECTORp *sectp;
|
|
|
|
|
|
|
|
if (Prediction)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (sop->track < SO_OPERATE_TRACK_START)
|
|
|
|
return;
|
|
|
|
|
2020-05-01 11:29:12 +00:00
|
|
|
so_setinterpolationtics(sop, locktics);
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
if (sop->bob_amt)
|
|
|
|
{
|
2020-09-02 18:56:09 +00:00
|
|
|
sop->bob_sine_ndx = (PlayClock << sop->bob_speed) & 2047;
|
2021-01-04 11:36:54 +00:00
|
|
|
sop->bob_diff = MulScale(sop->bob_amt, bsin(sop->bob_sine_ndx), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// for all sectors
|
|
|
|
for (i = 0, sectp = &sop->sectp[0]; *sectp; sectp++, i++)
|
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (sop->sectp[i]->hasU() && TEST(sop->sectp[i]->flags, SECTFU_SO_DONT_BOB))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
(*sectp)->floorz = sop->zorig_floor[i] + sop->bob_diff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobSpeedSO = 0;
|
|
|
|
|
|
|
|
//sop->ang_tgt = newang;
|
|
|
|
sop->ang_moving = newang;
|
|
|
|
|
|
|
|
sop->spin_ang = 0;
|
|
|
|
sop->ang = newang;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, newx - sop->xmid, newy - sop->ymid, false);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void OperateSectorObject(SECTOR_OBJECTp sop, short newang, int newx, int newy)
|
2020-05-01 11:29:12 +00:00
|
|
|
{
|
|
|
|
OperateSectorObjectForTics(sop, newang, newx, newy, synctics);
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void PlaceSectorObject(SECTOR_OBJECTp sop, int newx, int newy)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-05-01 11:29:12 +00:00
|
|
|
so_setinterpolationtics(sop, synctics);
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, newx - sop->xmid, newy - sop->ymid, false);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void VehicleSetSmoke(SECTOR_OBJECTp sop, ANIMATORp animator)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SECTORp *sectp;
|
|
|
|
SPRITEp sp;
|
|
|
|
USERp u;
|
|
|
|
|
|
|
|
for (sectp = sop->sectp; *sectp; sectp++)
|
|
|
|
{
|
2021-11-11 19:20:00 +00:00
|
|
|
SWSectIterator it(*sectp);
|
2021-10-30 18:00:02 +00:00
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 18:00:02 +00:00
|
|
|
USERp u = actor->u();
|
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
switch (sp->hitag)
|
|
|
|
{
|
|
|
|
|
|
|
|
case SPAWN_SPOT:
|
|
|
|
if (sp->clipdist == 3)
|
|
|
|
{
|
|
|
|
if (animator)
|
|
|
|
{
|
|
|
|
if (sp->statnum == STAT_NO_STATE)
|
|
|
|
break;
|
|
|
|
|
2021-10-30 18:00:02 +00:00
|
|
|
change_actor_stat(actor, STAT_NO_STATE);
|
2015-05-19 21:54:34 +00:00
|
|
|
DoSoundSpotMatch(sp->lotag, 1, 0);
|
|
|
|
DoSpawnSpotsForDamage(sp->lotag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-30 18:00:02 +00:00
|
|
|
change_actor_stat(actor, STAT_SPAWN_SPOT);
|
2015-05-19 21:54:34 +00:00
|
|
|
DoSoundSpotStopSound(sp->lotag);
|
|
|
|
}
|
|
|
|
|
|
|
|
u->ActorActionFunc = animator;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void KillSectorObject(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int newx = MAXSO;
|
|
|
|
int newy = MAXSO;
|
|
|
|
short newang = 0;
|
|
|
|
|
|
|
|
if (sop->track < SO_OPERATE_TRACK_START)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sop->ang_tgt = sop->ang_moving = newang;
|
|
|
|
|
|
|
|
sop->spin_ang = 0;
|
|
|
|
sop->ang = sop->ang_tgt;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, newx - sop->xmid, newy - sop->ymid, false);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void TornadoSpin(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
short delta_ang, speed;
|
|
|
|
short locktics = synctics;
|
|
|
|
|
|
|
|
// get delta to target angle
|
2020-09-16 11:46:03 +00:00
|
|
|
delta_ang = getincangle(sop->ang, sop->ang_tgt);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sop->ang = NORM_ANGLE(sop->ang + (delta_ang >> sop->turn_speed));
|
|
|
|
delta_ang = delta_ang >> sop->turn_speed;
|
|
|
|
|
|
|
|
// move z values
|
|
|
|
MoveZ(sop);
|
|
|
|
|
|
|
|
// calculate the spin speed
|
|
|
|
speed = sop->spin_speed * locktics;
|
|
|
|
// spin_ang is incremented by the spin_speed
|
|
|
|
sop->spin_ang = NORM_ANGLE(sop->spin_ang + speed);
|
|
|
|
|
|
|
|
if (sop->spin_speed)
|
|
|
|
{
|
|
|
|
// ignore delta angle if spinning
|
|
|
|
GlobSpeedSO = speed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The actual delta from the last frame
|
|
|
|
GlobSpeedSO = speed;
|
|
|
|
GlobSpeedSO += delta_ang;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void DoTornadoObject(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int xvect,yvect;
|
|
|
|
// this made them move together more or less - cool!
|
|
|
|
//static short ang = 1024;
|
|
|
|
int floor_dist;
|
SW: setsprite, setspritez, getzrange, clipmove, pushmove, neartag, dragpoint, screencapture, md_tilehasmodel, preparemirror, saveboard, loadboard, pos
git-svn-id: https://svn.eduke32.com/eduke32@5201 1a8010ca-5511-0410-912e-c29ae57300e0
2015-05-19 22:00:38 +00:00
|
|
|
vec3_t pos;
|
2015-05-19 21:54:34 +00:00
|
|
|
int ret;
|
|
|
|
short *ang = &sop->ang_moving;
|
|
|
|
|
2020-11-15 10:37:20 +00:00
|
|
|
xvect = sop->vel * bcos(*ang);
|
|
|
|
yvect = sop->vel * bcos(*ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 22:07:02 +00:00
|
|
|
auto cursect = sop->op_main_sector; // for sop->vel
|
|
|
|
floor_dist = (abs(cursect->ceilingz - cursect->floorz)) >> 2;
|
SW: setsprite, setspritez, getzrange, clipmove, pushmove, neartag, dragpoint, screencapture, md_tilehasmodel, preparemirror, saveboard, loadboard, pos
git-svn-id: https://svn.eduke32.com/eduke32@5201 1a8010ca-5511-0410-912e-c29ae57300e0
2015-05-19 22:00:38 +00:00
|
|
|
pos.x = sop->xmid;
|
|
|
|
pos.y = sop->ymid;
|
|
|
|
pos.z = floor_dist;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-03-07 13:51:49 +00:00
|
|
|
PlaceSectorObject(sop, MAXSO, MAXSO);
|
2021-11-26 15:08:12 +00:00
|
|
|
Collision coll;
|
|
|
|
clipmove(pos, &cursect, xvect, yvect, (int)sop->clipdist, Z(0), floor_dist, CLIPMASK_ACTOR, coll);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 15:08:12 +00:00
|
|
|
if (coll.type != kHitNone)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
*ang = NORM_ANGLE(*ang + 1024 + RANDOM_P2(512) - 256);
|
|
|
|
}
|
|
|
|
|
|
|
|
TornadoSpin(sop);
|
2020-09-09 17:52:52 +00:00
|
|
|
RefreshPoints(sop, pos.x - sop->xmid, pos.y - sop->ymid, true);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void DoAutoTurretObject(SECTOR_OBJECTp sop)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 19:07:53 +00:00
|
|
|
auto actor = sop->sp_child;
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
short delta_ang;
|
|
|
|
int diff;
|
|
|
|
short i;
|
|
|
|
|
2020-01-21 21:03:04 +00:00
|
|
|
if ((sop->max_damage != -9999 && sop->max_damage <= 0) || !u)
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
u->WaitTics -= synctics;
|
|
|
|
|
|
|
|
// check for new player if doesn't have a target or time limit expired
|
2021-10-30 22:53:23 +00:00
|
|
|
if (!u->targetActor || u->WaitTics < 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// 4 seconds
|
|
|
|
u->WaitTics = 4*120;
|
2021-10-30 11:05:07 +00:00
|
|
|
DoActorPickClosePlayer(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (MoveSkip2 == 0)
|
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
auto sActor = sop->so_actors[i];
|
|
|
|
auto shootp = &sActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
if (shootp->statnum == STAT_SO_SHOOT_POINT)
|
|
|
|
{
|
2021-11-24 17:35:42 +00:00
|
|
|
if (!FAFcansee(shootp->x, shootp->y, shootp->z-Z(4), shootp->sector(),
|
|
|
|
u->targetActor->s().x, u->targetActor->s().y, ActorUpper(u->targetActor), u->targetActor->s().sector()))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FirePausing
|
|
|
|
if (u->Counter > 0)
|
|
|
|
{
|
|
|
|
u->Counter -= synctics*2;
|
|
|
|
if (u->Counter <= 0)
|
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u->Counter == 0)
|
|
|
|
{
|
2021-11-02 17:45:21 +00:00
|
|
|
for (i = 0; sop->so_actors[i] != nullptr; i++)
|
|
|
|
{
|
|
|
|
auto sActor = sop->so_actors[i];
|
|
|
|
auto shootp = &sActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:45:21 +00:00
|
|
|
if (shootp->statnum == STAT_SO_SHOOT_POINT)
|
|
|
|
{
|
2015-05-19 21:54:34 +00:00
|
|
|
if (SP_TAG5(shootp))
|
|
|
|
u->Counter = SP_TAG5(shootp);
|
|
|
|
else
|
|
|
|
u->Counter = 12;
|
|
|
|
InitTurretMgun(sop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-30 11:16:40 +00:00
|
|
|
//sop->ang_tgt = getangle(sop->xmid - u->targetActor->s().x, sop->ymid - u->targetActor->s().y);
|
|
|
|
sop->ang_tgt = getangle(u->targetActor->s().x - sop->xmid, u->targetActor->s().y - sop->ymid);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// get delta to target angle
|
2020-09-16 11:46:03 +00:00
|
|
|
delta_ang = getincangle(sop->ang, sop->ang_tgt);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
//sop->ang += delta_ang >> 4;
|
|
|
|
sop->ang = NORM_ANGLE(sop->ang + (delta_ang >> 3));
|
|
|
|
//sop->ang += delta_ang >> 2;
|
|
|
|
|
|
|
|
if (sop->limit_ang_center >= 0)
|
|
|
|
{
|
2020-09-16 11:46:03 +00:00
|
|
|
diff = getincangle(sop->limit_ang_center, sop->ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (labs(diff) >= sop->limit_ang_delta)
|
|
|
|
{
|
|
|
|
if (diff < 0)
|
|
|
|
sop->ang = sop->limit_ang_center - sop->limit_ang_delta;
|
|
|
|
else
|
|
|
|
sop->ang = sop->limit_ang_center + sop->limit_ang_delta;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-01 11:29:12 +00:00
|
|
|
OperateSectorObjectForTics(sop, sop->ang, sop->xmid, sop->ymid, 2*synctics);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void DoActorHitTrackEndPoint(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
auto u = actor->u();
|
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
RESET(Track[u->track].flags, TF_TRACK_OCCUPIED);
|
|
|
|
|
|
|
|
// jump the current track & determine if you should go to another
|
|
|
|
if (TEST(u->Flags, SPR_RUN_AWAY))
|
|
|
|
{
|
|
|
|
// look for another track leading away from the player
|
2021-10-30 12:49:15 +00:00
|
|
|
u->track = FindTrackAwayFromPlayer(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (u->track >= 0)
|
|
|
|
{
|
|
|
|
sp->ang = NORM_ANGLE(getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RESET(u->Flags, SPR_RUN_AWAY);
|
2021-10-30 10:09:34 +00:00
|
|
|
DoActorSetSpeed(actor, NORM_SPEED);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->track = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TEST(u->Flags, SPR_FIND_PLAYER))
|
|
|
|
{
|
|
|
|
// look for another track leading away from the player
|
2021-10-30 12:49:15 +00:00
|
|
|
u->track = FindTrackToPlayer(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (u->track >= 0)
|
|
|
|
{
|
|
|
|
sp->ang = NORM_ANGLE(getangle((Track[u->track].TrackPoint + u->point)->x - sp->x, (Track[u->track].TrackPoint + u->point)->y - sp->y));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RESET(u->Flags, SPR_FIND_PLAYER);
|
2021-10-30 10:09:34 +00:00
|
|
|
DoActorSetSpeed(actor, NORM_SPEED);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->track = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-20 06:44:48 +00:00
|
|
|
u->track = -1;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
void ActorLeaveTrack(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (u->track == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RESET(u->Flags, SPR_FIND_PLAYER|SPR_RUN_AWAY|SPR_CLIMBING);
|
|
|
|
RESET(Track[u->track].flags, TF_TRACK_OCCUPIED);
|
|
|
|
u->track = -1;
|
|
|
|
}
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
bool ActorTrackDecide(TRACK_POINTp tpoint, DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp;
|
2021-11-05 23:37:16 +00:00
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
switch (tpoint->tag_low)
|
|
|
|
{
|
|
|
|
case TRACK_START:
|
|
|
|
|
|
|
|
// if track has a type and actor is going the right direction jump
|
|
|
|
// the track
|
|
|
|
if (Track[u->track].ttflags)
|
|
|
|
{
|
|
|
|
if (u->track_dir == -1)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
DoActorHitTrackEndPoint(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_END:
|
|
|
|
// if track has a type and actor is going to right direction jump the
|
|
|
|
// track
|
|
|
|
if (Track[u->track].ttflags)
|
|
|
|
{
|
|
|
|
if (u->track_dir == 1)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
DoActorHitTrackEndPoint(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case TRACK_ACTOR_WAIT_FOR_PLAYER:
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_WAIT_FOR_PLAYER);
|
|
|
|
u->Dist = tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_ACTOR_WAIT_FOR_TRIGGER:
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_WAIT_FOR_TRIGGER);
|
|
|
|
u->Dist = tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Controls the velocity
|
|
|
|
//
|
|
|
|
|
|
|
|
case TRACK_ACTOR_VEL_RATE:
|
|
|
|
u->vel_rate = tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
case TRACK_ACTOR_SPEED_UP:
|
|
|
|
RESET(u->Flags, SPR_SLOW_DOWN | SPR_SPEED_UP);
|
|
|
|
if (u->track_dir < 0)
|
|
|
|
{
|
|
|
|
// set target to new slower target
|
|
|
|
u->vel_tgt = u->vel_tgt - (tpoint->tag_high * 256);
|
|
|
|
SET(u->Flags, SPR_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->vel_tgt = u->vel_tgt + (tpoint->tag_high * 256);
|
|
|
|
SET(u->Flags, SPR_SPEED_UP);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_SLOW_DOWN:
|
|
|
|
RESET(u->Flags, SPR_SLOW_DOWN | SPR_SPEED_UP);
|
|
|
|
if (u->track_dir > 0)
|
|
|
|
{
|
|
|
|
u->vel_tgt = u->vel_tgt - (tpoint->tag_high * 256);
|
|
|
|
SET(u->Flags, SPR_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->vel_tgt = u->vel_tgt + (tpoint->tag_high * 256);
|
|
|
|
SET(u->Flags, SPR_SPEED_UP);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Reverse it
|
|
|
|
case TRACK_ACTOR_REVERSE:
|
|
|
|
u->track_dir *= -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_STAND:
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Stand);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_JUMP:
|
|
|
|
if (u->ActorActionSet->Jump)
|
|
|
|
{
|
|
|
|
sp->ang = tpoint->ang;
|
|
|
|
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->jump_speed = ACTOR_STD_JUMP;
|
|
|
|
else
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->ActorActionFunc = DoActorMoveJump;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_QUICK_JUMP:
|
|
|
|
case TRACK_ACTOR_QUICK_SUPER_JUMP:
|
|
|
|
if (u->ActorActionSet->Jump)
|
|
|
|
{
|
2015-05-19 22:01:22 +00:00
|
|
|
int zdiff;
|
2021-12-06 11:24:22 +00:00
|
|
|
HitInfo hit{};
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sp->ang = tpoint->ang;
|
|
|
|
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (tpoint->tag_high)
|
|
|
|
{
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RESET(sp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
2021-11-24 23:09:11 +00:00
|
|
|
FAFhitscan(sp->x, sp->y, sp->z - Z(24), sp->sector(), // Start position
|
2020-11-15 10:37:20 +00:00
|
|
|
bcos(sp->ang), // X vector of 3D ang
|
|
|
|
bsin(sp->ang), // Y vector of 3D ang
|
|
|
|
0, // Z vector of 3D ang
|
2021-11-26 00:27:44 +00:00
|
|
|
hit, CLIPMASK_MISSILE);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(sp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
2021-11-26 00:27:44 +00:00
|
|
|
ASSERT(hit.hitSector != nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 00:27:44 +00:00
|
|
|
if (hit.actor() != nullptr)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 00:27:44 +00:00
|
|
|
if (hit.hitWall == nullptr)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-05 20:31:19 +00:00
|
|
|
if (!hit.hitWall->twoSided())
|
2021-12-05 06:21:28 +00:00
|
|
|
return false;
|
|
|
|
|
2021-11-26 00:27:44 +00:00
|
|
|
zdiff = labs(sp->z - hit.hitWall->nextSector()->floorz) >> 8;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:56:26 +00:00
|
|
|
u->jump_speed = PickJumpSpeed(actor, zdiff);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->ActorActionFunc = DoActorMoveJump;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_QUICK_JUMP_DOWN:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->Jump)
|
|
|
|
{
|
|
|
|
sp->ang = tpoint->ang;
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (tpoint->tag_high)
|
|
|
|
{
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->jump_speed = -350;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->ActorActionFunc = DoActorMoveJump;
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_QUICK_SCAN:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->Jump)
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_QUICK_DUCK:
|
|
|
|
|
|
|
|
if (u->Rot != u->ActorActionSet->Duck)
|
|
|
|
{
|
|
|
|
sp->ang = tpoint->ang;
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 4 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
InitActorDuck(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->ActorActionFunc = DoActorDuck;
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_OPERATE:
|
|
|
|
case TRACK_ACTOR_QUICK_OPERATE:
|
|
|
|
{
|
2021-11-26 18:30:32 +00:00
|
|
|
HitInfo near;
|
2015-05-19 21:54:34 +00:00
|
|
|
int z[2];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (u->Rot == u->ActorActionSet->Sit || u->Rot == u->ActorActionSet->Stand)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sp->ang = tpoint->ang;
|
|
|
|
|
|
|
|
z[0] = sp->z - SPRITEp_SIZE_Z(sp) + Z(5);
|
|
|
|
z[1] = sp->z - DIV2(SPRITEp_SIZE_Z(sp));
|
|
|
|
|
|
|
|
for (i = 0; i < (int)SIZ(z); i++)
|
|
|
|
{
|
2021-11-26 18:30:32 +00:00
|
|
|
neartag({ sp->x, sp->y, z[i] }, sp->sector(), sp->ang, near, 1024, NTAG_SEARCH_LO_HI);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 18:30:32 +00:00
|
|
|
if (near.actor() != nullptr && near.hitpos.x < 1024)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-26 18:30:32 +00:00
|
|
|
if (OperateSprite(near.actor(), false))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 2 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Stand);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-26 18:30:32 +00:00
|
|
|
if (near.hitSector != nullptr && near.hitpos.x < 1024)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-26 18:30:32 +00:00
|
|
|
if (OperateSector(near.hitSector, false))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 2 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Sit);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_ACTOR_JUMP_IF_FORWARD:
|
|
|
|
if (u->ActorActionSet->Jump && u->track_dir == 1)
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->jump_speed = ACTOR_STD_JUMP;
|
|
|
|
else
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_JUMP_IF_REVERSE:
|
|
|
|
if (u->ActorActionSet->Jump && u->track_dir == -1)
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->jump_speed = ACTOR_STD_JUMP;
|
|
|
|
else
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_CRAWL:
|
|
|
|
if (u->Rot != u->ActorActionSet->Crawl)
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Crawl);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Rise);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_SWIM:
|
|
|
|
if (u->Rot != u->ActorActionSet->Swim)
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Swim);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Rise);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_FLY:
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Fly);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_SIT:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->Sit)
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 3 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Sit);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_DEATH1:
|
|
|
|
if (u->ActorActionSet->Death2)
|
|
|
|
{
|
|
|
|
u->WaitTics = 4 * 120;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Death1);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_DEATH2:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->Death2)
|
|
|
|
{
|
|
|
|
u->WaitTics = 4 * 120;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Death2);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_DEATH_JUMP:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->DeathJump)
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_DEAD);
|
|
|
|
sp->xvel <<= 1;
|
|
|
|
u->jump_speed = -495;
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->DeathJump);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_CLOSE_ATTACK1:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->CloseAttack[0])
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 2 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->CloseAttack[0]);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_CLOSE_ATTACK2:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->CloseAttack[1])
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 4 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->CloseAttack[1]);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_ATTACK1:
|
|
|
|
case TRACK_ACTOR_ATTACK2:
|
|
|
|
case TRACK_ACTOR_ATTACK3:
|
|
|
|
case TRACK_ACTOR_ATTACK4:
|
|
|
|
case TRACK_ACTOR_ATTACK5:
|
|
|
|
case TRACK_ACTOR_ATTACK6:
|
|
|
|
{
|
|
|
|
STATEp **ap = &u->ActorActionSet->Attack[0] + (tpoint->tag_low - TRACK_ACTOR_ATTACK1);
|
|
|
|
|
|
|
|
|
|
|
|
if (*ap)
|
|
|
|
{
|
|
|
|
if (!tpoint->tag_high)
|
|
|
|
u->WaitTics = 4 * 120;
|
|
|
|
else
|
|
|
|
u->WaitTics = tpoint->tag_high * 128;
|
|
|
|
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, *ap);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TRACK_ACTOR_ZDIFF_MODE:
|
|
|
|
if (TEST(u->Flags, SPR_ZDIFF_MODE))
|
|
|
|
{
|
|
|
|
RESET(u->Flags, SPR_ZDIFF_MODE);
|
2021-11-19 21:03:18 +00:00
|
|
|
sp->z = sp->sector()->floorz;
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->zvel = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_ZDIFF_MODE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_CLIMB_LADDER:
|
|
|
|
|
|
|
|
if (u->ActorActionSet->Jump)
|
|
|
|
{
|
|
|
|
int bos_z,nx,ny;
|
|
|
|
SPRITEp lsp;
|
2021-11-26 18:30:32 +00:00
|
|
|
HitInfo near;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Get angle and x,y pos from CLIMB_MARKER
|
|
|
|
//
|
2021-11-01 20:14:05 +00:00
|
|
|
auto lActor = FindNearSprite(actor, STAT_CLIMB_MARKER);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 20:14:05 +00:00
|
|
|
if (!lActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-11-01 20:14:05 +00:00
|
|
|
lsp = &lActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// determine where the player is supposed to be in relation to the ladder
|
|
|
|
// move out in front of the ladder
|
|
|
|
nx = MOVEx(100, lsp->ang);
|
|
|
|
ny = MOVEy(100, lsp->ang);
|
|
|
|
|
|
|
|
sp->x = lsp->x + nx;
|
|
|
|
sp->y = lsp->y + ny;
|
|
|
|
|
|
|
|
sp->ang = NORM_ANGLE(lsp->ang + 1024);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the z height to climb
|
|
|
|
//
|
|
|
|
|
2021-11-26 18:30:32 +00:00
|
|
|
neartag({ sp->x, sp->y, SPRITEp_TOS(sp) - DIV2(SPRITEp_SIZE_Z(sp)) }, sp->sector(), sp->ang, near, 600, NTAG_SEARCH_LO_HI);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 18:30:32 +00:00
|
|
|
if (near.hitWall == nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-11-26 18:30:32 +00:00
|
|
|
auto wal = near.hitWall;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#if DEBUG
|
2021-11-24 20:39:35 +00:00
|
|
|
if (!wal->twoSided())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 20:20:22 +00:00
|
|
|
I_Error("Take out white wall ladder x = %d, y = %d",wal->x, wal->y);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// destination z for climbing
|
2021-11-24 20:20:22 +00:00
|
|
|
if (wal->twoSided())
|
|
|
|
u->sz = wal->nextSector()->floorz;
|
|
|
|
else
|
|
|
|
u->sz = wal->sectorp()->ceilingz; // don't crash on bad setups.
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:47:13 +00:00
|
|
|
DoActorZrange(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Adjust for YCENTERING
|
|
|
|
//
|
|
|
|
|
|
|
|
SET(sp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
bos_z = SPRITEp_BOS(sp);
|
|
|
|
if (bos_z > u->loz)
|
|
|
|
{
|
|
|
|
u->sy = (bos_z - sp->z);
|
|
|
|
sp->z -= u->sy;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Misc climb setup
|
|
|
|
//
|
|
|
|
|
|
|
|
SET(u->Flags, SPR_CLIMBING);
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Climb);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sp->zvel = -Z(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRACK_ACTOR_SET_JUMP:
|
|
|
|
u->jump_speed = -tpoint->tag_high;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
!AIC - This is where actors follow tracks. Its massy, hard to read, and more
|
|
|
|
complex than it needs to be. It was taken from sector object track movement
|
|
|
|
code. The routine above ActorTrackDecide() is where a track tag is recognized
|
|
|
|
and acted upon. There are quite a few of these that are not useful to us at
|
|
|
|
present time.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2021-11-01 13:36:46 +00:00
|
|
|
int ActorFollowTrack(DSWActor* actor, short locktics)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 13:36:46 +00:00
|
|
|
USERp u = actor->u();
|
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
PLAYERp pp;
|
|
|
|
|
|
|
|
TRACK_POINTp tpoint;
|
|
|
|
short pnum;
|
|
|
|
int nx = 0, ny = 0, nz = 0, dx, dy, dz;
|
|
|
|
int dist;
|
|
|
|
|
|
|
|
// if not on a track then better not go here
|
|
|
|
if (u->track == -1)
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// if lying in wait for player
|
|
|
|
if (TEST(u->Flags, SPR_WAIT_FOR_PLAYER | SPR_WAIT_FOR_TRIGGER))
|
|
|
|
{
|
|
|
|
if (TEST(u->Flags, SPR_WAIT_FOR_PLAYER))
|
|
|
|
{
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
pp = &Player[pnum];
|
|
|
|
|
|
|
|
if (Distance(sp->x, sp->y, pp->posx, pp->posy) < u->Dist)
|
|
|
|
{
|
2021-10-30 11:15:02 +00:00
|
|
|
u->targetActor = pp->Actor();
|
2015-05-19 21:54:34 +00:00
|
|
|
RESET(u->Flags, SPR_WAIT_FOR_PLAYER);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u->Tics = 0;
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if pausing the return
|
|
|
|
if (u->WaitTics)
|
|
|
|
{
|
|
|
|
u->WaitTics -= locktics;
|
|
|
|
if (u->WaitTics <= 0)
|
|
|
|
{
|
|
|
|
RESET(u->Flags, SPR_DONT_UPDATE_ANG);
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, u->ActorActionSet->Run);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->WaitTics = 0;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tpoint = Track[u->track].TrackPoint + u->point;
|
|
|
|
|
|
|
|
if (!(TEST(u->Flags, SPR_CLIMBING | SPR_DONT_UPDATE_ANG)))
|
|
|
|
{
|
|
|
|
sp->ang = getangle(tpoint->x - sp->x, tpoint->y - sp->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dist = Distance(sp->x, sp->y, tpoint->x, tpoint->y)) < 200) // 64
|
|
|
|
{
|
2021-11-05 23:37:16 +00:00
|
|
|
if (!ActorTrackDecide(tpoint, actor))
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// get the next point
|
2021-11-05 23:37:16 +00:00
|
|
|
NextActorTrackPoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
tpoint = Track[u->track].TrackPoint + u->point;
|
|
|
|
|
|
|
|
if (!(TEST(u->Flags, SPR_CLIMBING | SPR_DONT_UPDATE_ANG)))
|
|
|
|
{
|
|
|
|
// calculate a new angle to the target
|
|
|
|
sp->ang = getangle(tpoint->x - sp->x, tpoint->y - sp->y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_ZDIFF_MODE))
|
|
|
|
{
|
|
|
|
int dist;
|
|
|
|
|
|
|
|
// set dx,dy,dz up for finding the z magnitude
|
|
|
|
dx = tpoint->x;
|
|
|
|
dy = tpoint->y;
|
|
|
|
dz = tpoint->z;
|
|
|
|
|
|
|
|
// find the distance to the target (player)
|
|
|
|
dist = DIST(dx, dy, sp->x, sp->y);
|
|
|
|
|
|
|
|
// (velocity * difference between the target and the object) /
|
|
|
|
// distance
|
|
|
|
sp->zvel = -((sp->xvel * (sp->z - dz)) / dist);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// make velocity approach the target velocity
|
|
|
|
if (TEST(u->Flags, SPR_SPEED_UP))
|
|
|
|
{
|
|
|
|
if ((u->track_vel += (locktics << u->vel_rate)) >= u->vel_tgt)
|
|
|
|
{
|
|
|
|
u->track_vel = u->vel_tgt;
|
|
|
|
RESET(u->Flags, SPR_SPEED_UP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the real velocity
|
2021-11-19 20:47:04 +00:00
|
|
|
sp->xvel = (u->track_vel) >> 8;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else if (TEST(u->Flags, SPR_SLOW_DOWN))
|
|
|
|
{
|
|
|
|
if ((u->track_vel -= (locktics << u->vel_rate)) <= u->vel_tgt)
|
|
|
|
{
|
|
|
|
u->track_vel = u->vel_tgt;
|
|
|
|
RESET(u->Flags, SOBJ_SLOW_DOWN);
|
|
|
|
}
|
|
|
|
|
2021-11-19 20:47:04 +00:00
|
|
|
sp->xvel = (u->track_vel) >> 8;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nx = 0;
|
|
|
|
ny = 0;
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_CLIMBING))
|
|
|
|
{
|
2021-11-19 20:47:04 +00:00
|
|
|
if (SPRITEp_TOS(sp) + (SPRITEp_SIZE_Z(sp) >> 2) < u->sz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
RESET(u->Flags, SPR_CLIMBING);
|
|
|
|
|
|
|
|
sp->zvel = 0;
|
|
|
|
|
|
|
|
sp->ang = getangle(tpoint->x - sp->x, tpoint->y - sp->y);
|
|
|
|
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
RESET(sp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
sp->z += u->sy;
|
|
|
|
|
2021-10-30 10:09:34 +00:00
|
|
|
DoActorSetSpeed(actor, SLOW_SPEED);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->ActorActionFunc = NinjaJumpActionFunc;
|
|
|
|
u->jump_speed = -650;
|
2021-10-29 18:49:57 +00:00
|
|
|
DoActorBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// calculate a new x and y
|
2021-01-04 11:36:54 +00:00
|
|
|
nx = MulScale(sp->xvel, bcos(sp->ang), 14);
|
|
|
|
ny = MulScale(sp->xvel, bsin(sp->ang), 14);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nz = 0;
|
|
|
|
|
|
|
|
if (sp->zvel)
|
|
|
|
nz = sp->zvel * locktics;
|
|
|
|
}
|
|
|
|
|
2021-11-05 20:37:49 +00:00
|
|
|
u->coll = move_sprite(actor, nx, ny, nz, u->ceiling_dist, u->floor_dist, 0, locktics);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
2021-11-04 23:06:21 +00:00
|
|
|
if (u->coll.type != kHitNone)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (!TEST(u->Flags, SPR_JUMPING|SPR_FALLING))
|
2021-11-05 23:37:16 +00:00
|
|
|
ActorLeaveTrack(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "saveable.h"
|
|
|
|
|
|
|
|
static saveable_code saveable_track_code[] =
|
|
|
|
{
|
|
|
|
SAVE_CODE(DoTornadoObject),
|
|
|
|
SAVE_CODE(DoAutoTurretObject),
|
|
|
|
};
|
|
|
|
|
|
|
|
saveable_module saveable_track =
|
|
|
|
{
|
|
|
|
// code
|
|
|
|
saveable_track_code,
|
|
|
|
SIZ(saveable_track_code),
|
|
|
|
|
|
|
|
// data
|
2021-07-10 12:25:18 +00:00
|
|
|
nullptr,0
|
2015-05-19 21:54:34 +00:00
|
|
|
};
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|