From 26677c612ef21c742f90fa260d2465e4bc380874 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 23 Jan 2024 22:06:17 -0700 Subject: [PATCH] WIP: Improved bumper defenses --- src/d_player.h | 1 + src/k_kart.c | 23 +++++++++++++++++++++++ src/k_kart.h | 5 +++++ src/lua_playerlib.c | 4 ++++ src/p_inter.c | 8 ++++++++ src/p_map.c | 6 ++++++ src/p_mobj.c | 5 +++++ src/p_saveg.c | 2 ++ 8 files changed, 54 insertions(+) diff --git a/src/d_player.h b/src/d_player.h index 75002da11..24b5ac1c7 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -979,6 +979,7 @@ struct player_t boolean markedfordeath; boolean dotrickfx; + UINT8 bumperinflate; UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? diff --git a/src/k_kart.c b/src/k_kart.c index 7334567a9..eba4701bd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4543,6 +4543,19 @@ static boolean K_LastTumbleBounceCondition(player_t *player) return (player->tumbleBounces > TUMBLEBOUNCES && player->tumbleHeight < 60); } +// Bumpers give you bonus launch height and speed, strengthening your DI to help evade combos. +// bumperinflate visuals are handled by MT_BATTLEBUMPER, but the effects are in K_KartPlayerThink. +void K_BumperInflate(player_t *player) +{ + if (!player || P_MobjWasRemoved(player->mo)) + return; + + if (!(player->mo->health > 1 && gametyperules & GTR_BUMPERS)) + return; + + player->bumperinflate = 3; +} + static void K_HandleTumbleBounce(player_t *player) { player->tumbleBounces++; @@ -4590,6 +4603,8 @@ static void K_HandleTumbleBounce(player_t *player) } } + K_BumperInflate(player); + // A bit of damage hitlag. // This gives a window for DI!! K_AddHitLag(player->mo, 3, true); @@ -8766,6 +8781,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->hyudorotimer) player->hyudorotimer--; + if (player->bumperinflate && player->mo->health > 1 && player->mo->hitlag == 0) + { + P_Thrust(player->mo, K_MomentumAngle(player->mo), BUMPER_THRUST); + if (player->tumbleBounces) + player->mo->momz += BUMPER_FLOAT; + player->bumperinflate--; + } + if (player->ringvolume < MINRINGVOLUME) player->ringvolume = MINRINGVOLUME; else if (MAXRINGVOLUME - player->ringvolume < RINGVOLUMEREGEN) diff --git a/src/k_kart.h b/src/k_kart.h index ad1132f61..c2b02ef01 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -37,6 +37,9 @@ Make sure this matches the actual number of states #define INSTAWHIP_TETHERBLOCK (TICRATE*4) #define PUNISHWINDOW (7*TICRATE/10) +#define BUMPER_FLOAT (4*mapobjectscale) +#define BUMPER_THRUST (10*mapobjectscale) + #define FLAMESHIELD_MAX (120) #define RR_PROJECTILE_FUSE (8*TICRATE) @@ -256,6 +259,8 @@ boolean K_IsPlayingDisplayPlayer(player_t *player); boolean K_PlayerCanPunt(player_t *player); void K_MakeObjectReappear(mobj_t *mo); +void K_BumperInflate(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index fe2291cab..875167cb6 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -259,6 +259,8 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->markedfordeath); else if (fastcmp(field,"dotrickfx")) lua_pushboolean(L, plr->dotrickfx); + else if (fastcmp(field,"bumperinflate")) + lua_pushboolean(L, plr->bumperinflate); else if (fastcmp(field,"ringboxdelay")) lua_pushinteger(L, plr->ringboxdelay); else if (fastcmp(field,"ringboxaward")) @@ -783,6 +785,8 @@ static int player_set(lua_State *L) plr->markedfordeath = luaL_checkboolean(L, 3); else if (fastcmp(field,"dotrickfx")) plr->dotrickfx = luaL_checkboolean(L, 3); + else if (fastcmp(field,"bumperinflate")) + plr->bumperinflate = luaL_checkboolean(L, 3); else if (fastcmp(field,"ringboxdelay")) plr->ringboxdelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"ringboxaward")) diff --git a/src/p_inter.c b/src/p_inter.c index 6a7164745..5561932b5 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3352,6 +3352,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->preventfailsafe = TICRATE*3; player->pflags &= ~PF_GAINAX; Obj_EndBungee(player); + K_BumperInflate(target->player); if (player->spectator == false && !(player->charflags & SF_IRONMAN)) { @@ -3376,6 +3377,13 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da //P_KillPlayer(player, inflictor, source, damagetype); } + // Have bumpers? Demote wipeout combos to stumble, force the attacker to make a DI read. + if (player->mo->health > 1 && gametyperules & GTR_BUMPERS) + { + if (type == DMG_WIPEOUT && P_PlayerInPain(player)) + type = DMG_STUMBLE; + } + switch (type) { case DMG_STING: diff --git a/src/p_map.c b/src/p_map.c index 7c7593cad..076687fb0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4177,6 +4177,12 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) P_PlayerHitBounceLine(bestslideline, &result->normal); mo->eflags |= MFE_JUSTBOUNCEDWALL; + if (mo->player && P_PlayerInPain(mo->player) && gametyperules & GTR_BUMPERS && mo->health > 1) + { + CONS_Printf("get me outta here\n"); + P_DamageMobj(mo, NULL, NULL, 1, DMG_STUMBLE); + } + mo->momx = tmxmove; mo->momy = tmymove; mo->player->cmomx = tmxmove; diff --git a/src/p_mobj.c b/src/p_mobj.c index 1e7f4a65c..6e687971a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6364,6 +6364,11 @@ static void P_MobjSceneryThink(mobj_t *mobj) // Shrink your items if the player shrunk too. P_SetScale(mobj, mobj->target->scale); + if (mobj->target->player->bumperinflate) + { + P_SetScale(mobj, mobj->target->scale + (mobj->target->scale * mobj->target->player->bumperinflate / 2)); + } + P_UnsetThingPosition(mobj); { const angle_t fa = ang >> ANGLETOFINESHIFT; diff --git a/src/p_saveg.c b/src/p_saveg.c index 2cf06d1e2..6fafe80bb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -592,6 +592,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].markedfordeath); WRITEUINT8(save->p, players[i].dotrickfx); + WRITEUINT8(save->p, players[i].bumperinflate); WRITEUINT8(save->p, players[i].ringboxdelay); WRITEUINT8(save->p, players[i].ringboxaward); @@ -1166,6 +1167,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].markedfordeath = READUINT8(save->p); players[i].dotrickfx = READUINT8(save->p); + players[i].bumperinflate = READUINT8(save->p); players[i].ringboxdelay = READUINT8(save->p); players[i].ringboxaward = READUINT8(save->p);