From eab0121744c10a14c663aeb7185e60de05df0188 Mon Sep 17 00:00:00 2001 From: Tom Leys Date: Tue, 16 May 2023 15:58:36 +1200 Subject: [PATCH] Zombies recover faster from crit. They heal Piercing damage (#16325) --- Content.Server/Zombies/ZombieSystem.cs | 49 ++++++++++++++++--- Content.Shared/Zombies/ZombieComponent.cs | 22 ++++++++- .../game-presets/preset-zombies.ftl | 3 +- Resources/Locale/en-US/zombies/zombie.ftl | 2 + 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/Content.Server/Zombies/ZombieSystem.cs b/Content.Server/Zombies/ZombieSystem.cs index 8f4b737fb6..8d5d0cd793 100644 --- a/Content.Server/Zombies/ZombieSystem.cs +++ b/Content.Server/Zombies/ZombieSystem.cs @@ -14,6 +14,8 @@ using Content.Shared.Damage; using Content.Shared.Inventory; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; using Content.Shared.Weapons.Melee.Events; using Content.Shared.Zombies; using Robust.Shared.Prototypes; @@ -35,6 +37,9 @@ namespace Content.Server.Zombies [Dependency] private readonly AutoEmoteSystem _autoEmote = default!; [Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!; [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { @@ -60,12 +65,15 @@ namespace Content.Server.Zombies public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); var curTime = _timing.CurTime; + var zombQuery = EntityQueryEnumerator(); + // Hurt the living infected - while (query.MoveNext(out var uid, out var comp)) + while (query.MoveNext(out var uid, out var comp, out var damage)) { + // Process only once per second if (comp.NextTick + TimeSpan.FromSeconds(1) > curTime) continue; @@ -74,18 +82,34 @@ namespace Content.Server.Zombies // 1x at 30s, 3x at 60s, 6x at 90s, 10x at 120s. var pain_multiple = 0.1 + 0.02 * comp.InfectedSecs + 0.0005 * comp.InfectedSecs * comp.InfectedSecs; comp.NextTick = curTime; - _damageable.TryChangeDamage(uid, comp.Damage * pain_multiple, true, false); + _damageable.TryChangeDamage(uid, comp.Damage * pain_multiple, true, false, damage); } - var zomb_query = EntityQueryEnumerator(); // Heal the zombified - while (zomb_query.MoveNext(out var uid, out var comp)) + while (zombQuery.MoveNext(out var uid, out var comp, out var damage, out var mobState)) { + // Process only once per second if (comp.NextTick + TimeSpan.FromSeconds(1) > curTime) continue; comp.NextTick = curTime; - _damageable.TryChangeDamage(uid, comp.Damage, true, false); + + if (comp.Permadeath) + { + // No healing + continue; + } + + if (mobState.CurrentState == MobState.Alive) + { + // Gradual healing for living zombies. + _damageable.TryChangeDamage(uid, comp.Damage, true, false, damage); + } + else if (_random.Prob(comp.ZombieReviveChance)) + { + // There's a small chance to reverse all the zombie's damage (damage.Damage) in one go + _damageable.TryChangeDamage(uid, -damage.Damage, true, false, damage); + } } } @@ -128,6 +152,19 @@ namespace Content.Server.Zombies // Stop random groaning _autoEmote.RemoveEmote(uid, "ZombieGroan"); + + if (args.NewMobState == MobState.Dead) + { + // Roll to see if this zombie is not coming back. + // Note that due to damage reductions it takes a lot of hits to gib a zombie without this. + if (_random.Prob(component.ZombiePermadeathChance)) + { + // You're dead! No reviving for you. + _mobThreshold.SetAllowRevives(uid, false); + component.Permadeath = true; + _popup.PopupEntity(Loc.GetString("zombie-permadeath"), uid, uid); + } + } } } diff --git a/Content.Shared/Zombies/ZombieComponent.cs b/Content.Shared/Zombies/ZombieComponent.cs index 02b5162634..87943531fc 100644 --- a/Content.Shared/Zombies/ZombieComponent.cs +++ b/Content.Shared/Zombies/ZombieComponent.cs @@ -26,6 +26,25 @@ namespace Content.Shared.Zombies [ViewVariables(VVAccess.ReadWrite)] public float MaxZombieInfectionChance = 0.40f; + /// + /// Chance that this zombie be permanently killed (rolled once on crit->death transition) + /// + [ViewVariables(VVAccess.ReadWrite)] + public float ZombiePermadeathChance = 0.70f; + + /// + /// Chance that this zombie will be healed (rolled each second when in crit or dead) + /// 3% means you have a 60% chance after 30 secs and a 84% chance after 60. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float ZombieReviveChance = 0.03f; + + /// + /// Has this zombie stopped healing now that it's died for real? + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool Permadeath = false; + /// /// The minimum infection chance possible. This is simply to prevent /// being invincible by bundling up. @@ -97,8 +116,9 @@ namespace Content.Shared.Zombies { DamageDict = new () { - { "Blunt", -0.3 }, + { "Blunt", -0.4 }, { "Slash", -0.2 }, + { "Piercing", -0.2 }, { "Heat", -0.2 }, { "Cold", -0.2 }, { "Shock", -0.2 }, diff --git a/Resources/Locale/en-US/game-ticking/game-presets/preset-zombies.ftl b/Resources/Locale/en-US/game-ticking/game-presets/preset-zombies.ftl index d7e487ba52..cef09786de 100644 --- a/Resources/Locale/en-US/game-ticking/game-presets/preset-zombies.ftl +++ b/Resources/Locale/en-US/game-ticking/game-presets/preset-zombies.ftl @@ -5,6 +5,7 @@ zombie-not-enough-ready-players = Not enough players readied up for the game! Th zombie-no-one-ready = No players readied up! Can't start Zombies. zombie-patientzero-role-greeting = You are patient 0. Hide your infection, get supplies, and be prepared to turn once you die. +zombie-healing = You feel a stirring in your flesh zombie-alone = You feel entirely alone. @@ -24,4 +25,4 @@ zombie-round-end-survivor-count = {$count -> [one] There was only one survivor left: *[other] There were only {$count} survivors left: } -zombie-round-end-user-was-survivor = - [color=White]{$name}[/color] ([color=gray]{$username}[/color]) survived the outbreak. \ No newline at end of file +zombie-round-end-user-was-survivor = - [color=White]{$name}[/color] ([color=gray]{$username}[/color]) survived the outbreak. diff --git a/Resources/Locale/en-US/zombies/zombie.ftl b/Resources/Locale/en-US/zombies/zombie.ftl index f534a962e0..dfcddf3308 100644 --- a/Resources/Locale/en-US/zombies/zombie.ftl +++ b/Resources/Locale/en-US/zombies/zombie.ftl @@ -5,3 +5,5 @@ zombie-generic = zombie zombie-name-prefix = Zombified {$target} zombie-role-desc = A malevolent creature of the dead. zombie-role-rules = You are an antagonist. Search out the living and bite them in order to infect them and turn them into zombies. Work together with other the zombies to overtake the station. + +zombie-permadeath = This time, you're dead for real. -- 2.51.2