diff --git a/src/k_terrain.c b/src/k_terrain.c index d94acb886..1bbef1bcb 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -511,6 +511,102 @@ 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. +--------------------------------------------------*/ +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; + size_t i; + + 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; + + if (numParticles == 1) + { + // Random angle. + pushAngle = P_RandomRange(0, ANGLE_MAX); + } + + dust = P_SpawnMobjFromMobj( + mo, + (12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)), + (12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)), + 0, s->mobjType + ); + + P_SetTarget(&dust->target, mo); + dust->angle = pushAngle; + + dust->destscale = FixedMul(mo->scale, s->scale); + P_SetScale(dust, dust->destscale); + + dust->momx = mo->momx / 2; + 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); + + if (s->color != SKINCOLOR_NONE) + { + dust->color = s->color; + } + + if (s->sfx != sfx_None) + { + S_StartSound(mo, s->sfx); + } + } +} + +/*-------------------------------------------------- + void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) + + See header file for description. +--------------------------------------------------*/ +void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) +{ + t_splash_t *s = NULL; + + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + + if (mo->terrain == NULL || mo->terrain->splashID == SIZE_MAX) + { + // No impact for this terrain type. + return; + } + else + { + s = K_GetSplashByIndex(mo->terrain->splashID); + } + + if (s == NULL || s->mobjType == MT_NULL || s->numParticles == 0) + { + // No particles to spawn. + return; + } + + // Idea for later: if different spawning styles are desired, + // we can put a switch case here! + K_SpawnSplashParticles(mo, s, impact); +} + /*-------------------------------------------------- static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) @@ -522,6 +618,8 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) angle_t pushAngle = ANGLE_MAX; angle_t tireAngle = ANGLE_MAX; fixed_t momentum = INT32_MAX; + fixed_t momH = INT32_MAX; + fixed_t momV = INT32_MAX; if (mo->player != NULL) { @@ -562,17 +660,20 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) dust->momy = mo->momy; dust->momz = P_GetMobjZMovement(mo) / 2; - momentum = P_AproxDistance(mo->momx, mo->momy) / 2; - dust->momx += FixedMul(momentum, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); - dust->momy += FixedMul(momentum, FINESINE(pushAngle >> ANGLETOFINESHIFT)); - dust->momz += (momentum / 16) * P_MobjFlip(mo); + momentum = P_AproxDistance(mo->momx, mo->momy); + momH = FixedMul(momentum, fs->pushH); + momV = FixedMul(momentum, fs->pushV); + + dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momy += FixedMul(momH, FINESINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momz += (momV / 16) * P_MobjFlip(mo); if (fs->color != SKINCOLOR_NONE) { dust->color = fs->color; } - if (fs->sfx != sfx_None && (leveltime % 6 == 0)) + if ((fs->sfx != sfx_None) && (fs->sfxFreq > 0) && (leveltime % fs->sfxFreq == 0)) { S_StartSound(mo, fs->sfx); } @@ -662,6 +763,13 @@ static void K_SplashDefaults(t_splash_t *splash) splash->sfx = sfx_None; splash->scale = FRACUNIT; splash->color = SKINCOLOR_NONE; + + splash->pushH = FRACUNIT/4; + splash->pushV = FRACUNIT/64; + splash->spread = 2; + splash->cone = ANGLE_11hh; + + splash->numParticles = 8; } /*-------------------------------------------------- @@ -735,6 +843,13 @@ static void K_FootstepDefaults(t_footstep_t *footstep) footstep->sfx = sfx_None; footstep->scale = FRACUNIT; footstep->color = SKINCOLOR_NONE; + + footstep->pushH = FRACUNIT/2; + footstep->pushV = FRACUNIT/32; + footstep->spread = 2; + footstep->cone = ANGLE_11hh; + + footstep->sfxFreq = 6; } /*-------------------------------------------------- diff --git a/src/k_terrain.h b/src/k_terrain.h index 32921d393..e4055be23 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -33,6 +33,13 @@ typedef struct t_splash_s UINT16 sfx; // Sound to play. fixed_t scale; // Thing scale multiplier. UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. + + fixed_t pushH; // Push-out horizontal multiplier. + fixed_t pushV; // Push-out vertical multiplier. + fixed_t spread; // Randomized spread distance. + angle_t cone; // Randomized angle of the push-out. + + UINT8 numParticles; // Number of particles to spawn. } t_splash_t; typedef struct t_footstep_s @@ -46,6 +53,13 @@ typedef struct t_footstep_s UINT16 sfx; // Sound to play. fixed_t scale; // Thing scale multiplier. UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. + + fixed_t pushH; // Push-out horizontal multiplier. + fixed_t pushV; // Push-out vertical multiplier. + fixed_t spread; // Randomized spread distance. + angle_t cone; // Randomized angle of the push-out. + + tic_t sfxFreq; // How frequently to play the sound. } t_footstep_t; typedef enum @@ -394,6 +408,21 @@ void K_ProcessTerrainEffect(mobj_t *mo); void K_SetDefaultFriction(mobj_t *mo); +/*-------------------------------------------------- + void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact); + + Spawns the splash particles for an object's + terrain type. Intended to be called when hitting a floor. + + Input Arguments:- + mo - The object to spawn a splash for. + + Return:- + None +--------------------------------------------------*/ +void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact); + + /*-------------------------------------------------- void K_HandleFootstepParticles(mobj_t *mo); diff --git a/src/p_local.h b/src/p_local.h index 7ddf59875..b9802b106 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -168,7 +168,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart #define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP) boolean P_InQuicksand(mobj_t *mo); -boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); +boolean P_PlayerHitFloor(player_t *player, boolean fromAir); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); diff --git a/src/p_user.c b/src/p_user.c index 5a065e8d5..9ba08e7d4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -52,6 +52,7 @@ #include "k_respawn.h" #include "k_bot.h" #include "k_grandprix.h" +#include "k_terrain.h" // K_SpawnSplashForMobj #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -1274,17 +1275,18 @@ void P_DoPlayerExit(player_t *player) // // Handles player hitting floor surface. // Returns whether to clip momz. -boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) +boolean P_PlayerHitFloor(player_t *player, boolean fromAir) { boolean clipmomz; - (void)dorollstuff; - I_Assert(player->mo != NULL); clipmomz = !(P_CheckDeathPitCollide(player->mo)); - // SRB2Kart: removed lots of really vanilla-specific code here + if (fromAir == true && clipmomz == true) + { + K_SpawnSplashForMobj(player->mo, abs(player->mo->momz)); + } return clipmomz; }