Merge branch 'sector-portals' into 'next'

Sector portals

See merge request STJr/SRB2!2139
This commit is contained in:
Logan Aerl Arias 2024-01-08 03:28:43 +00:00
commit 845df8f1df
18 changed files with 1078 additions and 278 deletions

View file

@ -10,6 +10,45 @@ udmf
prefix = "(0)";
}
6
{
title = "Sector Set Portal";
prefix = "(6)";
arg0
{
title = "Target sector tag";
type = 13;
}
arg1
{
title = "Portal type";
type = 11;
enum
{
0 = "Link to portal with same tag";
1 = "Copy portal from second tag";
2 = "Skybox portal";
3 = "Plane portal";
4 = "Horizon portal";
5 = "Copy portal to line";
6 = "Interactive portal (unimplemented)";
7 = "Link to sector with second tag";
8 = "Link to object with second tag";
}
}
arg2
{
title = "Affected planes";
type = 11;
enum = "floorceiling";
}
arg3
{
title = "Misc";
tooltip = "For type 0 portal: specifies whether the line belongs to the sector viewed\nthrough the portal (1) or the sector in which the portal is seen (0).\nFor type 1 portal: specifies the sector tag of the portal to copy.\nFor type 7 portal: specifies the sector tag to make a portal to.\nFor type 8 portal: specifies the object tag to make a portal to.";
}
}
7
{
title = "Sector Flat Alignment";

View file

@ -4291,7 +4291,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_POLYANCHOR",
"MT_POLYSPAWN",
// Skybox objects
// Portal objects
"MT_SKYBOX",
// Debris

View file

@ -566,7 +566,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
for (i = 0; i < subsector->numlines; i++, line++)
{
if (!line->glseg && line->linedef->special == HORIZONSPECIAL && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0)
if (!line->glseg && line->linedef->special == SPECIAL_HORIZON_LINE && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0)
{
P_ClosestPointOnLine(viewx, viewy, line->linedef, &v);
dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y));
@ -1139,9 +1139,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
INT32 gl_toptexture = 0, gl_bottomtexture = 0;
fixed_t texturevpeg;
boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
boolean bothfloorssky = false; // likewise, but for floors
SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight)
SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight)
@ -1506,7 +1503,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
else
{
// Single sided line... Deal only with the middletexture (if one exists)
if (gl_midtexture && gl_linedef->special != HORIZONSPECIAL) // (Ignore horizon line for OGL)
if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL)
{
grTex = HWR_GetTexture(gl_midtexture);
xscale = FixedToFloat(gl_sidedef->scalex_mid);
@ -1885,12 +1882,6 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
{
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
boolean bothceilingssky = false, bothfloorssky = false;
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
bothceilingssky = true;
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
bothfloorssky = true;
// GZDoom method of sloped line clipping
@ -2409,6 +2400,7 @@ static void HWR_AddLine(seg_t * line)
#endif
gl_backsector = line->backsector;
bothceilingssky = bothfloorssky = false;
#ifdef NEWCLIP
if (!line->backsector)
@ -2417,13 +2409,14 @@ static void HWR_AddLine(seg_t * line)
}
else
{
boolean bothceilingssky = false, bothfloorssky = false;
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum)
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum
&& !(P_SectorHasCeilingPortal(gl_backsector) || P_SectorHasCeilingPortal(gl_frontsector)))
bothceilingssky = true;
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum)
if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum
&& !(P_SectorHasFloorPortal(gl_backsector) || P_SectorHasFloorPortal(gl_frontsector)))
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
@ -3020,64 +3013,16 @@ static void HWR_Subsector(size_t num)
}
//SoM: 4/7/2000: Test to make Boom water work in Hardware mode.
gl_frontsector = R_FakeFlat(gl_frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false);
//FIXME: Use floorlightlevel and ceilinglightlevel insted of lightlevel.
gl_frontsector = R_FakeFlat(gl_frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false);
floorcolormap = ceilingcolormap = gl_frontsector->extra_colormap;
// ------------------------------------------------------------------------
// sector lighting, DISABLED because it's done in HWR_StoreWallRange
// ------------------------------------------------------------------------
/// \todo store a RGBA instead of just intensity, allow coloured sector lighting
//light = (FUBYTE)(sub->sector->lightlevel & 0xFF) / 255.0f;
//gl_cursectorlight.red = light;
//gl_cursectorlight.green = light;
//gl_cursectorlight.blue = light;
//gl_cursectorlight.alpha = light;
// ----- end special tricks -----
cullFloorHeight = P_GetSectorFloorZAt (gl_frontsector, viewx, viewy);
cullCeilingHeight = P_GetSectorCeilingZAt(gl_frontsector, viewx, viewy);
locFloorHeight = P_GetSectorFloorZAt (gl_frontsector, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y);
locCeilingHeight = P_GetSectorCeilingZAt(gl_frontsector, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y);
if (gl_frontsector->ffloors)
{
boolean anyMoved = gl_frontsector->moved;
if (anyMoved == false)
{
for (rover = gl_frontsector->ffloors; rover; rover = rover->next)
{
sector_t *controlSec = &sectors[rover->secnum];
if (controlSec->moved == true)
{
anyMoved = true;
break;
}
}
}
if (anyMoved == true)
{
gl_frontsector->numlights = sub->sector->numlights = 0;
R_Prep3DFloors(gl_frontsector);
sub->sector->lightlist = gl_frontsector->lightlist;
sub->sector->numlights = gl_frontsector->numlights;
sub->sector->moved = gl_frontsector->moved = false;
}
light = R_GetPlaneLight(gl_frontsector, locFloorHeight, false);
if (gl_frontsector->floorlightsec == -1 && !gl_frontsector->floorlightabsolute)
floorlightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->floorlightlevel));
floorcolormap = *gl_frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(gl_frontsector, locCeilingHeight, false);
if (gl_frontsector->ceilinglightsec == -1 && !gl_frontsector->ceilinglightabsolute)
ceilinglightlevel = max(0, min(255, *gl_frontsector->lightlist[light].lightlevel + gl_frontsector->ceilinglightlevel));
ceilingcolormap = *gl_frontsector->lightlist[light].extra_colormap;
}
R_CheckSectorLightLists(sub->sector, gl_frontsector, &floorlightlevel, &ceilinglightlevel, &floorcolormap, &ceilingcolormap);
sub->sector->extra_colormap = gl_frontsector->extra_colormap;

View file

@ -5123,7 +5123,7 @@ typedef enum mobj_type
MT_POLYANCHOR,
MT_POLYSPAWN,
// Skybox objects
// Portal objects
MT_SKYBOX,
// Debris

View file

@ -3477,7 +3477,7 @@ static void PTR_GlideClimbTraverse(line_t *li)
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL)
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != SPECIAL_HORIZON_LINE)
{
boolean canclimb;
angle_t climbangle, climbline;

View file

@ -41,20 +41,19 @@ UINT8 *save_p;
// Block UINT32s to attempt to ensure that the correct data is
// being sent and received
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
#define ARCHIVEBLOCK_POBJS 0x7F928546
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
#define ARCHIVEBLOCK_SPECIALS 0x7F228378
#define ARCHIVEBLOCK_EMBLEMS 0x7F4A5445
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
#define ARCHIVEBLOCK_POBJS 0x7F928546
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
#define ARCHIVEBLOCK_SPECIALS 0x7F228378
#define ARCHIVEBLOCK_EMBLEMS 0x7F4A5445
#define ARCHIVEBLOCK_SECPORTALS 0x7FBE34C9
// Note: This cannot be bigger
// than an UINT16
typedef enum
{
// RFLAGPOINT = 0x01,
// BFLAGPOINT = 0x02,
CAPSULE = 0x04,
AWAYVIEW = 0x08,
FIRSTAXIS = 0x10,
@ -853,33 +852,43 @@ static void P_NetUnArchiveWaypoints(void)
#define SD_DIFF3 0x80
// diff3 flags
#define SD_TAGLIST 0x01
#define SD_COLORMAP 0x02
#define SD_TAGLIST 0x01
#define SD_COLORMAP 0x02
#define SD_CRUMBLESTATE 0x04
#define SD_FLOORLIGHT 0x08
#define SD_CEILLIGHT 0x10
#define SD_FLAG 0x20
#define SD_SPECIALFLAG 0x40
#define SD_DIFF4 0x80
#define SD_FLOORLIGHT 0x08
#define SD_CEILLIGHT 0x10
#define SD_FLAG 0x20
#define SD_SPECIALFLAG 0x40
#define SD_DIFF4 0x80
//diff4 flags
// diff4 flags
#define SD_DAMAGETYPE 0x01
#define SD_TRIGGERTAG 0x02
#define SD_TRIGGERER 0x04
#define SD_GRAVITY 0x08
#define SD_FXSCALE 0x10
#define SD_FYSCALE 0x20
#define SD_CXSCALE 0x40
#define SD_CYSCALE 0x80
#define SD_FXSCALE 0x08
#define SD_FYSCALE 0x10
#define SD_CXSCALE 0x20
#define SD_CYSCALE 0x40
#define SD_DIFF5 0x80
// diff5 flags
#define SD_GRAVITY 0x01
#define SD_FLOORPORTAL 0x02
#define SD_CEILPORTAL 0x04
// diff1 flags
#define LD_FLAG 0x01
#define LD_SPECIAL 0x02
#define LD_CLLCOUNT 0x04
#define LD_ARGS 0x08
#define LD_STRINGARGS 0x10
#define LD_EXECUTORDELAY 0x20
#define LD_SIDE1 0x40
#define LD_SIDE2 0x80
#define LD_SIDE1 0x20
#define LD_SIDE2 0x40
#define LD_DIFF2 0x80
// diff2 flags
#define LD_EXECUTORDELAY 0x01
#define LD_TRANSFPORTAL 0x02
// sidedef flags
enum
@ -1028,11 +1037,11 @@ static void ArchiveSectors(void)
size_t i, j;
const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3, diff4;
UINT8 diff, diff2, diff3, diff4, diff5;
for (i = 0; i < numsectors; i++, ss++, spawnss++)
{
diff = diff2 = diff3 = diff4 = 0;
diff = diff2 = diff3 = diff4 = diff5 = 0;
if (ss->floorheight != spawnss->floorheight)
diff |= SD_FLOORHT;
if (ss->ceilingheight != spawnss->ceilingheight)
@ -1094,11 +1103,18 @@ static void ArchiveSectors(void)
if (ss->triggerer != spawnss->triggerer)
diff4 |= SD_TRIGGERER;
if (ss->gravity != spawnss->gravity)
diff4 |= SD_GRAVITY;
diff5 |= SD_GRAVITY;
if (ss->portal_floor != spawnss->portal_floor)
diff5 |= SD_FLOORPORTAL;
if (ss->portal_ceiling != spawnss->portal_ceiling)
diff5 |= SD_CEILPORTAL;
if (ss->ffloors && CheckFFloorDiff(ss))
diff |= SD_FFLOORS;
if (diff5)
diff4 |= SD_DIFF5;
if (diff4)
diff3 |= SD_DIFF4;
@ -1118,6 +1134,8 @@ static void ArchiveSectors(void)
WRITEUINT8(save_p, diff3);
if (diff3 & SD_DIFF4)
WRITEUINT8(save_p, diff4);
if (diff4 & SD_DIFF5)
WRITEUINT8(save_p, diff5);
if (diff & SD_FLOORHT)
WRITEFIXED(save_p, ss->floorheight);
if (diff & SD_CEILHT)
@ -1174,8 +1192,6 @@ static void ArchiveSectors(void)
WRITEINT16(save_p, ss->triggertag);
if (diff4 & SD_TRIGGERER)
WRITEUINT8(save_p, ss->triggerer);
if (diff4 & SD_GRAVITY)
WRITEFIXED(save_p, ss->gravity);
if (diff4 & SD_FXSCALE)
WRITEFIXED(save_p, ss->floorxscale);
if (diff4 & SD_FYSCALE)
@ -1184,6 +1200,12 @@ static void ArchiveSectors(void)
WRITEFIXED(save_p, ss->ceilingxscale);
if (diff4 & SD_CYSCALE)
WRITEFIXED(save_p, ss->ceilingyscale);
if (diff5 & SD_GRAVITY)
WRITEFIXED(save_p, ss->gravity);
if (diff5 & SD_FLOORPORTAL)
WRITEUINT32(save_p, ss->portal_floor);
if (diff5 & SD_CEILPORTAL)
WRITEUINT32(save_p, ss->portal_ceiling);
if (diff & SD_FFLOORS)
ArchiveFFloors(ss);
}
@ -1196,7 +1218,7 @@ static void UnArchiveSectors(void)
{
UINT32 i;
UINT16 j;
UINT8 diff, diff2, diff3, diff4;
UINT8 diff, diff2, diff3, diff4, diff5;
for (;;)
{
i = READUINT32(save_p);
@ -1220,6 +1242,10 @@ static void UnArchiveSectors(void)
diff4 = READUINT8(save_p);
else
diff4 = 0;
if (diff4 & SD_DIFF5)
diff5 = READUINT8(save_p);
else
diff5 = 0;
if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(save_p);
@ -1303,8 +1329,6 @@ static void UnArchiveSectors(void)
sectors[i].triggertag = READINT16(save_p);
if (diff4 & SD_TRIGGERER)
sectors[i].triggerer = READUINT8(save_p);
if (diff4 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save_p);
if (diff4 & SD_FXSCALE)
sectors[i].floorxscale = READFIXED(save_p);
if (diff4 & SD_FYSCALE)
@ -1313,6 +1337,12 @@ static void UnArchiveSectors(void)
sectors[i].ceilingxscale = READFIXED(save_p);
if (diff4 & SD_CYSCALE)
sectors[i].ceilingyscale = READFIXED(save_p);
if (diff5 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save_p);
if (diff5 & SD_FLOORPORTAL)
sectors[i].portal_floor = READUINT32(save_p);
if (diff5 & SD_CEILPORTAL)
sectors[i].portal_ceiling = READUINT32(save_p);
if (diff & SD_FFLOORS)
UnArchiveFFloors(&sectors[i]);
@ -1409,13 +1439,14 @@ static void ArchiveLines(void)
size_t i;
const line_t *li = lines;
const line_t *spawnli = spawnlines;
UINT8 diff;
UINT32 diff2;
UINT32 diff3;
UINT8 diff, diff2;
UINT32 side1diff;
UINT32 side2diff;
for (i = 0; i < numlines; i++, spawnli++, li++)
{
diff = diff2 = diff3 = 0;
diff = diff2 = 0;
side1diff = side2diff = 0;
if (li->special != spawnli->special)
diff |= LD_SPECIAL;
@ -1430,25 +1461,33 @@ static void ArchiveLines(void)
diff |= LD_STRINGARGS;
if (li->executordelay != spawnli->executordelay)
diff |= LD_EXECUTORDELAY;
diff2 |= LD_EXECUTORDELAY;
if (li->secportal != spawnli->secportal)
diff2 |= LD_TRANSFPORTAL;
if (li->sidenum[0] != NO_SIDEDEF)
{
diff2 = GetSideDiff(&sides[li->sidenum[0]], &spawnsides[li->sidenum[0]]);
if (diff2)
side1diff = GetSideDiff(&sides[li->sidenum[0]], &spawnsides[li->sidenum[0]]);
if (side1diff)
diff |= LD_SIDE1;
}
if (li->sidenum[1] != NO_SIDEDEF)
{
diff3 = GetSideDiff(&sides[li->sidenum[1]], &spawnsides[li->sidenum[1]]);
if (diff3)
side2diff = GetSideDiff(&sides[li->sidenum[1]], &spawnsides[li->sidenum[1]]);
if (side2diff)
diff |= LD_SIDE2;
}
if (diff2)
diff |= LD_DIFF2;
if (diff)
{
WRITEUINT32(save_p, i);
WRITEUINT8(save_p, diff);
if (diff & LD_DIFF2)
WRITEUINT8(save_p, diff2);
if (diff & LD_FLAG)
WRITEINT16(save_p, li->flags);
if (diff & LD_SPECIAL)
@ -1480,12 +1519,14 @@ static void ArchiveLines(void)
WRITECHAR(save_p, li->stringargs[j][k]);
}
}
if (diff & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
if (diff & LD_SIDE1)
ArchiveSide(&sides[li->sidenum[0]], diff2);
ArchiveSide(&sides[li->sidenum[0]], side1diff);
if (diff & LD_SIDE2)
ArchiveSide(&sides[li->sidenum[1]], diff3);
ArchiveSide(&sides[li->sidenum[1]], side2diff);
if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
if (diff2 & LD_TRANSFPORTAL)
WRITEUINT32(save_p, li->secportal);
}
}
WRITEUINT32(save_p, 0xffffffff);
@ -1537,7 +1578,7 @@ static void UnArchiveLines(void)
{
UINT32 i;
line_t *li;
UINT8 diff;
UINT8 diff, diff2;
for (;;)
{
@ -1549,6 +1590,10 @@ static void UnArchiveLines(void)
I_Error("Invalid line number %u from server", i);
diff = READUINT8(save_p);
if (diff & LD_DIFF2)
diff2 = READUINT8(save_p);
else
diff2 = 0;
li = &lines[i];
if (diff & LD_FLAG)
@ -1584,12 +1629,14 @@ static void UnArchiveLines(void)
li->stringargs[j][len] = '\0';
}
}
if (diff & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
if (diff & LD_SIDE1)
UnArchiveSide(&sides[li->sidenum[0]]);
if (diff & LD_SIDE2)
UnArchiveSide(&sides[li->sidenum[1]]);
if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
if (diff2 & LD_TRANSFPORTAL)
li->secportal = READUINT32(save_p);
}
}
@ -4851,6 +4898,86 @@ static inline void P_NetUnArchiveEmblems(void)
}
}
static void P_NetArchiveSectorPortals(void)
{
WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS);
WRITEUINT32(save_p, secportalcount);
for (size_t i = 0; i < secportalcount; i++)
{
UINT8 type = secportals[i].type;
WRITEUINT8(save_p, type);
WRITEFIXED(save_p, secportals[i].origin.x);
WRITEFIXED(save_p, secportals[i].origin.y);
switch (type)
{
case SECPORTAL_LINE:
WRITEUINT32(save_p, SaveLine(secportals[i].line.start));
WRITEUINT32(save_p, SaveLine(secportals[i].line.dest));
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
WRITEUINT32(save_p, SaveSector(secportals[i].sector));
break;
case SECPORTAL_OBJECT:
if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj))
SaveMobjnum(secportals[i].mobj);
else
WRITEUINT32(save_p, 0);
break;
default:
break;
}
}
}
static void P_NetUnArchiveSectorPortals(void)
{
if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS)
I_Error("Bad $$$.sav at archive block Secportals");
Z_Free(secportals);
P_InitSectorPortals();
UINT32 count = READUINT32(save_p);
for (UINT32 i = 0; i < count; i++)
{
UINT32 id = P_NewSectorPortal();
sectorportal_t *secportal = &secportals[id];
secportal->type = READUINT8(save_p);
secportal->origin.x = READFIXED(save_p);
secportal->origin.y = READFIXED(save_p);
switch (secportal->type)
{
case SECPORTAL_LINE:
secportal->line.start = LoadLine(READUINT32(save_p));
secportal->line.dest = LoadLine(READUINT32(save_p));
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
secportal->sector = LoadSector(READUINT32(save_p));
break;
case SECPORTAL_OBJECT:
id = READUINT32(save_p);
secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id);
break;
default:
break;
}
}
}
static inline void P_ArchiveLuabanksAndConsistency(void)
{
UINT8 i, banksinuse = NUM_LUABANKS;
@ -4937,6 +5064,7 @@ void P_SaveNetGame(boolean resending)
P_NetArchiveSpecials();
P_NetArchiveColormaps();
P_NetArchiveWaypoints();
P_NetArchiveSectorPortals();
}
LUA_Archive();
@ -4977,6 +5105,7 @@ boolean P_LoadNetGame(boolean reloading)
P_NetUnArchiveSpecials();
P_NetUnArchiveColormaps();
P_NetUnArchiveWaypoints();
P_NetUnArchiveSectorPortals();
P_RelinkPointers();
P_FinishMobjs();
}

View file

@ -993,6 +993,9 @@ static void P_InitializeSector(sector_t *ss)
ss->lightingdata = NULL;
ss->fadecolormapdata = NULL;
ss->portal_floor = UINT32_MAX;
ss->portal_ceiling = UINT32_MAX;
ss->heightsec = -1;
ss->camsec = -1;
@ -1110,6 +1113,7 @@ static void P_InitializeLinedef(line_t *ld)
ld->polyobj = NULL;
ld->callcount = 0;
ld->secportal = UINT32_MAX;
// cph 2006/09/30 - fix sidedef errors right away.
// cph 2002/07/20 - these errors are fatal if not fixed, so apply them
@ -7883,6 +7887,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_InitThinkers();
R_InitMobjInterpolators();
P_InitCachedActions();
P_InitSectorPortals();
// internal game map
maplumpname = G_BuildMapName(gamemap);

View file

@ -52,6 +52,10 @@ mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint
mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
size_t secportalcount;
size_t secportalcapacity;
sectorportal_t *secportals;
/** Animated texture descriptor
* This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
@ -6199,6 +6203,196 @@ fixed_t P_GetSectorGravityFactor(sector_t *sec)
return sec->gravity;
}
void P_InitSectorPortals(void)
{
secportalcount = 0;
secportalcapacity = 0;
secportals = NULL;
}
UINT32 P_NewSectorPortal(void)
{
size_t i = secportalcount++;
if (i == UINT32_MAX)
I_Error("Too many sector portals");
if (secportalcapacity == 0 || secportalcount == secportalcapacity)
{
secportalcapacity = secportalcapacity ? (secportalcapacity * 2) : 16;
secportals = Z_Realloc(secportals, secportalcapacity * sizeof(sectorportal_t), PU_LEVEL, NULL);
}
secportals[i].type = SECPORTAL_NONE;
return (UINT32)i;
}
boolean P_IsSectorPortalValid(sectorportal_t *secportal)
{
if (secportal == NULL)
return false;
switch (secportal->type)
{
case SECPORTAL_LINE:
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
return true;
case SECPORTAL_OBJECT:
return secportal->mobj && !P_MobjWasRemoved(secportal->mobj);
case SECPORTAL_SKYBOX:
return skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]);
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
return true;
default:
return false;
}
}
boolean P_SectorHasPortal(sector_t *sector)
{
return P_SectorHasFloorPortal(sector) || P_SectorHasCeilingPortal(sector);
}
sectorportal_t *P_SectorGetFloorPortal(sector_t *sector)
{
UINT32 num = sector->portal_floor;
if (num >= secportalcount)
return NULL;
return &secportals[num];
}
sectorportal_t *P_SectorGetCeilingPortal(sector_t *sector)
{
UINT32 num = sector->portal_ceiling;
if (num >= secportalcount)
return NULL;
return &secportals[num];
}
boolean P_SectorHasFloorPortal(sector_t *sector)
{
return P_IsSectorPortalValid(P_SectorGetFloorPortal(sector));
}
boolean P_SectorHasCeilingPortal(sector_t *sector)
{
return P_IsSectorPortalValid(P_SectorGetCeilingPortal(sector));
}
boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b)
{
if (a == NULL && b == NULL)
return true;
else if (!a || !b)
return false;
else if (a->type != b->type)
return false;
switch (a->type)
{
case SECPORTAL_LINE:
return a->line.start == b->line.start && a->line.dest == b->line.dest;
case SECPORTAL_FLOOR:
case SECPORTAL_CEILING:
return a->sector == b->sector;
case SECPORTAL_OBJECT:
return a->mobj == b->mobj;
default:
return true;
}
}
static mobj_t *P_GetMobjByTag(INT32 tag)
{
INT32 mtnum = -1;
TAG_ITER_THINGS(tag, mtnum)
{
mobj_t *mo = mapthings[mtnum].mobj;
if (mo)
return mo;
}
return NULL;
}
static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int tag)
{
INT32 secnum = -1;
TAG_ITER_SECTORS(tag, secnum)
{
sector_t *src_sector = &sectors[secnum];
if (plane_type == TMP_FLOOR || plane_type == TMP_BOTH)
dest_sector->portal_floor = src_sector->portal_floor;
if (plane_type == TMP_CEILING || plane_type == TMP_BOTH)
dest_sector->portal_ceiling = src_sector->portal_ceiling;
}
}
static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result)
{
sectorportal_t *secportal = NULL;
if (*num >= secportalcount)
{
*num = P_NewSectorPortal();
secportal = &secportals[*num];
secportal->origin.x = sector->soundorg.x;
secportal->origin.y = sector->soundorg.y;
*result = *num;
}
else
{
*result = *num;
secportal = &secportals[*num];
}
return secportal;
}
static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result)
{
return P_SectorGetPortalOrCreate(sector, &sector->portal_floor, result);
}
static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result)
{
return P_SectorGetPortalOrCreate(sector, &sector->portal_ceiling, result);
}
static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag)
{
for (size_t i = 0; i < numlines; i++)
{
if (lines[i].special != SPECIAL_SECTOR_SETPORTAL)
continue;
if (lines[i].args[1] != TMSECPORTAL_COPY_PORTAL_TO_LINE)
continue;
if (lines[i].args[3] != sector_tag)
continue;
if (lines[i].args[0] != 0)
{
INT32 linenum = -1;
TAG_ITER_LINES(lines[i].args[0], linenum)
{
lines[linenum].secportal = portal_num;
}
}
else
{
// Just transfer it to this line
lines[i].secportal = portal_num;
}
}
}
/** After the map has loaded, scans for specials that spawn 3Dfloors and
* thinkers.
*
@ -6365,6 +6559,146 @@ void P_SpawnSpecials(boolean fromnetsave)
P_AddCameraScanner(&sectors[sec], &sectors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y));
break;
case SPECIAL_SECTOR_SETPORTAL: // Sector portal
{
int target_sector_tag = lines[i].args[0];
int portal_type = lines[i].args[1];
int plane_type = lines[i].args[2];
int misc = lines[i].args[3];
boolean floor, ceiling;
if (plane_type == TMP_BOTH)
floor = ceiling = true;
else
{
floor = plane_type == TMP_FLOOR;
ceiling = plane_type == TMP_CEILING;
}
UINT32 portal_num = UINT32_MAX;
// Eternity's floor and horizon portal types
if (portal_type == TMSECPORTAL_PLANE || portal_type == TMSECPORTAL_HORIZON)
{
secportaltype_e type = portal_type == TMSECPORTAL_HORIZON ? SECPORTAL_HORIZON : SECPORTAL_PLANE;
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(lines[i].frontsector, &portal_num);
floorportal->type = type;
floorportal->sector = lines[i].frontsector;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(lines[i].frontsector, &portal_num);
ceilportal->type = type;
ceilportal->sector = lines[i].frontsector;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
break;
}
INT32 s1 = -1;
TAG_ITER_SECTORS(target_sector_tag, s1)
{
sector_t *target_sector = &sectors[s1];
// Line portal
if (portal_type == TMSECPORTAL_NORMAL)
{
INT32 linenum = -1;
TAG_ITER_LINES(misc, linenum)
{
if (lines[linenum].special == SPECIAL_SECTOR_SETPORTAL
&& lines[linenum].args[0] == target_sector_tag
&& lines[linenum].args[1] == portal_type
&& lines[linenum].args[2] == plane_type
&& lines[linenum].args[3] == 1)
{
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector, &portal_num);
floorportal->type = SECPORTAL_LINE;
floorportal->line.start = &lines[i];
floorportal->line.dest = &lines[linenum];
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_LINE;
ceilportal->line.start = &lines[i];
ceilportal->line.dest = &lines[linenum];
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
}
}
// Skybox portal
else if (portal_type == TMSECPORTAL_SKYBOX)
{
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector, &portal_num);
floorportal->type = SECPORTAL_SKYBOX;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_SKYBOX;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
// Plane portal
else if (portal_type == TMSECPORTAL_SECTOR)
{
INT32 s2 = -1;
TAG_ITER_SECTORS(misc, s2) // Sector tag to make a portal to
{
sector_t *view_sector = &sectors[s2];
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector, &portal_num);
floorportal->type = SECPORTAL_CEILING;
floorportal->sector = view_sector;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_FLOOR;
ceilportal->sector = view_sector;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
}
// Use mobj as viewpoint
else if (portal_type == TMSECPORTAL_OBJECT)
{
mobj_t *mobj = P_GetMobjByTag(misc);
if (!mobj)
break;
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector, &portal_num);
floorportal->type = SECPORTAL_OBJECT;
P_SetTarget(&floorportal->mobj, mobj);
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_OBJECT;
P_SetTarget(&ceilportal->mobj, mobj);
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
}
break;
}
case 7: // Flat alignment - redone by toast
{
// Set calculated offsets such that line's v1 is the apparent origin
@ -7140,10 +7474,6 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
// Allocate each list
for (i = 0; i < numsectors; i++)
if(secthinkers[i].thinkers)
@ -7172,6 +7502,33 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
// Copy portals
for (i = 0; i < numlines; i++)
{
if (lines[i].special != SPECIAL_SECTOR_SETPORTAL)
continue;
int portal_type = lines[i].args[1];
if (portal_type != TMSECPORTAL_COPIED)
continue;
int target_sector_tag = lines[i].args[0];
int plane_type = lines[i].args[2];
int tag_to_copy = lines[i].args[3];
if (plane_type == 3)
plane_type = TMP_BOTH;
if (target_sector_tag == 0)
P_DoPortalCopyFromLine(lines[i].frontsector, plane_type, tag_to_copy);
else
{
INT32 s1 = -1;
TAG_ITER_SECTORS(target_sector_tag, s1)
P_DoPortalCopyFromLine(&sectors[s1], plane_type, tag_to_copy);
}
}
if (!fromnetsave)
P_RunLevelLoadExecutors();
}

View file

@ -21,6 +21,10 @@ extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpo
extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
extern size_t secportalcount;
extern size_t secportalcapacity;
extern sectorportal_t *secportals;
// Amount (dx, dy) vector linedef is shifted right to get scroll amount
#define SCROLL_SHIFT 5
@ -472,6 +476,20 @@ typedef enum
TMB_MODULATE = 4,
} textmapblendmodes_t;
typedef enum
{
TMSECPORTAL_NORMAL = 0,
TMSECPORTAL_COPIED = 1,
TMSECPORTAL_SKYBOX = 2,
TMSECPORTAL_PLANE = 3,
TMSECPORTAL_HORIZON = 4,
TMSECPORTAL_COPY_PORTAL_TO_LINE = 5,
TMSECPORTAL_INTERACTIVE = 6, // unimplemented
// The two portal types below are new to SRB2
TMSECPORTAL_SECTOR = 7,
TMSECPORTAL_OBJECT = 8
} textmapsecportaltype_t;
// GETSECSPECIAL (specialval, section)
//
// Pulls out the special # from a particular section.
@ -521,6 +539,19 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player);
boolean P_IsFlagAtBase(mobjtype_t flag);
void P_InitSectorPortals(void);
UINT32 P_NewSectorPortal(void);
boolean P_IsSectorPortalValid(sectorportal_t *secportal);
sectorportal_t *P_SectorGetFloorPortal(sector_t *sector);
sectorportal_t *P_SectorGetCeilingPortal(sector_t *sector);
boolean P_SectorHasPortal(sector_t *sector);
boolean P_SectorHasFloorPortal(sector_t *sector);
boolean P_SectorHasCeilingPortal(sector_t *sector);
boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b);
boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec);
boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec);
boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec);

View file

@ -36,6 +36,11 @@ drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for ma
drawseg_t *drawsegs = NULL;
drawseg_t *ds_p = NULL;
boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
boolean bothfloorssky = false; // likewise, but for floors
boolean horizonline = false;
// indicates doors closed wrt automap bugfix:
INT32 doorclosed;
@ -366,6 +371,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
{
if (P_SectorHasPortal(front) && !P_SectorHasPortal(back))
return false;
else if (!P_SectorHasPortal(front) && P_SectorHasPortal(back))
return false;
return (
!line->polyseg &&
back->ceilingpic == front->ceilingpic
@ -407,7 +417,6 @@ static void R_AddLine(seg_t *line)
INT32 x1, x2;
angle_t angle1, angle2, span, tspan;
static sector_t tempsec;
boolean bothceilingssky = false, bothfloorssky = false;
portalline = false;
@ -465,6 +474,8 @@ static void R_AddLine(seg_t *line)
return;
backsector = line->backsector;
horizonline = line->linedef->special == SPECIAL_HORIZON_LINE;
bothceilingssky = bothfloorssky = false;
// Portal line
if (line->linedef->special == 40 && line->side == 0)
@ -489,6 +500,15 @@ static void R_AddLine(seg_t *line)
}
}
}
// Transferred portal
else if (line->linedef->secportal != UINT32_MAX && line->side == 0)
{
if (portalrender < cv_maxportals.value)
{
Portal_AddTransferred(line->linedef->secportal, x1, x2);
goto clipsolid;
}
}
// Single sided line?
if (!backsector)
@ -498,9 +518,15 @@ static void R_AddLine(seg_t *line)
doorclosed = 0;
if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum)
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum
&& !(P_SectorHasCeilingPortal(backsector) || P_SectorHasCeilingPortal(frontsector)))
bothceilingssky = true;
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum)
// likewise, but for floors and upper textures
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum
&& !(P_SectorHasFloorPortal(backsector) || P_SectorHasFloorPortal(frontsector)))
bothfloorssky = true;
if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
@ -585,7 +611,6 @@ static void R_AddLine(seg_t *line)
// Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides, identical light levels on both sides,
// and no middle texture.
if (R_IsEmptyLine(line, frontsector, backsector))
return;
@ -880,66 +905,32 @@ static void R_Subsector(size_t num)
floorcenterz = P_GetSectorFloorZAt (frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
ceilingcenterz = P_GetSectorCeilingZAt(frontsector, frontsector->soundorg.x, frontsector->soundorg.y);
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
if (frontsector->ffloors)
{
boolean anyMoved = frontsector->moved;
if (anyMoved == false)
{
for (rover = frontsector->ffloors; rover; rover = rover->next)
{
sector_t *controlSec = &sectors[rover->secnum];
if (controlSec->moved == true)
{
anyMoved = true;
break;
}
}
}
if (anyMoved == true)
{
frontsector->numlights = sub->sector->numlights = 0;
R_Prep3DFloors(frontsector);
sub->sector->lightlist = frontsector->lightlist;
sub->sector->numlights = frontsector->numlights;
sub->sector->moved = frontsector->moved = false;
}
light = R_GetPlaneLight(frontsector, floorcenterz, false);
if (frontsector->floorlightsec == -1 && !frontsector->floorlightabsolute)
floorlightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->floorlightlevel));
floorcolormap = *frontsector->lightlist[light].extra_colormap;
light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
if (frontsector->ceilinglightsec == -1 && !frontsector->ceilinglightabsolute)
ceilinglightlevel = max(0, min(255, *frontsector->lightlist[light].lightlevel + frontsector->ceilinglightlevel));
ceilingcolormap = *frontsector->lightlist[light].extra_colormap;
}
R_CheckSectorLightLists(sub->sector, frontsector, &floorlightlevel, &ceilinglightlevel, &floorcolormap, &ceilingcolormap);
sub->sector->extra_colormap = frontsector->extra_colormap;
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz
|| frontsector->floorpic == skyflatnum
|| P_SectorHasFloorPortal(frontsector)
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
{
floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
floorplane = R_FindPlane(frontsector, frontsector->floorheight, frontsector->floorpic, floorlightlevel,
frontsector->floorxoffset, frontsector->flooryoffset,
frontsector->floorxscale, frontsector->flooryscale, frontsector->floorangle,
floorcolormap, NULL, NULL, frontsector->f_slope);
floorcolormap, NULL, NULL, frontsector->f_slope, P_SectorGetFloorPortal(frontsector));
}
else
floorplane = NULL;
if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz
|| frontsector->ceilingpic == skyflatnum
|| P_SectorHasCeilingPortal(frontsector)
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
{
ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel,
ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel,
frontsector->ceilingxoffset, frontsector->ceilingyoffset,
frontsector->ceilingxscale, frontsector->ceilingyscale, frontsector->ceilingangle,
ceilingcolormap, NULL, NULL, frontsector->c_slope);
ceilingcolormap, NULL, NULL, frontsector->c_slope, P_SectorGetCeilingPortal(frontsector));
}
else
ceilingplane = NULL;
@ -980,10 +971,10 @@ static void R_Subsector(size_t num)
light = R_GetPlaneLight(frontsector, planecenterz,
viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs,
*rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope);
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL);
ffloor[numffloors].slope = *rover->b_slope;
@ -1010,10 +1001,10 @@ static void R_Subsector(size_t num)
{
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs,
*rover->topxscale, *rover->topyscale, *rover->topangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope);
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL);
ffloor[numffloors].slope = *rover->t_slope;
@ -1053,18 +1044,17 @@ static void R_Subsector(size_t num)
&& (viewz < polysec->floorheight))
{
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
ffloor[numffloors].plane = R_FindPlane(polysec, polysec->floorheight, polysec->floorpic,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel),
polysec->floorxoffset, polysec->flooryoffset,
polysec->floorxscale, polysec->flooryscale,
polysec->floorangle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually?
NULL, NULL);
ffloor[numffloors].height = polysec->floorheight;
ffloor[numffloors].polyobj = po;
ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++;
}
@ -1079,18 +1069,17 @@ static void R_Subsector(size_t num)
&& (viewz > polysec->ceilingheight))
{
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
ffloor[numffloors].plane = R_FindPlane(polysec, polysec->ceilingheight, polysec->ceilingpic,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel),
polysec->ceilingxoffset, polysec->ceilingyoffset,
polysec->ceilingxscale, polysec->ceilingyscale,
polysec->ceilingangle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually?
NULL, NULL);
ffloor[numffloors].polyobj = po;
ffloor[numffloors].height = polysec->ceilingheight;
ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++;
}
@ -1099,18 +1088,18 @@ static void R_Subsector(size_t num)
}
}
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.
//
// 10/98 killough:
//
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!!
// Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way,
// like passing it as an argument.
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.
//
// 10/98 killough:
//
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!!
// Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way,
// like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2);
firstseg = NULL;
@ -1121,7 +1110,6 @@ static void R_Subsector(size_t num)
while (count--)
{
// CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime);
if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
R_AddLine(line);
line++;
@ -1129,6 +1117,51 @@ static void R_Subsector(size_t num)
}
}
void R_CheckSectorLightLists(sector_t *sector, sector_t *fakeflat, INT32 *floorlightlevel, INT32 *ceilinglightlevel, extracolormap_t **floorcolormap, extracolormap_t **ceilingcolormap)
{
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
if (fakeflat->ffloors)
{
fixed_t floorcenterz = P_GetSectorFloorZAt (fakeflat, fakeflat->soundorg.x, fakeflat->soundorg.y);
fixed_t ceilingcenterz = P_GetSectorCeilingZAt(fakeflat, fakeflat->soundorg.x, fakeflat->soundorg.y);
boolean anyMoved = fakeflat->moved;
if (anyMoved == false)
{
for (ffloor_t *rover = fakeflat->ffloors; rover; rover = rover->next)
{
sector_t *controlSec = &sectors[rover->secnum];
if (controlSec->moved == true)
{
anyMoved = true;
break;
}
}
}
if (anyMoved == true)
{
fakeflat->numlights = sector->numlights = 0;
R_Prep3DFloors(fakeflat);
sector->lightlist = fakeflat->lightlist;
sector->numlights = fakeflat->numlights;
sector->moved = fakeflat->moved = false;
}
INT32 light = R_GetPlaneLight(fakeflat, floorcenterz, false);
if (fakeflat->floorlightsec == -1 && !fakeflat->floorlightabsolute)
*floorlightlevel = max(0, min(255, *fakeflat->lightlist[light].lightlevel + fakeflat->floorlightlevel));
*floorcolormap = *fakeflat->lightlist[light].extra_colormap;
light = R_GetPlaneLight(fakeflat, ceilingcenterz, false);
if (fakeflat->ceilinglightsec == -1 && !fakeflat->ceilinglightabsolute)
*ceilinglightlevel = max(0, min(255, *fakeflat->lightlist[light].lightlevel + fakeflat->ceilinglightlevel));
*ceilingcolormap = *fakeflat->lightlist[light].extra_colormap;
}
}
//
// R_Prep3DFloors
//
@ -1314,3 +1347,59 @@ void R_RenderBSPNode(INT32 bspnum)
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}
void R_RenderPortalHorizonLine(sector_t *sector)
{
INT32 floorlightlevel, ceilinglightlevel;
static sector_t tempsec; // Deep water hack
extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap;
frontsector = sector;
backsector = NULL;
// Deep water/fake ceiling effect.
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false);
floorcolormap = ceilingcolormap = frontsector->extra_colormap;
R_CheckSectorLightLists(sector, frontsector, &floorlightlevel, &ceilinglightlevel, &floorcolormap, &ceilingcolormap);
sector->extra_colormap = frontsector->extra_colormap;
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz
|| frontsector->floorpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
{
floorplane = R_FindPlane(frontsector, frontsector->floorheight, frontsector->floorpic, floorlightlevel,
frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorxscale, frontsector->flooryscale,
frontsector->floorangle, floorcolormap, NULL, NULL, NULL, NULL);
}
else
floorplane = NULL;
if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz
|| frontsector->ceilingpic == skyflatnum
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
{
ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic,
ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingxscale, frontsector->ceilingyscale,
frontsector->ceilingyoffset, frontsector->ceilingangle,
ceilingcolormap, NULL, NULL, NULL, NULL);
}
else
ceilingplane = NULL;
numffloors = 0;
portalline = false;
doorclosed = 0;
bothceilingssky = bothfloorssky = false;
horizonline = true;
firstseg = NULL;
curline = &segs[0];
R_ClipSolidWallSegment(portalclipstart, portalclipend);
curline = NULL;
}

View file

@ -25,13 +25,17 @@ extern sector_t *frontsector;
extern sector_t *backsector;
extern boolean portalline; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c
extern INT32 checkcoord[12][4];
extern drawseg_t *curdrawsegs;
extern drawseg_t *drawsegs;
extern drawseg_t *ds_p;
extern boolean bothceilingssky;
extern boolean bothfloorssky;
extern boolean horizonline;
extern INT32 doorclosed;
// BSP?
@ -39,6 +43,7 @@ void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum);
void R_RenderPortalHorizonLine(sector_t *sector);
void R_SortPolyObjects(subsector_t *sub);
@ -52,4 +57,5 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector);
void R_CheckSectorLightLists(sector_t *sector, sector_t *fakeflat, INT32 *floorlightlevel, INT32 *ceilinglightlevel, extracolormap_t **floorcolormap, extracolormap_t **ceilingcolormap);
#endif

View file

@ -211,6 +211,34 @@ typedef enum
BT_STRONG,
} busttype_e;
typedef enum
{
SECPORTAL_LINE, // Works similar to a line portal
SECPORTAL_SKYBOX, // Uses the skybox object as the reference view
SECPORTAL_PLANE, // Eternity Engine's plane portal type
SECPORTAL_HORIZON, // Eternity Engine's horizon portal type
SECPORTAL_OBJECT, // Uses an object as the reference view
SECPORTAL_FLOOR, // Uses a sector as the reference view; the view height is aligned with the sector's floor
SECPORTAL_CEILING, // Uses a sector as the reference view; the view height is aligned with the sector's ceiling
SECPORTAL_NONE = 0xFF
} secportaltype_e;
typedef struct sectorportal_s
{
secportaltype_e type;
union {
struct {
struct line_s *start;
struct line_s *dest;
} line;
struct sector_s *sector;
struct mobj_s *mobj;
};
struct {
fixed_t x, y;
} origin;
} sectorportal_t;
typedef struct ffloor_s
{
fixed_t *topheight;
@ -505,6 +533,10 @@ typedef struct sector_s
// colormap structure
extracolormap_t *spawn_extra_colormap;
// portals
UINT32 portal_floor;
UINT32 portal_ceiling;
} sector_t;
//
@ -518,7 +550,9 @@ typedef enum
ST_NEGATIVE
} slopetype_t;
#define HORIZONSPECIAL 41
#define SPECIAL_HORIZON_LINE 41
#define SPECIAL_SECTOR_SETPORTAL 6
#define NUMLINEARGS 10
#define NUMLINESTRINGARGS 2
@ -561,6 +595,8 @@ typedef struct line_s
polyobj_t *polyobj; // Belongs to a polyobject?
INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0
UINT32 secportal; // transferred sector portal
} line_t;
typedef struct

View file

@ -1534,9 +1534,8 @@ void R_RenderPlayerView(player_t *player)
ps_numsprites.value.i = numvisiblesprites;
// Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0])
Portal_AddSkyboxPortals();
// Add portals caused by visplanes.
Portal_AddPlanePortals(cv_skybox.value);
// Portal rendering. Hijacks the BSP traversal.
PS_START_TIMING(ps_sw_portaltime);
@ -1569,9 +1568,21 @@ void R_RenderPlayerView(player_t *player)
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
if (portal->is_horizon)
{
// If the portal is a plane or a horizon portal, then we just render a horizon line
R_RenderPortalHorizonLine(portal->horizon_sector);
}
else
{
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
}
// Don't add skybox portals while already rendering a skybox view, because that'll cause an infinite loop
Portal_AddPlanePortals(cv_skybox.value && !portal->is_skybox);
Mask_Post(&masks[nummasks - 1]);
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);

View file

@ -368,10 +368,10 @@ static visplane_t *new_visplane(unsigned hash)
// Same height, same flattexture, same lightlevel.
// If not, allocates another of them.
//
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 lightlevel,
fixed_t xoff, fixed_t yoff, fixed_t xscale, fixed_t yscale,
angle_t plangle, extracolormap_t *planecolormap,
ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope)
ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope, sectorportal_t *portalsector)
{
visplane_t *check;
unsigned hash;
@ -430,7 +430,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
&& check->viewangle == viewangle
&& check->plangle == plangle
&& check->slope == slope
&& check->polyobj == polyobj)
&& check->polyobj == polyobj
&& P_CompareSectorPortals(check->portalsector, portalsector))
{
return check;
}
@ -459,6 +460,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
check->viewz = viewz;
check->viewangle = viewangle;
check->plangle = plangle;
check->sector = sector;
check->portalsector = portalsector;
check->polyobj = polyobj;
check->slope = slope;
@ -537,8 +540,10 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
new_pl->viewz = pl->viewz;
new_pl->viewangle = pl->viewangle;
new_pl->plangle = pl->plangle;
new_pl->sector = pl->sector;
new_pl->polyobj = pl->polyobj;
new_pl->slope = pl->slope;
new_pl->portalsector = pl->portalsector;
pl = new_pl;
pl->minx = start;
pl->maxx = stop;

View file

@ -51,9 +51,11 @@ typedef struct visplane_s
fixed_t xoffs, yoffs; // Scrolling flats.
fixed_t xscale, yscale;
sector_t *sector;
struct ffloor_s *ffloor;
polyobj_t *polyobj;
pslope_t *slope;
sectorportal_t *portalsector;
} visplane_t;
extern visplane_t *visplanes[MAXVISPLANES];
@ -71,8 +73,9 @@ void R_ClearPlanes(void);
void R_ClearFFloorClips (void);
void R_DrawPlanes(void);
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, fixed_t xscale, fixed_t yscale,
angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope);
visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 lightlevel,
fixed_t xoff, fixed_t yoff, fixed_t xscale, fixed_t yscale, angle_t plangle,
extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope, sectorportal_t *portalsector);
visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_PlaneBounds(visplane_t *plane);

View file

@ -16,6 +16,8 @@
#include "r_main.h"
#include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints
#include "p_slopes.h" // P_GetSectorFloorZAt and P_GetSectorCeilingZAt
#include "p_local.h"
#include "z_zone.h"
#include "r_things.h"
#include "r_sky.h"
@ -140,30 +142,17 @@ void Portal_Remove (portal_t* portal)
Z_Free(portal);
}
/** Creates a portal out of two lines and a determined screen range.
*
* line1 determines the entrance, and line2 the exit.
* x1 and x2 determine the screen's column bounds.
* The view's offset from the entry line center is obtained,
* and then rotated&translated to the exit line's center.
* When the portal renders, it will create the illusion of
* the two lines being seamed together.
*/
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest)
{
portal_t* portal = Portal_Add(x1, x2);
// Offset the portal view by the linedef centers
line_t* start = &lines[line1];
line_t* dest = &lines[line2];
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint;
angle_t angtopoint;
vertex_t dest_c, start_c;
struct {
fixed_t x, y;
} dest_c, start_c;
// looking glass center
start_c.x = (start->v1->x + start->v2->x) / 2;
@ -181,8 +170,31 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
}
/** Creates a portal out of two lines and a determined screen range.
*
* line1 determines the entrance, and line2 the exit.
* x1 and x2 determine the screen's column bounds.
* The view's offset from the entry line center is obtained,
* and then rotated&translated to the exit line's center.
* When the portal renders, it will create the illusion of
* the two lines being seamed together.
*/
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
{
portal_t* portal = Portal_Add(x1, x2);
line_t* start = &lines[line1];
line_t* dest = &lines[line2];
Portal_GetViewpointForLine(portal, start, dest);
portal->clipline = line2;
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_ClipRange(portal);
@ -252,30 +264,14 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16*
return false;
}
/** Creates a skybox portal out of a visplane.
*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
void Portal_AddSkybox (const visplane_t* plane)
static void Portal_GetViewpointForSkybox(portal_t *portal)
{
INT16 start, end;
mapheader_t *mh;
portal_t* portal;
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y;
portal->viewz = skyboxmo[0]->z;
portal->viewangle = viewangle + skyboxmo[0]->angle;
mh = mapheaderinfo[gamemap-1];
mapheader_t *mh = mapheaderinfo[gamemap-1];
// If a relative viewpoint exists, offset the viewpoint.
if (skyboxmo[1])
@ -302,34 +298,192 @@ void Portal_AddSkybox (const visplane_t* plane)
portal->viewz += viewz / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
portal->viewz += viewz * -mh->skybox_scalez;
portal->clipline = -1;
}
/** Creates portals for the currently existing sky visplanes.
/** Creates a skybox portal out of a visplane.
*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
static boolean Portal_AddSkybox (const visplane_t* plane)
{
INT16 start, end;
portal_t* portal;
if (TrimVisplaneBounds(plane, &start, &end))
return false;
portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_skybox = true;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSkybox(portal);
return true;
}
static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal)
{
fixed_t x, y, z;
angle_t angle;
switch (secportal->type)
{
case SECPORTAL_LINE:
Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest);
return;
case SECPORTAL_OBJECT:
if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj))
return;
x = secportal->mobj->x;
y = secportal->mobj->y;
z = secportal->mobj->z;
angle = secportal->mobj->angle;
break;
case SECPORTAL_FLOOR:
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
z = P_GetSectorFloorZAt(secportal->sector, x, y);
angle = 0;
break;
case SECPORTAL_CEILING:
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
z = P_GetSectorCeilingZAt(secportal->sector, x, y);
angle = 0;
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
portal->is_horizon = true;
portal->horizon_sector = secportal->sector;
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
if (secportal->type == SECPORTAL_PLANE)
z = -viewz;
else
z = 0;
angle = 0;
break;
default:
return;
}
fixed_t refx = secportal->origin.x - viewx;
fixed_t refy = secportal->origin.y - viewy;
// Rotate the X/Y to match the target angle
if (angle != 0)
{
fixed_t tr_x = refx, tr_y = refy;
angle_t ang = angle >> ANGLETOFINESHIFT;
refx = FixedMul(tr_x, FINECOSINE(ang)) - FixedMul(tr_y, FINESINE(ang));
refy = FixedMul(tr_x, FINESINE(ang)) + FixedMul(tr_y, FINECOSINE(ang));
}
portal->viewx = x - refx;
portal->viewy = y - refy;
portal->viewz = z + viewz;
portal->viewangle = angle + viewangle;
}
/** Creates a sector portal out of a visplane.
*/
static boolean Portal_AddSectorPortal (const visplane_t* plane)
{
INT16 start, end;
sectorportal_t *secportal = plane->portalsector;
// Shortcut
if (secportal->type == SECPORTAL_SKYBOX)
{
if (cv_skybox.value && skyboxmo[0])
return Portal_AddSkybox(plane);
return false;
}
if (TrimVisplaneBounds(plane, &start, &end))
return false;
portal_t* portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->is_skybox = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSecPortal(portal, secportal);
return true;
}
/** Creates a transferred sector portal.
*/
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2)
{
if (secportalnum >= secportalcount)
return;
sectorportal_t *secportal = &secportals[secportalnum];
if (!P_IsSectorPortalValid(secportal))
return;
portal_t* portal = Portal_Add(x1, x2);
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
if (secportal->type == SECPORTAL_SKYBOX)
Portal_GetViewpointForSkybox(portal);
else
Portal_GetViewpointForSecPortal(portal, secportal);
if (secportal->type == SECPORTAL_LINE)
portal->clipline = secportal->line.dest - lines;
else
portal->clipline = -1;
Portal_ClipRange(portal);
portalline = true;
}
/** Creates portals for the currently existing portal visplanes.
* The visplanes are also removed and cleared from the list.
*/
void Portal_AddSkyboxPortals (void)
void Portal_AddPlanePortals (boolean add_skyboxes)
{
visplane_t *pl;
INT32 i;
UINT16 count = 0;
for (i = 0; i < MAXVISPLANES; i++, pl++)
for (INT32 i = 0; i < MAXVISPLANES; i++, pl++)
{
for (pl = visplanes[i]; pl; pl = pl->next)
{
if (pl->picnum == skyflatnum)
{
Portal_AddSkybox(pl);
if (pl->minx >= pl->maxx)
continue;
boolean added_portal = false;
// Render sector portal if recursiveness limit hasn't been reached
if (pl->portalsector && portalrender < cv_maxportals.value)
added_portal = Portal_AddSectorPortal(pl);
// Render skybox portal
if (!added_portal && pl->picnum == skyflatnum && add_skyboxes && skyboxmo[0])
added_portal = Portal_AddSkybox(pl);
// don't render this visplane anymore
if (added_portal)
{
pl->minx = 0;
pl->maxx = -1;
count++;
}
}
}
CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count);
}

View file

@ -30,6 +30,12 @@ typedef struct portal_s
fixed_t viewz;
angle_t viewangle;
// For horizon portals
boolean is_horizon;
sector_t *horizon_sector;
boolean is_skybox;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */
@ -49,13 +55,13 @@ extern line_t *portalclipline;
extern sector_t *portalcullsector;
extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddSkybox (const visplane_t* plane);
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2);
void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
void Portal_AddPlanePortals (boolean add_skyboxes);
#endif

View file

@ -1867,9 +1867,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else
{
// two sided line
boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
boolean bothfloorssky = false; // likewise, but for floors
SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight)
worldhigh -= viewz;
@ -1877,21 +1874,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
worldlow -= viewz;
worldlowslope -= viewz;
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (frontsector->ceilingpic == skyflatnum
&& backsector->ceilingpic == skyflatnum)
{
bothceilingssky = true;
}
// likewise, but for floors and upper textures
if (frontsector->floorpic == skyflatnum
&& backsector->floorpic == skyflatnum)
{
bothfloorssky = true;
}
ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
ds_p->silhouette = 0;
@ -1991,6 +1973,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->floorlightsec != frontsector->floorlightsec
//SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap
|| !P_CompareSectorPortals(P_SectorGetFloorPortal(frontsector), P_SectorGetFloorPortal(backsector))
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{
markfloor = true;
@ -2026,9 +2009,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|| backsector->ceilinglightsec != frontsector->ceilinglightsec
//SoM: 4/3/2000: Check for colormaps
|| frontsector->extra_colormap != backsector->extra_colormap
|| !P_CompareSectorPortals(P_SectorGetCeilingPortal(frontsector), P_SectorGetCeilingPortal(backsector))
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
{
markceiling = true;
markceiling = true;
}
else
{
@ -2478,7 +2462,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
worldtopslope >>= 4;
worldbottomslope >>= 4;
if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES
if (horizonline) { // HORIZON LINES
topstep = bottomstep = 0;
topfrac = bottomfrac = (centeryfrac>>4);
topfrac++; // Prevent 1px HOM
@ -2579,7 +2563,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
ffloor[i].f_pos >>= 4;
ffloor[i].f_pos_slope >>= 4;
if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
if (horizonline) // Horizon lines extend FOFs in contact with them too.
{
ffloor[i].f_step = 0;
ffloor[i].f_frac = (centeryfrac>>4);