diff --git a/src/d_player.h b/src/d_player.h index 0657f2fab..c4fb80a79 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -482,7 +482,8 @@ typedef struct player_s UINT8 boostcharge; // Charge during race start INT16 growshrinktimer; // > 0 = Big, < 0 = small - INT16 growcancel; // Duration of grow canceling + INT16 growcancel; // Duration of grow canceling + INT16 squishedtimer; // Duration of being squished UINT16 rocketsneakertimer; // Rocket Sneaker duration timer UINT16 invincibilitytimer; // Invincibility timer diff --git a/src/deh_tables.c b/src/deh_tables.c index 181bc3b3c..62a957170 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5506,7 +5506,6 @@ const char *const MOBJFLAG_LIST[] = { "RUNSPAWNFUNC", "DONTENCOREMAP", "PICKUPFROMBELOW", - "NOSQUISH", NULL }; @@ -6247,6 +6246,7 @@ struct int_const_s const INT_CONST[] = { // for P_DamageMobj //// Damage types {"DMG_NORMAL",DMG_NORMAL}, + {"DMG_SQUISH",DMG_SQUISH}, {"DMG_WIPEOUT",DMG_WIPEOUT}, {"DMG_EXPLODE",DMG_EXPLODE}, {"DMG_STING",DMG_STING}, diff --git a/src/info.c b/src/info.c index fd0e3708c..bf7bac537 100644 --- a/src/info.c +++ b/src/info.c @@ -22893,7 +22893,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_NOSQUISH, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/k_bot.c b/src/k_bot.c index 8b2d1b9f2..94a628d56 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -262,7 +262,7 @@ void K_UpdateMatchRaceBots(void) boolean K_PlayerUsesBotMovement(player_t *player) { if (player->exiting) - return true; + return false; if (player->bot) return true; @@ -278,11 +278,7 @@ boolean K_PlayerUsesBotMovement(player_t *player) boolean K_BotCanTakeCut(player_t *player) { if ( -#if 1 - K_TripwirePassConditions(player) != TRIPWIRE_NONE -#else - K_ApplyOffroad(player) == false -#endif + (K_TripwirePassConditions(player) != TRIPWIRE_NONE || K_ApplyOffroad(player) == false) || player->itemtype == KITEM_SNEAKER || player->itemtype == KITEM_ROCKETSNEAKER || player->itemtype == KITEM_INVINCIBILITY diff --git a/src/k_collide.c b/src/k_collide.c index c4a64a5ee..745fde687 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -842,8 +842,8 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) boolean stungT1 = false; boolean stungT2 = false; - t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)) || (t1->player->invincibilitytimer > 0); - t2Condition = (t2->scale > t1->scale + (mapobjectscale/8)) || (t2->player->invincibilitytimer > 0); + t1Condition = (t1->player->invincibilitytimer > 0); + t2Condition = (t2->player->invincibilitytimer > 0); if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true)) { @@ -860,6 +860,25 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT); return true; } + + t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)); + t2Condition = (t2->scale > t1->scale + (mapobjectscale/8)); + + if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true)) + { + K_DoPowerClash(t1->player, t2->player); + return false; + } + else if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_SQUISH); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_SQUISH); + return true; + } // Flame Shield dash damage t1Condition = flameT1; diff --git a/src/k_kart.c b/src/k_kart.c index 972f2043f..5386f8a5d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7,6 +7,7 @@ #include "k_kart.h" #include "d_player.h" #include "doomstat.h" +#include "info.h" #include "k_battle.h" #include "k_boss.h" #include "k_pwrlv.h" @@ -1396,6 +1397,11 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) return false; } } + + if ((mobj1->player && mobj1->player->squishedtimer > 0) + || (mobj2->player && mobj2->player->squishedtimer > 0)) + return false; + // Don't bump if you've recently bumped if (mobj1->player && mobj1->player->justbumped) @@ -3230,6 +3236,76 @@ static void K_RemoveGrowShrink(player_t *player) P_RestoreMusic(player); } + +INT32 K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, boolean crush) +{ + if (crush) + { + if ((player->invincibilitytimer > 0) || (player->growshrinktimer > 0) + || (player->hyudorotimer > 0) || (player->flashing > 0) || (player->squishedtimer > 0)) + { + K_DoInstashield(player); + return 0; + } + player->instashield = 15; + player->squishedtimer = TICRATE; + + // Reduce Shrink timer + if (player->growshrinktimer < 0) + { + player->growshrinktimer += TICRATE; + if (player->growshrinktimer >= 0) + K_RemoveGrowShrink(player); + } + + player->mo->flags |= MF_NOCLIP; + + player->instashield = 15; + + player->sneakertimer = 0; + player->driftboost = 0; + player->ringboost = 0; + player->glanceDir = 0; + player->pflags &= ~PF_GAINAX; + + K_PlayPainSound(player->mo, NULL); + P_PlayRinglossSound(player->mo); + P_PlayerRingBurst(player, 5); + + if (gametyperules & GTR_BUMPERS) + { + if (player->bumpers > 0) + player->bumpers--; + } + + return 0; + } + else + { + player->squishedtimer = TICRATE; + + // Reduce Shrink timer + if (player->growshrinktimer < 0) + { + player->growshrinktimer += TICRATE; + if (player->growshrinktimer >= 0) + K_RemoveGrowShrink(player); + } + + player->mo->flags |= MF_NOCLIP; + + player->instashield = 15; + if (cv_kartdebughuddrop.value && !modeattacking) + K_DropItems(player); + else + { + K_DropHnextList(player, false); + } + + return 5; + } +} + void K_ApplyTripWire(player_t *player, tripwirestate_t state) { if (state == TRIPSTATE_PASSED) @@ -3249,6 +3325,8 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A K_DirectorFollowAttack(player, inflictor, source); player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz = (117 * player->mo->momz) / 200; player->mo->momx = player->mo->momy = 0; player->spinouttype = KSPIN_EXPLOSION; @@ -3264,9 +3342,6 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A } } - if (player->mo->eflags & MFE_UNDERWATER) - player->mo->momz = (117 * player->mo->momz) / 200; - P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (P_IsDisplayPlayer(player)) @@ -4107,50 +4182,6 @@ void K_DriftDustHandling(mobj_t *spawner) } } -void K_Squish(mobj_t *mo) -{ - const fixed_t maxstretch = 4*FRACUNIT; - const fixed_t factor = 5 * mo->height / 4; - const fixed_t threshold = factor / 6; - - fixed_t old3dspeed = abs(mo->lastmomz); - fixed_t new3dspeed = abs(mo->momz); - - fixed_t delta = abs(old3dspeed - new3dspeed); - fixed_t grav = mo->height/3; - fixed_t add = abs(grav - new3dspeed); - - if (R_ThingIsFloorSprite(mo)) - return; - - if (delta < 2 * add && new3dspeed > grav) - delta += add; - - if (delta > threshold) - { - mo->spritexscale = - FRACUNIT + FixedDiv(delta, factor); - - if (mo->spritexscale > maxstretch) - mo->spritexscale = maxstretch; - - if (new3dspeed > old3dspeed || new3dspeed > grav) - { - mo->spritexscale = - FixedDiv(FRACUNIT, mo->spritexscale); - } - } - else - { - mo->spritexscale -= - (mo->spritexscale - FRACUNIT) - / (mo->spritexscale < FRACUNIT ? 8 : 3); - } - - mo->spriteyscale = - FixedDiv(FRACUNIT, mo->spritexscale); -} - static mobj_t *K_FindLastTrailMobj(player_t *player) { mobj_t *trail; @@ -6563,7 +6594,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->karthud[khud_timeovercam] = 0; // Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations. - if (player->spinouttimer != 0 || player->wipeoutslow != 0) + if (player->spinouttimer != 0 || player->wipeoutslow != 0 || player->squishedtimer != 0) { if (( player->spinouttype & KSPIN_IFRAMES ) == 0) player->flashing = 0; @@ -6745,6 +6776,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->stealingtimer--; else if (player->stealingtimer < 0) player->stealingtimer++; + + if (player->squishedtimer > 0) + player->squishedtimer--; if (player->justbumped > 0) player->justbumped--; @@ -6880,6 +6914,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_HandleDelayedHitByEm(player); K_RaceStart(player); + + // Squishing + // If a Grow player or a sector crushes you, get flattened instead of being killed. + if (player->squishedtimer <= 0) + { + player->mo->flags &= ~MF_NOCLIP; + } + else + { + player->mo->flags |= MF_NOCLIP; + player->mo->momx = 0; + player->mo->momy = 0; + } } void K_KartResetPlayerColor(player_t *player) @@ -9013,6 +9060,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_AdjustPlayerFriction(player); K_KartDrift(player, onground); + + // Quick Turning + // You can't turn your kart when you're not moving. + // So now it's time to burn some rubber! + if (player->speed < 2 && leveltime > starttime && player->cmd.buttons & BT_ACCELERATE && player->cmd.buttons & BT_BRAKE && player->cmd.turning != 0) + { + if (leveltime % 8 == 0) + S_StartSound(player->mo, sfx_s224); + } if (onground == false) { diff --git a/src/k_kart.h b/src/k_kart.h index e4b0cc05d..f5e8fb07d 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -74,7 +74,6 @@ void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_DriftDustHandling(mobj_t *spawner); -void K_Squish(mobj_t *mo); mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow); void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_DoSneaker(player_t *player, INT32 type); @@ -109,6 +108,7 @@ boolean K_SlopeResistance(player_t *player); tripwirepass_t K_TripwirePassConditions(player_t *player); boolean K_TripwirePass(player_t *player); boolean K_WaterRun(player_t *player); +INT32 K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, boolean crush); void K_ApplyTripWire(player_t *player, tripwirestate_t state); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberbanding); diff --git a/src/p_inter.c b/src/p_inter.c index b7c239b3c..f1f82510b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -127,7 +127,12 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) if (weapon == 2) { // Invulnerable - if (player->flashing > 0) + if (player->flashing > 0 + || player->spinouttimer > 0 + || player->squishedtimer > 0 + || player->invincibilitytimer > 0 + || player->growshrinktimer > 0 + || player->hyudorotimer > 0) return false; // Already have fake @@ -2051,6 +2056,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da case DMG_KARMA: ringburst = K_ExplodePlayer(player, inflictor, source); break; + case DMG_SQUISH: + ringburst = K_SquishPlayer(player, inflictor, source, false); + break; case DMG_WIPEOUT: if (P_IsDisplayPlayer(player)) P_StartQuake(32<type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT) @@ -1317,7 +1317,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // collide if (tmthing->z < thing->z && thing->momz < 0) - ;//P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH); + P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH); else { if ((K_KartSolidBounce(tmthing, thing) == true) && (thing->flags2 & MF2_AMBUSH)) @@ -4117,8 +4117,10 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) // Crush the object if (netgame && thing->player && thing->player->spectator) P_DamageMobj(thing, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators - else + else if (!thing->player) P_DamageMobj(thing, killer, killer, 1, DMG_CRUSHED); + else + P_DamageMobj(thing, NULL, NULL, 1, DMG_SQUISH); return true; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 28535ce56..8833bdf5f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2733,7 +2733,7 @@ void P_PlayerZMovement(mobj_t *mo) K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingpic : tmfloorpic)); // Get up if you fell. - if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0) + if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->squishedtimer == 0) { P_SetPlayerMobjState(mo, S_KART_STILL); } @@ -3663,17 +3663,6 @@ static void P_CheckFloatbobPlatforms(mobj_t *mobj) } } -static void P_SquishThink(mobj_t *mobj) -{ - if (!(mobj->flags & MF_NOSQUISH) && - !(mobj->eflags & MFE_SLOPELAUNCHED)) - { - K_Squish(mobj); - } - - mobj->lastmomz = mobj->momz; -} - static void P_PlayerMobjThinker(mobj_t *mobj) { I_Assert(mobj != NULL); @@ -3739,7 +3728,6 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->eflags &= ~MFE_JUSTHITFLOOR; } - P_SquishThink(mobj); K_UpdateTerrainOverlay(mobj); animonly: @@ -9269,7 +9257,6 @@ void P_MobjThinker(mobj_t *mobj) P_ButteredSlope(mobj); } - P_SquishThink(mobj); K_UpdateTerrainOverlay(mobj); if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health diff --git a/src/p_mobj.h b/src/p_mobj.h index 369d0cb51..975c1740e 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -159,10 +159,8 @@ typedef enum MF_DONTENCOREMAP = 1<<28, // Hitbox extends just as far below as above. MF_PICKUPFROMBELOW = 1<<29, - // Disable momentum-based squash and stretch. - MF_NOSQUISH = 1<<30, - // Free - // = (INT32)(1U<<31), + //free = 1<<30, + //free = (INT32)(1U<<31), // no more free slots, next up I suppose we can get rid of shit like MF_BOXICON? } mobjflag_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 9df75d741..6abce7af0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -257,6 +257,7 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].flashing); WRITEUINT16(save_p, players[i].spinouttimer); WRITEUINT8(save_p, players[i].spinouttype); + WRITEINT16(save_p, players[i].squishedtimer); WRITEUINT8(save_p, players[i].instashield); WRITEUINT8(save_p, players[i].wipeoutslow); WRITEUINT8(save_p, players[i].justbumped); @@ -541,6 +542,7 @@ static void P_NetUnArchivePlayers(void) players[i].flashing = READUINT16(save_p); players[i].spinouttimer = READUINT16(save_p); players[i].spinouttype = READUINT8(save_p); + players[i].squishedtimer = READINT16(save_p); players[i].instashield = READUINT8(save_p); players[i].wipeoutslow = READUINT8(save_p); players[i].justbumped = READUINT8(save_p); diff --git a/src/p_user.c b/src/p_user.c index f87b347bb..ed47dfbea 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -20,6 +20,7 @@ #include "d_event.h" #include "d_net.h" #include "g_game.h" +#include "info.h" #include "p_local.h" #include "r_fps.h" #include "r_main.h" @@ -454,7 +455,7 @@ UINT8 P_FindHighestLap(void) // boolean P_PlayerInPain(player_t *player) { - if (player->spinouttimer) + if (player->spinouttimer || player->squishedtimer) return true; return false; @@ -2144,7 +2145,14 @@ void P_MovePlayer(player_t *player) player->justDI = 0; } - if (player->carry == CR_SLIDING) + if (player->squishedtimer > 0) + { + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + player->mo->spriteyscale = (FRACUNIT / 4); + if (player->squishedtimer == 1) + player->mo->spriteyscale = FRACUNIT; + } + else if (player->carry == CR_SLIDING) { P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); player->drawangle -= ANGLE_22h; @@ -2171,8 +2179,7 @@ void P_MovePlayer(player_t *player) } else if (player->nocontrol && player->pflags & PF_SKIDDOWN) { - if (player->mo->state != &states[S_KART_SPINOUT]) - P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (((player->nocontrol + 5) % 20) < 10) player->drawangle += ANGLE_11hh; @@ -2345,7 +2352,7 @@ void P_MovePlayer(player_t *player) if (player->spectator) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); + K_SquishPlayer(player, NULL, NULL, true); // SRB2kart - we don't kill when squished, we squish when squished. if (player->playerstate == PST_DEAD) return;