Merge branch 'better-splash' into 'master'

TERRAIN expansion pak

See merge request KartKrew/Kart!680
This commit is contained in:
Sal 2022-09-27 16:02:07 +00:00
commit 699666a5d3
11 changed files with 690 additions and 91 deletions

View file

@ -5635,7 +5635,7 @@ const char *const MOBJFLAG_LIST[] = {
"SCENERY",
"PAIN",
"STICKY",
"NIGHTSITEM",
"APPLYTERRAIN",
"NOCLIPTHING",
"GRENADEBOUNCE",
"RUNSPAWNFUNC",

View file

@ -5280,7 +5280,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
MT_THOK, // damage
sfx_None, // activesound
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
(statenum_t)MT_THOK // raisestate
},
@ -5307,7 +5307,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_DONTENCOREMAP, // flags
MF_SOLID|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -20790,7 +20790,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NIGHTSITEM, // flags
MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -20817,7 +20817,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NIGHTSITEM, // flags
MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -20844,7 +20844,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NIGHTSITEM, // flags
MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -20871,7 +20871,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NIGHTSITEM, // flags
MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -20898,7 +20898,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NIGHTSITEM, // flags
MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -23332,7 +23332,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_cdfm28, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23359,7 +23359,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23386,7 +23386,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_peel, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23413,7 +23413,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23440,7 +23440,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_s3k96, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23467,7 +23467,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23494,7 +23494,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_s3kc0s, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23521,7 +23521,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23575,7 +23575,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_s3k5c, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23602,7 +23602,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23710,7 +23710,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_s3k5c, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23737,7 +23737,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_s3k96, // activesound
MF_SPECIAL|MF_DONTENCOREMAP, // flags
MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23764,7 +23764,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -23791,7 +23791,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -24088,7 +24088,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -24304,7 +24304,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_s3k5c, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},
@ -24331,7 +24331,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
S_NULL // raisestate
},

View file

@ -7634,9 +7634,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
ghost->renderflags |= RF_DONTDRAW;
}
// Could probably be moved somewhere else.
K_HandleFootstepParticles(player->mo);
if (P_IsObjectOnGround(player->mo))
{
// Draft dust
@ -8063,6 +8060,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
{
K_SpawnBrakeVisuals(player);
}
else
{
player->mo->spriteyoffset = 0;
}
K_HandleDelayedHitByEm(player);
}

View file

@ -35,6 +35,9 @@ static size_t numSplashDefs = 0;
static t_footstep_t *footstepDefs = NULL;
static size_t numFootstepDefs = 0;
static t_overlay_t *overlayDefs = NULL;
static size_t numOverlayDefs = 0;
static terrain_t *terrainDefs = NULL;
static size_t numTerrainDefs = 0;
@ -182,6 +185,75 @@ t_footstep_t *K_GetFootstepByName(const char *checkName)
return NULL;
}
/*--------------------------------------------------
size_t K_GetOverlayHeapIndex(t_overlay_t *overlay)
See header file for description.
--------------------------------------------------*/
size_t K_GetOverlayHeapIndex(t_overlay_t *overlay)
{
if (overlay == NULL)
{
return SIZE_MAX;
}
return (overlay - overlayDefs);
}
/*--------------------------------------------------
size_t K_GetNumOverlayDefs(void)
See header file for description.
--------------------------------------------------*/
size_t K_GetNumOverlayDefs(void)
{
return numOverlayDefs;
}
/*--------------------------------------------------
t_overlay_t *K_GetOverlayByIndex(size_t checkIndex)
See header file for description.
--------------------------------------------------*/
t_overlay_t *K_GetOverlayByIndex(size_t checkIndex)
{
if (checkIndex >= numOverlayDefs)
{
return NULL;
}
return &overlayDefs[checkIndex];
}
/*--------------------------------------------------
t_overlay_t *K_GetOverlayByName(const char *checkName)
See header file for description.
--------------------------------------------------*/
t_overlay_t *K_GetOverlayByName(const char *checkName)
{
UINT32 checkHash = quickncasehash(checkName, TERRAIN_NAME_LEN);
size_t i;
if (numOverlayDefs == 0)
{
return NULL;
}
for (i = 0; i < numOverlayDefs; i++)
{
t_overlay_t *o = &overlayDefs[i];
if (checkHash == o->hash && !strncmp(checkName, o->name, TERRAIN_NAME_LEN))
{
// Name matches.
return o;
}
}
return NULL;
}
/*--------------------------------------------------
size_t K_GetTerrainHeapIndex(terrain_t *terrain)
@ -407,7 +479,7 @@ void K_ProcessTerrainEffect(mobj_t *mo)
const fixed_t hscale = mapobjectscale + (mapobjectscale - mo->scale);
const fixed_t minspeed = 24*hscale;
fixed_t speed = FixedHypot(mo->momx, mo->momy);
fixed_t upwards = 16 * FRACUNIT * terrain->trickPanel;
fixed_t upwards = 16 * terrain->trickPanel;
player->trickpanel = 1;
player->pflags |= PF_TRICKDELAY;
@ -521,20 +593,37 @@ void K_SetDefaultFriction(mobj_t *mo)
/*--------------------------------------------------
static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
See header file for description.
Creates all of the splash particles for an object
from a splash definition.
Input Arguments:-
mo - The object to spawn the splash particles for.
s - The splash definition to use.
impact - How hard the object hit the surface.
Return:-
N/A
--------------------------------------------------*/
static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
{
const UINT8 numParticles = s->numParticles;
const angle_t particleSpread = ANGLE_MAX / numParticles;
fixed_t momH = INT32_MAX;
fixed_t momV = INT32_MAX;
size_t i;
momH = FixedMul(impact, s->pushH);
momV = FixedMul(impact, s->pushV);
for (i = 0; i < numParticles; i++)
{
mobj_t *dust = NULL;
angle_t pushAngle = (particleSpread * i);
fixed_t momH = INT32_MAX;
fixed_t momV = INT32_MAX;
fixed_t xOff = 0;
fixed_t yOff = 0;
if (numParticles == 1)
{
@ -542,11 +631,23 @@ static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
pushAngle = P_RandomRange(PR_TERRAIN, 0, ANGLE_MAX);
}
if (s->spread > 0)
{
xOff = P_RandomRange(PR_TERRAIN, -s->spread / FRACUNIT, s->spread / FRACUNIT) * FRACUNIT;
yOff = P_RandomRange(PR_TERRAIN, -s->spread / FRACUNIT, s->spread / FRACUNIT) * FRACUNIT;
}
if (s->cone > 0)
{
pushAngle += P_RandomRange(PR_TERRAIN, -s->cone / ANG1, s->cone / ANG1) * ANG1;
}
dust = P_SpawnMobjFromMobj(
mo,
(12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)),
(12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)),
0, s->mobjType
xOff + (12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)),
yOff + (12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)),
0, //P_RandomRange(PR_TERRAIN, 0, s->spread / FRACUNIT) * FRACUNIT,
s->mobjType
);
P_SetTarget(&dust->target, mo);
@ -559,12 +660,9 @@ static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
dust->momy = mo->momy / 2;
dust->momz = 0;
momH = FixedMul(impact, s->pushH);
momV = FixedMul(impact, s->pushV);
dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT));
dust->momy += FixedMul(momH, FINESINE(pushAngle >> ANGLETOFINESHIFT));
dust->momz += momV * P_MobjFlip(mo);
dust->momz += (momV / 16) * P_MobjFlip(mo);
if (s->color != SKINCOLOR_NONE)
{
@ -585,7 +683,7 @@ static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
--------------------------------------------------*/
void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
{
const fixed_t minImpact = 4 * mo->scale;
const fixed_t minImpact = mo->scale;
t_splash_t *s = NULL;
if (mo == NULL || P_MobjWasRemoved(mo) == true)
@ -594,6 +692,12 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
return;
}
if (!(mo->flags & MF_APPLYTERRAIN))
{
// No TERRAIN effects for this object.
return;
}
if (mo->terrain == NULL || mo->terrain->splashID == SIZE_MAX)
{
// No impact for this terrain type.
@ -610,6 +714,8 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
return;
}
impact /= 4;
if (impact < minImpact)
{
impact = minImpact;
@ -623,7 +729,16 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
/*--------------------------------------------------
static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs)
See header file for description.
Creates a new footstep particle for an object
from a footstep definition.
Input Arguments:-
mo - The object to spawn the footstep particle for.
fs - The footstep definition to use.
timer - Spawning frequency timer.
Return:-
N/A
--------------------------------------------------*/
static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer)
{
@ -699,7 +814,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer)
dust->momx = mo->momx;
dust->momy = mo->momy;
dust->momz = P_GetMobjZMovement(mo) / 2;
dust->momz = P_GetMobjZMovement(mo);
momH = FixedMul(momentum, fs->pushH);
momV = FixedMul(momentum, fs->pushV);
@ -735,6 +850,12 @@ void K_HandleFootstepParticles(mobj_t *mo)
return;
}
if (!(mo->flags & MF_APPLYTERRAIN))
{
// No TERRAIN effects for this object.
return;
}
if (mo->terrain == NULL || mo->terrain->footstepID == SIZE_MAX)
{
// If no terrain, check for offroad.
@ -767,6 +888,204 @@ void K_HandleFootstepParticles(mobj_t *mo)
K_SpawnFootstepParticle(mo, fs, timer);
}
/*--------------------------------------------------
static void K_CleanupTerrainOverlay(mobj_t *mo)
Removes an object's terrain overlay.
Input Arguments:-
mo - The object to remove the overlay from.
Return:-
N/A
--------------------------------------------------*/
static void K_CleanupTerrainOverlay(mobj_t *mo)
{
if (mo->terrainOverlay != NULL && P_MobjWasRemoved(mo->terrainOverlay) == false)
{
P_RemoveMobj(mo->terrainOverlay);
}
}
/*--------------------------------------------------
static boolean K_InitTerrainOverlay(mobj_t *mo)
Creates a new terrain overlay for an object.
Input Arguments:-
mo - The object to give an overlay to.
Return:-
true if successful, otherwise false.
--------------------------------------------------*/
static boolean K_InitTerrainOverlay(mobj_t *mo)
{
mobj_t *new = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_OVERLAY);
// Tells the overlay that we haven't set up a state yet.
new->extravalue1 = TOV_UNDEFINED;
// Set up our pointers.
P_SetTarget(&new->target, mo);
P_SetTarget(&mo->terrainOverlay, new);
return true;
}
/*--------------------------------------------------
static t_overlay_state_t K_DesiredTerrainOverlayAction(mobj_t *mo)
Figures out the overlay action to use for an object.
Input Arguments:-
mo - The object
st - The terrain overlay state.
Return:-
The overlay action enum to use for the object.
--------------------------------------------------*/
static t_overlay_action_t K_DesiredTerrainOverlayAction(mobj_t *mo)
{
const boolean moving = (P_AproxDistance(mo->momx, mo->momy) >= (mo->scale >> 1));
if (moving == true)
{
return TOV_MOVING;
}
return TOV_STILL;
}
/*--------------------------------------------------
static statenum_t K_GetTerrainOverlayState(t_overlay_t *o, t_overlay_action_t act)
Converts our overlay's action enum into an actual state ID.
Input Arguments:-
o - The overlay properties.
act - The terrain overlay action.
Return:-
The actual state ID, for use with P_SetMobjState.
--------------------------------------------------*/
static statenum_t K_GetTerrainOverlayState(t_overlay_t *o, t_overlay_action_t act)
{
if (act >= 0 && act < TOV__MAX)
{
return o->states[act];
}
return S_NULL;
}
/*--------------------------------------------------
static void K_SetTerrainOverlayState(mobj_t *mo, t_overlay_action_t act, statenum_t st)
Updates our overlay's current state.
Input Arguments:-
o - The overlay properties.
act - The terrain overlay action.
st - The new object's state.
Return:-
N/A
--------------------------------------------------*/
static void K_SetTerrainOverlayState(mobj_t *mo, t_overlay_action_t act, statenum_t st)
{
if (act == mo->terrainOverlay->extravalue1)
{
// Already set the state, so leave it alone.
return;
}
P_SetMobjState(mo->terrainOverlay, st);
mo->terrainOverlay->extravalue1 = act;
}
/*--------------------------------------------------
static void K_UpdateTerrainOverlay(mobj_t *mo)
See header file for description.
--------------------------------------------------*/
void K_UpdateTerrainOverlay(mobj_t *mo)
{
t_overlay_t *o = NULL;
t_overlay_action_t act = TOV_UNDEFINED;
statenum_t st = S_NULL;
if (mo == NULL || P_MobjWasRemoved(mo) == true)
{
// Invalid object.
return;
}
if (!(mo->flags & MF_APPLYTERRAIN))
{
// No TERRAIN effects for this object.
K_CleanupTerrainOverlay(mo);
return;
}
if (mo->terrain == NULL || mo->terrain->overlayID == SIZE_MAX)
{
// No overlay for this terrain type.
K_CleanupTerrainOverlay(mo);
return;
}
else
{
o = K_GetOverlayByIndex(mo->terrain->overlayID);
}
if (o == NULL)
{
// No overlay to use.
K_CleanupTerrainOverlay(mo);
return;
}
// Determine the state to use. We want to do this before creating
// the overlay, so that we keep it despawned if the state is S_NULL.
act = K_DesiredTerrainOverlayAction(mo);
st = K_GetTerrainOverlayState(o, act);
if (st == S_NULL)
{
// No state to use for this action.
K_CleanupTerrainOverlay(mo);
return;
}
if (mo->terrainOverlay == NULL || P_MobjWasRemoved(mo->terrainOverlay) == true)
{
// Doesn't exist currently, so try to create
// a new terrain overlay.
if (K_InitTerrainOverlay(mo) == false)
{
// We were unsuccessful, get out of here.
return;
}
}
mo->terrainOverlay->spriteyoffset = -mo->terrain->floorClip;
mo->terrainOverlay->color = o->color;
mo->terrainOverlay->movefactor = o->scale;
K_SetTerrainOverlayState(mo, act, st);
if (mo->state->tics > 1 && o->speed > 0)
{
const fixed_t maxSpeed = 60 * mapobjectscale;
fixed_t speed = P_AproxDistance(mo->momx, mo->momy);
fixed_t speedDiv = FRACUNIT + FixedMul(FixedDiv(speed, maxSpeed), o->speed);
tic_t animSpeed = max(FixedDiv(mo->state->tics, speedDiv), 1);
mo->tics = min(mo->tics, animSpeed);
}
}
/*--------------------------------------------------
static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val)
@ -1003,6 +1322,89 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val)
}
}
/*--------------------------------------------------
static void K_OverlayDefaults(t_overlay_t *overlay)
Sets the defaults for a new Overlay block.
Input Arguments:-
overlay - Terrain Overlay structure to default.
Return:-
None
--------------------------------------------------*/
static void K_OverlayDefaults(t_overlay_t *overlay)
{
size_t i;
for (i = 0; i < TOV__MAX; i++)
{
overlay->states[i] = S_NULL;
}
overlay->scale = FRACUNIT;
overlay->color = SKINCOLOR_NONE;
overlay->speed = FRACUNIT;
}
/*--------------------------------------------------
static void K_NewOverlayDefs(void)
Increases the size of overlayDefs by 1, and
sets the new struct's values to their defaults.
Input Arguments:-
None
Return:-
None
--------------------------------------------------*/
static void K_NewOverlayDefs(void)
{
numOverlayDefs++;
overlayDefs = (t_overlay_t *)Z_Realloc(overlayDefs, sizeof(t_overlay_t) * (numOverlayDefs + 1), PU_STATIC, NULL);
K_OverlayDefaults( &overlayDefs[numOverlayDefs - 1] );
}
/*--------------------------------------------------
static void K_ParseOverlayParameter(size_t i, char *param, char *val)
Parser function for Overlay blocks.
Input Arguments:-
i - Struct ID
param - Parameter string
val - Value string
Return:-
None
--------------------------------------------------*/
static void K_ParseOverlayParameter(size_t i, char *param, char *val)
{
t_overlay_t *overlay = &overlayDefs[i];
if (stricmp(param, "stillState") == 0)
{
overlay->states[TOV_STILL] = get_number(val);
}
else if (stricmp(param, "movingState") == 0)
{
overlay->states[TOV_MOVING] = get_number(val);
}
else if (stricmp(param, "scale") == 0)
{
overlay->scale = FLOAT_TO_FIXED(atof(val));
}
else if (stricmp(param, "color") == 0)
{
overlay->color = get_number(val);
}
else if (stricmp(param, "speed") == 0)
{
overlay->speed = FLOAT_TO_FIXED(atof(val));
}
}
/*--------------------------------------------------
static void K_TerrainDefaults(terrain_t *terrain)
@ -1018,6 +1420,7 @@ static void K_TerrainDefaults(terrain_t *terrain)
{
terrain->splashID = SIZE_MAX;
terrain->footstepID = SIZE_MAX;
terrain->overlayID = SIZE_MAX;
terrain->friction = 0;
terrain->offroad = 0;
@ -1072,6 +1475,11 @@ static void K_ParseTerrainParameter(size_t i, char *param, char *val)
t_footstep_t *footstep = K_GetFootstepByName(val);
terrain->footstepID = K_GetFootstepHeapIndex(footstep);
}
else if (stricmp(param, "overlay") == 0)
{
t_overlay_t *overlay = K_GetOverlayByName(val);
terrain->overlayID = K_GetOverlayHeapIndex(overlay);
}
else if (stricmp(param, "friction") == 0)
{
terrain->friction = FLOAT_TO_FIXED(atof(val));
@ -1086,7 +1494,11 @@ static void K_ParseTerrainParameter(size_t i, char *param, char *val)
}
else if (stricmp(param, "trickPanel") == 0)
{
terrain->trickPanel = (UINT8)get_number(val); // trick panel strength enum?
terrain->trickPanel = FLOAT_TO_FIXED(atof(val));
}
else if (stricmp(param, "floorClip") == 0)
{
terrain->floorClip = FLOAT_TO_FIXED(atof(val));
}
else if (stricmp(param, "liquid") == 0)
{
@ -1284,6 +1696,47 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size)
valid = false;
}
}
else if (stricmp(tkn, "overlay") == 0)
{
Z_Free(tkn);
tkn = M_GetToken(NULL);
pos = M_GetTokenPos();
if (tkn && pos < size)
{
t_overlay_t *o = NULL;
tknHash = quickncasehash(tkn, TERRAIN_NAME_LEN);
for (i = 0; i < numOverlayDefs; i++)
{
o = &overlayDefs[i];
if (tknHash == o->hash && !strncmp(tkn, o->name, TERRAIN_NAME_LEN))
{
break;
}
}
if (i == numOverlayDefs)
{
K_NewOverlayDefs();
o = &overlayDefs[i];
strncpy(o->name, tkn, TERRAIN_NAME_LEN);
o->hash = tknHash;
CONS_Printf("Created new Overlay type '%s'\n", o->name);
}
valid = K_DoTERRAINLumpParse(i, K_ParseOverlayParameter);
}
else
{
CONS_Alert(CONS_ERROR, "No Overlay type name.\n");
valid = false;
}
}
else if (stricmp(tkn, "terrain") == 0)
{
Z_Free(tkn);

View file

@ -66,10 +66,33 @@ typedef struct t_footstep_s
fixed_t requiredSpeed; // Speed percentage you need to be at to trigger the particles.
} t_footstep_t;
typedef enum
{
// Overlay actions.
TOV_UNDEFINED = -1,
TOV_STILL,
TOV_MOVING,
TOV__MAX
} t_overlay_action_t;
typedef struct t_overlay_s
{
// Overlay definition.
// These are sprites displayed on top of the base object.
char name[TERRAIN_NAME_LEN]; // Lookup name.
UINT32 hash; // Lookup name's hash.
UINT16 states[TOV__MAX]; // State to use when the object is still.
fixed_t scale; // Thing scale multiplier.
UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize.
fixed_t speed; // Speed-up based on object speed. 0 plays the animation at a constant rate.
} t_overlay_t;
typedef enum
{
// Terrain flag values.
TRF_LIQUID = 1, // Texture water properties (wavy, slippery, etc)
TRF_LIQUID = 1, // Texture has water properties (wavy, slippery, etc)
TRF_SNEAKERPANEL = 1<<1, // Texture is a booster
TRF_STAIRJANK = 1<<2, // Texture is bumpy road
TRF_TRIPWIRE = 1<<3 // Texture is a tripwire when used as a midtexture
@ -85,11 +108,13 @@ typedef struct terrain_s
size_t splashID; // Splash defintion ID.
size_t footstepID; // Footstep defintion ID.
size_t overlayID; // Overlay defintion ID.
fixed_t friction; // The default friction of this texture.
UINT8 offroad; // The default offroad level of this texture.
INT16 damageType; // The default damage type of this texture. (Negative means no damage).
UINT8 trickPanel; // Trick panel strength
fixed_t floorClip; // Offset for sprites on this ground
UINT32 flags; // Flag values (see: terrain_flags_t)
} terrain_t;
@ -226,6 +251,67 @@ t_footstep_t *K_GetFootstepByIndex(size_t checkIndex);
t_footstep_t *K_GetFootstepByName(const char *checkName);
/*--------------------------------------------------
size_t K_GetOverlayHeapIndex(t_overlay_t *overlay);
Returns an overlay defintion's index in the
overlay definition heap.
Input Arguments:-
overlay - The overlay definition to return the index of.
Return:-
The overlay heap index, SIZE_MAX if the overlay was invalid.
--------------------------------------------------*/
size_t K_GetOverlayHeapIndex(t_overlay_t *overlay);
/*--------------------------------------------------
size_t K_GetNumOverlayDefs(void);
Returns the number of overlay definitions.
Input Arguments:-
None
Return:-
Length of overlayDefs.
--------------------------------------------------*/
size_t K_GetNumOverlayDefs(void);
/*--------------------------------------------------
t_overlay_t *K_GetOverlayByIndex(size_t checkIndex);
Retrieves an overlay definition by its heap index.
Input Arguments:-
checkIndex - The heap index to retrieve.
Return:-
The overlay definition, NULL if it didn't exist.
--------------------------------------------------*/
t_overlay_t *K_GetOverlayByIndex(size_t checkIndex);
/*--------------------------------------------------
t_overlay_t *K_GetOverlayByName(const char *checkName);
Retrieves an overlay definition by its lookup name.
Input Arguments:-
checkName - The lookup name to retrieve.
Return:-
The overlay definition, NULL if it didn't exist.
--------------------------------------------------*/
t_overlay_t *K_GetOverlayByName(const char *checkName);
/*--------------------------------------------------
size_t K_GetTerrainHeapIndex(terrain_t *terrain);
@ -443,6 +529,23 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact);
void K_HandleFootstepParticles(mobj_t *mo);
/*--------------------------------------------------
void K_UpdateTerrainOverlay(mobj_t *mo);
Updates an object's terrainOverlay pointer,
depending on the terrain type. Intended to be
called every tic.
Input Arguments:-
mo - The object to update the overlay for.
Return:-
None
--------------------------------------------------*/
void K_UpdateTerrainOverlay(mobj_t *mo);
/*--------------------------------------------------
void K_InitTerrain(UINT16 wadNum);

View file

@ -1771,10 +1771,15 @@ void P_XYMovement(mobj_t *mo)
if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
return;
if (moved == true)
{
// TERRAIN footstep effects.
K_HandleFootstepParticles(mo);
}
if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT))
{
// Check to see if we ran off
if (oldslope != mo->standingslope)
{
// First, compare different slopes
@ -2310,7 +2315,7 @@ boolean P_ZMovement(mobj_t *mo)
// clip movement
if (((mo->z <= mo->floorz && !(mo->eflags & MFE_VERTICALFLIP))
|| (mo->z + mo->height >= mo->ceilingz && mo->eflags & MFE_VERTICALFLIP))
&& !(mo->flags & MF_NOCLIPHEIGHT))
&& !(mo->flags & MF_NOCLIPHEIGHT))
{
vector3_t mom;
mom.x = mo->momx;
@ -2418,6 +2423,7 @@ boolean P_ZMovement(mobj_t *mo)
if (P_MobjFlip(mo)*mom.z < 0) // falling
{
mo->eflags |= MFE_JUSTHITFLOOR;
K_SpawnSplashForMobj(mo, abs(mom.z));
if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something
mom.z = -mom.z;
@ -3838,6 +3844,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
}
P_SquishThink(mobj);
K_UpdateTerrainOverlay(mobj);
animonly:
P_CyclePlayerMobjState(mobj);
@ -5098,7 +5105,7 @@ void P_RunOverlays(void)
}
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale;
mo->scale = mo->destscale = FixedMul(mo->target->scale, mo->movefactor);
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
mo->rollangle = mo->target->rollangle;
mo->pitch = mo->target->pitch;
@ -9397,6 +9404,7 @@ void P_MobjThinker(mobj_t *mobj)
}
P_SquishThink(mobj);
K_UpdateTerrainOverlay(mobj);
if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health
&& P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
@ -12736,15 +12744,10 @@ static void P_SetAmbush(mobj_t *mobj)
mobj->flags ^= MF_NOGRAVITY;
}
if (mobj->flags & MF_NIGHTSITEM)
{
// Spawn already displayed
mobj->flags |= MF_SPECIAL;
mobj->flags &= ~MF_NIGHTSITEM;
}
if (mobj->flags & MF_PUSHABLE)
{
mobj->flags &= ~MF_PUSHABLE;
}
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
{
@ -12770,10 +12773,6 @@ static void P_SetObjectSpecial(mobj_t *mobj)
mobj->flags2 |= MF2_STRONGBOX;
}
// Requires you to be in bonus time to activate
if (mobj->flags & MF_NIGHTSITEM)
mobj->flags2 |= MF2_STRONGBOX;
// Pushables bounce and slide coolly with object special flag set
if (mobj->flags & MF_PUSHABLE)
{
@ -12852,10 +12851,6 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
}
}
// Final set of not being able to draw nightsitems.
if (mobj->flags & MF_NIGHTSITEM)
mobj->renderflags |= RF_DONTDRAW;
return mobj;
}

View file

@ -147,8 +147,8 @@ typedef enum
MF_PAIN = 1<<22,
// This mobj will stick to any surface or solid object it touches.
MF_STICKY = 1<<23,
// NiGHTS hidden item. Goes to seestate and turns MF_SPECIAL when paralooped.
MF_NIGHTSITEM = 1<<24,
// Object uses terrain effects. (Overlays, footsteps, etc)
MF_APPLYTERRAIN = 1<<24,
// for chase camera, don't be blocked by things (partial clipping)
MF_NOCLIPTHING = 1<<25,
// Missile bounces like a grenade.
@ -406,6 +406,8 @@ typedef struct mobj_s
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
struct mobj_s *terrainOverlay; // Overlay sprite object for terrain
INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
INT32 dispoffset;

View file

@ -1882,7 +1882,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_ITNEXT;
if (mobj->lastmomz)
diff2 |= MD2_LASTMOMZ;
if (mobj->terrain != NULL)
if (mobj->terrain != NULL || mobj->terrainOverlay != NULL)
diff2 |= MD2_TERRAIN;
if (diff2 != 0)
@ -3202,6 +3202,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_TERRAIN)
{
mobj->terrain = (terrain_t *)(size_t)READUINT32(save_p);
mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save_p);
}
else
{
@ -4244,6 +4245,13 @@ static void P_RelinkPointers(void)
CONS_Debug(DBG_GAMELOGIC, "terrain not found on %d\n", mobj->type);
}
}
if (mobj->terrainOverlay)
{
temp = (UINT32)(size_t)mobj->terrainOverlay;
mobj->terrainOverlay = NULL;
if (!P_SetTarget(&mobj->terrainOverlay, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "terrainOverlay not found on %d\n", mobj->type);
}
if (mobj->player)
{
if ( mobj->player->skybox.viewpoint)

View file

@ -84,7 +84,7 @@ static fixed_t *maskedtextureheight = NULL;
// multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now.
static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap)
static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap, INT32 baseclip)
{
INT32 topscreen, bottomscreen;
@ -107,6 +107,9 @@ static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yh >= baseclip && baseclip != -1)
dc_yh = baseclip;
if (dc_yl >= vid.height || dc_yh < 0)
return;
@ -144,7 +147,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
fixed_t height, realbot;
lightlist_t *light;
r_lightlist_t *rlight;
void (*colfunc_2s)(column_t *, column_t *);
void (*colfunc_2s)(column_t *, column_t *, INT32);
line_t *ldef;
sector_t *front, *back;
INT32 times, repeats;
@ -457,7 +460,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (windowbottom >= realbot)
{
windowbottom = realbot;
colfunc_2s(col, bmCol);
colfunc_2s(col, bmCol, -1);
for (i++; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
@ -466,7 +469,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
continue;
}
colfunc_2s(col, bmCol);
colfunc_2s(col, bmCol, -1);
windowtop = windowbottom + 1;
dc_colormap = rlight->rcolormap;
dc_fullbright = colormaps;
@ -478,7 +481,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
}
windowbottom = realbot;
if (windowtop < windowbottom)
colfunc_2s(col, bmCol);
colfunc_2s(col, bmCol, -1);
spryscale += rw_scalestep;
continue;
@ -561,7 +564,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
}
else
#endif
colfunc_2s(col, bmCol);
colfunc_2s(col, bmCol, -1);
}
spryscale += rw_scalestep;
}
@ -571,10 +574,11 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
}
// Loop through R_DrawMaskedColumn calls
static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm)
static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm, INT32 baseclip)
{
while (sprtopscreen < sprbotscreen) {
R_DrawMaskedColumn(col, bm);
while (sprtopscreen < sprbotscreen)
{
R_DrawMaskedColumn(col, bm, baseclip);
if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX;
else
@ -582,10 +586,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm)
}
}
static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm)
static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm, INT32 baseclip)
{
do {
R_DrawFlippedMaskedColumn(col, bm);
R_DrawFlippedMaskedColumn(col, bm, baseclip);
sprtopscreen += dc_texheight*spryscale;
} while (sprtopscreen < sprbotscreen);
}
@ -632,7 +636,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t left_top, left_bottom; // needed here for slope skewing
pslope_t *skewslope = NULL;
void (*colfunc_2s) (column_t *, column_t *);
void (*colfunc_2s) (column_t *, column_t *, INT32);
// Calculate light table.
// Use different light tables
@ -1051,7 +1055,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{
windowbottom = sprbotscreen;
// draw the texture
colfunc_2s (col, bmCol);
colfunc_2s (col, bmCol, -1);
for (i++; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
@ -1062,7 +1066,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
continue;
}
// draw the texture
colfunc_2s (col, bmCol);
colfunc_2s (col, bmCol, -1);
if (solid)
windowtop = bheight;
else
@ -1081,7 +1085,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
windowbottom = sprbotscreen;
// draw the texture, if there is any space left
if (windowtop < windowbottom)
colfunc_2s (col, bmCol);
colfunc_2s (col, bmCol, -1);
spryscale += rw_scalestep;
continue;
@ -1108,7 +1112,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
// draw the texture
colfunc_2s (col, bmCol);
colfunc_2s (col, bmCol, -1);
spryscale += rw_scalestep;
}
}

View file

@ -635,7 +635,7 @@ INT16 *mceilingclip;
fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0;
fixed_t windowtop = 0, windowbottom = 0;
void R_DrawMaskedColumn(column_t *column, column_t *brightmap)
void R_DrawMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip)
{
INT32 topscreen;
INT32 bottomscreen;
@ -673,11 +673,15 @@ void R_DrawMaskedColumn(column_t *column, column_t *brightmap)
dc_yh = mfloorclip[dc_x]-1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x]+1;
if (dc_yl < 0)
dc_yl = 0;
if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop
dc_yh = vid.height - 1;
if (dc_yh >= baseclip && baseclip != -1)
dc_yh = baseclip;
if (dc_yl <= dc_yh && dc_yh > 0)
{
dc_source = (UINT8 *)column + 3;
@ -711,7 +715,7 @@ void R_DrawMaskedColumn(column_t *column, column_t *brightmap)
INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap)
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip)
{
INT32 topscreen;
INT32 bottomscreen;
@ -750,6 +754,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap)
dc_yh = mfloorclip[dc_x]-1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x]+1;
if (dc_yh >= baseclip && baseclip != -1)
dc_yh = baseclip;
if (dc_yl < 0)
dc_yl = 0;
if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop
@ -855,7 +863,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
static void R_DrawVisSprite(vissprite_t *vis)
{
column_t *column;
void (*localcolfunc)(column_t *, column_t *);
void (*localcolfunc)(column_t *, column_t *, INT32);
INT32 texturecolumn;
INT32 pwidth;
fixed_t frac;
@ -863,6 +871,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
fixed_t this_scale = vis->thingscale;
INT32 x1, x2;
INT64 overflow_test;
INT32 baseclip = -1;
if (!patch)
return;
@ -938,8 +947,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale);
if (this_scale <= 0)
this_scale = 1;
if (this_scale != FRACUNIT)
{
if (!(vis->cut & SC_ISSCALED))
@ -961,6 +972,16 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
}
if (vis->floorclip)
{
sprbotscreen = sprtopscreen + FixedMul(patch->height << FRACBITS, spryscale);
baseclip = (sprbotscreen - FixedMul(vis->floorclip, spryscale)) >> FRACBITS;
}
else
{
baseclip = -1;
}
x1 = vis->x1;
x2 = vis->x2;
@ -1001,7 +1022,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
localcolfunc (column, NULL);
localcolfunc (column, NULL, baseclip);
}
}
else if (vis->cut & SC_SHEAR)
@ -1023,7 +1044,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
#endif
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
localcolfunc (column, NULL);
localcolfunc (column, NULL, baseclip);
}
}
else
@ -1043,7 +1064,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
#else
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS]));
#endif
localcolfunc (column, NULL);
localcolfunc (column, NULL, baseclip);
}
}
@ -1117,7 +1138,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
#else
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS]));
#endif
R_DrawMaskedColumn(column, NULL);
R_DrawMaskedColumn(column, NULL, -1);
}
R_SetColumnFunc(BASEDRAWFUNC, false);
@ -1610,6 +1631,8 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t this_scale;
fixed_t spritexscale, spriteyscale;
fixed_t floorClip = 0;
// rotsprite
fixed_t spr_width, spr_height;
fixed_t spr_offset, spr_topoffset;
@ -2169,6 +2192,12 @@ static void R_ProjectSprite(mobj_t *thing)
return;
}
if (thing->terrain != NULL && (thing->flags & MF_APPLYTERRAIN))
{
// Clip the bottom of the thing's sprite
floorClip = thing->terrain->floorClip;
}
// store information in a vissprite
vis = R_NewVisSprite();
vis->renderflags = thing->renderflags;
@ -2185,7 +2214,8 @@ static void R_ProjectSprite(mobj_t *thing)
vis->thingheight = thing->height;
vis->pz = interp.z;
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = FixedDiv(gzt - viewz, spriteyscale);
vis->floorclip = floorClip;
vis->texturemid = FixedDiv(gzt - viewz - FixedMul(vis->floorclip, mapobjectscale), spriteyscale);
vis->scalestep = scalestep;
vis->paperoffset = paperoffset;
vis->paperdistance = paperdistance;
@ -2447,6 +2477,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->thingheight = 4*FRACUNIT;
vis->pz = interp.z;
vis->pzt = vis->pz + vis->thingheight;
vis->floorclip = 0;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = 0;
vis->paperdistance = 0;

View file

@ -47,8 +47,8 @@ extern fixed_t windowtop;
extern fixed_t windowbottom;
extern INT32 lengthcol;
void R_DrawMaskedColumn(column_t *column, column_t *brightmap);
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap);
void R_DrawMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip);
void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip);
// ----------------
// SPRITE RENDERING
@ -217,6 +217,8 @@ typedef struct vissprite_s
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
fixed_t floorclip; // Cut off your tires in tall grass
} vissprite_t;
extern UINT32 visspritecount;