Zombie disease is easier to spread and deadly in minutes. Zombies heal over time. (#16235)
* Nerf Space zombies, get DoT in space (barotrauma) and spawn stunned. - Also discard any helmet or mask you might be wearing. * Zombies have heal over time, infection far more fatal - Stun time reduced to 2 seconds * Zombification occurs after you die, rather than after you crit. - Zombies cannot inflict Zombification DoT on other zombies. * Heal shock damage, space zombies are back. * Lower the chance of infection per hit * Removed the stun, reduced zombification virus slightly
This commit is contained in:
@@ -12,12 +12,18 @@ public sealed class PendingZombieComponent : Component
|
|||||||
{
|
{
|
||||||
[DataField("damage")] public DamageSpecifier Damage = new()
|
[DataField("damage")] public DamageSpecifier Damage = new()
|
||||||
{
|
{
|
||||||
DamageDict = new Dictionary<string, FixedPoint2>()
|
DamageDict = new ()
|
||||||
{
|
{
|
||||||
{ "Blunt", FixedPoint2.New(1) }
|
{ "Blunt", 0.5 },
|
||||||
|
{ "Cellular", 0.2 },
|
||||||
|
{ "Toxin", 0.2 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[DataField("nextTick", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
[DataField("nextTick", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||||
public TimeSpan NextTick;
|
public TimeSpan NextTick;
|
||||||
|
|
||||||
|
// Scales damage over time.
|
||||||
|
[DataField("infectedSecs")]
|
||||||
|
public int InfectedSecs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,12 +63,28 @@ namespace Content.Server.Zombies
|
|||||||
var query = EntityQueryEnumerator<PendingZombieComponent>();
|
var query = EntityQueryEnumerator<PendingZombieComponent>();
|
||||||
var curTime = _timing.CurTime;
|
var curTime = _timing.CurTime;
|
||||||
|
|
||||||
|
// Hurt the living infected
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
{
|
{
|
||||||
if (comp.NextTick < curTime)
|
if (comp.NextTick + TimeSpan.FromSeconds(1) > curTime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
comp.NextTick += TimeSpan.FromSeconds(1);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
var zomb_query = EntityQueryEnumerator<ZombieComponent>();
|
||||||
|
// Heal the zombified
|
||||||
|
while (zomb_query.MoveNext(out var uid, out var comp))
|
||||||
|
{
|
||||||
|
if (comp.NextTick + TimeSpan.FromSeconds(1) > curTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comp.NextTick = curTime;
|
||||||
_damageable.TryChangeDamage(uid, comp.Damage, true, false);
|
_damageable.TryChangeDamage(uid, comp.Damage, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,14 +182,18 @@ namespace Content.Server.Zombies
|
|||||||
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
|
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_random.Prob(GetZombieInfectionChance(entity, component)))
|
|
||||||
{
|
|
||||||
EnsureComp<PendingZombieComponent>(entity);
|
|
||||||
EnsureComp<ZombifyOnDeathComponent>(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasComp<ZombieComponent>(entity))
|
if (HasComp<ZombieComponent>(entity))
|
||||||
|
{
|
||||||
args.BonusDamage = -args.BaseDamage * zombieComp.OtherZombieDamageCoefficient;
|
args.BonusDamage = -args.BaseDamage * zombieComp.OtherZombieDamageCoefficient;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_random.Prob(GetZombieInfectionChance(entity, component)))
|
||||||
|
{
|
||||||
|
EnsureComp<PendingZombieComponent>(entity);
|
||||||
|
EnsureComp<ZombifyOnDeathComponent>(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((mobState.CurrentState == MobState.Dead || mobState.CurrentState == MobState.Critical)
|
if ((mobState.CurrentState == MobState.Dead || mobState.CurrentState == MobState.Critical)
|
||||||
&& !HasComp<ZombieComponent>(entity))
|
&& !HasComp<ZombieComponent>(entity))
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.Administration.Commands;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
@@ -22,6 +23,7 @@ using Content.Shared.Hands.EntitySystems;
|
|||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Mobs;
|
using Content.Shared.Mobs;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Nutrition.Components;
|
using Content.Shared.Nutrition.Components;
|
||||||
@@ -54,6 +56,8 @@ namespace Content.Server.Zombies
|
|||||||
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
||||||
[Dependency] private readonly IChatManager _chatMan = default!;
|
[Dependency] private readonly IChatManager _chatMan = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
|
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -67,8 +71,7 @@ namespace Content.Server.Zombies
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
|
private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
|
||||||
{
|
{
|
||||||
if (args.NewMobState == MobState.Dead ||
|
if (args.NewMobState == MobState.Dead)
|
||||||
args.NewMobState == MobState.Critical)
|
|
||||||
{
|
{
|
||||||
ZombifyEntity(uid, args.Component);
|
ZombifyEntity(uid, args.Component);
|
||||||
}
|
}
|
||||||
@@ -181,10 +184,17 @@ namespace Content.Server.Zombies
|
|||||||
if (TryComp<TemperatureComponent>(target, out var tempComp))
|
if (TryComp<TemperatureComponent>(target, out var tempComp))
|
||||||
tempComp.ColdDamage.ClampMax(0);
|
tempComp.ColdDamage.ClampMax(0);
|
||||||
|
|
||||||
|
// Zombies can revive themselves
|
||||||
|
_mobThreshold.SetAllowRevives(target, true);
|
||||||
|
|
||||||
//Heals the zombie from all the damage it took while human
|
//Heals the zombie from all the damage it took while human
|
||||||
if (TryComp<DamageableComponent>(target, out var damageablecomp))
|
if (TryComp<DamageableComponent>(target, out var damageablecomp))
|
||||||
_damageable.SetAllDamage(target, damageablecomp, 0);
|
_damageable.SetAllDamage(target, damageablecomp, 0);
|
||||||
|
|
||||||
|
// Revive them now
|
||||||
|
if (TryComp<MobStateComponent>(target, out var mobstate) && mobstate.CurrentState==MobState.Dead)
|
||||||
|
_mobState.ChangeMobState(target, MobState.Alive, mobstate);
|
||||||
|
|
||||||
//gives it the funny "Zombie ___" name.
|
//gives it the funny "Zombie ___" name.
|
||||||
var meta = MetaData(target);
|
var meta = MetaData(target);
|
||||||
zombiecomp.BeforeZombifiedEntityName = meta.EntityName;
|
zombiecomp.BeforeZombifiedEntityName = meta.EntityName;
|
||||||
@@ -221,6 +231,8 @@ namespace Content.Server.Zombies
|
|||||||
_sharedHands.RemoveHand(target, hand.Name);
|
_sharedHands.RemoveHand(target, hand.Name);
|
||||||
}
|
}
|
||||||
RemComp<HandsComponent>(target);
|
RemComp<HandsComponent>(target);
|
||||||
|
// No longer waiting to become a zombie:
|
||||||
|
RemComp<PendingZombieComponent>(target);
|
||||||
|
|
||||||
//zombie gamemode stuff
|
//zombie gamemode stuff
|
||||||
RaiseLocalEvent(new EntityZombifiedEvent(target));
|
RaiseLocalEvent(new EntityZombifiedEvent(target));
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using Content.Shared.Chat.Prototypes;
|
using Content.Shared.Chat.Prototypes;
|
||||||
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
using static Content.Shared.Humanoid.HumanoidAppearanceState;
|
using static Content.Shared.Humanoid.HumanoidAppearanceState;
|
||||||
|
|
||||||
@@ -22,14 +24,14 @@ namespace Content.Shared.Zombies
|
|||||||
/// The baseline infection chance you have if you are completely nude
|
/// The baseline infection chance you have if you are completely nude
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float MaxZombieInfectionChance = 0.50f;
|
public float MaxZombieInfectionChance = 0.40f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The minimum infection chance possible. This is simply to prevent
|
/// The minimum infection chance possible. This is simply to prevent
|
||||||
/// being invincible by bundling up.
|
/// being invincible by bundling up.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float MinZombieInfectionChance = 0.05f;
|
public float MinZombieInfectionChance = 0.10f;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float ZombieMovementSpeedDebuff = 0.75f;
|
public float ZombieMovementSpeedDebuff = 0.75f;
|
||||||
@@ -86,5 +88,21 @@ namespace Content.Shared.Zombies
|
|||||||
public string? EmoteSoundsId = "Zombie";
|
public string? EmoteSoundsId = "Zombie";
|
||||||
|
|
||||||
public EmoteSoundsPrototype? EmoteSounds;
|
public EmoteSoundsPrototype? EmoteSounds;
|
||||||
|
|
||||||
|
// Heal on tick
|
||||||
|
[DataField("nextTick", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextTick;
|
||||||
|
|
||||||
|
[DataField("damage")] public DamageSpecifier Damage = new()
|
||||||
|
{
|
||||||
|
DamageDict = new ()
|
||||||
|
{
|
||||||
|
{ "Blunt", -0.3 },
|
||||||
|
{ "Slash", -0.2 },
|
||||||
|
{ "Heat", -0.2 },
|
||||||
|
{ "Cold", -0.2 },
|
||||||
|
{ "Shock", -0.2 },
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user