Implement "copy portal to line" sector portal type

This commit is contained in:
Lactozilla 2023-08-24 17:36:38 -03:00
parent ff5d53e54d
commit 9335ee3031
11 changed files with 186 additions and 74 deletions

View file

@ -461,6 +461,7 @@ enums
2 = "Skybox";
3 = "Plane";
4 = "Horizon";
5 = "Transfer to line";
7 = "Sector";
8 = "Object";
}

View file

@ -577,7 +577,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));
@ -1466,7 +1466,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)
{
fixed_t texturevpeg;

View file

@ -3473,7 +3473,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

@ -886,6 +886,7 @@ static void P_NetUnArchiveWaypoints(void)
#define LD_ARGS 0x10
#define LD_STRINGARGS 0x20
#define LD_EXECUTORDELAY 0x40
#define LD_TRANSFPORTAL 0x80
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
{
@ -1312,6 +1313,9 @@ static void ArchiveLines(void)
if (li->executordelay != spawnli->executordelay)
diff2 |= LD_EXECUTORDELAY;
if (li->secportal != spawnli->secportal)
diff2 |= LD_TRANSFPORTAL;
if (li->sidenum[0] != 0xffff)
{
si = &sides[li->sidenum[0]];
@ -1402,6 +1406,8 @@ static void ArchiveLines(void)
}
if (diff2 & LD_EXECUTORDELAY)
WRITEINT32(save_p, li->executordelay);
if (diff2 & LD_TRANSFPORTAL)
WRITEUINT32(save_p, li->secportal);
}
}
WRITEUINT16(save_p, 0xffff);
@ -1486,7 +1492,8 @@ static void UnArchiveLines(void)
}
if (diff2 & LD_EXECUTORDELAY)
li->executordelay = READINT32(save_p);
if (diff2 & LD_TRANSFPORTAL)
li->secportal = READUINT32(save_p);
}
}

View file

@ -1108,6 +1108,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

View file

@ -6214,7 +6214,7 @@ UINT32 P_NewSectorPortal(void)
return (UINT32)i;
}
static boolean P_IsSectorPortalValid(sectorportal_t *secportal)
boolean P_IsSectorPortalValid(sectorportal_t *secportal)
{
if (secportal == NULL)
return false;
@ -6325,28 +6325,59 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta
}
}
static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector)
static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result)
{
sectorportal_t *secportal = P_SectorGetFloorPortal(sector);
if (secportal == NULL)
*result = sector->portal_floor;
if (*result >= secportalcount)
{
sector->portal_floor = P_NewSectorPortal();
return &secportals[sector->portal_floor];
*result = P_NewSectorPortal();
sector->portal_floor = *result;
}
return secportal;
return &secportals[sector->portal_floor];
}
static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector)
static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result)
{
sectorportal_t *secportal = P_SectorGetCeilingPortal(sector);
if (secportal == NULL)
*result = sector->portal_floor;
if (*result >= secportalcount)
{
sector->portal_ceiling = P_NewSectorPortal();
return &secportals[sector->portal_ceiling];
*result = P_NewSectorPortal();
sector->portal_ceiling = *result;
}
return secportal;
return &secportals[sector->portal_ceiling];
}
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
@ -6514,7 +6545,7 @@ 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 6: // Sector portal
case SPECIAL_SECTOR_SETPORTAL: // Sector portal
{
int target_sector_tag = lines[i].args[0];
int portal_type = lines[i].args[1];
@ -6530,28 +6561,32 @@ void P_SpawnSpecials(boolean fromnetsave)
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);
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);
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) // Target sector tag
TAG_ITER_SECTORS(target_sector_tag, s1)
{
sector_t *target_sector = &sectors[s1];
@ -6561,7 +6596,7 @@ void P_SpawnSpecials(boolean fromnetsave)
INT32 linenum = -1;
TAG_ITER_LINES(misc, linenum)
{
if (lines[linenum].special == 6
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
@ -6569,17 +6604,19 @@ void P_SpawnSpecials(boolean fromnetsave)
{
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector);
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);
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);
}
}
}
@ -6589,13 +6626,15 @@ void P_SpawnSpecials(boolean fromnetsave)
{
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector);
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);
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_SKYBOX;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
// Plane portal
@ -6607,15 +6646,17 @@ void P_SpawnSpecials(boolean fromnetsave)
sector_t *view_sector = &sectors[s2];
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector);
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);
sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector, &portal_num);
ceilportal->type = SECPORTAL_FLOOR;
ceilportal->sector = view_sector;
P_CopySectorPortalToLines(portal_num, target_sector_tag);
}
}
}
@ -6627,15 +6668,17 @@ void P_SpawnSpecials(boolean fromnetsave)
break;
if (floor)
{
sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector);
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);
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);
}
}
}
@ -7448,7 +7491,7 @@ void P_SpawnSpecials(boolean fromnetsave)
// Copy portals
for (i = 0; i < numlines; i++)
{
if (lines[i].special != 6)
if (lines[i].special != SPECIAL_SECTOR_SETPORTAL)
continue;
int portal_type = lines[i].args[1];
@ -7470,7 +7513,6 @@ void P_SpawnSpecials(boolean fromnetsave)
TAG_ITER_SECTORS(target_sector_tag, s1)
P_DoPortalCopyFromLine(&sectors[s1], plane_type, tag_to_copy);
}
break;
}
if (!fromnetsave)

View file

@ -483,9 +483,8 @@ typedef enum
TMSECPORTAL_SKYBOX = 2,
TMSECPORTAL_PLANE = 3,
TMSECPORTAL_HORIZON = 4,
// The two portal types below are unimplemented
TMSECPORTAL_COPY_PORTAL_TO_LINE = 5,
TMSECPORTAL_INTERACTIVE = 6,
TMSECPORTAL_INTERACTIVE = 6, // unimplemented
// The two portal types below are new to SRB2
TMSECPORTAL_SECTOR = 7,
TMSECPORTAL_OBJECT = 8
@ -543,6 +542,8 @@ 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);

View file

@ -458,7 +458,7 @@ static void R_AddLine(seg_t *line)
return;
backsector = line->backsector;
horizonline = line->linedef->special == HORIZONSPECIAL;
horizonline = line->linedef->special == SPECIAL_HORIZON_LINE;
bothceilingssky = bothfloorssky = false;
// Portal line
@ -484,6 +484,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-lines, line->linedef->secportal, x1, x2);
goto clipsolid;
}
}
// Single sided line?
if (!backsector)

View file

@ -536,7 +536,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
@ -577,6 +579,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

@ -263,30 +263,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])
@ -313,31 +297,22 @@ 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;
portal->is_horizon = false;
portal->horizon_sector = NULL;
}
/** Creates a sector portal out of a visplane.
/** Creates a skybox portal out of a visplane.
*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
void Portal_AddSectorPortal (const visplane_t* plane)
void Portal_AddSkybox (const visplane_t* plane)
{
INT16 start, end;
fixed_t x, y, z, angle;
sectorportal_t *secportal = plane->portalsector;
// Shortcut
if (secportal->type == SECPORTAL_SKYBOX)
{
Portal_AddSkybox(plane);
return;
}
portal_t* portal;
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal_t* portal = Portal_Add(start, end);
portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
@ -345,6 +320,13 @@ void Portal_AddSectorPortal (const visplane_t* plane)
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSkybox(portal);
}
static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal, fixed_t origin_x, fixed_t origin_y)
{
fixed_t x, y, z, angle;
switch (secportal->type)
{
case SECPORTAL_LINE:
@ -374,8 +356,8 @@ void Portal_AddSectorPortal (const visplane_t* plane)
case SECPORTAL_HORIZON:
portal->is_horizon = true;
portal->horizon_sector = secportal->sector;
x = plane->sector->soundorg.x;
y = plane->sector->soundorg.y;
x = secportal->sector->soundorg.x;
y = secportal->sector->soundorg.y;
if (secportal->type == SECPORTAL_PLANE)
z = -viewz;
else
@ -386,8 +368,8 @@ void Portal_AddSectorPortal (const visplane_t* plane)
return;
}
fixed_t refx = plane->sector->soundorg.x - viewx;
fixed_t refy = plane->sector->soundorg.y - viewy;
fixed_t refx = origin_x - viewx;
fixed_t refy = origin_y - viewy;
// Rotate the X/Y to match the target angle
if (angle != 0)
@ -404,6 +386,70 @@ void Portal_AddSectorPortal (const visplane_t* plane)
portal->viewangle = angle + viewangle;
}
/** Creates a sector portal out of a visplane.
*/
void Portal_AddSectorPortal (const visplane_t* plane)
{
INT16 start, end;
sectorportal_t *secportal = plane->portalsector;
// Shortcut
if (secportal->type == SECPORTAL_SKYBOX)
{
Portal_AddSkybox(plane);
return;
}
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal_t* portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSecPortal(portal, secportal, plane->sector->soundorg.x, plane->sector->soundorg.y);
}
/** Creates a transferred sector portal.
*/
void Portal_AddTransferred (const INT32 linenum, 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_horizon = false;
portal->horizon_sector = NULL;
if (secportal->type == SECPORTAL_SKYBOX)
Portal_GetViewpointForSkybox(portal);
else
{
line_t *line = &lines[linenum];
fixed_t refx = (line->v1->x + line->v2->x) / 2;
fixed_t refy = (line->v1->y + line->v2->y) / 2;
Portal_GetViewpointForSecPortal(portal, secportal, refx, refy);
}
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 sky visplanes.
* The visplanes are also removed and cleared from the list.
*/

View file

@ -58,6 +58,7 @@ 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_AddSectorPortal (const visplane_t* plane);
void Portal_AddTransferred (const INT32 linenum, UINT32 secportalnum, const INT32 x1, const INT32 x2);
void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);