Zombie Rework & Polymorph Expansion (#8413)

Co-authored-by: Kara <lunarautomaton6@gmail.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
EmoGarbage404
2022-06-12 01:53:13 -04:00
committed by GitHub
parent a45529d649
commit 63fd01f3bb
30 changed files with 485 additions and 422 deletions

View File

@@ -1,19 +0,0 @@
namespace Content.Server.Disease.Components
{
/// <summary>
/// The component which records the buildup/progression of an infection
/// </summary>
[RegisterComponent]
public sealed class DiseaseBuildupComponent : Component
{
/// This could be served to be generalized to allow for multiple
/// diseases to build up at once, but it doesn't matter too much.
/// <summary>
/// The current amount of progression that has built up.
/// </summary>
[DataField("progression")]
[ViewVariables(VVAccess.ReadWrite)]
public float Progression = 0.00f;
}
}

View File

@@ -0,0 +1,30 @@
using JetBrains.Annotations;
using Content.Shared.Disease;
namespace Content.Server.Disease.Effects
{
/// <summary>
/// Adds a component to the diseased entity
/// </summary>
[UsedImplicitly]
public sealed class DiseaseAddComponent : DiseaseEffect
{
/// <summary>
/// The component that is added at the end of build up
/// </summary>
[DataField("comp")]
public string? Comp = null;
public override void Effect(DiseaseEffectArgs args)
{
if (Comp == null)
return;
EntityUid uid = args.DiseasedEntity;
var newComponent = (Component) IoCManager.Resolve<IComponentFactory>().GetComponent(Comp);
newComponent.Owner = uid;
if (!args.EntityManager.HasComponent(uid, newComponent.GetType()))
args.EntityManager.AddComponent(uid, newComponent);
}
}
}

View File

@@ -1,45 +0,0 @@
using Content.Server.Disease.Components;
using JetBrains.Annotations;
using Content.Shared.Disease;
namespace Content.Server.Disease.Effects
{
/// <summary>
/// Handles a disease which incubates over a period of time
/// before adding another component to the infected entity
/// currently used for zombie virus
/// </summary>
[UsedImplicitly]
public sealed class DiseaseProgression : DiseaseEffect
{
/// <summary>
/// The rate that's increased over time. Defaults to 1% so the probability can be varied in yaml
/// </summary>
[DataField("rate")]
[ViewVariables(VVAccess.ReadWrite)]
public float Rate = 0.01f;
/// <summary>
/// The component that is added at the end of build up
/// </summary>
[DataField("comp")]
public string? Comp = null;
public override void Effect(DiseaseEffectArgs args)
{
args.EntityManager.EnsureComponent<DiseaseBuildupComponent>(args.DiseasedEntity, out var buildup);
if (buildup.Progression < 1) //increases steadily until 100%
{
buildup.Progression += Rate;
}
else if (Comp != null)//adds the component for the later stage of the disease.
{
EntityUid uid = args.DiseasedEntity;
var newComponent = (Component) IoCManager.Resolve<IComponentFactory>().GetComponent(Comp);
newComponent.Owner = uid;
if (!args.EntityManager.HasComponent(uid, newComponent.GetType()))
args.EntityManager.AddComponent(uid, newComponent);
}
}
}
}

View File

@@ -1,37 +0,0 @@
namespace Content.Server.Disease.Zombie.Components
{
/// <summary>
/// The component which gives an entity zombie traits.
/// </summary>
[RegisterComponent]
public sealed class DiseaseZombieComponent : Component
{
/// <summary>
/// The probability that a given bite will infect a player.
/// zombie infection is not based on disease resist items like masks or gloves.
/// </summary>
[DataField("probability")]
[ViewVariables(VVAccess.ReadWrite)]
public float Probability = 0.33f;
/// <summary>
/// A multiplier on the movement speed that zombies recieve.
/// </summary>
[DataField("slowAmount")]
[ViewVariables(VVAccess.ReadWrite)]
public float SlowAmount = 0.75f;
/// <summary>
/// Whether or not the zombie needs all the zombie traits initialized upon component init
/// useful for entities that already are zombies and do not need the additional traits.
/// </summary>
[DataField("applyZombieTraits")]
public bool ApplyZombieTraits = true;
/// <summary>
/// The color of the zombie's skin
/// </summary>
[DataField("skinColor")]
public readonly Color SkinColor = (0.70f, 0.72f, 0.48f, 1);
}
}

View File

@@ -1,130 +0,0 @@
using Robust.Shared.Player;
using Content.Server.Speech.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Disease.Components;
using Content.Server.Disease.Zombie.Components;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Popups;
using Content.Server.Atmos.Components;
using Content.Server.Hands.Components;
using Content.Server.Nutrition.Components;
using Content.Server.Mind.Components;
using Content.Server.Chat.Managers;
using Content.Server.Inventory;
using Content.Shared.Damage;
using Content.Shared.MobState.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Movement.EntitySystems;
using Content.Shared.CharacterAppearance.Components;
using Content.Shared.CharacterAppearance.Systems;
using Content.Server.Weapons.Melee.ZombieTransfer.Components;
namespace Content.Server.Disease.Zombie
{
/// <summary>
/// Handles zombie propagation and inherent zombie traits
/// </summary>
public sealed class DiseaseZombieSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly ServerInventorySystem _serverInventory = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
[Dependency] private readonly SharedHumanoidAppearanceSystem _sharedHumanoidAppearance = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DiseaseZombieComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<DiseaseZombieComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
}
/// <remarks>
/// I would imagine that if this component got assigned to something other than a mob, it would throw hella errors.
/// </remarks>
private void OnComponentInit(EntityUid uid, DiseaseZombieComponent component, ComponentInit args)
{
if (!component.ApplyZombieTraits || !HasComp<MobStateComponent>(uid))
return;
RemComp<DiseaseCarrierComponent>(uid);
RemComp<DiseaseBuildupComponent>(uid);
RemComp<RespiratorComponent>(uid);
RemComp<BarotraumaComponent>(uid);
RemComp<HungerComponent>(uid);
RemComp<ThirstComponent>(uid);
EntityManager.EnsureComponent<BloodstreamComponent>(uid, out var bloodstream); //zoms need bloodstream anyway for healing
_bloodstream.SetBloodLossThreshold(uid, 0f, bloodstream);
_bloodstream.TryModifyBleedAmount(uid, -bloodstream.BleedAmount, bloodstream);
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
EntityManager.EnsureComponent<ReplacementAccentComponent>(uid).Accent = "zombie";
if (TryComp<DamageableComponent>(uid, out var comp))
{
_damageable.SetDamageModifierSetId(uid, "Zombie", comp);
_damageable.SetAllDamage(comp, 0);
}
if (TryComp<HumanoidAppearanceComponent>(uid, out var spritecomp))
{
var oldapp = spritecomp.Appearance;
var newapp = oldapp.WithSkinColor(component.SkinColor);
_sharedHumanoidAppearance.UpdateAppearance(uid, newapp);
_sharedHumanoidAppearance.ForceAppearanceUpdate(uid);
}
if (TryComp<HandsComponent>(uid, out var handcomp))
{
foreach (var hand in handcomp.Hands)
{
_sharedHands.TrySetActiveHand(uid, hand.Key);
_sharedHands.TryDrop(uid);
var pos = EntityManager.GetComponent<TransformComponent>(uid).Coordinates;
var claw = EntityManager.SpawnEntity("ZombieClaw", pos);
_sharedHands.DoPickup(uid, hand.Value, claw);
}
}
else
{
EnsureComp<ZombieTransferComponent>(uid);
}
if (TryComp<ServerInventoryComponent>(uid, out var servInvComp))
_serverInventory.TryUnequip(uid, "gloves", true, true, predicted: false, servInvComp);
_popupSystem.PopupEntity(Loc.GetString("zombie-transform", ("target", uid)), uid, Filter.Pvs(uid));
if (TryComp<MetaDataComponent>(uid, out var metacomp))
metacomp.EntityName = Loc.GetString("zombie-name-prefix", ("target", metacomp.EntityName));
var mindcomp = EnsureComp<MindComponent>(uid);
if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session))
{
var chatMgr = IoCManager.Resolve<IChatManager>();
chatMgr.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
}
if (!HasComp<GhostRoleMobSpawnerComponent>(uid) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig
{
EntityManager.EnsureComponent<GhostTakeoverAvailableComponent>(uid, out var ghostcomp);
ghostcomp.RoleName = Loc.GetString("zombie-generic");
ghostcomp.RoleDescription = Loc.GetString("zombie-role-desc");
ghostcomp.RoleRules = Loc.GetString("zombie-role-rules");
}
}
private void OnRefreshMovementSpeedModifiers(EntityUid uid, DiseaseZombieComponent component, RefreshMovementSpeedModifiersEvent args)
{
args.ModifySpeed(component.SlowAmount, component.SlowAmount);
}
}
}