2015-05-19 21:54:34 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 1997 , 2005 - 3 D 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 , 3 D 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"
2020-08-05 22:18:45 +00:00
# include "misc.h"
2021-03-25 15:45:40 +00:00
# include "hw_drawinfo.h"
2015-05-19 21:54:34 +00:00
2019-10-09 16:09:05 +00:00
BEGIN_SW_NS
2015-05-19 21:54:34 +00:00
////////////////////////////////////////////////////////////////////
//
// FLOOR ABOVE FLOOR
//
////////////////////////////////////////////////////////////////////
# define ZMAX 400
typedef struct
{
2021-11-24 22:16:28 +00:00
sectortype * sect [ ZMAX ] ;
2015-05-19 21:58:29 +00:00
int32_t zval [ ZMAX ] ;
int16_t pic [ ZMAX ] ;
int16_t zcount ;
int16_t slope [ ZMAX ] ;
2015-05-19 21:54:34 +00:00
} SAVE , * SAVEp ;
SAVE save ;
2020-09-09 18:32:24 +00:00
bool FAF_DebugView = false ;
2015-05-19 21:54:34 +00:00
2021-12-04 21:04:16 +00:00
DSWActor * insertActor ( sectortype * sect , int statnum )
2015-05-19 21:54:34 +00:00
{
2021-12-06 16:00:15 +00:00
auto pActor = static_cast < DSWActor * > ( : : InsertActor ( RUNTIME_CLASS ( DSWActor ) , sect , statnum ) ) ;
2021-11-06 11:32:19 +00:00
auto pSprite = & pActor - > s ( ) ;
2015-05-19 21:54:34 +00:00
2021-10-31 15:55:24 +00:00
pSprite - > x = pSprite - > y = pSprite - > z = 0 ;
2021-09-06 06:33:02 +00:00
pSprite - > cstat = 0 ;
pSprite - > picnum = 0 ;
pSprite - > shade = 0 ;
pSprite - > pal = 0 ;
pSprite - > clipdist = 0 ;
2021-10-31 15:55:24 +00:00
pSprite - > xrepeat = pSprite - > yrepeat = 0 ;
pSprite - > xoffset = pSprite - > yoffset = 0 ;
2021-09-06 06:33:02 +00:00
pSprite - > ang = 0 ;
pSprite - > owner = - 1 ;
2021-10-31 15:55:24 +00:00
pSprite - > xvel = pSprite - > yvel = pSprite - > zvel = 0 ;
2021-09-06 06:33:02 +00:00
pSprite - > lotag = 0 ;
pSprite - > hitag = 0 ;
pSprite - > extra = 0 ;
2015-05-19 21:54:34 +00:00
2021-11-06 11:32:19 +00:00
return pActor ;
2015-05-19 21:54:34 +00:00
}
2021-11-26 15:44:45 +00:00
bool FAF_Sector ( sectortype * sect )
2021-11-24 17:35:42 +00:00
{
SPRITEp sp ;
2021-11-26 15:44:45 +00:00
SWSectIterator it ( sect ) ;
2021-11-24 17:35:42 +00:00
while ( auto actor = it . Next ( ) )
{
sp = & actor - > s ( ) ;
if ( sp - > statnum = = STAT_FAF & &
( sp - > hitag > = VIEW_LEVEL1 & & sp - > hitag < = VIEW_LEVEL6 ) )
{
return true ;
}
}
return false ;
}
2021-11-24 22:27:20 +00:00
void SetWallWarpHitscan ( sectortype * sect )
2015-05-19 21:54:34 +00:00
{
2021-11-03 15:51:38 +00:00
DSWActor * sp_warp ;
2015-05-19 21:54:34 +00:00
2021-11-24 22:27:20 +00:00
if ( ! WarpSectorInfo ( sect , & sp_warp ) )
2015-05-19 21:54:34 +00:00
return ;
if ( ! sp_warp )
return ;
2021-11-24 22:27:20 +00:00
auto start_wall = sect - > firstWall ( ) ;
2021-11-24 19:33:47 +00:00
auto wall_num = start_wall ;
2015-05-19 21:54:34 +00:00
// Travel all the way around loop setting wall bits
do
{
2021-11-24 19:59:19 +00:00
if ( wall_num - > twoSided ( ) )
2021-11-24 19:33:47 +00:00
SET ( wall_num - > cstat , CSTAT_WALL_WARP_HITSCAN ) ;
wall_num = wall_num - > point2Wall ( ) ;
2015-05-19 21:54:34 +00:00
}
while ( wall_num ! = start_wall ) ;
}
2021-11-24 22:27:20 +00:00
void ResetWallWarpHitscan ( sectortype * sect )
2015-05-19 21:54:34 +00:00
{
2021-11-24 22:27:20 +00:00
auto start_wall = sect - > firstWall ( ) ;
2021-11-24 19:33:47 +00:00
auto wall_num = start_wall ;
2015-05-19 21:54:34 +00:00
// Travel all the way around loop setting wall bits
do
{
2021-11-24 19:33:47 +00:00
RESET ( wall_num - > cstat , CSTAT_WALL_WARP_HITSCAN ) ;
wall_num = wall_num - > point2Wall ( ) ;
2015-05-19 21:54:34 +00:00
}
while ( wall_num ! = start_wall ) ;
}
2021-11-03 23:23:05 +00:00
void
2021-11-24 23:09:11 +00:00
FAFhitscan ( int32_t x , int32_t y , int32_t z , sectortype * sect ,
2021-11-03 23:23:05 +00:00
int32_t xvect , int32_t yvect , int32_t zvect ,
2021-11-26 00:27:44 +00:00
HitInfo & hit , int32_t clipmask )
2015-05-19 21:54:34 +00:00
{
int loz , hiz ;
2021-11-24 23:20:16 +00:00
auto newsector = sect ;
2015-05-19 21:54:34 +00:00
int startclipmask = 0 ;
2020-09-09 18:32:24 +00:00
bool plax_found = false ;
2015-05-19 21:54:34 +00:00
if ( clipmask = = CLIPMASK_MISSILE )
startclipmask = CLIPMASK_WARP_HITSCAN ;
2021-11-26 00:27:44 +00:00
hitscan ( { x , y , z } , sect , { xvect , yvect , zvect } , hit , startclipmask ) ;
2015-05-19 21:54:34 +00:00
2021-11-26 00:27:44 +00:00
if ( hit . hitSector = = nullptr )
2015-05-19 21:54:34 +00:00
return ;
2021-11-26 00:27:44 +00:00
if ( hit . hitWall ! = nullptr )
2015-05-19 21:54:34 +00:00
{
// hitscan warping
2021-11-26 00:27:44 +00:00
if ( TEST ( hit . hitWall - > cstat , CSTAT_WALL_WARP_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
// back it up a bit to get a correct warp location
2021-11-26 00:27:44 +00:00
hit . hitpos . x - = xvect > > 9 ;
hit . hitpos . y - = yvect > > 9 ;
2015-05-19 21:54:34 +00:00
// warp to new x,y,z, sectnum
2021-12-12 04:44:53 +00:00
sectortype * newsect = nullptr ;
2021-11-26 00:27:44 +00:00
if ( Warp ( & hit . hitpos . x , & hit . hitpos . y , & hit . hitpos . z , & newsect ) )
2015-05-19 21:54:34 +00:00
{
// hitscan needs to pass through dest sect
2021-11-26 00:27:44 +00:00
ResetWallWarpHitscan ( newsect ) ;
2015-05-19 21:54:34 +00:00
// NOTE: This could be recursive I think if need be
2021-11-26 00:27:44 +00:00
auto pos = hit . hitpos ;
hitscan ( pos , newsect , { xvect , yvect , zvect } , hit , startclipmask ) ;
2015-05-19 21:54:34 +00:00
// reset hitscan block for dest sect
2021-11-26 00:27:44 +00:00
SetWallWarpHitscan ( newsect ) ;
2015-05-19 21:54:34 +00:00
return ;
}
else
{
2020-09-09 17:52:52 +00:00
ASSERT ( true = = false ) ;
2015-05-19 21:54:34 +00:00
}
}
}
// make sure it hit JUST a sector before doing a check
2021-11-26 00:27:44 +00:00
if ( hit . hitWall = = nullptr & & hit . actor ( ) = = nullptr )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
if ( TEST ( hit . hitSector - > extra , SECTFX_WARP_SECTOR ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
if ( TEST ( hit . hitSector - > firstWall ( ) - > cstat , CSTAT_WALL_WARP_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
// hit the floor of a sector that is a warping sector
2021-12-12 04:44:53 +00:00
sectortype * newsect = nullptr ;
2021-11-26 00:27:44 +00:00
if ( Warp ( & hit . hitpos . x , & hit . hitpos . y , & hit . hitpos . z , & newsect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
auto pos = hit . hitpos ;
hitscan ( pos , newsect , { xvect , yvect , zvect } , hit , clipmask ) ;
2015-05-19 21:54:34 +00:00
return ;
}
}
else
{
2021-12-15 18:06:43 +00:00
sectortype * newsect = nullptr ;
2021-11-26 00:27:44 +00:00
if ( WarpPlane ( & hit . hitpos . x , & hit . hitpos . y , & hit . hitpos . z , & newsect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
auto pos = hit . hitpos ;
hitscan ( pos , newsect , { xvect , yvect , zvect } , hit , clipmask ) ;
2015-05-19 21:54:34 +00:00
return ;
}
}
}
2021-11-26 00:27:44 +00:00
getzsofslopeptr ( hit . hitSector , hit . hitpos . x , hit . hitpos . y , & hiz , & loz ) ;
if ( abs ( hit . hitpos . z - loz ) < Z ( 4 ) )
2015-05-19 21:54:34 +00:00
{
2021-12-17 19:31:42 +00:00
if ( FAF_ConnectFloor ( hit . hitSector ) & & ! TEST ( hit . hitSector - > floorstat , CSTAT_SECTOR_FAF_BLOCK_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
updatesectorz ( hit . hitpos . x , hit . hitpos . y , hit . hitpos . z + Z ( 12 ) , & newsector ) ;
2020-09-09 17:52:52 +00:00
plax_found = true ;
2015-05-19 21:54:34 +00:00
}
}
2021-11-26 00:27:44 +00:00
else if ( labs ( hit . hitpos . z - hiz ) < Z ( 4 ) )
2015-05-19 21:54:34 +00:00
{
2021-12-17 19:31:42 +00:00
if ( FAF_ConnectCeiling ( hit . hitSector ) & & ! TEST ( hit . hitSector - > floorstat , CSTAT_SECTOR_FAF_BLOCK_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:27:44 +00:00
updatesectorz ( hit . hitpos . x , hit . hitpos . y , hit . hitpos . z - Z ( 12 ) , & newsector ) ;
2020-09-09 17:52:52 +00:00
plax_found = true ;
2015-05-19 21:54:34 +00:00
}
}
}
if ( plax_found )
{
2021-11-26 00:27:44 +00:00
auto pos = hit . hitpos ;
hitscan ( pos , newsector , { xvect , yvect , zvect } , hit , clipmask ) ;
2015-05-19 21:54:34 +00:00
}
}
2021-11-24 17:35:42 +00:00
bool FAFcansee ( int32_t xs , int32_t ys , int32_t zs , sectortype * sects ,
int32_t xe , int32_t ye , int32_t ze , sectortype * secte )
2015-05-19 21:54:34 +00:00
{
int loz , hiz ;
2021-11-24 17:35:42 +00:00
auto newsect = sects ;
2015-05-19 21:54:34 +00:00
int xvect , yvect , zvect ;
short ang ;
int dist ;
2020-09-09 18:32:24 +00:00
bool plax_found = false ;
2015-05-19 22:01:22 +00:00
vec3_t s = { xs , ys , zs } ;
2015-05-19 21:54:34 +00:00
2019-12-03 09:44:51 +00:00
// ASSERT(sects >= 0 && secte >= 0);
2015-05-19 21:54:34 +00:00
// early out to regular routine
2021-11-24 17:35:42 +00:00
if ( ( ! sects | | ! FAF_Sector ( sects ) ) & & ( ! secte | | ! FAF_Sector ( secte ) ) )
2015-05-19 21:54:34 +00:00
{
2020-09-09 18:28:05 +00:00
return ! ! cansee ( xs , ys , zs , sects , xe , ye , ze , secte ) ;
2015-05-19 21:54:34 +00:00
}
// get angle
ang = getangle ( xe - xs , ye - ys ) ;
// get x,y,z, vectors
2020-11-15 10:19:03 +00:00
xvect = bcos ( ang ) ;
yvect = bsin ( ang ) ;
2015-05-19 21:54:34 +00:00
// find the distance to the target
dist = ksqrt ( SQ ( xe - xs ) + SQ ( ye - ys ) ) ;
if ( dist ! = 0 )
{
if ( xe - xs ! = 0 )
2021-01-04 12:34:55 +00:00
zvect = Scale ( xvect , ze - zs , xe - xs ) ;
2015-05-19 21:54:34 +00:00
else if ( ye - ys ! = 0 )
2021-01-04 12:34:55 +00:00
zvect = Scale ( yvect , ze - zs , ye - ys ) ;
2015-05-19 21:54:34 +00:00
else
zvect = 0 ;
}
else
zvect = 0 ;
2021-12-06 11:24:22 +00:00
HitInfo hit { } ;
2021-11-26 00:01:16 +00:00
hitscan ( s , sects , { xvect , yvect , zvect } , hit , CLIPMASK_MISSILE ) ;
2015-05-19 21:54:34 +00:00
2021-11-26 00:01:16 +00:00
if ( hit . hitSector = = nullptr )
2020-09-09 17:52:52 +00:00
return false ;
2015-05-19 21:54:34 +00:00
// make sure it hit JUST a sector before doing a check
2021-11-26 00:01:16 +00:00
if ( hit . hitWall = = nullptr & & hit . actor ( ) = = nullptr )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:01:16 +00:00
getzsofslopeptr ( hit . hitSector , hit . hitpos . x , hit . hitpos . y , & hiz , & loz ) ;
if ( labs ( hit . hitpos . z - loz ) < Z ( 4 ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:01:16 +00:00
if ( FAF_ConnectFloor ( hit . hitSector ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:01:16 +00:00
updatesectorz ( hit . hitpos . x , hit . hitpos . y , hit . hitpos . z + Z ( 12 ) , & newsect ) ;
2020-09-09 17:52:52 +00:00
plax_found = true ;
2015-05-19 21:54:34 +00:00
}
}
2021-11-26 00:01:16 +00:00
else if ( labs ( hit . hitpos . z - hiz ) < Z ( 4 ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:01:16 +00:00
if ( FAF_ConnectCeiling ( hit . hitSector ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 00:01:16 +00:00
updatesectorz ( hit . hitpos . x , hit . hitpos . y , hit . hitpos . z - Z ( 12 ) , & newsect ) ;
2020-09-09 17:52:52 +00:00
plax_found = true ;
2015-05-19 21:54:34 +00:00
}
}
}
else
{
2020-09-09 18:28:05 +00:00
return ! ! cansee ( xs , ys , zs , sects , xe , ye , ze , secte ) ;
2015-05-19 21:54:34 +00:00
}
if ( plax_found )
2021-11-26 00:01:16 +00:00
return ! ! cansee ( hit . hitpos . x , hit . hitpos . y , hit . hitpos . z , newsect , xe , ye , ze , secte ) ;
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-24 23:37:05 +00:00
int GetZadjustment ( sectortype * sect , short hitag )
2015-05-19 21:54:34 +00:00
{
SPRITEp sp ;
2021-11-24 23:37:05 +00:00
if ( sect = = nullptr | | ! TEST ( sect - > extra , SECTFX_Z_ADJUST ) )
return 0 ;
2015-05-19 21:54:34 +00:00
2021-11-06 08:29:38 +00:00
SWStatIterator it ( STAT_ST1 ) ;
while ( auto itActor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-06 08:29:38 +00:00
sp = & itActor - > s ( ) ;
2015-05-19 21:54:34 +00:00
2021-11-24 23:37:05 +00:00
if ( sp - > hitag = = hitag & & sp - > sector ( ) = = sect )
2015-05-19 21:54:34 +00:00
{
return Z ( sp - > lotag ) ;
}
}
2021-11-24 23:37:05 +00:00
return 0 ;
2015-05-19 21:54:34 +00:00
}
2021-11-06 11:19:08 +00:00
bool SectorZadjust ( const Collision & ceilhit , int32_t * hiz , const Collision & florhit , int32_t * loz )
2015-05-19 21:54:34 +00:00
{
extern int PlaxCeilGlobZadjust , PlaxFloorGlobZadjust ;
int z_amt = 0 ;
2020-09-09 18:32:24 +00:00
bool SkipFAFcheck = false ;
2015-05-19 21:54:34 +00:00
2021-11-06 11:19:08 +00:00
if ( florhit . type ! = - 1 )
2015-05-19 21:54:34 +00:00
{
2021-11-06 11:19:08 +00:00
switch ( florhit . type )
2015-05-19 21:54:34 +00:00
{
2021-11-06 11:19:08 +00:00
case kHitSector :
2015-05-19 21:54:34 +00:00
{
2021-11-26 14:14:10 +00:00
auto hit_sector = florhit . hitSector ;
2015-05-19 21:54:34 +00:00
// don't jack with connect sectors
2021-11-24 23:45:55 +00:00
if ( FAF_ConnectFloor ( hit_sector ) )
2015-05-19 21:54:34 +00:00
{
// rippers were dying through the floor in $rock
2021-12-17 19:31:42 +00:00
if ( TEST ( hit_sector - > floorstat , CSTAT_SECTOR_FAF_BLOCK_HITSCAN ) )
2015-05-19 21:54:34 +00:00
break ;
2021-11-24 23:37:05 +00:00
if ( TEST ( hit_sector - > extra , SECTFX_Z_ADJUST ) )
2015-05-19 21:54:34 +00:00
{
// see if a z adjust ST1 is around
2015-05-19 22:01:22 +00:00
z_amt = GetZadjustment ( hit_sector , FLOOR_Z_ADJUST ) ;
2015-05-19 21:54:34 +00:00
if ( z_amt )
{
// explicit z adjust overrides Connect Floor
* loz + = z_amt ;
2020-09-09 17:52:52 +00:00
SkipFAFcheck = true ;
2015-05-19 21:54:34 +00:00
}
}
break ;
}
2021-11-24 23:37:05 +00:00
if ( ! TEST ( hit_sector - > extra , SECTFX_Z_ADJUST ) )
2015-05-19 21:54:34 +00:00
break ;
// see if a z adjust ST1 is around
2015-05-19 22:01:22 +00:00
z_amt = GetZadjustment ( hit_sector , FLOOR_Z_ADJUST ) ;
2015-05-19 21:54:34 +00:00
if ( z_amt )
{
// explicit z adjust overrides plax default
* loz + = z_amt ;
}
else
// default adjustment for plax
2021-12-17 19:31:42 +00:00
if ( TEST ( hit_sector - > floorstat , CSTAT_SECTOR_SKY ) )
2015-05-19 21:54:34 +00:00
{
* loz + = PlaxFloorGlobZadjust ;
}
break ;
}
}
}
2021-11-06 11:19:08 +00:00
if ( ceilhit . type ! = - 1 )
2015-05-19 21:54:34 +00:00
{
2021-11-06 11:19:08 +00:00
switch ( ceilhit . type )
2015-05-19 21:54:34 +00:00
{
2021-11-06 11:19:08 +00:00
case kHitSector :
2015-05-19 21:54:34 +00:00
{
2021-11-26 14:14:10 +00:00
auto hit_sector = ceilhit . hitSector ;
2015-05-19 21:54:34 +00:00
// don't jack with connect sectors
2021-11-24 23:45:55 +00:00
if ( FAF_ConnectCeiling ( hit_sector ) )
2015-05-19 21:54:34 +00:00
{
2021-11-24 23:37:05 +00:00
if ( TEST ( hit_sector - > extra , SECTFX_Z_ADJUST ) )
2015-05-19 21:54:34 +00:00
{
// see if a z adjust ST1 is around
2015-05-19 22:01:22 +00:00
z_amt = GetZadjustment ( hit_sector , CEILING_Z_ADJUST ) ;
2015-05-19 21:54:34 +00:00
if ( z_amt )
{
// explicit z adjust overrides Connect Floor
* loz + = z_amt ;
2020-09-09 17:52:52 +00:00
SkipFAFcheck = true ;
2015-05-19 21:54:34 +00:00
}
}
break ;
}
2021-11-24 23:37:05 +00:00
if ( ! TEST ( hit_sector - > extra , SECTFX_Z_ADJUST ) )
2015-05-19 21:54:34 +00:00
break ;
// see if a z adjust ST1 is around
2015-05-19 22:01:22 +00:00
z_amt = GetZadjustment ( hit_sector , CEILING_Z_ADJUST ) ;
2015-05-19 21:54:34 +00:00
if ( z_amt )
{
// explicit z adjust overrides plax default
* hiz - = z_amt ;
}
else
// default adjustment for plax
2021-12-17 19:31:42 +00:00
if ( TEST ( hit_sector - > ceilingstat , CSTAT_SECTOR_SKY ) )
2015-05-19 21:54:34 +00:00
{
* hiz - = PlaxCeilGlobZadjust ;
}
break ;
}
}
}
return SkipFAFcheck ;
}
2021-11-06 11:19:08 +00:00
void WaterAdjust ( const Collision & florhit , int32_t * loz )
2015-05-19 21:54:34 +00:00
{
2021-11-06 11:19:08 +00:00
if ( florhit . type = = kHitSector )
2015-05-19 21:54:34 +00:00
{
2021-11-26 14:14:10 +00:00
auto sect = florhit . hitSector ;
2021-11-19 22:20:58 +00:00
if ( ! sect - > hasU ( ) ) return ;
2015-05-19 21:54:34 +00:00
2021-11-20 22:20:43 +00:00
if ( sect - > hasU ( ) & & FixedToInt ( sect - > depth_fixed ) )
* loz + = Z ( FixedToInt ( sect - > depth_fixed ) ) ;
2015-05-19 21:54:34 +00:00
}
}
2021-11-26 19:07:42 +00:00
void FAFgetzrange ( vec3_t pos , sectortype * sect , int32_t * hiz , Collision * ceilhit , int32_t * loz , Collision * florhit , int32_t clipdist , int32_t clipmask )
2015-05-19 21:54:34 +00:00
{
int foo1 ;
2021-11-06 11:19:08 +00:00
Collision foo2 ;
2020-09-09 18:32:24 +00:00
bool SkipFAFcheck ;
2021-11-06 11:19:08 +00:00
Collision trash ; trash . invalidate ( ) ;
2015-05-19 21:54:34 +00:00
// IMPORTANT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This will return invalid FAF ceiling and floor heights inside of analyzesprite
// because the ceiling and floors get moved out of the way for drawing.
// early out to regular routine
2021-11-26 19:07:42 +00:00
if ( sect = = nullptr | | ! FAF_ConnectArea ( sect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:06:07 +00:00
getzrange ( pos , sect , hiz , * ceilhit , loz , * florhit , clipdist , clipmask ) ;
2015-05-19 21:54:34 +00:00
SectorZadjust ( * ceilhit , hiz , * florhit , loz ) ;
WaterAdjust ( * florhit , loz ) ;
return ;
}
2021-11-26 19:06:07 +00:00
getzrange ( pos , sect , hiz , * ceilhit , loz , * florhit , clipdist , clipmask ) ;
2015-05-19 21:54:34 +00:00
SkipFAFcheck = SectorZadjust ( * ceilhit , hiz , * florhit , loz ) ;
WaterAdjust ( * florhit , loz ) ;
if ( SkipFAFcheck )
return ;
2021-11-24 23:45:55 +00:00
if ( FAF_ConnectCeiling ( sect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:06:07 +00:00
auto uppersect = sect ;
2015-05-19 21:54:34 +00:00
int newz = * hiz - Z ( 2 ) ;
2021-12-01 22:30:02 +00:00
if ( ceilhit - > type = = kHitSprite ) return ;
2015-05-19 21:54:34 +00:00
2021-10-30 11:47:03 +00:00
updatesectorz ( pos . x , pos . y , newz , & uppersect ) ;
2021-11-26 19:06:07 +00:00
if ( uppersect = = nullptr )
return ;
2021-10-30 11:47:03 +00:00
vec3_t npos = pos ;
npos . z = newz ;
2021-11-26 19:06:07 +00:00
getzrange ( npos , uppersect , hiz , * ceilhit , & foo1 , foo2 , clipdist , clipmask ) ;
2021-11-06 11:19:08 +00:00
SectorZadjust ( * ceilhit , hiz , trash , nullptr ) ;
2015-05-19 21:54:34 +00:00
}
2021-12-17 19:31:42 +00:00
else if ( FAF_ConnectFloor ( sect ) & & ! TEST ( sect - > floorstat , CSTAT_SECTOR_FAF_BLOCK_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:06:07 +00:00
auto lowersect = sect ;
2015-05-19 21:54:34 +00:00
int newz = * loz + Z ( 2 ) ;
2021-12-01 22:30:02 +00:00
if ( florhit - > type = = kHitSprite ) return ;
2015-05-19 21:54:34 +00:00
2021-10-30 11:47:03 +00:00
updatesectorz ( pos . x , pos . y , newz , & lowersect ) ;
2021-11-26 19:06:07 +00:00
if ( lowersect = = nullptr )
2019-12-03 09:44:51 +00:00
return ; // _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d", x, y, newz);
2021-10-30 11:47:03 +00:00
vec3_t npos = pos ;
npos . z = newz ;
2021-11-26 19:06:07 +00:00
getzrange ( npos , lowersect , & foo1 , foo2 , loz , * florhit , clipdist , clipmask ) ;
2021-11-06 11:19:08 +00:00
SectorZadjust ( trash , nullptr , * florhit , loz ) ;
2015-05-19 21:54:34 +00:00
WaterAdjust ( * florhit , loz ) ;
}
}
2021-11-25 16:12:41 +00:00
void FAFgetzrangepoint ( int32_t x , int32_t y , int32_t z , sectortype * const sect ,
2021-11-06 11:19:08 +00:00
int32_t * hiz , Collision * ceilhit ,
int32_t * loz , Collision * florhit )
2015-05-19 21:54:34 +00:00
{
int foo1 ;
2021-11-06 11:19:08 +00:00
Collision foo2 ;
2020-09-09 18:32:24 +00:00
bool SkipFAFcheck ;
2021-11-06 11:19:08 +00:00
Collision trash ; trash . invalidate ( ) ;
2015-05-19 21:54:34 +00:00
// IMPORTANT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This will return invalid FAF ceiling and floor heights inside of analyzesprite
// because the ceiling and floors get moved out of the way for drawing.
// early out to regular routine
2021-11-24 23:45:55 +00:00
if ( ! FAF_ConnectArea ( sect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:18:30 +00:00
getzrangepoint ( x , y , z , sect , hiz , ceilhit , loz , florhit ) ;
2015-05-19 21:54:34 +00:00
SectorZadjust ( * ceilhit , hiz , * florhit , loz ) ;
WaterAdjust ( * florhit , loz ) ;
return ;
}
2021-11-26 19:18:30 +00:00
getzrangepoint ( x , y , z , sect , hiz , ceilhit , loz , florhit ) ;
2015-05-19 21:54:34 +00:00
SkipFAFcheck = SectorZadjust ( * ceilhit , hiz , * florhit , loz ) ;
WaterAdjust ( * florhit , loz ) ;
if ( SkipFAFcheck )
return ;
2021-11-24 23:45:55 +00:00
if ( FAF_ConnectCeiling ( sect ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:18:30 +00:00
auto uppersect = sect ;
2015-05-19 21:54:34 +00:00
int newz = * hiz - Z ( 2 ) ;
2021-11-06 11:19:08 +00:00
if ( ceilhit - > type = = kHitSprite )
2015-05-19 21:54:34 +00:00
return ;
2021-11-06 11:19:08 +00:00
2015-05-19 21:54:34 +00:00
updatesectorz ( x , y , newz , & uppersect ) ;
2021-11-26 19:18:30 +00:00
if ( uppersect = = nullptr )
2021-11-26 19:07:42 +00:00
return ;
2015-05-19 21:54:34 +00:00
getzrangepoint ( x , y , newz , uppersect , hiz , ceilhit , & foo1 , & foo2 ) ;
2021-11-06 11:19:08 +00:00
SectorZadjust ( * ceilhit , hiz , trash , nullptr ) ;
2015-05-19 21:54:34 +00:00
}
2021-12-17 19:31:42 +00:00
else if ( FAF_ConnectFloor ( sect ) & & ! TEST ( sect - > floorstat , CSTAT_SECTOR_FAF_BLOCK_HITSCAN ) )
2015-05-19 21:54:34 +00:00
{
2021-11-26 19:18:30 +00:00
auto lowersect = sect ;
2015-05-19 21:54:34 +00:00
int newz = * loz + Z ( 2 ) ;
2021-11-06 11:19:08 +00:00
if ( florhit - > type = = kHitSprite )
2015-05-19 21:54:34 +00:00
return ;
updatesectorz ( x , y , newz , & lowersect ) ;
2021-11-26 19:18:30 +00:00
if ( lowersect = = nullptr )
2021-11-26 19:07:42 +00:00
return ;
2015-05-19 21:54:34 +00:00
getzrangepoint ( x , y , newz , lowersect , & foo1 , & foo2 , loz , florhit ) ;
2021-11-06 11:19:08 +00:00
SectorZadjust ( trash , nullptr , * florhit , loz ) ;
2015-05-19 21:54:34 +00:00
WaterAdjust ( * florhit , loz ) ;
}
}
2021-12-11 02:49:58 +00:00
void SetupMirrorTiles ( void )
2015-05-19 21:54:34 +00:00
{
SPRITEp sp ;
2021-11-02 18:36:47 +00:00
SWStatIterator it ( STAT_FAF ) ;
while ( auto actor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2015-05-19 21:54:34 +00:00
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > ceilingpicnum = = FAF_PLACE_MIRROR_PIC )
2015-05-19 21:54:34 +00:00
{
2021-11-19 21:03:18 +00:00
sp - > sector ( ) - > ceilingpicnum = FAF_MIRROR_PIC ;
2021-12-17 19:31:42 +00:00
SET ( sp - > sector ( ) - > ceilingstat , CSTAT_SECTOR_SKY ) ;
2015-05-19 21:54:34 +00:00
}
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > floorpicnum = = FAF_PLACE_MIRROR_PIC )
2015-05-19 21:54:34 +00:00
{
2021-11-19 21:03:18 +00:00
sp - > sector ( ) - > floorpicnum = FAF_MIRROR_PIC ;
2021-12-17 19:31:42 +00:00
SET ( sp - > sector ( ) - > floorstat , CSTAT_SECTOR_SKY ) ;
2015-05-19 21:54:34 +00:00
}
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > ceilingpicnum = = FAF_PLACE_MIRROR_PIC + 1 )
sp - > sector ( ) - > ceilingpicnum = FAF_MIRROR_PIC + 1 ;
2015-05-19 21:54:34 +00:00
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > floorpicnum = = FAF_PLACE_MIRROR_PIC + 1 )
sp - > sector ( ) - > floorpicnum = FAF_MIRROR_PIC + 1 ;
2015-05-19 21:54:34 +00:00
}
}
2021-11-25 15:55:02 +00:00
void GetUpperLowerSector ( short match , int x , int y , sectortype * * upper , sectortype * * lower )
2015-05-19 21:54:34 +00:00
{
2021-03-25 15:45:40 +00:00
int i ;
2021-11-25 15:55:02 +00:00
sectortype * sectorlist [ 16 ] ;
2021-03-25 15:45:40 +00:00
int sln = 0 ;
SPRITEp sp ;
2021-11-02 18:36:47 +00:00
2021-11-25 15:55:02 +00:00
for ( auto & sect : sectors ( ) )
2021-11-02 18:36:47 +00:00
{
2021-11-25 15:55:02 +00:00
if ( inside ( x , y , & sect ) = = 1 )
2021-03-25 15:45:40 +00:00
{
bool found = false ;
2021-11-25 15:55:02 +00:00
SWSectIterator it ( & sect ) ;
2021-11-02 18:36:47 +00:00
while ( auto actor = it . Next ( ) )
2021-03-25 15:45:40 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > statnum = = STAT_FAF & &
( sp - > hitag > = VIEW_LEVEL1 & & sp - > hitag < = VIEW_LEVEL6 )
& & sp - > lotag = = match )
{
found = true ;
}
}
if ( ! found )
continue ;
2021-11-02 18:36:47 +00:00
if ( sln < ( int ) SIZ ( sectorlist ) )
2021-11-25 15:55:02 +00:00
sectorlist [ sln ] = & sect ;
2021-03-25 15:45:40 +00:00
sln + + ;
}
}
// might not find ANYTHING if not tagged right
if ( sln = = 0 )
{
2021-11-25 15:55:02 +00:00
* upper = nullptr ;
* lower = nullptr ;
2021-03-25 15:45:40 +00:00
return ;
}
// Map rooms have NOT been dragged on top of each other
else if ( sln = = 1 )
{
* lower = sectorlist [ 0 ] ;
* upper = sectorlist [ 0 ] ;
return ;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line.
else if ( sln > 2 )
{
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector ( match , x - 1 , y , upper , lower ) ;
}
if ( sln = = 2 )
{
2021-11-25 15:55:02 +00:00
if ( sectorlist [ 0 ] - > floorz < sectorlist [ 1 ] - > floorz )
2021-03-25 15:45:40 +00:00
{
// swap
// make sectorlist[0] the LOW sector
2021-11-25 15:55:02 +00:00
std : : swap ( sectorlist [ 0 ] , sectorlist [ 1 ] ) ;
2021-03-25 15:45:40 +00:00
}
* lower = sectorlist [ 0 ] ;
* upper = sectorlist [ 1 ] ;
}
}
2021-11-25 18:06:52 +00:00
bool FindCeilingView ( int match , int * x , int * y , int z , sectortype * * sect )
2021-03-25 15:45:40 +00:00
{
int xoff = 0 ;
int yoff = 0 ;
2021-07-10 12:25:18 +00:00
SPRITEp sp = nullptr ;
2021-03-25 15:45:40 +00:00
int pix_diff ;
int newz ;
save . zcount = 0 ;
2015-05-19 21:54:34 +00:00
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
2021-11-02 18:36:47 +00:00
SWStatIterator it ( STAT_FAF ) ;
while ( auto actor = it . Next ( ) )
2021-03-25 15:45:40 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > hitag = = VIEW_THRU_CEILING & & sp - > lotag = = match )
{
xoff = * x - sp - > x ;
yoff = * y - sp - > y ;
break ;
}
}
it . Reset ( STAT_FAF ) ;
2021-11-02 18:36:47 +00:00
while ( auto actor = it . Next ( ) )
2021-03-25 15:45:40 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > lotag = = match )
{
// determine x,y position
if ( sp - > hitag = = VIEW_THRU_FLOOR )
{
2021-11-25 15:55:02 +00:00
sectortype * upper , * lower ;
2021-03-25 15:45:40 +00:00
* x = sp - > x + xoff ;
* y = sp - > y + yoff ;
// get new sector
GetUpperLowerSector ( match , * x , * y , & upper , & lower ) ;
2021-11-25 18:06:52 +00:00
* sect = upper ;
2021-03-25 15:45:40 +00:00
break ;
}
}
}
2021-11-25 18:06:52 +00:00
if ( * sect = = nullptr )
2021-03-25 15:45:40 +00:00
return false ;
2021-05-10 22:59:23 +00:00
if ( ! sp | | sp - > hitag ! = VIEW_THRU_FLOOR )
{
2021-11-25 18:06:52 +00:00
* sect = nullptr ;
2021-05-10 22:59:23 +00:00
return false ;
}
2021-03-25 15:45:40 +00:00
if ( ! testnewrenderer )
{
2021-11-19 21:03:18 +00:00
pix_diff = labs ( z - sp - > sector ( ) - > floorz ) > > 8 ;
newz = sp - > sector ( ) - > floorz + ( ( pix_diff / 128 ) + 1 ) * Z ( 128 ) ;
2021-05-10 22:59:23 +00:00
2021-03-25 15:45:40 +00:00
it . Reset ( STAT_FAF ) ;
2021-11-02 18:36:47 +00:00
while ( auto actor = it . Next ( ) )
2021-03-25 15:45:40 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > lotag = = match )
{
// move lower levels ceilings up for the correct view
if ( sp - > hitag = = VIEW_LEVEL2 )
{
// save it off
2021-11-24 22:16:28 +00:00
save . sect [ save . zcount ] = sp - > sector ( ) ;
2021-11-19 21:03:18 +00:00
save . zval [ save . zcount ] = sp - > sector ( ) - > floorz ;
save . pic [ save . zcount ] = sp - > sector ( ) - > floorpicnum ;
save . slope [ save . zcount ] = sp - > sector ( ) - > floorheinum ;
2021-03-25 15:45:40 +00:00
2021-11-19 21:03:18 +00:00
sp - > sector ( ) - > floorz = newz ;
2021-03-25 15:45:40 +00:00
// don't change FAF_MIRROR_PIC - ConnectArea
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > floorpicnum ! = FAF_MIRROR_PIC )
sp - > sector ( ) - > floorpicnum = FAF_MIRROR_PIC + 1 ;
sp - > sector ( ) - > floorheinum = 0 ;
2021-03-25 15:45:40 +00:00
save . zcount + + ;
PRODUCTION_ASSERT ( save . zcount < ZMAX ) ;
}
}
}
}
return true ;
}
2021-11-25 18:06:52 +00:00
bool FindFloorView ( int match , int * x , int * y , int z , sectortype * * sect )
2021-03-25 15:45:40 +00:00
{
int xoff = 0 ;
int yoff = 0 ;
2021-07-10 12:25:18 +00:00
SPRITEp sp = nullptr ;
2021-03-25 15:45:40 +00:00
int newz ;
int pix_diff ;
save . zcount = 0 ;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
2021-11-02 18:36:47 +00:00
SWStatIterator it ( STAT_FAF ) ;
while ( auto actor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2015-05-19 21:54:34 +00:00
2021-03-25 15:45:40 +00:00
if ( sp - > hitag = = VIEW_THRU_FLOOR & & sp - > lotag = = match )
{
xoff = * x - sp - > x ;
yoff = * y - sp - > y ;
break ;
}
2015-05-19 21:54:34 +00:00
}
2021-03-25 15:45:40 +00:00
it . Reset ( STAT_FAF ) ;
2021-11-02 18:36:47 +00:00
while ( auto actor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > lotag = = match )
2015-05-19 21:54:34 +00:00
{
2021-03-25 15:45:40 +00:00
// determine x,y position
if ( sp - > hitag = = VIEW_THRU_CEILING )
{
2021-11-25 15:55:02 +00:00
sectortype * upper , * lower ;
2015-05-19 21:54:34 +00:00
2021-03-25 15:45:40 +00:00
* x = sp - > x + xoff ;
* y = sp - > y + yoff ;
2015-05-19 21:54:34 +00:00
2021-03-25 15:45:40 +00:00
// get new sector
GetUpperLowerSector ( match , * x , * y , & upper , & lower ) ;
2021-11-25 18:06:52 +00:00
* sect = lower ;
2021-03-25 15:45:40 +00:00
break ;
}
2015-05-19 21:54:34 +00:00
}
2021-03-25 15:45:40 +00:00
}
2021-11-25 18:06:52 +00:00
if ( * sect = = nullptr )
2021-03-25 15:45:40 +00:00
return false ;
2021-05-10 22:59:23 +00:00
if ( ! sp | | sp - > hitag ! = VIEW_THRU_CEILING )
{
2021-11-25 18:06:52 +00:00
* sect = nullptr ;
2021-05-10 22:59:23 +00:00
return false ;
}
2021-03-25 15:45:40 +00:00
if ( ! testnewrenderer )
{
2021-05-10 22:59:23 +00:00
// move ceiling multiple of 128 so that the wall tile will line up
2021-11-19 21:03:18 +00:00
pix_diff = labs ( z - sp - > sector ( ) - > ceilingz ) > > 8 ;
newz = sp - > sector ( ) - > ceilingz - ( ( pix_diff / 128 ) + 1 ) * Z ( 128 ) ;
2021-05-10 22:59:23 +00:00
2021-03-25 15:45:40 +00:00
it . Reset ( STAT_FAF ) ;
2021-11-02 18:36:47 +00:00
while ( auto actor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > lotag = = match )
{
// move upper levels floors down for the correct view
if ( sp - > hitag = = VIEW_LEVEL1 )
{
// save it off
2021-11-24 22:16:28 +00:00
save . sect [ save . zcount ] = sp - > sector ( ) ;
2021-11-19 21:03:18 +00:00
save . zval [ save . zcount ] = sp - > sector ( ) - > ceilingz ;
save . pic [ save . zcount ] = sp - > sector ( ) - > ceilingpicnum ;
save . slope [ save . zcount ] = sp - > sector ( ) - > ceilingheinum ;
2021-03-25 15:45:40 +00:00
2021-11-19 21:03:18 +00:00
sp - > sector ( ) - > ceilingz = newz ;
2021-03-25 15:45:40 +00:00
// don't change FAF_MIRROR_PIC - ConnectArea
2021-11-19 21:03:18 +00:00
if ( sp - > sector ( ) - > ceilingpicnum ! = FAF_MIRROR_PIC )
sp - > sector ( ) - > ceilingpicnum = FAF_MIRROR_PIC + 1 ;
sp - > sector ( ) - > ceilingheinum = 0 ;
2021-03-25 15:45:40 +00:00
save . zcount + + ;
PRODUCTION_ASSERT ( save . zcount < ZMAX ) ;
}
}
2015-05-19 21:54:34 +00:00
}
}
2021-03-25 15:45:40 +00:00
return true ;
}
2021-11-25 18:06:52 +00:00
short FindViewSectorInScene ( sectortype * cursect , short level )
2021-03-25 15:45:40 +00:00
{
SPRITEp sp ;
short match ;
2021-11-02 18:36:47 +00:00
SWStatIterator it ( STAT_FAF ) ;
while ( auto actor = it . Next ( ) )
2015-05-19 21:54:34 +00:00
{
2021-11-02 18:36:47 +00:00
sp = & actor - > s ( ) ;
2021-03-25 15:45:40 +00:00
if ( sp - > hitag = = level )
{
2021-11-25 18:06:52 +00:00
if ( cursect = = sp - > sector ( ) )
2021-03-25 15:45:40 +00:00
{
// ignore case if sprite is pointing up
if ( sp - > ang = = 1536 )
continue ;
// only gets to here is sprite is pointing down
// found a potential match
match = sp - > lotag ;
return match ;
}
}
}
return - 1 ;
}
2021-03-25 20:21:48 +00:00
struct PortalGroup
2021-03-25 15:45:40 +00:00
{
2021-03-25 20:21:48 +00:00
TArray < int > sectors ;
int othersector = - 1 ;
vec3_t offset = { 0 , 0 , 0 } ;
} ;
2021-03-25 15:45:40 +00:00
2021-03-25 20:21:48 +00:00
// This is very messy because some portals are linked outside the actual portal sectors, so we have to use the complicated original linking logic to find the connection. :?
void CollectPortals ( )
{
int t = testnewrenderer ;
testnewrenderer = true ;
TArray < PortalGroup > floorportals ;
TArray < PortalGroup > ceilingportals ;
2021-11-10 23:59:27 +00:00
BitArray floordone ( numsectors ) , ceilingdone ( numsectors ) ;
2021-03-25 20:21:48 +00:00
2021-05-20 16:52:27 +00:00
for ( int i = 0 ; i < numsectors ; i + + )
{
sector [ i ] . portalflags = sector [ i ] . portalnum = 0 ;
}
2021-03-25 20:21:48 +00:00
floordone . Zero ( ) ;
ceilingdone . Zero ( ) ;
2021-05-20 16:52:27 +00:00
portalClear ( ) ;
2021-03-25 20:21:48 +00:00
for ( int i = 0 ; i < numsectors ; i + + )
{
if ( sector [ i ] . floorpicnum = = FAF_MIRROR_PIC & & ! floordone [ i ] )
{
auto & fp = floorportals [ floorportals . Reserve ( 1 ) ] ;
fp . sectors . Push ( i ) ;
floordone . Set ( i ) ;
for ( unsigned ii = 0 ; ii < fp . sectors . Size ( ) ; ii + + )
{
2021-11-24 20:33:23 +00:00
for ( auto & wal : wallsofsector ( fp . sectors [ ii ] ) )
2021-03-25 20:21:48 +00:00
{
2021-11-24 20:33:23 +00:00
if ( ! wal . twoSided ( ) ) continue ;
auto nsec = wal . nextSector ( ) ;
auto ns = sectnum ( nsec ) ;
if ( floordone [ ns ] | | nsec - > floorpicnum ! = FAF_MIRROR_PIC ) continue ;
2021-03-25 20:21:48 +00:00
fp . sectors . Push ( ns ) ;
floordone . Set ( ns ) ;
}
}
}
if ( sector [ i ] . ceilingpicnum = = FAF_MIRROR_PIC & & ! ceilingdone [ i ] )
{
auto & fp = ceilingportals [ ceilingportals . Reserve ( 1 ) ] ;
fp . sectors . Push ( i ) ;
ceilingdone . Set ( i ) ;
for ( unsigned ii = 0 ; ii < fp . sectors . Size ( ) ; ii + + )
{
2021-11-24 20:33:23 +00:00
for ( auto & wal : wallsofsector ( fp . sectors [ ii ] ) )
2021-03-25 20:21:48 +00:00
{
2021-11-24 20:33:23 +00:00
if ( ! wal . twoSided ( ) ) continue ;
auto nsec = wal . nextSector ( ) ;
auto ns = sectnum ( nsec ) ;
if ( ceilingdone [ ns ] | | nsec - > ceilingpicnum ! = FAF_MIRROR_PIC ) continue ;
2021-03-25 20:21:48 +00:00
fp . sectors . Push ( ns ) ;
ceilingdone . Set ( ns ) ;
}
}
}
}
// now try to find connections.
for ( auto & fp : ceilingportals )
2021-03-25 15:45:40 +00:00
{
2021-03-25 20:21:48 +00:00
// pick one sprite out of the sectors, repeat until we get a valid connection
for ( auto sec : fp . sectors )
{
2021-11-05 23:48:28 +00:00
SWSectIterator it ( sec ) ;
while ( auto actor = it . Next ( ) )
2021-03-25 20:21:48 +00:00
{
2021-11-05 23:48:28 +00:00
int tx = actor - > s ( ) . x ;
int ty = actor - > s ( ) . y ;
int tz = actor - > s ( ) . z ;
2021-11-25 18:06:52 +00:00
auto tsect = & sector [ sec ] ;
2021-03-25 15:45:40 +00:00
2021-11-25 18:06:52 +00:00
int match = FindViewSectorInScene ( tsect , VIEW_LEVEL1 ) ;
2021-03-25 20:21:48 +00:00
if ( match ! = - 1 )
{
2021-11-25 18:06:52 +00:00
FindCeilingView ( match , & tx , & ty , tz , & tsect ) ;
if ( tsect ! = nullptr & & tsect - > floorpicnum = = FAF_MIRROR_PIC )
2021-03-25 20:21:48 +00:00
{
// got something!
2021-11-25 18:06:52 +00:00
fp . othersector = sectnum ( tsect ) ;
2021-03-25 20:21:48 +00:00
fp . offset = { tx , ty , tz } ;
2021-11-05 23:48:28 +00:00
fp . offset - = actor - > s ( ) . pos ;
2021-03-25 20:21:48 +00:00
goto nextfg ;
}
}
}
}
nextfg : ;
2021-03-25 15:45:40 +00:00
}
2021-03-25 20:21:48 +00:00
for ( auto & fp : floorportals )
2021-03-25 15:45:40 +00:00
{
2021-03-25 20:21:48 +00:00
for ( auto sec : fp . sectors )
2021-03-25 15:45:40 +00:00
{
2021-11-05 23:48:28 +00:00
SWSectIterator it ( sec ) ;
while ( auto actor = it . Next ( ) )
2021-03-25 20:21:48 +00:00
{
2021-11-05 23:48:28 +00:00
int tx = actor - > s ( ) . x ;
int ty = actor - > s ( ) . y ;
int tz = actor - > s ( ) . z ;
2021-11-25 18:06:52 +00:00
auto tsect = & sector [ sec ] ;
2021-03-25 15:45:40 +00:00
2021-11-25 18:06:52 +00:00
int match = FindViewSectorInScene ( tsect , VIEW_LEVEL2 ) ;
2021-03-25 20:21:48 +00:00
if ( match ! = - 1 )
{
2021-11-25 18:06:52 +00:00
FindFloorView ( match , & tx , & ty , tz , & tsect ) ;
if ( tsect ! = nullptr & & tsect - > ceilingpicnum = = FAF_MIRROR_PIC )
2021-03-25 20:21:48 +00:00
{
// got something!
2021-11-25 18:06:52 +00:00
fp . othersector = sectnum ( tsect ) ;
2021-03-25 20:21:48 +00:00
fp . offset = { tx , ty , tz } ;
2021-11-05 23:48:28 +00:00
fp . offset - = actor - > s ( ) . pos ;
2021-03-25 20:21:48 +00:00
goto nextcg ;
}
}
}
}
nextcg : ;
}
for ( auto & pt : floorportals )
{
if ( pt . othersector > - 1 )
{
auto findother = [ & ] ( int other ) - > PortalGroup *
{
for ( auto & pt2 : ceilingportals )
{
if ( pt2 . sectors . Find ( other ) ! = pt2 . sectors . Size ( ) ) return & pt2 ;
}
return nullptr ;
} ;
auto pt2 = findother ( pt . othersector ) ;
if ( pt2 )
{
int pnum = portalAdd ( PORTAL_SECTOR_FLOOR , - 1 , pt . offset . x , pt . offset . y , 0 ) ;
allPortals [ pnum ] . targets = pt2 - > sectors ; // do not move! We still need the original.
for ( auto sec : pt . sectors )
{
sector [ sec ] . portalflags = PORTAL_SECTOR_FLOOR ;
sector [ sec ] . portalnum = pnum ;
}
}
}
}
for ( auto & pt : ceilingportals )
{
if ( pt . othersector > - 1 )
{
auto findother = [ & ] ( int other ) - > PortalGroup *
{
for ( auto & pt2 : floorportals )
{
if ( pt2 . sectors . Find ( other ) ! = pt2 . sectors . Size ( ) ) return & pt2 ;
}
return nullptr ;
} ;
2021-03-25 15:45:40 +00:00
2021-03-25 20:21:48 +00:00
auto pt2 = findother ( pt . othersector ) ;
if ( pt2 )
{
2021-05-06 22:23:56 +00:00
int pnum = portalAdd ( PORTAL_SECTOR_CEILING , - 1 , pt . offset . x , pt . offset . y , 0 ) ;
2021-03-25 20:21:48 +00:00
allPortals [ pnum ] . targets = std : : move ( pt2 - > sectors ) ;
for ( auto sec : pt . sectors )
{
sector [ sec ] . portalflags = PORTAL_SECTOR_CEILING ;
sector [ sec ] . portalnum = pnum ;
}
}
2021-03-25 15:45:40 +00:00
}
2015-05-19 21:54:34 +00:00
}
2021-03-28 20:29:13 +00:00
testnewrenderer = t ;
2015-05-19 21:54:34 +00:00
}
2021-03-25 20:21:48 +00:00
2019-10-09 16:09:05 +00:00
END_SW_NS