From 13ac83a2083440fafe62dd12928c4a647b0545b4 Mon Sep 17 00:00:00 2001 From: sphere Date: Mon, 5 Apr 2021 16:23:21 +0200 Subject: [PATCH 01/22] Floor portal test, ported Co-authored-by: Lactozilla --- src/deh_tables.c | 3 ++- src/info.c | 27 +++++++++++++++++++ src/info.h | 3 ++- src/p_mobj.c | 22 ++++++++++++++++ src/p_setup.c | 2 ++ src/r_bsp.c | 12 ++++----- src/r_defs.h | 3 +++ src/r_main.c | 4 +-- src/r_plane.c | 5 +++- src/r_plane.h | 3 ++- src/r_portal.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-- src/r_portal.h | 10 ++++--- 12 files changed, 143 insertions(+), 19 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 3580e15c6..05f61f6e5 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4283,8 +4283,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_POLYANCHOR", "MT_POLYSPAWN", - // Skybox objects + // Portal objects "MT_SKYBOX", + "MT_PORTALREFPOINT", // Debris "MT_SPARK", //spark diff --git a/src/info.c b/src/info.c index 11e9c9fe8..f71a2bd1c 100644 --- a/src/info.c +++ b/src/info.c @@ -20759,6 +20759,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PORTALREFPOINT + 781, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 10, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SPARK -1, // doomednum S_SPRK1, // spawnstate diff --git a/src/info.h b/src/info.h index 5c7a9f3fd..00822faea 100644 --- a/src/info.h +++ b/src/info.h @@ -5114,8 +5114,9 @@ typedef enum mobj_type MT_POLYANCHOR, MT_POLYSPAWN, - // Skybox objects + // Portal objects MT_SKYBOX, + MT_PORTALREFPOINT, // Debris MT_SPARK, //spark diff --git a/src/p_mobj.c b/src/p_mobj.c index de2c3a72c..f7ad7616d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12822,6 +12822,28 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean skyboxviewpnts[tag] = mobj; break; } + case MT_PORTALREFPOINT: + { + size_t i; + for (i = 0; i < numsectors; i++) + { + sector_t *targetsec = §ors[i]; + for (int j = 0; j < targetsec->tags.count; j++) + { + if ((mthing->extrainfo == targetsec->tags.tags[j]) && (GETSECSPECIAL(targetsec->special, 3) == 1)) + { + // origin + if (targetsec == mobj->subsector->sector) + targetsec->portals[1] = mobj; + // target + else + targetsec->portals[0] = mobj; + break; + } + } + } + } + break; case MT_EGGSTATUE: if (mthing->args[1]) { diff --git a/src/p_setup.c b/src/p_setup.c index e289b8346..51c14e147 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -989,6 +989,8 @@ static void P_InitializeSector(sector_t *ss) ss->floordata = NULL; ss->ceilingdata = NULL; ss->lightingdata = NULL; + ss->portals[0] = NULL; + ss->portals[1] = NULL; ss->fadecolormapdata = NULL; ss->heightsec = -1; diff --git a/src/r_bsp.c b/src/r_bsp.c index 42e050adf..70a9dbd94 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -908,7 +908,7 @@ static void R_Subsector(size_t num) || frontsector->floorpic == skyflatnum || (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->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope); } else @@ -918,7 +918,7 @@ static void R_Subsector(size_t num) || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { - ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, + ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, ceilingcolormap, NULL, NULL, frontsector->c_slope); } @@ -961,7 +961,7 @@ 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->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope); @@ -990,7 +990,7 @@ 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->topangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope); @@ -1032,7 +1032,7 @@ 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->floorangle-po->angle, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, @@ -1056,7 +1056,7 @@ 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->ceilingangle-po->angle, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, NULL); // will ffloors be slopable eventually? diff --git a/src/r_defs.h b/src/r_defs.h index dfd2d6d70..61f9eaa4e 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -494,6 +494,9 @@ typedef struct sector_s // colormap structure extracolormap_t *spawn_extra_colormap; + + // floor portals + mobj_t *portals[2]; } sector_t; // diff --git a/src/r_main.c b/src/r_main.c index 952171405..8a0575d66 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1513,10 +1513,8 @@ void R_RenderPlayerView(player_t *player) R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); - // Add skybox portals caused by sky visplanes. - if (cv_skybox.value && skyboxmo[0]) - Portal_AddSkyboxPortals(); + Portal_AddSkyboxPortals(); // Portal rendering. Hijacks the BSP traversal. PS_START_TIMING(ps_sw_portaltime); diff --git a/src/r_plane.c b/src/r_plane.c index 29ce26b29..a24ea9d28 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -390,7 +390,7 @@ 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, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope) { @@ -447,6 +447,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, && lightlevel == check->lightlevel && xoff == check->xoffs && yoff == check->yoffs && planecolormap == check->extra_colormap + && !pfloor && !check->ffloor && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewangle == viewangle && check->plangle == plangle @@ -477,6 +478,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->viewz = viewz; check->viewangle = viewangle; check->plangle = plangle; + check->sector = sector; check->polyobj = polyobj; check->slope = slope; @@ -553,6 +555,7 @@ 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; pl = new_pl; diff --git a/src/r_plane.h b/src/r_plane.h index 917e8b041..a3ae84f65 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -50,6 +50,7 @@ typedef struct visplane_s fixed_t xoffs, yoffs; // Scrolling flats. + sector_t *sector; struct ffloor_s *ffloor; polyobj_t *polyobj; pslope_t *slope; @@ -75,7 +76,7 @@ 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, angle_t plangle, +visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope); visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop); void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop); diff --git a/src/r_portal.c b/src/r_portal.c index e594f960a..1a2b905f9 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -16,11 +16,13 @@ #include "r_main.h" #include "doomstat.h" #include "p_spec.h" // Skybox viewpoints +#include "p_local.h" #include "z_zone.h" #include "r_things.h" #include "r_sky.h" UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ +UINT8 floorportalrender; /**< Same deal, but for floorportals. */ // Linked list for portals. portal_t *portal_base, *portal_cap; @@ -34,6 +36,7 @@ boolean portalline; // is curline a portal seg? void Portal_InitList (void) { portalrender = 0; + floorportalrender = 0; portal_base = portal_cap = NULL; } @@ -306,6 +309,45 @@ void Portal_AddSkybox (const visplane_t* plane) portal->clipline = -1; } +/** Creates a floor portal out of a visplane. + * + * Mostly the same as Portal_AddSkybox. + */ +void Portal_AddFloorPortal (const visplane_t* plane) +{ + INT16 start, end; + portal_t* portal; + sector_t *portalsector = plane->sector; + mobj_t *portalmobj = portalsector->portals[0]; + mobj_t *refmobj = portalsector->portals[1]; + fixed_t refx, refy; + + if (TrimVisplaneBounds(plane, &start, &end)) + return; + + portal = Portal_Add(start, end); + + Portal_ClipVisplane(plane, portal); + + if ((refmobj != NULL) && !(P_MobjWasRemoved(refmobj))) + { + refx = (refmobj->x - viewx); + refy = (refmobj->y - viewy); + } + else + { + refx = (portalsector->soundorg.x - viewx); + refy = (portalsector->soundorg.y - viewy); + } + + portal->viewx = portalmobj->x - refx; + portal->viewy = portalmobj->y - refy; + portal->viewz = portalmobj->z + viewz; + portal->viewangle = viewangle + portalmobj->angle; + + portal->clipline = -1; +} + /** Creates portals for the currently existing sky visplanes. * The visplanes are also removed and cleared from the list. */ @@ -319,13 +361,35 @@ void Portal_AddSkyboxPortals (void) { for (pl = visplanes[i]; pl; pl = pl->next) { + // true if added a portal for this visplane + boolean addedportal = false; + boolean floorportalpresent = (pl->sector->portals[0] != NULL && !P_MobjWasRemoved(pl->sector->portals[0])); + + // skybox portal if (pl->picnum == skyflatnum) { - Portal_AddSkybox(pl); + if (cv_skybox.value && skyboxmo[0]) + { + Portal_AddSkybox(pl); + addedportal = true; + } + } + // floor portal + else if (floorportalpresent) + { + if (floorportalrender < cv_maxportals.value) + { + Portal_AddFloorPortal(pl); + floorportalrender++; + addedportal = true; + } + } + // don't render this visplane anymore + if (addedportal) + { pl->minx = 0; pl->maxx = -1; - count++; } } diff --git a/src/r_portal.h b/src/r_portal.h index f90f05fbc..14b49f289 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -44,15 +44,17 @@ typedef struct portal_s extern portal_t* portal_base; extern portal_t* portal_cap; extern UINT8 portalrender; +extern UINT8 floorportalrender; 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_AddSkybox (const visplane_t* plane); +void Portal_AddFloorPortal (const visplane_t* plane); void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); From 1506909a1f5ac3b943e7d068d06c01b298b0bb68 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 04:24:06 -0300 Subject: [PATCH 02/22] Reimplement sector portals --- src/p_mobj.c | 22 ----------------- src/p_setup.c | 12 ++++++++-- src/p_spec.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/r_bsp.c | 14 +++++------ src/r_defs.h | 14 +++++++++-- src/r_plane.c | 7 ++++-- src/r_plane.h | 3 ++- src/r_portal.c | 64 ++++++++++++++++++++------------------------------ src/r_portal.h | 2 +- 9 files changed, 121 insertions(+), 76 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f7ad7616d..de2c3a72c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12822,28 +12822,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean skyboxviewpnts[tag] = mobj; break; } - case MT_PORTALREFPOINT: - { - size_t i; - for (i = 0; i < numsectors; i++) - { - sector_t *targetsec = §ors[i]; - for (int j = 0; j < targetsec->tags.count; j++) - { - if ((mthing->extrainfo == targetsec->tags.tags[j]) && (GETSECSPECIAL(targetsec->special, 3) == 1)) - { - // origin - if (targetsec == mobj->subsector->sector) - targetsec->portals[1] = mobj; - // target - else - targetsec->portals[0] = mobj; - break; - } - } - } - } - break; case MT_EGGSTATUE: if (mthing->args[1]) { diff --git a/src/p_setup.c b/src/p_setup.c index 51c14e147..c590bba4f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -978,6 +978,13 @@ static void P_LoadVertices(UINT8 *data) } } +static void InitializeSectorPortal(sectorportal_t *secportal) +{ + secportal->target = NULL; + secportal->viewpoint.x = secportal->viewpoint.y = secportal->viewpoint.z = 0; + secportal->viewpoint.angle = 0; +} + static void P_InitializeSector(sector_t *ss) { memset(&ss->soundorg, 0, sizeof(ss->soundorg)); @@ -989,10 +996,11 @@ static void P_InitializeSector(sector_t *ss) ss->floordata = NULL; ss->ceilingdata = NULL; ss->lightingdata = NULL; - ss->portals[0] = NULL; - ss->portals[1] = NULL; ss->fadecolormapdata = NULL; + InitializeSectorPortal(&ss->portal_plane_floor); + InitializeSectorPortal(&ss->portal_plane_ceiling); + ss->heightsec = -1; ss->camsec = -1; diff --git a/src/p_spec.c b/src/p_spec.c index 28ecc60f4..4c34aaf05 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6186,6 +6186,38 @@ fixed_t P_GetSectorGravityFactor(sector_t *sec) return sec->gravity; } +static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, INT32 viewpoint_tag) +{ + secportal->target = target_sector; + secportal->viewpoint.x = target_sector->soundorg.x; + secportal->viewpoint.y = target_sector->soundorg.y; + secportal->viewpoint.z = target_sector->ceilingheight; + secportal->viewpoint.angle = 0; + + if (viewpoint_tag <= 0) + return; + + for (thinker_t *th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mobj_t *mo = (mobj_t *)th; + + if (mo->type != MT_PORTALREFPOINT || mo->spawnpoint == NULL) + continue; + + if (!Tag_Find(&mo->spawnpoint->tags, viewpoint_tag)) + continue; + + secportal->viewpoint.x = mo->x; + secportal->viewpoint.y = mo->y; + secportal->viewpoint.z = mo->z; + secportal->viewpoint.angle = mo->angle; + return; + } +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6351,6 +6383,33 @@ void P_SpawnSpecials(boolean fromnetsave) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; + case 6: // Sector portal + { + INT32 s1, s2; + TAG_ITER_SECTORS(lines[i].args[0], s1) // Target sector tag + { + TAG_ITER_SECTORS(lines[i].args[1], s2) // Sector tag to make a portal to + { + sector_t *target_sector = §ors[s2]; + boolean floor, ceiling; + + if (lines[i].args[2] == TMP_BOTH) + floor = ceiling = true; + else + { + floor = lines[i].args[2] == TMP_FLOOR; + ceiling = lines[i].args[2] == TMP_CEILING; + } + + if (floor) + SetSectorPortal(§ors[s1].portal_plane_floor, target_sector, lines[i].args[3]); + if (ceiling) + SetSectorPortal(§ors[s1].portal_plane_ceiling, target_sector, lines[i].args[3]); + } + } + break; + } + case 7: // Flat alignment - redone by toast { // Set calculated offsets such that line's v1 is the apparent origin diff --git a/src/r_bsp.c b/src/r_bsp.c index 70a9dbd94..5c9aa3ff9 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -909,7 +909,7 @@ static void R_Subsector(size_t num) || (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, frontsector->f_slope); + frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope, frontsector->portal_plane_floor.target != NULL ? &frontsector->portal_plane_floor : NULL); } else floorplane = NULL; @@ -920,7 +920,7 @@ static void R_Subsector(size_t num) { ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, frontsector->c_slope); + ceilingcolormap, NULL, NULL, frontsector->c_slope, frontsector->portal_plane_ceiling.target != NULL ? &frontsector->portal_plane_ceiling : NULL); } else ceilingplane = NULL; @@ -963,7 +963,7 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, - *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope); + *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL); ffloor[numffloors].slope = *rover->b_slope; @@ -992,7 +992,7 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *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; @@ -1036,12 +1036,11 @@ static void R_Subsector(size_t num) (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floorxoffset, polysec->flooryoffset, 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++; } @@ -1059,12 +1058,11 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(polysec, polysec->ceilingheight, polysec->ceilingpic, (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceilingxoffset, polysec->ceilingyoffset, 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++; } diff --git a/src/r_defs.h b/src/r_defs.h index 61f9eaa4e..d9fe6193d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -208,6 +208,15 @@ typedef enum BT_STRONG, } busttype_e; +typedef struct sectorportal_s +{ + struct sector_s *target; + struct { + fixed_t x, y, z; + angle_t angle; + } viewpoint; +} sectorportal_t; + typedef struct ffloor_s { fixed_t *topheight; @@ -495,8 +504,9 @@ typedef struct sector_s // colormap structure extracolormap_t *spawn_extra_colormap; - // floor portals - mobj_t *portals[2]; + // portals + sectorportal_t portal_plane_floor; + sectorportal_t portal_plane_ceiling; } sector_t; // diff --git a/src/r_plane.c b/src/r_plane.c index a24ea9d28..5cd791023 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -392,7 +392,7 @@ static visplane_t *new_visplane(unsigned hash) // visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, 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; @@ -451,7 +451,8 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewangle == viewangle && check->plangle == plangle - && check->slope == slope) + && check->slope == slope + && check->portalsector == portalsector) { return check; } @@ -479,6 +480,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li check->viewangle = viewangle; check->plangle = plangle; check->sector = sector; + check->portalsector = portalsector; check->polyobj = polyobj; check->slope = slope; @@ -558,6 +560,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) 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; diff --git a/src/r_plane.h b/src/r_plane.h index a3ae84f65..e33267798 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -54,6 +54,7 @@ typedef struct visplane_s struct ffloor_s *ffloor; polyobj_t *polyobj; pslope_t *slope; + sectorportal_t *portalsector; } visplane_t; extern visplane_t *visplanes[MAXVISPLANES]; @@ -77,7 +78,7 @@ void R_ClearFFloorClips (void); void R_DrawPlanes(void); visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, - extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope); + 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); diff --git a/src/r_portal.c b/src/r_portal.c index 1a2b905f9..b4328a56e 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -309,41 +309,38 @@ void Portal_AddSkybox (const visplane_t* plane) portal->clipline = -1; } -/** Creates a floor portal out of a visplane. +/** Creates a sector portal out of a visplane. * * Mostly the same as Portal_AddSkybox. */ -void Portal_AddFloorPortal (const visplane_t* plane) +void Portal_AddSectorPortal (const visplane_t* plane) { INT16 start, end; - portal_t* portal; - sector_t *portalsector = plane->sector; - mobj_t *portalmobj = portalsector->portals[0]; - mobj_t *refmobj = portalsector->portals[1]; - fixed_t refx, refy; + sector_t *source = plane->sector; + sectorportal_t *target = plane->portalsector; if (TrimVisplaneBounds(plane, &start, &end)) return; - portal = Portal_Add(start, end); + portal_t* portal = Portal_Add(start, end); Portal_ClipVisplane(plane, portal); - if ((refmobj != NULL) && !(P_MobjWasRemoved(refmobj))) + fixed_t refx = source->soundorg.x - viewx; + fixed_t refy = source->soundorg.y - viewy; + + if (target->viewpoint.angle) { - refx = (refmobj->x - viewx); - refy = (refmobj->y - viewy); - } - else - { - refx = (portalsector->soundorg.x - viewx); - refy = (portalsector->soundorg.y - viewy); + fixed_t x = refx, y = refy; + angle_t ang = target->viewpoint.angle >> ANGLETOFINESHIFT; + refx = FixedMul(x, FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + refy = FixedMul(x, FINESINE(ang)) + FixedMul(y, FINECOSINE(ang)); } - portal->viewx = portalmobj->x - refx; - portal->viewy = portalmobj->y - refy; - portal->viewz = portalmobj->z + viewz; - portal->viewangle = viewangle + portalmobj->angle; + portal->viewx = target->viewpoint.x - refx; + portal->viewy = target->viewpoint.y - refy; + portal->viewz = target->viewpoint.z + viewz; + portal->viewangle = target->viewpoint.angle + viewangle; portal->clipline = -1; } @@ -354,16 +351,12 @@ void Portal_AddFloorPortal (const visplane_t* plane) void Portal_AddSkyboxPortals (void) { 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) { - // true if added a portal for this visplane - boolean addedportal = false; - boolean floorportalpresent = (pl->sector->portals[0] != NULL && !P_MobjWasRemoved(pl->sector->portals[0])); + boolean added_portal = false; // skybox portal if (pl->picnum == skyflatnum) @@ -371,29 +364,24 @@ void Portal_AddSkyboxPortals (void) if (cv_skybox.value && skyboxmo[0]) { Portal_AddSkybox(pl); - addedportal = true; + added_portal = true; } } + // floor portal - else if (floorportalpresent) + if (pl->portalsector && pl->portalsector->target && floorportalrender < cv_maxportals.value) { - if (floorportalrender < cv_maxportals.value) - { - Portal_AddFloorPortal(pl); - floorportalrender++; - addedportal = true; - } + Portal_AddSectorPortal(pl); + floorportalrender++; + added_portal = true; } // don't render this visplane anymore - if (addedportal) + if (added_portal) { pl->minx = 0; pl->maxx = -1; - count++; } } } - - CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count); } diff --git a/src/r_portal.h b/src/r_portal.h index 14b49f289..6e2a6dedb 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -54,7 +54,7 @@ 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_AddFloorPortal (const visplane_t* plane); +void Portal_AddSectorPortal (const visplane_t* plane); void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); From 2b64698c4eedd14ab80d94e866d8962aba5aa545 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 04:34:35 -0300 Subject: [PATCH 03/22] Use different default viewpoint heights so that ceiling portals make more sense --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 4c34aaf05..5dc99ee5b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6186,12 +6186,12 @@ fixed_t P_GetSectorGravityFactor(sector_t *sec) return sec->gravity; } -static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, INT32 viewpoint_tag) +static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, fixed_t default_z, INT32 viewpoint_tag) { secportal->target = target_sector; secportal->viewpoint.x = target_sector->soundorg.x; secportal->viewpoint.y = target_sector->soundorg.y; - secportal->viewpoint.z = target_sector->ceilingheight; + secportal->viewpoint.z = default_z; secportal->viewpoint.angle = 0; if (viewpoint_tag <= 0) @@ -6402,9 +6402,9 @@ void P_SpawnSpecials(boolean fromnetsave) } if (floor) - SetSectorPortal(§ors[s1].portal_plane_floor, target_sector, lines[i].args[3]); + SetSectorPortal(§ors[s1].portal_plane_floor, target_sector, target_sector->ceilingheight, lines[i].args[3]); if (ceiling) - SetSectorPortal(§ors[s1].portal_plane_ceiling, target_sector, lines[i].args[3]); + SetSectorPortal(§ors[s1].portal_plane_ceiling, target_sector, target_sector->floorheight, lines[i].args[3]); } } break; From 03daf721effb5d99254f8d6e86fbc697ed79bf67 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 13:43:02 -0300 Subject: [PATCH 04/22] Allow sector portals to be displayed properly on sky sectors --- src/hardware/hw_main.c | 18 +++++++----------- src/p_setup.c | 10 +++++----- src/p_spec.c | 27 ++++++++++++++++----------- src/p_spec.h | 2 ++ src/r_bsp.c | 19 ++++++++++++++----- src/r_bsp.h | 6 ++++-- src/r_defs.h | 8 ++++---- src/r_plane.c | 3 +-- src/r_portal.c | 39 +++++++++++++++++---------------------- src/r_portal.h | 1 - src/r_segs.c | 20 +++----------------- 11 files changed, 73 insertions(+), 80 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bc66955fc..2340b9e8b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1117,8 +1117,7 @@ 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 + bothceilingssky = bothfloorssky = false; SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight) @@ -1854,12 +1853,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 @@ -2354,13 +2347,16 @@ static void HWR_AddLine(seg_t * line) } else { - boolean bothceilingssky = false, bothfloorssky = false; + bothceilingssky = 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 + && !(gl_backsector->portal_ceiling.exists || gl_frontsector->portal_ceiling.exists)) bothceilingssky = true; - if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum) + + if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum + && !(gl_backsector->portal_floor.exists || gl_frontsector->portal_floor.exists)) bothfloorssky = true; if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then diff --git a/src/p_setup.c b/src/p_setup.c index c590bba4f..b9c2b5939 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -980,9 +980,9 @@ static void P_LoadVertices(UINT8 *data) static void InitializeSectorPortal(sectorportal_t *secportal) { - secportal->target = NULL; - secportal->viewpoint.x = secportal->viewpoint.y = secportal->viewpoint.z = 0; - secportal->viewpoint.angle = 0; + secportal->exists = false; + secportal->target.x = secportal->target.y = secportal->target.z = 0; + secportal->target.angle = 0; } static void P_InitializeSector(sector_t *ss) @@ -998,8 +998,8 @@ static void P_InitializeSector(sector_t *ss) ss->lightingdata = NULL; ss->fadecolormapdata = NULL; - InitializeSectorPortal(&ss->portal_plane_floor); - InitializeSectorPortal(&ss->portal_plane_ceiling); + InitializeSectorPortal(&ss->portal_floor); + InitializeSectorPortal(&ss->portal_ceiling); ss->heightsec = -1; ss->camsec = -1; diff --git a/src/p_spec.c b/src/p_spec.c index 5dc99ee5b..57653416a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6186,13 +6186,18 @@ fixed_t P_GetSectorGravityFactor(sector_t *sec) return sec->gravity; } +boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) +{ + return !memcmp(a, b, sizeof(sectorportal_t)); +} + static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, fixed_t default_z, INT32 viewpoint_tag) { - secportal->target = target_sector; - secportal->viewpoint.x = target_sector->soundorg.x; - secportal->viewpoint.y = target_sector->soundorg.y; - secportal->viewpoint.z = default_z; - secportal->viewpoint.angle = 0; + secportal->exists = target_sector; + secportal->target.x = target_sector->soundorg.x; + secportal->target.y = target_sector->soundorg.y; + secportal->target.z = default_z; + secportal->target.angle = 0; if (viewpoint_tag <= 0) return; @@ -6210,10 +6215,10 @@ static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, if (!Tag_Find(&mo->spawnpoint->tags, viewpoint_tag)) continue; - secportal->viewpoint.x = mo->x; - secportal->viewpoint.y = mo->y; - secportal->viewpoint.z = mo->z; - secportal->viewpoint.angle = mo->angle; + secportal->target.x = mo->x; + secportal->target.y = mo->y; + secportal->target.z = mo->z; + secportal->target.angle = mo->angle; return; } } @@ -6402,9 +6407,9 @@ void P_SpawnSpecials(boolean fromnetsave) } if (floor) - SetSectorPortal(§ors[s1].portal_plane_floor, target_sector, target_sector->ceilingheight, lines[i].args[3]); + SetSectorPortal(§ors[s1].portal_floor, target_sector, target_sector->ceilingheight, lines[i].args[3]); if (ceiling) - SetSectorPortal(§ors[s1].portal_plane_ceiling, target_sector, target_sector->floorheight, lines[i].args[3]); + SetSectorPortal(§ors[s1].portal_ceiling, target_sector, target_sector->floorheight, lines[i].args[3]); } } break; diff --git a/src/p_spec.h b/src/p_spec.h index 50ab6410f..71c9dcf3a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -521,6 +521,8 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); +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); diff --git a/src/r_bsp.c b/src/r_bsp.c index 5c9aa3ff9..70f08e127 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -36,6 +36,9 @@ 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 + // indicates doors closed wrt automap bugfix: INT32 doorclosed; @@ -391,7 +394,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; @@ -481,10 +483,17 @@ static void R_AddLine(seg_t *line) backsector = R_FakeFlat(backsector, &tempsec, NULL, NULL, true); doorclosed = 0; + bothceilingssky = bothfloorssky = false; - 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 + && !(backsector->portal_ceiling.exists || frontsector->portal_ceiling.exists)) bothceilingssky = true; - if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum) + + // likewise, but for floors and upper textures + if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum + && !(backsector->portal_floor.exists || frontsector->portal_floor.exists)) bothfloorssky = true; if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then @@ -909,7 +918,7 @@ static void R_Subsector(size_t num) || (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, frontsector->f_slope, frontsector->portal_plane_floor.target != NULL ? &frontsector->portal_plane_floor : NULL); + frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope, frontsector->portal_floor.exists ? &frontsector->portal_floor : NULL); } else floorplane = NULL; @@ -920,7 +929,7 @@ static void R_Subsector(size_t num) { ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, frontsector->c_slope, frontsector->portal_plane_ceiling.target != NULL ? &frontsector->portal_plane_ceiling : NULL); + ceilingcolormap, NULL, NULL, frontsector->c_slope, frontsector->portal_ceiling.exists ? &frontsector->portal_ceiling : NULL); } else ceilingplane = NULL; diff --git a/src/r_bsp.h b/src/r_bsp.h index 55199405a..f36f7e64d 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -25,13 +25,15 @@ 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 INT32 doorclosed; // BSP? diff --git a/src/r_defs.h b/src/r_defs.h index d9fe6193d..d435f69ab 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -210,11 +210,11 @@ typedef enum typedef struct sectorportal_s { - struct sector_s *target; + boolean exists; struct { fixed_t x, y, z; angle_t angle; - } viewpoint; + } target; } sectorportal_t; typedef struct ffloor_s @@ -505,8 +505,8 @@ typedef struct sector_s extracolormap_t *spawn_extra_colormap; // portals - sectorportal_t portal_plane_floor; - sectorportal_t portal_plane_ceiling; + sectorportal_t portal_floor; + sectorportal_t portal_ceiling; } sector_t; // diff --git a/src/r_plane.c b/src/r_plane.c index 5cd791023..d9051ae05 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -441,8 +441,6 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li hash = visplane_hash(picnum, lightlevel, height); for (check = visplanes[hash]; check; check = check->next) { - if (polyobj != check->polyobj) - continue; if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel && xoff == check->xoffs && yoff == check->yoffs @@ -452,6 +450,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li && check->viewangle == viewangle && check->plangle == plangle && check->slope == slope + && check->polyobj == polyobj && check->portalsector == portalsector) { return check; diff --git a/src/r_portal.c b/src/r_portal.c index b4328a56e..136eb4fac 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -22,7 +22,6 @@ #include "r_sky.h" UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ -UINT8 floorportalrender; /**< Same deal, but for floorportals. */ // Linked list for portals. portal_t *portal_base, *portal_cap; @@ -36,7 +35,6 @@ boolean portalline; // is curline a portal seg? void Portal_InitList (void) { portalrender = 0; - floorportalrender = 0; portal_base = portal_cap = NULL; } @@ -317,7 +315,7 @@ void Portal_AddSectorPortal (const visplane_t* plane) { INT16 start, end; sector_t *source = plane->sector; - sectorportal_t *target = plane->portalsector; + sectorportal_t *secportal = plane->portalsector; if (TrimVisplaneBounds(plane, &start, &end)) return; @@ -329,18 +327,19 @@ void Portal_AddSectorPortal (const visplane_t* plane) fixed_t refx = source->soundorg.x - viewx; fixed_t refy = source->soundorg.y - viewy; - if (target->viewpoint.angle) + // Rotate the X/Y to match the target angle + if (secportal->target.angle) { fixed_t x = refx, y = refy; - angle_t ang = target->viewpoint.angle >> ANGLETOFINESHIFT; + angle_t ang = secportal->target.angle >> ANGLETOFINESHIFT; refx = FixedMul(x, FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); refy = FixedMul(x, FINESINE(ang)) + FixedMul(y, FINECOSINE(ang)); } - portal->viewx = target->viewpoint.x - refx; - portal->viewy = target->viewpoint.y - refy; - portal->viewz = target->viewpoint.z + viewz; - portal->viewangle = target->viewpoint.angle + viewangle; + portal->viewx = secportal->target.x - refx; + portal->viewy = secportal->target.y - refy; + portal->viewz = secportal->target.z + viewz; + portal->viewangle = secportal->target.angle + viewangle; portal->clipline = -1; } @@ -358,21 +357,17 @@ void Portal_AddSkyboxPortals (void) { boolean added_portal = false; - // skybox portal - if (pl->picnum == skyflatnum) - { - if (cv_skybox.value && skyboxmo[0]) - { - Portal_AddSkybox(pl); - added_portal = true; - } - } - - // floor portal - if (pl->portalsector && pl->portalsector->target && floorportalrender < cv_maxportals.value) + // Render sector portal if recursiveness limit hasn't been reached + if (pl->portalsector && portalrender < cv_maxportals.value) { Portal_AddSectorPortal(pl); - floorportalrender++; + added_portal = true; + } + + // Render skybox portal + if (!added_portal && pl->picnum == skyflatnum && cv_skybox.value && skyboxmo[0]) + { + Portal_AddSkybox(pl); added_portal = true; } diff --git a/src/r_portal.h b/src/r_portal.h index 6e2a6dedb..1e4bbfb12 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -44,7 +44,6 @@ typedef struct portal_s extern portal_t* portal_base; extern portal_t* portal_cap; extern UINT8 portalrender; -extern UINT8 floorportalrender; extern line_t *portalclipline; extern sector_t *portalcullsector; diff --git a/src/r_segs.c b/src/r_segs.c index 9af83f0c7..a8fb635d1 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1787,8 +1787,7 @@ 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 + bothceilingssky = bothfloorssky = false; SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight) SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight) @@ -1797,21 +1796,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; @@ -1909,6 +1893,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(&frontsector->portal_floor, &backsector->portal_floor) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markfloor = true; @@ -1942,6 +1927,7 @@ 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(&frontsector->portal_ceiling, &backsector->portal_ceiling) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markceiling = true; From 5b387ec94ac96180a99d98677d48a5e9cc871954 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 15:04:50 -0300 Subject: [PATCH 05/22] Make linedef type 6 closer to ZDoom's Sector_SetPortal --- src/deh_tables.c | 1 - src/hardware/hw_main.c | 4 +- src/info.c | 27 ------- src/info.h | 1 - src/p_setup.c | 4 +- src/p_spec.c | 165 ++++++++++++++++++++++++++++++++--------- src/p_spec.h | 2 + src/r_bsp.c | 8 +- src/r_defs.h | 24 ++++-- src/r_portal.c | 106 ++++++++++++++++++-------- src/r_segs.c | 2 +- 11 files changed, 236 insertions(+), 108 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 05f61f6e5..34cf7e5ff 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4285,7 +4285,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t // Portal objects "MT_SKYBOX", - "MT_PORTALREFPOINT", // Debris "MT_SPARK", //spark diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2340b9e8b..12a2d54ee 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2352,11 +2352,11 @@ static void HWR_AddLine(seg_t * line) gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true); if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum - && !(gl_backsector->portal_ceiling.exists || gl_frontsector->portal_ceiling.exists)) + && !(P_SectorHasCeilingPortal(gl_backsector) || P_SectorHasCeilingPortal(gl_frontsector))) bothceilingssky = true; if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum - && !(gl_backsector->portal_floor.exists || gl_frontsector->portal_floor.exists)) + && !(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 diff --git a/src/info.c b/src/info.c index f71a2bd1c..11e9c9fe8 100644 --- a/src/info.c +++ b/src/info.c @@ -20759,33 +20759,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_PORTALREFPOINT - 781, // doomednum - S_INVISIBLE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12*FRACUNIT, // radius - 24*FRACUNIT, // height - 0, // display offset - 10, // mass - 0, // damage - sfx_None, // activesound - MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - { // MT_SPARK -1, // doomednum S_SPRK1, // spawnstate diff --git a/src/info.h b/src/info.h index 00822faea..602d12f28 100644 --- a/src/info.h +++ b/src/info.h @@ -5116,7 +5116,6 @@ typedef enum mobj_type // Portal objects MT_SKYBOX, - MT_PORTALREFPOINT, // Debris MT_SPARK, //spark diff --git a/src/p_setup.c b/src/p_setup.c index b9c2b5939..79c919a4f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -980,9 +980,7 @@ static void P_LoadVertices(UINT8 *data) static void InitializeSectorPortal(sectorportal_t *secportal) { - secportal->exists = false; - secportal->target.x = secportal->target.y = secportal->target.z = 0; - secportal->target.angle = 0; + memset(secportal, 0, sizeof(*secportal)); } static void P_InitializeSector(sector_t *ss) diff --git a/src/p_spec.c b/src/p_spec.c index 57653416a..c4c254a82 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6186,22 +6186,54 @@ fixed_t P_GetSectorGravityFactor(sector_t *sec) return sec->gravity; } -boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) +static boolean P_IsSectorPortalValid(sectorportal_t *secportal) { - return !memcmp(a, b, sizeof(sectorportal_t)); + 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]); + default: + return false; + } } -static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, fixed_t default_z, INT32 viewpoint_tag) +boolean P_SectorHasFloorPortal(sector_t *sector) { - secportal->exists = target_sector; - secportal->target.x = target_sector->soundorg.x; - secportal->target.y = target_sector->soundorg.y; - secportal->target.z = default_z; - secportal->target.angle = 0; + return P_IsSectorPortalValid(§or->portal_floor); +} - if (viewpoint_tag <= 0) - return; +boolean P_SectorHasCeilingPortal(sector_t *sector) +{ + return P_IsSectorPortalValid(§or->portal_ceiling); +} +boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) +{ + 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 *GetSectorPortalObject(INT32 tag) +{ for (thinker_t *th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) @@ -6209,18 +6241,14 @@ static void SetSectorPortal(sectorportal_t *secportal, sector_t *target_sector, mobj_t *mo = (mobj_t *)th; - if (mo->type != MT_PORTALREFPOINT || mo->spawnpoint == NULL) + if (mo->spawnpoint == NULL) continue; - if (!Tag_Find(&mo->spawnpoint->tags, viewpoint_tag)) - continue; - - secportal->target.x = mo->x; - secportal->target.y = mo->y; - secportal->target.z = mo->z; - secportal->target.angle = mo->angle; - return; + if (Tag_Find(&mo->spawnpoint->tags, tag)) + return mo; } + + return NULL; } /** After the map has loaded, scans for specials that spawn 3Dfloors and @@ -6390,26 +6418,97 @@ void P_SpawnSpecials(boolean fromnetsave) case 6: // Sector portal { - INT32 s1, s2; - TAG_ITER_SECTORS(lines[i].args[0], s1) // Target sector tag + 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 { - TAG_ITER_SECTORS(lines[i].args[1], s2) // Sector tag to make a portal to + floor = plane_type == TMP_FLOOR; + ceiling = plane_type == TMP_CEILING; + } + + INT32 s1 = -1; + + TAG_ITER_SECTORS(target_sector_tag, s1) // Target sector tag + { + sectorportal_t *floorportal = §ors[s1].portal_floor; + sectorportal_t *ceilportal = §ors[s1].portal_ceiling; + + // Line portal + if (portal_type == 0) { - sector_t *target_sector = §ors[s2]; - boolean floor, ceiling; - - if (lines[i].args[2] == TMP_BOTH) - floor = ceiling = true; - else + INT32 linenum = -1; + TAG_ITER_LINES(misc, linenum) { - floor = lines[i].args[2] == TMP_FLOOR; - ceiling = lines[i].args[2] == TMP_CEILING; + if (lines[linenum].special == 6 + && 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) + { + floorportal->type = SECPORTAL_LINE; + floorportal->line.start = &lines[i]; + floorportal->line.dest = &lines[linenum]; + } + if (ceiling) + { + ceilportal->type = SECPORTAL_LINE; + ceilportal->line.start = &lines[i]; + ceilportal->line.dest = &lines[linenum]; + } + } } - + } + // Skybox portal + else if (portal_type == 2) + { if (floor) - SetSectorPortal(§ors[s1].portal_floor, target_sector, target_sector->ceilingheight, lines[i].args[3]); + floorportal->type = SECPORTAL_SKYBOX; if (ceiling) - SetSectorPortal(§ors[s1].portal_ceiling, target_sector, target_sector->floorheight, lines[i].args[3]); + ceilportal->type = SECPORTAL_SKYBOX; + } + // Plane portal + else if (portal_type == 7) + { + INT32 s2 = -1; + TAG_ITER_SECTORS(misc, s2) // Sector tag to make a portal to + { + sector_t *target_sector = §ors[s2]; + if (floor) + { + floorportal->type = SECPORTAL_CEILING; + floorportal->sector = target_sector; + } + if (ceiling) + { + ceilportal->type = SECPORTAL_FLOOR; + ceilportal->sector = target_sector; + } + } + } + // Use mobj as viewpoint + else if (portal_type == 8) + { + mobj_t *mobj = GetSectorPortalObject(misc); + if (!mobj) + break; + if (floor) + { + floorportal->type = SECPORTAL_OBJECT; + floorportal->mobj = mobj; + } + if (ceiling) + { + ceilportal->type = SECPORTAL_OBJECT; + ceilportal->mobj = mobj; + } } } break; diff --git a/src/p_spec.h b/src/p_spec.h index 71c9dcf3a..63ae8b504 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -521,6 +521,8 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); +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); diff --git a/src/r_bsp.c b/src/r_bsp.c index 70f08e127..f902f2a83 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -488,12 +488,12 @@ static void R_AddLine(seg_t *line) // 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 - && !(backsector->portal_ceiling.exists || frontsector->portal_ceiling.exists)) + && !(P_SectorHasCeilingPortal(backsector) || P_SectorHasCeilingPortal(frontsector))) bothceilingssky = true; // likewise, but for floors and upper textures if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum - && !(backsector->portal_floor.exists || frontsector->portal_floor.exists)) + && !(P_SectorHasFloorPortal(backsector) || P_SectorHasFloorPortal(frontsector))) bothfloorssky = true; if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then @@ -918,7 +918,7 @@ static void R_Subsector(size_t num) || (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, frontsector->f_slope, frontsector->portal_floor.exists ? &frontsector->portal_floor : NULL); + frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope, P_SectorHasFloorPortal(frontsector) ? &frontsector->portal_floor : NULL); } else floorplane = NULL; @@ -929,7 +929,7 @@ static void R_Subsector(size_t num) { ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, frontsector->c_slope, frontsector->portal_ceiling.exists ? &frontsector->portal_ceiling : NULL); + ceilingcolormap, NULL, NULL, frontsector->c_slope, P_SectorHasCeilingPortal(frontsector) ? &frontsector->portal_ceiling : NULL); } else ceilingplane = NULL; diff --git a/src/r_defs.h b/src/r_defs.h index d435f69ab..2e58a1bb8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -208,13 +208,27 @@ typedef enum BT_STRONG, } busttype_e; +typedef enum +{ + SECPORTAL_NONE, + SECPORTAL_LINE, + SECPORTAL_OBJECT, + SECPORTAL_SKYBOX, + SECPORTAL_FLOOR, + SECPORTAL_CEILING, +} secportaltype_e; + typedef struct sectorportal_s { - boolean exists; - struct { - fixed_t x, y, z; - angle_t angle; - } target; + secportaltype_e type; + union { + struct { + struct line_s *start; + struct line_s *dest; + } line; + struct sector_s *sector; + struct mobj_s *mobj; + }; } sectorportal_t; typedef struct ffloor_s diff --git a/src/r_portal.c b/src/r_portal.c index 136eb4fac..b6a430b67 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -141,30 +141,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; @@ -182,6 +169,26 @@ 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; @@ -314,9 +321,17 @@ void Portal_AddSkybox (const visplane_t* plane) void Portal_AddSectorPortal (const visplane_t* plane) { INT16 start, end; - sector_t *source = plane->sector; + fixed_t x, y, z, angle; sectorportal_t *secportal = plane->portalsector; + if (secportal->type == SECPORTAL_NONE) + return; + else if (secportal->type == SECPORTAL_SKYBOX) + { + Portal_AddSkybox(plane); + return; + } + if (TrimVisplaneBounds(plane, &start, &end)) return; @@ -324,24 +339,53 @@ void Portal_AddSectorPortal (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - fixed_t refx = source->soundorg.x - viewx; - fixed_t refy = source->soundorg.y - viewy; + portal->clipline = -1; - // Rotate the X/Y to match the target angle - if (secportal->target.angle) + switch (secportal->type) { - fixed_t x = refx, y = refy; - angle_t ang = secportal->target.angle >> ANGLETOFINESHIFT; - refx = FixedMul(x, FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); - refy = FixedMul(x, FINESINE(ang)) + FixedMul(y, FINECOSINE(ang)); + 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 = secportal->sector->floorheight; + angle = 0; + break; + case SECPORTAL_CEILING: + x = secportal->sector->soundorg.x; + y = secportal->sector->soundorg.y; + z = secportal->sector->ceilingheight; + angle = 0; + break; + default: + return; } - portal->viewx = secportal->target.x - refx; - portal->viewy = secportal->target.y - refy; - portal->viewz = secportal->target.z + viewz; - portal->viewangle = secportal->target.angle + viewangle; + fixed_t refx = plane->sector->soundorg.x - viewx; + fixed_t refy = plane->sector->soundorg.y - viewy; - portal->clipline = -1; + // 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 portals for the currently existing sky visplanes. diff --git a/src/r_segs.c b/src/r_segs.c index a8fb635d1..81fca64e1 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1930,7 +1930,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) || !P_CompareSectorPortals(&frontsector->portal_ceiling, &backsector->portal_ceiling) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { - markceiling = true; + markceiling = true; } else { From 395e9bdd20934fed7303ea60c86d6bdc7d1d0de9 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 15:29:16 -0300 Subject: [PATCH 06/22] Implement sector portal copying --- src/p_spec.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index c4c254a82..af1a04434 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6232,7 +6232,7 @@ boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) } } -static mobj_t *GetSectorPortalObject(INT32 tag) +static mobj_t *P_GetMobjByTag(INT32 tag) { for (thinker_t *th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { @@ -6251,6 +6251,27 @@ static mobj_t *GetSectorPortalObject(INT32 tag) return NULL; } +static void P_CopySectorPortal(sectorportal_t *dest, sectorportal_t *src) +{ + if (src->type == SECPORTAL_NONE) + return; + + memcpy(dest, src, sizeof(sectorportal_t)); +} + +static void P_DoPortalCopyFromLine(sectorportal_t *floorportal, sectorportal_t *ceilportal, int tag) +{ + INT32 secnum = -1; + TAG_ITER_SECTORS(tag, secnum) + { + sector_t *src_sector = §ors[secnum]; + if (floorportal) + P_CopySectorPortal(floorportal, &src_sector->portal_floor); + if (ceilportal) + P_CopySectorPortal(ceilportal, &src_sector->portal_ceiling); + } +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6496,7 +6517,7 @@ void P_SpawnSpecials(boolean fromnetsave) // Use mobj as viewpoint else if (portal_type == 8) { - mobj_t *mobj = GetSectorPortalObject(misc); + mobj_t *mobj = P_GetMobjByTag(misc); if (!mobj) break; if (floor) @@ -7289,10 +7310,6 @@ void P_SpawnSpecials(boolean fromnetsave) } } - - - - // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) @@ -7321,6 +7338,48 @@ void P_SpawnSpecials(boolean fromnetsave) } } + // Copy portals + for (i = 0; i < numlines; i++) + { + if (lines[i].special != 6) + continue; + + int portal_type = lines[i].args[1]; + if (portal_type != 1) + continue; + + int target_sector_tag = lines[i].args[0]; + int plane_type = lines[i].args[2]; + int tag_to_copy = 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; + } + + if (target_sector_tag == 0) + { + sectorportal_t *floorportal = floor ? &lines[i].frontsector->portal_floor : NULL; + sectorportal_t *ceilportal = ceiling ? &lines[i].frontsector->portal_ceiling : NULL; + P_DoPortalCopyFromLine(floorportal, ceilportal, tag_to_copy); + } + else + { + INT32 s1 = -1; + TAG_ITER_SECTORS(target_sector_tag, s1) + { + sectorportal_t *floorportal = floor ? §ors[s1].portal_floor : NULL; + sectorportal_t *ceilportal = ceiling ? §ors[s1].portal_ceiling : NULL; + P_DoPortalCopyFromLine(floorportal, ceilportal, tag_to_copy); + } + } + break; + } + if (!fromnetsave) P_RunLevelLoadExecutors(); } From e230d38aad68eac9ce69e5dac211fa747e5d7751 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 15:46:48 -0300 Subject: [PATCH 07/22] Ensure sector portals are rendered when they would otherwise be missed --- src/p_spec.c | 11 ++++++++++- src/p_spec.h | 1 + src/r_bsp.c | 8 +++++++- src/r_plane.c | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index af1a04434..734bada68 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6203,6 +6203,11 @@ static boolean P_IsSectorPortalValid(sectorportal_t *secportal) } } +boolean P_SectorHasPortal(sector_t *sector) +{ + return P_SectorHasFloorPortal(sector) || P_SectorHasCeilingPortal(sector); +} + boolean P_SectorHasFloorPortal(sector_t *sector) { return P_IsSectorPortalValid(§or->portal_floor); @@ -6215,7 +6220,11 @@ boolean P_SectorHasCeilingPortal(sector_t *sector) boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) { - if (a->type != b->type) + if (a == NULL && b == NULL) + return true; + else if (!a || !b) + return false; + else if (a->type != b->type) return false; switch (a->type) diff --git a/src/p_spec.h b/src/p_spec.h index 63ae8b504..0c4ce4f32 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -521,6 +521,7 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); +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); diff --git a/src/r_bsp.c b/src/r_bsp.c index f902f2a83..6f115a923 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -357,6 +357,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 @@ -578,7 +583,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; @@ -915,6 +919,7 @@ static void R_Subsector(size_t num) 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, frontsector->floorheight, frontsector->floorpic, floorlightlevel, @@ -925,6 +930,7 @@ static void R_Subsector(size_t num) 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, frontsector->ceilingheight, frontsector->ceilingpic, diff --git a/src/r_plane.c b/src/r_plane.c index d9051ae05..4695034bd 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -451,7 +451,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li && check->plangle == plangle && check->slope == slope && check->polyobj == polyobj - && check->portalsector == portalsector) + && P_CompareSectorPortals(check->portalsector, portalsector)) { return check; } From 50506254e8ec12664ad64a141c7f6fe33faa815b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 16:31:03 -0300 Subject: [PATCH 08/22] Support plane type 3 in the "copy portal" line special SRB2 doesn't implement sector portals the way ZDoom does, but this ensures plane type 3 acts the same as plane type 2. --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 734bada68..ccd72e594 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7362,7 +7362,7 @@ void P_SpawnSpecials(boolean fromnetsave) int tag_to_copy = lines[i].args[3]; boolean floor, ceiling; - if (plane_type == TMP_BOTH) + if (plane_type == TMP_BOTH || plane_type == 3) floor = ceiling = true; else { From 74ea880ca046e6a9b945e1cc7ce64fea590ea5e7 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 23 Aug 2023 17:49:29 -0300 Subject: [PATCH 09/22] Refactor --- src/p_setup.c | 10 ++-- src/p_spec.c | 136 +++++++++++++++++++++++++++++++++++-------------- src/p_spec.h | 10 ++++ src/r_bsp.c | 4 +- src/r_defs.h | 7 ++- src/r_portal.c | 7 +-- src/r_segs.c | 4 +- 7 files changed, 120 insertions(+), 58 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 79c919a4f..565a44eae 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -978,11 +978,6 @@ static void P_LoadVertices(UINT8 *data) } } -static void InitializeSectorPortal(sectorportal_t *secportal) -{ - memset(secportal, 0, sizeof(*secportal)); -} - static void P_InitializeSector(sector_t *ss) { memset(&ss->soundorg, 0, sizeof(ss->soundorg)); @@ -996,8 +991,8 @@ static void P_InitializeSector(sector_t *ss) ss->lightingdata = NULL; ss->fadecolormapdata = NULL; - InitializeSectorPortal(&ss->portal_floor); - InitializeSectorPortal(&ss->portal_ceiling); + ss->portal_floor = UINT32_MAX; + ss->portal_ceiling = UINT32_MAX; ss->heightsec = -1; ss->camsec = -1; @@ -7827,6 +7822,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_InitThinkers(); R_InitMobjInterpolators(); P_InitCachedActions(); + P_InitSectorPortals(); // internal game map maplumpname = G_BuildMapName(gamemap); diff --git a/src/p_spec.c b/src/p_spec.c index ccd72e594..0c798b976 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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 @@ -6186,8 +6190,33 @@ 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); + } + + return (UINT32)i; +} + static boolean P_IsSectorPortalValid(sectorportal_t *secportal) { + if (secportal == NULL) + return false; + switch (secportal->type) { case SECPORTAL_LINE: @@ -6208,14 +6237,32 @@ 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(§or->portal_floor); + return P_IsSectorPortalValid(P_SectorGetFloorPortal(sector)); } boolean P_SectorHasCeilingPortal(sector_t *sector) { - return P_IsSectorPortalValid(§or->portal_ceiling); + return P_IsSectorPortalValid(P_SectorGetCeilingPortal(sector)); } boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) @@ -6260,27 +6307,43 @@ static mobj_t *P_GetMobjByTag(INT32 tag) return NULL; } -static void P_CopySectorPortal(sectorportal_t *dest, sectorportal_t *src) -{ - if (src->type == SECPORTAL_NONE) - return; - - memcpy(dest, src, sizeof(sectorportal_t)); -} - -static void P_DoPortalCopyFromLine(sectorportal_t *floorportal, sectorportal_t *ceilportal, int tag) +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 = §ors[secnum]; - if (floorportal) - P_CopySectorPortal(floorportal, &src_sector->portal_floor); - if (ceilportal) - P_CopySectorPortal(ceilportal, &src_sector->portal_ceiling); + 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_SectorGetFloorPortalOrCreate(sector_t *sector) +{ + sectorportal_t *secportal = P_SectorGetFloorPortal(sector); + if (secportal == NULL) + { + sector->portal_floor = P_NewSectorPortal(); + return &secportals[sector->portal_floor]; + } + + return secportal; +} + +static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector) +{ + sectorportal_t *secportal = P_SectorGetCeilingPortal(sector); + if (secportal == NULL) + { + sector->portal_ceiling = P_NewSectorPortal(); + return &secportals[sector->portal_ceiling]; + } + + return secportal; +} + /** After the map has loaded, scans for specials that spawn 3Dfloors and * thinkers. * @@ -6466,8 +6529,7 @@ void P_SpawnSpecials(boolean fromnetsave) TAG_ITER_SECTORS(target_sector_tag, s1) // Target sector tag { - sectorportal_t *floorportal = §ors[s1].portal_floor; - sectorportal_t *ceilportal = §ors[s1].portal_ceiling; + sector_t *target_sector = §ors[s1]; // Line portal if (portal_type == 0) @@ -6483,12 +6545,14 @@ void P_SpawnSpecials(boolean fromnetsave) { if (floor) { + sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector); floorportal->type = SECPORTAL_LINE; floorportal->line.start = &lines[i]; floorportal->line.dest = &lines[linenum]; } if (ceiling) { + sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector); ceilportal->type = SECPORTAL_LINE; ceilportal->line.start = &lines[i]; ceilportal->line.dest = &lines[linenum]; @@ -6500,9 +6564,15 @@ void P_SpawnSpecials(boolean fromnetsave) else if (portal_type == 2) { if (floor) + { + sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector); floorportal->type = SECPORTAL_SKYBOX; + } if (ceiling) + { + sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector); ceilportal->type = SECPORTAL_SKYBOX; + } } // Plane portal else if (portal_type == 7) @@ -6510,16 +6580,18 @@ void P_SpawnSpecials(boolean fromnetsave) INT32 s2 = -1; TAG_ITER_SECTORS(misc, s2) // Sector tag to make a portal to { - sector_t *target_sector = §ors[s2]; + sector_t *view_sector = §ors[s2]; if (floor) { + sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector); floorportal->type = SECPORTAL_CEILING; - floorportal->sector = target_sector; + floorportal->sector = view_sector; } if (ceiling) { + sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector); ceilportal->type = SECPORTAL_FLOOR; - ceilportal->sector = target_sector; + ceilportal->sector = view_sector; } } } @@ -6531,11 +6603,13 @@ void P_SpawnSpecials(boolean fromnetsave) break; if (floor) { + sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector); floorportal->type = SECPORTAL_OBJECT; floorportal->mobj = mobj; } if (ceiling) { + sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector); ceilportal->type = SECPORTAL_OBJECT; ceilportal->mobj = mobj; } @@ -7361,30 +7435,16 @@ void P_SpawnSpecials(boolean fromnetsave) int plane_type = lines[i].args[2]; int tag_to_copy = lines[i].args[3]; - boolean floor, ceiling; - if (plane_type == TMP_BOTH || plane_type == 3) - floor = ceiling = true; - else - { - floor = plane_type == TMP_FLOOR; - ceiling = plane_type == TMP_CEILING; - } + if (plane_type == 3) + plane_type = TMP_BOTH; if (target_sector_tag == 0) - { - sectorportal_t *floorportal = floor ? &lines[i].frontsector->portal_floor : NULL; - sectorportal_t *ceilportal = ceiling ? &lines[i].frontsector->portal_ceiling : NULL; - P_DoPortalCopyFromLine(floorportal, ceilportal, tag_to_copy); - } + P_DoPortalCopyFromLine(lines[i].frontsector, plane_type, tag_to_copy); else { INT32 s1 = -1; TAG_ITER_SECTORS(target_sector_tag, s1) - { - sectorportal_t *floorportal = floor ? §ors[s1].portal_floor : NULL; - sectorportal_t *ceilportal = ceiling ? §ors[s1].portal_ceiling : NULL; - P_DoPortalCopyFromLine(floorportal, ceilportal, tag_to_copy); - } + P_DoPortalCopyFromLine(§ors[s1], plane_type, tag_to_copy); } break; } diff --git a/src/p_spec.h b/src/p_spec.h index 0c4ce4f32..bb995a97a 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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 @@ -521,6 +525,12 @@ 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); + +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); diff --git a/src/r_bsp.c b/src/r_bsp.c index 6f115a923..8ab5998c4 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -923,7 +923,7 @@ static void R_Subsector(size_t num) || (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, frontsector->f_slope, P_SectorHasFloorPortal(frontsector) ? &frontsector->portal_floor : NULL); + frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope, P_SectorGetFloorPortal(frontsector)); } else floorplane = NULL; @@ -935,7 +935,7 @@ static void R_Subsector(size_t num) { ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, frontsector->c_slope, P_SectorHasCeilingPortal(frontsector) ? &frontsector->portal_ceiling : NULL); + ceilingcolormap, NULL, NULL, frontsector->c_slope, P_SectorGetCeilingPortal(frontsector)); } else ceilingplane = NULL; diff --git a/src/r_defs.h b/src/r_defs.h index 2e58a1bb8..a8addfe0b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -210,12 +210,11 @@ typedef enum typedef enum { - SECPORTAL_NONE, SECPORTAL_LINE, SECPORTAL_OBJECT, SECPORTAL_SKYBOX, SECPORTAL_FLOOR, - SECPORTAL_CEILING, + SECPORTAL_CEILING } secportaltype_e; typedef struct sectorportal_s @@ -519,8 +518,8 @@ typedef struct sector_s extracolormap_t *spawn_extra_colormap; // portals - sectorportal_t portal_floor; - sectorportal_t portal_ceiling; + UINT32 portal_floor; + UINT32 portal_ceiling; } sector_t; // diff --git a/src/r_portal.c b/src/r_portal.c index b6a430b67..c485aa033 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -315,8 +315,6 @@ void Portal_AddSkybox (const visplane_t* plane) } /** Creates a sector portal out of a visplane. - * - * Mostly the same as Portal_AddSkybox. */ void Portal_AddSectorPortal (const visplane_t* plane) { @@ -324,9 +322,8 @@ void Portal_AddSectorPortal (const visplane_t* plane) fixed_t x, y, z, angle; sectorportal_t *secportal = plane->portalsector; - if (secportal->type == SECPORTAL_NONE) - return; - else if (secportal->type == SECPORTAL_SKYBOX) + // Shortcut + if (secportal->type == SECPORTAL_SKYBOX) { Portal_AddSkybox(plane); return; diff --git a/src/r_segs.c b/src/r_segs.c index 81fca64e1..2a86cc41a 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1893,7 +1893,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(&frontsector->portal_floor, &backsector->portal_floor) + || !P_CompareSectorPortals(P_SectorGetFloorPortal(frontsector), P_SectorGetFloorPortal(backsector)) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markfloor = true; @@ -1927,7 +1927,7 @@ 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(&frontsector->portal_ceiling, &backsector->portal_ceiling) + || !P_CompareSectorPortals(P_SectorGetCeilingPortal(frontsector), P_SectorGetCeilingPortal(backsector)) || (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags))) { markceiling = true; From 6d812b4a4343c134669bfc527a73645055334c6b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 24 Aug 2023 00:51:52 -0300 Subject: [PATCH 10/22] Implement Eternity Engine's plane portal and horizon portal types --- src/hardware/hw_main.c | 5 +- src/p_spec.c | 30 +++++++-- src/p_spec.h | 15 +++++ src/r_bsp.c | 142 ++++++++++++++++++++++++++++++----------- src/r_bsp.h | 3 + src/r_defs.h | 12 ++-- src/r_main.c | 15 ++++- src/r_portal.c | 23 ++++++- src/r_portal.h | 4 ++ src/r_segs.c | 6 +- 10 files changed, 194 insertions(+), 61 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 12a2d54ee..30f9c4073 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -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 diff --git a/src/p_spec.c b/src/p_spec.c index 0c798b976..3334b184b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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 = §ors[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]; diff --git a/src/p_spec.h b/src/p_spec.h index bb995a97a..6ceec1cae 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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. diff --git a/src/r_bsp.c b/src/r_bsp.c index 8ab5998c4..0486cd699 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -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 = §ors[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 = §ors[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; +} diff --git a/src/r_bsp.h b/src/r_bsp.h index f36f7e64d..3effb916a 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -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); diff --git a/src/r_defs.h b/src/r_defs.h index a8addfe0b..dee15975f 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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 diff --git a/src/r_main.c b/src/r_main.c index 8a0575d66..c73039c2a 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -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); diff --git a/src/r_portal.c b/src/r_portal.c index c485aa033..e4af45f9f 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -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: diff --git a/src/r_portal.h b/src/r_portal.h index 1e4bbfb12..1a8291f3c 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -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. */ diff --git a/src/r_segs.c b/src/r_segs.c index 2a86cc41a..c3c3cc334 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -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); From 563233a55ffcd9466f5da6908ff2b5d7845edf4c Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 24 Aug 2023 01:09:46 -0300 Subject: [PATCH 11/22] Add editor definition for linedef type 6 --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 28 ++++++++++++++++++++ extras/conf/udb/Includes/SRB222_misc.cfg | 11 ++++++++ src/p_spec.h | 18 ++++++------- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 680778623..9f3e41d39 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -10,6 +10,34 @@ udmf prefix = "(0)"; } + 6 + { + title = "Sector Portal"; + prefix = "(6)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Type"; + type = 11; + enum = "sectorportal"; + } + arg2 + { + title = "Affected planes"; + type = 11; + enum = "floorceiling"; + } + arg3 + { + title = "Miscellaneous"; + type = 0; + } + } + 7 { title = "Sector Flat Alignment"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index e274fece6..18bb0aec7 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -453,6 +453,17 @@ enums 3 = "Reverse subtract"; 4 = "Modulate"; } + + sectorportal + { + 0 = "Normal"; + 1 = "Copied"; + 2 = "Skybox"; + 3 = "Plane"; + 4 = "Horizon"; + 7 = "Sector"; + 8 = "Object"; + } } //Default things filters diff --git a/src/p_spec.h b/src/p_spec.h index 6ceec1cae..87f9951a6 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -478,17 +478,17 @@ typedef enum typedef enum { - TMSECPORTAL_NORMAL, - TMSECPORTAL_COPIED, - TMSECPORTAL_SKYBOX, - TMSECPORTAL_PLANE, - TMSECPORTAL_HORIZON, + TMSECPORTAL_NORMAL = 0, + TMSECPORTAL_COPIED = 1, + TMSECPORTAL_SKYBOX = 2, + TMSECPORTAL_PLANE = 3, + TMSECPORTAL_HORIZON = 4, // The two portal types below are unimplemented - TMSECPORTAL_COPY_PORTAL_TO_LINE, - TMSECPORTAL_INTERACTIVE, + TMSECPORTAL_COPY_PORTAL_TO_LINE = 5, + TMSECPORTAL_INTERACTIVE = 6, // The two portal types below are new to SRB2 - TMSECPORTAL_SECTOR, - TMSECPORTAL_OBJECT + TMSECPORTAL_SECTOR = 7, + TMSECPORTAL_OBJECT = 8 } textmapsecportaltype_t; // GETSECSPECIAL (specialval, section) From 6303e37fbe88fcfec9243c1ad572c17c4a41ab77 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 24 Aug 2023 01:19:58 -0300 Subject: [PATCH 12/22] Use P_SetTarget here --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 3334b184b..e76968b8a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6625,13 +6625,13 @@ void P_SpawnSpecials(boolean fromnetsave) { sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(target_sector); floorportal->type = SECPORTAL_OBJECT; - floorportal->mobj = mobj; + P_SetTarget(&floorportal->mobj, mobj); } if (ceiling) { sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(target_sector); ceilportal->type = SECPORTAL_OBJECT; - ceilportal->mobj = mobj; + P_SetTarget(&ceilportal->mobj, mobj); } } } From ff5d53e54d309aef952543ab1c1d2b0e593b3d74 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 24 Aug 2023 16:04:31 -0300 Subject: [PATCH 13/22] Serialize sector portals --- src/hardware/hw_main.c | 52 +--------------- src/p_saveg.c | 131 ++++++++++++++++++++++++++++++++++------- src/p_spec.c | 4 ++ src/r_bsp.c | 115 ++++++++++++++++++------------------ src/r_bsp.h | 1 + src/r_defs.h | 3 +- src/r_portal.c | 2 +- 7 files changed, 178 insertions(+), 130 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 30f9c4073..5b8f1178d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2927,64 +2927,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 = §ors[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; diff --git a/src/p_saveg.c b/src/p_saveg.c index faecd1377..b3ac59e81 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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,20 +852,22 @@ 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 -#define SD_DAMAGETYPE 0x01 -#define SD_TRIGGERTAG 0x02 -#define SD_TRIGGERER 0x04 -#define SD_GRAVITY 0x08 +#define SD_DAMAGETYPE 0x01 +#define SD_TRIGGERTAG 0x02 +#define SD_TRIGGERER 0x04 +#define SD_GRAVITY 0x08 +#define SD_FLOORPORTAL 0x10 +#define SD_CEILPORTAL 0x20 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -1064,6 +1065,10 @@ static void ArchiveSectors(void) diff4 |= SD_TRIGGERER; if (ss->gravity != spawnss->gravity) diff4 |= SD_GRAVITY; + if (ss->portal_floor != spawnss->portal_floor) + diff4 |= SD_FLOORPORTAL; + if (ss->portal_ceiling != spawnss->portal_ceiling) + diff4 |= SD_CEILPORTAL; if (ss->ffloors && CheckFFloorDiff(ss)) diff |= SD_FFLOORS; @@ -1145,6 +1150,10 @@ static void ArchiveSectors(void) WRITEUINT8(save_p, ss->triggerer); if (diff4 & SD_GRAVITY) WRITEFIXED(save_p, ss->gravity); + if (diff4 & SD_FLOORPORTAL) + WRITEUINT32(save_p, ss->portal_floor); + if (diff4 & SD_CEILPORTAL) + WRITEUINT32(save_p, ss->portal_ceiling); if (diff & SD_FFLOORS) ArchiveFFloors(ss); } @@ -1265,6 +1274,10 @@ static void UnArchiveSectors(void) sectors[i].triggerer = READUINT8(save_p); if (diff4 & SD_GRAVITY) sectors[i].gravity = READFIXED(save_p); + if (diff4 & SD_FLOORPORTAL) + sectors[i].portal_floor = READUINT32(save_p); + if (diff4 & SD_CEILPORTAL) + sectors[i].portal_ceiling = READUINT32(save_p); if (diff & SD_FFLOORS) UnArchiveFFloors(§ors[i]); @@ -4735,6 +4748,82 @@ 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); + + 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); + + 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; @@ -4821,6 +4910,7 @@ void P_SaveNetGame(boolean resending) P_NetArchiveSpecials(); P_NetArchiveColormaps(); P_NetArchiveWaypoints(); + P_NetArchiveSectorPortals(); } LUA_Archive(); @@ -4861,6 +4951,7 @@ boolean P_LoadNetGame(boolean reloading) P_NetUnArchiveSpecials(); P_NetUnArchiveColormaps(); P_NetUnArchiveWaypoints(); + P_NetUnArchiveSectorPortals(); P_RelinkPointers(); P_FinishMobjs(); } diff --git a/src/p_spec.c b/src/p_spec.c index e76968b8a..d6b7b18b6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6209,6 +6209,8 @@ UINT32 P_NewSectorPortal(void) secportals = Z_Realloc(secportals, secportalcapacity * sizeof(sectorportal_t), PU_LEVEL, NULL); } + secportals[i].type = SECPORTAL_NONE; + return (UINT32)i; } @@ -6536,11 +6538,13 @@ void P_SpawnSpecials(boolean fromnetsave) { sectorportal_t *floorportal = P_SectorGetFloorPortalOrCreate(lines[i].frontsector); floorportal->type = type; + floorportal->sector = lines[i].frontsector; } if (ceiling) { sectorportal_t *ceilportal = P_SectorGetCeilingPortalOrCreate(lines[i].frontsector); ceilportal->type = type; + ceilportal->sector = lines[i].frontsector; } break; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 0486cd699..91b4fdbc0 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -847,51 +847,6 @@ 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 = §ors[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; @@ -1098,18 +1053,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; @@ -1120,7 +1075,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++; @@ -1128,6 +1082,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 = §ors[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 // diff --git a/src/r_bsp.h b/src/r_bsp.h index 3effb916a..44ddd0b1b 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -57,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 diff --git a/src/r_defs.h b/src/r_defs.h index dee15975f..b6ea8d6e5 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -216,7 +216,8 @@ typedef enum 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_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 diff --git a/src/r_portal.c b/src/r_portal.c index e4af45f9f..327821b9d 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -373,7 +373,7 @@ void Portal_AddSectorPortal (const visplane_t* plane) case SECPORTAL_PLANE: case SECPORTAL_HORIZON: portal->is_horizon = true; - portal->horizon_sector = plane->sector; + portal->horizon_sector = secportal->sector; x = plane->sector->soundorg.x; y = plane->sector->soundorg.y; if (secportal->type == SECPORTAL_PLANE) From 9335ee3031599f6d4b4835fa6d29ad8821ccbbb3 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 24 Aug 2023 17:36:38 -0300 Subject: [PATCH 14/22] Implement "copy portal to line" sector portal type --- extras/conf/udb/Includes/SRB222_misc.cfg | 1 + src/hardware/hw_main.c | 4 +- src/p_map.c | 2 +- src/p_saveg.c | 9 +- src/p_setup.c | 1 + src/p_spec.c | 98 ++++++++++++------ src/p_spec.h | 5 +- src/r_bsp.c | 11 +- src/r_defs.h | 6 +- src/r_portal.c | 122 ++++++++++++++++------- src/r_portal.h | 1 + 11 files changed, 186 insertions(+), 74 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 18bb0aec7..2fb863921 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -461,6 +461,7 @@ enums 2 = "Skybox"; 3 = "Plane"; 4 = "Horizon"; + 5 = "Transfer to line"; 7 = "Sector"; 8 = "Object"; } diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5b8f1178d..1d5543202 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -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; diff --git a/src/p_map.c b/src/p_map.c index 132a3cf85..b7fcbb2dd 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -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; diff --git a/src/p_saveg.c b/src/p_saveg.c index b3ac59e81..80b111946 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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); } } diff --git a/src/p_setup.c b/src/p_setup.c index 565a44eae..88cd74ed0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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 diff --git a/src/p_spec.c b/src/p_spec.c index d6b7b18b6..e1dd6bcec 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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(§ors[sec], §ors[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 = §ors[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 = §ors[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(§ors[s1], plane_type, tag_to_copy); } - break; } if (!fromnetsave) diff --git a/src/p_spec.h b/src/p_spec.h index 87f9951a6..3bbaba58b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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); diff --git a/src/r_bsp.c b/src/r_bsp.c index 91b4fdbc0..4bb0e290c 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -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) diff --git a/src/r_defs.h b/src/r_defs.h index b6ea8d6e5..865776146 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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 diff --git a/src/r_portal.c b/src/r_portal.c index 327821b9d..f66424ab6 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -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. */ diff --git a/src/r_portal.h b/src/r_portal.h index 1a8291f3c..7e0f63fe1 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -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); From 87d40fc3cc7459cce775e1afd73c355abf047312 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 00:18:20 -0300 Subject: [PATCH 15/22] Use original portal's origin for the viewpoint displacement --- src/p_saveg.c | 4 ++++ src/p_spec.c | 35 ++++++++++++++++++++--------------- src/r_bsp.c | 2 +- src/r_defs.h | 3 +++ src/r_portal.c | 17 ++++++----------- src/r_portal.h | 2 +- 6 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 80b111946..bf6856506 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4766,6 +4766,8 @@ static void P_NetArchiveSectorPortals(void) 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) { @@ -4808,6 +4810,8 @@ static void P_NetUnArchiveSectorPortals(void) 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) { diff --git a/src/p_spec.c b/src/p_spec.c index e1dd6bcec..ed745f1fb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6325,30 +6325,35 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta } } -static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result) +static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result) { - *result = sector->portal_floor; + sectorportal_t *secportal = NULL; - if (*result >= secportalcount) + if (*num >= secportalcount) { - *result = P_NewSectorPortal(); - sector->portal_floor = *result; + *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 &secportals[sector->portal_floor]; + return secportal; +} + +static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result) +{ + return P_SectorGetPortalOrCreate(sector, §or->portal_floor, result); } static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result) { - *result = sector->portal_floor; - - if (*result >= secportalcount) - { - *result = P_NewSectorPortal(); - sector->portal_ceiling = *result; - } - - return &secportals[sector->portal_ceiling]; + return P_SectorGetPortalOrCreate(sector, §or->portal_ceiling, result); } static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag) diff --git a/src/r_bsp.c b/src/r_bsp.c index 4bb0e290c..b845e0d14 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -489,7 +489,7 @@ static void R_AddLine(seg_t *line) { if (portalrender < cv_maxportals.value) { - Portal_AddTransferred(line->linedef-lines, line->linedef->secportal, x1, x2); + Portal_AddTransferred(line->linedef->secportal, x1, x2); goto clipsolid; } } diff --git a/src/r_defs.h b/src/r_defs.h index 865776146..d9bc72d1d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -231,6 +231,9 @@ typedef struct sectorportal_s struct sector_s *sector; struct mobj_s *mobj; }; + struct { + fixed_t x, y; + } origin; } sectorportal_t; typedef struct ffloor_s diff --git a/src/r_portal.c b/src/r_portal.c index f66424ab6..bb40b2c80 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -323,7 +323,7 @@ void Portal_AddSkybox (const visplane_t* plane) Portal_GetViewpointForSkybox(portal); } -static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal, fixed_t origin_x, fixed_t origin_y) +static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal) { fixed_t x, y, z, angle; @@ -368,8 +368,8 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se return; } - fixed_t refx = origin_x - viewx; - fixed_t refy = origin_y - viewy; + 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) @@ -411,12 +411,12 @@ void Portal_AddSectorPortal (const visplane_t* plane) portal->is_horizon = false; portal->horizon_sector = NULL; - Portal_GetViewpointForSecPortal(portal, secportal, plane->sector->soundorg.x, plane->sector->soundorg.y); + Portal_GetViewpointForSecPortal(portal, secportal); } /** Creates a transferred sector portal. */ -void Portal_AddTransferred (const INT32 linenum, UINT32 secportalnum, const INT32 x1, const INT32 x2) +void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) { if (secportalnum >= secportalcount) return; @@ -433,12 +433,7 @@ void Portal_AddTransferred (const INT32 linenum, UINT32 secportalnum, const INT3 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); - } + Portal_GetViewpointForSecPortal(portal, secportal); if (secportal->type == SECPORTAL_LINE) portal->clipline = secportal->line.dest - lines; diff --git a/src/r_portal.h b/src/r_portal.h index 7e0f63fe1..69ecb8d7f 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -58,7 +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_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); From cf1f3103636b5221924c625145c2ddeb02833c27 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 00:47:40 -0300 Subject: [PATCH 16/22] Add sector portals from visplanes while rendering a portal --- src/r_main.c | 7 +++++-- src/r_portal.c | 17 ++++++++++++----- src/r_portal.h | 4 +++- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index c73039c2a..c999b0f5e 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1513,8 +1513,8 @@ void R_RenderPlayerView(player_t *player) R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); - // Add skybox portals caused by sky visplanes. - Portal_AddSkyboxPortals(); + // Add portals caused by visplanes. + Portal_AddPlanePortals(cv_skybox.value); // Portal rendering. Hijacks the BSP traversal. PS_START_TIMING(ps_sw_portaltime); @@ -1559,6 +1559,9 @@ void R_RenderPlayerView(player_t *player) R_RenderBSPNode((INT32)numnodes - 1); } + // Don't add skybox portals while IN a skybox portal, because that'll cause infinite recursion + Portal_AddPlanePortals(!portal->is_skybox); + Mask_Post(&masks[nummasks - 1]); R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); diff --git a/src/r_portal.c b/src/r_portal.c index bb40b2c80..ffa5d1a0d 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -192,6 +192,7 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con Portal_GetViewpointForLine(portal, start, dest); portal->clipline = line2; + portal->is_skybox = false; portal->is_horizon = false; portal->horizon_sector = NULL; @@ -317,6 +318,7 @@ void Portal_AddSkybox (const visplane_t* plane) Portal_ClipVisplane(plane, portal); portal->clipline = -1; + portal->is_skybox = true; portal->is_horizon = false; portal->horizon_sector = NULL; @@ -396,7 +398,8 @@ void Portal_AddSectorPortal (const visplane_t* plane) // Shortcut if (secportal->type == SECPORTAL_SKYBOX) { - Portal_AddSkybox(plane); + if (skyboxmo[0]) + Portal_AddSkybox(plane); return; } @@ -409,6 +412,7 @@ void Portal_AddSectorPortal (const visplane_t* plane) portal->clipline = -1; portal->is_horizon = false; + portal->is_skybox = false; portal->horizon_sector = NULL; Portal_GetViewpointForSecPortal(portal, secportal); @@ -426,7 +430,7 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) return; portal_t* portal = Portal_Add(x1, x2); - + portal->is_skybox = false; portal->is_horizon = false; portal->horizon_sector = NULL; @@ -445,10 +449,10 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) portalline = true; } -/** Creates portals for the currently existing sky visplanes. +/** 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; @@ -456,6 +460,9 @@ void Portal_AddSkyboxPortals (void) { for (pl = visplanes[i]; pl; pl = pl->next) { + if (pl->minx >= pl->maxx) + continue; + boolean added_portal = false; // Render sector portal if recursiveness limit hasn't been reached @@ -466,7 +473,7 @@ void Portal_AddSkyboxPortals (void) } // Render skybox portal - if (!added_portal && pl->picnum == skyflatnum && cv_skybox.value && skyboxmo[0]) + if (!added_portal && pl->picnum == skyflatnum && add_skyboxes && skyboxmo[0]) { Portal_AddSkybox(pl); added_portal = true; diff --git a/src/r_portal.h b/src/r_portal.h index 69ecb8d7f..b3c4b0edc 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -34,6 +34,8 @@ typedef struct portal_s 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. */ @@ -63,5 +65,5 @@ 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 From d7bc644dfeb3dd42465d7d8badca8ed033136701 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 00:57:10 -0300 Subject: [PATCH 17/22] Check for cv_skybox.value if in a portal too --- src/r_main.c | 2 +- src/r_portal.c | 28 +++++++++++++--------------- src/r_portal.h | 2 -- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index c999b0f5e..3d0eafe37 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1560,7 +1560,7 @@ void R_RenderPlayerView(player_t *player) } // Don't add skybox portals while IN a skybox portal, because that'll cause infinite recursion - Portal_AddPlanePortals(!portal->is_skybox); + Portal_AddPlanePortals(cv_skybox.value && !portal->is_skybox); Mask_Post(&masks[nummasks - 1]); diff --git a/src/r_portal.c b/src/r_portal.c index ffa5d1a0d..3e7954ca6 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -305,13 +305,13 @@ static void Portal_GetViewpointForSkybox(portal_t *portal) * Applies the necessary offsets and rotation to give * a depth illusion to the skybox. */ -void Portal_AddSkybox (const visplane_t* plane) +static boolean Portal_AddSkybox (const visplane_t* plane) { INT16 start, end; portal_t* portal; if (TrimVisplaneBounds(plane, &start, &end)) - return; + return false; portal = Portal_Add(start, end); @@ -323,6 +323,8 @@ void Portal_AddSkybox (const visplane_t* plane) portal->horizon_sector = NULL; Portal_GetViewpointForSkybox(portal); + + return true; } static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal) @@ -390,7 +392,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se /** Creates a sector portal out of a visplane. */ -void Portal_AddSectorPortal (const visplane_t* plane) +static boolean Portal_AddSectorPortal (const visplane_t* plane) { INT16 start, end; sectorportal_t *secportal = plane->portalsector; @@ -398,13 +400,13 @@ void Portal_AddSectorPortal (const visplane_t* plane) // Shortcut if (secportal->type == SECPORTAL_SKYBOX) { - if (skyboxmo[0]) - Portal_AddSkybox(plane); - return; + if (cv_skybox.value && skyboxmo[0]) + return Portal_AddSkybox(plane); + return false; } if (TrimVisplaneBounds(plane, &start, &end)) - return; + return false; portal_t* portal = Portal_Add(start, end); @@ -416,6 +418,8 @@ void Portal_AddSectorPortal (const visplane_t* plane) portal->horizon_sector = NULL; Portal_GetViewpointForSecPortal(portal, secportal); + + return true; } /** Creates a transferred sector portal. @@ -467,17 +471,11 @@ void Portal_AddPlanePortals (boolean add_skyboxes) // Render sector portal if recursiveness limit hasn't been reached if (pl->portalsector && portalrender < cv_maxportals.value) - { - Portal_AddSectorPortal(pl); - added_portal = true; - } + added_portal = Portal_AddSectorPortal(pl); // Render skybox portal if (!added_portal && pl->picnum == skyflatnum && add_skyboxes && skyboxmo[0]) - { - Portal_AddSkybox(pl); - added_portal = true; - } + added_portal = Portal_AddSkybox(pl); // don't render this visplane anymore if (added_portal) diff --git a/src/r_portal.h b/src/r_portal.h index b3c4b0edc..2485e45a7 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -58,8 +58,6 @@ 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_AddSectorPortal (const visplane_t* plane); void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_ClipRange (portal_t* portal); From 3505c90d5c68bea63bac4c3cd6bb3836c98a49b8 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 04:28:46 -0300 Subject: [PATCH 18/22] Clarify comment --- src/r_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index 3d0eafe37..a84d1cc40 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1559,7 +1559,7 @@ void R_RenderPlayerView(player_t *player) R_RenderBSPNode((INT32)numnodes - 1); } - // Don't add skybox portals while IN a skybox portal, because that'll cause infinite recursion + // 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]); From 5996c8a5ac1c81ed5f5aab3437052ed8ac5d1394 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 05:02:23 -0300 Subject: [PATCH 19/22] Fix P_GetMobjByTag so that it iterates through mapthings --- src/p_spec.c | 15 +++++---------- src/r_portal.c | 3 ++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index ed745f1fb..0711a155f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6295,17 +6295,12 @@ boolean P_CompareSectorPortals(sectorportal_t *a, sectorportal_t *b) static mobj_t *P_GetMobjByTag(INT32 tag) { - for (thinker_t *th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + INT32 mtnum = -1; + + TAG_ITER_THINGS(tag, mtnum) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mobj_t *mo = (mobj_t *)th; - - if (mo->spawnpoint == NULL) - continue; - - if (Tag_Find(&mo->spawnpoint->tags, tag)) + mobj_t *mo = mapthings[mtnum].mobj; + if (mo) return mo; } diff --git a/src/r_portal.c b/src/r_portal.c index 3e7954ca6..4d042cae3 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -329,7 +329,8 @@ static boolean Portal_AddSkybox (const visplane_t* plane) static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *secportal) { - fixed_t x, y, z, angle; + fixed_t x, y, z; + angle_t angle; switch (secportal->type) { From 2c86f266d307246602d0471616b891a063b4b0bc Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 05:30:12 -0300 Subject: [PATCH 20/22] Update editor definition --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 21 +++++++++++++++----- extras/conf/udb/Includes/SRB222_misc.cfg | 12 ----------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 9f3e41d39..dcc5cf335 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -12,7 +12,7 @@ udmf 6 { - title = "Sector Portal"; + title = "Sector Set Portal"; prefix = "(6)"; arg0 { @@ -21,9 +21,20 @@ udmf } arg1 { - title = "Type"; + title = "Portal type"; type = 11; - enum = "sectorportal"; + 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 same tag"; + 8 = "Link to object with same tag"; + } } arg2 { @@ -33,8 +44,8 @@ udmf } arg3 { - title = "Miscellaneous"; - type = 0; + 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."; } } diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 2fb863921..e274fece6 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -453,18 +453,6 @@ enums 3 = "Reverse subtract"; 4 = "Modulate"; } - - sectorportal - { - 0 = "Normal"; - 1 = "Copied"; - 2 = "Skybox"; - 3 = "Plane"; - 4 = "Horizon"; - 5 = "Transfer to line"; - 7 = "Sector"; - 8 = "Object"; - } } //Default things filters From d6e13fe27a1359096b54f6f108ecf19a58e0eb7d Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 25 Aug 2023 05:31:08 -0300 Subject: [PATCH 21/22] "same tag" -> "second tag" --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index dcc5cf335..152cafe21 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -32,8 +32,8 @@ udmf 4 = "Horizon portal"; 5 = "Copy portal to line"; 6 = "Interactive portal (unimplemented)"; - 7 = "Link to sector with same tag"; - 8 = "Link to object with same tag"; + 7 = "Link to sector with second tag"; + 8 = "Link to object with second tag"; } } arg2 From 5257b498eaa25c1579832f0f1980721e55f4c103 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 3 Dec 2023 01:21:39 -0300 Subject: [PATCH 22/22] Remove useless check --- src/r_plane.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/r_plane.c b/src/r_plane.c index 4695034bd..6714c2a6d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -445,7 +445,6 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li && lightlevel == check->lightlevel && xoff == check->xoffs && yoff == check->yoffs && planecolormap == check->extra_colormap - && !pfloor && !check->ffloor && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewangle == viewangle && check->plangle == plangle