Survival mode bugfixes and revive mechanism
All checks were successful
CI / lint (push) Successful in 31s
CI / build (push) Successful in 32s
CI / release (push) Successful in 32s

This commit is contained in:
Kamal Tufekcic 2026-07-08 18:10:09 +03:00
commit 2fa85e8b1f
14 changed files with 529 additions and 35 deletions

View file

@ -100,13 +100,43 @@ public class BalanceInvariantTests
[Fact]
public void Per_mode_override_applies_only_named_fields()
{
// The survival override down-weights the skill factors so the WAVE FLOOR drives difficulty; everything else inherits.
// The survival override zeroes every skill factor so the WAVE FLOOR alone drives difficulty; everything else inherits.
var baseH = T.Hcap();
var ov = T.Surv().Handicap!; // the default survival override
var eff = ov.ApplyTo(baseH);
Assert.Equal(0.3, eff.KdWeight); // overridden
Assert.Equal(0.0, eff.KdWeight); // overridden -> in-run performance cannot move the handicap
Assert.Equal(0.0, eff.HsWeight);
Assert.Equal(0.0, eff.StreakWeight);
Assert.Equal(0.0, eff.LevelWeight);
Assert.Equal(0.0, eff.ProgressWeight);
Assert.Equal(10.0, eff.MTakeCeiling); // overridden
Assert.Equal(baseH.MasterDifficulty, eff.MasterDifficulty); // inherited from base (not set in the override)
Assert.Equal(baseH.Curve, eff.Curve); // inherited
}
[Fact]
public void Survival_handicap_is_wave_only_and_invariant_to_performance()
{
// Bug fix: survival's handicap must depend ONLY on the wave (via the floor), never on K/D / headshots / streak /
// level. A dominant player and a struggling player on the SAME wave get the SAME t, and killing more bots inside a
// wave never changes it — so the 1st and the 100th kill of a wave take identical shots. (Before, K/D + HS saturated
// after a handful of kills and drove a good player straight to the floor mid-wave-1.)
var rh = T.Resolved(T.Surv().Handicap!.ApplyTo(T.Hcap()));
foreach (var wave in new[] { 1, 5, 12, 25 })
{
double floor = SurvivalEconomy.HandicapFloor(wave, T.Surv());
double dominant = HandicapModel.ComputeT(
T.Snap(level: 100, kills: 60, deaths: 0, headshotKills: 60, streak: 50, floor: floor), rh);
double struggling = HandicapModel.ComputeT(
T.Snap(level: 1, kills: 0, deaths: 20, headshotKills: 0, streak: 0, floor: floor), rh);
double freshMidWave = HandicapModel.ComputeT(
T.Snap(level: 1, kills: 7, deaths: 0, headshotKills: 7, streak: 7, floor: floor), rh);
Assert.Equal(dominant, struggling, Eps); // same wave -> same handicap, regardless of performance
Assert.Equal(dominant, freshMidWave, Eps);
// it IS just the eased wave floor (floor >= 0 for any real wave, so Ease reduces to Pow)
Assert.Equal(Math.Pow(floor, rh.Config.Curve), dominant, Eps);
}
}
}