mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
- made SW's sector portals operational.
Unlike the other games these are so poorly defined that the engine has to rely on the original fudging to pick the proper portal to link to. As a result they are just as limited as they always were. In addition all the portal search code had to be reinstated.
This commit is contained in:
parent
168b0385cf
commit
af54cf3a3c
11 changed files with 426 additions and 350 deletions
|
@ -67,7 +67,7 @@ struct sectortype
|
|||
uint8_t dirty;
|
||||
float ceilingxpan_, ceilingypan_, floorxpan_, floorypan_;
|
||||
uint8_t portalflags;
|
||||
uint8_t portalnum;
|
||||
int8_t portalnum;
|
||||
|
||||
int ceilingxpan() const { return int(ceilingxpan_); }
|
||||
int ceilingypan() const { return int(ceilingypan_); }
|
||||
|
|
|
@ -11,6 +11,7 @@ bool System_WantGuiCapture(); // During playing this tells us whether the game m
|
|||
#include "inputstate.h"
|
||||
|
||||
class FSerializer;
|
||||
struct FRenderViewpoint;
|
||||
|
||||
struct GameStats
|
||||
{
|
||||
|
@ -102,6 +103,7 @@ struct GameInterface
|
|||
virtual int chaseCamY(binangle ang) { return 0; }
|
||||
virtual int chaseCamZ(fixedhoriz horiz) { return 0; }
|
||||
virtual void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) {}
|
||||
virtual int SetupPortal(FRenderViewpoint& vp) { return -1; }
|
||||
|
||||
virtual FString statFPS()
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "hw_drawstructs.h"
|
||||
#include "automap.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "hw_portal.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -136,6 +137,10 @@ bool BunchDrawer::CheckClip(walltype* wal)
|
|||
if (frontsector->ceilingstat & backsector->ceilingstat & CSTAT_SECTOR_SKY) return false;
|
||||
if (frontsector->floorstat & backsector->floorstat & CSTAT_SECTOR_SKY) return false;
|
||||
|
||||
// if we are in a sector portal, no two sided line may clip.
|
||||
// originally this was achieved by temporarily altering the map geometry in the portal sectors.
|
||||
if (portalState.insectorportal) return false;
|
||||
|
||||
float bs_floorheight1;
|
||||
float bs_floorheight2;
|
||||
float bs_ceilingheight1;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "flatvertices.h"
|
||||
#include "hw_clock.h"
|
||||
#include "texturemanager.h"
|
||||
#include "gamestruct.h"
|
||||
|
||||
EXTERN_CVAR(Int, r_mirror_recursions)
|
||||
EXTERN_CVAR(Bool, gl_portals)
|
||||
|
@ -813,12 +814,24 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
auto portal = origin;
|
||||
auto &vp = di->Viewpoint;
|
||||
|
||||
vp.Pos += DVector3(portal->dx / 16., portal->dy / -16., portal->dz / -256.);
|
||||
vp.SectNums = portal->targets.Data();
|
||||
vp.SectCount = portal->targets.Size();
|
||||
if (portal)
|
||||
{
|
||||
vp.Pos += DVector3(portal->dx / 16., portal->dy / -16., portal->dz / -256.);
|
||||
vp.SectNums = portal->targets.Data();
|
||||
vp.SectCount = portal->targets.Size();
|
||||
type = origin->type;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state->renderdepth > 1) return false; // there is no way to make these portals recursive.
|
||||
// Shadow Warrior's portals are too poorly defined so that the static approach won't work.
|
||||
type = gi->SetupPortal(vp);
|
||||
if (type == -1) return false;
|
||||
}
|
||||
state->insectorportal = true;
|
||||
|
||||
// avoid recursions!
|
||||
screen->instack[origin->type == PORTAL_SECTOR_CEILING ? 1 : 0]++;
|
||||
screen->instack[type == PORTAL_SECTOR_CEILING ? 1 : 0]++;
|
||||
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
//SetupCoverage(di);
|
||||
|
@ -830,7 +843,8 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
|
||||
void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
screen->instack[origin->type == PORTAL_SECTOR_CEILING ? 1 : 0]--;
|
||||
screen->instack[type == PORTAL_SECTOR_CEILING ? 1 : 0]--;
|
||||
mState->insectorportal = false;
|
||||
}
|
||||
|
||||
const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
|
||||
|
|
|
@ -182,6 +182,7 @@ struct FPortalSceneState
|
|||
|
||||
int PlaneMirrorMode = 0;
|
||||
bool inskybox = 0;
|
||||
bool insectorportal = false;
|
||||
|
||||
UniqueList<HWSkyInfo> UniqueSkies;
|
||||
UniqueList<HWHorizonInfo> UniqueHorizons;
|
||||
|
@ -350,6 +351,7 @@ public:
|
|||
struct HWSectorStackPortal : public HWScenePortalBase
|
||||
{
|
||||
TArray<sectortype *> sectors;
|
||||
int type = -1;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
|
|
|
@ -81,13 +81,13 @@ void HWWall::SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowr
|
|||
{
|
||||
int ptype;
|
||||
|
||||
if (sector->portalflags == PORTAL_SECTOR_CEILING || sector->portalflags == PORTAL_SECTOR_FLOOR)
|
||||
if ((sector->portalflags == PORTAL_SECTOR_CEILING && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR && plane == plane_floor))
|
||||
{
|
||||
if (screen->instack[1 - plane] || allPortals.Size() == 0) return;
|
||||
portal = &allPortals[sector->portalnum];
|
||||
if (screen->instack[1 - plane] || sector->portalnum >= (int)allPortals.Size()) return;
|
||||
portal = sector->portalnum < 0? nullptr : &allPortals[sector->portalnum];
|
||||
PutPortal(di, PORTALTYPE_SECTORSTACK, plane);
|
||||
}
|
||||
else if (sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT || sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT)
|
||||
else if ((sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT && plane == plane_floor))
|
||||
{
|
||||
ptype = PORTALTYPE_PLANEMIRROR;
|
||||
if (plane == plane_ceiling && (sector->ceilingstat & CSTAT_SECTOR_SLOPE)) return;
|
||||
|
|
|
@ -1,310 +1,7 @@
|
|||
BEGIN_SW_NS
|
||||
|
||||
short GlobStackSect[2];
|
||||
|
||||
void
|
||||
GetUpperLowerSector(short match, int x, int y, short* upper, short* lower)
|
||||
{
|
||||
int i;
|
||||
short sectorlist[16];
|
||||
int sln = 0;
|
||||
int SpriteNum;
|
||||
SPRITEp sp;
|
||||
|
||||
// keep a list of the last stacked sectors the view was in and
|
||||
// check those fisrt
|
||||
sln = 0;
|
||||
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
|
||||
{
|
||||
// will not hurt if GlobStackSect is invalid - inside checks for this
|
||||
if (inside(x, y, GlobStackSect[i]) == 1)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
SectIterator it(GlobStackSect[i]);
|
||||
while ((SpriteNum = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[SpriteNum];
|
||||
|
||||
if (sp->statnum == STAT_FAF &&
|
||||
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
|
||||
&& sp->lotag == match)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
sectorlist[sln] = GlobStackSect[i];
|
||||
sln++;
|
||||
}
|
||||
}
|
||||
|
||||
// didn't find it yet so test ALL sectors
|
||||
if (sln < 2)
|
||||
{
|
||||
sln = 0;
|
||||
for (i = numsectors - 1; i >= 0; i--)
|
||||
{
|
||||
if (inside(x, y, (short)i) == 1)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
SectIterator it(i);
|
||||
while ((SpriteNum = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[SpriteNum];
|
||||
|
||||
if (sp->statnum == STAT_FAF &&
|
||||
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
|
||||
&& sp->lotag == match)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
if (sln < (int)SIZ(GlobStackSect))
|
||||
GlobStackSect[sln] = i;
|
||||
if (sln < (int)SIZ(sectorlist))
|
||||
sectorlist[sln] = i;
|
||||
sln++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// might not find ANYTHING if not tagged right
|
||||
if (sln == 0)
|
||||
{
|
||||
*upper = -1;
|
||||
*lower = -1;
|
||||
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)
|
||||
{
|
||||
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
|
||||
MONO_PRINT(ds);
|
||||
// try again moving the x,y pos around until you only get two sectors
|
||||
GetUpperLowerSector(match, x - 1, y, upper, lower);
|
||||
}
|
||||
|
||||
if (sln == 2)
|
||||
{
|
||||
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
|
||||
{
|
||||
// swap
|
||||
// make sectorlist[0] the LOW sector
|
||||
short hold;
|
||||
|
||||
hold = sectorlist[0];
|
||||
sectorlist[0] = sectorlist[1];
|
||||
sectorlist[1] = hold;
|
||||
}
|
||||
|
||||
*lower = sectorlist[0];
|
||||
*upper = sectorlist[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
int i;
|
||||
SPRITEp sp = NULL;
|
||||
int pix_diff;
|
||||
int newz;
|
||||
|
||||
save.zcount = 0;
|
||||
|
||||
// Search Stat List For closest ceiling view sprite
|
||||
// Get the match, xoff, yoff from this point
|
||||
StatIterator it(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
|
||||
{
|
||||
xoff = *x - sp->x;
|
||||
yoff = *y - sp->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// determine x,y position
|
||||
if (sp->hitag == VIEW_THRU_FLOOR)
|
||||
{
|
||||
short upper, lower;
|
||||
|
||||
*x = sp->x + xoff;
|
||||
*y = sp->y + yoff;
|
||||
|
||||
// get new sector
|
||||
GetUpperLowerSector(match, *x, *y, &upper, &lower);
|
||||
*sectnum = upper;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*sectnum < 0)
|
||||
return false;
|
||||
|
||||
ASSERT(sp);
|
||||
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
|
||||
|
||||
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
|
||||
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// move lower levels ceilings up for the correct view
|
||||
if (sp->hitag == VIEW_LEVEL2)
|
||||
{
|
||||
// save it off
|
||||
save.sectnum[save.zcount] = sp->sectnum;
|
||||
save.zval[save.zcount] = sector[sp->sectnum].floorz;
|
||||
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
|
||||
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
|
||||
|
||||
sector[sp->sectnum].floorz = newz;
|
||||
// don't change FAF_MIRROR_PIC - ConnectArea
|
||||
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
|
||||
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC + 1;
|
||||
sector[sp->sectnum].floorheinum = 0;
|
||||
|
||||
save.zcount++;
|
||||
PRODUCTION_ASSERT(save.zcount < ZMAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
int i;
|
||||
SPRITEp sp = NULL;
|
||||
int newz;
|
||||
int pix_diff;
|
||||
|
||||
save.zcount = 0;
|
||||
|
||||
// Search Stat List For closest ceiling view sprite
|
||||
// Get the match, xoff, yoff from this point
|
||||
StatIterator it(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
|
||||
{
|
||||
xoff = *x - sp->x;
|
||||
yoff = *y - sp->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// determine x,y position
|
||||
if (sp->hitag == VIEW_THRU_CEILING)
|
||||
{
|
||||
short upper, lower;
|
||||
|
||||
*x = sp->x + xoff;
|
||||
*y = sp->y + yoff;
|
||||
|
||||
// get new sector
|
||||
GetUpperLowerSector(match, *x, *y, &upper, &lower);
|
||||
*sectnum = lower;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*sectnum < 0)
|
||||
return false;
|
||||
|
||||
ASSERT(sp);
|
||||
ASSERT(sp->hitag == VIEW_THRU_CEILING);
|
||||
|
||||
// move ceiling multiple of 128 so that the wall tile will line up
|
||||
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
|
||||
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// move upper levels floors down for the correct view
|
||||
if (sp->hitag == VIEW_LEVEL1)
|
||||
{
|
||||
// save it off
|
||||
save.sectnum[save.zcount] = sp->sectnum;
|
||||
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
|
||||
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
|
||||
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
|
||||
|
||||
sector[sp->sectnum].ceilingz = newz;
|
||||
|
||||
// don't change FAF_MIRROR_PIC - ConnectArea
|
||||
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
|
||||
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC + 1;
|
||||
sector[sp->sectnum].ceilingheinum = 0;
|
||||
|
||||
save.zcount++;
|
||||
PRODUCTION_ASSERT(save.zcount < ZMAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
|
||||
bool FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
|
||||
|
||||
|
||||
short
|
||||
|
|
|
@ -1438,6 +1438,26 @@ void UpdateWallPortalState()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The entire setup here is so catastrophically bad that we have to completely rely on the original information.
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (sector[i].ceilingpicnum == FAF_MIRROR_PIC)
|
||||
{
|
||||
sector[i].portalflags = PORTAL_SECTOR_CEILING;
|
||||
sector[i].portalnum = -1;
|
||||
}
|
||||
else if (sector[i].floorpicnum == FAF_MIRROR_PIC)
|
||||
{
|
||||
sector[i].portalflags = PORTAL_SECTOR_FLOOR;
|
||||
sector[i].portalnum = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector[i].portalflags = 0;
|
||||
sector[i].portalnum = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -407,7 +407,6 @@ void InitLevel(MapRecord *maprec)
|
|||
PlaceActorsOnTracks();
|
||||
PostSetupSectorObject();
|
||||
SetupMirrorTiles();
|
||||
SetupSectorPortals();
|
||||
initlava();
|
||||
|
||||
// reset NewGame
|
||||
|
|
|
@ -2135,7 +2135,6 @@ void DrawOverlapRoom(int tx,int ty,int tz,fixed_t tq16ang,fixed_t tq16horiz,shor
|
|||
void SetupMirrorTiles(void); // rooms.c
|
||||
bool FAF_Sector(short sectnum); // rooms.c
|
||||
int GetZadjustment(short sectnum,short hitag); // rooms.c
|
||||
void SetupSectorPortals();
|
||||
|
||||
void InitSetup(void); // setup.c
|
||||
|
||||
|
@ -2256,6 +2255,7 @@ struct GameInterface : ::GameInterface
|
|||
int chaseCamX(binangle ang) { return -ang.bcos(-3); }
|
||||
int chaseCamY(binangle ang) { return -ang.bsin(-3); }
|
||||
int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() >> 8; }
|
||||
int SetupPortal(FRenderViewpoint& vp) override;
|
||||
|
||||
|
||||
GameStats getStats() override;
|
||||
|
|
|
@ -29,6 +29,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|||
#include "names2.h"
|
||||
#include "panel.h"
|
||||
#include "misc.h"
|
||||
#include "hw_drawinfo.h"
|
||||
|
||||
BEGIN_SW_NS
|
||||
|
||||
|
@ -678,50 +679,386 @@ SetupMirrorTiles(void)
|
|||
}
|
||||
}
|
||||
|
||||
short GlobStackSect[2];
|
||||
|
||||
void SetupSectorPortals()
|
||||
void
|
||||
GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
|
||||
{
|
||||
TArray<int> foundf, foundc;
|
||||
// Search Stat List For closest ceiling view sprite
|
||||
// Get the match, xoff, yoff from this point
|
||||
StatIterator it(STAT_FAF);
|
||||
int i;
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
short sectorlist[16];
|
||||
int sln = 0;
|
||||
int SpriteNum;
|
||||
SPRITEp sp;
|
||||
|
||||
// keep a list of the last stacked sectors the view was in and
|
||||
// check those fisrt
|
||||
sln = 0;
|
||||
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
|
||||
{
|
||||
auto sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == VIEW_THRU_CEILING) foundc.Push(i);
|
||||
if (sp->hitag == VIEW_THRU_FLOOR) foundf.Push(i);
|
||||
}
|
||||
|
||||
portalClear();
|
||||
while (foundf.Size())
|
||||
{
|
||||
auto spf = &sprite[foundf[0]];
|
||||
auto cindex = foundc.FindEx([=](int i) { return spf->lotag == sprite[i].lotag; });
|
||||
if (cindex != foundc.Size())
|
||||
// will not hurt if GlobStackSect is invalid - inside checks for this
|
||||
if (inside(x, y, GlobStackSect[i]) == 1)
|
||||
{
|
||||
auto spc = &sprite[foundf[cindex]];
|
||||
sector[spf->sectnum].portalflags = PORTAL_SECTOR_FLOOR;
|
||||
sector[spf->sectnum].portalnum = portalAdd(PORTAL_SECTOR_FLOOR, spc->sectnum, spc->x - spf->x, spc->y - spf->y, 0);
|
||||
bool found = false;
|
||||
|
||||
sector[spc->sectnum].portalflags = PORTAL_SECTOR_CEILING;
|
||||
sector[spc->sectnum].portalnum = portalAdd(PORTAL_SECTOR_CEILING, spf->sectnum, spf->x - spc->x, spf->y - spc->y, 0);
|
||||
SectIterator it(GlobStackSect[i]);
|
||||
while ((SpriteNum = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[SpriteNum];
|
||||
|
||||
//Printf("Portal with tag %d\n", sprite[foundf[0]].lotag);
|
||||
foundf.Delete(0);
|
||||
foundc.Delete(cindex);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Printf("Floor portal %d without partner\n", sprite[foundf[0]].lotag);
|
||||
foundf.Delete(0);
|
||||
if (sp->statnum == STAT_FAF &&
|
||||
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
|
||||
&& sp->lotag == match)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
sectorlist[sln] = GlobStackSect[i];
|
||||
sln++;
|
||||
}
|
||||
}
|
||||
for (auto c : foundc)
|
||||
|
||||
// didn't find it yet so test ALL sectors
|
||||
if (sln < 2)
|
||||
{
|
||||
//Printf("Ceiling portal %d without partner\n", sprite[c].lotag);
|
||||
sln = 0;
|
||||
for (i = numsectors - 1; i >= 0; i--)
|
||||
{
|
||||
if (inside(x, y, (short) i) == 1)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
SectIterator it(i);
|
||||
while ((SpriteNum = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[SpriteNum];
|
||||
|
||||
if (sp->statnum == STAT_FAF &&
|
||||
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
|
||||
&& sp->lotag == match)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
if (sln < (int)SIZ(GlobStackSect))
|
||||
GlobStackSect[sln] = i;
|
||||
if (sln < (int)SIZ(sectorlist))
|
||||
sectorlist[sln] = i;
|
||||
sln++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// might not find ANYTHING if not tagged right
|
||||
if (sln == 0)
|
||||
{
|
||||
*upper = -1;
|
||||
*lower = -1;
|
||||
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)
|
||||
{
|
||||
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
|
||||
MONO_PRINT(ds);
|
||||
// try again moving the x,y pos around until you only get two sectors
|
||||
GetUpperLowerSector(match, x - 1, y, upper, lower);
|
||||
}
|
||||
|
||||
if (sln == 2)
|
||||
{
|
||||
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
|
||||
{
|
||||
// swap
|
||||
// make sectorlist[0] the LOW sector
|
||||
short hold;
|
||||
|
||||
hold = sectorlist[0];
|
||||
sectorlist[0] = sectorlist[1];
|
||||
sectorlist[1] = hold;
|
||||
}
|
||||
|
||||
*lower = sectorlist[0];
|
||||
*upper = sectorlist[1];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
int i;
|
||||
SPRITEp sp = NULL;
|
||||
int pix_diff;
|
||||
int newz;
|
||||
|
||||
save.zcount = 0;
|
||||
|
||||
// Search Stat List For closest ceiling view sprite
|
||||
// Get the match, xoff, yoff from this point
|
||||
StatIterator it(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
|
||||
{
|
||||
xoff = *x - sp->x;
|
||||
yoff = *y - sp->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// determine x,y position
|
||||
if (sp->hitag == VIEW_THRU_FLOOR)
|
||||
{
|
||||
short upper, lower;
|
||||
|
||||
*x = sp->x + xoff;
|
||||
*y = sp->y + yoff;
|
||||
|
||||
// get new sector
|
||||
GetUpperLowerSector(match, *x, *y, &upper, &lower);
|
||||
*sectnum = upper;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*sectnum < 0)
|
||||
return false;
|
||||
|
||||
ASSERT(sp);
|
||||
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
|
||||
|
||||
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
|
||||
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
|
||||
|
||||
if (!testnewrenderer)
|
||||
{
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// move lower levels ceilings up for the correct view
|
||||
if (sp->hitag == VIEW_LEVEL2)
|
||||
{
|
||||
// save it off
|
||||
save.sectnum[save.zcount] = sp->sectnum;
|
||||
save.zval[save.zcount] = sector[sp->sectnum].floorz;
|
||||
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
|
||||
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
|
||||
|
||||
sector[sp->sectnum].floorz = newz;
|
||||
// don't change FAF_MIRROR_PIC - ConnectArea
|
||||
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
|
||||
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC + 1;
|
||||
sector[sp->sectnum].floorheinum = 0;
|
||||
|
||||
save.zcount++;
|
||||
PRODUCTION_ASSERT(save.zcount < ZMAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
int i;
|
||||
SPRITEp sp = NULL;
|
||||
int newz;
|
||||
int pix_diff;
|
||||
|
||||
save.zcount = 0;
|
||||
|
||||
// Search Stat List For closest ceiling view sprite
|
||||
// Get the match, xoff, yoff from this point
|
||||
StatIterator it(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
|
||||
{
|
||||
xoff = *x - sp->x;
|
||||
yoff = *y - sp->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// determine x,y position
|
||||
if (sp->hitag == VIEW_THRU_CEILING)
|
||||
{
|
||||
short upper, lower;
|
||||
|
||||
*x = sp->x + xoff;
|
||||
*y = sp->y + yoff;
|
||||
|
||||
// get new sector
|
||||
GetUpperLowerSector(match, *x, *y, &upper, &lower);
|
||||
*sectnum = lower;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*sectnum < 0)
|
||||
return false;
|
||||
|
||||
ASSERT(sp);
|
||||
ASSERT(sp->hitag == VIEW_THRU_CEILING);
|
||||
|
||||
// move ceiling multiple of 128 so that the wall tile will line up
|
||||
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
|
||||
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
|
||||
|
||||
if (!testnewrenderer)
|
||||
{
|
||||
it.Reset(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->lotag == match)
|
||||
{
|
||||
// move upper levels floors down for the correct view
|
||||
if (sp->hitag == VIEW_LEVEL1)
|
||||
{
|
||||
// save it off
|
||||
save.sectnum[save.zcount] = sp->sectnum;
|
||||
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
|
||||
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
|
||||
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
|
||||
|
||||
sector[sp->sectnum].ceilingz = newz;
|
||||
|
||||
// don't change FAF_MIRROR_PIC - ConnectArea
|
||||
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
|
||||
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC + 1;
|
||||
sector[sp->sectnum].ceilingheinum = 0;
|
||||
|
||||
save.zcount++;
|
||||
PRODUCTION_ASSERT(save.zcount < ZMAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
short
|
||||
FindViewSectorInScene(short cursectnum, short level)
|
||||
{
|
||||
int i;
|
||||
SPRITEp sp;
|
||||
short match;
|
||||
|
||||
StatIterator it(STAT_FAF);
|
||||
while ((i = it.NextIndex()) >= 0)
|
||||
{
|
||||
sp = &sprite[i];
|
||||
|
||||
if (sp->hitag == level)
|
||||
{
|
||||
if (cursectnum == sp->sectnum)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
int GameInterface::SetupPortal(FRenderViewpoint &vp)
|
||||
{
|
||||
short i;
|
||||
short match;
|
||||
|
||||
save.zcount = 0;
|
||||
int16_t tsectnum = int16_t(vp.SectNums == nullptr ? vp.SectCount : vp.SectNums[0]);
|
||||
int tx = vp.Pos.X * 16;
|
||||
int ty = vp.Pos.Y * -16;
|
||||
int tz = vp.Pos.Z * -128;
|
||||
int type = -1;
|
||||
int looktype = -1;
|
||||
|
||||
match = FindViewSectorInScene(tsectnum, VIEW_LEVEL1);
|
||||
if (match != -1)
|
||||
{
|
||||
FindCeilingView(match, &tx, &ty, tz, &tsectnum);
|
||||
type = PORTAL_SECTOR_CEILING;
|
||||
|
||||
if (tsectnum < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
match = FindViewSectorInScene(tsectnum, VIEW_LEVEL2);
|
||||
if (match != -1)
|
||||
{
|
||||
FindFloorView(match, &tx, &ty, tz, &tsectnum);
|
||||
type = PORTAL_SECTOR_FLOOR;
|
||||
|
||||
if (tsectnum < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
vp.Pos = { tx / 16.f, ty / -16.f, tz / -128.f };
|
||||
vp.SectNums = nullptr;
|
||||
vp.SectCount = tsectnum;
|
||||
return type;
|
||||
}
|
||||
|
||||
END_SW_NS
|
||||
|
|
Loading…
Reference in a new issue