diff --git a/src/d_player.h b/src/d_player.h index afa232991..ba83aae60 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -517,6 +517,8 @@ typedef struct player_s UINT8 kickstartaccel; + UINT8 stairjank; + #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/deh_tables.c b/src/deh_tables.c index 75b667e66..891f681bf 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4649,6 +4649,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DEBTSPIKEC", "S_DEBTSPIKED", "S_DEBTSPIKEE", + + // Sparks when driving on stairs + "S_JANKSPARK1", + "S_JANKSPARK2", + "S_JANKSPARK3", + "S_JANKSPARK4", }; // RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1", @@ -5452,6 +5458,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_DRIFTDUST", "MT_DRIFTELECTRICITY", "MT_DRIFTELECTRICSPARK", + "MT_JANKSPARK", "MT_ROCKETSNEAKER", // Rocket sneakers diff --git a/src/info.c b/src/info.c index eaa800ebc..5788d8945 100644 --- a/src/info.c +++ b/src/info.c @@ -543,6 +543,7 @@ char sprnames[NUMSPRITES + 1][5] = "DRWS", // Drift dust sparks "DREL", // Drift electricity "DRES", // Drift electric sparks + "JANK", // Stair janking sparks // Kart Items "RSHE", // Rocket sneaker @@ -5232,6 +5233,12 @@ state_t states[NUMSTATES] = {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKED}, // S_DEBTSPIKEC {SPR_DEBT, 6|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEE}, // S_DEBTSPIKED {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE1}, // S_DEBTSPIKEE + + // Sparks when driving on stairs + {SPR_JANK, 0, 1, {NULL}, 0, 0, S_JANKSPARK2}, // S_JANKSPARK1 + {SPR_JANK, FF_PAPERSPRITE|FF_FULLBRIGHT|FF_ANIMATE, 4, {NULL}, 3, 1, S_JANKSPARK3}, // S_JANKSPARK2 + {SPR_JANK, 0, 0, {A_SetCustomValue}, -1, 5, S_JANKSPARK4}, // S_JANKSPARK3 + {SPR_JANK, 0, 0, {A_ChangeAngleRelative}, 180, 180, S_JANKSPARK2}, // S_JANKSPARK4 }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = @@ -23532,6 +23539,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_JANKSPARK + -1, // doomednum + S_JANKSPARK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_FLOAT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_ROCKETSNEAKER -1, // doomednum S_ROCKETSNEAKER_L, // spawnstate diff --git a/src/info.h b/src/info.h index 697d206c6..d15d0dde0 100644 --- a/src/info.h +++ b/src/info.h @@ -1085,6 +1085,7 @@ typedef enum sprite SPR_DRWS, // Drift dust sparks SPR_DREL, // Drift electricity SPR_DRES, // Drift electric sparks + SPR_JANK, // Stair janking sparks // Kart Items SPR_RSHE, // Rocket sneaker @@ -5638,6 +5639,11 @@ typedef enum state S_DEBTSPIKED, S_DEBTSPIKEE, + S_JANKSPARK1, + S_JANKSPARK2, + S_JANKSPARK3, + S_JANKSPARK4, + S_FIRSTFREESLOT, S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1, NUMSTATES @@ -6460,6 +6466,7 @@ typedef enum mobj_type MT_DRIFTDUST, MT_DRIFTELECTRICITY, MT_DRIFTELECTRICSPARK, + MT_JANKSPARK, MT_ROCKETSNEAKER, diff --git a/src/k_kart.c b/src/k_kart.c index dedf9dddc..6b00758d1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1760,11 +1760,6 @@ static void K_SpawnBrakeDriftSparks(player_t *player) // Be sure to update the m sparks->renderflags |= RF_DONTDRAW; } -static fixed_t K_RandomFlip(fixed_t f) -{ - return ( ( leveltime & 1 ) ? f : -f ); -} - void K_SpawnDriftBoostClip(player_t *player) { mobj_t *clip; @@ -1789,7 +1784,7 @@ void K_SpawnDriftBoostClip(player_t *player) clip->momz += player->mo->momz; P_InstaThrust(clip, player->mo->angle + - K_RandomFlip(P_RandomRange(FRACUNIT/2, FRACUNIT)), + P_RandomFlip(P_RandomRange(FRACUNIT/2, FRACUNIT)), FixedMul(scale, player->speed)); } @@ -7856,6 +7851,11 @@ SINT8 K_Sliptiding(player_t *player) return player->drift ? 0 : player->aizdriftstrat; } +INT32 K_StairJankFlip(INT32 value) +{ + return P_AltFlip(value, 2); +} + static void K_KartSpindashDust(mobj_t *parent) { fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale); diff --git a/src/k_kart.h b/src/k_kart.h index ad254822c..756d5273f 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -85,6 +85,7 @@ boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); void K_UpdateSteeringValue(player_t *player, INT16 destSteering); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); INT32 K_GetKartDriftSparkValue(player_t *player); +INT32 K_StairJankFlip(INT32 value); INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage); void K_SpawnDriftBoostExplosion(player_t *player, int stage); void K_SpawnDriftElectricSparks(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index 44d656cf0..c9ba95245 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14650,4 +14650,4 @@ void A_InvincSparkleRotate(mobj_t *actor) actor->momz = actor->target->momz; // Give momentum for eventual interp builds idk. actor->angle += ANG1*10*(actor->extravalue2); // Arbitrary value, change this if you want, I suppose. -} \ No newline at end of file +} diff --git a/src/p_map.c b/src/p_map.c index 4a34ed7f0..1b18d11c3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2417,6 +2417,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) fixed_t radius = thing->radius; fixed_t thingtop; fixed_t startingonground = P_IsObjectOnGround(thing); + fixed_t stairjank = 0; + pslope_t *oldslope = thing->standingslope; floatok = false; // reset this to 0 at the start of each trymove call as it's only used here @@ -2488,6 +2490,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (maxstep > 0) { + const boolean flipped = + (thing->eflags & MFE_VERTICALFLIP) != 0; + thingtop = thing->z + thing->height; // Step up @@ -2495,6 +2500,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { if (tmfloorstep <= maxstep) { + if (!flipped) + stairjank = tmfloorstep; + thing->z = thing->floorz = tmfloorz; thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; @@ -2508,6 +2516,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { if (tmceilingstep <= maxstep) { + if (flipped) + stairjank = tmceilingstep; + thing->z = ( thing->ceilingz = tmceilingz ) - thing->height; thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; @@ -2524,6 +2535,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) { + if (flipped) + stairjank = (tmceilingz - thingtop); + thing->z = (thing->ceilingz = tmceilingz) - thing->height; thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; @@ -2531,6 +2545,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) { + if (!flipped) + stairjank = (thing->z - tmfloorz); + thing->z = thing->floorz = tmfloorz; thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; @@ -2617,6 +2634,28 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) else // don't set standingslope if you're not going to clip against it thing->standingslope = NULL; + /* FIXME: slope step down (even up) has some false + positives, so just ignore them entirely. */ + if (stairjank && !oldslope && !thing->standingslope && + thing->player && !thing->player->spectator) + { + /* use a shorter sound if not two tics have passed + * since the last step */ + S_StartSound(thing, thing->player->stairjank + >= 16 ? sfx_s23b : sfx_s268); + + if (!thing->player->stairjank) + { + mobj_t * spark = P_SpawnMobjFromMobj(thing, + 0, 0, 0, MT_JANKSPARK); + spark->fuse = 9; + spark->cusval = K_StairJankFlip(ANGLE_90); + P_SetTarget(&spark->target, thing); + } + + thing->player->stairjank = 17; + } + thing->x = x; thing->y = y; diff --git a/src/p_mobj.c b/src/p_mobj.c index f3711f819..ae7a7eaf4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6626,6 +6626,21 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags |= RF_DONTDRAW; } break; + case MT_JANKSPARK: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return false; + } + if (mobj->fuse == 1 && mobj->target->player && + mobj->target->player->stairjank >= 8) + { + mobj->fuse = 9; + } + P_TeleportMove(mobj, mobj->target->x, + mobj->target->y, mobj->target->z); + mobj->angle = mobj->target->angle + mobj->cusval; + break; case MT_PLAYERRETICULE: if (!mobj->target || !mobj->target->health) { diff --git a/src/p_slopes.c b/src/p_slopes.c index 1749e2369..d1e8f5f54 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -848,6 +848,11 @@ void P_SlopeLaunch(mobj_t *mo) //CONS_Printf("Launched off of slope.\n"); mo->standingslope = NULL; + + if (mo->player) + { + mo->player->stairjank = 0; // fuck you + } } // diff --git a/src/p_tick.c b/src/p_tick.c index 6157d0bda..5e92649cb 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -36,6 +36,11 @@ tic_t leveltime; +INT32 P_AltFlip(INT32 n, tic_t tics) +{ + return leveltime % (2 * tics) < tics ? n : -(n); +} + // // THINKERS // All thinkers should be allocated by Z_Calloc diff --git a/src/p_tick.h b/src/p_tick.h index 1fb88f3f2..e90f1be31 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -30,4 +30,8 @@ void P_DoTeamscrambling(void); void P_RemoveThinkerDelayed(thinker_t *thinker); //killed mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98 +// Negate the value for tics +INT32 P_AltFlip(INT32 value, tic_t tics); +#define P_RandomFlip(value) P_AltFlip(value, 1) + #endif diff --git a/src/p_user.c b/src/p_user.c index 3cd0bba5c..6dc2164e4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1677,12 +1677,22 @@ static void P_3dMovement(player_t *player) // Get the old momentum; this will be needed at the end of the function! -SH oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - if (player->drift != 0) - movepushangle = player->mo->angle-(ANGLE_45/5)*player->drift; - else if (player->spinouttimer || player->wipeoutslow) // if spun out, use the boost angle + if (player->stairjank > 8 && leveltime & 3) + { + movepushangle = K_MomentumAngle(player->mo); + } + else if (player->drift != 0) + { + movepushangle = player->mo->angle - (ANGLE_45/5) * player->drift; + } + else if (player->spinouttimer || player->wipeoutslow) // if spun out, use the boost angle + { movepushangle = (angle_t)player->boostangle; + } else + { movepushangle = player->mo->angle; + } // cmomx/cmomy stands for the conveyor belt speed. if (player->onconveyor == 2) // Wind/Current @@ -4486,14 +4496,19 @@ void P_PlayerThink(player_t *player) player->typing_duration = 0; } + if (player->stairjank > 0) + { + player->stairjank--; + } + K_KartPlayerThink(player, cmd); // SRB2kart DoABarrelRoll(player); - LUAh_PlayerThink(player); - if (player->carry == CR_SLIDING) player->carry = CR_NONE; + + LUAh_PlayerThink(player); } // diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index ad401d91d..096b678ea 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -15,6 +15,7 @@ #include "w_wad.h" #include "r_main.h" // R_PointToAngle #include "k_kart.h" // K_Sliptiding +#include "p_tick.h" #ifdef ROTSPRITE fixed_t rollcosang[ROTANGLES]; @@ -32,16 +33,14 @@ angle_t R_GetPitchRollAngle(mobj_t *mobj) return rollOrPitch; } -angle_t R_SpriteRotationAngle(mobj_t *mobj) +static angle_t R_PlayerSpriteRotation(player_t *player) { - angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y); - angle_t angleDelta = (viewingAngle - mobj->angle); + angle_t viewingAngle = R_PointToAngle(player->mo->x, player->mo->y); + angle_t angleDelta = (viewingAngle - player->mo->angle); - angle_t sliptideLift = mobj->player - ? mobj->player->aizdrifttilt : 0; + angle_t sliptideLift = player->aizdrifttilt; - angle_t rollOrPitch = R_GetPitchRollAngle(mobj); - angle_t rollAngle = (rollOrPitch + mobj->rollangle); + angle_t rollAngle = 0; if (sliptideLift) { @@ -52,6 +51,25 @@ angle_t R_SpriteRotationAngle(mobj_t *mobj) FixedMul(sliptideLift, FINECOSINE(angleDelta >> ANGLETOFINESHIFT)); } + if (player->stairjank) + { + rollAngle += K_StairJankFlip(ANGLE_11hh / 2 / + (17 / player->stairjank)); + } + + return rollAngle; +} + +angle_t R_SpriteRotationAngle(mobj_t *mobj) +{ + angle_t rollOrPitch = R_GetPitchRollAngle(mobj); + angle_t rollAngle = (rollOrPitch + mobj->rollangle); + + if (mobj->player) + { + rollAngle += R_PlayerSpriteRotation(mobj->player); + } + return rollAngle; }