diff --git a/src/d_player.h b/src/d_player.h index 89161e23c..b7d1d9456 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -857,7 +857,8 @@ struct player_t mobj_t *hand; mobj_t *flickyAttacker; - UINT8 instaShieldCooldown; + UINT8 instaWhipCharge; + UINT8 instaWhipChargeLockout; UINT8 guardCooldown; UINT8 handtimer; diff --git a/src/k_botitem.c b/src/k_botitem.c index 98fcc44d9..c483afdb5 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -1415,7 +1415,7 @@ static void K_BotItemInstashield(player_t *player, ticcmd_t *cmd) return; } - if (player->instaShieldCooldown || leveltime < starttime || player->spindash) + if (player->instaWhipCharge || leveltime < starttime || player->spindash) { // Instashield is on cooldown. return; diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 41740137e..5afd75d18 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -869,7 +869,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) attacker->renderflags &= ~RF_DONTDRAW; attackerPlayer->spindashboost = 0; attackerPlayer->sneakertimer = 0; - attackerPlayer->instaShieldCooldown = GUARDBREAK_COOLDOWN; + attackerPlayer->instaWhipCharge = GUARDBREAK_COOLDOWN; attackerPlayer->guardCooldown = GUARDBREAK_COOLDOWN; attackerPlayer->flashing = 0; diff --git a/src/k_kart.c b/src/k_kart.c index 65f7baf2b..fe3bf34de 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1410,7 +1410,7 @@ static void K_UpdateDraft(player_t *player) } // Opportunity cost for berserk attacking. Get your slingshot speed first! - if (player->instaShieldCooldown && player->rings <= 0) + if (player->instaWhipCharge && player->rings <= 0) return; // Not enough speed to draft. @@ -3692,7 +3692,7 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { return; // short-circuit instashield for vfx visibility - t1->player->instaShieldCooldown = GUARDBREAK_COOLDOWN; + t1->player->instaWhipCharge = GUARDBREAK_COOLDOWN; t1->player->guardCooldown = GUARDBREAK_COOLDOWN; S_StartSound(t1, sfx_gbrk); @@ -8136,30 +8136,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->gateBoost) player->gateBoost--; - if (leveltime < starttime) - { - player->instaShieldCooldown = (gametyperules & GTR_SPHERES) ? INSTAWHIP_STARTOFBATTLE : INSTAWHIP_STARTOFRACE; - } - else if (player->rings > 0) - { - if (player->instaShieldCooldown > INSTAWHIP_COOLDOWN) - player->instaShieldCooldown--; - else - player->instaShieldCooldown = INSTAWHIP_COOLDOWN; - } - else - { - if (player->instaShieldCooldown) - { - player->instaShieldCooldown--; - if (!P_IsObjectOnGround(player->mo)) - player->instaShieldCooldown = max(player->instaShieldCooldown, 1); - } - } - if (player->powerup.rhythmBadgeTimer > 0) { - player->instaShieldCooldown = min(player->instaShieldCooldown, 1); + player->instaWhipCharge = min(player->instaWhipCharge, 1); player->powerup.rhythmBadgeTimer--; } @@ -8291,6 +8270,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->justbumped > 0) player->justbumped--; + if (player->instaWhipChargeLockout) + player->instaWhipChargeLockout--; + if (!(player->cmd.buttons & BT_ATTACK)) // Deliberate Item button release, no need to protect you from lockout + player->instaWhipChargeLockout = 0; + + if (P_PlayerInPain(player)) + player->instaWhipCharge = 0; + if (player->tiregrease) { // Remove grease faster if players are moving slower; players that are recovering @@ -8448,9 +8435,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_DRIFTINPUT; } - if (K_PlayerGuard(player) && !K_PowerUpRemaining(player, POWERUP_BARRIER)) - player->instaShieldCooldown = max(player->instaShieldCooldown, INSTAWHIP_DROPGUARD); - // Roulette Code K_KartItemRoulette(player, cmd); @@ -10196,6 +10180,29 @@ boolean K_PlayerGuard(player_t *player) return true; } + // Ugh. Duplicating a lot of this because while Guard _superficially_ looks like it's + // restricted similarly to ebrake, it's actually _really_ bad if we can't guard after item bumps. + + if (player->respawn.state != RESPAWNST_NONE + && (player->respawn.init == true || player->respawn.fromRingShooter == true)) + { + return false; + } + + if (Obj_PlayerRingShooterFreeze(player) == true) + { + return false; + } + + if (K_PressingEBrake(player) == true + && (player->drift == 0 || P_IsObjectOnGround(player->mo) == false) + && P_PlayerInPain(player) == false + && player->spindashboost == 0 + && player->nocontrol == 0) + { + return false; + } + return (K_PlayerEBrake(player) && player->spheres > 0); } @@ -10994,16 +11001,38 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->pflags & PF_USERINGS) { - if (ATTACK_IS_DOWN && player->rings <= 0) + boolean chargingwhip = (cmd->buttons & BT_ATTACK) && (player->rings <= 0) && (!player->instaWhipChargeLockout); + boolean releasedwhip = !(cmd->buttons & BT_ATTACK) && (player->rings <= 0 && player->instaWhipCharge); + + if (K_PowerUpRemaining(player, POWERUP_BADGE)) { - if (player->instaShieldCooldown || leveltime < starttime || player->spindash) + chargingwhip = false; + releasedwhip = (ATTACK_IS_DOWN && player->rings <= 0); + player->instaWhipCharge = INSTAWHIP_COOLDOWN; + } + + if (chargingwhip) + { + //CONS_Printf("charging %d\n", player->instaWhipCharge); + player->instaWhipCharge = min(player->instaWhipCharge + 1, INSTAWHIP_COOLDOWN + 1); + + if (player->instaWhipCharge == 1) + { + Obj_SpawnInstaWhipRecharge(player, 0); + Obj_SpawnInstaWhipRecharge(player, ANGLE_120); + Obj_SpawnInstaWhipRecharge(player, ANGLE_240); + } + } + else if (releasedwhip) + { + if (player->instaWhipCharge < INSTAWHIP_COOLDOWN || leveltime < starttime || player->spindash) { S_StartSound(player->mo, sfx_kc50); + player->instaWhipCharge = 0; } else { - player->instaShieldCooldown = INSTAWHIP_COOLDOWN; - + player->instaWhipCharge = 0; if (!K_PowerUpRemaining(player, POWERUP_BARRIER)) { player->guardCooldown = INSTAWHIP_COOLDOWN; @@ -11023,16 +11052,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { whip->flags2 |= MF2_AMBUSH; } - - if (!K_PowerUpRemaining(player, POWERUP_BADGE)) - { - // Spawn in triangle formation - Obj_SpawnInstaWhipRecharge(player, 0); - Obj_SpawnInstaWhipRecharge(player, ANGLE_120); - Obj_SpawnInstaWhipRecharge(player, ANGLE_240); - } } } + else + player->instaWhipCharge = 0; if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) { diff --git a/src/k_kart.h b/src/k_kart.h index 9d3375c69..ef4b7a265 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -30,7 +30,7 @@ Make sure this matches the actual number of states #define SHRINK_PHYSICS_SCALE (3*FRACUNIT/4) #define INSTAWHIP_DURATION (12) -#define INSTAWHIP_COOLDOWN (TICRATE*2) +#define INSTAWHIP_COOLDOWN (5*TICRATE/4) #define INSTAWHIP_STARTOFRACE (255) #define INSTAWHIP_STARTOFBATTLE (1) #define INSTAWHIP_DROPGUARD (12) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 9bb2be94b..40ad65561 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -329,8 +329,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->sliptideZipDelay); else if (fastcmp(field,"sliptideZipBoost")) lua_pushinteger(L, plr->sliptideZipBoost); - else if (fastcmp(field,"instaShieldCooldown")) - lua_pushinteger(L, plr->instaShieldCooldown); + else if (fastcmp(field,"instaWhipCharge")) + lua_pushinteger(L, plr->instaWhipCharge); else if (fastcmp(field,"guardCooldown")) lua_pushinteger(L, plr->guardCooldown); /* @@ -807,8 +807,8 @@ static int player_set(lua_State *L) plr->sliptideZipDelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"sliptideZipBoost")) plr->sliptideZipBoost = luaL_checkinteger(L, 3); - else if (fastcmp(field,"instaShieldCooldown")) - plr->instaShieldCooldown = luaL_checkinteger(L, 3); + else if (fastcmp(field,"instaWhipCharge")) + plr->instaWhipCharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"guardCooldown")) plr->guardCooldown = luaL_checkinteger(L, 3); /* diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c index dc1e410ed..70e9ee05f 100644 --- a/src/objects/instawhip.c +++ b/src/objects/instawhip.c @@ -2,6 +2,7 @@ #include "../info.h" #include "../k_objects.h" #include "../p_local.h" +#include "../k_kart.h" // INSTAWHIP_COOLDOWN #define recharge_target(o) ((o)->target) #define recharge_offset(o) ((o)->movedir) @@ -49,7 +50,7 @@ void Obj_SpawnInstaWhipRecharge(player_t *player, angle_t angleOffset) { mobj_t *x = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_INSTAWHIP_RECHARGE); - x->tics = max(player->instaShieldCooldown - states[x->info->raisestate].tics, 0); + x->tics = max(INSTAWHIP_COOLDOWN - player->instaWhipCharge - states[x->info->raisestate].tics, 0); x->renderflags |= RF_SLOPESPLAT | RF_NOSPLATBILLBOARD; P_SetTarget(&recharge_target(x), player->mo); @@ -60,7 +61,7 @@ void Obj_InstaWhipRechargeThink(mobj_t *x) { mobj_t *target = recharge_target(x); - if (P_MobjWasRemoved(target)) + if (P_MobjWasRemoved(target) || !target->player->instaWhipCharge) { P_RemoveMobj(x); return; diff --git a/src/p_enemy.c b/src/p_enemy.c index 084ccb169..cad9b9f5c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3856,6 +3856,8 @@ void A_AttractChase(mobj_t *actor) else S_StartSoundAtVolume(actor->target, sfx_s227, actor->target->player->ringvolume); + actor->target->player->instaWhipChargeLockout = 10; + actor->target->player->ringvolume -= RINGVOLUMECOLLECTPENALTY; actor->target->player->pickuprings--; diff --git a/src/p_inter.c b/src/p_inter.c index aa25a087b..89567b184 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -108,6 +108,15 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End) // GET STUFF // +boolean P_Whipping(player_t *player) +{ + if (player->instaWhipCharge) + return true; + if (player->whip && !P_MobjWasRemoved(player->whip)) + return true; + return false; +} + // // P_CanPickupItem // @@ -115,7 +124,7 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End) // boolean P_CanPickupItem(player_t *player, UINT8 weapon) { - if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED) || player->itemRoulette.reserved) + if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED) || player->itemRoulette.reserved || P_Whipping(player)) return false; // 0: Sphere/Ring @@ -438,6 +447,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case KITEM_SUPERRING: if (player->pflags & PF_RINGLOCK) // no cheaty rings return; + if (player->instaWhipCharge) + return; break; default: if (!P_CanPickupItem(player, 1)) @@ -635,6 +646,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->pflags & PF_RINGLOCK) return; + // Prepping instawhip? Don't ruin it by collecting rings + if (player->instaWhipCharge) + return; + // Don't immediately pick up spilled rings if (special->threshold > 0 || P_PlayerInPain(player) || player->spindash) // player->spindash: Otherwise, players can pick up rings that are thrown out of them from invinc spindash penalty return; diff --git a/src/p_local.h b/src/p_local.h index 15b338f9d..ef6964bc5 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -544,6 +544,7 @@ void P_CheckTimeLimit(void); void P_CheckPointLimit(void); boolean P_CheckRacers(void); +boolean P_Whipping(player_t *player); boolean P_CanPickupItem(player_t *player, UINT8 weapon); boolean P_IsPickupCheesy(player_t *player, UINT8 type); void P_UpdateLastPickup(player_t *player, UINT8 type); diff --git a/src/p_saveg.c b/src/p_saveg.c index edf502fdf..284fabac3 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -541,7 +541,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH); - WRITEUINT8(save->p, players[i].instaShieldCooldown); + WRITEUINT8(save->p, players[i].instaWhipCharge); WRITEUINT8(save->p, players[i].guardCooldown); WRITEUINT8(save->p, players[i].handtimer); @@ -1051,7 +1051,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) READMEM(save->p, players[i].public_key, PUBKEYLENGTH); - players[i].instaShieldCooldown = READUINT8(save->p); + players[i].instaWhipCharge = READUINT8(save->p); players[i].guardCooldown = READUINT8(save->p); players[i].handtimer = READUINT8(save->p); diff --git a/src/r_spritefx.cpp b/src/r_spritefx.cpp index 0664819ff..31b7260c8 100644 --- a/src/r_spritefx.cpp +++ b/src/r_spritefx.cpp @@ -23,7 +23,7 @@ INT32 R_ThingLightLevel(mobj_t* thing) if (player) { - if (player->instaShieldCooldown && !player->whip && (player->rings <= 0) && (leveltime & 1)) + if (player->instaWhipCharge && !player->whip && (player->rings <= 0) && (leveltime & 1)) { // Darken on every other frame of instawhip cooldown lightlevel -= 128;