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

@ -220,7 +220,7 @@ public sealed partial class OutnumberedPlugin
vpd.Deaths++; vpd.Streak = 0;
// streak-earned availability is lost on death; active effects end. Cooldowns keep ticking (spec §4).
Array.Clear(vpd.AbilityActiveUntil);
_driver.OnHumanDeath(victim, vpd); // survival: run wipe detection (no respawn; revived at wave-clear). No-op elsewhere.
_driver.OnHumanDeath(victim, vpd, attacker); // survival: wipe detection + revive-beacon (attacker gates combat vs suicide). No-op elsewhere.
}
// attacker kill: human -> kills++/streak/XP + mode result; bot -> mode result only (bots have no PlayerData)
@ -368,7 +368,10 @@ public sealed partial class OutnumberedPlugin
{
if (p.Team is CsTeam.Terrorist or CsTeam.None)
{
p.SwitchTeam(CsTeam.Spectator);
// ChangeTeam, NOT SwitchTeam: SwitchTeam keeps the player alive, but an alive spectator is invalid, so a
// player who spawned alive on T (survival has no death-respawn to correct it) would silently stay on T.
// ChangeTeam follows gamemode rules (suicides + relocates), so the park actually takes.
p.ChangeTeam(CsTeam.Spectator);
p.PrintToChat("[Outnumbered] A survival run is in progress — you'll join the next one.");
}
return;
@ -380,10 +383,11 @@ public sealed partial class OutnumberedPlugin
switch (p.Team)
{
// an over-cap CT, or a T/None arrival when CT is already full -> spectator (both land on the same outcome)
// an over-cap CT, or a T/None arrival when CT is already full -> spectator (both land on the same outcome).
// ChangeTeam, not SwitchTeam: SwitchTeam keeps a live player alive, which can't hold on the spectator team.
case CsTeam.CounterTerrorist when ctHumans >= cap:
case CsTeam.Terrorist or CsTeam.None when ctHumans >= cap:
p.SwitchTeam(CsTeam.Spectator);
p.ChangeTeam(CsTeam.Spectator);
p.PrintToChat($"[Outnumbered] CT is full (max {cap}) — moved to spectator.");
break;
// a T/None arrival with room -> put them on CT (native DM spawns them on the new team)