diff --git a/src/cvars.cpp b/src/cvars.cpp index 959ca9f68..65b1f1291 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -788,6 +788,8 @@ consvar_t cv_votetime = UnsavedNetVar("votetime", "20").min_max(10, 3600); // Cheats don't save... // +consvar_t cv_barriertime = OnlineCheat("barriertime", "30").values(CV_Natural).description("How long it takes for the Barrier to shrink in Battle Overtime"); +consvar_t cv_battlespawn = OnlineCheat("battlespawn", "0").values(CV_Unsigned).description("Spawn every player at the same spawnpoint in Battle (0 = random spawns)"); consvar_t cv_battletest = OnlineCheat("battletest", "Off").on_off().description("Free Play goes to Battle instead of Prisons"); #ifdef DEVELOP diff --git a/src/g_game.c b/src/g_game.c index 877840150..c4e30f9f9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2603,12 +2603,22 @@ mapthing_t *G_FindBattleStart(INT32 playernum) if (numdmstarts) { - for (j = 0; j < 64; j++) + extern consvar_t cv_battlespawn; + if (cv_battlespawn.value) { - i = P_RandomKey(PR_PLAYERSTARTS, numdmstarts); - if (G_CheckSpot(playernum, deathmatchstarts[i])) + i = cv_battlespawn.value - 1; + if (i < numdmstarts) return deathmatchstarts[i]; } + else + { + for (j = 0; j < 64; j++) + { + i = P_RandomKey(PR_PLAYERSTARTS, numdmstarts); + if (G_CheckSpot(playernum, deathmatchstarts[i])) + return deathmatchstarts[i]; + } + } if (doprints) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n")); return NULL; diff --git a/src/info.c b/src/info.c index 51dd15cfc..b23860213 100644 --- a/src/info.c +++ b/src/info.c @@ -4166,7 +4166,7 @@ state_t states[NUMSTATES] = //{SPR_ICAP, FF_FLOORSPRITE|5, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_INSIDE {SPR_NULL, 0, 1, {NULL}, 6, 1, S_SPAWNSTATE}, // S_MONITOR_DAMAGE - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_MONITOR_DEATH + {SPR_NULL, 0, 50, {NULL}, 0, 0, S_NULL}, // S_MONITOR_DEATH {SPR_IMON, FF_PAPERSPRITE|1, 1, {NULL}, 3, 1, S_MONITOR_SCREEN1B}, // S_MONITOR_SCREEN1A {SPR_IMON, FF_PAPERSPRITE|0, 1, {NULL}, 3, 1, S_MONITOR_SCREEN2A}, // S_MONITOR_SCREEN1B {SPR_IMON, FF_PAPERSPRITE|2, 1, {NULL}, 3, 1, S_MONITOR_SCREEN2B}, // S_MONITOR_SCREEN2A diff --git a/src/k_battle.c b/src/k_battle.c index 02aa9c24a..8e9aba69f 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -150,7 +150,7 @@ void K_CheckBumpers(void) } } - if (numingame <= 2 && battleovertime.enabled && battleovertime.radius <= BARRIER_MIN_RADIUS) + if (numingame - eliminated <= 2 && battleovertime.enabled && battleovertime.radius <= BARRIER_MIN_RADIUS) { Music_Stop("battle_overtime"); S_StartSound(NULL, sfx_kc4b); // Loud noise helps mask transition @@ -383,7 +383,7 @@ void K_RunPaperItemSpawners(void) return; } - if (leveltime == g_battleufo.due) + if (leveltime == g_battleufo.due && overtime == false) { Obj_SpawnBattleUFOFromSpawner(); } @@ -722,8 +722,9 @@ void K_RunBattleOvertime(void) if (battleovertime.radius > minradius) { + extern consvar_t cv_barriertime; tic_t t = leveltime - battleovertime.start; - const tic_t duration = 30*TICRATE; + const tic_t duration = cv_barriertime.value * TICRATE; battleovertime.radius = Easing_OutSine(min(t, duration) * FRACUNIT / duration, battleovertime.initial_radius, minradius); } diff --git a/src/k_collide.cpp b/src/k_collide.cpp index da30e6b94..71b06cb9a 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -858,7 +858,9 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) angle_t thrangle = R_PointToAngle2(victim->x, victim->y, shield->x, shield->y); attacker->momx = attacker->momy = 0; - P_Thrust(attacker, thrangle, FRACUNIT*7); + P_Thrust(attacker, thrangle, mapobjectscale*7); + + P_DamageMobj(attacker, victim, victim, 1, DMG_TUMBLE); // A little extra juice, so successful reads are usually positive or zero on spheres. victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40); @@ -875,14 +877,14 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) attackerPlayer->flashing = 0; // Localized broly for a local event. - if (mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag)) + if (mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag/2)) { broly->extravalue2 = 16*mapobjectscale; } P_PlayVictorySound(victim); - P_DamageMobj(attacker, victim, victim, 1, DMG_STING); + P_DamageMobj(attacker, victim, victim, 1, DMG_TUMBLE); S_StartSound(victim, sfx_mbv92); K_AddHitLag(attacker, victimHitlag, true); @@ -890,9 +892,6 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) K_DoPowerClash(shield, victim); // REJECTED - attacker->hitlag = victimHitlag; // No, seriously, we do not care about K_AddHitLag's idea of a normal maximum - shield->hitlag = attacker->hitlag; - shield->extravalue2 = 1; return true; diff --git a/src/k_hud_track.cpp b/src/k_hud_track.cpp index 3b3ddb98b..a0599607a 100644 --- a/src/k_hud_track.cpp +++ b/src/k_hud_track.cpp @@ -33,9 +33,9 @@ namespace enum class Visibility { - kHidden, kVisible, kTransparent, + kFlicker, }; struct TargetTracking @@ -280,31 +280,29 @@ bool is_object_tracking_target(const mobj_t* mobj) return is_player_tracking_target() && Obj_MonitorGetEmerald(mobj) != 0; case MT_SUPER_FLICKY: - return Obj_IsSuperFlickyTargettingYou(mobj, stplyr->mo); + return Obj_IsSuperFlickyWhippable(mobj, stplyr->mo); case MT_SPRAYCAN: - return !(mobj->renderflags & (RF_TRANSMASK | RF_DONTDRAW)); // the spraycan wasn't collected yet + return !(mobj->renderflags & (RF_TRANSMASK | RF_DONTDRAW)) && // the spraycan wasn't collected yet + P_CheckSight(stplyr->mo, const_cast(mobj)); default: return false; } } -Visibility is_object_visible(mobj_t* mobj) +Visibility is_object_visible(const mobj_t* mobj) { switch (mobj->type) { + case MT_SPRAYCAN: case MT_SUPER_FLICKY: // Always flickers. - return (leveltime & 1) ? Visibility::kVisible : Visibility::kHidden; - - case MT_SPRAYCAN: - // Flickers, but only when visible. - return P_CheckSight(stplyr->mo, mobj) && (leveltime & 1) ? Visibility::kVisible : Visibility::kHidden; + return Visibility::kFlicker; default: // Transparent when not visible. - return P_CheckSight(stplyr->mo, mobj) ? Visibility::kVisible : Visibility::kTransparent; + return P_CheckSight(stplyr->mo, const_cast(mobj)) ? Visibility::kVisible : Visibility::kTransparent; } } @@ -312,7 +310,7 @@ void K_DrawTargetTracking(const TargetTracking& target) { Visibility visibility = is_object_visible(target.mobj); - if (visibility == Visibility::kHidden) + if (visibility == Visibility::kFlicker && (leveltime & 1)) { return; } diff --git a/src/k_kart.c b/src/k_kart.c index c481cb13a..74aeaba21 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3471,7 +3471,7 @@ fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dor if (player->spheres > 0) { - fixed_t sphereAdd = (FRACUNIT/40); // 100% at max + fixed_t sphereAdd = (FRACUNIT/60); // 66% at max finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres)); } @@ -3552,7 +3552,7 @@ UINT16 K_GetKartFlashing(const player_t *player) if (gametyperules & GTR_BUMPERS) { - return 1; + return 0; } if (player == NULL) @@ -3831,7 +3831,11 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { S_StartSound(t1, sfx_gbrk); K_AddHitLag(t1, 24, true); - P_DamageMobj(t1, t2, t2, 1, DMG_STING); + + angle_t thrangle = R_PointToAngle2(t1->x, t1->y, t2->x, t2->y); + P_Thrust(t1, thrangle, 7*mapobjectscale); + + P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE); clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK); @@ -8446,12 +8450,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->spheredigestion == 0) { - player->spheres--; + if (player->spheres > 5) + player->spheres--; player->spheredigestion = spheredigestion; } if (K_PlayerGuard(player) && !K_PowerUpRemaining(player, POWERUP_BARRIER) && (player->ebrakefor%6 == 0)) player->spheres--; + + if (player->instaWhipCharge && !K_PowerUpRemaining(players, POWERUP_BADGE) && leveltime%6 == 0) + player->spheres--; } else { @@ -8694,6 +8702,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->justbumped > 0) player->justbumped--; + if (K_PressingEBrake(player) == true && onground) + { + if (gametyperules & GTR_BUMPERS) + player->instaWhipCooldown = INSTAWHIP_DROPGUARD; // Delay whip out of spindash and guard. + else + player->instaWhipCharge = 0; // Not that important in race, avoid black flash. + } + if (player->instaWhipCooldown) { player->instaWhipCharge = 0; @@ -11568,9 +11584,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (K_PowerUpRemaining(player, POWERUP_BADGE)) { + if (P_PlayerInPain(player)) + { + releasedwhip = false; + player->instaWhipCharge = 0; + } + else + { + releasedwhip = (ATTACK_IS_DOWN && player->rings <= 0 && player->itemflags & IF_USERINGS); + player->instaWhipCharge = INSTAWHIP_CHARGETIME; + } + chargingwhip = false; - releasedwhip = (ATTACK_IS_DOWN && player->rings <= 0); - player->instaWhipCharge = INSTAWHIP_CHARGETIME; player->instaWhipCooldown = 0; } diff --git a/src/objects/monitor.c b/src/objects/monitor.c index 2a78dc586..359210d8e 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -8,6 +8,7 @@ #include "../k_battle.h" #include "../m_random.h" #include "../r_main.h" +#include "../s_sound.h" #define FINE90 (FINEANGLES/4) #define FINE180 (FINEANGLES/2) @@ -664,7 +665,8 @@ Obj_MonitorOnDamage monitor_rammingspeed(monitor) = inflictor ? FixedDiv(FixedHypot(inflictor->momx, inflictor->momy), 4 * inflictor->radius) : 0; monitor->hitlag = - 6 * get_damage_multiplier(monitor) / FRACUNIT; + 3 * get_damage_multiplier(monitor) / FRACUNIT; + S_StartSound(monitor, sfx_kc40); } void @@ -707,6 +709,8 @@ Obj_MonitorOnDeath (mobj_t *monitor) spawn_monitor_explosion(monitor); + S_StartSound(monitor, sfx_gshcc); + // There is hitlag from being damaged, so remove // tangibility RIGHT NOW. monitor->flags &= ~(MF_SOLID); diff --git a/src/objects/random-item.c b/src/objects/random-item.c index 7a93d964b..550b98d73 100644 --- a/src/objects/random-item.c +++ b/src/objects/random-item.c @@ -147,6 +147,10 @@ void Obj_RandomItemVisuals(mobj_t *mobj) boolean Obj_RandomItemSpawnIn(mobj_t *mobj) { + // battleprisons isn't set in time to do this on spawn. GROAN + if ((mobj->flags2 & MF2_BOSSFLEE) && (gametyperules & GTR_BUMPERS) && !battleprisons) + mobj->renderflags |= RF_DONTDRAW; + if ((leveltime == starttime) && !(gametyperules & GTR_CIRCUIT) && (mobj->flags2 & MF2_BOSSFLEE)) // here on map start? { if (gametyperules & GTR_PAPERITEMS) diff --git a/src/p_inter.c b/src/p_inter.c index 48ea0c4e2..dc955cfc7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3211,7 +3211,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da source->player->invincibilitytimer += kinvextend; // This has a scaling boost type now, don't let it get too crazy - source->player->invincibilitytimer = max(source->player->invincibilitytimer, 20*TICRATE); + source->player->invincibilitytimer = min(source->player->invincibilitytimer, 20*TICRATE); if (P_IsDisplayPlayer(source->player)) S_StartSound(NULL, sfx_gsha7); @@ -3329,7 +3329,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } if (gametyperules & GTR_BUMPERS) - player->spheres = min(player->spheres + 5, 40); + player->spheres = min(player->spheres + 10, 40); if ((hardhit == true) || cv_kartdebughuddrop.value) { @@ -3411,6 +3411,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (source && source->player && target) G_GhostAddHit((INT32) (source->player - players), target); + if ((gametyperules & GTR_BUMPERS) && !battleprisons) + laglength /= 2; + K_SetHitLagForObjects(target, inflictor, source, laglength, true); target->flags2 |= MF2_ALREADYHIT; diff --git a/src/p_spec.c b/src/p_spec.c index 27c75a51b..55394e72a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -50,6 +50,7 @@ #include "acs/interface.h" #include "m_easing.h" #include "music.h" +#include "k_battle.h" // battleprisons // Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog #include @@ -9517,6 +9518,11 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset) addZ = -addZ; } + if ((gametyperules & GTR_PRISONS) && !battleprisons) + { + addZ /= 2; + } + if (cv_screenshake.value == 1) // Half { addZ /= 2;