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);