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", "SCENERY",
"PAIN", "PAIN",
"STICKY", "STICKY",
"NIGHTSITEM", "APPLYTERRAIN",
"NOCLIPTHING", "NOCLIPTHING",
"GRENADEBOUNCE", "GRENADEBOUNCE",
"RUNSPAWNFUNC", "RUNSPAWNFUNC",

View file

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

View file

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

View file

@ -35,6 +35,9 @@ static size_t numSplashDefs = 0;
static t_footstep_t *footstepDefs = NULL; static t_footstep_t *footstepDefs = NULL;
static size_t numFootstepDefs = 0; static size_t numFootstepDefs = 0;
static t_overlay_t *overlayDefs = NULL;
static size_t numOverlayDefs = 0;
static terrain_t *terrainDefs = NULL; static terrain_t *terrainDefs = NULL;
static size_t numTerrainDefs = 0; static size_t numTerrainDefs = 0;
@ -182,6 +185,75 @@ t_footstep_t *K_GetFootstepByName(const char *checkName)
return NULL; 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) 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 hscale = mapobjectscale + (mapobjectscale - mo->scale);
const fixed_t minspeed = 24*hscale; const fixed_t minspeed = 24*hscale;
fixed_t speed = FixedHypot(mo->momx, mo->momy); 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->trickpanel = 1;
player->pflags |= PF_TRICKDELAY; 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) 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) static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact)
{ {
const UINT8 numParticles = s->numParticles; const UINT8 numParticles = s->numParticles;
const angle_t particleSpread = ANGLE_MAX / numParticles; const angle_t particleSpread = ANGLE_MAX / numParticles;
fixed_t momH = INT32_MAX;
fixed_t momV = INT32_MAX;
size_t i; size_t i;
momH = FixedMul(impact, s->pushH);
momV = FixedMul(impact, s->pushV);
for (i = 0; i < numParticles; i++) for (i = 0; i < numParticles; i++)
{ {
mobj_t *dust = NULL; mobj_t *dust = NULL;
angle_t pushAngle = (particleSpread * i); 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) 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); 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( dust = P_SpawnMobjFromMobj(
mo, mo,
(12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)), xOff + (12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)),
(12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)), yOff + (12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)),
0, s->mobjType 0, //P_RandomRange(PR_TERRAIN, 0, s->spread / FRACUNIT) * FRACUNIT,
s->mobjType
); );
P_SetTarget(&dust->target, mo); 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->momy = mo->momy / 2;
dust->momz = 0; dust->momz = 0;
momH = FixedMul(impact, s->pushH);
momV = FixedMul(impact, s->pushV);
dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT));
dust->momy += FixedMul(momH, FINESINE(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) 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) 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; t_splash_t *s = NULL;
if (mo == NULL || P_MobjWasRemoved(mo) == true) if (mo == NULL || P_MobjWasRemoved(mo) == true)
@ -594,6 +692,12 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
return; return;
} }
if (!(mo->flags & MF_APPLYTERRAIN))
{
// No TERRAIN effects for this object.
return;
}
if (mo->terrain == NULL || mo->terrain->splashID == SIZE_MAX) if (mo->terrain == NULL || mo->terrain->splashID == SIZE_MAX)
{ {
// No impact for this terrain type. // No impact for this terrain type.
@ -610,6 +714,8 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact)
return; return;
} }
impact /= 4;
if (impact < minImpact) if (impact < minImpact)
{ {
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) 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) 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->momx = mo->momx;
dust->momy = mo->momy; dust->momy = mo->momy;
dust->momz = P_GetMobjZMovement(mo) / 2; dust->momz = P_GetMobjZMovement(mo);
momH = FixedMul(momentum, fs->pushH); momH = FixedMul(momentum, fs->pushH);
momV = FixedMul(momentum, fs->pushV); momV = FixedMul(momentum, fs->pushV);
@ -735,6 +850,12 @@ void K_HandleFootstepParticles(mobj_t *mo)
return; return;
} }
if (!(mo->flags & MF_APPLYTERRAIN))
{
// No TERRAIN effects for this object.
return;
}
if (mo->terrain == NULL || mo->terrain->footstepID == SIZE_MAX) if (mo->terrain == NULL || mo->terrain->footstepID == SIZE_MAX)
{ {
// If no terrain, check for offroad. // If no terrain, check for offroad.
@ -767,6 +888,204 @@ void K_HandleFootstepParticles(mobj_t *mo)
K_SpawnFootstepParticle(mo, fs, timer); 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) 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) static void K_TerrainDefaults(terrain_t *terrain)
@ -1018,6 +1420,7 @@ static void K_TerrainDefaults(terrain_t *terrain)
{ {
terrain->splashID = SIZE_MAX; terrain->splashID = SIZE_MAX;
terrain->footstepID = SIZE_MAX; terrain->footstepID = SIZE_MAX;
terrain->overlayID = SIZE_MAX;
terrain->friction = 0; terrain->friction = 0;
terrain->offroad = 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); t_footstep_t *footstep = K_GetFootstepByName(val);
terrain->footstepID = K_GetFootstepHeapIndex(footstep); 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) else if (stricmp(param, "friction") == 0)
{ {
terrain->friction = FLOAT_TO_FIXED(atof(val)); 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) 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) else if (stricmp(param, "liquid") == 0)
{ {
@ -1284,6 +1696,47 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size)
valid = false; 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) else if (stricmp(tkn, "terrain") == 0)
{ {
Z_Free(tkn); 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. fixed_t requiredSpeed; // Speed percentage you need to be at to trigger the particles.
} t_footstep_t; } 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 typedef enum
{ {
// Terrain flag values. // 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_SNEAKERPANEL = 1<<1, // Texture is a booster
TRF_STAIRJANK = 1<<2, // Texture is bumpy road TRF_STAIRJANK = 1<<2, // Texture is bumpy road
TRF_TRIPWIRE = 1<<3 // Texture is a tripwire when used as a midtexture 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 splashID; // Splash defintion ID.
size_t footstepID; // Footstep defintion ID. size_t footstepID; // Footstep defintion ID.
size_t overlayID; // Overlay defintion ID.
fixed_t friction; // The default friction of this texture. fixed_t friction; // The default friction of this texture.
UINT8 offroad; // The default offroad level 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). INT16 damageType; // The default damage type of this texture. (Negative means no damage).
UINT8 trickPanel; // Trick panel strength UINT8 trickPanel; // Trick panel strength
fixed_t floorClip; // Offset for sprites on this ground
UINT32 flags; // Flag values (see: terrain_flags_t) UINT32 flags; // Flag values (see: terrain_flags_t)
} terrain_t; } terrain_t;
@ -226,6 +251,67 @@ t_footstep_t *K_GetFootstepByIndex(size_t checkIndex);
t_footstep_t *K_GetFootstepByName(const char *checkName); 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); 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_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); 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;; if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
return; return;
if (moved == true)
{
// TERRAIN footstep effects.
K_HandleFootstepParticles(mo);
}
if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT)) if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT))
{ {
// Check to see if we ran off // Check to see if we ran off
if (oldslope != mo->standingslope) if (oldslope != mo->standingslope)
{ {
// First, compare different slopes // First, compare different slopes
@ -2310,7 +2315,7 @@ boolean P_ZMovement(mobj_t *mo)
// clip movement // clip movement
if (((mo->z <= mo->floorz && !(mo->eflags & MFE_VERTICALFLIP)) if (((mo->z <= mo->floorz && !(mo->eflags & MFE_VERTICALFLIP))
|| (mo->z + mo->height >= mo->ceilingz && 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; vector3_t mom;
mom.x = mo->momx; mom.x = mo->momx;
@ -2418,6 +2423,7 @@ boolean P_ZMovement(mobj_t *mo)
if (P_MobjFlip(mo)*mom.z < 0) // falling if (P_MobjFlip(mo)*mom.z < 0) // falling
{ {
mo->eflags |= MFE_JUSTHITFLOOR; mo->eflags |= MFE_JUSTHITFLOOR;
K_SpawnSplashForMobj(mo, abs(mom.z));
if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something
mom.z = -mom.z; mom.z = -mom.z;
@ -3838,6 +3844,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
} }
P_SquishThink(mobj); P_SquishThink(mobj);
K_UpdateTerrainOverlay(mobj);
animonly: animonly:
P_CyclePlayerMobjState(mobj); P_CyclePlayerMobjState(mobj);
@ -5098,7 +5105,7 @@ void P_RunOverlays(void)
} }
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); 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->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
mo->rollangle = mo->target->rollangle; mo->rollangle = mo->target->rollangle;
mo->pitch = mo->target->pitch; mo->pitch = mo->target->pitch;
@ -9397,6 +9404,7 @@ void P_MobjThinker(mobj_t *mobj)
} }
P_SquishThink(mobj); P_SquishThink(mobj);
K_UpdateTerrainOverlay(mobj);
if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health
&& P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz && 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; 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) if (mobj->flags & MF_PUSHABLE)
{
mobj->flags &= ~MF_PUSHABLE; mobj->flags &= ~MF_PUSHABLE;
}
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
{ {
@ -12770,10 +12773,6 @@ static void P_SetObjectSpecial(mobj_t *mobj)
mobj->flags2 |= MF2_STRONGBOX; 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 // Pushables bounce and slide coolly with object special flag set
if (mobj->flags & MF_PUSHABLE) 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; return mobj;
} }

View file

@ -147,8 +147,8 @@ typedef enum
MF_PAIN = 1<<22, MF_PAIN = 1<<22,
// This mobj will stick to any surface or solid object it touches. // This mobj will stick to any surface or solid object it touches.
MF_STICKY = 1<<23, MF_STICKY = 1<<23,
// NiGHTS hidden item. Goes to seestate and turns MF_SPECIAL when paralooped. // Object uses terrain effects. (Overlays, footsteps, etc)
MF_NIGHTSITEM = 1<<24, MF_APPLYTERRAIN = 1<<24,
// for chase camera, don't be blocked by things (partial clipping) // for chase camera, don't be blocked by things (partial clipping)
MF_NOCLIPTHING = 1<<25, MF_NOCLIPTHING = 1<<25,
// Missile bounces like a grenade. // 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 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 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 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
INT32 dispoffset; INT32 dispoffset;

View file

@ -1882,7 +1882,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_ITNEXT; diff2 |= MD2_ITNEXT;
if (mobj->lastmomz) if (mobj->lastmomz)
diff2 |= MD2_LASTMOMZ; diff2 |= MD2_LASTMOMZ;
if (mobj->terrain != NULL) if (mobj->terrain != NULL || mobj->terrainOverlay != NULL)
diff2 |= MD2_TERRAIN; diff2 |= MD2_TERRAIN;
if (diff2 != 0) if (diff2 != 0)
@ -3202,6 +3202,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_TERRAIN) if (diff2 & MD2_TERRAIN)
{ {
mobj->terrain = (terrain_t *)(size_t)READUINT32(save_p); mobj->terrain = (terrain_t *)(size_t)READUINT32(save_p);
mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save_p);
} }
else else
{ {
@ -4244,6 +4245,13 @@ static void P_RelinkPointers(void)
CONS_Debug(DBG_GAMELOGIC, "terrain not found on %d\n", mobj->type); 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)
{ {
if ( mobj->player->skybox.viewpoint) 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 // multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now. // 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; INT32 topscreen, bottomscreen;
@ -107,6 +107,9 @@ static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap
if (dc_yl <= mceilingclip[dc_x]) if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1; dc_yl = mceilingclip[dc_x] + 1;
if (dc_yh >= baseclip && baseclip != -1)
dc_yh = baseclip;
if (dc_yl >= vid.height || dc_yh < 0) if (dc_yl >= vid.height || dc_yh < 0)
return; return;
@ -144,7 +147,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
fixed_t height, realbot; fixed_t height, realbot;
lightlist_t *light; lightlist_t *light;
r_lightlist_t *rlight; r_lightlist_t *rlight;
void (*colfunc_2s)(column_t *, column_t *); void (*colfunc_2s)(column_t *, column_t *, INT32);
line_t *ldef; line_t *ldef;
sector_t *front, *back; sector_t *front, *back;
INT32 times, repeats; INT32 times, repeats;
@ -457,7 +460,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (windowbottom >= realbot) if (windowbottom >= realbot)
{ {
windowbottom = realbot; windowbottom = realbot;
colfunc_2s(col, bmCol); colfunc_2s(col, bmCol, -1);
for (i++; i < dc_numlights; i++) for (i++; i < dc_numlights; i++)
{ {
rlight = &dc_lightlist[i]; rlight = &dc_lightlist[i];
@ -466,7 +469,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
continue; continue;
} }
colfunc_2s(col, bmCol); colfunc_2s(col, bmCol, -1);
windowtop = windowbottom + 1; windowtop = windowbottom + 1;
dc_colormap = rlight->rcolormap; dc_colormap = rlight->rcolormap;
dc_fullbright = colormaps; dc_fullbright = colormaps;
@ -478,7 +481,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
windowbottom = realbot; windowbottom = realbot;
if (windowtop < windowbottom) if (windowtop < windowbottom)
colfunc_2s(col, bmCol); colfunc_2s(col, bmCol, -1);
spryscale += rw_scalestep; spryscale += rw_scalestep;
continue; continue;
@ -561,7 +564,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
else else
#endif #endif
colfunc_2s(col, bmCol); colfunc_2s(col, bmCol, -1);
} }
spryscale += rw_scalestep; spryscale += rw_scalestep;
} }
@ -571,10 +574,11 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
// Loop through R_DrawMaskedColumn calls // 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) { while (sprtopscreen < sprbotscreen)
R_DrawMaskedColumn(col, bm); {
R_DrawMaskedColumn(col, bm, baseclip);
if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX; sprtopscreen = INT32_MAX;
else 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 { do {
R_DrawFlippedMaskedColumn(col, bm); R_DrawFlippedMaskedColumn(col, bm, baseclip);
sprtopscreen += dc_texheight*spryscale; sprtopscreen += dc_texheight*spryscale;
} while (sprtopscreen < sprbotscreen); } 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 fixed_t left_top, left_bottom; // needed here for slope skewing
pslope_t *skewslope = NULL; pslope_t *skewslope = NULL;
void (*colfunc_2s) (column_t *, column_t *); void (*colfunc_2s) (column_t *, column_t *, INT32);
// Calculate light table. // Calculate light table.
// Use different light tables // Use different light tables
@ -1051,7 +1055,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{ {
windowbottom = sprbotscreen; windowbottom = sprbotscreen;
// draw the texture // draw the texture
colfunc_2s (col, bmCol); colfunc_2s (col, bmCol, -1);
for (i++; i < dc_numlights; i++) for (i++; i < dc_numlights; i++)
{ {
rlight = &dc_lightlist[i]; rlight = &dc_lightlist[i];
@ -1062,7 +1066,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
continue; continue;
} }
// draw the texture // draw the texture
colfunc_2s (col, bmCol); colfunc_2s (col, bmCol, -1);
if (solid) if (solid)
windowtop = bheight; windowtop = bheight;
else else
@ -1081,7 +1085,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
windowbottom = sprbotscreen; windowbottom = sprbotscreen;
// draw the texture, if there is any space left // draw the texture, if there is any space left
if (windowtop < windowbottom) if (windowtop < windowbottom)
colfunc_2s (col, bmCol); colfunc_2s (col, bmCol, -1);
spryscale += rw_scalestep; spryscale += rw_scalestep;
continue; 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); dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
// draw the texture // draw the texture
colfunc_2s (col, bmCol); colfunc_2s (col, bmCol, -1);
spryscale += rw_scalestep; spryscale += rw_scalestep;
} }
} }

View file

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

View file

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