Implement Eternity Engine's plane portal and horizon portal types

This commit is contained in:
Lactozilla 2023-08-24 00:51:52 -03:00
parent 74ea880ca0
commit 6d812b4a43
10 changed files with 194 additions and 61 deletions

View file

@ -1117,8 +1117,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
INT32 gl_toptexture = 0, gl_bottomtexture = 0;
fixed_t texturevpeg;
bothceilingssky = bothfloorssky = false;
SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight)
SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight)
@ -2339,6 +2337,7 @@ static void HWR_AddLine(seg_t * line)
#endif
gl_backsector = line->backsector;
bothceilingssky = bothfloorssky = false;
#ifdef NEWCLIP
if (!line->backsector)
@ -2347,8 +2346,6 @@ static void HWR_AddLine(seg_t * line)
}
else
{
bothceilingssky = bothfloorssky = false;
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum

View file

@ -6227,6 +6227,9 @@ static boolean P_IsSectorPortalValid(sectorportal_t *secportal)
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;
}
@ -6525,6 +6528,23 @@ void P_SpawnSpecials(boolean fromnetsave)
ceiling = plane_type == TMP_CEILING;
}
// 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);
floorportal->type = type;
}
if (ceiling)
{
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(lines[i].frontsector);
ceilportal->type = type;
}
break;
}
INT32 s1 = -1;
TAG_ITER_SECTORS(target_sector_tag, s1) // Target sector tag
@ -6532,7 +6552,7 @@ void P_SpawnSpecials(boolean fromnetsave)
sector_t *target_sector = &sectors[s1];
// Line portal
if (portal_type == 0)
if (portal_type == TMSECPORTAL_NORMAL)
{
INT32 linenum = -1;
TAG_ITER_LINES(misc, linenum)
@ -6561,7 +6581,7 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
// Skybox portal
else if (portal_type == 2)
else if (portal_type == TMSECPORTAL_SKYBOX)
{
if (floor)
{
@ -6575,7 +6595,7 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
// Plane portal
else if (portal_type == 7)
else if (portal_type == TMSECPORTAL_SECTOR)
{
INT32 s2 = -1;
TAG_ITER_SECTORS(misc, s2) // Sector tag to make a portal to
@ -6596,7 +6616,7 @@ void P_SpawnSpecials(boolean fromnetsave)
}
}
// Use mobj as viewpoint
else if (portal_type == 8)
else if (portal_type == TMSECPORTAL_OBJECT)
{
mobj_t *mobj = P_GetMobjByTag(misc);
if (!mobj)
@ -7428,7 +7448,7 @@ void P_SpawnSpecials(boolean fromnetsave)
continue;
int portal_type = lines[i].args[1];
if (portal_type != 1)
if (portal_type != TMSECPORTAL_COPIED)
continue;
int target_sector_tag = lines[i].args[0];

View file

@ -476,6 +476,21 @@ typedef enum
TMB_MODULATE = 4,
} textmapblendmodes_t;
typedef enum
{
TMSECPORTAL_NORMAL,
TMSECPORTAL_COPIED,
TMSECPORTAL_SKYBOX,
TMSECPORTAL_PLANE,
TMSECPORTAL_HORIZON,
// The two portal types below are unimplemented
TMSECPORTAL_COPY_PORTAL_TO_LINE,
TMSECPORTAL_INTERACTIVE,
// The two portal types below are new to SRB2
TMSECPORTAL_SECTOR,
TMSECPORTAL_OBJECT
} textmapsecportaltype_t;
// GETSECSPECIAL (specialval, section)
//
// Pulls out the special # from a particular section.

View file

@ -39,6 +39,8 @@ 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;
@ -456,6 +458,8 @@ static void R_AddLine(seg_t *line)
return;
backsector = line->backsector;
horizonline = line->linedef->special == HORIZONSPECIAL;
bothceilingssky = bothfloorssky = false;
// Portal line
if (line->linedef->special == 40 && line->side == 0)
@ -488,7 +492,6 @@ static void R_AddLine(seg_t *line)
backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true);
doorclosed = 0;
bothceilingssky = bothfloorssky = false;
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
@ -844,6 +847,51 @@ static void R_AddPolyObjects(subsector_t *sub)
drawseg_t *firstseg;
static 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;
}
}
static void R_Subsector(size_t num)
{
INT32 count, floorlightlevel, ceilinglightlevel, light;
@ -877,43 +925,7 @@ 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;
@ -1301,3 +1313,57 @@ 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->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->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

@ -34,6 +34,8 @@ extern drawseg_t *ds_p;
extern boolean bothceilingssky;
extern boolean bothfloorssky;
extern boolean horizonline;
extern INT32 doorclosed;
// BSP?
@ -41,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);

View file

@ -210,11 +210,13 @@ typedef enum
typedef enum
{
SECPORTAL_LINE,
SECPORTAL_OBJECT,
SECPORTAL_SKYBOX,
SECPORTAL_FLOOR,
SECPORTAL_CEILING
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
} secportaltype_e;
typedef struct sectorportal_s

View file

@ -1547,9 +1547,18 @@ 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);
}
Mask_Post(&masks[nummasks - 1]);
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);

View file

@ -16,6 +16,7 @@
#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"
@ -191,6 +192,8 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
Portal_GetViewpointForLine(portal, start, dest);
portal->clipline = line2;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_ClipRange(portal);
@ -312,6 +315,8 @@ void Portal_AddSkybox (const visplane_t* plane)
portal->viewz += viewz * -mh->skybox_scalez;
portal->clipline = -1;
portal->is_horizon = false;
portal->horizon_sector = NULL;
}
/** Creates a sector portal out of a visplane.
@ -337,6 +342,8 @@ void Portal_AddSectorPortal (const visplane_t* plane)
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->horizon_sector = NULL;
switch (secportal->type)
{
@ -354,13 +361,25 @@ void Portal_AddSectorPortal (const visplane_t* plane)
case SECPORTAL_FLOOR:
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
z = secportal->sector->floorheight;
z = P_GetSectorFloorZAt(secportal->sector, x, y);
angle = 0;
break;
case SECPORTAL_CEILING:
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
z = secportal->sector->ceilingheight;
z = P_GetSectorCeilingZAt(secportal->sector, x, y);
angle = 0;
break;
case SECPORTAL_PLANE:
case SECPORTAL_HORIZON:
portal->is_horizon = true;
portal->horizon_sector = plane->sector;
x = plane->sector->soundorg.x;
y = plane->sector->soundorg.y;
if (secportal->type == SECPORTAL_PLANE)
z = -viewz;
else
z = 0;
angle = 0;
break;
default:

View file

@ -30,6 +30,10 @@ typedef struct portal_s
fixed_t viewz;
angle_t viewangle;
// For horizon portals
boolean is_horizon;
sector_t *horizon_sector;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */

View file

@ -1787,8 +1787,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else
{
// two sided line
bothceilingssky = bothfloorssky = false;
SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight)
worldhigh -= viewz;
@ -2334,7 +2332,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
@ -2435,7 +2433,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);