Zombies recover faster from crit. They heal Piercing damage (#16325)

This commit is contained in:
Tom Leys 2023-05-16 15:58:36 +12:00 committed by GitHub
parent 525d746d6e
commit eab0121744
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 8 deletions

View File

@ -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<PendingZombieComponent>();
var query = EntityQueryEnumerator<PendingZombieComponent, DamageableComponent>();
var curTime = _timing.CurTime;
var zombQuery = EntityQueryEnumerator<ZombieComponent, DamageableComponent, MobStateComponent>();
// 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<ZombieComponent>();
// 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);
}
}
}
}

View File

@ -26,6 +26,25 @@ namespace Content.Shared.Zombies
[ViewVariables(VVAccess.ReadWrite)]
public float MaxZombieInfectionChance = 0.40f;
/// <summary>
/// Chance that this zombie be permanently killed (rolled once on crit->death transition)
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float ZombiePermadeathChance = 0.70f;
/// <summary>
/// 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.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float ZombieReviveChance = 0.03f;
/// <summary>
/// Has this zombie stopped healing now that it's died for real?
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool Permadeath = false;
/// <summary>
/// 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 },

View File

@ -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.
zombie-round-end-user-was-survivor = - [color=White]{$name}[/color] ([color=gray]{$username}[/color]) survived the outbreak.

View File

@ -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.