diff --git a/doc/specs/udmf_srb2.txt b/doc/specs/udmf_srb2.txt index d6d71a0d5f7217482422799a4e521714e604b204..eaa3a8a9704439b72569aee0a0c4db956e8d8482 100644 --- a/doc/specs/udmf_srb2.txt +++ b/doc/specs/udmf_srb2.txt @@ -1,5 +1,5 @@ =============================================================================== -Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.02.2024 +Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.06.2024 Copyright (c) 2024 Sonic Team Junior uses Universal Doom Map Format Specification v1.1 as a template, @@ -143,6 +143,9 @@ Sonic Robo Blast 2 defines the following standardized fields: offsetx_bottom = <float>; // X offset for lower texture. Default = 0.0. offsety_bottom = <float>; // Y offset for lower texture. Default = 0.0. + light = <integer>; // Light level, relative to 'sector' light level. Default = 0. + lightabsolute = <bool>; // true = 'light' is an absolute value, ignoring 'sector' light level. + comment = <string>; // A comment. Implementors should attach no special // semantic meaning to this field. } diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 90c85cdea40827970a7b44222e9a2f6a5e2668f6..e5cafead431c0d79eaaef734eee008eeab89dd15 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -115,7 +115,7 @@ mapformat_udmf // Enables setting distinct brightness for floor, ceiling, and walls distinctfloorandceilingbrightness = true; - distinctwallbrightness = false; + distinctwallbrightness = true; // Enables setting distinct brightness for upper, middle, and lower sidedef parts distinctsidedefpartbrightness = false; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index 37b01d7dd56eadaeb1eb3ae4759fb74efc79e61f..c37c29ce0def1f471565d7d4494ac7ab833eb054 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -280,18 +280,18 @@ universalfields default = ""; } - //light - //{ - // type = 0; - // default = 0; - //} - // - //lightabsolute - //{ - // type = 3; - // default = false; - //} - // + light + { + type = 0; + default = 0; + } + + lightabsolute + { + type = 3; + default = false; + } + //light_top //{ // type = 0; diff --git a/src/d_main.c b/src/d_main.c index 3a3a0b26a3ee5213ef7bffb7cd881079e20bea22..bad78c53070174e215416ce1fe9ed51b090c84c0 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1535,7 +1535,7 @@ void D_SRB2Main(void) I_Error("Cannot find a map remotely named '%s'\n", word); else { - if (!M_CheckParm("-server")) + if (!(M_CheckParm("-server") || dedicated)) G_SetUsedCheats(true); autostart = true; } diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 87c5f8e328aa8e918d942cf9b1b506a0db9c2111..c70b6dd01f79487b80d3e74f47926da3054ec80a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -309,6 +309,43 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) return (FUINT)finallight; } +static FUINT HWR_SideLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light + + ((side->lightabsolute) ? 0 : base_lightlevel); +} + +/* TODO: implement per-texture lighting +static FUINT HWR_TopLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_top + + ((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel)); +} + +static FUINT HWR_MidLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_mid + + ((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel)); +} + +static FUINT HWR_BottomLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel)); +} +*/ + +static UINT8 HWR_FloorLightLevel(sector_t *sector, UINT8 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 HWR_CeilingLightLevel(sector_t *sector, UINT8 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} // ========================================================================== // FLOOR/CEILING GENERATION FROM SUBSECTORS // ========================================================================== @@ -705,8 +742,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, fixed_t v2x = FloatToFixed(wallVerts[1].x); fixed_t v2y = FloatToFixed(wallVerts[1].z); + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel); const UINT8 alpha = Surf->PolyColor.s.alpha; - FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); + lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; if (!r_renderwalls) @@ -750,13 +788,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, { if (pfloor && (pfloor->fofflags & FOF_FOG)) { - lightnum = pfloor->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel); colormap = pfloor->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } else { - lightnum = *list[i].lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel); colormap = *list[i].extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } @@ -1167,7 +1205,7 @@ static void HWR_ProcessSeg(void) float cliplow = (float)gl_curline->offset; float cliphigh = cliplow + (gl_curline->flength * FRACUNIT); - FUINT lightnum = gl_frontsector->lightlevel; + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel); extracolormap_t *colormap = gl_frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); @@ -1628,11 +1666,11 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); - Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap); if (gl_frontsector->numlights) HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode); @@ -1785,7 +1823,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Fog|PF_NoTexture; - lightnum = rover->master->frontsector->lightlevel; + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); @@ -2442,7 +2480,7 @@ static void HWR_Subsector(size_t num) rover; rover = rover->next) { fixed_t bottomCullHeight, topCullHeight, centerHeight; - + if (!(rover->fofflags & FOF_EXISTS) || !(rover->fofflags & FOF_RENDERPLANES)) continue; if (sub->validcount == validcount) @@ -2471,13 +2509,13 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } @@ -2489,7 +2527,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); @@ -2498,8 +2536,9 @@ static void HWR_Subsector(size_t num) { HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } @@ -2516,13 +2555,13 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } @@ -2534,7 +2573,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); @@ -2543,8 +2582,9 @@ static void HWR_Subsector(size_t num) { HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } } @@ -3906,7 +3946,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent FOF planes always use light level planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; @@ -3938,7 +3978,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent polyobject planes always use light level polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6b489f22b1939941c0ebf83a5a3ae0b7e215de5a..9985e5631201752eddf1ba2abc71aa7304da8f62 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -213,6 +213,14 @@ enum side_e { side_sector, side_special, side_repeatcnt, + side_light, + side_light_top, + side_light_mid, + side_light_bottom, + side_lightabsolute, + side_lightabsolute_top, + side_lightabsolute_mid, + side_lightabsolute_bottom, side_text }; @@ -241,6 +249,14 @@ static const char *const side_opt[] = { "sector", "special", "repeatcnt", + "light", + "light_top", + "light_mid", + "light_bottom", + "lightabsolute", + "lightabsolute_top", + "lightabsolute_mid", + "lightabsolute_bottom", "text", NULL}; @@ -1311,6 +1327,30 @@ static int side_get(lua_State *L) case side_repeatcnt: lua_pushinteger(L, side->repeatcnt); return 1; + case side_light: + lua_pushinteger(L, side->light); + return 1; + case side_light_top: + lua_pushinteger(L, side->light_top); + return 1; + case side_light_mid: + lua_pushinteger(L, side->light_mid); + return 1; + case side_light_bottom: + lua_pushinteger(L, side->light_bottom); + return 1; + case side_lightabsolute: + lua_pushboolean(L, side->lightabsolute); + return 1; + case side_lightabsolute_top: + lua_pushboolean(L, side->lightabsolute_top); + return 1; + case side_lightabsolute_mid: + lua_pushboolean(L, side->lightabsolute_mid); + return 1; + case side_lightabsolute_bottom: + lua_pushboolean(L, side->lightabsolute_bottom); + return 1; // TODO: 2.3: Delete case side_text: { @@ -1413,6 +1453,30 @@ static int side_set(lua_State *L) case side_repeatcnt: side->repeatcnt = luaL_checkinteger(L, 3); break; + case side_light: + side->light = luaL_checkinteger(L, 3); + break; + case side_light_top: + side->light_top = luaL_checkinteger(L, 3); + break; + case side_light_mid: + side->light_mid = luaL_checkinteger(L, 3); + break; + case side_light_bottom: + side->light_bottom = luaL_checkinteger(L, 3); + break; + case side_lightabsolute: + side->lightabsolute = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_top: + side->lightabsolute_top = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_mid: + side->lightabsolute_mid = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_bottom: + side->lightabsolute_bottom = luaL_checkboolean(L, 3); + break; } return 0; } diff --git a/src/m_cond.c b/src/m_cond.c index 5a5913297157e24ada893ca5fad77a4d38ffd3e3..fa6cda223c376b2f458605ec4f99e23e1c28c2d2 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -494,6 +494,12 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data) { + if (dedicated) + { + // See M_MapLocked; don't make dedicated servers annoying. + return false; + } + if (M_MapLocked(mapnum, data) == true) { // Warping to locked maps is definitely always a cheat diff --git a/src/p_saveg.c b/src/p_saveg.c index 219410bb63741e0ca0eb138cc57cf3323665e297..da73dd8a0e1470a1fafd4f5285923ea29c70b7fb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -919,7 +919,11 @@ enum LD_SDMIDLIGHT = 1<<19, LD_SDBOTLIGHT = 1<<20, LD_SDREPEATCNT = 1<<21, - LD_SDFLAGS = 1<<22 + LD_SDFLAGS = 1<<22, + LD_SDLIGHTABS = 1<<23, + LD_SDTOPLIGHTABS = 1<<24, + LD_SDMIDLIGHTABS = 1<<25, + LD_SDBOTLIGHTABS = 1<<26 }; static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) @@ -1393,6 +1397,22 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi) diff |= LD_SDBOTSCALEY; if (si->repeatcnt != spawnsi->repeatcnt) diff |= LD_SDREPEATCNT; + if (si->light != spawnsi->light) + diff |= LD_SDLIGHT; + if (si->light_top != spawnsi->light_top) + diff |= LD_SDTOPLIGHT; + if (si->light_mid != spawnsi->light_mid) + diff |= LD_SDMIDLIGHT; + if (si->light_bottom != spawnsi->light_bottom) + diff |= LD_SDBOTLIGHT; + if (si->lightabsolute != spawnsi->lightabsolute) + diff |= LD_SDLIGHTABS; + if (si->lightabsolute_top != spawnsi->lightabsolute_top) + diff |= LD_SDTOPLIGHTABS; + if (si->lightabsolute_mid != spawnsi->lightabsolute_mid) + diff |= LD_SDMIDLIGHTABS; + if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom) + diff |= LD_SDBOTLIGHTABS; return diff; } @@ -1436,6 +1456,22 @@ static void ArchiveSide(const side_t *si, UINT32 diff) WRITEFIXED(save_p, si->scaley_bottom); if (diff & LD_SDREPEATCNT) WRITEINT16(save_p, si->repeatcnt); + if (diff & LD_SDLIGHT) + WRITEINT16(save_p, si->light); + if (diff & LD_SDTOPLIGHT) + WRITEINT16(save_p, si->light_top); + if (diff & LD_SDMIDLIGHT) + WRITEINT16(save_p, si->light_mid); + if (diff & LD_SDBOTLIGHT) + WRITEINT16(save_p, si->light_bottom); + if (diff & LD_SDLIGHTABS) + WRITEUINT8(save_p, si->lightabsolute); + if (diff & LD_SDTOPLIGHTABS) + WRITEUINT8(save_p, si->lightabsolute_top); + if (diff & LD_SDMIDLIGHTABS) + WRITEUINT8(save_p, si->lightabsolute_mid); + if (diff & LD_SDBOTLIGHTABS) + WRITEUINT8(save_p, si->lightabsolute_bottom); } static void ArchiveLines(void) @@ -1576,6 +1612,22 @@ static void UnArchiveSide(side_t *si) si->scaley_bottom = READFIXED(save_p); if (diff & LD_SDREPEATCNT) si->repeatcnt = READINT16(save_p); + if (diff & LD_SDLIGHT) + si->light = READINT16(save_p); + if (diff & LD_SDTOPLIGHT) + si->light_top = READINT16(save_p); + if (diff & LD_SDMIDLIGHT) + si->light_mid = READINT16(save_p); + if (diff & LD_SDBOTLIGHT) + si->light_bottom = READINT16(save_p); + if (diff & LD_SDLIGHTABS) + si->lightabsolute = READUINT8(save_p); + if (diff & LD_SDTOPLIGHTABS) + si->lightabsolute_top = READUINT8(save_p); + if (diff & LD_SDMIDLIGHTABS) + si->lightabsolute_mid = READUINT8(save_p); + if (diff & LD_SDBOTLIGHTABS) + si->lightabsolute_bottom = READUINT8(save_p); } static void UnArchiveLines(void) @@ -3245,6 +3297,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->translation = READUINT16(save_p); if (diff2 & MD2_ALPHA) mobj->alpha = READFIXED(save_p); + else + mobj->alpha = FRACUNIT; if (diff & MD_REDFLAG) { diff --git a/src/p_setup.c b/src/p_setup.c index e9bd69dc5ff0beef361b33c401e6fb18e1f78c45..b5ed485d8a7df9512ce24a4b78f61e950280b280 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1367,6 +1367,9 @@ static void P_LoadSidedefs(UINT8 *data) sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT; sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; + P_SetSidedefSector(i, (UINT16)SHORT(msd->sector)); // Special info stored in texture fields! @@ -1977,6 +1980,22 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char P_SetSidedefSector(i, atol(val)); else if (fastcmp(param, "repeatcnt")) sides[i].repeatcnt = atol(val); + else if (fastcmp(param, "light")) + sides[i].light = atol(val); + else if (fastcmp(param, "light_top")) + sides[i].light_top = atol(val); + else if (fastcmp(param, "light_mid")) + sides[i].light_mid = atol(val); + else if (fastcmp(param, "light_bottom")) + sides[i].light_bottom = atol(val); + else if (fastcmp(param, "lightabsolute") && fastcmp("true", val)) + sides[i].lightabsolute = true; + else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val)) + sides[i].lightabsolute_top = true; + else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val)) + sides[i].lightabsolute_mid = true; + else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val)) + sides[i].lightabsolute_bottom = true; } static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val) @@ -2704,6 +2723,22 @@ static void P_WriteTextmap(void) fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name); if (wsides[i].repeatcnt != 0) fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt); + if (wsides[i].light != 0) + fprintf(f, "light = %d;\n", wsides[i].light); + if (wsides[i].light_top != 0) + fprintf(f, "light_top = %d;\n", wsides[i].light_top); + if (wsides[i].light_mid != 0) + fprintf(f, "light_mid = %d;\n", wsides[i].light_mid); + if (wsides[i].light_bottom != 0) + fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom); + if (wsides[i].lightabsolute) + fprintf(f, "lightabsolute = true;\n"); + if (wsides[i].lightabsolute_top) + fprintf(f, "lightabsolute_top = true;\n"); + if (wsides[i].lightabsolute_mid) + fprintf(f, "lightabsolute_mid = true;\n"); + if (wsides[i].lightabsolute_bottom) + fprintf(f, "lightabsolute_bottom = true;\n"); fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -3106,6 +3141,8 @@ static void P_LoadTextmap(void) sd->bottomtexture = R_TextureNumForName("-"); sd->sector = NULL; sd->repeatcnt = 0; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter); diff --git a/src/r_bsp.c b/src/r_bsp.c index d606d7a274b322e932cdd9778ea9d780748c7394..4b4c81b882986478eb682c4b17cb77d035409bee 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void) && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); } +static UINT8 R_FloorLightLevel(sector_t *sector, UINT8 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 R_CeilingLightLevel(sector_t *sector, UINT8 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} + // // If player's view height is underneath fake floor, lower the // drawn ceiling to be just under the floor height, and replace @@ -312,11 +324,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight @@ -356,11 +368,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } sec = tempsec; @@ -968,11 +980,10 @@ static void R_Subsector(size_t num) && ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) { - light = R_GetPlaneLight(frontsector, planecenterz, - viewz < heightcheck); + light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic, - *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, + R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL); @@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic, - *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, + R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs, *rover->topxscale, *rover->topyscale, *rover->topangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL); diff --git a/src/r_defs.h b/src/r_defs.h index ea697c7bb3958eaab830fcfd1393db92a2de6ef7..51cc0864652f0363eaf614fee7b23394a6b0dfc1 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -633,6 +633,11 @@ typedef struct fixed_t scalex_top, scalex_mid, scalex_bottom; fixed_t scaley_top, scaley_mid, scaley_bottom; + // per-wall lighting for UDMF + // TODO: implement per-texture lighting + INT16 light, light_top, light_mid, light_bottom; + boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom; + // Texture indices. // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; diff --git a/src/r_plane.c b/src/r_plane.c index 33e3aac1349faebb317d47c1f30ecec5d94a55ce..04272f8d317a790de6f658ddb2592072e50f7393 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -910,7 +910,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent polyobject planes always use light level light = LIGHTLEVELS-1; } else @@ -952,7 +952,7 @@ void R_DrawSinglePlane(visplane_t *pl) if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent FOF planes use light level instead of always being fullbright light = LIGHTLEVELS-1; } else if (pl->ffloor->fofflags & FOF_FOG) diff --git a/src/r_segs.c b/src/r_segs.c index 303de88807bcbbb7289b948e268c71c0d3a30914..637e528fe886636a1fcb9e5255d7a4768c3ff6b7 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -94,6 +94,32 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); } +static INT16 R_SideLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light + + ((side->lightabsolute) ? 0 : base_lightlevel); +} + +/* TODO: implement per-texture lighting +static INT16 R_TopLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_top + + ((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel)); +} + +static INT16 R_MidLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_mid + + ((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel)); +} + +static INT16 R_BottomLightLevel(side_t *side, UINT8 base_lightlevel) +{ + return side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel)); +} +*/ + // If we have a multi-patch texture on a 2sided wall (rare) then we draw // it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this // way we don't have to store extra post_t info with each column for @@ -324,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (rlight->flags & FOF_FOG) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -342,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -798,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Check if the current light effects the colormap/lightlevel if (pfloor->fofflags & FOF_FOG) - rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; else - rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) ; @@ -818,18 +844,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { // Get correct light level! if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; else if (fog) - lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; else if (fuzzy) lightnum = LIGHTLEVELS-1; else - lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) - ->lightlevel >> LIGHTSEGSHIFT; + lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))); else if (curline->v1->y == curline->v2->y) - lightnum--; + lightnum--; else if (curline->v1->x == curline->v2->x) lightnum++; @@ -1463,7 +1488,7 @@ static void R_RenderSegLoop (void) for (i = 0; i < dc_numlights; i++) { INT32 lightnum; - lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT; if (dc_lightlist[i].extra_colormap) ; @@ -2650,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // use different light tables // for horizontal / vertical / diagonal // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; if (curline->v1->y == curline->v2->y) lightnum--; diff --git a/src/r_textures.c b/src/r_textures.c index 6e01d56412f5663bf970baface676ebad6561cb1..b61ddb86f849f26c3e53980163c5a7f1ac2e94cd 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1179,7 +1179,7 @@ static lumpnum_t W_GetTexPatchLumpNum(const char *name) if (lump == LUMPERROR) { // Use whatever else you can find. - return W_GetNumForName(name); + return W_CheckNumForPatchName(name); } return lump;