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:
@@ -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;
|
||||
}
|
||||
}
|
||||
30
Content.Server/Disease/Effects/DiseaseAddComponent.cs
Normal file
30
Content.Server/Disease/Effects/DiseaseAddComponent.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Content.Server.Temperature.Systems;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Robust.Shared.Containers;
|
||||
using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
|
||||
|
||||
namespace Content.Server.Inventory
|
||||
@@ -42,5 +43,35 @@ namespace Content.Server.Inventory
|
||||
_storageSystem.OpenStorageUI(entityUid.Value, uid, storageComponent);
|
||||
}
|
||||
}
|
||||
|
||||
public void TransferEntityInventories(EntityUid uid, EntityUid target)
|
||||
{
|
||||
if (TryGetContainerSlotEnumerator(uid, out var enumerator))
|
||||
{
|
||||
Dictionary<string, EntityUid?> inventoryEntities = new();
|
||||
var slots = GetSlots(uid);
|
||||
while (enumerator.MoveNext(out var containerSlot))
|
||||
{
|
||||
//records all the entities stored in each of the target's slots
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
if (TryGetSlotContainer(target, slot.Name, out var conslot, out var _) &&
|
||||
conslot.ID == containerSlot.ID)
|
||||
{
|
||||
inventoryEntities.Add(slot.Name, containerSlot.ContainedEntity);
|
||||
}
|
||||
}
|
||||
//drops everything in the target's inventory on the ground
|
||||
containerSlot.EmptyContainer();
|
||||
}
|
||||
/// This takes the objects we removed and stored earlier
|
||||
/// and actually equips all of it to the new entity
|
||||
foreach (var item in inventoryEntities)
|
||||
{
|
||||
if (item.Value != null)
|
||||
TryEquip(target, item.Value.Value, item.Key, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ using Content.Server.Inventory;
|
||||
using Content.Server.Mind.Commands;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Polymorph.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
using Content.Shared.CharacterAppearance.Components;
|
||||
using Content.Shared.CharacterAppearance.Systems;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Polymorph;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -27,8 +28,9 @@ namespace Content.Server.Polymorph.Systems
|
||||
[Dependency] private readonly ServerInventorySystem _inventory = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly SharedHumanoidAppearanceSystem _sharedHuApp = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -61,15 +63,15 @@ namespace Content.Server.Polymorph.Systems
|
||||
/// </summary>
|
||||
/// <param name="target">The entity that will be transformed</param>
|
||||
/// <param name="id">The id of the polymorph prototype</param>
|
||||
public void PolymorphEntity(EntityUid target, String id)
|
||||
public EntityUid? PolymorphEntity(EntityUid target, String id)
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(id, out var proto))
|
||||
{
|
||||
_saw.Error("Invalid polymorph prototype");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
PolymorphEntity(target, proto);
|
||||
return PolymorphEntity(target, proto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -77,8 +79,12 @@ namespace Content.Server.Polymorph.Systems
|
||||
/// </summary>
|
||||
/// <param name="target">The entity that will be transformed</param>
|
||||
/// <param name="proto">The polymorph prototype</param>
|
||||
public void PolymorphEntity(EntityUid target, PolymorphPrototype proto)
|
||||
public EntityUid? PolymorphEntity(EntityUid target, PolymorphPrototype proto)
|
||||
{
|
||||
/// This is the big papa function. This handles the transformation, moving the old entity
|
||||
/// logic and conditions specified in the prototype, and everything else that may be needed.
|
||||
/// I am clinically insane - emo
|
||||
|
||||
// mostly just for vehicles
|
||||
if (TryComp<BuckleComponent>(target, out var buckle))
|
||||
buckle.TryUnbuckle(target, true);
|
||||
@@ -93,42 +99,72 @@ namespace Content.Server.Polymorph.Systems
|
||||
comp.Prototype = proto;
|
||||
RaiseLocalEvent(child, new PolymorphComponentSetupEvent());
|
||||
|
||||
var targetXform = Transform(target);
|
||||
var childXform = Transform(child);
|
||||
childXform.LocalRotation = targetXform.LocalRotation;
|
||||
|
||||
if (_container.TryGetContainingContainer(target, out var cont))
|
||||
cont.Insert(child);
|
||||
|
||||
//Transfers all damage from the original to the new one
|
||||
if (TryComp<DamageableComponent>(child, out var damageParent) &&
|
||||
if (proto.TransferDamage &&
|
||||
TryComp<DamageableComponent>(child, out var damageParent) &&
|
||||
_damageable.GetScaledDamage(target, child, out var damage) &&
|
||||
damage != null)
|
||||
{
|
||||
_damageable.SetDamage(damageParent, damage);
|
||||
}
|
||||
|
||||
if (proto.DropInventory)
|
||||
if (proto.Inventory == PolymorphInventoryChange.Transfer)
|
||||
{
|
||||
//drops everything in the user's inventory
|
||||
if (_inventory.TryGetContainerSlotEnumerator(target, out var enumerator))
|
||||
{
|
||||
while (enumerator.MoveNext(out var containerSlot))
|
||||
{
|
||||
containerSlot.EmptyContainer();
|
||||
}
|
||||
}
|
||||
//drops everything in the user's hands
|
||||
_inventory.TransferEntityInventories(target, child);
|
||||
foreach (var hand in _sharedHands.EnumerateHeld(target))
|
||||
{
|
||||
hand.TryRemoveFromContainer();
|
||||
_sharedHands.TryPickupAnyHand(child, hand);
|
||||
}
|
||||
}
|
||||
else if (proto.Inventory == PolymorphInventoryChange.Drop)
|
||||
{
|
||||
if(_inventory.TryGetContainerSlotEnumerator(target, out var enumerator))
|
||||
while (enumerator.MoveNext(out var slot))
|
||||
slot.EmptyContainer();
|
||||
|
||||
foreach (var hand in _sharedHands.EnumerateHeld(target))
|
||||
hand.TryRemoveFromContainer();
|
||||
}
|
||||
|
||||
if (proto.TransferName &&
|
||||
TryComp<MetaDataComponent>(target, out var targetMeta) &&
|
||||
TryComp<MetaDataComponent>(child, out var childMeta))
|
||||
{
|
||||
childMeta.EntityName = targetMeta.EntityName;
|
||||
}
|
||||
|
||||
if (proto.TransferHumanoidAppearance &&
|
||||
TryComp<HumanoidAppearanceComponent>(target, out var targetHuApp) &&
|
||||
TryComp<HumanoidAppearanceComponent>(child, out var childHuApp))
|
||||
{
|
||||
_sharedHuApp.UpdateAppearance(child, targetHuApp.Appearance);
|
||||
_sharedHuApp.ForceAppearanceUpdate(child);
|
||||
}
|
||||
|
||||
if (TryComp<MindComponent>(target, out var mind) && mind.Mind != null)
|
||||
mind.Mind.TransferTo(child);
|
||||
|
||||
//Ensures a map to banish the entity to
|
||||
EnsurePausesdMap();
|
||||
if(PausedMap != null)
|
||||
if (PausedMap != null)
|
||||
targetTransformComp.AttachParent(Transform(PausedMap.Value));
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("polymorph-popup-generic", ("parent", target), ("child", child)), child, Filter.Pvs(child));
|
||||
return child;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a sidebar action for an entity to be able to polymorph at will
|
||||
/// </summary>
|
||||
/// <param name="id">The string of the id of the polymorph action</param>
|
||||
/// <param name="target">The entity that will be gaining the action</param>
|
||||
public void CreatePolymorphAction(string id, EntityUid target)
|
||||
{
|
||||
if (!_proto.TryIndex<PolymorphPrototype>(id, out var polyproto))
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Inventory;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Polymorph.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Polymorph;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Polymorph.Systems
|
||||
@@ -15,6 +20,9 @@ namespace Content.Server.Polymorph.Systems
|
||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly ServerInventorySystem _inventory = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -35,22 +43,51 @@ namespace Content.Server.Polymorph.Systems
|
||||
/// <param name="uid">The entityuid of the entity being reverted</param>
|
||||
public void Revert(EntityUid uid)
|
||||
{
|
||||
if (Deleted(uid))
|
||||
return;
|
||||
|
||||
if (!TryComp<PolymorphedEntityComponent>(uid, out var component))
|
||||
return;
|
||||
|
||||
var proto = component.Prototype;
|
||||
|
||||
var uidXform = Transform(uid);
|
||||
var parentXform = Transform(component.Parent);
|
||||
|
||||
parentXform.AttachParent(uidXform.ParentUid);
|
||||
parentXform.Coordinates = uidXform.Coordinates;
|
||||
parentXform.LocalRotation = uidXform.LocalRotation;
|
||||
|
||||
if (TryComp<DamageableComponent>(component.Parent, out var damageParent) &&
|
||||
if (_container.TryGetContainingContainer(uid, out var cont))
|
||||
cont.Insert(component.Parent);
|
||||
|
||||
if (component.Prototype.TransferDamage &&
|
||||
TryComp<DamageableComponent>(component.Parent, out var damageParent) &&
|
||||
_damageable.GetScaledDamage(uid, component.Parent, out var damage) &&
|
||||
damage != null)
|
||||
{
|
||||
_damageable.SetDamage(damageParent, damage);
|
||||
}
|
||||
|
||||
if (proto.Inventory == PolymorphInventoryChange.Transfer)
|
||||
{
|
||||
_inventory.TransferEntityInventories(uid, component.Parent);
|
||||
foreach (var hand in _sharedHands.EnumerateHeld(component.Parent))
|
||||
{
|
||||
hand.TryRemoveFromContainer();
|
||||
_sharedHands.TryPickupAnyHand(component.Parent, hand);
|
||||
}
|
||||
}
|
||||
else if (proto.Inventory == PolymorphInventoryChange.Drop)
|
||||
{
|
||||
if (_inventory.TryGetContainerSlotEnumerator(uid, out var enumerator))
|
||||
while (enumerator.MoveNext(out var slot))
|
||||
slot.EmptyContainer();
|
||||
|
||||
foreach (var hand in _sharedHands.EnumerateHeld(uid))
|
||||
hand.TryRemoveFromContainer();
|
||||
}
|
||||
|
||||
if (TryComp<MindComponent>(uid, out var mind) && mind.Mind != null)
|
||||
{
|
||||
mind.Mind.TransferTo(component.Parent);
|
||||
|
||||
@@ -67,9 +67,9 @@ public sealed class VocalSystem : EntitySystem
|
||||
if (!_blocker.CanSpeak(uid))
|
||||
return false;
|
||||
|
||||
// Currently this requires humanoid appearance & doesn't have any sort of fall-back or gender-neutral scream.
|
||||
if (!TryComp(uid, out HumanoidAppearanceComponent? humanoid))
|
||||
return false;
|
||||
var sex = Sex.Male; //the default is male because requiring humanoid appearance for this is dogshit
|
||||
if (TryComp(uid, out HumanoidAppearanceComponent? humanoid))
|
||||
sex = humanoid.Sex;
|
||||
|
||||
if (_random.Prob(component.WilhelmProbability))
|
||||
{
|
||||
@@ -80,7 +80,7 @@ public sealed class VocalSystem : EntitySystem
|
||||
var scale = (float) _random.NextGaussian(1, VocalComponent.Variation);
|
||||
var pitchedParams = component.AudioParams.WithPitchScale(scale);
|
||||
|
||||
switch (humanoid.Sex)
|
||||
switch (sex)
|
||||
{
|
||||
case Sex.Male:
|
||||
SoundSystem.Play(Filter.Pvs(uid), component.MaleScream.GetSound(), uid, pitchedParams);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Content.Server.Chat;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Server.Disease.Zombie.Components;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Sound;
|
||||
using Content.Server.Zombies;
|
||||
|
||||
namespace Content.Server.StationEvents.Events
|
||||
{
|
||||
@@ -42,16 +43,19 @@ namespace Content.Server.StationEvents.Events
|
||||
|
||||
var toInfect = _random.Next(1, 3);
|
||||
|
||||
var zombifysys = _entityManager.EntitySysManager.GetEntitySystem<ZombifyOnDeathSystem>();
|
||||
|
||||
// Now we give it to people in the list of dead entities earlier.
|
||||
var entSysMgr = IoCManager.Resolve<IEntitySystemManager>();
|
||||
var stationSystem = entSysMgr.GetEntitySystem<StationSystem>();
|
||||
var chatSystem = entSysMgr.GetEntitySystem<ChatSystem>();
|
||||
|
||||
foreach (var target in deadList)
|
||||
{
|
||||
if (toInfect-- == 0)
|
||||
break;
|
||||
|
||||
_entityManager.EnsureComponent<DiseaseZombieComponent>(target.Owner);
|
||||
zombifysys.ZombifyEntity(target.Owner);
|
||||
|
||||
var station = stationSystem.GetOwningStation(target.Owner);
|
||||
if(station == null) continue;
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Content.Server.Weapon.Melee
|
||||
if (args.Target is {Valid: true} target)
|
||||
{
|
||||
// Raise event before doing damage so we can cancel damage if the event is handled
|
||||
var hitEvent = new MeleeHitEvent(new List<EntityUid>() { target }, args.User);
|
||||
var hitEvent = new MeleeHitEvent(new List<EntityUid>() { target }, args.User, comp.Damage);
|
||||
RaiseLocalEvent(owner, hitEvent, false);
|
||||
|
||||
if (!hitEvent.Handled)
|
||||
@@ -152,7 +152,7 @@ namespace Content.Server.Weapon.Melee
|
||||
}
|
||||
|
||||
// Raise event before doing damage so we can cancel damage if handled
|
||||
var hitEvent = new MeleeHitEvent(hitEntities, args.User);
|
||||
var hitEvent = new MeleeHitEvent(hitEntities, args.User, comp.Damage);
|
||||
RaiseLocalEvent(owner, hitEvent, false);
|
||||
SendAnimation(comp.Arc, angle, args.User, owner, hitEntities);
|
||||
|
||||
@@ -352,6 +352,11 @@ namespace Content.Server.Weapon.Melee
|
||||
/// </summary>
|
||||
public sealed class MeleeHitEvent : HandledEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The base amount of damage dealt by the melee hit.
|
||||
/// </summary>
|
||||
public readonly DamageSpecifier BaseDamage = new();
|
||||
|
||||
/// <summary>
|
||||
/// Modifier sets to apply to the hit event when it's all said and done.
|
||||
/// This should be modified by adding a new entry to the list.
|
||||
@@ -382,10 +387,11 @@ namespace Content.Server.Weapon.Melee
|
||||
/// </summary>
|
||||
public EntityUid User { get; }
|
||||
|
||||
public MeleeHitEvent(List<EntityUid> hitEntities, EntityUid user)
|
||||
public MeleeHitEvent(List<EntityUid> hitEntities, EntityUid user, DamageSpecifier baseDamage)
|
||||
{
|
||||
HitEntities = hitEntities;
|
||||
User = user;
|
||||
BaseDamage = baseDamage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Content.Server.Weapons.Melee.ZombieTransfer.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class ZombieTransferComponent : Component
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Disease.Components;
|
||||
using Content.Server.Disease.Zombie.Components;
|
||||
using Content.Server.Drone.Components;
|
||||
using Content.Server.Weapon.Melee;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Server.Disease;
|
||||
using Content.Server.Weapons.Melee.ZombieTransfer.Components;
|
||||
|
||||
namespace Content.Server.Weapons.Melee.ZombieTransfer
|
||||
{
|
||||
public sealed class ZombieTransferSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ZombieTransferComponent, MeleeHitEvent>(OnMeleeHit);
|
||||
}
|
||||
|
||||
private void OnMeleeHit(EntityUid uid, ZombieTransferComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<DiseaseZombieComponent>(args.User, out var diseaseZombieComp))
|
||||
return;
|
||||
|
||||
if (!args.HitEntities.Any())
|
||||
return;
|
||||
|
||||
foreach (EntityUid entity in args.HitEntities)
|
||||
{
|
||||
if (args.User == entity)
|
||||
continue;
|
||||
|
||||
if (!HasComp<MobStateComponent>(entity) || HasComp<DroneComponent>(entity))
|
||||
continue;
|
||||
|
||||
if (_robustRandom.Prob(diseaseZombieComp.Probability) && HasComp<DiseaseCarrierComponent>(entity))
|
||||
{
|
||||
_disease.TryAddDisease(entity, "ZombieInfection");
|
||||
}
|
||||
|
||||
EntityManager.EnsureComponent<MobStateComponent>(entity, out var mobState);
|
||||
if ((mobState.IsDead() || mobState.IsCritical()) && !HasComp<DiseaseZombieComponent>(entity)) //dead entities are eautomatically infected. MAYBE: have activated infect ability?
|
||||
{
|
||||
EntityManager.AddComponent<DiseaseZombieComponent>(entity);
|
||||
var dspec = new DamageSpecifier();
|
||||
//these damages match the zombie claw
|
||||
dspec.DamageDict.TryAdd("Slash", -12);
|
||||
dspec.DamageDict.TryAdd("Piercing", -7);
|
||||
args.BonusDamage += dspec;
|
||||
}
|
||||
else if (mobState.IsAlive()) //heals when zombies bite live entities
|
||||
{
|
||||
var healingSolution = new Solution();
|
||||
healingSolution.AddReagent("Bicaridine", 1.00); //if OP, reduce/change chem
|
||||
_bloodstream.TryAddToChemicals(args.User, healingSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Content.Server/Zombies/ZombieComponent.cs
Normal file
12
Content.Server/Zombies/ZombieComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Content.Server.Zombies
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class ZombieComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The coefficient of the damage reduction applied when a zombie
|
||||
/// attacks another zombie. longe name
|
||||
/// </summary>
|
||||
public float OtherZombieDamageCoefficient = 0.75f;
|
||||
}
|
||||
}
|
||||
62
Content.Server/Zombies/ZombieSystem.cs
Normal file
62
Content.Server/Zombies/ZombieSystem.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Disease.Components;
|
||||
using Content.Server.Drone.Components;
|
||||
using Content.Server.Weapon.Melee;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Server.Disease;
|
||||
|
||||
namespace Content.Server.Zombies
|
||||
{
|
||||
public sealed class ZombieSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly ZombifyOnDeathSystem _zombify = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ZombieComponent, MeleeHitEvent>(OnMeleeHit);
|
||||
}
|
||||
|
||||
private void OnMeleeHit(EntityUid uid, ZombieComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<ZombieComponent>(args.User, out var zombieComp))
|
||||
return;
|
||||
|
||||
if (!args.HitEntities.Any())
|
||||
return;
|
||||
|
||||
foreach (EntityUid entity in args.HitEntities)
|
||||
{
|
||||
if (args.User == entity)
|
||||
continue;
|
||||
|
||||
if (!TryComp<MobStateComponent>(entity, out var mobState) || HasComp<DroneComponent>(entity))
|
||||
continue;
|
||||
|
||||
if (_robustRandom.Prob(0.5f) && HasComp<DiseaseCarrierComponent>(entity))
|
||||
_disease.TryAddDisease(entity, "ActiveZombieVirus");
|
||||
|
||||
if (HasComp<ZombieComponent>(entity))
|
||||
args.BonusDamage = args.BaseDamage * zombieComp.OtherZombieDamageCoefficient;
|
||||
|
||||
if ((mobState.IsDead() || mobState.IsCritical())
|
||||
&& !HasComp<ZombieComponent>(entity))
|
||||
{
|
||||
_zombify.ZombifyEntity(entity);
|
||||
args.BonusDamage = -args.BaseDamage;
|
||||
}
|
||||
else if (mobState.IsAlive()) //heals when zombies bite live entities
|
||||
{
|
||||
var healingSolution = new Solution();
|
||||
healingSolution.AddReagent("Bicaridine", 1.00); //if OP, reduce/change chem
|
||||
_bloodstream.TryAddToChemicals(args.User, healingSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Content.Server/Zombies/ZombifyOnDeathComponent.cs
Normal file
15
Content.Server/Zombies/ZombifyOnDeathComponent.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Content.Shared.Weapons.Melee;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Zombies
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class ZombifyOnDeathComponent : Component
|
||||
{
|
||||
[DataField("skinColor")]
|
||||
public Color SkinColor = new Color(0.70f, 0.72f, 0.48f, 1);
|
||||
|
||||
[DataField("attackArc", customTypeSerializer: typeof(PrototypeIdSerializer<MeleeWeaponAnimationPrototype>))]
|
||||
public string AttackArc = "claw";
|
||||
}
|
||||
}
|
||||
147
Content.Server/Zombies/ZombifyOnDeathSystem.cs
Normal file
147
Content.Server/Zombies/ZombifyOnDeathSystem.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.CharacterAppearance.Components;
|
||||
using Content.Shared.CharacterAppearance.Systems;
|
||||
using Content.Server.Disease.Components;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.CombatMode;
|
||||
using Content.Server.Inventory;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Server.Mind.Commands;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Weapon.Melee.Components;
|
||||
using Content.Server.Disease;
|
||||
using Robust.Shared.Containers;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.MobState;
|
||||
|
||||
namespace Content.Server.Zombies
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles zombie propagation and inherent zombie traits
|
||||
/// </summary>
|
||||
public sealed class ZombifyOnDeathSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedHandsSystem _sharedHands = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private readonly ServerInventorySystem _serverInventory = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||
[Dependency] private readonly SharedHumanoidAppearanceSystem _sharedHuApp = default!;
|
||||
[Dependency] private readonly IChatManager _chatMan = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ZombifyOnDeathComponent, MobStateChangedEvent>(OnDamageChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles an entity turning into a zombie when they die or go into crit
|
||||
/// </summary>
|
||||
private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (!TryComp<MobStateComponent>(uid, out var mobstate))
|
||||
return;
|
||||
|
||||
if (mobstate.IsDead() ||
|
||||
mobstate.IsCritical())
|
||||
{
|
||||
ZombifyEntity(uid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the general purpose function to call if you want to zombify an entity.
|
||||
/// It handles both humanoid and nonhumanoid transformation.
|
||||
/// </summary>
|
||||
/// <param name="target">the entity being zombified</param>
|
||||
public void ZombifyEntity(EntityUid target)
|
||||
{
|
||||
if (HasComp<ZombieComponent>(target))
|
||||
return;
|
||||
|
||||
_disease.CureAllDiseases(target);
|
||||
RemComp<DiseaseCarrierComponent>(target);
|
||||
RemComp<RespiratorComponent>(target);
|
||||
RemComp<BarotraumaComponent>(target);
|
||||
RemComp<HungerComponent>(target);
|
||||
RemComp<ThirstComponent>(target);
|
||||
|
||||
var zombiecomp = EnsureComp<ZombifyOnDeathComponent>(target);
|
||||
if (TryComp<HumanoidAppearanceComponent>(target, out var huApComp))
|
||||
{
|
||||
var appearance = huApComp.Appearance;
|
||||
_sharedHuApp.UpdateAppearance(target, appearance.WithSkinColor(zombiecomp.SkinColor), huApComp);
|
||||
_sharedHuApp.ForceAppearanceUpdate(target, huApComp);
|
||||
}
|
||||
|
||||
if (!HasComp<SharedDummyInputMoverComponent>(target))
|
||||
MakeSentientCommand.MakeSentient(target, EntityManager);
|
||||
|
||||
EnsureComp<ReplacementAccentComponent>(target).Accent = "zombie";
|
||||
|
||||
//funny add delet go brrr
|
||||
RemComp<CombatModeComponent>(target);
|
||||
AddComp<CombatModeComponent>(target);
|
||||
|
||||
var melee = EnsureComp<MeleeWeaponComponent>(target);
|
||||
melee.Arc = zombiecomp.AttackArc;
|
||||
melee.ClickArc = zombiecomp.AttackArc;
|
||||
//lord forgive me for the hardcoded damage
|
||||
DamageSpecifier dspec = new();
|
||||
dspec.DamageDict.Add("Slash", 13);
|
||||
dspec.DamageDict.Add("Piercing", 7);
|
||||
melee.Damage = dspec;
|
||||
|
||||
_damageable.SetDamageModifierSetId(target, "Zombie");
|
||||
_bloodstream.SetBloodLossThreshold(target, 0f);
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("zombie-transform", ("target", target)), target, Filter.Pvs(target));
|
||||
_serverInventory.TryUnequip(target, "gloves", true, true);
|
||||
|
||||
if (TryComp<TemperatureComponent>(target, out var tempComp))
|
||||
tempComp.ColdDamage.ClampMax(0);
|
||||
|
||||
if (TryComp<DamageableComponent>(target, out var damageablecomp))
|
||||
_damageable.SetAllDamage(damageablecomp, 0);
|
||||
|
||||
if (TryComp<MetaDataComponent>(target, out var meta))
|
||||
meta.EntityName = Loc.GetString("zombie-name-prefix", ("target", meta.EntityName));
|
||||
|
||||
var mindcomp = EnsureComp<MindComponent>(target);
|
||||
if (mindcomp.Mind != null && mindcomp.Mind.TryGetSession(out var session))
|
||||
_chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
|
||||
|
||||
if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !mindcomp.HasMind) //this specific component gives build test trouble so pop off, ig
|
||||
{
|
||||
EntityManager.EnsureComponent<GhostTakeoverAvailableComponent>(target, out var ghostcomp);
|
||||
ghostcomp.RoleName = Loc.GetString("zombie-generic");
|
||||
ghostcomp.RoleDescription = Loc.GetString("zombie-role-desc");
|
||||
ghostcomp.RoleRules = Loc.GetString("zombie-role-rules");
|
||||
}
|
||||
|
||||
foreach (var hand in _sharedHands.EnumerateHands(target))
|
||||
{
|
||||
_sharedHands.SetActiveHand(target, hand);
|
||||
hand.Container?.EmptyContainer();
|
||||
_sharedHands.RemoveHand(target, hand.Name);
|
||||
}
|
||||
RemComp<HandsComponent>(target);
|
||||
|
||||
EnsureComp<ZombieComponent>(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,11 +53,28 @@ namespace Content.Shared.Polymorph
|
||||
public bool Forced = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the target will drop their inventory
|
||||
/// when they are polymorphed (includes items in hands)
|
||||
/// Whether or not the entity transfers its damage between forms.
|
||||
/// </summary>
|
||||
[DataField("dropInventory", serverOnly: true)]
|
||||
public bool DropInventory = false;
|
||||
[DataField("transferDamage", serverOnly: true)]
|
||||
public bool TransferDamage = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity transfers its name between forms.
|
||||
/// </summary>
|
||||
[DataField("transferName", serverOnly: true)]
|
||||
public bool TransferName = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity transfers its hair, skin color, hair color, etc.
|
||||
/// </summary>
|
||||
[DataField("transferHumanoidAppearance", serverOnly: true)]
|
||||
public bool TransferHumanoidAppearance = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity transfers its inventory and equipment between forms.
|
||||
/// </summary>
|
||||
[DataField("inventory", serverOnly: true)]
|
||||
public PolymorphInventoryChange Inventory = PolymorphInventoryChange.None;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the polymorph reverts when the entity goes into crit.
|
||||
@@ -71,4 +88,11 @@ namespace Content.Shared.Polymorph
|
||||
[DataField("revertOnDeath", serverOnly: true)]
|
||||
public bool RevertOnDeath = true;
|
||||
}
|
||||
|
||||
public enum PolymorphInventoryChange : byte
|
||||
{
|
||||
None,
|
||||
Drop,
|
||||
Transfer,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
reagent: Phalanximine
|
||||
min: 15
|
||||
|
||||
|
||||
- type: disease
|
||||
id: StageIIIALungCancer
|
||||
name: Stage IIIA Lung Cancer
|
||||
@@ -42,27 +41,3 @@
|
||||
|
||||
|
||||
### Once radiation is refactored I want it to have a small chance of giving you regular cancer
|
||||
|
||||
- type: disease
|
||||
id: ZombieInfection
|
||||
name: Zombie Infection #This is the incubation period of the zombie disease.
|
||||
infectious: false
|
||||
cureResist: 0.2
|
||||
effects:
|
||||
- !type:DiseaseHealthChange
|
||||
probability: 0.01
|
||||
damage:
|
||||
types:
|
||||
Blunt: 2 #this is low but it goes for like 5 minutes so it's fine
|
||||
- !type:DiseaseSnough
|
||||
probability: 0.05
|
||||
snoughMessage: disease-cough
|
||||
snoughSound:
|
||||
collection: Coughs
|
||||
- !type:DiseaseProgression
|
||||
probability: 0.33
|
||||
comp: DiseaseZombie
|
||||
cures:
|
||||
- !type:DiseaseReagentCure
|
||||
reagent: Romerol
|
||||
min: 10
|
||||
|
||||
26
Resources/Prototypes/Diseases/zombie.yml
Normal file
26
Resources/Prototypes/Diseases/zombie.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
- type: disease
|
||||
id: ActiveZombieVirus
|
||||
name: Zombie Virus
|
||||
infectious: false
|
||||
cureResist: 0.2
|
||||
effects:
|
||||
- !type:DiseaseHealthChange
|
||||
probability: 0.075
|
||||
damage:
|
||||
types:
|
||||
Blunt: 4
|
||||
- !type:DiseaseAdjustReagent
|
||||
probability: 0.05
|
||||
reagent: Toxin
|
||||
amount: 1
|
||||
- !type:DiseaseSnough
|
||||
probability: 0.01
|
||||
snoughMessage: disease-cough
|
||||
snoughSound:
|
||||
collection: Coughs
|
||||
- !type:DiseaseAddComponent
|
||||
comp: ZombifyOnDeath
|
||||
cures:
|
||||
- !type:DiseaseReagentCure
|
||||
reagent: Romerol
|
||||
min: 5
|
||||
@@ -728,7 +728,6 @@
|
||||
damage:
|
||||
types:
|
||||
Blunt: 0.1
|
||||
- type: HumanoidAppearance # no this doesnt make sense but its needed for vocal
|
||||
- type: Vocal
|
||||
# mice are gender neutral who cares
|
||||
maleScream: /Audio/Animals/mouse_squeak.ogg
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
parent: HandheldHealthAnalyzer
|
||||
id: HandheldHealthAnalyzerZombie
|
||||
name: Zombie Infector
|
||||
suffix: DEBUG
|
||||
suffix: Active
|
||||
components:
|
||||
- type: HealthAnalyzer
|
||||
fake: true
|
||||
disease: ZombieInfection
|
||||
disease: ActiveZombieVirus
|
||||
@@ -1,22 +0,0 @@
|
||||
# Special entity used to fill zombie's hands when they turn undead
|
||||
- type: entity
|
||||
id: ZombieClaw
|
||||
name: Zombie Claw
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Weapons/Melee/zombie_claw.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
- type: Sharp
|
||||
- type: ZombieTransfer
|
||||
- type: Unremoveable
|
||||
- type: MeleeWeapon
|
||||
damage:
|
||||
types:
|
||||
Slash: 13
|
||||
Piercing: 7
|
||||
range: 1
|
||||
arcwidth: 0
|
||||
arc: claw
|
||||
|
||||
@@ -8,30 +8,38 @@
|
||||
id: Chicken
|
||||
entity: MobChicken
|
||||
forced: true
|
||||
dropInventory: true
|
||||
inventory: Drop
|
||||
|
||||
- type: polymorph
|
||||
id: Monkey
|
||||
entity: MobMonkey
|
||||
forced: true
|
||||
dropInventory: true
|
||||
inventory: Drop
|
||||
revertOnCrit: true
|
||||
revertOnDeath: true
|
||||
|
||||
# this is a test for transferring some visual appearance stuff
|
||||
- type: polymorph
|
||||
id: TestHumanMorph
|
||||
entity: MobHuman
|
||||
transferName: true
|
||||
transferHumanoidAppearance: true
|
||||
inventory: Transfer
|
||||
|
||||
- type: polymorph
|
||||
id: AdminMonkeySmite
|
||||
entity: MobMonkey
|
||||
forced: true
|
||||
dropInventory: true
|
||||
inventory: Drop
|
||||
|
||||
- type: polymorph
|
||||
id: AdminBreadSmite
|
||||
entity: FoodBreadPlain
|
||||
forced: true
|
||||
dropInventory: true
|
||||
inventory: Drop
|
||||
|
||||
- type: polymorph
|
||||
id: AdminInstrumentSmite
|
||||
entity: SuperSynthesizerInstrument
|
||||
forced: true
|
||||
dropInventory: true
|
||||
inventory: Drop
|
||||
|
||||
@@ -309,4 +309,4 @@
|
||||
Cellular: 1
|
||||
- !type:ChemCauseDisease
|
||||
causeChance: 1
|
||||
disease: ZombieInfection
|
||||
disease: ActiveZombieVirus
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.4 KiB |
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Illustrated by EmoGarbage",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user