diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 27f8feba4..aa5697997 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,6 +75,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 r_skins.c r_sky.c r_splats.c + r_spritefx.cpp r_things.c r_bbox.c r_textures.c diff --git a/src/deh_tables.c b/src/deh_tables.c index d348b3a4a..8bd721381 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6323,6 +6323,7 @@ struct int_const_s const INT_CONST[] = { {"RF_SHADOWDRAW",RF_SHADOWDRAW}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_DROPSHADOW",RF_DROPSHADOW}, + {"RF_ABSOLUTELIGHTLEVEL",RF_ABSOLUTELIGHTLEVEL}, {"RF_DONTDRAW",RF_DONTDRAW}, {"RF_DONTDRAWP1",RF_DONTDRAWP1}, {"RF_DONTDRAWP2",RF_DONTDRAWP2}, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 1ae7a6a78..322e322b1 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -42,6 +42,7 @@ enum mobj_e { mobj_spritexoffset, mobj_spriteyoffset, mobj_floorspriteslope, + mobj_lightlevel, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -124,6 +125,7 @@ static const char *const mobj_opt[] = { "spritexoffset", "spriteyoffset", "floorspriteslope", + "lightlevel", "touching_sectorlist", "subsector", "floorz", @@ -266,6 +268,9 @@ static int mobj_get(lua_State *L) case mobj_floorspriteslope: LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE); break; + case mobj_lightlevel: + lua_pushinteger(L, mo->lightlevel); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -569,6 +574,9 @@ static int mobj_set(lua_State *L) break; case mobj_floorspriteslope: return NOSET; + case mobj_lightlevel: + mo->lightlevel = (INT16)luaL_checkinteger(L, 3); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: diff --git a/src/p_mobj.h b/src/p_mobj.h index b6eddadea..0387fdc16 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -312,6 +312,7 @@ struct mobj_t fixed_t old_spritexscale, old_spriteyscale; fixed_t old_spritexoffset, old_spriteyoffset; pslope_t *floorspriteslope; // The slope that the floorsprite is rotated by + INT16 lightlevel; // Add to sector lightlevel, -255 - 255 msecnode_t *touching_sectorlist; // a linked list of sectors where this object appears @@ -469,6 +470,7 @@ struct precipmobj_t fixed_t old_spritexscale, old_spriteyscale; fixed_t old_spritexoffset, old_spriteyoffset; pslope_t *floorspriteslope; // The slope that the floorsprite is rotated by + INT16 lightlevel; // Add to sector lightlevel, -255 - 255 mprecipsecnode_t *touching_sectorlist; // a linked list of sectors where this object appears diff --git a/src/p_saveg.c b/src/p_saveg.c index 86416a33b..49e1ef46d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2228,6 +2228,7 @@ typedef enum MD2_LASTMOMZ = 1<<28, MD2_TERRAIN = 1<<29, MD2_WATERSKIP = 1<<30, + MD2_LIGHTLEVEL = (INT32)(1U<<31), } mobj_diff2_t; typedef enum @@ -2466,6 +2467,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } + if (mobj->lightlevel) + diff2 |= MD2_LIGHTLEVEL; if (mobj->hitlag) diff2 |= MD2_HITLAG; if (mobj->waterskip) @@ -2675,6 +2678,10 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEFIXED(save->p, slope->normal.y); WRITEFIXED(save->p, slope->normal.z); } + if (diff2 & MD2_LIGHTLEVEL) + { + WRITEINT16(save->p, mobj->lightlevel); + } if (diff2 & MD2_HITLAG) { WRITEINT32(save->p, mobj->hitlag); @@ -3834,6 +3841,10 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) P_UpdateSlopeLightOffset(slope); } + if (diff2 & MD2_LIGHTLEVEL) + { + mobj->lightlevel = READINT16(save->p); + } if (diff2 & MD2_HITLAG) { mobj->hitlag = READINT32(save->p); diff --git a/src/r_defs.h b/src/r_defs.h index ec4371e75..6f8049dc8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -961,6 +961,8 @@ typedef enum RF_SHADOWEFFECTS = 0x00008000, // Scales and becomes transparent like a shadow. RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK), + RF_ABSOLUTELIGHTLEVEL = 0x00010000, // mobj_t.lightlevel is absolute instead of relative + RF_DONTDRAW = 0x00F00000, // --Don't generate a vissprite RF_DONTDRAWP1 = 0x00100000, // No P1 RF_DONTDRAWP2 = 0x00200000, // No P2 diff --git a/src/r_spritefx.cpp b/src/r_spritefx.cpp new file mode 100644 index 000000000..f806588e6 --- /dev/null +++ b/src/r_spritefx.cpp @@ -0,0 +1,18 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \brief Special effects for sprite rendering + +#include "r_things.h" + +INT32 R_ThingLightLevel(mobj_t* thing) +{ + INT32 lightlevel = thing->lightlevel; + + return lightlevel; +} diff --git a/src/r_things.c b/src/r_things.c index 79510bff8..8a2bb8251 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1690,6 +1690,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t gz = 0, gzt = 0; INT32 heightsec, phs; INT32 light = 0; + lighttable_t **lights_array = spritelights; fixed_t this_scale; fixed_t spritexscale, spriteyscale; @@ -2239,29 +2240,46 @@ static void R_ProjectSprite(mobj_t *thing) return; } - if (thing->subsector->sector->numlights) + if (thing->renderflags & RF_ABSOLUTELIGHTLEVEL) + { + const UINT8 n = R_ThingLightLevel(thing); + + // n = uint8 aka 0 - 255, so the shift will always be 0 - LIGHTLEVELS - 1 + lights_array = scalelight[n >> LIGHTSEGSHIFT]; + } + else { INT32 lightnum; - fixed_t top = (splat) ? gz : gzt; - light = thing->subsector->sector->numlights - 1; - // R_GetPlaneLight won't work on sloped lights! - for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { - fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interp.x, interp.y); - if (h <= top) { - light = lightnum - 1; - break; + if (thing->subsector->sector->numlights) + { + fixed_t top = (splat) ? gz : gzt; + light = thing->subsector->sector->numlights - 1; + + // R_GetPlaneLight won't work on sloped lights! + for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { + fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interp.x, interp.y); + if (h <= top) { + light = lightnum - 1; + break; + } } + //light = R_GetPlaneLight(thing->subsector->sector, gzt, false); + lightnum = *thing->subsector->sector->lightlist[light].lightlevel; } - //light = R_GetPlaneLight(thing->subsector->sector, gzt, false); - lightnum = (*thing->subsector->sector->lightlist[light].lightlevel >> LIGHTSEGSHIFT); + else + { + lightnum = thing->subsector->sector->lightlevel; + } + + lightnum = (lightnum + R_ThingLightLevel(thing)) >> LIGHTSEGSHIFT; if (lightnum < 0) - spritelights = scalelight[0]; + lights_array = scalelight[0]; else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; + lights_array = scalelight[LIGHTLEVELS-1]; else - spritelights = scalelight[lightnum]; + lights_array = scalelight[lightnum]; } heightsec = thing->subsector->sector->heightsec; @@ -2414,7 +2432,7 @@ static void R_ProjectSprite(mobj_t *thing) if (vis->cut & SC_SEMIBRIGHT) lindex = (MAXLIGHTSCALE/2) + (lindex >> 1); - vis->colormap = spritelights[lindex]; + vis->colormap = lights_array[lindex]; } if (vflip) @@ -2425,7 +2443,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->patch = patch; vis->bright = R_CacheSpriteBrightMap(sprinfo, frame); - if (thing->subsector->sector->numlights && !(shadowdraw || splat)) + if (thing->subsector->sector->numlights && !(shadowdraw || splat) && !(thing->renderflags & RF_ABSOLUTELIGHTLEVEL)) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) diff --git a/src/r_things.h b/src/r_things.h index 30b3c87e3..78b6c013e 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -93,6 +93,8 @@ boolean R_ThingIsFullDark (mobj_t *thing); boolean R_ThingIsFlashing(mobj_t *thing); +INT32 R_ThingLightLevel(mobj_t *thing); + // -------------- // MASKED DRAWING // --------------