From 14b379fd2741e658672adddb0a9039f21d81148a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 23 Aug 2020 21:33:47 -0400 Subject: [PATCH 1/6] Cherry-pick 4eb69a664 --- src/d_clisrv.c | 8 +++ src/d_clisrv.h | 4 ++ src/d_player.h | 4 ++ src/dehacked.c | 2 +- src/k_collide.c | 106 +++++++++++++++++++++++++++++++- src/k_collide.h | 1 + src/k_kart.c | 144 ++++++++++++++++++++++---------------------- src/k_kart.h | 2 +- src/lua_baselib.c | 6 +- src/lua_playerlib.c | 12 ++++ src/p_inter.c | 9 +-- src/p_local.h | 2 +- src/p_map.c | 92 ++-------------------------- src/p_mobj.c | 7 ++- src/p_saveg.c | 8 +++ src/p_spec.c | 3 - src/p_user.c | 48 ++++++++++----- 17 files changed, 267 insertions(+), 191 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e4e19d259..036170c29 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -616,6 +616,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->airtime = (tic_t)LONG(players[i].airtime); + rsp->tumbleBounces = players[i].tumbleBounces; + rsp->tumbleHeight = SHORT(players[i].tumbleHeight); + rsp->tumbleLastBounce = players[i].tumbleLastBounce; + // respawnvars_t rsp->respawn_state = players[i].respawn.state; rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx); @@ -759,6 +763,10 @@ static void resynch_read_player(resynch_pak *rsp) players[i].airtime = (tic_t)LONG(rsp->airtime); + players[i].tumbleBounces = rsp->tumbleBounces; + players[i].tumbleHeight = SHORT(rsp->tumbleHeight); + players[i].tumbleLastBounce = (boolean)rsp->tumbleLastBounce; + // respawnvars_t players[i].respawn.state = rsp->respawn_state; players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 013990325..05d12250b 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -281,6 +281,10 @@ typedef struct INT32 kartstuff[NUMKARTSTUFF]; tic_t airtime; + UINT8 tumbleBounces; + UINT16 tumbleHeight; + boolean tumbleLastBounce; + // respawnvars_t UINT8 respawn_state; fixed_t respawn_pointx; diff --git a/src/d_player.h b/src/d_player.h index f4683a62b..1d71668f4 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -553,6 +553,10 @@ typedef struct player_s UINT16 followercolor; // Kart: Used to store the follower colour the player wishes to use mobj_t *follower; // Kart: This is the follower object we have. (If any) + UINT8 tumbleBounces; + UINT16 tumbleHeight; + boolean tumbleLastBounce; + // UINT32 charflags; // Extra abilities/settings for skins (combinable stuff) diff --git a/src/dehacked.c b/src/dehacked.c index 7f6be7e6d..471499c5c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11273,7 +11273,7 @@ struct { {"DMG_NORMAL",DMG_NORMAL}, {"DMG_WIPEOUT",DMG_WIPEOUT}, {"DMG_EXPLODE",DMG_EXPLODE}, - {"DMG_SQUISH",DMG_SQUISH}, + {"DMG_TUMBLE",DMG_TUMBLE}, {"DMG_STING",DMG_STING}, //// Death types {"DMG_INSTAKILL",DMG_INSTAKILL}, diff --git a/src/k_collide.c b/src/k_collide.c index 7fbe17603..0f2361062 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -380,10 +380,112 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) if (t1->health) P_KillMobj(t1, t2, t2, DMG_NORMAL); - /*if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0 + /* + if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0 || t2->player->kartstuff[k_growshrinktimer] > 0)) - return true;*/ + return true; + */ K_KartBouncing(t2, t1, false, true); return false; } + +boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) +{ + boolean t1Condition = false; + boolean t2Condition = false; + boolean stung = false; + + // Grow damage + t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)); + t2Condition = (t2->scale > t1->scale + (mapobjectscale/8)); + + if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE); + return true; + } + + // Invincibility damage + t1Condition = (t1->player->kartstuff[k_invincibilitytimer] > 0); + t2Condition = (t2->player->kartstuff[k_invincibilitytimer] > 0); + + if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE); + return true; + } + + // Flame Shield dash damage + t1Condition = (t1->player->kartstuff[k_flamedash] > 0 && t1->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD); + t2Condition = (t2->player->kartstuff[k_flamedash] > 0 && t2->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD); + + if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT); + return true; + } + + // Battle Mode Sneaker damage + // (Pogo Spring damage is handled in head-stomping code) + if (gametyperules & GTR_BUMPERS) + { + t1Condition = (t1->player->kartstuff[k_sneakertimer] > 0 && t1->player->powers[pw_flashing] != 0); + t2Condition = (t2->player->kartstuff[k_sneakertimer] > 0 && t2->player->powers[pw_flashing] != 0); + + if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT|DMG_STEAL); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT|DMG_STEAL); + return true; + } + } + + // Ring sting, this is a bit more unique + t1Condition = (K_GetShieldFromItem(t2->player->kartstuff[k_itemtype]) == KSHIELD_NONE); + t2Condition = (K_GetShieldFromItem(t1->player->kartstuff[k_itemtype]) == KSHIELD_NONE); + + if (t1Condition == true) + { + if (t2->player->rings <= 0) + { + P_DamageMobj(t2, t1, t1, 1, DMG_STING); + stung = true; + } + + P_PlayerRingBurst(t2->player, 1); + stung = true; + } + + if (t2Condition == true) + { + if (t1->player->rings <= 0) + { + P_DamageMobj(t1, t2, t2, 1, DMG_STING); + stung = true; + } + + P_PlayerRingBurst(t2->player, 1); + } + + return stung; +} diff --git a/src/k_collide.h b/src/k_collide.h index 86f643b3f..75a9404f8 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -12,5 +12,6 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); +boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2); #endif diff --git a/src/k_kart.c b/src/k_kart.c index e35b9ff56..26a878679 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -976,7 +976,7 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against) return weight; if (against && !P_MobjWasRemoved(against) && against->player - && ((!against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) // You're in spinout + && ((!P_PlayerInPain(against->player) && P_PlayerInPain(mobj->player)) // You're hurt || (against->player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD && mobj->player->kartstuff[k_itemtype] != KITEM_BUBBLESHIELD))) // They have a Bubble Shield { weight = 0; // This player does not cause any bump action @@ -1056,24 +1056,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) || (mobj2->player && mobj2->player->respawn.state != RESPAWNST_NONE)) return; - { // Don't bump if you're flashing - INT32 flash; + // Don't bump if you're flashing + if (mobj1->player && mobj1->player->powers[pw_flashing] > 0 && !P_PlayerInPain(mobj1->player)) + { + INT32 flash = K_GetKartFlashing(mobj1->player); + if (mobj1->player->powers[pw_flashing] < flash) + mobj1->player->powers[pw_flashing]++; + return; + } - flash = K_GetKartFlashing(mobj1->player); - if (mobj1->player && mobj1->player->powers[pw_flashing] > 0 && mobj1->player->powers[pw_flashing] < flash) - { - if (mobj1->player->powers[pw_flashing] < flash-1) - mobj1->player->powers[pw_flashing]++; - return; - } - - flash = K_GetKartFlashing(mobj2->player); - if (mobj2->player && mobj2->player->powers[pw_flashing] > 0 && mobj2->player->powers[pw_flashing] < flash) - { - if (mobj2->player->powers[pw_flashing] < flash-1) - mobj2->player->powers[pw_flashing]++; - return; - } + if (mobj2->player && mobj2->player->powers[pw_flashing] > 0 && !P_PlayerInPain(mobj2->player)) + { + INT32 flash = K_GetKartFlashing(mobj2->player); + if (mobj2->player->powers[pw_flashing] < flash) + mobj2->player->powers[pw_flashing]++; + return; } // Don't bump if you've recently bumped @@ -1199,15 +1196,6 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]); //mobj1->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type } - else if (mobj2->player // Player VS player bumping only - && (K_GetShieldFromItem(mobj1->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields - { - if (mobj1->player->rings <= 0) - { - P_DamageMobj(mobj1, mobj2, mobj2, 1, DMG_STING); - } - P_PlayerRingBurst(mobj1->player, 1); - } } if (mobj2->player) @@ -1223,15 +1211,6 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]); //mobj2->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type } - else if (mobj1->player // Player VS player bumping only - && (K_GetShieldFromItem(mobj2->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields - { - if (mobj2->player->rings <= 0) - { - P_DamageMobj(mobj2, mobj1, mobj1, 1, DMG_STING); - } - P_PlayerRingBurst(mobj2->player, 1); - } } } @@ -2583,25 +2562,64 @@ static void K_RemoveGrowShrink(player_t *player) P_RestoreMusic(player); } -void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source) +void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) { - (void)inflictor; (void)source; - player->kartstuff[k_squishedtimer] = TICRATE; + player->tumbleBounces = 1; - // Reduce Shrink timer - if (player->kartstuff[k_growshrinktimer] < 0) + player->mo->momx = 2 * player->mo->momx / 3; + player->mo->momy = 2 * player->mo->momy / 3; + + player->tumbleHeight = 30; + + if (inflictor && !P_MobjWasRemoved(inflictor)) { - player->kartstuff[k_growshrinktimer] += TICRATE; - if (player->kartstuff[k_growshrinktimer] >= 0) - K_RemoveGrowShrink(player); + const fixed_t infSpeed = P_AproxDistance(inflictor->momx, inflictor->momy) / 2; + player->tumbleHeight += (infSpeed / player->mo->scale); } - player->mo->flags |= MF_NOCLIP; + player->mo->momz = player->tumbleHeight * player->mo->scale * P_MobjFlip(player->mo); - if (player->mo->state != &states[S_KART_SQUISH]) // Squash - P_SetPlayerMobjState(player->mo, S_KART_SQUISH); + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + + if (P_IsDisplayPlayer(player)) + P_StartQuake(64<tumbleBounces++; + player->tumbleHeight = (player->tumbleHeight * 4) / 5; + + if (player->tumbleHeight < 10) + { + // 10 minimum bounce height + player->tumbleHeight = 10; + } + + if (player->tumbleBounces > 4 && player->tumbleHeight < 30) + { + // Leave tumble state when below 30 height, and have bounced off the ground enough + + if (player->tumbleLastBounce == true) + { + // End tumble state + player->tumbleBounces = 0; + return; + } + else + { + // One last bounce at the minimum height, to reset the animation + player->tumbleHeight = 10; + player->tumbleLastBounce = true; + } + } + + player->mo->momx = player->mo->momx / 2; + player->mo->momy = player->mo->momy / 2; + + player->mo->momz = player->tumbleHeight * player->mo->scale * P_MobjFlip(player->mo); } void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer @@ -2630,8 +2648,6 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b if (P_IsDisplayPlayer(player)) P_StartQuake(64<powers[pw_flashing] = 0; } // Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations. - else if (player->kartstuff[k_spinouttimer] != 0 - || player->kartstuff[k_wipeoutslow] != 0 - || player->kartstuff[k_squishedtimer] != 0) + else if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0) { player->powers[pw_flashing] = K_GetKartFlashing(player); } @@ -5776,22 +5790,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_stolentimer]) player->kartstuff[k_stolentimer]--; - if (player->kartstuff[k_squishedtimer]) - { - player->kartstuff[k_squishedtimer]--; - - if ((player->kartstuff[k_squishedtimer] == 0) && !(player->pflags & PF_NOCLIP)) - { - player->mo->flags &= ~MF_NOCLIP; - } - } - if (player->kartstuff[k_justbumped] > 0) player->kartstuff[k_justbumped]--; if (player->kartstuff[k_tiregrease]) player->kartstuff[k_tiregrease]--; + if (player->tumbleBounces > 0) + { + if (P_IsObjectOnGround(player->mo) && player->mo->momz * P_MobjFlip(player->mo) <= 0) + K_HandleTumbleBounce(player); + } + // This doesn't go in HUD update because it has potential gameplay ramifications if (player->karthud[khud_itemblink] && player->karthud[khud_itemblink]-- <= 0) { @@ -7774,16 +7784,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads K_KartSpindash(player); - // Squishing - // If a Grow player or a sector crushes you, get flattened instead of being killed. - - if (player->kartstuff[k_squishedtimer] > 0) - { - //player->mo->flags |= MF_NOCLIP; - player->mo->momx = 0; - player->mo->momy = 0; - } - // Play the starting countdown sounds if (player == &players[g_localplayers[0]]) // Don't play louder in splitscreen { diff --git a/src/k_kart.h b/src/k_kart.h index 408ed3303..e26e3de86 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,7 +45,7 @@ void K_DoInstashield(player_t *player); void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted); void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source); void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type); -void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source); +void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_StealBumper(player_t *player, player_t *victim); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 42e433254..81978546d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3400,7 +3400,7 @@ static int lib_kSpinPlayer(lua_State *L) return 0; } -static int lib_kSquishPlayer(lua_State *L) +static int lib_kTumblePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobj_t *inflictor = NULL; @@ -3412,7 +3412,7 @@ static int lib_kSquishPlayer(lua_State *L) inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - K_SquishPlayer(player, inflictor, source); + K_TumblePlayer(player, inflictor, source); return 0; } @@ -3916,7 +3916,7 @@ static luaL_Reg lib[] = { {"K_DoInstashield",lib_kDoInstashield}, {"K_SpawnBattlePoints",lib_kSpawnBattlePoints}, {"K_SpinPlayer",lib_kSpinPlayer}, - {"K_SquishPlayer",lib_kSquishPlayer}, + {"K_TumblePlayer",lib_kTumblePlayer}, {"K_ExplodePlayer",lib_kExplodePlayer}, {"K_StealBumper",lib_kStealBumper}, {"K_SpawnKartExplosion",lib_kSpawnKartExplosion}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 8a0113f08..812135f17 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -212,6 +212,12 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); + else if (fastcmp(field,"tumbleBounces")) + lua_pushinteger(L, plr->tumbleBounces); + else if (fastcmp(field,"tumbleHeight")) + lua_pushinteger(L, plr->tumbleHeight); + else if (fastcmp(field,"tumbleLastBounce")) + lua_pushboolean(L, plr->tumbleLastBounce); else if (fastcmp(field,"pflags")) lua_pushinteger(L, plr->pflags); else if (fastcmp(field,"panim")) @@ -499,6 +505,12 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"airtime")) plr->airtime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"tumbleBounces")) + plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"tumbleHeight")) + plr->tumbleHeight = (UINT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"tumbleLastBounce")) + plr->tumbleLastBounce = luaL_checkboolean(L, 3); else if (fastcmp(field,"kartspeed")) plr->kartspeed = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"kartweight")) diff --git a/src/p_inter.c b/src/p_inter.c index efa3d3eaa..7d47599ae 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -282,7 +282,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!special->target->player->kartstuff[k_comebackmode]) { - if (player->kartstuff[k_growshrinktimer] || player->kartstuff[k_squishedtimer] + if (player->kartstuff[k_growshrinktimer] || player->kartstuff[k_hyudorotimer] || P_PlayerInPain(player) || player->kartstuff[k_invincibilitytimer] || player->powers[pw_flashing]) return; @@ -465,8 +465,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } // no interaction - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0 - || player->kartstuff[k_squishedtimer] > 0 || P_PlayerInPain(player)) + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0 || P_PlayerInPain(player)) return; // attach to player! @@ -1918,13 +1917,15 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_KartPainEnergyFling(player); ringburst = 0; break; + case DMG_TUMBLE: + K_TumblePlayer(player, inflictor, source); + break; case DMG_EXPLODE: K_ExplodePlayer(player, inflictor, source); break; case DMG_WIPEOUT: if (P_IsDisplayPlayer(player)) P_StartQuake(32<player && thing->player - // Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person. - && !(thing->z + thing->height < tmthing->z || thing->z > tmthing->z + tmthing->height)) - { - if (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam) - { - if (tmthing->scale > thing->scale + (mapobjectscale/8)) // SRB2kart - Handle squishes first! - { - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SQUISH); - } - else if (thing->scale > tmthing->scale + (mapobjectscale/8)) - { - P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH); - } - else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility! - { - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT); - } - else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer]) - { - P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); - } - else if ((tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) - && !(thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield! - { - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT); - } - else if ((thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) - && !(tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) - { - P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); - } - } - } - if (thing->player) { - // Doesn't matter what gravity player's following! Just do your stuff in YOUR direction only - if (tmthing->eflags & MFE_VERTICALFLIP - && (tmthing->z + tmthing->height + tmthing->momz < thing->z - || tmthing->z + tmthing->height + tmthing->momz >= thing->z + thing->height)) - ; - else if (!(tmthing->eflags & MFE_VERTICALFLIP) - && (tmthing->z + tmthing->momz > thing->z + thing->height - || tmthing->z + tmthing->momz <= thing->z)) - ; - else if (P_IsObjectOnGround(thing) - && !P_IsObjectOnGround(tmthing) // Don't crush if the monitor is on the ground... - && (tmthing->flags & MF_SOLID)) - { - if (tmthing->flags & (MF_MONITOR|MF_PUSHABLE)) - { - // Objects kill you if it falls from above. - if (thing != tmthing->target) - P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_CRUSHED); - - tmthing->momz = -tmthing->momz/2; // Bounce, just for fun! - // The tmthing->target allows the pusher of the object - // to get the point if he topples it on an opponent. - } - } - if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) P_DoFanAndGasJet(tmthing, thing); } @@ -1299,10 +1238,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->player->kartstuff[k_squishedtimer] || thing->player->kartstuff[k_hyudorotimer] - || thing->player->kartstuff[k_justbumped] || thing->scale > tmthing->scale + (mapobjectscale/8) - || tmthing->player->kartstuff[k_squishedtimer] || tmthing->player->kartstuff[k_hyudorotimer] - || tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (mapobjectscale/8)) + if (thing->player->kartstuff[k_hyudorotimer] || tmthing->player->kartstuff[k_hyudorotimer]) { return true; } @@ -1337,19 +1273,8 @@ static boolean PIT_CheckThing(mobj_t *thing) P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } - if ((gametyperules & GTR_BUMPERS)) - { - if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible - { - P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); - } - else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing])) - { - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL); - } - } - K_KartBouncing(mo1, mo2, zbounce, false); + K_PvPTouchDamage(mo1, mo2); } return true; @@ -1429,22 +1354,13 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // continue to squish - if (tmthing->player->kartstuff[k_squishedtimer]) - { - tmthing->player->kartstuff[k_squishedtimer] = 2*TICRATE; - tmthing->player->powers[pw_flashing] = K_GetKartFlashing(tmthing->player); - return true; - } - // no interaction - if (tmthing->player->powers[pw_flashing] > 0 || tmthing->player->kartstuff[k_hyudorotimer] > 0 - || tmthing->player->kartstuff[k_spinouttimer] > 0) //|| tmthing->player->kartstuff[k_squishedtimer] > 0 + if (tmthing->player->powers[pw_flashing] > 0 || tmthing->player->kartstuff[k_hyudorotimer] > 0 || tmthing->player->kartstuff[k_spinouttimer] > 0) return true; // collide if (tmthing->z < thing->z && thing->momz < 0) - K_SquishPlayer(tmthing->player, thing, thing); + P_DamageMobj(tmthing, thing, thing, 1, DMG_TUMBLE); else { if (thing->flags2 & MF2_AMBUSH) diff --git a/src/p_mobj.c b/src/p_mobj.c index 42e61a918..4d443cea2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1105,6 +1105,11 @@ fixed_t P_GetMobjGravity(mobj_t *mo) { gravityadd = (4*gravityadd)/3; } + + if (mo->player->tumbleBounces > 0) + { + gravityadd = (5*gravityadd)/2; + } } else { @@ -2605,7 +2610,7 @@ void P_PlayerZMovement(mobj_t *mo) mo->z = mo->floorz; // Get up if you fell. - if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->kartstuff[k_squishedtimer] == 0) + if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0) P_SetPlayerMobjState(mo, S_KART_STILL); if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { diff --git a/src/p_saveg.c b/src/p_saveg.c index e8309f8d5..7c9a3a96f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -256,6 +256,10 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); WRITEUINT32(save_p, players[i].airtime); + WRITEUINT8(save_p, players[i].tumbleBounces); + WRITEUINT16(save_p, players[i].tumbleHeight); + WRITEUINT8(save_p, players[i].tumbleLastBounce); + // respawnvars_t WRITEUINT8(save_p, players[i].respawn.state); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -441,6 +445,10 @@ static void P_NetUnArchivePlayers(void) players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p); players[i].airtime = READUINT32(save_p); + players[i].tumbleBounces = READUINT8(save_p); + players[i].tumbleHeight = READUINT16(save_p); + players[i].tumbleLastBounce = (boolean)READUINT8(save_p); + // respawnvars_t players[i].respawn.state = READUINT8(save_p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 3d0eddd2e..c0ed5b63b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4832,9 +4832,6 @@ DoneSection2: if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) break; - if (player->powers[pw_ignorelatch] & (1<<15)) - break; - // Find line #3 tagged to this sector lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1); diff --git a/src/p_user.c b/src/p_user.c index 6c6c0578a..c294d3f64 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -461,7 +461,10 @@ UINT8 P_FindHighestLap(void) // boolean P_PlayerInPain(player_t *player) { - if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer] || player->respawn.state != RESPAWNST_NONE) + if (player->respawn.state != RESPAWNST_NONE) + return true; + + if (player->kartstuff[k_spinouttimer] || player->tumbleBounces > 0) return true; if (gametyperules & GTR_KARMA) @@ -2157,18 +2160,35 @@ void P_MovePlayer(player_t *player) P_3dMovement(player); // Kart frames - if (player->kartstuff[k_squishedtimer] > 0) + if (player->tumbleBounces > 0) { - P_SetPlayerMobjState(player->mo, S_KART_SQUISH); + fixed_t playerSpeed = P_AproxDistance(player->mo->momx, player->mo->momy); // maybe momz too? + + const UINT8 minSpinSpeed = 4; + UINT8 spinSpeed = max(minSpinSpeed, min(8 + minSpinSpeed, (playerSpeed / player->mo->scale) * 2)); + + UINT8 rollSpeed = max(1, min(8, player->tumbleHeight / 10)); + + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + player->drawangle -= (ANGLE_11hh * spinSpeed); + + player->mo->rollangle -= (ANGLE_11hh * rollSpeed); + + if (player->tumbleLastBounce == true) + { + if (abs((signed)player->mo->rollangle) < ANGLE_22h) + player->mo->rollangle = 0; + } } else if (player->pflags & PF_SLIDING) { P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); player->drawangle -= ANGLE_22h; + player->mo->rollangle = 0; } else if (player->kartstuff[k_spinouttimer] > 0) { - INT32 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8)); + UINT8 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8)); P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); @@ -2176,6 +2196,8 @@ void P_MovePlayer(player_t *player) player->drawangle = player->mo->angle; // Face forward at the end of the animation else player->drawangle -= (ANGLE_11hh * speed); + + player->mo->rollangle = 0; } else if (player->pflags & PF_FAULT) { @@ -2185,6 +2207,8 @@ void P_MovePlayer(player_t *player) player->drawangle += ANGLE_11hh; else player->drawangle -= ANGLE_11hh; + + player->mo->rollangle = 0; } else { @@ -2204,6 +2228,8 @@ void P_MovePlayer(player_t *player) player->drawangle += a; } } + + player->mo->rollangle = 0; } player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. @@ -2358,7 +2384,7 @@ void P_MovePlayer(player_t *player) // Crush test... if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) && !(player->mo->flags & MF_NOCLIP)) { - if ((netgame || multiplayer) && player->spectator) + 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); @@ -4240,7 +4266,8 @@ void P_PlayerThink(player_t *player) // Track airtime if (P_IsObjectOnGround(player->mo)) { - player->airtime = 0; + if (!P_PlayerInPain(player)) + player->airtime = 0; } else { @@ -4502,10 +4529,6 @@ void P_PlayerThink(player_t *player) else player->pflags &= ~PF_SPINDOWN; - // IF PLAYER NOT HERE THEN FLASH END IF - if (player->quittime && player->powers[pw_flashing] < K_GetKartFlashing(player) && !player->gotflag) - player->powers[pw_flashing] = K_GetKartFlashing(player); - // Counters, time dependent power ups. // Time Bonus & Ring Bonus count settings @@ -4524,11 +4547,6 @@ void P_PlayerThink(player_t *player) else player->powers[pw_nocontrol] = 0; - if (player->powers[pw_ignorelatch] & ((1<<15)-1) && player->powers[pw_ignorelatch] < UINT16_MAX) - player->powers[pw_ignorelatch]--; - else - player->powers[pw_ignorelatch] = 0; - //pw_super acts as a timer now if (player->powers[pw_super]) player->powers[pw_super]++; From e16c7d722fc50b27fe26553693e5b9d8ae3cccef Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 24 Aug 2020 02:06:17 -0400 Subject: [PATCH 2/6] Cherry-pick e1b265df2 --- src/d_netcmd.c | 1 + src/d_netcmd.h | 2 +- src/d_player.h | 23 ++++++++------- src/dehacked.c | 6 ++++ src/info.c | 31 ++++++++++++++++++++ src/info.h | 7 +++++ src/k_botitem.c | 1 + src/k_botsearch.c | 1 + src/k_collide.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++- src/k_collide.h | 1 + src/k_hud.c | 13 ++++++++ src/k_kart.c | 52 ++++++++++++++++++++++++++++++-- src/p_inter.c | 4 +-- src/p_map.c | 25 ++++++++++++++-- src/p_mobj.c | 29 ++++++++++++++++-- src/p_user.c | 6 ++++ 16 files changed, 256 insertions(+), 21 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a87d04cb5..46a033bb3 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -351,6 +351,7 @@ consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR|CV_C consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 7e36b6585..bd435c49e 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -66,7 +66,7 @@ extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_res // SRB2kart items extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; -extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine; +extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine, cv_landmine; extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield; extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink; diff --git a/src/d_player.h b/src/d_player.h index 1d71668f4..db1777b0f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -245,17 +245,18 @@ Run this macro, then #undef FOREACH afterward FOREACH (ORBINAUT, 6),\ FOREACH (JAWZ, 7),\ FOREACH (MINE, 8),\ - FOREACH (BALLHOG, 9),\ - FOREACH (SPB, 10),\ - FOREACH (GROW, 11),\ - FOREACH (SHRINK, 12),\ - FOREACH (THUNDERSHIELD, 13),\ - FOREACH (BUBBLESHIELD, 14),\ - FOREACH (FLAMESHIELD, 15),\ - FOREACH (HYUDORO, 16),\ - FOREACH (POGOSPRING, 17),\ - FOREACH (SUPERRING, 18),\ - FOREACH (KITCHENSINK, 19) + FOREACH (LANDMINE, 9),\ + FOREACH (BALLHOG, 10),\ + FOREACH (SPB, 11),\ + FOREACH (GROW, 12),\ + FOREACH (SHRINK, 13),\ + FOREACH (THUNDERSHIELD, 14),\ + FOREACH (BUBBLESHIELD, 15),\ + FOREACH (FLAMESHIELD, 16),\ + FOREACH (HYUDORO, 17),\ + FOREACH (POGOSPRING, 18),\ + FOREACH (SUPERRING, 19),\ + FOREACH (KITCHENSINK, 20) typedef enum { diff --git a/src/dehacked.c b/src/dehacked.c index 471499c5c..bb34ebd13 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8520,6 +8520,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SLOWBOOM9", "S_SLOWBOOM10", + // Land Mine + "S_LANDMINE", + "S_LANDMINE_EXPLODE", + // Ballhog "S_BALLHOG1", "S_BALLHOG2", @@ -10154,6 +10158,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BOOMEXPLODE", "MT_BOOMPARTICLE", + "MT_LANDMINE", // Land Mine + "MT_BALLHOG", // Ballhog "MT_BALLHOGBOOM", diff --git a/src/info.c b/src/info.c index c797c9283..9fda6292a 100644 --- a/src/info.c +++ b/src/info.c @@ -543,6 +543,7 @@ char sprnames[NUMSPRITES + 1][5] = "JAWZ", // Jawz "SSMN", // SS Mine "KRBM", // SS Mine BOOM + "LNDM", // Land Mine "BHOG", // Ballhog "BHBM", // Ballhog BOOM "SPBM", // Self-Propelled Bomb @@ -4209,6 +4210,9 @@ state_t states[NUMSTATES] = {SPR_KRBM, FF_FULLBRIGHT|8, 5, {NULL}, 0, 0, S_SLOWBOOM10}, // S_SLOWBOOM9 {SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10 + {SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE + {SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1 {SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2 {SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3 @@ -23842,6 +23846,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LANDMINE + -1, // doomednum + S_LANDMINE, // spawnstate + 2, // spawnhealth + S_NULL, // seestate + sfx_tossed, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_LANDMINE_EXPLODE, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_s3k5c, // activesound + MF_SHOOTABLE|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BALLHOG -1, // doomednum S_BALLHOG1, // spawnstate diff --git a/src/info.h b/src/info.h index 8e8a05ca3..af2778b62 100644 --- a/src/info.h +++ b/src/info.h @@ -814,6 +814,7 @@ typedef enum sprite SPR_JAWZ, // Jawz SPR_SSMN, // SS Mine SPR_KRBM, // SS Mine BOOM + SPR_LNDM, // Land Mine SPR_BHOG, // Ballhog SPR_BHBM, // Ballhog BOOM SPR_SPBM, // Self-Propelled Bomb @@ -4363,6 +4364,10 @@ typedef enum state S_SLOWBOOM9, S_SLOWBOOM10, + // Land mine + S_LANDMINE, + S_LANDMINE_EXPLODE, + // Ballhog S_BALLHOG1, S_BALLHOG2, @@ -6037,6 +6042,8 @@ typedef enum mobj_type MT_BOOMEXPLODE, MT_BOOMPARTICLE, + MT_LANDMINE, // Land Mine + MT_BALLHOG, // Ballhog MT_BALLHOGBOOM, diff --git a/src/k_botitem.c b/src/k_botitem.c index ce56b9b6e..a871c2305 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -1036,6 +1036,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemSneaker(player, cmd); break; case KITEM_BANANA: + case KITEM_LANDMINE: if (!player->kartstuff[k_itemheld]) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); diff --git a/src/k_botsearch.c b/src/k_botsearch.c index d5a08d2ad..5d6425127 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -589,6 +589,7 @@ static boolean K_BotSteerObjects(mobj_t *thing) case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: + case MT_LANDMINE: case MT_BALLHOG: case MT_SPB: case MT_BUBBLESHIELDTRAP: diff --git a/src/k_collide.c b/src/k_collide.c index 0f2361062..1adb1a694 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -68,7 +68,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) damageitem = true; } - else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE) + else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE) { damageitem = true; // Bomb death @@ -158,6 +158,12 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) damageitem = true; } + else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE) + { + damageitem = true; + // Bomb death + P_KillMobj(t2, t1, t1, DMG_NORMAL); + } else if (t2->flags & MF_SHOOTABLE) { // Shootable damage @@ -325,6 +331,73 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2) return true; } +boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) +{ + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) + return true; + + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (t2->player) + { + if (t2->player->powers[pw_flashing]) + return true; + + // Banana snipe! + if (t1->health > 1) + S_StartSound(t2, sfx_bsnipe); + + if (t2->player->kartstuff[k_flamedash] && t2->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) + { + // Melt item + S_StartSound(t2, sfx_s3k43); + } + else + { + // Player Damage + P_DamageMobj(t2, t1, t1->target, 1, DMG_TUMBLE); + } + + P_KillMobj(t1, t2, t2, DMG_NORMAL); + } + else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD + || t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD + || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_BALLHOG) + { + // Other Item Damage + if (t2->eflags & MFE_VERTICALFLIP) + t2->z -= t2->height; + else + t2->z += t2->height; + + S_StartSound(t2, t2->info->deathsound); + P_KillMobj(t2, t1, t1, DMG_NORMAL); + + P_SetObjectMomZ(t2, 8*FRACUNIT, false); + P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); + + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); + + P_KillMobj(t1, t2, t2, DMG_NORMAL); + } + else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE) + { + P_KillMobj(t1, t2, t2, DMG_NORMAL); + // Bomb death + P_KillMobj(t2, t1, t1, DMG_NORMAL); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); + P_KillMobj(t1, t2, t2, DMG_NORMAL); + } + + return true; +} + boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) { if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) diff --git a/src/k_collide.h b/src/k_collide.h index 75a9404f8..e005bc497 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -9,6 +9,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2); boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); boolean K_MineCollide(mobj_t *t1, mobj_t *t2); boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); +boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2); boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_hud.c b/src/k_hud.c index 42c7fd7c2..63ecce767 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -111,6 +111,7 @@ static patch_t *kp_eggman[2]; static patch_t *kp_orbinaut[5]; static patch_t *kp_jawz[2]; static patch_t *kp_mine[2]; +static patch_t *kp_landmine[2]; static patch_t *kp_ballhog[2]; static patch_t *kp_selfpropelledbomb[2]; static patch_t *kp_grow[2]; @@ -386,6 +387,7 @@ void K_LoadKartHUDGraphics(void) } kp_jawz[0] = W_CachePatchName("K_ITJAWZ", PU_HUDGFX); kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX); + kp_landmine[0] = W_CachePatchName("K_ITLNDM", PU_HUDGFX); kp_ballhog[0] = W_CachePatchName("K_ITBHOG", PU_HUDGFX); kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX); kp_grow[0] = W_CachePatchName("K_ITGROW", PU_HUDGFX); @@ -435,6 +437,7 @@ void K_LoadKartHUDGraphics(void) kp_orbinaut[4] = W_CachePatchName("K_ISORBN", PU_HUDGFX); kp_jawz[1] = W_CachePatchName("K_ISJAWZ", PU_HUDGFX); kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX); + kp_landmine[1] = W_CachePatchName("K_ISLNDM", PU_HUDGFX); kp_ballhog[1] = W_CachePatchName("K_ISBHOG", PU_HUDGFX); kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX); kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX); @@ -611,6 +614,8 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny) return (tiny ? "K_ISJAWZ" : "K_ITJAWZ"); case KITEM_MINE: return (tiny ? "K_ISMINE" : "K_ITMINE"); + case KITEM_LANDMINE: + return (tiny ? "K_ISLNDM" : "K_ITLNDM"); case KITEM_BALLHOG: return (tiny ? "K_ISBHOG" : "K_ITBHOG"); case KITEM_SPB: @@ -961,6 +966,10 @@ static void K_drawKartItem(void) localpatch = kp_superring[offset]; //localcolor = SKINCOLOR_GOLD; break; + case 15: // Land Mine + localpatch = kp_landmine[offset]; + //localcolor = SKINCOLOR_JET; + break; /*case 15: // Pogo Spring localpatch = kp_pogospring[offset]; localcolor = SKINCOLOR_TANGERINE; @@ -1046,6 +1055,9 @@ static void K_drawKartItem(void) case KITEM_MINE: localpatch = kp_mine[offset]; break; + case KITEM_LANDMINE: + localpatch = kp_landmine[offset]; + break; case KITEM_BALLHOG: localpatch = kp_ballhog[offset]; break; @@ -3722,6 +3734,7 @@ static void K_drawDistributionDebugger(void) kp_orbinaut[4], kp_jawz[1], kp_mine[1], + kp_landmine[1], kp_ballhog[1], kp_selfpropelledbomb[1], kp_grow[1], diff --git a/src/k_kart.c b/src/k_kart.c index 26a878679..6cc0e2c93 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -151,6 +151,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_orbinaut); CV_RegisterVar(&cv_jawz); CV_RegisterVar(&cv_mine); + CV_RegisterVar(&cv_landmine); CV_RegisterVar(&cv_ballhog); CV_RegisterVar(&cv_selfpropelledbomb); CV_RegisterVar(&cv_grow); @@ -252,6 +253,7 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] = &cv_orbinaut, &cv_jawz, &cv_mine, + &cv_landmine, &cv_ballhog, &cv_selfpropelledbomb, &cv_grow, @@ -281,11 +283,12 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility - /*Banana*/ { 7, 3, 1, 0, 0, 0, 0, 0 }, // Banana - /*Eggman Monitor*/ { 3, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor + /*Banana*/ { 6, 3, 1, 0, 0, 0, 0, 0 }, // Banana + /*Eggman Monitor*/ { 2, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor /*Orbinaut*/ { 7, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine + /*Land Mine*/ { 2, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow @@ -317,6 +320,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] = /*Orbinaut*/ { 8, 0 }, // Orbinaut /*Jawz*/ { 8, 1 }, // Jawz /*Mine*/ { 4, 1 }, // Mine + /*Land Mine*/ { 0, 0 }, // Land Mine /*Ballhog*/ { 2, 1 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 0 }, // Self-Propelled Bomb /*Grow*/ { 2, 1 }, // Grow @@ -525,6 +529,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, case KITEM_ORBINAUT: case KITEM_JAWZ: case KITEM_MINE: + case KITEM_LANDMINE: case KITEM_BALLHOG: case KITEM_SPB: case KITEM_GROW: @@ -553,6 +558,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, { case KITEM_ROCKETSNEAKER: case KITEM_JAWZ: + case KITEM_LANDMINE: case KITEM_BALLHOG: case KRITEM_TRIPLESNEAKER: case KRITEM_TRIPLEBANANA: @@ -4201,6 +4207,40 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) S_StartSound(mo, (sound == 1 ? sfx_kc2f : sfx_kpogos)); } +static void K_ThrowLandMine(player_t *player) +{ + mobj_t *landMine; + mobj_t *throwmo; + + landMine = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_LANDMINE); + K_FlipFromObject(landMine, player->mo); + landMine->threshold = 10; + + if (landMine->info->seesound) + S_StartSound(player->mo, landMine->info->seesound); + + P_SetTarget(&landMine->target, player->mo); + + P_SetScale(landMine, player->mo->scale); + landMine->destscale = player->mo->destscale; + + landMine->angle = player->mo->angle; + + landMine->momz = (30 * mapobjectscale * P_MobjFlip(player->mo)) + player->mo->momz; + landMine->color = player->skincolor; + + throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FIREDITEM); + P_SetTarget(&throwmo->target, player->mo); + // Ditto: + if (player->mo->eflags & MFE_VERTICALFLIP) + { + throwmo->z -= player->mo->height; + throwmo->eflags |= MFE_VERTICALFLIP; + } + + throwmo->movecount = 0; // above player +} + void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source) { mobj_t *cachenext; @@ -7469,6 +7509,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_UpdateHnextList(player, true); } break; + case KITEM_LANDMINE: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_ThrowLandMine(player); + K_PlayAttackTaunt(player->mo); + } + break; case KITEM_BALLHOG: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { diff --git a/src/p_inter.c b/src/p_inter.c index 7d47599ae..1a5064f76 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1821,7 +1821,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player) // Player is the target { const UINT8 type = (damagetype & DMG_TYPEMASK); - const boolean combo = (type == DMG_EXPLODE); // This damage type can be comboed from other damage + const boolean combo = (type == DMG_EXPLODE || type == DMG_TUMBLE); // This damage type can be comboed from other damage INT16 ringburst = 5; if (player->pflags & PF_GODMODE) @@ -1943,7 +1943,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da P_PlayerRingBurst(player, ringburst); K_PlayPainSound(player->mo); - if ((type == DMG_EXPLODE) || (cv_kartdebughuddrop.value && !modeattacking)) + if ((combo == true) || (cv_kartdebughuddrop.value && !modeattacking)) { K_DropItems(player); } diff --git a/src/p_map.c b/src/p_map.c index a8b0ae784..07995e9bf 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -725,7 +725,7 @@ static boolean PIT_CheckThing(mobj_t *thing) || (thing->player && thing->player->kartstuff[k_bubbleblowup])) && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG - || tmthing->type == MT_SSMINE || tmthing->type == MT_SINK + || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK || (tmthing->type == MT_PLAYER && thing->target != tmthing))) { // see if it went over / under @@ -783,7 +783,7 @@ static boolean PIT_CheckThing(mobj_t *thing) || (tmthing->player && tmthing->player->kartstuff[k_bubbleblowup])) && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || thing->type == MT_SINK + || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK || (thing->type == MT_PLAYER && tmthing->target != thing))) { // see if it went over / under @@ -928,6 +928,27 @@ static boolean PIT_CheckThing(mobj_t *thing) return K_MineExplosionCollide(thing, tmthing); } + if (tmthing->type == MT_LANDMINE) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + return K_LandMineCollide(tmthing, thing); + } + else if (thing->type == MT_LANDMINE) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + return K_LandMineCollide(thing, tmthing); + } + if (tmthing->type == MT_SINK) { // see if it went over / under diff --git a/src/p_mobj.c b/src/p_mobj.c index 4d443cea2..403bd82d6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1168,6 +1168,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_BANANA: case MT_EGGMANITEM: case MT_SSMINE: + case MT_LANDMINE: case MT_SINK: if (mo->extravalue2 > 0) gravityadd *= mo->extravalue2; @@ -2092,6 +2093,7 @@ boolean P_ZMovement(mobj_t *mo) case MT_JAWZ_DUD: case MT_BALLHOG: case MT_SSMINE: + case MT_LANDMINE: case MT_BUBBLESHIELDTRAP: // Remove stuff from death pits. if (P_CheckDeathPitCollide(mo)) @@ -4478,7 +4480,8 @@ boolean P_IsKartItem(INT32 type) type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || type == MT_SSMINE || type == MT_SSMINE_SHIELD || type == MT_SINK || type == MT_SINK_SHIELD || - type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP) + type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP || + type == MT_LANDMINE) return true; else return false; @@ -5759,6 +5762,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) case MT_ORBINAUT: case MT_BANANA: case MT_EGGMANITEM: + case MT_LANDMINE: case MT_SPB: if (P_IsObjectOnGround(mobj)) { @@ -6369,6 +6373,25 @@ static boolean P_MobjRegularThink(mobj_t *mobj) || (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13])) A_GrenadeRing(mobj); + if (mobj->threshold > 0) + mobj->threshold--; + break; + case MT_LANDMINE: + mobj->friction = ORIG_FRICTION/4; + + if (mobj->momx || mobj->momy || mobj->momz) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! + } + + if (P_IsObjectOnGround(mobj) && mobj->health > 1) + { + S_StartSound(mobj, mobj->info->activesound); + mobj->momx = mobj->momy = 0; + mobj->health = 1; + } + if (mobj->threshold > 0) mobj->threshold--; break; @@ -8508,7 +8531,8 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->type == MT_BANANA || mobj->type == MT_EGGMANITEM || mobj->type == MT_ORBINAUT || mobj->type == MT_BALLHOG || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD - || mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP) + || mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP + || mobj->type == MT_LANDMINE) { if (mobj->health > 0 && P_MobjTouchingSectorSpecial(mobj, 4, 7, true)) { @@ -8889,6 +8913,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: + case MT_LANDMINE: case MT_BALLHOG: case MT_SINK: case MT_ROCKETSNEAKER: diff --git a/src/p_user.c b/src/p_user.c index c294d3f64..61c7c5e8a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2169,6 +2169,9 @@ void P_MovePlayer(player_t *player) UINT8 rollSpeed = max(1, min(8, player->tumbleHeight / 10)); + if (player->tumbleLastBounce == true) + spinSpeed = 2; + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); player->drawangle -= (ANGLE_11hh * spinSpeed); @@ -2176,6 +2179,9 @@ void P_MovePlayer(player_t *player) if (player->tumbleLastBounce == true) { + if (abs((signed)(player->mo->angle - player->drawangle)) < ANGLE_22h) + player->drawangle = player->mo->angle; + if (abs((signed)player->mo->rollangle) < ANGLE_22h) player->mo->rollangle = 0; } From d7ba48e23e630e4210aa4ea00322c3ddb3bac9af Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 23 Sep 2020 00:09:19 -0400 Subject: [PATCH 3/6] Adjust Land Mine odds --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6cc0e2c93..52e8cdf79 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -283,12 +283,12 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility - /*Banana*/ { 6, 3, 1, 0, 0, 0, 0, 0 }, // Banana - /*Eggman Monitor*/ { 2, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor + /*Banana*/ { 5, 3, 1, 0, 0, 0, 0, 0 }, // Banana + /*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor /*Orbinaut*/ { 7, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine - /*Land Mine*/ { 2, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine + /*Land Mine*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog /*Self-Propelled Bomb*/ { 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb /*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow From 3983967449f167275962fabef1c27f3c569d80fd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 16 Nov 2020 20:11:54 -0500 Subject: [PATCH 4/6] Scale tumble height with player speed, not just inflictor speed --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 52e8cdf79..cb9f564c9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2581,8 +2581,8 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) if (inflictor && !P_MobjWasRemoved(inflictor)) { - const fixed_t infSpeed = P_AproxDistance(inflictor->momx, inflictor->momy) / 2; - player->tumbleHeight += (infSpeed / player->mo->scale); + const fixed_t addHeight = FixedHypot(FixedHypot(inflictor->momx, inflictor->momy) / 2, FixedHypot(player->mo->momx, player->mo->momy) / 2); + player->tumbleHeight += (addHeight / player->mo->scale); } player->mo->momz = player->tumbleHeight * player->mo->scale * P_MobjFlip(player->mo); From 03149d7810d7b35de62690776dc96144f968d539 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 6 Jan 2021 23:16:02 -0500 Subject: [PATCH 5/6] Only do touch damage when confirming a bump Should fix the mcdonalds rings --- src/p_map.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index fe1055a3e..3d1b90493 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1299,8 +1299,10 @@ static boolean PIT_CheckThing(mobj_t *thing) P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } - K_KartBouncing(mo1, mo2, zbounce, false); - K_PvPTouchDamage(mo1, mo2); + if (K_KartBouncing(mo1, mo2, zbounce, false)) + { + K_PvPTouchDamage(mo1, mo2); + } } return true; From b2bf38718ee4d3176254748f2cc8c59285fcbec7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 7 Jan 2021 00:32:38 -0500 Subject: [PATCH 6/6] Minimum tics is back to tics --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 691832200..7f16afbb4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2358,7 +2358,7 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics) if (mo1valid == true && mo2valid == true) { - const INT32 mintics = 1; + const INT32 mintics = tics; const fixed_t ticaddfactor = mapobjectscale * 8; const fixed_t mo1speed = FixedHypot(FixedHypot(mo1->momx, mo1->momy), mo1->momz);