mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
2.2 shadow port
This commit is contained in:
parent
834225c597
commit
18637b9eb2
10 changed files with 598 additions and 276 deletions
|
|
@ -39,6 +39,7 @@
|
|||
#include "../st_stuff.h"
|
||||
#include "../i_system.h"
|
||||
#include "../m_cheat.h"
|
||||
#include "../r_things.h" // R_GetShadowZ
|
||||
#ifdef ESLOPE
|
||||
#include "../p_slopes.h"
|
||||
#endif
|
||||
|
|
@ -4058,37 +4059,6 @@ static gr_vissprite_t *HWR_NewVisSprite(void)
|
|||
return HWR_GetVisSprite(gr_visspritecount++);
|
||||
}
|
||||
|
||||
// Finds a floor through which light does not pass.
|
||||
static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
|
||||
{
|
||||
const sector_t *sec = R_PointInSubsector(x, y)->sector;
|
||||
fixed_t floorz = sec->floorheight;
|
||||
|
||||
if (sec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t delta1, delta2;
|
||||
const fixed_t thingtop = z + height;
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS)
|
||||
|| !(rover->flags & FF_RENDERPLANES)
|
||||
|| rover->flags & FF_TRANSLUCENT
|
||||
|| rover->flags & FF_FOG
|
||||
|| rover->flags & FF_INVERTPLANES)
|
||||
continue;
|
||||
|
||||
delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
|
||||
delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
|
||||
if (*rover->topheight > floorz && abs(delta1) < abs(delta2))
|
||||
floorz = *rover->topheight;
|
||||
}
|
||||
}
|
||||
|
||||
return floorz;
|
||||
}
|
||||
|
||||
//
|
||||
// HWR_DoCulling
|
||||
// Hardware version of R_DoCulling
|
||||
|
|
@ -4129,185 +4099,116 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
|
|||
return false;
|
||||
}
|
||||
|
||||
static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale)
|
||||
static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
||||
{
|
||||
FOutVector swallVerts[4];
|
||||
GLPatch_t *gpatch;
|
||||
FOutVector shadowVerts[4];
|
||||
FSurfaceInfo sSurf;
|
||||
fixed_t floorheight, mobjfloor;
|
||||
float offset = 0;
|
||||
float fscale; float fx; float fy; float offset;
|
||||
UINT8 lightlevel = 0;
|
||||
extracolormap_t *colormap = NULL;
|
||||
UINT8 i;
|
||||
|
||||
mobjfloor = HWR_OpaqueFloorAtPos(
|
||||
spr->mobj->x, spr->mobj->y,
|
||||
spr->mobj->z, spr->mobj->height);
|
||||
if (cv_shadowoffs.value)
|
||||
INT32 light;
|
||||
fixed_t scalemul;
|
||||
UINT16 alpha;
|
||||
fixed_t floordiff;
|
||||
fixed_t floorz;
|
||||
fixed_t slopez;
|
||||
pslope_t *floorslope;
|
||||
|
||||
floorz = R_GetShadowZ(thing, &floorslope);
|
||||
floordiff = abs(thing->z - floorz);
|
||||
|
||||
alpha = floordiff / (4*FRACUNIT) + 75;
|
||||
if (alpha >= 255) return;
|
||||
alpha = 255 - alpha;
|
||||
|
||||
if (thing->whiteshadow)
|
||||
{
|
||||
angle_t shadowdir;
|
||||
|
||||
// Set direction
|
||||
if (splitscreen && stplyr == &players[displayplayers[1]])
|
||||
shadowdir = localangle[1] + FixedAngle(cv_cam2_rotate.value);
|
||||
else if (splitscreen > 1 && stplyr == &players[displayplayers[2]])
|
||||
shadowdir = localangle[2] + FixedAngle(cv_cam3_rotate.value);
|
||||
else if (splitscreen > 2 && stplyr == &players[displayplayers[3]])
|
||||
shadowdir = localangle[3] + FixedAngle(cv_cam4_rotate.value);
|
||||
else
|
||||
shadowdir = localangle[0] + FixedAngle(cv_cam_rotate.value);
|
||||
|
||||
// Find floorheight
|
||||
floorheight = HWR_OpaqueFloorAtPos(
|
||||
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
|
||||
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
|
||||
spr->mobj->z, spr->mobj->height);
|
||||
|
||||
// The shadow is falling ABOVE it's mobj?
|
||||
// Don't draw it, then!
|
||||
if (spr->mobj->z < floorheight)
|
||||
return;
|
||||
else
|
||||
{
|
||||
fixed_t floorz;
|
||||
floorz = HWR_OpaqueFloorAtPos(
|
||||
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight),
|
||||
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight),
|
||||
spr->mobj->z, spr->mobj->height);
|
||||
// The shadow would be falling on a wall? Don't draw it, then.
|
||||
// Would draw midair otherwise.
|
||||
if (floorz < floorheight)
|
||||
return;
|
||||
}
|
||||
|
||||
floorheight = FixedInt(spr->mobj->z - floorheight);
|
||||
|
||||
offset = floorheight;
|
||||
gpatch = (GLPatch_t *)W_CachePatchName("LSHADOW", PU_CACHE);
|
||||
lightlevel = 255;
|
||||
}
|
||||
else
|
||||
floorheight = FixedInt(spr->mobj->z - mobjfloor);
|
||||
{
|
||||
gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE);
|
||||
lightlevel = 0;
|
||||
}
|
||||
|
||||
if (!(gpatch && gpatch->mipmap.grInfo.format)) return;
|
||||
HWR_GetPatch(gpatch);
|
||||
|
||||
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||
scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height);
|
||||
|
||||
fscale = FIXED_TO_FLOAT(scalemul);
|
||||
fx = FIXED_TO_FLOAT(thing->x);
|
||||
fy = FIXED_TO_FLOAT(thing->y);
|
||||
|
||||
// create the sprite billboard
|
||||
//
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
|
||||
// x1/x2 were already scaled in HWR_ProjectSprite
|
||||
// First match the normal sprite
|
||||
swallVerts[0].x = swallVerts[3].x = spr->x1;
|
||||
swallVerts[2].x = swallVerts[1].x = spr->x2;
|
||||
swallVerts[0].z = swallVerts[3].z = spr->z1;
|
||||
swallVerts[2].z = swallVerts[1].z = spr->z2;
|
||||
|
||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
||||
{
|
||||
// Always a pixel above the floor, perfectly flat.
|
||||
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3);
|
||||
|
||||
// Now transform the TOP vertices along the floor in the direction of the camera
|
||||
swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos;
|
||||
swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos;
|
||||
swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin;
|
||||
swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin;
|
||||
}
|
||||
if (thing && fabsf(fscale - 1.0f) > 1.0E-36f)
|
||||
offset = (gpatch->height/2) * fscale;
|
||||
else
|
||||
{
|
||||
// Always a pixel above the floor, perfectly flat.
|
||||
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3);
|
||||
offset = (float)(gpatch->height/2);
|
||||
|
||||
// Now transform the TOP vertices along the floor in the direction of the camera
|
||||
swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos;
|
||||
swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos;
|
||||
swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin;
|
||||
swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin;
|
||||
shadowVerts[2].x = shadowVerts[3].x = fx + offset;
|
||||
shadowVerts[1].x = shadowVerts[0].x = fx - offset;
|
||||
shadowVerts[1].z = shadowVerts[2].z = fy - offset;
|
||||
shadowVerts[0].z = shadowVerts[3].z = fy + offset;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
float oldx = shadowVerts[i].x;
|
||||
float oldy = shadowVerts[i].z;
|
||||
shadowVerts[i].x = fx + ((oldx - fx) * gr_viewcos) - ((oldy - fy) * gr_viewsin);
|
||||
shadowVerts[i].z = fy + ((oldx - fx) * gr_viewsin) + ((oldy - fy) * gr_viewcos);
|
||||
}
|
||||
|
||||
// We also need to move the bottom ones away when shadowoffs is on
|
||||
if (cv_shadowoffs.value)
|
||||
if (floorslope)
|
||||
{
|
||||
swallVerts[0].x = spr->x1 + offset * gr_viewcos;
|
||||
swallVerts[1].x = spr->x2 + offset * gr_viewcos;
|
||||
swallVerts[0].z = spr->z1 + offset * gr_viewsin;
|
||||
swallVerts[1].z = spr->z2 + offset * gr_viewsin;
|
||||
}
|
||||
|
||||
if (spr->flip)
|
||||
{
|
||||
swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s;
|
||||
swallVerts[2].sow = swallVerts[1].sow = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
swallVerts[0].sow = swallVerts[3].sow = 0;
|
||||
swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s;
|
||||
}
|
||||
|
||||
// flip the texture coords (look familiar?)
|
||||
if (spr->vflip)
|
||||
{
|
||||
swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t;
|
||||
swallVerts[0].tow = swallVerts[1].tow = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
swallVerts[3].tow = swallVerts[2].tow = 0;
|
||||
swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t;
|
||||
}
|
||||
|
||||
sSurf.FlatColor.s.red = 0x00;
|
||||
sSurf.FlatColor.s.blue = 0x00;
|
||||
sSurf.FlatColor.s.green = 0x00;
|
||||
|
||||
/*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW)
|
||||
{
|
||||
sector_t *sector = spr->mobj->subsector->sector;
|
||||
UINT8 lightlevel = 255;
|
||||
extracolormap_t *colormap = sector->extra_colormap;
|
||||
|
||||
if (sector->numlights)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
{
|
||||
lightlevel = *sector->lightlist[light].lightlevel;
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
}
|
||||
|
||||
if (sector->lightlist[light].extra_colormap)
|
||||
colormap = sector->lightlist[light].extra_colormap;
|
||||
slopez = P_GetZAt(floorslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
|
||||
shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + 0.05f;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightlevel = sector->lightlevel;
|
||||
|
||||
if (sector->extra_colormap)
|
||||
colormap = sector->extra_colormap;
|
||||
}
|
||||
|
||||
if (colormap)
|
||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true);
|
||||
else
|
||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true);
|
||||
}*/
|
||||
|
||||
// shadow is always half as translucent as the sprite itself
|
||||
if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency)
|
||||
sSurf.FlatColor.s.alpha = 0x80; // default
|
||||
else if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
sSurf.FlatColor.s.alpha = 0x20;
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
{
|
||||
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf);
|
||||
sSurf.FlatColor.s.alpha /= 2; //cut alpha in half!
|
||||
}
|
||||
else
|
||||
sSurf.FlatColor.s.alpha = 0x80; // default
|
||||
|
||||
if (sSurf.FlatColor.s.alpha > floorheight/4)
|
||||
{
|
||||
sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4);
|
||||
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
|
||||
for (i = 0; i < 4; i++)
|
||||
shadowVerts[i].y = FIXED_TO_FLOAT(floorz) + 0.05f;
|
||||
}
|
||||
|
||||
shadowVerts[0].sow = shadowVerts[3].sow = 0;
|
||||
shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s;
|
||||
|
||||
shadowVerts[3].tow = shadowVerts[2].tow = 0;
|
||||
shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t;
|
||||
|
||||
if (thing->subsector->sector->numlights)
|
||||
{
|
||||
light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before
|
||||
|
||||
if (thing->subsector->sector->lightlist[light].extra_colormap)
|
||||
colormap = thing->subsector->sector->lightlist[light].extra_colormap;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thing->subsector->sector->extra_colormap)
|
||||
colormap = thing->subsector->sector->extra_colormap;
|
||||
}
|
||||
|
||||
if (colormap)
|
||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
|
||||
else
|
||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
|
||||
|
||||
sSurf.FlatColor.s.alpha = alpha;
|
||||
|
||||
HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
|
||||
}
|
||||
|
||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
|
|
@ -4384,22 +4285,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||
HWR_GetMappedPatch(gpatch, spr->colormap);
|
||||
|
||||
// Draw shadow BEFORE sprite
|
||||
if (cv_shadow.value // Shadows enabled
|
||||
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
|
||||
&& !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
|
||||
#ifdef ALAM_LIGHTING
|
||||
&& !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow.
|
||||
&& (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players.
|
||||
#endif
|
||||
&& (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
|
||||
{
|
||||
////////////////////
|
||||
// SHADOW SPRITE! //
|
||||
////////////////////
|
||||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
||||
}
|
||||
|
||||
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
|
||||
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
|
||||
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
|
||||
|
|
@ -4802,22 +4687,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
|||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||
HWR_GetMappedPatch(gpatch, spr->colormap);
|
||||
|
||||
// Draw shadow BEFORE sprite
|
||||
if (cv_shadow.value // Shadows enabled
|
||||
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
|
||||
&& !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
|
||||
#ifdef ALAM_LIGHTING
|
||||
&& !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow.
|
||||
&& (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players.
|
||||
#endif
|
||||
&& (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
|
||||
{
|
||||
////////////////////
|
||||
// SHADOW SPRITE! //
|
||||
////////////////////
|
||||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
||||
}
|
||||
|
||||
// if it has a dispoffset, push it a little towards the camera
|
||||
if (spr->dispoffset) {
|
||||
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
||||
|
|
@ -5430,6 +5299,12 @@ static void HWR_DrawSprites(void)
|
|||
HWR_DrawPrecipitationSprite(spr);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value)
|
||||
{
|
||||
HWR_DrawDropShadow(spr->mobj, spr->mobj->shadowscale);
|
||||
}
|
||||
|
||||
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
{
|
||||
// 8/1/19: Only don't display player models if no default SPR_PLAY is found.
|
||||
|
|
@ -5445,6 +5320,7 @@ static void HWR_DrawSprites(void)
|
|||
else
|
||||
HWR_DrawMD2(spr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6212,6 +6212,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
P_SetMobjState(ring, S_FASTRING1);
|
||||
ring->extravalue1 = 1; // Ring use animation timer
|
||||
ring->extravalue2 = 1; // Ring use animation flag
|
||||
ring->shadowscale = 0;
|
||||
P_SetTarget(&ring->target, player->mo); // user
|
||||
player->kartstuff[k_rings]--;
|
||||
player->kartstuff[k_ringdelay] = 3;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ enum mobj_e {
|
|||
#ifdef ESLOPE
|
||||
mobj_standingslope,
|
||||
#endif
|
||||
mobj_colorized
|
||||
mobj_colorized,
|
||||
mobj_shadowscale,
|
||||
mobj_whiteshadow
|
||||
};
|
||||
|
||||
static const char *const mobj_opt[] = {
|
||||
|
|
@ -149,6 +151,8 @@ static const char *const mobj_opt[] = {
|
|||
"standingslope",
|
||||
#endif
|
||||
"colorized",
|
||||
"shadowscale",
|
||||
"whiteshadow",
|
||||
NULL};
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||
|
|
@ -360,6 +364,12 @@ static int mobj_get(lua_State *L)
|
|||
case mobj_colorized:
|
||||
lua_pushboolean(L, mo->colorized);
|
||||
break;
|
||||
case mobj_shadowscale:
|
||||
lua_pushfixed(L, mo->shadowscale);
|
||||
break;
|
||||
case mobj_whiteshadow:
|
||||
lua_pushboolean(L, mo->whiteshadow);
|
||||
break;
|
||||
default: // extra custom variables in Lua memory
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
@ -677,6 +687,12 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_colorized:
|
||||
mo->colorized = luaL_checkboolean(L, 3);
|
||||
break;
|
||||
case mobj_shadowscale:
|
||||
mo->shadowscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_whiteshadow:
|
||||
mo->whiteshadow = luaL_checkboolean(L, 3);
|
||||
break;
|
||||
default:
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
|
|||
|
|
@ -2157,6 +2157,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL);
|
||||
target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL);
|
||||
target->health = 0; // This makes it easy to check if something's dead elsewhere.
|
||||
target->shadowscale = 0;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUAh_MobjDeath(target, inflictor, source) || P_MobjWasRemoved(target))
|
||||
|
|
|
|||
64
src/p_mobj.c
64
src/p_mobj.c
|
|
@ -3729,11 +3729,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
|||
mobj->z += mobj->momz;
|
||||
P_SetThingPosition(mobj);
|
||||
P_CheckPosition(mobj, mobj->x, mobj->y);
|
||||
mobj->floorz = tmfloorz;
|
||||
mobj->ceilingz = tmceilingz;
|
||||
goto animonly;
|
||||
}
|
||||
else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer)
|
||||
{
|
||||
P_CheckPosition(mobj, mobj->x, mobj->y);
|
||||
mobj->floorz = tmfloorz;
|
||||
mobj->ceilingz = tmceilingz;
|
||||
goto animonly;
|
||||
}
|
||||
|
||||
|
|
@ -9900,6 +9904,63 @@ void P_SceneryThinker(mobj_t *mobj)
|
|||
// GAME SPAWN FUNCTIONS
|
||||
//
|
||||
|
||||
static void P_DefaultMobjShadowScale(mobj_t *thing)
|
||||
{
|
||||
thing->shadowscale = 0;
|
||||
thing->whiteshadow = (thing->frame & FF_FULLBRIGHT);
|
||||
|
||||
switch (thing->type)
|
||||
{
|
||||
case MT_PLAYER:
|
||||
case MT_SMALLMACE:
|
||||
case MT_BIGMACE:
|
||||
case MT_PUMA:
|
||||
case MT_BIGPUMA:
|
||||
case MT_FALLINGROCK:
|
||||
case MT_SMK_MOLE:
|
||||
case MT_SMK_THWOMP:
|
||||
case MT_BATTLEBUMPER:
|
||||
case MT_BANANA:
|
||||
case MT_ORBINAUT:
|
||||
case MT_ORBINAUT_SHIELD:
|
||||
case MT_JAWZ:
|
||||
case MT_JAWZ_DUD:
|
||||
case MT_JAWZ_SHIELD:
|
||||
case MT_SSMINE:
|
||||
case MT_SSMINE_SHIELD:
|
||||
case MT_BALLHOG:
|
||||
case MT_SINK:
|
||||
case MT_THUNDERSHIELD:
|
||||
case MT_ROCKETSNEAKER:
|
||||
case MT_SPB:
|
||||
thing->shadowscale = 3*FRACUNIT/2;
|
||||
break;
|
||||
case MT_BANANA_SHIELD:
|
||||
thing->shadowscale = 12*FRACUNIT/5;
|
||||
break;
|
||||
case MT_RANDOMITEM:
|
||||
thing->shadowscale = FRACUNIT/2;
|
||||
thing->whiteshadow = false;
|
||||
break;
|
||||
case MT_EGGMANITEM:
|
||||
thing->shadowscale = FRACUNIT;
|
||||
thing->whiteshadow = false;
|
||||
break;
|
||||
case MT_EGGMANITEM_SHIELD:
|
||||
thing->shadowscale = 3*FRACUNIT/2;
|
||||
thing->whiteshadow = false;
|
||||
break;
|
||||
case MT_RING:
|
||||
case MT_FLOATINGITEM:
|
||||
thing->shadowscale = FRACUNIT/2;
|
||||
break;
|
||||
default:
|
||||
if (thing->flags & (MF_ENEMY|MF_BOSS))
|
||||
thing->shadowscale = FRACUNIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_SpawnMobj
|
||||
//
|
||||
|
|
@ -10000,6 +10061,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
|
||||
mobj->colorized = false;
|
||||
|
||||
// Set shadowscale here, before spawn hook so that Lua can change it
|
||||
P_DefaultMobjShadowScale(mobj);
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
// DANGER! This can cause P_SpawnMobj to return NULL!
|
||||
// Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks!
|
||||
|
|
|
|||
|
|
@ -377,6 +377,9 @@ typedef struct mobj_s
|
|||
|
||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||
|
||||
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
|
||||
boolean whiteshadow; // Use white shadow, set to true by default for fullbright objects
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -168,8 +168,7 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo,
|
|||
consvar_t cv_flipcam3 = {"flipcam3", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam3_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_flipcam4 = {"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
@ -1505,7 +1504,6 @@ void R_RegisterEngineStuff(void)
|
|||
CV_RegisterVar(&cv_chasecam3);
|
||||
CV_RegisterVar(&cv_chasecam4);
|
||||
CV_RegisterVar(&cv_shadow);
|
||||
CV_RegisterVar(&cv_shadowoffs);
|
||||
CV_RegisterVar(&cv_skybox);
|
||||
|
||||
CV_RegisterVar(&cv_cam_dist);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ extern consvar_t cv_showhud, cv_translucenthud;
|
|||
extern consvar_t cv_homremoval;
|
||||
extern consvar_t cv_chasecam, cv_chasecam2, cv_chasecam3, cv_chasecam4;
|
||||
extern consvar_t cv_flipcam, cv_flipcam2, cv_flipcam3, cv_flipcam4;
|
||||
extern consvar_t cv_shadow, cv_shadowoffs;
|
||||
extern consvar_t cv_shadow;
|
||||
extern consvar_t cv_translucency;
|
||||
extern consvar_t /*cv_precipdensity,*/ cv_drawdist, /*cv_drawdist_nights,*/ cv_drawdist_precip;
|
||||
extern consvar_t cv_fov;
|
||||
|
|
|
|||
454
src/r_things.c
454
src/r_things.c
|
|
@ -802,9 +802,7 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
|
|||
static void R_DrawVisSprite(vissprite_t *vis)
|
||||
{
|
||||
column_t *column;
|
||||
#ifdef RANGECHECK
|
||||
INT32 texturecolumn;
|
||||
#endif
|
||||
fixed_t frac;
|
||||
patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE);
|
||||
fixed_t this_scale = vis->mobj->scale;
|
||||
|
|
@ -920,6 +918,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
if (!(vis->scalestep))
|
||||
{
|
||||
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
|
||||
sprtopscreen += vis->shear.tan * vis->shear.offset;
|
||||
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
|
||||
}
|
||||
|
||||
|
|
@ -942,31 +941,50 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
vis->x2--;
|
||||
#endif
|
||||
|
||||
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
|
||||
// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
|
||||
if (vis->scalestep)
|
||||
{
|
||||
if (vis->scalestep) // currently papersprites only
|
||||
// Papersprite drawing loop
|
||||
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep)
|
||||
{
|
||||
#ifndef RANGECHECK
|
||||
if ((frac>>FRACBITS) < 0 || (frac>>FRACBITS) >= SHORT(patch->width)) // if this doesn't work i'm removing papersprites
|
||||
break;
|
||||
#endif
|
||||
angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF;
|
||||
texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale;
|
||||
|
||||
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
|
||||
continue;
|
||||
|
||||
if (vis->xiscale < 0) // Flipped sprite
|
||||
texturecolumn = SHORT(patch->width) - 1 - texturecolumn;
|
||||
|
||||
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
|
||||
dc_iscale = (0xffffffffu / (unsigned)spryscale);
|
||||
spryscale += vis->scalestep;
|
||||
}
|
||||
#ifdef RANGECHECK
|
||||
texturecolumn = frac>>FRACBITS;
|
||||
|
||||
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
|
||||
I_Error("R_DrawSpriteRange: bad texturecolumn");
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
|
||||
|
||||
if (vis->cut & SC_VFLIP)
|
||||
R_DrawFlippedMaskedColumn(column, patch->height);
|
||||
else
|
||||
R_DrawMaskedColumn(column);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-paper drawing loop
|
||||
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
|
||||
{
|
||||
#ifdef RANGECHECK
|
||||
texturecolumn = frac>>FRACBITS;
|
||||
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
|
||||
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
|
||||
#else
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
|
||||
#endif
|
||||
if (vis->cut & SC_VFLIP)
|
||||
R_DrawFlippedMaskedColumn(column, patch->height);
|
||||
else
|
||||
R_DrawMaskedColumn(column);
|
||||
if (vis->cut & SC_VFLIP)
|
||||
R_DrawFlippedMaskedColumn(column, patch->height);
|
||||
else
|
||||
R_DrawMaskedColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
colfunc = basecolfunc;
|
||||
|
|
@ -1138,6 +1156,278 @@ static void R_SplitSprite(vissprite_t *sprite)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_GetShadowZ(thing, shadowslope)
|
||||
// Get the first visible floor below the object for shadows
|
||||
// shadowslope is filled with the floor's slope, if provided
|
||||
//
|
||||
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
|
||||
{
|
||||
fixed_t z, floorz = INT32_MIN;
|
||||
pslope_t *slope, *floorslope = NULL;
|
||||
msecnode_t *node;
|
||||
sector_t *sector;
|
||||
ffloor_t *rover;
|
||||
|
||||
for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
sector = node->m_sector;
|
||||
|
||||
slope = (sector->heightsec != -1) ? NULL : sector->f_slope;
|
||||
z = slope ? P_GetZAt(slope, thing->x, thing->y) : (
|
||||
(sector->heightsec != -1) ? sectors[sector->heightsec].floorheight : sector->floorheight
|
||||
);
|
||||
|
||||
if (z < thing->z+thing->height/2 && z > floorz)
|
||||
{
|
||||
floorz = z;
|
||||
floorslope = slope;
|
||||
}
|
||||
|
||||
if (sector->ffloors)
|
||||
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
|
||||
continue;
|
||||
|
||||
z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight;
|
||||
if (z < thing->z+thing->height/2 && z > floorz)
|
||||
{
|
||||
floorz = z;
|
||||
floorslope = *rover->t_slope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->floorz > floorz + (!floorslope ? 0 : FixedMul(abs(floorslope->zdelta), thing->radius*3/2)))
|
||||
{
|
||||
floorz = thing->floorz;
|
||||
floorslope = NULL;
|
||||
}
|
||||
|
||||
#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
|
||||
//#ifdef POLYOBJECTS
|
||||
// Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz
|
||||
if (thing->type == MT_RING)
|
||||
{
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
|
||||
xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
|
||||
BMBOUNDFIX(xl, xh, yl, yh);
|
||||
|
||||
validcount++;
|
||||
|
||||
for (by = yl; by <= yh; by++)
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
{
|
||||
INT32 offset;
|
||||
polymaplink_t *plink; // haleyjd 02/22/06
|
||||
|
||||
if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight)
|
||||
continue;
|
||||
|
||||
offset = by*bmapwidth + bx;
|
||||
|
||||
// haleyjd 02/22/06: consider polyobject lines
|
||||
plink = polyblocklinks[offset];
|
||||
|
||||
while (plink)
|
||||
{
|
||||
polyobj_t *po = plink->po;
|
||||
|
||||
if (po->validcount != validcount) // if polyobj hasn't been checked
|
||||
{
|
||||
po->validcount = validcount;
|
||||
|
||||
if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES))
|
||||
{
|
||||
plink = (polymaplink_t *)(plink->link.next);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're inside it! Yess...
|
||||
z = po->lines[0]->backsector->ceilingheight;
|
||||
|
||||
if (z < thing->z+thing->height/2 && z > floorz)
|
||||
{
|
||||
floorz = z;
|
||||
floorslope = NULL;
|
||||
}
|
||||
}
|
||||
plink = (polymaplink_t *)(plink->link.next);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shadowslope != NULL)
|
||||
*shadowslope = floorslope;
|
||||
|
||||
return floorz;
|
||||
}
|
||||
|
||||
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
|
||||
{
|
||||
vissprite_t *shadow;
|
||||
patch_t *patch;
|
||||
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
|
||||
INT32 light = 0;
|
||||
fixed_t scalemul; UINT8 trans;
|
||||
fixed_t floordiff;
|
||||
fixed_t floorz;
|
||||
pslope_t *floorslope;
|
||||
|
||||
floorz = R_GetShadowZ(thing, &floorslope);
|
||||
|
||||
if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||
|
||||
floordiff = abs(thing->z - floorz);
|
||||
|
||||
trans = floordiff / (100*FRACUNIT) + 3;
|
||||
if (trans >= 9) return;
|
||||
|
||||
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||
|
||||
if (thing->whiteshadow)
|
||||
patch = W_CachePatchName("LSHADOW", PU_CACHE);
|
||||
else
|
||||
patch = W_CachePatchName("DSHADOW", PU_CACHE);
|
||||
|
||||
xscale = FixedDiv(projection, tz);
|
||||
yscale = FixedDiv(projectiony, tz);
|
||||
shadowxscale = FixedMul(thing->radius*2, scalemul);
|
||||
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz));
|
||||
shadowyscale = min(shadowyscale, shadowxscale) / patch->height;
|
||||
shadowxscale /= patch->width;
|
||||
shadowskew = 0;
|
||||
|
||||
if (floorslope)
|
||||
{
|
||||
// haha let's try some dumb stuff
|
||||
fixed_t xslope, zslope;
|
||||
angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT;
|
||||
|
||||
xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta);
|
||||
zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta);
|
||||
|
||||
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
|
||||
|
||||
if (viewz < floorz)
|
||||
shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
|
||||
else
|
||||
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
|
||||
|
||||
shadowyscale = abs(shadowyscale);
|
||||
|
||||
shadowskew = xslope;
|
||||
}
|
||||
|
||||
tx -= patch->width * shadowxscale/2;
|
||||
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
|
||||
if (x1 >= viewwidth) return;
|
||||
|
||||
tx += patch->width * shadowxscale;
|
||||
x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--;
|
||||
if (x2 < 0 || x2 <= x1) return;
|
||||
|
||||
if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes?
|
||||
|
||||
shadow = R_NewVisSprite();
|
||||
|
||||
if (thing->whiteshadow)
|
||||
shadow->patch = W_CheckNumForName("LSHADOW");
|
||||
else
|
||||
shadow->patch = W_CheckNumForName("DSHADOW");
|
||||
|
||||
shadow->heightsec = vis->heightsec;
|
||||
|
||||
shadow->thingheight = FRACUNIT;
|
||||
shadow->pz = floorz;
|
||||
shadow->pzt = shadow->pz + shadow->thingheight;
|
||||
|
||||
shadow->mobjflags = 0;
|
||||
shadow->sortscale = vis->sortscale;
|
||||
shadow->dispoffset = vis->dispoffset - 5;
|
||||
shadow->gx = thing->x;
|
||||
shadow->gy = thing->y;
|
||||
shadow->gzt = shadow->pz + patch->height * shadowyscale / 2;
|
||||
shadow->gz = shadow->gzt - patch->height * shadowyscale;
|
||||
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
|
||||
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||
shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale);
|
||||
shadow->scalestep = 0;
|
||||
shadow->shear.tan = shadowskew; // repurposed variable
|
||||
|
||||
shadow->mobj = thing; // Easy access! Tails 06-07-2002
|
||||
|
||||
shadow->x1 = x1 < 0 ? 0 : x1;
|
||||
shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||
|
||||
// PORTAL SEMI-CLIPPING
|
||||
if (portalrender)
|
||||
{
|
||||
if (shadow->x1 < portalclipstart)
|
||||
shadow->x1 = portalclipstart;
|
||||
if (shadow->x2 >= portalclipend)
|
||||
shadow->x2 = portalclipend-1;
|
||||
}
|
||||
|
||||
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
|
||||
shadow->scale = FixedMul(yscale, shadowyscale);
|
||||
shadow->sector = vis->sector;
|
||||
shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS);
|
||||
shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS);
|
||||
shadow->cut = SC_ISSCALED|SC_SHADOW; //check this
|
||||
|
||||
shadow->startfrac = 0;
|
||||
//shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2);
|
||||
shadow->xiscale = (patch->width<<FRACBITS)/(x2-x1+1); // fuck it
|
||||
|
||||
if (shadow->x1 > x1)
|
||||
shadow->startfrac += shadow->xiscale*(shadow->x1-x1);
|
||||
|
||||
// reusing x1 variable
|
||||
x1 += (x2-x1)/2;
|
||||
shadow->shear.offset = shadow->x1-x1;
|
||||
|
||||
if (thing->subsector->sector->numlights)
|
||||
{
|
||||
INT32 lightnum;
|
||||
#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights!
|
||||
light = thing->subsector->sector->numlights - 1;
|
||||
|
||||
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
|
||||
: thing->subsector->sector->lightlist[lightnum].height;
|
||||
if (h <= shadow->gzt) {
|
||||
light = lightnum - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (thing->subsector->sector->numlights)
|
||||
shadow->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap;
|
||||
else
|
||||
shadow->extra_colormap = thing->subsector->sector->extra_colormap;
|
||||
|
||||
shadow->transmap = transtables + (trans<<FF_TRANSSHIFT);
|
||||
|
||||
if (thing->whiteshadow)
|
||||
shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright!
|
||||
else
|
||||
shadow->colormap = scalelight[0][0]; // full dark!
|
||||
|
||||
objectsdrawn++;
|
||||
}
|
||||
|
||||
//
|
||||
// R_ProjectSprite
|
||||
// Generates a vissprite for a thing
|
||||
|
|
@ -1168,7 +1458,11 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t iscale;
|
||||
fixed_t scalestep; // toast '16
|
||||
fixed_t offset, offset2;
|
||||
boolean papersprite = (thing->frame & FF_PAPERSPRITE);
|
||||
|
||||
fixed_t basetx; // drop shadows
|
||||
|
||||
boolean papersprite = !!(thing->frame & FF_PAPERSPRITE);
|
||||
fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0;
|
||||
|
||||
//SoM: 3/17/2000
|
||||
fixed_t gz, gzt;
|
||||
|
|
@ -1176,8 +1470,6 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
INT32 light = 0;
|
||||
fixed_t this_scale = thing->scale;
|
||||
|
||||
fixed_t ang_scale = FRACUNIT;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thing->x - viewx;
|
||||
tr_y = thing->y - viewy;
|
||||
|
|
@ -1188,15 +1480,15 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
tz = gxt-gyt;
|
||||
|
||||
// thing is behind view plane?
|
||||
if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
|
||||
if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
|
||||
return;
|
||||
|
||||
gxt = -FixedMul(tr_x, viewsin);
|
||||
gyt = FixedMul(tr_y, viewcos);
|
||||
tx = -(gyt + gxt);
|
||||
basetx = tx = -(gyt + gxt);
|
||||
|
||||
// too far off the side?
|
||||
if (abs(tx) > tz<<2)
|
||||
if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
|
||||
return;
|
||||
|
||||
// aspect ratio stuff
|
||||
|
|
@ -1249,8 +1541,6 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
|
||||
else
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
if (papersprite)
|
||||
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
|
||||
}
|
||||
|
||||
if (sprframe->rotate == SRF_SINGLE)
|
||||
|
|
@ -1288,27 +1578,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
else
|
||||
offset = -spritecachedinfo[lump].offset;
|
||||
offset = FixedMul(offset, this_scale);
|
||||
tx += FixedMul(offset, ang_scale);
|
||||
x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS;
|
||||
|
||||
// off the right side?
|
||||
if (x1 > viewwidth)
|
||||
return;
|
||||
|
||||
offset2 = FixedMul(spritecachedinfo[lump].width, this_scale);
|
||||
tx += FixedMul(offset2, ang_scale);
|
||||
x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - 1;
|
||||
|
||||
// off the left side
|
||||
if (x2 < 0)
|
||||
return;
|
||||
|
||||
if (papersprite)
|
||||
{
|
||||
fixed_t yscale2, cosmul, sinmul, tz2;
|
||||
|
||||
if (x2 <= x1)
|
||||
return;
|
||||
fixed_t xscale2, yscale2, cosmul, sinmul, tx2, tz2;
|
||||
INT32 range;
|
||||
|
||||
if (ang >= ANGLE_180)
|
||||
{
|
||||
|
|
@ -1325,7 +1600,23 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
gyt = -FixedMul(tr_y, viewsin);
|
||||
tz = gxt-gyt;
|
||||
yscale = FixedDiv(projectiony, tz);
|
||||
if (yscale < 64) return; // Fix some funky visuals
|
||||
//if (yscale < 64) return; // Fix some funky visuals
|
||||
|
||||
gxt = -FixedMul(tr_x, viewsin);
|
||||
gyt = FixedMul(tr_y, viewcos);
|
||||
tx = -(gyt + gxt);
|
||||
xscale = FixedDiv(projection, tz);
|
||||
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
|
||||
|
||||
// Get paperoffset (offset) and paperoffset (distance)
|
||||
paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
|
||||
paperdistance = -FixedMul(tr_x, sinmul) + FixedMul(tr_y, cosmul);
|
||||
if (paperdistance < 0)
|
||||
{
|
||||
paperoffset = -paperoffset;
|
||||
paperdistance = -paperdistance;
|
||||
}
|
||||
centerangle = viewangle - thing->angle;
|
||||
|
||||
tr_x += FixedMul(offset2, cosmul);
|
||||
tr_y += FixedMul(offset2, sinmul);
|
||||
|
|
@ -1333,13 +1624,52 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
gyt = -FixedMul(tr_y, viewsin);
|
||||
tz2 = gxt-gyt;
|
||||
yscale2 = FixedDiv(projectiony, tz2);
|
||||
if (yscale2 < 64) return; // ditto
|
||||
//if (yscale2 < 64) return; // ditto
|
||||
|
||||
gxt = -FixedMul(tr_x, viewsin);
|
||||
gyt = FixedMul(tr_y, viewcos);
|
||||
tx2 = -(gyt + gxt);
|
||||
xscale2 = FixedDiv(projection, tz2);
|
||||
x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
|
||||
|
||||
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
|
||||
return;
|
||||
|
||||
scalestep = (yscale2 - yscale)/(x2 - x1);
|
||||
scalestep = scalestep ? scalestep : 1;
|
||||
// Needs partially clipped
|
||||
if (tz < FixedMul(MINZ, this_scale))
|
||||
{
|
||||
fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz);
|
||||
tx += FixedDiv(tx2-tx, div);
|
||||
tz = FixedMul(MINZ, this_scale);
|
||||
yscale = FixedDiv(projectiony, tz);
|
||||
xscale = FixedDiv(projection, tz);
|
||||
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
|
||||
}
|
||||
else if (tz2 < FixedMul(MINZ, this_scale))
|
||||
{
|
||||
fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2);
|
||||
tx2 += FixedDiv(tx-tx2, div);
|
||||
tz2 = FixedMul(MINZ, this_scale);
|
||||
yscale2 = FixedDiv(projectiony, tz2);
|
||||
xscale2 = FixedDiv(projection, tz2);
|
||||
x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
|
||||
}
|
||||
|
||||
// off the right side?
|
||||
if (x1 > viewwidth)
|
||||
return;
|
||||
|
||||
// off the left side
|
||||
if (x2 < 0)
|
||||
return;
|
||||
|
||||
if ((range = x2 - x1) <= 0)
|
||||
return;
|
||||
|
||||
range++; // fencepost problem
|
||||
|
||||
scalestep = ((yscale2 - yscale)/range) ?: 1;
|
||||
xscale = FixedDiv(range<<FRACBITS, abs(offset2));
|
||||
|
||||
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
|
||||
// sortscale = max(yscale, yscale2);
|
||||
|
|
@ -1349,9 +1679,20 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
{
|
||||
scalestep = 0;
|
||||
yscale = sortscale;
|
||||
}
|
||||
tx += offset;
|
||||
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
|
||||
|
||||
xscale = FixedMul(xscale, ang_scale);
|
||||
// off the right side?
|
||||
if (x1 > viewwidth)
|
||||
return;
|
||||
|
||||
tx += offset2;
|
||||
x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--;
|
||||
|
||||
// off the left side
|
||||
if (x2 < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// PORTAL SPRITE CLIPPING
|
||||
if (portalrender)
|
||||
|
|
@ -1445,6 +1786,11 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = scalestep;
|
||||
vis->paperoffset = paperoffset;
|
||||
vis->paperdistance = paperdistance;
|
||||
vis->centerangle = centerangle;
|
||||
vis->shear.tan = 0;
|
||||
vis->shear.offset = 0;
|
||||
|
||||
vis->mobj = thing; // Easy access! Tails 06-07-2002
|
||||
|
||||
|
|
@ -1537,6 +1883,9 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (thing->subsector->sector->numlights)
|
||||
R_SplitSprite(vis);
|
||||
|
||||
if (thing->shadowscale && cv_shadow.value)
|
||||
R_ProjectDropShadow(thing, vis, thing->shadowscale, basetx, tz);
|
||||
|
||||
// Debug
|
||||
++objectsdrawn;
|
||||
}
|
||||
|
|
@ -1670,6 +2019,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = 0;
|
||||
vis->paperdistance = 0;
|
||||
vis->shear.tan = 0;
|
||||
vis->shear.offset = 0;
|
||||
|
||||
vis->x1 = x1 < 0 ? 0 : x1;
|
||||
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ void R_SortVisSprites(void);
|
|||
// (only sprites from namelist are added or replaced)
|
||||
void R_AddSpriteDefs(UINT16 wadnum);
|
||||
|
||||
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
|
||||
|
||||
#ifdef DELFILE
|
||||
void R_DelSpriteDefs(UINT16 wadnum);
|
||||
#endif
|
||||
|
|
@ -114,7 +116,8 @@ typedef enum
|
|||
SC_FULLBRIGHT = 1<<4,
|
||||
SC_SEMIBRIGHT = 1<<5,
|
||||
SC_VFLIP = 1<<6,
|
||||
SC_ISSCALED = 1>>7,
|
||||
SC_ISSCALED = 1<<7,
|
||||
SC_SHADOW = 1<<8,
|
||||
// masks
|
||||
SC_CUTMASK = SC_TOP|SC_BOTTOM,
|
||||
SC_FLAGMASK = ~SC_CUTMASK
|
||||
|
|
@ -139,8 +142,16 @@ typedef struct vissprite_s
|
|||
fixed_t startfrac; // horizontal position of x1
|
||||
fixed_t scale, sortscale; // sortscale only differs from scale for flat sprites
|
||||
fixed_t scalestep; // only for flat sprites, 0 otherwise
|
||||
fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle
|
||||
fixed_t xiscale; // negative if flipped
|
||||
|
||||
angle_t centerangle; // for paper sprites
|
||||
|
||||
struct {
|
||||
fixed_t tan; // The amount to shear the sprite vertically per row
|
||||
INT32 offset; // The center of the shearing location offset from x1
|
||||
} shear;
|
||||
|
||||
fixed_t texturemid;
|
||||
lumpnum_t patch;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue