mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-17 18:01:17 +00:00
275 lines
9.7 KiB
C++
275 lines
9.7 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
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
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
#include "ns.h"
|
|
|
|
#include "build.h"
|
|
|
|
#include "names2.h"
|
|
#include "game.h"
|
|
#include "tags.h"
|
|
#include "weapon.h"
|
|
#include "sprite.h"
|
|
#include "misc.h"
|
|
#include "interpso.h"
|
|
#include "render.h"
|
|
|
|
BEGIN_SW_NS
|
|
|
|
extern int GlobSpeedSO;
|
|
|
|
void CopySectorWalls(short dest_sectnum, short src_sectnum)
|
|
{
|
|
short dest_wall_num, src_wall_num, start_wall;
|
|
SECTOR_OBJECTp sop;
|
|
SECTORp *sectp;
|
|
|
|
dest_wall_num = sector[dest_sectnum].wallptr;
|
|
src_wall_num = sector[src_sectnum].wallptr;
|
|
|
|
start_wall = dest_wall_num;
|
|
|
|
do
|
|
{
|
|
wall[dest_wall_num].picnum = wall[src_wall_num].picnum;
|
|
|
|
wall[dest_wall_num].xrepeat = wall[src_wall_num].xrepeat;
|
|
wall[dest_wall_num].yrepeat = wall[src_wall_num].yrepeat;
|
|
wall[dest_wall_num].overpicnum = wall[src_wall_num].overpicnum;
|
|
wall[dest_wall_num].pal = wall[src_wall_num].pal;
|
|
wall[dest_wall_num].cstat = wall[src_wall_num].cstat;
|
|
wall[dest_wall_num].shade = wall[src_wall_num].shade;
|
|
wall[dest_wall_num].xpan_ = wall[src_wall_num].xpan_;
|
|
wall[dest_wall_num].ypan_ = wall[src_wall_num].ypan_;
|
|
wall[dest_wall_num].hitag = wall[src_wall_num].hitag;
|
|
wall[dest_wall_num].lotag = wall[src_wall_num].lotag;
|
|
wall[dest_wall_num].extra = wall[src_wall_num].extra;
|
|
|
|
uint32_t const dest_nextwall = wall[dest_wall_num].nextwall;
|
|
uint32_t const src_nextwall = wall[src_wall_num].nextwall;
|
|
|
|
if (validWallIndex(dest_nextwall) && validWallIndex(src_nextwall))
|
|
{
|
|
wall[dest_nextwall].picnum = wall[src_nextwall].picnum;
|
|
wall[dest_nextwall].xrepeat = wall[src_nextwall].xrepeat;
|
|
wall[dest_nextwall].yrepeat = wall[src_nextwall].yrepeat;
|
|
wall[dest_nextwall].overpicnum = wall[src_nextwall].overpicnum;
|
|
wall[dest_nextwall].pal = wall[src_nextwall].pal;
|
|
wall[dest_nextwall].cstat = wall[src_nextwall].cstat;
|
|
wall[dest_nextwall].shade = wall[src_nextwall].shade;
|
|
wall[dest_nextwall].xpan_ = wall[src_nextwall].xpan_;
|
|
wall[dest_nextwall].ypan_ = wall[src_nextwall].ypan_;
|
|
wall[dest_nextwall].hitag = wall[src_nextwall].hitag;
|
|
wall[dest_nextwall].lotag = wall[src_nextwall].lotag;
|
|
wall[dest_nextwall].extra = wall[src_nextwall].extra;
|
|
}
|
|
|
|
dest_wall_num = wall[dest_wall_num].point2;
|
|
src_wall_num = wall[src_wall_num].point2;
|
|
}
|
|
while (dest_wall_num != start_wall);
|
|
|
|
// TODO: Mapping a sector to the sector object to which it belongs is better
|
|
for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++)
|
|
{
|
|
if (SO_EMPTY(sop))
|
|
continue;
|
|
|
|
for (sectp = sop->sectp; *sectp; sectp++)
|
|
if (*sectp - sector == dest_sectnum)
|
|
{
|
|
so_setinterpolationtics(sop, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CopySectorMatch(short match)
|
|
{
|
|
SPRITEp dest_sp, src_sp;
|
|
SECTORp dsectp,ssectp;
|
|
int kill;
|
|
SPRITEp k;
|
|
|
|
SWStatIterator it(STAT_COPY_DEST);
|
|
while (auto dActor = it.Next())
|
|
{
|
|
dest_sp = &dActor->s();
|
|
dsectp = §or[dest_sp->sectnum];
|
|
|
|
if (match != dest_sp->lotag)
|
|
continue;
|
|
|
|
SWStatIterator it2(STAT_COPY_SOURCE);
|
|
while (auto sActor = it2.Next())
|
|
{
|
|
src_sp = &sActor->s();
|
|
|
|
if (SP_TAG2(src_sp) == SP_TAG2(dest_sp) &&
|
|
SP_TAG3(src_sp) == SP_TAG3(dest_sp))
|
|
{
|
|
ssectp = §or[src_sp->sectnum];
|
|
|
|
// !!!!!AAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHH
|
|
// Don't kill anything you don't have to
|
|
// this wall killing things on a Queue causing
|
|
// invalid situations
|
|
|
|
#if 1
|
|
// kill all sprites in the dest sector that need to be
|
|
SWSectIterator itsec(dest_sp->sectnum);
|
|
while (auto itActor = itsec.Next())
|
|
{
|
|
k = &itActor->s();
|
|
|
|
// kill anything not invisible
|
|
if (!TEST(k->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
{
|
|
if (itActor->hasU())
|
|
{
|
|
// be safe with the killing
|
|
//SetSuicide(kill);
|
|
}
|
|
else
|
|
{
|
|
SpriteQueueDelete(itActor); // new function to allow killing - hopefully
|
|
KillActor(itActor);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
CopySectorWalls(dest_sp->sectnum, src_sp->sectnum);
|
|
|
|
itsec.Reset(src_sp->sectnum);
|
|
while (auto itActor = itsec.Next())
|
|
{
|
|
auto sp = &itActor->s();
|
|
// don't move ST1 Copy Tags
|
|
if (SP_TAG1(sp) != SECT_COPY_SOURCE)
|
|
{
|
|
int sx,sy,dx,dy,src_xoff,src_yoff,trash;
|
|
|
|
// move sprites from source to dest - use center offset
|
|
|
|
// get center of src and dest sect
|
|
SectorMidPoint(src_sp->sectnum, &sx, &sy, &trash);
|
|
SectorMidPoint(dest_sp->sectnum, &dx, &dy, &trash);
|
|
|
|
// get offset
|
|
src_xoff = sx - sp->x;
|
|
src_yoff = sy - sp->y;
|
|
|
|
// move sprite to dest sector
|
|
sp->x = dx - src_xoff;
|
|
sp->y = dy - src_yoff;
|
|
|
|
// change sector
|
|
ChangeActorSect(itActor, dest_sp->sectnum);
|
|
|
|
// check to see if it moved on to a sector object
|
|
if (TEST(sector[dest_sp->sectnum].extra, SECTFX_SECTOR_OBJECT))
|
|
{
|
|
SECTOR_OBJECTp sop;
|
|
|
|
// find and add sprite to SO
|
|
sop = DetectSectorObject(§or[sp->sectnum]);
|
|
AddSpriteToSectorObject(itActor->GetSpriteIndex(), sop);
|
|
|
|
// update sprites postions so they aren't in the
|
|
// wrong place for one frame
|
|
GlobSpeedSO = 0;
|
|
RefreshPoints(sop, 0, 0, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy sector user if there is one
|
|
if (SectUser[src_sp->sectnum].Data() || SectUser[dest_sp->sectnum].Data())
|
|
{
|
|
SECT_USERp ssectu = GetSectUser(src_sp->sectnum);
|
|
SECT_USERp dsectu = GetSectUser(dest_sp->sectnum);
|
|
|
|
memcpy(dsectu, ssectu, sizeof(SECT_USER));
|
|
}
|
|
|
|
dsectp->hitag = ssectp->hitag;
|
|
dsectp->lotag = ssectp->lotag;
|
|
|
|
dsectp->floorz = ssectp->floorz;
|
|
dsectp->ceilingz = ssectp->ceilingz;
|
|
|
|
dsectp->floorshade = ssectp->floorshade;
|
|
dsectp->ceilingshade = ssectp->ceilingshade;
|
|
|
|
dsectp->floorpicnum = ssectp->floorpicnum;
|
|
dsectp->ceilingpicnum = ssectp->ceilingpicnum;
|
|
|
|
dsectp->floorheinum = ssectp->floorheinum;
|
|
dsectp->ceilingheinum = ssectp->ceilingheinum;
|
|
|
|
dsectp->floorpal = ssectp->floorpal;
|
|
dsectp->ceilingpal = ssectp->ceilingpal;
|
|
|
|
dsectp->floorxpan_ = ssectp->floorxpan_;
|
|
dsectp->ceilingxpan_ = ssectp->ceilingxpan_;
|
|
|
|
dsectp->floorypan_ = ssectp->floorypan_;
|
|
dsectp->ceilingypan_ = ssectp->ceilingypan_;
|
|
|
|
dsectp->floorstat = ssectp->floorstat;
|
|
dsectp->ceilingstat = ssectp->ceilingstat;
|
|
|
|
dsectp->extra = ssectp->extra;
|
|
dsectp->visibility = ssectp->visibility;
|
|
|
|
if (ssectp->floorpicnum == FAF_MIRROR_PIC || ssectp->ceilingpicnum == FAF_MIRROR_PIC)
|
|
{
|
|
CollectPortals(); // unavoidable. Since these portals are not static we have to reinitialize all of them.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// do this outside of processing loop for safety
|
|
|
|
// kill all matching dest
|
|
it.Reset(STAT_COPY_DEST);
|
|
while (auto dActor = it.Next())
|
|
{
|
|
if (match == dActor->s().lotag)
|
|
KillActor(dActor);
|
|
}
|
|
|
|
// kill all matching sources
|
|
it.Reset(STAT_COPY_SOURCE);
|
|
while (auto sActor = it.Next())
|
|
{
|
|
if (match == sActor->s().lotag)
|
|
KillActor(sActor);
|
|
}
|
|
|
|
}
|
|
END_SW_NS
|