* 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
{
[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))]
public TimeSpan NextTick;
+
+ // Scales damage over time.
+ [DataField("infectedSecs")]
+ public int InfectedSecs;
}
var query = EntityQueryEnumerator<PendingZombieComponent>();
var curTime = _timing.CurTime;
+ // Hurt the living infected
while (query.MoveNext(out var uid, out var comp))
{
- if (comp.NextTick < curTime)
+ if (comp.NextTick + TimeSpan.FromSeconds(1) > curTime)
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);
}
}
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
continue;
- if (_random.Prob(GetZombieInfectionChance(entity, component)))
- {
- EnsureComp<PendingZombieComponent>(entity);
- EnsureComp<ZombifyOnDeathComponent>(entity);
- }
-
if (HasComp<ZombieComponent>(entity))
+ {
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)
&& !HasComp<ZombieComponent>(entity))
+using Content.Server.Administration.Commands;
using Content.Server.Atmos.Components;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Humanoid;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
+using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Nutrition.Components;
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
[Dependency] private readonly IChatManager _chatMan = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
+ [Dependency] private readonly MobStateSystem _mobState = default!;
+ [Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
public override void Initialize()
{
/// </summary>
private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
{
- if (args.NewMobState == MobState.Dead ||
- args.NewMobState == MobState.Critical)
+ if (args.NewMobState == MobState.Dead)
{
ZombifyEntity(uid, args.Component);
}
if (TryComp<TemperatureComponent>(target, out var tempComp))
tempComp.ColdDamage.ClampMax(0);
+ // Zombies can revive themselves
+ _mobThreshold.SetAllowRevives(target, true);
+
//Heals the zombie from all the damage it took while human
if (TryComp<DamageableComponent>(target, out var damageablecomp))
_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.
var meta = MetaData(target);
zombiecomp.BeforeZombifiedEntityName = meta.EntityName;
_sharedHands.RemoveHand(target, hand.Name);
}
RemComp<HandsComponent>(target);
+ // No longer waiting to become a zombie:
+ RemComp<PendingZombieComponent>(target);
//zombie gamemode stuff
RaiseLocalEvent(new EntityZombifiedEvent(target));
using Content.Shared.Chat.Prototypes;
+using Content.Shared.Damage;
using Content.Shared.Roles;
using Content.Shared.Humanoid;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using static Content.Shared.Humanoid.HumanoidAppearanceState;
/// The baseline infection chance you have if you are completely nude
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
- public float MaxZombieInfectionChance = 0.50f;
+ public float MaxZombieInfectionChance = 0.40f;
/// <summary>
/// The minimum infection chance possible. This is simply to prevent
/// being invincible by bundling up.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
- public float MinZombieInfectionChance = 0.05f;
+ public float MinZombieInfectionChance = 0.10f;
[ViewVariables(VVAccess.ReadWrite)]
public float ZombieMovementSpeedDebuff = 0.75f;
public string? EmoteSoundsId = "Zombie";
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 },
+ }
+ };
}
}