Zombie virus delayed from 20-30 minutes from rule start. (#16346)

This commit is contained in:
Tom Leys
2023-05-16 17:59:39 +12:00
committed by GitHub
parent 10348fe11d
commit d3b6bb62c0
8 changed files with 120 additions and 19 deletions

View File

@@ -55,6 +55,7 @@ namespace Content.Server.Zombies
SubscribeLocalEvent<ZombieComponent, TryingToSleepEvent>(OnSleepAttempt);
SubscribeLocalEvent<PendingZombieComponent, MapInitEvent>(OnPendingMapInit);
SubscribeLocalEvent<PendingZombieComponent, MobStateChangedEvent>(OnPendingMobState);
}
private void OnPendingMapInit(EntityUid uid, PendingZombieComponent component, MapInitEvent args)
@@ -65,24 +66,47 @@ namespace Content.Server.Zombies
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<PendingZombieComponent, DamageableComponent>();
var query = EntityQueryEnumerator<PendingZombieComponent, DamageableComponent, MobStateComponent>();
var curTime = _timing.CurTime;
var zombQuery = EntityQueryEnumerator<ZombieComponent, DamageableComponent, MobStateComponent>();
// Hurt the living infected
while (query.MoveNext(out var uid, out var comp, out var damage))
while (query.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.InfectedSecs += 1;
// Pain of becoming a zombie grows over time
// 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, damage);
comp.InfectedSecs += 1;
// See if there should be a warning popup for the player.
if (comp.InfectionWarnings.TryGetValue(comp.InfectedSecs, out var popupStr))
{
_popup.PopupEntity(Loc.GetString(popupStr), uid, uid);
}
if (comp.InfectedSecs < 0)
{
// This zombie has a latent virus, probably set up by ZombieRuleSystem. No damage yet.
continue;
}
// Pain of becoming a zombie grows over time
// By scaling the number of seconds we have an accessible way to scale this exponential function.
// The function was hand tuned to 120 seconds, hence the 120 constant here.
var scaledSeconds = (120.0f / comp.MaxInfectionLength) * comp.InfectedSecs;
// 1x at 30s, 3x at 60s, 6x at 90s, 10x at 120s. Limit at 20x so we don't gib you.
var painMultiple = Math.Min(20f, 0.1f + 0.02f * scaledSeconds + 0.0005f * scaledSeconds * scaledSeconds);
if (mobState.CurrentState == MobState.Critical)
{
// Speed up their transformation when they are (or have been) in crit by ensuring their damage
// multiplier is at least 10x
painMultiple = Math.Max(comp.MinimumCritMultiplier, painMultiple);
}
_damageable.TryChangeDamage(uid, comp.Damage * painMultiple, true, false, damage);
}
// Heal the zombified
@@ -168,6 +192,15 @@ namespace Content.Server.Zombies
}
}
private void OnPendingMobState(EntityUid uid, PendingZombieComponent pending, MobStateChangedEvent args)
{
if (args.NewMobState == MobState.Critical)
{
// Immediately jump to an active virus when you crit
pending.InfectedSecs = Math.Max(0, pending.InfectedSecs);
}
}
private float GetZombieInfectionChance(EntityUid uid, ZombieComponent component)
{
var baseChance = component.MaxZombieInfectionChance;
@@ -227,7 +260,8 @@ namespace Content.Server.Zombies
{
if (_random.Prob(GetZombieInfectionChance(entity, component)))
{
EnsureComp<PendingZombieComponent>(entity);
var pending = EnsureComp<PendingZombieComponent>(entity);
pending.MaxInfectionLength = _random.NextFloat(0.25f, 1.0f) * component.ZombieInfectionTurnTime;
EnsureComp<ZombifyOnDeathComponent>(entity);
}
}