diff --git a/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml b/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml
new file mode 100644
index 00000000000..36c24b3e978
--- /dev/null
+++ b/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml.cs b/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml.cs
new file mode 100644
index 00000000000..14a1fd8c1e2
--- /dev/null
+++ b/Content.Client/ADT/Changeling/UI/ChangelingTransformMenu.xaml.cs
@@ -0,0 +1,105 @@
+using System.Numerics;
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Chat.Prototypes;
+using Content.Shared.Speech;
+using Content.Shared.Whitelist;
+using Robust.Client.AutoGenerated;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Player;
+using Robust.Shared.Prototypes;
+using Content.Shared.ADT.Phantom;
+using Robust.Shared.Utility;
+using Content.Shared.Humanoid.Prototypes;
+using Content.Client.Humanoid;
+using Content.Shared.Preferences;
+using Robust.Shared.Map;
+using Content.Shared.Humanoid;
+using System.Linq;
+using Content.Shared.Changeling;
+
+namespace Content.Client.ADT.Changeling.UI;
+
+[GenerateTypedNameReferences]
+public sealed partial class ChangelingTransformMenu : RadialMenu
+{
+ [Dependency] private readonly EntityManager _entManager = default!;
+ [Dependency] private readonly IPrototypeManager _proto = default!;
+ [Dependency] private readonly ISharedPlayerManager _playerManager = default!;
+
+ private readonly HumanoidAppearanceSystem _appearanceSystem;
+ private readonly SpriteSystem _spriteSystem;
+ public List Forms = new();
+ public ChangelingMenuType Type = ChangelingMenuType.Transform;
+ public NetEntity Target = NetEntity.Invalid;
+
+ public event Action? OnSelectForm;
+
+ public ChangelingTransformMenu()
+ {
+ IoCManager.InjectDependencies(this);
+ RobustXamlLoader.Load(this);
+
+ _spriteSystem = _entManager.System();
+ _appearanceSystem = _entManager.System();
+ }
+
+ public void Populate(RequestChangelingFormsMenuEvent args)
+ {
+ var parent = FindControl("Main");
+
+ foreach (var item in args.HumanoidData)
+ {
+ if (Forms.Contains(item.NetEntity))
+ return;
+
+ var dummy = _entManager.SpawnEntity(_proto.Index(item.Profile.Species).DollPrototype, MapCoordinates.Nullspace);
+ _appearanceSystem.LoadProfile(dummy, item.Profile);
+ var face = new SpriteView();
+ face.SetEntity(dummy);
+
+ var button = new ChangelingTransformMenuButton
+ {
+ StyleClasses = { "RadialMenuButton" },
+ SetSize = new Vector2(64f, 64f),
+ ToolTip = Loc.GetString(item.Name ?? String.Empty),
+ Entity = item.NetEntity,
+ Profile = item.Profile,
+ Name = item.Name,
+ };
+
+ face.Scale *= 1f;
+ button.AddChild(face);
+ parent.AddChild(button);
+ Forms.Add(item.NetEntity);
+ }
+ foreach (var child in Children)
+ {
+ if (child is not RadialContainer container)
+ continue;
+ AddLingClickAction(container);
+ }
+ }
+ private void AddLingClickAction(RadialContainer container)
+ {
+ foreach (var child in container.Children)
+ {
+ if (child is not ChangelingTransformMenuButton castChild)
+ continue;
+
+ castChild.OnButtonUp += _ =>
+ {
+ OnSelectForm?.Invoke(castChild.Entity);
+ };
+ }
+ }
+}
+
+
+public sealed class ChangelingTransformMenuButton : RadialMenuTextureButton
+{
+ public NetEntity Entity;
+ public HumanoidCharacterProfile? Profile;
+ public string? Name;
+}
diff --git a/Content.Client/ADT/Changeling/UI/ChangelingTransformUIController.cs b/Content.Client/ADT/Changeling/UI/ChangelingTransformUIController.cs
new file mode 100644
index 00000000000..7c2527e30f6
--- /dev/null
+++ b/Content.Client/ADT/Changeling/UI/ChangelingTransformUIController.cs
@@ -0,0 +1,88 @@
+using JetBrains.Annotations;
+using Robust.Client.Graphics;
+using Robust.Client.Input;
+using Robust.Client.UserInterface.Controllers;
+using Robust.Shared.Player;
+using Content.Shared.Changeling;
+
+namespace Content.Client.ADT.Changeling.UI;
+
+[UsedImplicitly]
+public sealed class ChangelingTransformUIController : UIController//, IOnStateChanged
+{
+ [Dependency] private readonly IEntityManager _entityManager = default!;
+ [Dependency] private readonly IClyde _displayManager = default!;
+ [Dependency] private readonly IInputManager _inputManager = default!;
+ [Dependency] private readonly ISharedPlayerManager _playerManager = default!;
+
+ private ChangelingTransformMenu? _menu;
+
+ public override void Initialize()
+ {
+ EntityManager.EventBus.SubscribeEvent(EventSource.Network, this, OnRequestMenu);
+ }
+
+ private void OnRequestMenu(RequestChangelingFormsMenuEvent ev)
+ {
+ ToggleMenu(ev);
+ }
+
+ private void ToggleMenu(RequestChangelingFormsMenuEvent ev)
+ {
+ if (_menu == null)
+ {
+ // setup window
+ _menu = UIManager.CreateWindow();
+ _menu.OnClose += OnWindowClosed;
+ _menu.OnOpen += OnWindowOpen;
+ _menu.OnSelectForm += OnSelectForm;
+
+ _menu.Type = ev.Type;
+ _menu.Target = ev.Target;
+
+ _menu.Populate(ev);
+
+ _menu.OpenCentered();
+ }
+ else
+ {
+ _menu.OnClose -= OnWindowClosed;
+ _menu.OnOpen -= OnWindowOpen;
+ _menu.OnSelectForm -= OnSelectForm;
+ _menu.Forms.Clear();
+
+ CloseMenu();
+ }
+ }
+
+ private void OnWindowClosed()
+ {
+ CloseMenu();
+ }
+
+ private void OnWindowOpen()
+ {
+ }
+
+ private void CloseMenu()
+ {
+ if (_menu == null)
+ return;
+
+ _menu.Dispose();
+ _menu = null;
+ }
+
+ private void OnSelectForm(NetEntity ent)
+ {
+ if (_menu == null)
+ return;
+
+ var player = _entityManager.GetNetEntity(_playerManager.LocalSession?.AttachedEntity ?? EntityUid.Invalid);
+
+ var ev = new SelectChangelingFormEvent(player, _menu.Target, ent, _menu.Type);
+ _entityManager.RaisePredictiveEvent(ev);
+
+ CloseMenu();
+ }
+}
diff --git a/Content.Client/ADT/Stealth/StealthSystem.cs b/Content.Client/ADT/Stealth/StealthSystem.cs
new file mode 100644
index 00000000000..011e73608d7
--- /dev/null
+++ b/Content.Client/ADT/Stealth/StealthSystem.cs
@@ -0,0 +1,31 @@
+using Content.Client.Interactable.Components;
+using Content.Client.StatusIcon;
+using Content.Shared.ADT.Stealth.Components;
+using Content.Shared.Stealth;
+using Content.Shared.Stealth.Components;
+using Content.Shared.Tag;
+using Content.Shared.Whitelist;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+using Robust.Client.Player;
+using Robust.Shared.Prototypes;
+
+namespace Content.Client.Stealth;
+
+public sealed partial class StealthSystem
+{
+ private void InitializeADT()
+ {
+ _player.LocalPlayerAttached += OnAttachedChanged;
+ _player.LocalPlayerDetached += OnAttachedChanged;
+ }
+
+ private void OnAttachedChanged(EntityUid uid)
+ {
+ var query = AllEntityQuery();
+ while (query.MoveNext(out var ent, out var comp, out _))
+ {
+ SetShader(ent, comp.Enabled);
+ }
+ }
+}
diff --git a/Content.Client/Stealth/StealthSystem.cs b/Content.Client/Stealth/StealthSystem.cs
index adb25e1ef63..d59145d7c7c 100644
--- a/Content.Client/Stealth/StealthSystem.cs
+++ b/Content.Client/Stealth/StealthSystem.cs
@@ -1,17 +1,22 @@
using Content.Client.Interactable.Components;
using Content.Client.StatusIcon;
+using Content.Shared.ADT.Stealth.Components;
using Content.Shared.Stealth;
using Content.Shared.Stealth.Components;
+using Content.Shared.Tag;
+using Content.Shared.Whitelist;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
+using Robust.Client.Player;
using Robust.Shared.Prototypes;
namespace Content.Client.Stealth;
-public sealed class StealthSystem : SharedStealthSystem
+public sealed partial class StealthSystem : SharedStealthSystem
{
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+ [Dependency] private readonly IPlayerManager _player = default!;
private ShaderInstance _shader = default!;
@@ -24,6 +29,8 @@ public override void Initialize()
SubscribeLocalEvent(OnShutdown);
SubscribeLocalEvent(OnStartup);
SubscribeLocalEvent(OnShaderRender);
+
+ InitializeADT(); // ADT tweak
}
public override void SetEnabled(EntityUid uid, bool value, StealthComponent? component = null)
@@ -39,6 +46,10 @@ private void SetShader(EntityUid uid, bool enabled, StealthComponent? component
{
if (!Resolve(uid, ref component, ref sprite, false))
return;
+ // ADT start
+ if (!CheckStealthWhitelist(_player.LocalEntity, uid))
+ enabled = false;
+ // ADT end
sprite.Color = Color.White;
sprite.PostShader = enabled ? _shader : null;
diff --git a/Content.Server/ADT/Changeling/ChangelingActionNotPresentCondition.cs b/Content.Server/ADT/Changeling/ChangelingActionNotPresentCondition.cs
new file mode 100644
index 00000000000..1839f5a2a0f
--- /dev/null
+++ b/Content.Server/ADT/Changeling/ChangelingActionNotPresentCondition.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Store;
+
+namespace Content.Server.Store.Conditions;
+
+///
+/// Only allows a listing to be purchased while buyer can refresh.
+///
+public sealed partial class ChangelingActionNotPresentCondition : ListingCondition
+{
+ public override bool Condition(ListingConditionArgs args)
+ {
+ if (!args.EntityManager.TryGetComponent(args.Buyer, out var ling))
+ return false;
+
+ foreach (var item in ling.BoughtActions)
+ {
+ if (args.EntityManager.TryGetComponent(item, out var meta) && meta.EntityPrototype?.ID == args.Listing.ProductAction)
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Content.Server/ADT/Changeling/ChangelingCanRefreshCondition.cs b/Content.Server/ADT/Changeling/ChangelingCanRefreshCondition.cs
new file mode 100644
index 00000000000..9821a9670a0
--- /dev/null
+++ b/Content.Server/ADT/Changeling/ChangelingCanRefreshCondition.cs
@@ -0,0 +1,16 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Store;
+
+namespace Content.Server.Store.Conditions;
+
+///
+/// Only allows a listing to be purchased while buyer can refresh.
+///
+public sealed partial class ChangelingCanRefreshCondition : ListingCondition
+{
+
+ public override bool Condition(ListingConditionArgs args)
+ {
+ return args.EntityManager.TryGetComponent(args.Buyer, out var ling) && ling.CanRefresh;
+ }
+}
diff --git a/Content.Server/ADT/Changeling/ChangelingLastResortNotUsedCondition.cs b/Content.Server/ADT/Changeling/ChangelingLastResortNotUsedCondition.cs
new file mode 100644
index 00000000000..38b4dcbb8fb
--- /dev/null
+++ b/Content.Server/ADT/Changeling/ChangelingLastResortNotUsedCondition.cs
@@ -0,0 +1,20 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Store;
+
+namespace Content.Server.Store.Conditions;
+
+///
+/// Only allows a listing to be purchased while buyer can refresh.
+///
+public sealed partial class ChangelingLastResortNotUsedCondition : ListingCondition
+{
+ public override bool Condition(ListingConditionArgs args)
+ {
+ if (!args.EntityManager.TryGetComponent(args.Buyer, out var ling))
+ return false;
+ if (ling.LastResortUsed)
+ return false;
+
+ return true;
+ }
+}
diff --git a/Content.Server/ADT/Changeling/Role/ChangelingRoleComponent.cs b/Content.Server/ADT/Changeling/Role/ChangelingRoleComponent.cs
new file mode 100644
index 00000000000..12a5eb939f9
--- /dev/null
+++ b/Content.Server/ADT/Changeling/Role/ChangelingRoleComponent.cs
@@ -0,0 +1,8 @@
+using Content.Shared.Roles;
+
+namespace Content.Server.Roles;
+
+[RegisterComponent]
+public sealed partial class ChangelingRoleComponent : BaseMindRoleComponent
+{
+}
diff --git a/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Combat.cs b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Combat.cs
new file mode 100644
index 00000000000..4edf484b68f
--- /dev/null
+++ b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Combat.cs
@@ -0,0 +1,523 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Changeling;
+using Content.Shared.Inventory;
+using Content.Shared.Interaction.Components;
+using Content.Shared.Hands.Components;
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.Popups;
+using Robust.Shared.Player;
+using Content.Shared.IdentityManagement;
+using Content.Shared.FixedPoint;
+using Content.Shared.Chemistry.Components;
+using Content.Server.Destructible;
+using Content.Shared.Movement.Systems;
+using Content.Shared.ADT.Damage.Events;
+using Content.Shared.StatusEffect;
+using Content.Shared.Eye.Blinding.Components;
+using Content.Shared.Eye.Blinding.Systems;
+using Content.Shared.Damage.Components;
+using Content.Shared.Mobs.Components;
+
+namespace Content.Server.Changeling.EntitySystems;
+
+public sealed partial class ChangelingSystem
+{
+ private void InitializeCombatAbilities()
+ {
+ SubscribeLocalEvent(OnLingEmp);
+ SubscribeLocalEvent(OnResonantShriek);
+ SubscribeLocalEvent(OnMuscles);
+ SubscribeLocalEvent(OnBlindSting);
+ SubscribeLocalEvent(OnAdrenaline);
+
+ SubscribeLocalEvent(OnArmBladeAction);
+ SubscribeLocalEvent(OnArmShieldAction);
+ SubscribeLocalEvent(OnArmaceAction);
+ SubscribeLocalEvent(OnLingArmorAction);
+ SubscribeLocalEvent(OnBoneShard);
+
+ SubscribeLocalEvent(OnRefreshMovespeed);
+ SubscribeLocalEvent(OnDamage);
+ SubscribeLocalEvent(OnBeforeStaminacrit);
+ }
+
+ #region Actions
+ private void OnLingEmp(EntityUid uid, ChangelingComponent component, LingEMPActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ args.Handled = true;
+
+ var coords = _transform.GetMapCoordinates(uid);
+ _emp.EmpPulse(coords, component.DissonantShriekEmpRange, component.DissonantShriekEmpConsumption, component.DissonantShriekEmpDuration);
+ }
+
+ public void OnResonantShriek(EntityUid uid, ChangelingComponent component, LingResonantShriekEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (_mobState.IsDead(uid))
+ {
+ var selfMessage = Loc.GetString("changeling-regenerate-fail-dead");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ args.Handled = true;
+
+ var xform = Transform(uid);
+ foreach (var ent in _lookup.GetEntitiesInRange(xform.Coordinates, 15))
+ {
+ if (HasComp(ent))
+ continue;
+
+ _flashSystem.Flash(ent, uid, null, 6f, 0.8f, false);
+
+ if (!_mindSystem.TryGetMind(ent, out var mindId, out var mind))
+ continue;
+ if (mind.Session == null)
+ continue;
+ _audioSystem.PlayGlobal(component.SoundResonant, mind.Session);
+ }
+ }
+
+ private void OnMuscles(EntityUid uid, ChangelingComponent component, ChangelingMusclesActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ args.Handled = true;
+
+ var message = Loc.GetString("changeling-lingmuscles");
+ _popup.PopupEntity(message, uid, uid);
+
+ component.MusclesActive = !component.MusclesActive;
+ _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
+ if (!component.MusclesActive)
+ _stun.TryParalyze(uid, TimeSpan.FromSeconds(4), true);
+
+ }
+
+ private void OnAdrenaline(EntityUid uid, ChangelingComponent component, AdrenalineActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-lesser-form"), uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTen))
+ return;
+
+ args.Handled = true;
+
+ _status.TryAddStatusEffect(uid, "Adrenaline", TimeSpan.FromMinutes(1), false);
+ var selfMessage = Loc.GetString("changeling-adrenaline-self-success");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+
+ private void OnBlindSting(EntityUid uid, ChangelingComponent component, BlindStingEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+
+ if (!TryStingTarget(uid, target))
+ return;
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFifteen))
+ return;
+
+ args.Handled = true;
+
+ _status.TryAddStatusEffect(target, TemporaryBlindnessSystem.BlindingStatusEffect, component.BlindStingDuration, true);
+
+ var selfMessageSuccess = Loc.GetString("changeling-success-sting", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageSuccess, uid, uid);
+
+ }
+
+ private void OnArmBladeAction(EntityUid uid, ChangelingComponent component, ArmBladeActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty, !component.ArmBladeActive))
+ return;
+
+ args.Handled = true;
+
+ component.ArmBladeActive = !component.ArmBladeActive;
+
+ if (component.ArmBladeActive)
+ {
+ if (!SpawnArmBlade(uid, component))
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-armblade-fail"), uid, uid);
+ return;
+ }
+
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+
+ var othersMessage = Loc.GetString("changeling-armblade-success-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armblade-success-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else
+ RemoveBladeEntity(uid, component);
+ }
+
+ private void OnArmShieldAction(EntityUid uid, ChangelingComponent component, ArmShieldActionEvent args) // При нажатии на действие орг. щита
+ {
+ if (args.Handled)
+ return;
+
+ if (!TryComp(uid, out HandsComponent? handsComponent))
+ return;
+ if (handsComponent.ActiveHand == null)
+ return;
+
+ var handContainer = handsComponent.ActiveHand.Container;
+
+ if (handContainer == null)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty, !component.ArmShieldActive))
+ return;
+
+ args.Handled = true;
+
+ component.ArmShieldActive = !component.ArmShieldActive;
+
+ if (component.ArmShieldActive)
+ {
+ if (!SpawnArmShield(uid, component))
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-armshield-fail"), uid, uid);
+ return;
+ }
+
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+
+ var othersMessage = Loc.GetString("changeling-armshield-success-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armshield-success-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else
+ RemoveShieldEntity(uid, component);
+ }
+
+ private void OnArmaceAction(EntityUid uid, ChangelingComponent component, ArmaceActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty, !component.ArmBladeActive))
+ return;
+
+ args.Handled = true;
+
+ component.ArmaceActive = !component.ArmaceActive;
+
+ if (component.ArmaceActive)
+ {
+ if (!SpawnArmace(uid, component))
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-armblade-fail"), uid, uid);
+ return;
+ }
+
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+
+ var othersMessage = Loc.GetString("changeling-armace-success-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armace-success-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else
+ RemoveArmaceEntity(uid, component);
+ }
+
+ private void OnLingArmorAction(EntityUid uid, ChangelingComponent component, LingArmorActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (!TryComp(uid, out var inventory))
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty, !component.LingArmorActive, component.LingArmorRegenCost))
+ return;
+
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+ component.LingArmorActive = !component.LingArmorActive;
+
+ if (component.LingArmorActive)
+ {
+ args.Handled = true;
+
+ SpawnLingArmor(uid, inventory);
+
+ var othersMessage = Loc.GetString("changeling-armor-success-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armor-success-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else
+ {
+ _inventorySystem.TryUnequip(uid, "head", true, true, false);
+ _inventorySystem.TryUnequip(uid, "outerClothing", true, true, false);
+
+ var othersMessage = Loc.GetString("changeling-armor-retract-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armor-retract-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+
+ var solution = new Solution();
+ solution.AddReagent("Blood", FixedPoint2.New(75));
+ _puddle.TrySpillAt(Transform(uid).Coordinates, solution, out _);
+ }
+ }
+
+ private void OnBoneShard(EntityUid uid, ChangelingComponent component, ChangelingBoneShardEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFifteen))
+ return;
+
+ args.Handled = true;
+
+ var shard = Spawn("ADTThrowingStarChangeling", Transform(uid).Coordinates);
+
+ _damageableSystem.TryChangeDamage(uid, new DamageSpecifier(_proto.Index("Blunt"), 20));
+ _handsSystem.TryPickupAnyHand(uid, shard);
+
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+ }
+ #endregion
+
+ #region Events
+ private void OnRefreshMovespeed(EntityUid uid, ChangelingComponent component, RefreshMovementSpeedModifiersEvent args)
+ {
+ if (component.MusclesActive)
+ args.ModifySpeed(component.MusclesModifier);
+ }
+
+ private void OnDamage(EntityUid uid, ChangelingShieldComponent component, DamageChangedEvent args)
+ {
+ var parent = Transform(uid).ParentUid;
+ if (!TryComp(parent, out var ling))
+ return;
+ if (!TryComp(uid, out var damage))
+ return;
+
+ var additionalShieldHealth = 50 * ling.AbsorbedDnaModifier;
+ var shieldHealth = 150 + additionalShieldHealth;
+ if (damage.TotalDamage >= shieldHealth)
+ {
+ ling.ArmShieldActive = false;
+ QueueDel(ling.ShieldEntity);
+
+ _audioSystem.PlayPvs(ling.SoundFlesh, uid);
+
+ var othersMessage = Loc.GetString("changeling-armshield-broke-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, parent, Filter.PvsExcept(parent), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armshield-broke-self");
+ _popup.PopupEntity(selfMessage, parent, parent, PopupType.MediumCaution);
+ }
+ }
+
+ private void OnBeforeStaminacrit(EntityUid uid, ChangelingComponent component, ref BeforeStaminaCritEvent args)
+ {
+ if (!component.MusclesActive)
+ return;
+
+ args.Cancelled = true;
+
+ if (_timing.CurTime < component.NextMusclesDamage)
+ return;
+
+ _damageableSystem.TryChangeDamage(uid, new DamageSpecifier(_proto.Index("Brute"), 5));
+ component.NextMusclesDamage = _timing.CurTime + TimeSpan.FromSeconds(1);
+ }
+ #endregion
+
+ #region Misc
+ public bool SpawnArmBlade(EntityUid uid, ChangelingComponent component)
+ {
+ var armblade = Spawn("ADTArmBlade", Transform(uid).Coordinates);
+ EnsureComp(armblade);
+ RemComp(armblade);
+ if (!_handsSystem.TryPickupAnyHand(uid, armblade))
+ {
+ QueueDel(armblade);
+ return false;
+ }
+
+ component.BladeEntity = armblade;
+ return true;
+ }
+
+ public bool SpawnArmShield(EntityUid uid, ChangelingComponent component)
+ {
+ var armshield = Spawn("ADTArmShield", Transform(uid).Coordinates);
+ EnsureComp(armshield);
+
+ if (!_handsSystem.TryPickupAnyHand(uid, armshield))
+ {
+ QueueDel(armshield);
+ return false;
+ }
+ component.ShieldEntity = armshield;
+ return true;
+ }
+
+ public bool SpawnArmace(EntityUid uid, ChangelingComponent component)
+ {
+ var mace = Spawn("ADTArmace", Transform(uid).Coordinates);
+ EnsureComp(mace);
+
+ if (!_handsSystem.TryPickupAnyHand(uid, mace))
+ {
+ QueueDel(mace);
+ return false;
+ }
+ component.ArmaceEntity = mace;
+ return true;
+ }
+
+ private void RemoveBladeEntity(EntityUid uid, ChangelingComponent component)
+ {
+ if (!component.BladeEntity.HasValue)
+ return;
+ QueueDel(component.BladeEntity);
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+ component.ArmBladeActive = false;
+
+ var othersMessage = Loc.GetString("changeling-armblade-retract-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armblade-retract-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+
+ private void RemoveShieldEntity(EntityUid uid, ChangelingComponent component)
+ {
+ if (!component.ShieldEntity.HasValue)
+ return;
+ QueueDel(component.ShieldEntity);
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+ component.ArmShieldActive = false;
+
+ var othersMessage = Loc.GetString("changeling-armshield-retract-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armshield-retract-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+
+ private void RemoveArmaceEntity(EntityUid uid, ChangelingComponent component)
+ {
+ if (!component.ArmaceEntity.HasValue)
+ return;
+ QueueDel(component.ArmaceEntity);
+ _audioSystem.PlayPvs(component.SoundFlesh, uid);
+ component.ArmaceActive = false;
+
+ var othersMessage = Loc.GetString("changeling-armace-retract-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-armace-retract-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+
+ public void SpawnLingArmor(EntityUid uid, InventoryComponent inventory)
+ {
+ var helmet = Spawn("ClothingHeadHelmetLing", Transform(uid).Coordinates);
+ var armor = Spawn("ClothingOuterArmorChangeling", Transform(uid).Coordinates);
+ EnsureComp(helmet);
+ EnsureComp(armor);
+
+ _inventorySystem.TryUnequip(uid, "head", true, true, false, inventory);
+ _inventorySystem.TryUnequip(uid, "outerClothing", true, true, false, inventory);
+
+ _inventorySystem.TryEquip(uid, helmet, "head", true, true, false, inventory);
+ _inventorySystem.TryEquip(uid, armor, "outerClothing", true, true, false, inventory);
+ }
+ #endregion
+}
diff --git a/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Headslug.cs b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Headslug.cs
new file mode 100644
index 00000000000..055de1754e4
--- /dev/null
+++ b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Headslug.cs
@@ -0,0 +1,125 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Changeling;
+using Content.Shared.Inventory;
+using Content.Shared.Interaction.Components;
+using Content.Shared.Hands.Components;
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.Popups;
+using Robust.Shared.Player;
+using Content.Shared.IdentityManagement;
+using Content.Shared.FixedPoint;
+using Content.Shared.Chemistry.Components;
+using Content.Server.Destructible;
+using Content.Shared.Movement.Systems;
+using Content.Shared.ADT.Damage.Events;
+using Content.Shared.StatusEffect;
+using Content.Shared.Eye.Blinding.Components;
+using Content.Shared.Eye.Blinding.Systems;
+using Content.Shared.Damage.Components;
+using Robust.Shared.Containers;
+using Content.Shared.Interaction;
+using Content.Shared.DoAfter;
+using Content.Shared.Humanoid;
+using Content.Server.Resist;
+using Content.Shared.Examine;
+using System.Linq;
+
+namespace Content.Server.Changeling.EntitySystems;
+
+public sealed partial class ChangelingSystem
+{
+ private void InitializeSlug()
+ {
+ SubscribeLocalEvent(OnLayEggs);
+ SubscribeLocalEvent(OnLayEggsDoAfter);
+
+ SubscribeLocalEvent(OnExamineContainer);
+ }
+
+ private void OnLayEggs(EntityUid uid, ChangelingHeadslugComponent comp, UserActivateInWorldEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+ if (!HasComp(target))
+ return;
+
+ if (!TryStingTarget(uid, target) || !_mobState.IsDead(target) || HasComp(target))
+ return;
+
+ var doAfter = new DoAfterArgs(EntityManager, uid, 4f, new LingEggDoAfterEvent(), uid, target: target)
+ {
+ DistanceThreshold = 1,
+ BreakOnMove = true,
+ BreakOnWeightlessMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.StartAndEnd
+ };
+
+ _doAfter.TryStartDoAfter(doAfter);
+ }
+
+ private void OnLayEggsDoAfter(EntityUid uid, ChangelingHeadslugComponent comp, LingEggDoAfterEvent args)
+ {
+ if (args.Handled || args.Cancelled || !args.Target.HasValue)
+ return;
+
+ var containerComp = EnsureComp(args.Target.Value);
+ containerComp.Container = _container.EnsureContainer(args.Target.Value, "headslug", out _);
+
+ RemComp(uid);
+ _container.Insert(uid, containerComp.Container);
+ comp.IsInside = true;
+ comp.Container = args.Target;
+ }
+
+ private void OnExamineContainer(EntityUid uid, ChangelingHeadslugContainerComponent comp, ExaminedEvent args)
+ {
+ var slug = comp?.Container.ContainedEntities.First();
+ if (!slug.HasValue)
+ return;
+
+ if (!Comp(slug.Value).Alerted)
+ args.PushMarkup(Loc.GetString("changeling-headslug-inside"));
+ else
+ args.PushMarkup(Loc.GetString("changeling-headslug-inside-soon"));
+ }
+
+ private void UpdateChangelingHeadslug(EntityUid uid, float frameTime, ChangelingHeadslugComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp))
+ return;
+ if (!comp.IsInside || !comp.Container.HasValue)
+ return;
+
+ comp.Accumulator += frameTime;
+
+ if (comp.Accumulator >= comp.AccumulateTime * 0.75f && !comp.Alerted)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-slug-almost-ready"), uid, uid);
+ comp.Alerted = true;
+ }
+
+ if (comp.Accumulator < comp.AccumulateTime)
+ return;
+
+ if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+ return;
+
+ var monke = Spawn("ADTMobMonkeyChangeling", Transform(comp.Container.Value).Coordinates);
+ _mindSystem.TransferTo(mindId, monke);
+ var ling = EnsureComp(monke);
+
+ EntityUid? lesserFormActionEntity = null;
+ _action.AddAction(monke, ref lesserFormActionEntity, "ActionLingLesserForm");
+ _action.SetToggled(lesserFormActionEntity, true);
+
+ ling.BoughtActions.Add(lesserFormActionEntity);
+ ling.LesserFormActive = true;
+ ling.LastResortUsed = true;
+
+ _damageableSystem.TryChangeDamage(comp.Container.Value, new DamageSpecifier(_proto.Index("Blunt"), 500000));
+ }
+}
diff --git a/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Useful.cs b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Useful.cs
new file mode 100644
index 00000000000..dffb8199b72
--- /dev/null
+++ b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.Useful.cs
@@ -0,0 +1,709 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Changeling;
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.Popups;
+using Robust.Shared.Player;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Stealth.Components;
+using Content.Shared.DoAfter;
+using Content.Shared.Humanoid;
+using Content.Server.Forensics;
+using Content.Shared.FixedPoint;
+using Content.Shared.Mobs;
+using Content.Shared.Cuffs.Components;
+using Content.Shared.Rejuvenate;
+using Content.Shared.Store.Components;
+using Content.Shared.Gibbing.Events;
+using Content.Shared.Speech.Muting;
+using System.Linq;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Whitelist;
+using Content.Shared.ADT.Stealth.Components;
+
+namespace Content.Server.Changeling.EntitySystems;
+
+public sealed partial class ChangelingSystem
+{
+ private void InitializeUsefulAbilities()
+ {
+ SubscribeLocalEvent(StartAbsorbing);
+
+ SubscribeLocalEvent(OnRegenerate);
+ SubscribeLocalEvent(OnStasisDeathAction);
+ SubscribeLocalEvent(OnFleshmend);
+
+ SubscribeLocalEvent(OnLingInvisible);
+ SubscribeLocalEvent(OnDigitalCamouflage);
+ SubscribeLocalEvent(OnLesserForm);
+ SubscribeLocalEvent(OnLastResort);
+ SubscribeLocalEvent(OnBiodegrade);
+
+ SubscribeLocalEvent(OnLingDNASting);
+ SubscribeLocalEvent(OnMuteSting);
+ SubscribeLocalEvent(OnDrugSting);
+ SubscribeLocalEvent(OnTransformSting);
+
+ SubscribeLocalEvent(OnAbsorbDoAfter);
+ SubscribeLocalEvent(OnBiodegradeDoAfter);
+ }
+
+ private void StartAbsorbing(EntityUid uid, ChangelingComponent component, LingAbsorbActionEvent args) // Начало поглощения
+ {
+ if (args.Handled)
+ return;
+ if (component.DoAfter.HasValue)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ var target = args.Target;
+ if (!HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-fail-nohuman", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!_mobState.IsIncapacitated(target)) // if target isn't crit or dead dont let absorb
+ {
+ var selfMessage = Loc.GetString("changeling-dna-fail-notdead", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-alreadyabsorbed", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (_tagSystem.HasTag(target, "ChangelingBlacklist"))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-nodna", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+
+ args.Handled = true;
+
+ _popup.PopupEntity(Loc.GetString("changeling-dna-stage-1"), uid, uid);
+
+ var doAfter = new DoAfterArgs(EntityManager, uid, component.AbsorbDuration, new AbsorbDoAfterEvent(), uid, target: target)
+ {
+ DistanceThreshold = 2,
+ BreakOnMove = true,
+ BreakOnWeightlessMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.StartAndEnd
+ };
+
+ _doAfter.TryStartDoAfter(doAfter, out component.DoAfter);
+ }
+
+ private void OnAbsorbDoAfter(EntityUid uid, ChangelingComponent component, AbsorbDoAfterEvent args)
+ {
+ if (args.Handled || args.Args.Target == null)
+ return;
+
+ args.Handled = true;
+ args.Repeat = RepeatDoAfter(component);
+ var target = args.Args.Target.Value;
+
+ if (args.Cancelled || !_mobState.IsIncapacitated(target) || HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-interrupted", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ component.AbsorbStage = 0;
+ args.Repeat = false;
+ return;
+ }
+
+ if (component.AbsorbStage == 0)
+ {
+ var othersMessage = Loc.GetString("changeling-dna-stage-2-others", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-dna-stage-2-self");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else if (component.AbsorbStage == 1)
+ {
+ var othersMessage = Loc.GetString("changeling-dna-stage-3-others", ("user", Identity.Entity(uid, EntityManager)), ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.LargeCaution);
+
+ var selfMessage = Loc.GetString("changeling-dna-stage-3-self", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.LargeCaution);
+ }
+ else if (component.AbsorbStage == 2)
+ {
+ var doStealDNA = true;
+ if (TryComp(target, out var dnaCompTarget))
+ {
+ foreach (var storedData in component.StoredDNA)
+ {
+ if (storedData.DNA != null && storedData.DNA == dnaCompTarget.DNA)
+ doStealDNA = false;
+ }
+ }
+
+ if (doStealDNA)
+ {
+ if (!StealDNA(uid, target, component))
+ {
+ component.AbsorbStage = 0;
+ args.Repeat = false;
+ return;
+ }
+ }
+
+ component.DoAfter = null;
+
+ // Нанесение 200 генетического урона и замена крови на кислоту
+ var dmg = new DamageSpecifier(_proto.Index("Genetic"), component.AbsorbGeneticDmg);
+ _damageableSystem.TryChangeDamage(target, dmg);
+
+ var solution = new Solution();
+ solution.AddReagent("FerrochromicAcid", FixedPoint2.New(150));
+ _puddle.TrySpillAt(Transform(target).Coordinates, solution, out _);
+ _bloodstreamSystem.TryModifyBloodLevel(target, -500);
+
+ EnsureComp(target);
+
+ if (HasComp(target)) // Если это был другой генокрад, получим моментально 5 очков эволюции
+ {
+ var selfMessage = Loc.GetString("changeling-dna-success-ling", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.Medium);
+
+ if (TryComp(uid, out var store))
+ {
+ _store.TryAddCurrency(new Dictionary { { "EvolutionPoints", component.AbsorbedChangelingPointsAmount } }, uid, store);
+ _store.UpdateUserInterface(uid, uid, store);
+ }
+ }
+ else // Если это не был генокрад, получаем возможность "сброса"
+ {
+ var selfMessage = Loc.GetString("changeling-dna-success", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.Medium);
+ component.CanRefresh = true;
+ component.AbsorbedDnaModifier += 1;
+ }
+ }
+
+ if (component.AbsorbStage >= 2)
+ component.AbsorbStage = 0;
+ else
+ component.AbsorbStage += 1;
+ }
+
+ private static bool RepeatDoAfter(ChangelingComponent component)
+ {
+ if (component.AbsorbStage < 2.0)
+ return true;
+ else
+ return false;
+ }
+
+ private void OnRegenerate(EntityUid uid, ChangelingComponent component, LingRegenerateActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-lesser-form"), uid, uid);
+ return;
+ }
+
+ if (!_mobState.IsCritical(uid)) // make sure the ling is critical, if not they cant regenerate
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-regenerate-fail-not-crit"), uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTen))
+ return;
+
+ args.Handled = true;
+
+ var damage_brute = new DamageSpecifier(_proto.Index("Brute"), component.RegenerateBruteHealAmount);
+ var damage_burn = new DamageSpecifier(_proto.Index("Burn"), component.RegenerateBurnHealAmount);
+ _damageableSystem.TryChangeDamage(uid, damage_brute);
+ _damageableSystem.TryChangeDamage(uid, damage_burn);
+ _bloodstreamSystem.TryModifyBloodLevel(uid, component.RegenerateBloodVolumeHealAmount); // give back blood and remove bleeding
+ _bloodstreamSystem.TryModifyBleedAmount(uid, component.RegenerateBleedReduceAmount);
+ _audioSystem.PlayPvs(component.SoundRegenerate, uid);
+
+ var othersMessage = Loc.GetString("changeling-regenerate-others-success", ("user", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
+
+ var selfMessage = Loc.GetString("changeling-regenerate-self-success");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+
+ private void OnLingInvisible(EntityUid uid, ChangelingComponent component, LingInvisibleActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+ if (component.DigitalCamouflageActive)
+ {
+ var selfMessage = Loc.GetString("changeling-chameleon-fail-digi-camo");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwentyFive, !component.ChameleonSkinActive))
+ return;
+
+ args.Handled = true;
+
+ var stealth = EnsureComp(uid);
+ var stealthonmove = EnsureComp(uid);
+
+ var message = Loc.GetString(!component.ChameleonSkinActive ? "changeling-chameleon-toggle-on" : "changeling-chameleon-toggle-off");
+ _popup.PopupEntity(message, uid, uid);
+
+ if (!component.ChameleonSkinActive)
+ {
+ stealthonmove.PassiveVisibilityRate = component.ChameleonSkinPassiveVisibilityRate;
+ stealthonmove.MovementVisibilityRate = component.ChameleonSkinMovementVisibilityRate;
+ stealth.MinVisibility = -1f;
+ }
+ else
+ {
+ RemCompDeferred(uid, stealth);
+ RemCompDeferred(uid, stealthonmove);
+ }
+
+ component.ChameleonSkinActive = !component.ChameleonSkinActive;
+ }
+
+ private void OnLingDNASting(EntityUid uid, ChangelingComponent component, LingStingExtractActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+
+ if (!TryStingTarget(uid, target))
+ return;
+
+ var dnaCompTarget = EnsureComp(target);
+
+ foreach (var storedData in component.StoredDNA)
+ {
+ if (storedData.DNA != null && storedData.DNA == dnaCompTarget.DNA)
+ {
+ var selfMessageFailAlreadyDna = Loc.GetString("changeling-dna-sting-fail-alreadydna", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageFailAlreadyDna, uid, uid);
+ return;
+ }
+ }
+
+ if (component.StoredDNA.Count >= component.DNAStrandCap)
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-full");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwentyFive))
+ return;
+
+ if (StealDNA(uid, target, component))
+ {
+ args.Handled = true;
+
+ var selfMessageSuccess = Loc.GetString("changeling-dna-sting", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageSuccess, uid, uid);
+ }
+ }
+
+ private void OnStasisDeathAction(EntityUid uid, ChangelingComponent component, StasisDeathActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ component.StasisDeathActive = !component.StasisDeathActive;
+
+ if (component.StasisDeathActive)
+ {
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwentyFive))
+ return;
+
+ args.Handled = true;
+
+ if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+ mind.PreventGhosting = true;
+
+ _mobState.ChangeMobState(uid, MobState.Dead);
+
+ var selfMessage = Loc.GetString("changeling-stasis-death-self-success"); /// всё, я спать откисать, адьос
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+ }
+ else
+ {
+ if (!_mobState.IsDead(uid))
+ {
+ component.StasisDeathActive = false;
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFree))
+ return;
+
+ args.Handled = true;
+
+ var selfMessage = Loc.GetString("changeling-stasis-death-self-revive"); /// вейк ап энд cum бэк ту ворк
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution);
+
+ _audioSystem.PlayPvs(component.SoundRegenerate, uid);
+
+ RaiseLocalEvent(uid, new RejuvenateEvent());
+
+ component.StasisDeathActive = false;
+
+ if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+ {
+ mind.PreventGhosting = false;
+ mind.PreventGhostingSendMessage = false;
+ }
+ }
+
+ _action.SetToggled(component.ChangelingStasisDeathActionEntity, component.StasisDeathActive);
+ }
+
+ private void OnMuteSting(EntityUid uid, ChangelingComponent component, MuteStingEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+
+ if (!TryStingTarget(uid, target))
+ return;
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ args.Handled = true;
+
+ _status.TryAddStatusEffect(target, "Muted", TimeSpan.FromSeconds(45), true);
+
+ var selfMessageSuccess = Loc.GetString("changeling-success-sting", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageSuccess, uid, uid);
+
+ }
+
+ private void OnDrugSting(EntityUid uid, ChangelingComponent component, DrugStingEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+
+ if (!TryStingTarget(uid, target))
+ return;
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ args.Handled = true;
+
+ _hallucinations.StartHallucinations(target, "ADTHallucinations", TimeSpan.FromSeconds(40), true, "Changeling");
+ var selfMessageSuccess = Loc.GetString("changeling-success-sting", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageSuccess, uid, uid);
+
+ }
+
+ private void OnFleshmend(EntityUid uid, ChangelingComponent component, FleshmendActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-lesser-form"), uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwentyFive))
+ return;
+
+ args.Handled = true;
+
+ var damage_brute = new DamageSpecifier(_proto.Index("Brute"), component.RegenerateBruteHealAmount);
+ var damage_burn = new DamageSpecifier(_proto.Index("Burn"), component.RegenerateBurnHealAmount);
+ _damageableSystem.TryChangeDamage(uid, damage_brute);
+ _damageableSystem.TryChangeDamage(uid, damage_burn);
+ _bloodstreamSystem.TryModifyBloodLevel(uid, component.RegenerateBloodVolumeHealAmount); // give back blood and remove bleeding
+ _bloodstreamSystem.TryModifyBleedAmount(uid, component.RegenerateBleedReduceAmount);
+ _audioSystem.PlayPvs(component.SoundFleshQuiet, uid);
+
+ var selfMessage = Loc.GetString("changeling-omnizine-self-success");
+ _popup.PopupEntity(selfMessage, uid, uid, PopupType.Small);
+ }
+
+ private void OnLesserForm(EntityUid uid, ChangelingComponent component, ChangelingLesserFormActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ args.Handled = true;
+
+ if (!component.LesserFormActive)
+ {
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty))
+ return;
+
+ RemoveShieldEntity(uid, component);
+ RemoveBladeEntity(uid, component);
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ component.MusclesActive = false;
+ _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid);
+
+ if (component.LingArmorActive)
+ {
+ _inventorySystem.TryUnequip(uid, "head", true, true, false);
+ _inventorySystem.TryUnequip(uid, "outerClothing", true, true, false);
+ component.ChemicalsPerSecond += component.LingArmorRegenCost;
+ }
+
+ foreach (var item in component.BoughtActions.Where(x =>
+ x.HasValue &&
+ TryPrototype(x.Value, out var proto) &&
+ proto.ID == "ActionLingLesserForm"))
+ {
+ _action.SetToggled(item, true);
+ }
+
+ component.LesserFormActive = true;
+
+ var transformedUid = _polymorph.PolymorphEntity(uid, component.LesserFormMob);
+ if (transformedUid == null)
+ return;
+
+ var selfMessage = Loc.GetString("changeling-lesser-form-activate-monkey");
+ _popup.PopupEntity(selfMessage, transformedUid.Value, transformedUid.Value);
+
+ CopyLing(uid, transformedUid.Value);
+ }
+ else
+ {
+ if (component.StoredDNA.Count <= 0)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-nodna"), uid, uid);
+ return;
+ }
+
+ if (TryComp(uid, out var actorComponent))
+ {
+ var ev = new RequestChangelingFormsMenuEvent(GetNetEntity(uid), ChangelingMenuType.HumanForm);
+
+ foreach (var item in component.StoredDNA)
+ {
+ var netEntity = GetNetEntity(item.EntityUid);
+
+ ev.HumanoidData.Add(new(
+ netEntity,
+ Name(item.EntityUid),
+ item.HumanoidAppearanceComponent.Species.Id,
+ BuildProfile(item)));
+ }
+
+ // реализовать сортировку
+ RaiseNetworkEvent(ev, actorComponent.PlayerSession);
+ }
+ }
+ }
+
+ private void OnLastResort(EntityUid uid, ChangelingComponent component, LastResortActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFree))
+ return;
+ if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+ return;
+
+ args.Handled = true;
+
+ foreach (var item in component.BoughtActions)
+ {
+ _action.RemoveAction(item);
+ QueueDel(item);
+ }
+
+ var slug = Spawn("ADTChangelingHeadslug", Transform(uid).Coordinates);
+ _mindSystem.TransferTo(mindId, slug);
+
+ _damageableSystem.TryChangeDamage(uid, new DamageSpecifier(_proto.Index("Blunt"), 500000));
+ }
+
+ private void OnBiodegrade(EntityUid uid, ChangelingComponent component, LingBiodegradeActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (_mobState.IsDead(uid))
+ {
+ var selfMessage = Loc.GetString("changeling-regenerate-fail-dead");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ }
+
+ if (!TryComp(uid, out var cuffs) || cuffs.Container.ContainedEntities.Count < 1)
+ {
+ var selfMessage = Loc.GetString("changeling-biodegrade-fail-nocuffs");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFifteen))
+ return;
+
+ args.Handled = true;
+
+ _popup.PopupEntity(Loc.GetString("changeling-biodegrade-start"), uid, uid);
+
+ var doAfter = new DoAfterArgs(EntityManager, uid, component.BiodegradeDuration, new BiodegradeDoAfterEvent(), uid, target: uid)
+ {
+ DistanceThreshold = 2,
+ BreakOnMove = true,
+ BreakOnWeightlessMove = true,
+ BreakOnDamage = true,
+ AttemptFrequency = AttemptFrequency.StartAndEnd,
+ RequireCanInteract = false
+ };
+
+ _doAfter.TryStartDoAfter(doAfter);
+ }
+
+ private void OnBiodegradeDoAfter(EntityUid uid, ChangelingComponent component, BiodegradeDoAfterEvent args)
+ {
+ if (args.Handled || args.Args.Target == null)
+ return;
+ args.Handled = true;
+ var target = args.Args.Target.Value;
+ if (args.Cancelled)
+ {
+ var selfMessage = Loc.GetString("changeling-biodegrade-interrupted");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ args.Repeat = false;
+ return;
+ }
+ if (!TryComp(target, out var cuffs) || cuffs.Container.ContainedEntities.Count < 1)
+ return;
+ if (!TryComp(cuffs.LastAddedCuffs, out var handcuffs) || cuffs.Container.ContainedEntities.Count < 1)
+ return;
+ _cuffable.Uncuff(target, uid, cuffs.LastAddedCuffs, cuffs, handcuffs);
+ }
+
+ public void OnTransformSting(EntityUid uid, ChangelingComponent component, TransformationStingEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ var target = args.Target;
+
+ if (!TryStingTarget(uid, target))
+ return;
+
+ if (component.StoredDNA.Count <= 0)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-nodna"), uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFifty))
+ return;
+
+ args.Handled = true;
+
+ if (TryComp(uid, out var actorComponent))
+ {
+ var ev = new RequestChangelingFormsMenuEvent(GetNetEntity(target), ChangelingMenuType.Sting);
+
+ foreach (var item in component.StoredDNA)
+ {
+ var netEntity = GetNetEntity(item.EntityUid);
+
+ ev.HumanoidData.Add(new(
+ netEntity,
+ Name(item.EntityUid),
+ item.HumanoidAppearanceComponent.Species.Id,
+ BuildProfile(item)));
+ }
+
+ // реализовать сортировку
+ RaiseNetworkEvent(ev, actorComponent.PlayerSession);
+ }
+ }
+
+ private void OnDigitalCamouflage(EntityUid uid, ChangelingComponent component, DigitalCamouflageEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (component.LesserFormActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+ if (component.ChameleonSkinActive)
+ {
+ var selfMessage = Loc.GetString("changeling-digi-camo-fail-chameleon");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostTwenty, !component.DigitalCamouflageActive))
+ return;
+
+ args.Handled = true;
+
+
+ var message = Loc.GetString(!component.DigitalCamouflageActive ? "changeling-digital-camo-toggle-on" : "changeling-digital-camo-toggle-off");
+ _popup.PopupEntity(message, uid, uid);
+
+ if (!component.DigitalCamouflageActive)
+ {
+ EnsureComp(uid);
+ var stealth = EnsureComp(uid);
+
+ stealth.MinVisibility = -1f;
+ _stealth.SetVisibility(uid, -1f);
+ _stealth.SetDesc(uid, Loc.GetString("changeling-digital-camo-desc", ("user", Identity.Entity(uid, EntityManager))));
+ }
+ else
+ {
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ }
+
+ component.DigitalCamouflageActive = !component.DigitalCamouflageActive;
+ }
+}
diff --git a/Content.Server/ADT/Changeling/Systems/ChangelingSystem.cs b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.cs
new file mode 100644
index 00000000000..4821d0013ea
--- /dev/null
+++ b/Content.Server/ADT/Changeling/Systems/ChangelingSystem.cs
@@ -0,0 +1,612 @@
+using Content.Server.Actions;
+using Content.Shared.Inventory;
+using Content.Server.Store.Systems;
+using Content.Shared.Changeling;
+using Content.Shared.Changeling.Components;
+using Content.Shared.Popups;
+using Content.Shared.Store;
+using Content.Server.Traitor.Uplink;
+using Content.Shared.Mobs.Systems;
+using Content.Shared.FixedPoint;
+using Content.Shared.Humanoid;
+using Content.Shared.IdentityManagement;
+using Content.Server.Polymorph.Systems;
+using Content.Server.Flash;
+using Content.Shared.Polymorph;
+using Content.Server.Forensics;
+using Content.Shared.Actions;
+using Robust.Shared.Serialization.Manager;
+using Content.Shared.Alert;
+using Content.Shared.Stealth.Components;
+using Content.Shared.Nutrition.Components;
+using Content.Shared.Tag;
+using Content.Shared.StatusEffect;
+using Content.Shared.Movement.Systems;
+using Content.Shared.Damage.Systems;
+using Content.Shared.Damage;
+using Content.Server.Stunnable;
+using Content.Shared.Mind;
+using Robust.Shared.Player;
+using System.Linq;
+using Content.Shared.Preferences;
+using Content.Server.Humanoid;
+using Robust.Shared.Utility;
+using Content.Shared.Humanoid.Markings;
+using Content.Shared.Store.Components;
+using Robust.Shared.Prototypes;
+using Content.Server.Hands.Systems;
+using Content.Server.Body.Systems;
+using Robust.Shared.Audio.Systems;
+using Content.Server.Emp;
+using Content.Shared.DoAfter;
+using Content.Server.Fluids.EntitySystems;
+using Content.Server.Cuffs;
+using Robust.Shared.Timing;
+using Content.Server.ADT.Hallucinations;
+using Content.Shared.Gibbing.Systems;
+using Content.Shared.Mobs;
+using Content.Server.Stealth;
+using Content.Server.ADT.Store;
+using Robust.Server.Containers;
+using Content.Server.Ghost;
+using Content.Shared.ADT.Stealth.Components;
+
+namespace Content.Server.Changeling.EntitySystems;
+
+public sealed partial class ChangelingSystem : EntitySystem
+{
+ #region Dependency
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+ [Dependency] private readonly StoreSystem _store = default!;
+ [Dependency] private readonly ActionsSystem _action = default!;
+ [Dependency] private readonly UplinkSystem _uplink = default!;
+ [Dependency] private readonly MobStateSystem _mobState = default!;
+ [Dependency] private readonly PolymorphSystem _polymorph = default!;
+ [Dependency] private readonly MetaDataSystem _metaData = default!;
+ [Dependency] private readonly ISerializationManager _serialization = default!;
+ [Dependency] private readonly ActionContainerSystem _actionContainer = default!;
+ [Dependency] private readonly AlertsSystem _alerts = default!;
+ [Dependency] private readonly TagSystem _tagSystem = default!;
+ [Dependency] private readonly StatusEffectsSystem _status = default!;
+ [Dependency] private readonly EntityManager _entityManager = default!;
+ [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
+ [Dependency] private readonly StaminaSystem _stamina = default!;
+ [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly EntityLookupSystem _lookup = default!;
+ [Dependency] private readonly SharedMindSystem _mindSystem = default!;
+ [Dependency] private readonly AlertsSystem _alertsSystem = default!;
+ [Dependency] private readonly StunSystem _stun = default!;
+ [Dependency] private readonly FlashSystem _flashSystem = default!;
+ [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
+ [Dependency] private readonly IPrototypeManager _proto = default!;
+ [Dependency] private readonly HandsSystem _handsSystem = default!;
+ [Dependency] private readonly InventorySystem _inventorySystem = default!;
+ [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
+ [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] private readonly EmpSystem _emp = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly PuddleSystem _puddle = default!;
+ [Dependency] private readonly CuffableSystem _cuffable = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly HallucinationsSystem _hallucinations = default!;
+ [Dependency] private readonly StealthSystem _stealth = default!;
+
+ [Dependency] private readonly ContainerSystem _container = default!;
+ #endregion
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnMapInit);
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnMobState);
+ SubscribeLocalEvent(OnActionBought);
+ SubscribeLocalEvent(OnRefresh);
+
+ SubscribeLocalEvent(OnShop);
+ SubscribeLocalEvent(OnTransform);
+
+ SubscribeNetworkEvent(OnSelectChangelingForm);
+
+ InitializeUsefulAbilities();
+ InitializeCombatAbilities();
+ InitializeSlug();
+ }
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ var lingQuery = EntityQueryEnumerator();
+ while (lingQuery.MoveNext(out var uid, out var comp))
+ {
+ UpdateChangeling(uid, frameTime, comp);
+ }
+
+ var slugQuery = EntityQueryEnumerator();
+ while (slugQuery.MoveNext(out var uid, out var comp))
+ {
+ UpdateChangelingHeadslug(uid, frameTime, comp);
+ }
+ }
+
+ private void OnStartup(EntityUid uid, ChangelingComponent component, ComponentStartup args)
+ {
+ //RemComp(uid); // TODO: Исправить проблему с волосами слаймов
+ //RemComp(uid);
+ //RemComp(uid);
+ StealDNA(uid, component);
+
+ RemComp(uid);
+ RemComp(uid);
+ _store.TryAddStore(uid,
+ new HashSet> { "EvolutionPoints" },
+ new HashSet> { "ChangelingAbilities" },
+ new Dictionary, FixedPoint2> { { "EvolutionPoints", 10 } },
+ false, false);
+ }
+
+ private void OnMapInit(EntityUid uid, ChangelingComponent component, MapInitEvent args)
+ {
+ _action.AddAction(uid, ref component.ChangelingEvolutionMenuActionEntity, component.ChangelingEvolutionMenuAction);
+ _action.AddAction(uid, ref component.ChangelingRegenActionEntity, component.ChangelingRegenAction);
+ _action.AddAction(uid, ref component.ChangelingAbsorbActionEntity, component.ChangelingAbsorbAction);
+ _action.AddAction(uid, ref component.ChangelingDNAStingActionEntity, component.ChangelingDNAStingAction);
+ _action.AddAction(uid, ref component.ChangelingDNACycleActionEntity, component.ChangelingDNACycleAction);
+ _action.AddAction(uid, ref component.ChangelingStasisDeathActionEntity, component.ChangelingStasisDeathAction);
+
+ component.BasicTransferredActions.Add(component.ChangelingEvolutionMenuActionEntity);
+ component.BasicTransferredActions.Add(component.ChangelingRegenActionEntity);
+ component.BasicTransferredActions.Add(component.ChangelingAbsorbActionEntity);
+ component.BasicTransferredActions.Add(component.ChangelingDNAStingActionEntity);
+ component.BasicTransferredActions.Add(component.ChangelingDNACycleActionEntity);
+ component.BasicTransferredActions.Add(component.ChangelingStasisDeathActionEntity);
+ }
+
+ private void OnShutdown(EntityUid uid, ChangelingComponent component, ComponentShutdown args)
+ {
+ _action.RemoveAction(uid, component.ChangelingEvolutionMenuActionEntity);
+ _action.RemoveAction(uid, component.ChangelingRegenActionEntity);
+ _action.RemoveAction(uid, component.ChangelingAbsorbActionEntity);
+ _action.RemoveAction(uid, component.ChangelingDNAStingActionEntity);
+ _action.RemoveAction(uid, component.ChangelingDNACycleActionEntity);
+ _action.RemoveAction(uid, component.ChangelingStasisDeathActionEntity);
+ }
+
+ private void OnShop(EntityUid uid, ChangelingComponent component, ChangelingEvolutionMenuActionEvent args)
+ {
+ _store.OnInternalShop(uid);
+ }
+
+ public void OnTransform(EntityUid uid, ChangelingComponent component, ChangelingTransformActionEvent args)
+ {
+ if (args.Handled)
+ return;
+ if (component.StoredDNA.Count <= 0)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-transform-fail-nodna"), uid, uid);
+ return;
+ }
+
+ if (TryComp(uid, out var actorComponent))
+ {
+ var ev = new RequestChangelingFormsMenuEvent(GetNetEntity(uid), ChangelingMenuType.Transform);
+
+ foreach (var item in component.StoredDNA)
+ {
+ var netEntity = GetNetEntity(item.EntityUid);
+
+ ev.HumanoidData.Add(new(
+ netEntity,
+ Name(item.EntityUid),
+ item.HumanoidAppearanceComponent.Species.Id,
+ BuildProfile(item)));
+ }
+
+ // реализовать сортировку
+ RaiseNetworkEvent(ev, actorComponent.PlayerSession);
+ }
+ args.Handled = true;
+ }
+
+ private void OnMobState(EntityUid uid, ChangelingComponent component, MobStateChangedEvent args)
+ {
+ if (args.NewMobState == MobState.Dead)
+ {
+ RemoveBladeEntity(uid, component);
+ RemoveShieldEntity(uid, component);
+ RemoveArmaceEntity(uid, component);
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ component.ChameleonSkinActive = false;
+ component.DigitalCamouflageActive = false;
+ return;
+ }
+
+ if (args.NewMobState != MobState.Dead && component.StasisDeathActive)
+ {
+ component.StasisDeathActive = false;
+ _action.SetToggled(component.ChangelingStasisDeathActionEntity, component.StasisDeathActive);
+ }
+ }
+
+ private void OnActionBought(EntityUid uid, ChangelingComponent component, ref ActionBoughtEvent args)
+ {
+ component.BoughtActions.Add(args.ActionEntity);
+ }
+
+ private void OnRefresh(EntityUid uid, ChangelingComponent component, ChangelingRefreshEvent args)
+ {
+ if (!component.CanRefresh)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-cant-refresh"), uid, uid);
+ return;
+ }
+
+ foreach (var item in component.BoughtActions)
+ {
+ _action.RemoveAction(item);
+ QueueDel(item);
+ }
+
+ if (!TryComp(uid, out var store))
+ return;
+
+ RemoveBladeEntity(uid, component);
+ RemoveShieldEntity(uid, component);
+ RemoveArmaceEntity(uid, component);
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ RemCompDeferred(uid);
+ component.ChameleonSkinActive = false;
+ component.DigitalCamouflageActive = false;
+
+ if (component.LingArmorActive)
+ {
+ _inventorySystem.TryUnequip(uid, "head", true, true, false);
+ _inventorySystem.TryUnequip(uid, "outerClothing", true, true, false);
+ TryUseAbility(uid, component, 0f, false, component.LingArmorRegenCost);
+ component.LingArmorActive = false;
+ }
+
+ component.BoughtActions.Clear();
+
+ _store.TrySetCurrency(new Dictionary, FixedPoint2> { { "EvolutionPoints", 10 } }, uid);
+ _store.TryRefreshStoreStock(uid);
+ component.CanRefresh = false;
+
+ _store.UpdateUserInterface(uid, uid);
+ }
+
+ private void OnSelectChangelingForm(SelectChangelingFormEvent ev)
+ {
+ var uid = GetEntity(ev.User);
+ var target = GetEntity(ev.Target);
+ var selected = GetEntity(ev.EntitySelected);
+
+ if (!TryComp(uid, out var comp))
+ return;
+
+ if (ev.Type == ChangelingMenuType.Sting)
+ {
+ var list = comp.StoredDNA.Where(x => x.EntityUid == selected);
+ if (list.Count() <= 0)
+ return;
+
+ var newHumanoidData = _polymorph.CopyPolymorphHumanoidData(list.First());
+
+ _polymorph.PolymorphEntityAsHumanoid(GetEntity(ev.Target), newHumanoidData);
+
+ comp.StoredDNA.Remove(list.First());
+ return;
+ }
+
+ TransformChangeling(uid, comp, ev);
+ }
+
+ public void CopyLing(EntityUid from, EntityUid to, ChangelingComponent? comp = null)
+ {
+ if (!Resolve(from, ref comp))
+ return;
+ if (HasComp(to))
+ RemComp(to);
+
+ var newLingComponent = EnsureComp(to);
+ newLingComponent.Chemicals = comp.Chemicals;
+ newLingComponent.ChemicalsPerSecond = comp.ChemicalsPerSecond;
+ newLingComponent.StoredDNA = comp.StoredDNA;
+ newLingComponent.SelectedDNA = comp.SelectedDNA;
+ newLingComponent.ArmBladeActive = comp.ArmBladeActive;
+ newLingComponent.ChameleonSkinActive = comp.ChameleonSkinActive;
+ newLingComponent.LingArmorActive = comp.LingArmorActive;
+ newLingComponent.CanRefresh = comp.CanRefresh;
+ newLingComponent.LesserFormActive = comp.LesserFormActive;
+ newLingComponent.AbsorbedDnaModifier = comp.AbsorbedDnaModifier;
+ newLingComponent.BasicTransferredActions = comp.BasicTransferredActions;
+ newLingComponent.BoughtActions = comp.BoughtActions;
+ newLingComponent.LastResortUsed = comp.LastResortUsed;
+ RemComp(from, comp);
+
+ if (TryComp(from, out StoreComponent? storeComp))
+ {
+ var copiedStoreComponent = (Component)_serialization.CreateCopy(storeComp, notNullableOverride: true);
+ RemComp(to);
+ EntityManager.AddComponent(to, copiedStoreComponent);
+ }
+
+ if (TryComp(from, out StealthComponent? stealthComp)) // copy over stealth status
+ {
+ if (TryComp(from, out StealthOnMoveComponent? stealthOnMoveComp))
+ {
+ var copiedStealthComponent = (Component)_serialization.CreateCopy(stealthComp, notNullableOverride: true);
+ EntityManager.AddComponent(to, copiedStealthComponent);
+ RemComp(from, stealthComp);
+
+ var copiedStealthOnMoveComponent = (Component)_serialization.CreateCopy(stealthOnMoveComp, notNullableOverride: true);
+ EntityManager.AddComponent(to, copiedStealthOnMoveComponent);
+ RemComp(from, stealthOnMoveComp);
+ }
+ }
+
+ foreach (var basic in comp.BasicTransferredActions)
+ {
+ if (basic.HasValue)
+ _actionContainer.TransferActionWithNewAttached(basic.Value, to, to);
+ }
+ foreach (var item in comp.BoughtActions)
+ {
+ if (item.HasValue)
+ _actionContainer.TransferActionWithNewAttached(item.Value, to, to);
+ }
+
+ }
+
+ private HumanoidCharacterProfile BuildProfile(PolymorphHumanoidData data)
+ {
+ HumanoidCharacterAppearance hca = new();
+ var humanoid = data.HumanoidAppearanceComponent;
+
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.FacialHair, out var facialHair))
+ if (facialHair.TryGetValue(0, out var marking))
+ {
+ hca = hca.WithFacialHairStyleName(marking.MarkingId);
+ hca = hca.WithFacialHairColor(marking.MarkingColors.First());
+ }
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Hair, out var hair))
+ if (hair.TryGetValue(0, out var marking))
+ {
+ hca = hca.WithHairStyleName(marking.MarkingId);
+ hca = hca.WithHairColor(marking.MarkingColors.First());
+ }
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Head, out var head))
+ hca = hca.WithMarkings(head);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.HeadSide, out var headSide))
+ hca = hca.WithMarkings(headSide);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.HeadTop, out var headTop))
+ hca = hca.WithMarkings(headTop);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Snout, out var snout))
+ hca = hca.WithMarkings(snout);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Chest, out var chest))
+ hca = hca.WithMarkings(chest);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Arms, out var arms))
+ hca = hca.WithMarkings(arms);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Legs, out var legs))
+ hca = hca.WithMarkings(legs);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Tail, out var tail))
+ hca = hca.WithMarkings(tail);
+ if (humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Overlay, out var overlay))
+ hca = hca.WithMarkings(overlay);
+
+ hca = hca.WithSkinColor(humanoid.SkinColor);
+ hca = hca.WithEyeColor(humanoid.EyeColor);
+
+ return new HumanoidCharacterProfile().
+ WithCharacterAppearance(hca).
+ WithSpecies(data.HumanoidAppearanceComponent.Species).
+ WithSex(data.HumanoidAppearanceComponent.Sex).
+ WithName(data.MetaDataComponent.EntityName);
+ }
+
+ public void TransformChangeling(EntityUid uid, ChangelingComponent component, SelectChangelingFormEvent ev)
+ {
+ var selectedEntity = GetEntity(ev.EntitySelected);
+ var list = component.StoredDNA.Where(x => x.EntityUid == selectedEntity);
+ if (list.Count() <= 0)
+ return;
+
+ var selectedHumanoidData = list.First();
+
+ var dnaComp = EnsureComp(uid);
+
+ if (selectedHumanoidData.DNA == dnaComp.DNA)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-already", ("target", selectedHumanoidData.MetaDataComponent.EntityName));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (component.ArmBladeActive || component.LingArmorActive || component.ChameleonSkinActive || component.MusclesActive || component.DigitalCamouflageActive)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-mutation");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (component.LesserFormActive && ev.Type != ChangelingMenuType.HumanForm)
+ {
+ var selfMessage = Loc.GetString("changeling-transform-fail-lesser-form");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+
+ if (!TryUseAbility(uid, component, component.ChemicalsCostFive))
+ return;
+
+ foreach (var item in component.BoughtActions.Where(x =>
+ x.HasValue &&
+ TryPrototype(x.Value, out var proto) &&
+ proto.ID == "ActionLingLesserForm"))
+ {
+ _action.SetToggled(item, false);
+ }
+
+ component.LesserFormActive = false;
+
+ component.StoredDNA.Remove(selectedHumanoidData);
+
+ var transformedUid = _polymorph.PolymorphEntityAsHumanoid(uid, selectedHumanoidData);
+ if (transformedUid == null)
+ return;
+
+ var message = Loc.GetString("changeling-transform-activate", ("target", selectedHumanoidData.MetaDataComponent.EntityName));
+ _popup.PopupEntity(message, transformedUid.Value, transformedUid.Value);
+
+ CopyLing(uid, transformedUid.Value);
+ }
+
+ public void StealDNA(EntityUid uid, ChangelingComponent component)
+ {
+ var newHumanoidData = _polymorph.TryRegisterPolymorphHumanoidData(uid, uid);
+ if (newHumanoidData == null)
+ return;
+
+ if (component.StoredDNA.Count >= component.DNAStrandCap)
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-full");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return;
+ }
+ else
+ {
+ component.StoredDNA.Add(newHumanoidData.Value);
+ }
+
+ return;
+ }
+
+ private bool TryStingTarget(EntityUid uid, EntityUid target)
+ {
+ if (HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-sting-fail-self", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+
+ var targetMessage = Loc.GetString("changeling-sting-fail-target");
+ _popup.PopupEntity(targetMessage, target, target);
+ return false;
+ }
+
+ if (HasComp(target))
+ {
+ var selfMessageFailNoDna = Loc.GetString("changeling-dna-sting-fail-nodna", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessageFailNoDna, uid, uid);
+ return false;
+ }
+
+ if (!HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-fail-nohuman", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return false;
+ }
+
+ if (!HasComp(target))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-nodna", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return false;
+ }
+
+ if (_tagSystem.HasTag(target, "ChangelingBlacklist"))
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-nodna", ("target", Identity.Entity(target, EntityManager)));
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool ChangeChemicalsAmount(EntityUid uid, float amount, ChangelingComponent? component = null, bool regenCap = true)
+ {
+ if (!Resolve(uid, ref component))
+ return false;
+
+ component.Chemicals += amount;
+
+ if (regenCap)
+ float.Min(component.Chemicals, component.MaxChemicals);
+
+ _alerts.ShowAlert(uid, _proto.Index("Chemicals"), (short)Math.Clamp(Math.Round(component.Chemicals / 10.7f), 0, 7));
+
+ return true;
+ }
+
+ private bool TryUseAbility(EntityUid uid, ChangelingComponent component, float abilityCost, bool activated = true, float regenCost = 0f)
+ {
+ if (component.Chemicals <= Math.Abs(abilityCost) && activated)
+ {
+ _popup.PopupEntity(Loc.GetString("changeling-not-enough-chemicals"), uid, uid);
+ return false;
+ }
+
+ if (activated)
+ {
+ ChangeChemicalsAmount(uid, abilityCost, component, false);
+ component.ChemicalsPerSecond -= regenCost;
+ }
+ else
+ {
+ component.ChemicalsPerSecond += regenCost;
+ }
+
+ return true;
+ }
+
+ public bool StealDNA(EntityUid uid, EntityUid target, ChangelingComponent component)
+ {
+ if (!HasComp(target))
+ return false;
+
+ var newHumanoidData = _polymorph.TryRegisterPolymorphHumanoidData(target);
+ if (newHumanoidData == null)
+ return false;
+
+ else if (component.StoredDNA.Count >= component.DNAStrandCap)
+ {
+ var selfMessage = Loc.GetString("changeling-dna-sting-fail-full");
+ _popup.PopupEntity(selfMessage, uid, uid);
+ return false;
+ }
+
+ else
+ {
+ component.StoredDNA.Add(newHumanoidData.Value);
+ }
+
+ return true;
+ }
+
+ private void UpdateChangeling(EntityUid uid, float frameTime, ChangelingComponent? comp = null)
+ {
+ if (!Resolve(uid, ref comp))
+ return;
+
+ comp.Accumulator += frameTime;
+
+ if (comp.Accumulator <= 1)
+ return;
+ comp.Accumulator -= 1;
+
+ if (comp.Chemicals < comp.MaxChemicals)
+ ChangeChemicalsAmount(uid, _mobState.IsDead(uid) ? comp.ChemicalsPerSecond / 2 : comp.ChemicalsPerSecond, comp, regenCap: true);
+
+ if (comp.MusclesActive)
+ _stamina.TakeStaminaDamage(uid, comp.MusclesStaminaDamage, null, null, null, false);
+
+ }
+}
diff --git a/Content.Server/ADT/GameTicking/Rules/ChangelingRuleSystem.cs b/Content.Server/ADT/GameTicking/Rules/ChangelingRuleSystem.cs
new file mode 100644
index 00000000000..2638ba4d84a
--- /dev/null
+++ b/Content.Server/ADT/GameTicking/Rules/ChangelingRuleSystem.cs
@@ -0,0 +1,72 @@
+using Content.Server.Antag;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Mind;
+using Content.Server.Objectives;
+using Content.Shared.Roles;
+using Robust.Shared.Prototypes;
+using System.Text;
+using Content.Shared.Changeling.Components;
+using Content.Shared.NPC.Systems;
+using Content.Shared.NPC.Prototypes;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Tag;
+
+namespace Content.Server.GameTicking.Rules;
+
+public sealed partial class ChangelingRuleSystem : GameRuleSystem
+{
+ [Dependency] private readonly MindSystem _mind = default!;
+ [Dependency] private readonly AntagSelectionSystem _antag = default!;
+ [Dependency] private readonly NpcFactionSystem _npcFaction = default!;
+ [Dependency] private readonly SharedRoleSystem _role = default!;
+ [Dependency] private readonly TagSystem _tag = default!;
+
+ public readonly ProtoId SyndicateFactionId = "Syndicate";
+
+ public readonly ProtoId NanotrasenFactionId = "NanoTrasen";
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnAntagSelect);
+ // SubscribeLocalEvent(OnObjectivesTextPrepend);
+ }
+
+ private void OnAntagSelect(Entity ent, ref AfterAntagEntitySelectedEvent args)
+ {
+ TryMakeChangeling(args.EntityUid, ent.Comp);
+ }
+
+ public bool TryMakeChangeling(EntityUid target, ChangelingRuleComponent rule)
+ {
+ if (!_mind.TryGetMind(target, out var mindId, out var mind))
+ return false;
+ if (_tag.HasTag(target, "ChangelingBlacklist"))
+ return false;
+
+ // briefing
+ if (HasComp(target))
+ {
+ _antag.SendBriefing(target, Loc.GetString("changeling-role-greeting", ("character-name", Identity.Entity(target, EntityManager))), Color.Red, rule.ChangelingStartSound);
+
+ _role.MindAddRole(mindId, "MindRoleChangeling", mind, true);
+ }
+
+ _npcFaction.RemoveFaction(target, NanotrasenFactionId, false);
+ _npcFaction.AddFaction(target, SyndicateFactionId);
+
+ // Ensure Changeling component and role
+ EnsureComp(target);
+
+ rule.Minds.Add(mindId);
+
+ return true;
+ }
+
+
+ // public void OnObjectivesTextPrepend(Entity ent, ref ObjectivesTextPrependEvent args)
+ // {
+ // args.Text += "\n" + Loc.GetString("traitor-round-end-codewords", ("codewords", string.Join(", ", comp.Codewords)));
+ // }
+}
diff --git a/Content.Server/ADT/GameTicking/Rules/Components/ChangelingRuleComponent.cs b/Content.Server/ADT/GameTicking/Rules/Components/ChangelingRuleComponent.cs
new file mode 100644
index 00000000000..2491438970b
--- /dev/null
+++ b/Content.Server/ADT/GameTicking/Rules/Components/ChangelingRuleComponent.cs
@@ -0,0 +1,17 @@
+using Robust.Shared.Audio;
+using Robust.Shared.Prototypes;
+using Content.Shared.Store;
+
+namespace Content.Server.GameTicking.Rules.Components;
+
+[RegisterComponent, Access(typeof(ChangelingRuleSystem))]
+public sealed partial class ChangelingRuleComponent : Component
+{
+ public readonly List Minds = new();
+
+ ///
+ /// Path to changeling start sound.
+ ///
+ [DataField]
+ public SoundSpecifier ChangelingStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/changeling_start.ogg");
+}
diff --git a/Content.Server/ADT/Objectives/Components/AbsorbDnaConditionComponent.cs b/Content.Server/ADT/Objectives/Components/AbsorbDnaConditionComponent.cs
new file mode 100644
index 00000000000..cba90d4a531
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Components/AbsorbDnaConditionComponent.cs
@@ -0,0 +1,25 @@
+using Content.Server.Objectives.Systems;
+
+namespace Content.Server.Objectives.Components;
+
+///
+/// Requires that the player is on the emergency shuttle's grid when docking to CentCom.
+///
+[RegisterComponent, Access(typeof(AbsorbDnaConditionSystem))]
+public sealed partial class AbsorbDnaConditionComponent : Component
+{
+ [DataField]
+ public int AbsorbDnaCount = 4;
+
+ [DataField]
+ public int MaxDnaCount = 4;
+
+ [DataField]
+ public int MinDnaCount = 2;
+
+ [DataField(required: true)]
+ public LocId ObjectiveText;
+ [DataField(required: true)]
+ public LocId DescriptionText;
+
+}
diff --git a/Content.Server/ADT/Objectives/Components/PickRandomDnaComponent.cs b/Content.Server/ADT/Objectives/Components/PickRandomDnaComponent.cs
new file mode 100644
index 00000000000..9b85ae2fc03
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Components/PickRandomDnaComponent.cs
@@ -0,0 +1,11 @@
+using Content.Server.Objectives.Systems;
+
+namespace Content.Server.Objectives.Components;
+
+///
+/// Sets the target for to a random person.
+///
+[RegisterComponent, Access(typeof(StealPersonalityConditionSystem))]
+public sealed partial class PickRandomDnaComponent : Component
+{
+}
diff --git a/Content.Server/ADT/Objectives/Components/PickRandomHeadDnaComponent.cs b/Content.Server/ADT/Objectives/Components/PickRandomHeadDnaComponent.cs
new file mode 100644
index 00000000000..d8fe0ecd714
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Components/PickRandomHeadDnaComponent.cs
@@ -0,0 +1,12 @@
+using Content.Server.Objectives.Systems;
+
+namespace Content.Server.Objectives.Components;
+
+///
+/// Sets the target for to a random head.
+/// If there are no heads it will fallback to any person.
+///
+[RegisterComponent, Access(typeof(StealPersonalityConditionSystem))]
+public sealed partial class PickRandomHeadDnaComponent : Component
+{
+}
diff --git a/Content.Server/ADT/Objectives/Components/StealPersonalityConditionComponent.cs b/Content.Server/ADT/Objectives/Components/StealPersonalityConditionComponent.cs
new file mode 100644
index 00000000000..95b60ca200c
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Components/StealPersonalityConditionComponent.cs
@@ -0,0 +1,20 @@
+using Content.Server.Objectives.Systems;
+
+namespace Content.Server.Objectives.Components;
+
+///
+/// Requires that a target dies or, if is false, is not on the emergency shuttle.
+/// Depends on to function.
+///
+[RegisterComponent, Access(typeof(StealPersonalityConditionSystem))]
+public sealed partial class StealPersonalityConditionComponent : Component
+{
+ ///
+ /// Whether the target must be truly dead, ignores missing evac.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool RequireDead = false;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public string? ReqiredDNA;
+}
diff --git a/Content.Server/ADT/Objectives/Systems/AbsorbDnaConditionSystem.cs b/Content.Server/ADT/Objectives/Systems/AbsorbDnaConditionSystem.cs
new file mode 100644
index 00000000000..2681adcfa08
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Systems/AbsorbDnaConditionSystem.cs
@@ -0,0 +1,75 @@
+using Content.Server.Objectives.Components;
+using Content.Server.Shuttles.Systems;
+using Content.Shared.Changeling.Components;
+using Robust.Shared.Random;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Components;
+using Content.Shared.Mobs.Systems;
+
+namespace Content.Server.Objectives.Systems;
+
+public sealed class AbsorbDnaConditionSystem : EntitySystem
+{
+ [Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
+ [Dependency] private readonly SharedMindSystem _mind = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly MetaDataSystem _metaData = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnAssigned);
+ SubscribeLocalEvent(OnAfterAssign);
+
+ SubscribeLocalEvent(OnGetProgress);
+ }
+
+ private void OnAssigned(Entity condition, ref ObjectiveAssignedEvent args)
+ {
+ var maxSize = condition.Comp.MaxDnaCount;
+
+ var minSize = condition.Comp.MinDnaCount;
+
+ condition.Comp.AbsorbDnaCount = _random.Next(minSize, maxSize);
+
+ }
+
+ public void OnAfterAssign(Entity condition, ref ObjectiveAfterAssignEvent args)
+ {
+ var title = Loc.GetString(condition.Comp.ObjectiveText, ("count", condition.Comp.AbsorbDnaCount));
+
+ var description = Loc.GetString(condition.Comp.DescriptionText, ("count", condition.Comp.AbsorbDnaCount));
+
+ _metaData.SetEntityName(condition.Owner, title, args.Meta);
+ _metaData.SetEntityDescription(condition.Owner, description, args.Meta);
+
+ }
+ private void OnGetProgress(EntityUid uid, AbsorbDnaConditionComponent comp, ref ObjectiveGetProgressEvent args)
+ {
+ if (args.Mind.OwnedEntity != null)
+ {
+ var ling = args.Mind.OwnedEntity.Value;
+ args.Progress = GetProgress(ling, args.MindId, args.Mind, comp);
+ }
+ else
+ args.Progress = 0f;
+ }
+
+ private float GetProgress(EntityUid uid, EntityUid mindId, MindComponent mind, AbsorbDnaConditionComponent comp)
+ {
+ // Не генокрад - не выполнил цель (да ладно.)
+ if (!TryComp(uid, out var ling))
+ return 0f;
+
+ // Умер - не выполнил цель.
+ if (mind.OwnedEntity == null || _mind.IsCharacterDeadIc(mind))
+ return 0f;
+
+ // Подсчёт требуемых и имеющихся ДНК
+ var count = ling.AbsorbedDnaModifier;
+ var result = count / comp.AbsorbDnaCount;
+ result = Math.Clamp(result, 0, 1);
+ return result;
+ }
+}
diff --git a/Content.Server/ADT/Objectives/Systems/StealPersonalityConditionSystem.cs b/Content.Server/ADT/Objectives/Systems/StealPersonalityConditionSystem.cs
new file mode 100644
index 00000000000..d0860454c2c
--- /dev/null
+++ b/Content.Server/ADT/Objectives/Systems/StealPersonalityConditionSystem.cs
@@ -0,0 +1,146 @@
+using Content.Server.Objectives.Components;
+using Content.Server.Shuttles.Systems;
+using Content.Shared.CCVar;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Components;
+using Content.Shared.Roles.Jobs;
+using Robust.Shared.Configuration;
+using Robust.Shared.Random;
+using Content.Server.Forensics;
+using Content.Shared.Cuffs.Components;
+
+namespace Content.Server.Objectives.Systems;
+
+///
+/// Handles kill person condition logic and picking random kill targets.
+///
+public sealed class StealPersonalityConditionSystem : EntitySystem
+{
+ [Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
+ [Dependency] private readonly IConfigurationManager _config = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedJobSystem _job = default!;
+ [Dependency] private readonly SharedMindSystem _mind = default!;
+ [Dependency] private readonly TargetObjectiveSystem _target = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnGetProgress);
+
+ SubscribeLocalEvent(OnPersonAssigned);
+
+ SubscribeLocalEvent(OnHeadAssigned);
+ }
+
+ private void OnGetProgress(EntityUid uid, StealPersonalityConditionComponent comp, ref ObjectiveGetProgressEvent args)
+ {
+ if (!_target.GetTarget(uid, out var target))
+ return;
+
+ args.Progress = GetProgress(args.MindId, args.Mind, target.Value, comp.ReqiredDNA ?? "", comp.RequireDead);
+ }
+
+ private void OnPersonAssigned(EntityUid uid, PickRandomDnaComponent comp, ref ObjectiveAssignedEvent args)
+ {
+ // invalid objective prototype
+ if (!TryComp(uid, out var target))
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ // target already assigned
+ if (target.Target != null)
+ return;
+
+ // no other humans to kill
+ var allHumans = _mind.GetAliveHumansExcept(args.MindId);
+ if (allHumans.Count == 0)
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ if (!TryComp(uid, out var reqiredDna))
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ if (TryComp(uid, out var pers))
+ pers.ReqiredDNA = reqiredDna.DNA;
+ }
+
+ private void OnHeadAssigned(EntityUid uid, PickRandomHeadDnaComponent comp, ref ObjectiveAssignedEvent args)
+ {
+ // invalid prototype
+ if (!TryComp(uid, out var target))
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ // target already assigned
+ if (target.Target != null)
+ return;
+
+ // no other humans to kill
+ var allHumans = _mind.GetAliveHumansExcept(args.MindId);
+ if (allHumans.Count == 0)
+ {
+ args.Cancelled = true;
+ return;
+ }
+
+ var allHeads = new List();
+ foreach (var mind in allHumans)
+ {
+ // RequireAdminNotify used as a cheap way to check for command department
+ if (_job.MindTryGetJob(mind, out var prototype) && prototype.RequireAdminNotify)
+ allHeads.Add(mind);
+ }
+
+ if (allHeads.Count == 0)
+ allHeads = allHumans; // fallback to non-head target
+
+ if (!TryComp(uid, out var reqiredDna))
+ {
+ args.Cancelled = true;
+ return;
+ }
+ if (TryComp(uid, out var pers))
+ pers.ReqiredDNA = reqiredDna.DNA;
+ }
+
+ private float GetProgress(EntityUid mindId, MindComponent mind, EntityUid target, string targetDna, bool requireDead)
+ {
+ // Генокрада не существует?
+ if (!TryComp(mindId, out _))
+ return 0f;
+
+ // Если генокрад в форме обезьяны, например
+ if (!TryComp(mind.CurrentEntity, out var dna))
+ return 0f;
+
+ if (_emergencyShuttle.ShuttlesLeft && _emergencyShuttle.IsTargetEscaping(mind.CurrentEntity.Value))
+ {
+ if (_emergencyShuttle.IsTargetEscaping(target))
+ return 0f;
+ if (dna.DNA == targetDna && TryComp(mind.CurrentEntity, out var cuffed) && cuffed.CuffedHandCount > 0)
+ return 1f;
+ }
+ else
+ {
+ // ДНК соответствует, но нужно ещё улететь и убить цель
+ if (targetDna == dna.DNA)
+ return 0.5f;
+ else
+ return 0f;
+ }
+
+ // Эвак ждёт, а цель ещё не пришла к нему. Ещё и жива, падаль.
+ return _emergencyShuttle.EmergencyShuttleArrived ? 0.5f : 0f;
+ }
+}
diff --git a/Content.Server/ADT/Store/ActionBoughtEvent.cs b/Content.Server/ADT/Store/ActionBoughtEvent.cs
new file mode 100644
index 00000000000..c43b88ccb10
--- /dev/null
+++ b/Content.Server/ADT/Store/ActionBoughtEvent.cs
@@ -0,0 +1,4 @@
+namespace Content.Server.ADT.Store;
+
+[ByRefEvent]
+public record struct ActionBoughtEvent(EntityUid? ActionEntity);
diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs
index d755a54bf8f..13e93af0277 100644
--- a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs
+++ b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs
@@ -36,6 +36,11 @@ public sealed partial class AdminVerbSystem
[ValidatePrototypeId]
private const string PirateGearId = "PirateGear";
+ // ADT-Changeling-Tweak-Start
+ [ValidatePrototypeId]
+ private const string DefaultChangelingRule = "ChangelingGameRule";
+ // ADT-Changeling-Tweak-End
+
// All antag verbs have names so invokeverb works.
private void AddAntagVerbs(GetVerbsEvent args)
{
@@ -166,5 +171,21 @@ private void AddAntagVerbs(GetVerbsEvent args)
Message = Loc.GetString("admin-verb-make-heretic"),
};
args.Verbs.Add(heretic);
+
+ // ADT-Changeling-Tweak-Start
+ Verb changeling = new()
+ {
+ Text = Loc.GetString("admin-verb-text-make-changeling"),
+ Category = VerbCategory.Antag,
+ Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/ADT/Changeling/Objects/armblade.rsi"), "icon"),
+ Act = () =>
+ {
+ _antag.ForceMakeAntag(targetPlayer, DefaultChangelingRule);
+ },
+ Impact = LogImpact.High,
+ Message = Loc.GetString("admin-verb-make-changeling"),
+ };
+ args.Verbs.Add(changeling);
+ // ADT-Changeling-Tweak-End
}
}
diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs
index 9a27de3b1d9..58d29dd3d37 100644
--- a/Content.Server/Ghost/GhostSystem.cs
+++ b/Content.Server/Ghost/GhostSystem.cs
@@ -519,7 +519,7 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma
if (mind.PreventGhosting)
{
- if (mind.Session != null) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts
+ if (mind.Session != null && mind.PreventGhostingSendMessage) // Logging is suppressed to prevent spam from ghost attempts caused by movement attempts // ADT tweak
{
_chatManager.DispatchServerMessage(mind.Session, Loc.GetString("comp-mind-ghosting-prevented"),
true);
diff --git a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.cs b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.cs
index 92944b2b15f..0407628e1d6 100644
--- a/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.cs
+++ b/Content.Server/Humanoid/Systems/HumanoidAppearanceSystem.cs
@@ -1,26 +1,42 @@
-using Content.Shared.ADT.SpeechBarks;
+using Content.Shared.Examine; // ADT-Changeling-Tweak
+using System.Linq; // ADT-Changeling-Tweak
+using Content.Shared.Decals; // ADT-Changeling-Tweak
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
+using Content.Shared.IdentityManagement; // ADT-Changeling-Tweak
using Content.Shared.Preferences;
using Content.Shared.Verbs;
using Robust.Shared.GameObjects.Components.Localization;
+using Robust.Shared.Prototypes; // ADT-Changeling-Tweak
namespace Content.Server.Humanoid;
public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
{
[Dependency] private readonly MarkingManager _markingManager = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!; // ADT-Changeling-Tweak
public override void Initialize()
{
base.Initialize();
-
SubscribeLocalEvent(OnMarkingsSet);
SubscribeLocalEvent(OnBaseLayersSet);
SubscribeLocalEvent>(OnVerbsRequest);
+ //SubscribeLocalEvent(OnExamined);
}
+ // ADT-Changeling-Tweak-Start
+ private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
+ {
+ var identity = Identity.Entity(uid, EntityManager);
+ var species = GetSpeciesRepresentation(component.Species).ToLower();
+ var age = GetAgeRepresentation(component.Species, component.Age);
+
+ args.PushText(Loc.GetString("humanoid-appearance-component-examine", ("user", identity), ("age", age), ("species", species)));
+ }
+ // ADT-Changeling-Tweak-End
+
// this was done enough times that it only made sense to do it here
///
@@ -30,33 +46,50 @@ public override void Initialize()
/// Target entity to apply the source entity's appearance to.
/// Source entity's humanoid component.
/// Target entity's humanoid component.
- public void CloneAppearance(EntityUid source, EntityUid target, HumanoidAppearanceComponent? sourceHumanoid = null,
- HumanoidAppearanceComponent? targetHumanoid = null)
+
+ // ADT-Changeling-Tweak-Start
+ public void SetAppearance(HumanoidAppearanceComponent sourceHumanoid, HumanoidAppearanceComponent targetHumanoid)
{
- if (!Resolve(source, ref sourceHumanoid) || !Resolve(target, ref targetHumanoid))
- {
- return;
- }
targetHumanoid.Species = sourceHumanoid.Species;
targetHumanoid.SkinColor = sourceHumanoid.SkinColor;
targetHumanoid.EyeColor = sourceHumanoid.EyeColor;
targetHumanoid.Age = sourceHumanoid.Age;
- SetSex(target, sourceHumanoid.Sex, false, targetHumanoid);
+ SetSex(targetHumanoid.Owner, sourceHumanoid.Sex, false, targetHumanoid);
targetHumanoid.CustomBaseLayers = new(sourceHumanoid.CustomBaseLayers);
targetHumanoid.MarkingSet = new(sourceHumanoid.MarkingSet);
- SetTTSVoice(target, sourceHumanoid.Voice, targetHumanoid); // Corvax-TTS
- if (TryComp(source, out var barks))
- SetBarkData(target, barks.Sound, barks.BarkPitch, barks.BarkLowVar, barks.BarkHighVar); // ADT Barks
+ SetTTSVoice(targetHumanoid.Owner, sourceHumanoid.Voice, targetHumanoid); // Corvax-TTS
targetHumanoid.Gender = sourceHumanoid.Gender;
- if (TryComp(target, out var grammar))
+ if (TryComp(targetHumanoid.Owner, out var grammar))
{
grammar.Gender = sourceHumanoid.Gender;
}
- Dirty(target, targetHumanoid);
+ Dirty(targetHumanoid.Owner, targetHumanoid);
+ }
+ // ADT-Changeling-Tweak-End
+
+ ///
+ /// Clones a humanoid's appearance to a target mob, provided they both have humanoid components.
+ ///
+ /// Source entity to fetch the original appearance from.
+ /// Target entity to apply the source entity's appearance to.
+ /// Source entity's humanoid component.
+ /// Target entity's humanoid component.
+
+ // ADT-Changeling-Tweak-Start
+ public void CloneAppearance(EntityUid source, EntityUid target, HumanoidAppearanceComponent? sourceHumanoid = null,
+ HumanoidAppearanceComponent? targetHumanoid = null)
+ {
+ if (!Resolve(source, ref sourceHumanoid) || !Resolve(target, ref targetHumanoid))
+ {
+ return;
+ }
+
+ SetAppearance(sourceHumanoid, targetHumanoid);
}
+ // ADT-Changeling-Tweak-End
///
/// Removes a marking from a humanoid by ID.
@@ -155,4 +188,44 @@ public void SetMarkingColor(EntityUid uid, MarkingCategories category, int index
Dirty(uid, humanoid);
}
+
+ // ADT-Changeling-Tweak-Start
+ ///
+ /// Takes ID of the species prototype, returns UI-friendly name of the species.
+ ///
+ public string GetSpeciesRepresentation(string speciesId)
+ {
+ if (_prototypeManager.TryIndex(speciesId, out var species))
+ {
+ return Loc.GetString(species.Name);
+ }
+ else
+ {
+ return Loc.GetString("humanoid-appearance-component-unknown-species");
+ }
+ }
+
+ public string GetAgeRepresentation(string species, int age)
+ {
+ _prototypeManager.TryIndex(species, out var speciesPrototype);
+
+ if (speciesPrototype == null)
+ {
+ Logger.Error("Tried to get age representation of species that couldn't be indexed: " + species);
+ return Loc.GetString("identity-age-young");
+ }
+
+ if (age < speciesPrototype.YoungAge)
+ {
+ return Loc.GetString("identity-age-young");
+ }
+
+ if (age < speciesPrototype.OldAge)
+ {
+ return Loc.GetString("identity-age-middle-aged");
+ }
+
+ return Loc.GetString("identity-age-old");
+ }
+ // ADT-Changeling-Tweak-End
}
diff --git a/Content.Server/Inventory/ServerInventorySystem.cs b/Content.Server/Inventory/ServerInventorySystem.cs
index e3783753bbc..a97697d6129 100644
--- a/Content.Server/Inventory/ServerInventorySystem.cs
+++ b/Content.Server/Inventory/ServerInventorySystem.cs
@@ -31,8 +31,8 @@ public void TransferEntityInventories(Entity source, Entity
var enumerator = new InventorySlotEnumerator(source.Comp);
while (enumerator.NextItem(out var item, out var slot))
{
- if (TryUnequip(source, slot.Name, true, true, inventory: source.Comp))
- TryEquip(target, item, slot.Name , true, true, inventory: target.Comp);
+ if (!TryEquip(target, item, slot.Name , true, true, inventory: target.Comp)) // ADT-Changeling-Tweak
+ TryUnequip(source, slot.Name, true, true, inventory: source.Comp); // ADT-Changeling-Tweak
}
}
}
diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs
index da7a251c06a..90a1b52e299 100644
--- a/Content.Server/Medical/DefibrillatorSystem.cs
+++ b/Content.Server/Medical/DefibrillatorSystem.cs
@@ -24,7 +24,11 @@
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Timing;
-using Content.Shared.ADT.Atmos.Miasma; //ADT-Medicine
+using Content.Shared.ADT.Atmos.Miasma;
+using Content.Shared.Changeling.Components;
+using Robust.Server.Containers;
+using System.Linq;
+using Content.Server.Resist; //ADT-Medicine
namespace Content.Server.Medical;
@@ -48,6 +52,7 @@ public sealed class DefibrillatorSystem : EntitySystem
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
+ [Dependency] private readonly ContainerSystem _container = default!;
///
public override void Initialize()
@@ -148,6 +153,28 @@ public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorCo
ICommonSession? session = null;
var dead = true;
+ // ADT Changeling start
+ if (TryComp(target, out var slug))
+ {
+ _chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-changeling-slug"),
+ InGameICChatType.Speak, true);
+
+ var headslug = slug.Container.ContainedEntities.First();
+ _container.EmptyContainer(slug.Container, true);
+ _electrocution.TryDoElectrocution(headslug, null, component.ZapDamage, component.WritheDuration, true, ignoreInsulation: true);
+ if (TryComp(headslug, out var slugComp))
+ {
+ slugComp.Accumulator = 0;
+ slugComp.Alerted = false;
+ slugComp.Container = null;
+ }
+ EnsureComp(headslug);
+
+ RemComp(target, slug);
+ return;
+ }
+ // ADT Changeling end
+
if (_rotting.IsRotten(target))
{
_chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-rotten"),
diff --git a/Content.Server/Objectives/Components/TargetObjectiveComponent.cs b/Content.Server/Objectives/Components/TargetObjectiveComponent.cs
index c0cd521bc7c..26233d8f3e7 100644
--- a/Content.Server/Objectives/Components/TargetObjectiveComponent.cs
+++ b/Content.Server/Objectives/Components/TargetObjectiveComponent.cs
@@ -18,4 +18,7 @@ public sealed partial class TargetObjectiveComponent : Component
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
public EntityUid? Target;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)] // ADT-Changeling-Tweak
+ public string? TargetDNA;
}
diff --git a/Content.Server/Objectives/Systems/TargetObjectiveSystem.cs b/Content.Server/Objectives/Systems/TargetObjectiveSystem.cs
index 82ebd28ca9e..81d9c1965cf 100644
--- a/Content.Server/Objectives/Systems/TargetObjectiveSystem.cs
+++ b/Content.Server/Objectives/Systems/TargetObjectiveSystem.cs
@@ -4,6 +4,7 @@
using Content.Shared.Roles.Jobs;
using Robust.Shared.GameObjects;
using System.Diagnostics.CodeAnalysis;
+using Content.Server.Forensics; // ADT-Changeling-Tweak
namespace Content.Server.Objectives.Systems;
diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs
index 08c94bc5d0a..96abd3c2a88 100644
--- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs
+++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs
@@ -1,5 +1,6 @@
using Content.Server.Actions;
using Content.Server.Humanoid;
+using Content.Shared.Humanoid; // ADT-Changeling-Tweak
using Content.Server.Inventory;
using Content.Server.Mind.Commands;
using Content.Server.Nutrition;
@@ -22,6 +23,9 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
+using Content.Server.Forensics; // ADT-Changeling-Tweak
+using Content.Shared.Mindshield.Components; // ADT-Changeling-Tweak
+using Robust.Shared.Serialization.Manager; // ADT-Changeling-Tweak
namespace Content.Server.Polymorph.Systems;
@@ -45,7 +49,7 @@ public sealed partial class PolymorphSystem : EntitySystem
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
-
+ [Dependency] private readonly ISerializationManager _serialization = default!; // ADT-Changeling-Tweak
private const string RevertPolymorphId = "ActionRevertPolymorph";
public override void Initialize()
@@ -255,17 +259,89 @@ private void OnDestruction(Entity ent, ref Destructi
{
_humanoid.CloneAppearance(uid, child);
}
+ // ADT-Changeling-Tweak-Start
+ if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+ _mindSystem.TransferTo(mindId, child, mind: mind);
+ SendToPausedMap(uid, targetTransformComp);
+
+ return child;
+ }
+
+ ///
+ /// Polymorphs the target entity into an exact copy of the given PolymorphHumanoidData
+ ///
+ /// The entity that will be transformed
+ /// The humanoid data
+ public EntityUid? PolymorphEntityAsHumanoid(EntityUid uid, PolymorphHumanoidData data)
+ {
+ var targetTransformComp = Transform(uid);
+ var child = data.EntityUid;
+
+ RetrievePausedEntity(uid, child);
+
+ if (TryComp(child, out var humanoidAppearance))
+ _humanoid.SetAppearance(data.HumanoidAppearanceComponent, humanoidAppearance);
+
+ if (TryComp(child, out var dnaComp))
+ dnaComp.DNA = data.DNA;
+
+ //Transfers all damage from the original to the new one
+ if (TryComp(child, out var damageParent)
+ && _mobThreshold.GetScaledDamage(uid, child, out var damage)
+ && damage != null)
+ {
+ _damageable.SetDamage(child, damageParent, damage);
+ }
+ _inventory.TransferEntityInventories(uid, child); // transfer the inventory all the time
+ foreach (var hand in _hands.EnumerateHeld(uid))
+ {
+ if (!_hands.TryPickupAnyHand(child, hand))
+ _hands.TryDrop(uid, hand, checkActionBlocker: false);
+ }
+ // ADT-Changeling-Tweak-End
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
_mindSystem.TransferTo(mindId, child, mind: mind);
- //Ensures a map to banish the entity to
EnsurePausedMap();
if (PausedMap != null)
_transform.SetParent(uid, targetTransformComp, PausedMap.Value);
return child;
}
+ // ADT-Changeling-Tweak-Start
+ ///
+ /// Sends the given entity to a pauses map
+ ///
+ public void SendToPausedMap(EntityUid uid, TransformComponent transform)
+ {
+ //Ensures a map to banish the entity to
+ EnsurePausedMap();
+ if (PausedMap != null)
+ _transform.SetParent(uid, transform, PausedMap.Value);
+ }
+
+ ///
+ /// Retrieves a paused entity (target) at the user's position
+ ///
+ private void RetrievePausedEntity(EntityUid user, EntityUid target)
+ {
+ if (Deleted(user))
+ return;
+ if (Deleted(target))
+ return;
+
+ var targetTransform = Transform(target);
+ var userTransform = Transform(user);
+
+ _transform.SetParent(target, targetTransform, user);
+ targetTransform.Coordinates = userTransform.Coordinates;
+ targetTransform.LocalRotation = userTransform.LocalRotation;
+
+ if (_container.TryGetContainingContainer(user, out var cont))
+ _container.Insert(target, cont);
+ }
+ // ADT-Changeling-Tweak-End
///
/// Reverts a polymorphed entity back into its original form
@@ -387,6 +463,92 @@ public void RemovePolymorphAction(ProtoId id, Entity
+ /// Registers PolymorphHumanoidData from an EntityUid, provived they have all the needed components
+ ///
+ /// The source that the humanoid data is referencing from
+ public PolymorphHumanoidData? TryRegisterPolymorphHumanoidData(EntityUid source)
+ {
+ var newHumanoidData = new PolymorphHumanoidData();
+
+ if (!TryComp(source, out var targetMeta))
+ return null;
+ if (!TryPrototype(source, out var prototype, targetMeta))
+ return null;
+ if (!TryComp(source, out var dnaComp))
+ return null;
+ if (!TryComp(source, out var targetHumanoidAppearance))
+ return null;
+
+
+ newHumanoidData.EntityPrototype = prototype;
+ newHumanoidData.MetaDataComponent = targetMeta;
+ newHumanoidData.HumanoidAppearanceComponent = _serialization.CreateCopy(targetHumanoidAppearance, notNullableOverride: true);
+ newHumanoidData.DNA = dnaComp.DNA;
+
+ var targetTransformComp = Transform(source);
+
+ var newEntityUid = Spawn(newHumanoidData.EntityPrototype.ID, targetTransformComp.Coordinates);
+ var newEntityUidTransformComp = Transform(newEntityUid);
+
+ if (TryComp(source, out MindShieldComponent? mindshieldComp)) // copy over mindshield status
+ {
+ var copiedMindshieldComp = (Component) _serialization.CreateCopy(mindshieldComp, notNullableOverride: true);
+ EntityManager.AddComponent(newEntityUid, copiedMindshieldComp);
+ }
+
+ SendToPausedMap(newEntityUid, newEntityUidTransformComp);
+
+ newHumanoidData.EntityUid = newEntityUid;
+ _metaData.SetEntityName(newEntityUid, targetMeta.EntityName);
+
+ return newHumanoidData;
+ }
+
+ ///
+ /// Registers PolymorphHumanoidData from an EntityUid, provived they have all the needed components. This allows you to add a uid as the HumanoidData's EntityUid variable. Does not send the given uid to the pause map.
+ ///
+ /// The source that the humanoid data is referencing from
+ /// The uid that will become the newHumanoidData's EntityUid
+ public PolymorphHumanoidData? TryRegisterPolymorphHumanoidData(EntityUid source, EntityUid uid)
+ {
+ var newHumanoidData = new PolymorphHumanoidData();
+
+ if (!TryComp(source, out var targetMeta))
+ return null;
+ if (!TryPrototype(source, out var prototype, targetMeta))
+ return null;
+ if (!TryComp(source, out var dnaComp))
+ return null;
+ if (!TryComp(source, out var targetHumanoidAppearance))
+ return null;
+
+ newHumanoidData.EntityPrototype = prototype;
+ newHumanoidData.MetaDataComponent = targetMeta;
+ newHumanoidData.HumanoidAppearanceComponent = _serialization.CreateCopy(targetHumanoidAppearance, notNullableOverride: true);;
+ newHumanoidData.DNA = dnaComp.DNA;
+ newHumanoidData.EntityUid = uid;
+
+ return newHumanoidData;
+ }
+
+ public PolymorphHumanoidData CopyPolymorphHumanoidData(PolymorphHumanoidData data)
+ {
+ var newHumanoidData = new PolymorphHumanoidData();
+ var ent = Spawn(data.EntityPrototype.ID);
+ SendToPausedMap(ent, Transform(ent));
+
+ newHumanoidData.EntityPrototype = data.EntityPrototype;
+ newHumanoidData.MetaDataComponent = data.MetaDataComponent;
+ newHumanoidData.HumanoidAppearanceComponent = _serialization.CreateCopy(data.HumanoidAppearanceComponent, notNullableOverride: true);;
+ newHumanoidData.DNA = data.DNA;
+ newHumanoidData.EntityUid = ent;
+ _metaData.SetEntityName(ent, data.MetaDataComponent.EntityName);
+ return newHumanoidData;
+ }
+ // ADT-Changeling-Tweak-End
}
// goob edit
diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
index dec4d191e03..ba28d57a98c 100644
--- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
+++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs
@@ -180,7 +180,7 @@ private bool TryUseAbility(EntityUid uid, RevenantComponent component, FixedPoin
var tileref = Transform(uid).Coordinates.GetTileRef();
if (tileref != null)
{
- if(_physics.GetEntitiesIntersectingBody(uid, (int) CollisionGroup.Impassable).Count > 0)
+ if (_physics.GetEntitiesIntersectingBody(uid, (int) CollisionGroup.Impassable).Count > 0)
{
_popup.PopupEntity(Loc.GetString("revenant-in-solid"), uid, uid);
return false;
@@ -197,9 +197,7 @@ private bool TryUseAbility(EntityUid uid, RevenantComponent component, FixedPoin
private void OnShop(EntityUid uid, RevenantComponent component, RevenantShopActionEvent args)
{
- if (!TryComp(uid, out var store))
- return;
- _store.ToggleUi(uid, uid, store);
+ _store.OnInternalShop(uid); // ADT-Changeling-Tweak
}
private void OnSinguloConsumeAttempt(EntityUid uid, RevenantComponent component, ref EventHorizonAttemptConsumeEntityEvent args) // ADT
diff --git a/Content.Server/Store/Systems/StoreSystem.Listings.cs b/Content.Server/Store/Systems/StoreSystem.Listings.cs
index 4699ec7b669..2e39485128c 100644
--- a/Content.Server/Store/Systems/StoreSystem.Listings.cs
+++ b/Content.Server/Store/Systems/StoreSystem.Listings.cs
@@ -2,11 +2,13 @@
using Content.Shared.Store;
using Content.Shared.Store.Components;
using Robust.Shared.Prototypes;
+using Content.Shared.Actions; // ADT-Changeling-Tweak
namespace Content.Server.Store.Systems;
public sealed partial class StoreSystem
{
+
///
/// Refreshes all listings on a store.
/// Do not use if you don't know what you're doing.
diff --git a/Content.Server/Store/Systems/StoreSystem.Ui.cs b/Content.Server/Store/Systems/StoreSystem.Ui.cs
index e73b03cfe48..9512f58df02 100644
--- a/Content.Server/Store/Systems/StoreSystem.Ui.cs
+++ b/Content.Server/Store/Systems/StoreSystem.Ui.cs
@@ -1,6 +1,8 @@
using System.Linq;
using Content.Server.Actions;
using Content.Server.Administration.Logs;
+using Content.Server.ADT.Store; // ADT-Changeling-Tweak
+using Content.Server.Botany.Components; // ADT-Changeling-Tweak
using Content.Server.Heretic.EntitySystems;
using Content.Server.PDA.Ringer;
using Content.Server.Stack;
@@ -218,11 +220,16 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
EntityUid? actionId;
// I guess we just allow duplicate actions?
// Allow duplicate actions and just have a single list buy for the buy-once ones.
- if (!_mind.TryGetMind(buyer, out var mind, out _))
+ if (!_mind.TryGetMind(buyer, out var mind, out _) || !listing.MindAction) // ADT-Changeling-Tweak
actionId = _actions.AddAction(buyer, listing.ProductAction);
else
actionId = _actionContainer.AddAction(mind, listing.ProductAction);
+ // ADT start
+ var actionEv = new ActionBoughtEvent(actionId);
+ RaiseLocalEvent(buyer, ref actionEv);
+ // ADT end
+
// Add the newly bought action entity to the list of bought entities
// And then add that action entity to the relevant product upgrade listing, if applicable
if (actionId != null)
diff --git a/Content.Server/Store/Systems/StoreSystem.cs b/Content.Server/Store/Systems/StoreSystem.cs
index 7bdf550301e..6c9769757ab 100644
--- a/Content.Server/Store/Systems/StoreSystem.cs
+++ b/Content.Server/Store/Systems/StoreSystem.cs
@@ -10,6 +10,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using System.Linq;
+using Content.Shared.Store; // ADT-Changeling-Tweak
namespace Content.Server.Store.Systems;
@@ -105,6 +106,18 @@ private void OnImplantActivate(EntityUid uid, StoreComponent component, OpenUpli
ToggleUi(args.Performer, uid, component);
}
+ ///
+ /// Toggles the shop UI if the given entityuid has a shop component.
+ /// Used for things such as revenants or changelings.
+ ///
+
+ public void OnInternalShop(EntityUid uid)
+ {
+ if (!TryComp(uid, out StoreComponent? store))
+ return;
+ ToggleUi(uid, uid, store);
+ }
+
///
/// Gets the value from an entity's currency component.
/// Scales with stacks.
@@ -181,6 +194,77 @@ public bool TryAddCurrency(Dictionary currency, EntityUid u
UpdateUserInterface(null, uid, store);
return true;
}
+
+ // ADT changeling start
+ public bool TryAddStore(EntityUid uid,
+ HashSet> currencyWhitelist,
+ HashSet> categories,
+ Dictionary, FixedPoint2> balance,
+ bool allowRefund,
+ bool ownerOnly)
+ {
+ if (HasComp(uid))
+ return false;
+
+ AddStore(uid, currencyWhitelist, categories, balance, allowRefund, ownerOnly);
+
+ return true;
+ }
+
+ public void AddStore(EntityUid uid,
+ HashSet> currencyWhitelist,
+ HashSet> categories,
+ Dictionary, FixedPoint2> balance,
+ bool allowRefund,
+ bool ownerOnly)
+ {
+ var comp = new StoreComponent();
+ comp.CurrencyWhitelist = currencyWhitelist;
+ comp.Categories = categories;
+ comp.Balance = balance;
+ comp.RefundAllowed = allowRefund;
+ comp.OwnerOnly = ownerOnly;
+
+ AddComp(uid, comp);
+ }
+
+ public bool TrySetCurrency(Dictionary, FixedPoint2> currency, EntityUid uid, StoreComponent? store = null)
+ {
+ if (!Resolve(uid, ref store))
+ return false;
+
+ //verify these before values are modified
+ foreach (var type in currency)
+ {
+ if (!store.CurrencyWhitelist.Contains(type.Key))
+ return false;
+ }
+
+ foreach (var type in currency)
+ {
+ if (!store.Balance.TryAdd(type.Key, type.Value))
+ store.Balance[type.Key] = type.Value;
+ }
+
+ UpdateUserInterface(null, uid, store);
+ return true;
+ }
+
+ public bool TryRefreshStoreStock(EntityUid uid, StoreComponent? store = null)
+ {
+ if (!Resolve(uid, ref store))
+ return false;
+
+ foreach (var item in store.FullListingsCatalog)
+ {
+ item.PurchaseAmount = 0;
+ }
+
+ UpdateUserInterface(null, uid, store);
+ return true;
+ }
+
+ // ADT changeling end
}
public sealed class CurrencyInsertAttemptEvent : CancellableEntityEventArgs
diff --git a/Content.Shared/ADT/Changeling/Components/AbsorbedComponent.cs b/Content.Shared/ADT/Changeling/Components/AbsorbedComponent.cs
new file mode 100644
index 00000000000..f87721db783
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/Components/AbsorbedComponent.cs
@@ -0,0 +1,7 @@
+namespace Content.Shared.Changeling.Components;
+
+[RegisterComponent]
+public sealed partial class AbsorbedComponent : Component // component give to people who have been absorbed by changelings
+{
+
+}
diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs
new file mode 100644
index 00000000000..8712384dcc2
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs
@@ -0,0 +1,330 @@
+using Robust.Shared.Audio;
+using Content.Shared.Polymorph;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Content.Shared.Chemistry.Reagent;
+using Robust.Shared.Prototypes;
+using Content.Shared.Actions;
+using Robust.Shared.GameStates;
+using System.Diagnostics.CodeAnalysis;
+using Content.Shared.DoAfter;
+
+namespace Content.Shared.Changeling.Components;
+
+[RegisterComponent, NetworkedComponent]
+[AutoGenerateComponentState(true)]
+public sealed partial class ChangelingComponent : Component
+{
+ ///
+ /// The amount of chemicals the ling has.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float Chemicals = 20f;
+
+ public float Accumulator = 0f;
+
+ ///
+ /// The amount of chemicals passively generated per second
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float ChemicalsPerSecond = 0.5f;
+
+ ///
+ /// The lings's current max amount of chemicals.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float MaxChemicals = 75f;
+
+ ///
+ /// The maximum amount of DNA strands a ling can have at one time
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public int DNAStrandCap = 7;
+
+ ///
+ /// List of stolen DNA
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public List StoredDNA = new List();
+
+ ///
+ /// The DNA index that the changeling currently has selected
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public int SelectedDNA = 0;
+
+ ///
+ /// Flesh sound
+ ///
+ public SoundSpecifier? SoundFlesh = new SoundPathSpecifier("/Audio/Effects/blobattack.ogg")
+ {
+ Params = AudioParams.Default.WithVolume(-3f),
+ };
+
+ ///
+ /// Flesh sound
+ ///
+ public SoundSpecifier? SoundFleshQuiet = new SoundPathSpecifier("/Audio/Effects/blobattack.ogg")
+ {
+ Params = AudioParams.Default.WithVolume(-1f),
+ };
+
+ public SoundSpecifier? SoundResonant = new SoundPathSpecifier("/Audio/ADT/resonant.ogg")
+ {
+ Params = AudioParams.Default.WithVolume(-3f),
+ };
+
+ ///
+ /// Blind sting duration
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan BlindStingDuration = TimeSpan.FromSeconds(18);
+
+ ///
+ /// Refresh ability
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool CanRefresh = false;
+
+ #region Actions
+ public EntProtoId ChangelingEvolutionMenuAction = "ActionChangelingEvolutionMenu";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingEvolutionMenuActionEntity;
+
+ public EntProtoId ChangelingRegenAction = "ActionLingRegenerate";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingRegenActionEntity;
+
+ public EntProtoId ChangelingAbsorbAction = "ActionChangelingAbsorb";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingAbsorbActionEntity;
+
+ public EntProtoId ChangelingDNACycleAction = "ActionChangelingTransform";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingDNACycleActionEntity;
+
+ public EntProtoId ChangelingDNAStingAction = "ActionLingStingExtract";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingDNAStingActionEntity;
+
+ public EntProtoId ChangelingStasisDeathAction = "ActionStasisDeath";
+
+ [AutoNetworkedField]
+ public EntityUid? ChangelingStasisDeathActionEntity;
+
+ public List BoughtActions = new();
+
+ public List BasicTransferredActions = new();
+ #endregion
+
+ #region Chemical Costs
+ public float ChemicalsCostFree = 0;
+ public float ChemicalsCostFive = -5f;
+ public float ChemicalsCostTen = -10f;
+ public float ChemicalsCostFifteen = -15f;
+ public float ChemicalsCostTwenty = -20f;
+ public float ChemicalsCostTwentyFive = -25f;
+ public float ChemicalsCostFifty = -50f;
+ #endregion
+
+ #region DNA Absorb Ability
+ ///
+ /// How long an absorb stage takes, in seconds.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public int AbsorbDuration = 10;
+
+ ///
+ /// The stage of absorbing that the changeling is on. Maximum of 2 stages.
+ ///
+ public int AbsorbStage = 0;
+
+ ///
+ /// The amount of genetic damage the target gains when they're absorbed.
+ ///
+ public float AbsorbGeneticDmg = 200.0f;
+
+ ///
+ /// The amount of evolution points the changeling gains when they absorb another changeling.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float AbsorbedChangelingPointsAmount = 5.0f;
+
+ ///
+ /// The amount of evolution points the changeling gains when they absorb somebody.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float AbsorbedMobPointsAmount = 2.0f;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float AbsorbedDnaModifier = 0f;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public DoAfterId? DoAfter;
+ #endregion
+
+ #region Regenerate Ability
+ ///
+ /// The amount of burn damage is healed when the regenerate ability is sucesssfully used.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float RegenerateBurnHealAmount = -100f;
+
+ ///
+ /// The amount of brute damage is healed when the regenerate ability is sucesssfully used.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float RegenerateBruteHealAmount = -125f;
+
+ ///
+ /// The amount of blood volume that is gained when the regenerate ability is sucesssfully used.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float RegenerateBloodVolumeHealAmount = 1000f;
+
+ ///
+ /// The amount of bleeding that is reduced when the regenerate ability is sucesssfully used.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float RegenerateBleedReduceAmount = -1000f;
+
+ ///
+ /// Sound that plays when the ling uses the regenerate ability.
+ ///
+ public SoundSpecifier? SoundRegenerate = new SoundPathSpecifier("/Audio/Effects/demon_consume.ogg")
+ {
+ Params = AudioParams.Default.WithVolume(-3f),
+ };
+ #endregion
+
+ #region Armblade Ability
+ ///
+ /// If the ling has an active armblade or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool ArmBladeActive = false;
+
+ [AutoNetworkedField]
+ public EntityUid? BladeEntity;
+
+ #endregion
+
+ #region Armace Ability
+ ///
+ /// If the ling has an active armace or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool ArmaceActive = false;
+
+ [AutoNetworkedField]
+ public EntityUid? ArmaceEntity;
+ #endregion
+
+ #region Chitinous Armor Ability
+ ///
+ /// The amount of chemical regeneration is reduced when the ling armor is active.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float LingArmorRegenCost = 0.125f;
+
+ ///
+ /// If the ling has the armor on or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool LingArmorActive = false;
+ #endregion
+
+ #region Chameleon Skin Ability
+ ///
+ /// If the ling has chameleon skin active or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool ChameleonSkinActive = false;
+
+ ///
+ /// How fast the changeling will turn invisible from standing still when using chameleon skin.
+ ///
+ public float ChameleonSkinPassiveVisibilityRate = -0.15f;
+
+ ///
+ /// How fast the changeling will turn visible from movement when using chameleon skin.
+ ///
+ public float ChameleonSkinMovementVisibilityRate = 0.60f;
+ #endregion
+
+ #region Dissonant Shriek Ability
+ ///
+ /// Range of the Dissonant Shriek's EMP in tiles.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float DissonantShriekEmpRange = 5f;
+
+ ///
+ /// Power consumed from batteries by the Dissonant Shriek's EMP
+ ///
+ public float DissonantShriekEmpConsumption = 50000f;
+
+ ///
+ /// How long the Dissonant Shriek's EMP effects last for
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float DissonantShriekEmpDuration = 12f;
+ #endregion
+
+ #region Stasis Death Ability
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool StasisDeathActive = false; /// Is ling dead or alive
+
+ #endregion
+
+ #region Muscles Ability
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool MusclesActive = false;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float MusclesModifier = 1.4f;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float MusclesStaminaDamage = 3f;
+
+ public TimeSpan NextMusclesDamage = TimeSpan.Zero;
+ #endregion
+
+ #region Lesser Form Ability
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool LesserFormActive = false;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public string LesserFormMob = "ADTChangelingLesserForm";
+
+
+ #endregion
+
+ #region Armshield Ability
+ ///
+ /// If the ling has an active armblade or not.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool ArmShieldActive = false;
+
+ [AutoNetworkedField]
+ public EntityUid? ShieldEntity;
+
+ #endregion
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public int BiodegradeDuration = 3;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool LastResortUsed = false;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool DigitalCamouflageActive = false;
+}
diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingHeadslugComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingHeadslugComponent.cs
new file mode 100644
index 00000000000..8f7d878598b
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/Components/ChangelingHeadslugComponent.cs
@@ -0,0 +1,17 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Changeling.Components;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ChangelingHeadslugComponent : Component
+{
+ public EntityUid? Container;
+
+ public bool IsInside = false;
+
+ public float Accumulator = 0f;
+
+ public float AccumulateTime = 90f;
+
+ public bool Alerted = false;
+}
diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingShieldComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingShieldComponent.cs
new file mode 100644
index 00000000000..b82f0d5cdae
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/Components/ChangelingShieldComponent.cs
@@ -0,0 +1,8 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Changeling.Components;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ChangelingShieldComponent : Component
+{
+}
diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingSlugContainerComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingSlugContainerComponent.cs
new file mode 100644
index 00000000000..bfc48fb3147
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/Components/ChangelingSlugContainerComponent.cs
@@ -0,0 +1,12 @@
+using Robust.Shared.GameStates;
+using Robust.Shared.Containers;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Content.Shared.Changeling.Components;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ChangelingHeadslugContainerComponent : Component
+{
+ [NotNull]
+ public Container? Container;
+}
diff --git a/Content.Shared/ADT/Changeling/SharedChangeling.cs b/Content.Shared/ADT/Changeling/SharedChangeling.cs
new file mode 100644
index 00000000000..37313d5f418
--- /dev/null
+++ b/Content.Shared/ADT/Changeling/SharedChangeling.cs
@@ -0,0 +1,193 @@
+using Content.Shared.Actions;
+using Content.Shared.DoAfter;
+using Content.Shared.Preferences;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Changeling;
+
+public sealed partial class LingAbsorbActionEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class LingStingExtractActionEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class BlindStingEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class MuteStingEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class DrugStingEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class TransformationStingEvent : EntityTargetActionEvent
+{
+}
+
+public sealed partial class LingEggActionEvent : EntityTargetActionEvent
+{
+}
+
+[Serializable, NetSerializable]
+public sealed partial class AbsorbDoAfterEvent : SimpleDoAfterEvent
+{
+}
+
+[Serializable, NetSerializable]
+public sealed partial class LingEggDoAfterEvent : SimpleDoAfterEvent
+{
+}
+
+[Serializable, NetSerializable]
+public sealed partial class BiodegradeDoAfterEvent : SimpleDoAfterEvent
+{
+}
+public sealed partial class ChangelingEvolutionMenuActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ChangelingTransformActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingRegenerateActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ArmBladeActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingArmorActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingInvisibleActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingEMPActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class StasisDeathActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class AdrenalineActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class FleshmendActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ChangelingRefreshActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ChangelingMusclesActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ChangelingLesserFormActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ArmShieldActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ArmaceActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LastResortActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingBiodegradeActionEvent : InstantActionEvent
+{
+}
+
+public sealed partial class LingResonantShriekEvent : InstantActionEvent
+{
+}
+
+public sealed partial class DigitalCamouflageEvent : InstantActionEvent
+{
+}
+
+public sealed partial class ChangelingBoneShardEvent : InstantActionEvent
+{
+}
+
+///
+/// This event carries humanoid information list of entities, which DNA were stolen. Used for radial UI of "The genestealer".
+///
+[Serializable, NetSerializable]
+public sealed partial class RequestChangelingFormsMenuEvent : EntityEventArgs
+{
+ public List HumanoidData = new();
+
+ public NetEntity Target;
+ public ChangelingMenuType Type;
+
+ public RequestChangelingFormsMenuEvent(NetEntity target, ChangelingMenuType type)
+ {
+ Target = target;
+ Type = type;
+ }
+}
+
+[Serializable, NetSerializable]
+public enum ChangelingMenuType : byte
+{
+ Transform,
+ HumanForm,
+ Sting,
+}
+
+[Serializable, NetSerializable]
+public sealed class HDATA(NetEntity netEntity, string name, string species, HumanoidCharacterProfile profile)
+{
+ public NetEntity NetEntity = netEntity;
+ public string Name = name;
+ public string Species = species;
+ public HumanoidCharacterProfile Profile = profile;
+}
+
+
+///
+/// This event carries prototype-id of emote, which was selected. This class is a part of code which is responsible for using RadialUiController.
+///
+[Serializable, NetSerializable]
+public sealed partial class SelectChangelingFormEvent : EntityEventArgs
+{
+ public NetEntity EntitySelected;
+
+ public NetEntity User;
+ public NetEntity Target;
+
+ public bool Handled = false;
+ public ChangelingMenuType Type;
+
+ public SelectChangelingFormEvent(NetEntity user, NetEntity target, NetEntity entitySelected, ChangelingMenuType type)
+ {
+ User = user;
+ Target = target;
+ EntitySelected = entitySelected;
+ Type = type;
+ }
+}
+
+[NetSerializable, Serializable]
+[DataDefinition]
+public sealed partial class ChangelingRefreshEvent : EntityEventArgs
+{
+}
diff --git a/Content.Shared/ADT/Damage/Events/BeforeStaminaCritEvent.cs b/Content.Shared/ADT/Damage/Events/BeforeStaminaCritEvent.cs
new file mode 100644
index 00000000000..a47402483b2
--- /dev/null
+++ b/Content.Shared/ADT/Damage/Events/BeforeStaminaCritEvent.cs
@@ -0,0 +1,4 @@
+namespace Content.Shared.ADT.Damage.Events;
+
+[ByRefEvent]
+public record struct BeforeStaminaCritEvent(bool Cancelled = false);
diff --git a/Content.Shared/ADT/Stealth/Components/DigitalCamouflageComponent.cs b/Content.Shared/ADT/Stealth/Components/DigitalCamouflageComponent.cs
new file mode 100644
index 00000000000..4f9353ea45e
--- /dev/null
+++ b/Content.Shared/ADT/Stealth/Components/DigitalCamouflageComponent.cs
@@ -0,0 +1,13 @@
+using Content.Shared.Stealth;
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Shared.ADT.Stealth.Components;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(SharedStealthSystem))]
+public sealed partial class DigitalCamouflageComponent : Component
+{
+}
diff --git a/Content.Shared/ADT/Stealth/Events/CheckStealthWhitelistEvent.cs b/Content.Shared/ADT/Stealth/Events/CheckStealthWhitelistEvent.cs
new file mode 100644
index 00000000000..2bf3a21983b
--- /dev/null
+++ b/Content.Shared/ADT/Stealth/Events/CheckStealthWhitelistEvent.cs
@@ -0,0 +1,4 @@
+namespace Content.Shared.Stealth;
+
+[ByRefEvent]
+public record struct CheckStealthWhitelistEvent(EntityUid? User, EntityUid StealthEntity, bool Cancelled = false);
diff --git a/Content.Shared/ADT/Stealth/SharedStealthSystem.cs b/Content.Shared/ADT/Stealth/SharedStealthSystem.cs
new file mode 100644
index 00000000000..12e009dc79c
--- /dev/null
+++ b/Content.Shared/ADT/Stealth/SharedStealthSystem.cs
@@ -0,0 +1,47 @@
+using Content.Shared.ADT.Stealth.Components;
+using Content.Shared.Stealth.Components;
+using Content.Shared.Tag;
+
+namespace Content.Shared.Stealth;
+
+public abstract partial class SharedStealthSystem
+{
+ [Dependency] private readonly TagSystem _tag = default!;
+
+ private void InitializeADT()
+ {
+ SubscribeLocalEvent(CheckDigiCamo);
+ }
+
+ private void CheckDigiCamo(EntityUid uid, DigitalCamouflageComponent comp, ref CheckStealthWhitelistEvent args)
+ {
+ if (!args.User.HasValue)
+ return;
+
+ if (!_tag.HasTag(args.User.Value, "ADTSiliconStealthWhitelist"))
+ args.Cancelled = true;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// True, если для отрисовывается шейдер
+ public bool CheckStealthWhitelist(EntityUid? user, EntityUid stealthEnt)
+ {
+ var ev = new CheckStealthWhitelistEvent(user, stealthEnt);
+ RaiseLocalEvent(stealthEnt, ref ev);
+ return !ev.Cancelled;
+ }
+
+ public void SetDesc(EntityUid uid, string desc, StealthComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ component.ExaminedDesc = desc;
+
+ Dirty(uid, component);
+ }
+}
diff --git a/Content.Shared/Actions/ActionContainerSystem.cs b/Content.Shared/Actions/ActionContainerSystem.cs
index 1a83cf38e51..2dc6a43ca72 100644
--- a/Content.Shared/Actions/ActionContainerSystem.cs
+++ b/Content.Shared/Actions/ActionContainerSystem.cs
@@ -237,6 +237,20 @@ public bool AddAction(EntityUid uid, EntityUid actionId, BaseActionComponent? ac
DebugTools.AssertOwner(uid, comp);
comp ??= EnsureComp(uid);
+
+ // ADT-Tweak-Changeling-start
+ if (!TryComp(actionId, out var actionMetaData))
+ return false;
+ if (!TryPrototype(actionId, out var actionPrototype, actionMetaData))
+ return false;
+
+ if (HasAction(uid, actionPrototype.ID))
+ {
+ Log.Debug($"Tried to insert action {ToPrettyString(actionId)} into {ToPrettyString(uid)}. Failed due to duplicate actions.");
+ return false;
+ }
+ // ADT-Tweak-Changeling-end
+
if (!_container.Insert(actionId, comp.Container))
{
Log.Error($"Failed to insert action {ToPrettyString(actionId)} into {ToPrettyString(uid)}");
@@ -250,6 +264,30 @@ public bool AddAction(EntityUid uid, EntityUid actionId, BaseActionComponent? ac
return true;
}
+ // ADT changeling start
+ ///
+ /// Checks if the given entity has an action prototype in their actions container.
+ ///
+ public bool HasAction(EntityUid uid, string prototypeID, ActionsContainerComponent? actionsContainerComp = null)
+ {
+ if (!Resolve(uid, ref actionsContainerComp, false))
+ return false;
+
+ foreach (var act in actionsContainerComp.Container.ContainedEntities.ToArray())
+ {
+ if (TryPrototype(act, out var actPrototype))
+ {
+ if (prototypeID == actPrototype.ID)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ // ADT changeling end
+
///
/// Removes an action from its container and any action-performer and moves the action to null-space
///
diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs
index 1244a603796..a3f5b228344 100644
--- a/Content.Shared/Damage/Systems/StaminaSystem.cs
+++ b/Content.Shared/Damage/Systems/StaminaSystem.cs
@@ -1,5 +1,6 @@
using System.Linq;
using Content.Shared.Administration.Logs;
+using Content.Shared.ADT.Damage.Events; // ADT-Changeling-Tweak
using Content.Shared.Alert;
using Content.Shared.CombatMode;
using Content.Shared.Damage.Components;
@@ -368,6 +369,13 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null)
{
return;
}
+ // ADT staminacrit cancellation event start
+ var ev = new BeforeStaminaCritEvent();
+ RaiseLocalEvent(uid, ref ev);
+
+ if (ev.Cancelled)
+ return;
+ // ADT staminacrit cancellation event end
// To make the difference between a stun and a stamcrit clear
// TODO: Mask?
diff --git a/Content.Shared/Eye/VisibilityFlags.cs b/Content.Shared/Eye/VisibilityFlags.cs
index a616b430bec..a29bee1c285 100644
--- a/Content.Shared/Eye/VisibilityFlags.cs
+++ b/Content.Shared/Eye/VisibilityFlags.cs
@@ -10,5 +10,8 @@ public enum VisibilityFlags : int
Normal = 1 << 0,
Ghost = 1 << 1, // ADT Phantom
PhantomVessel = 2 << 1, // ADT Phantom
+ Narcotic = 1 << 2, // ADT-Changeling-Tweak
+ Schizo = 1 << 3, // ADT-Changeling-Tweak
+ LingToxin = 1 << 4, // ADT-Changeling-Tweak
}
}
diff --git a/Content.Shared/Mind/MindComponent.cs b/Content.Shared/Mind/MindComponent.cs
index 010a8a5d7d4..e45c4bd1f2c 100644
--- a/Content.Shared/Mind/MindComponent.cs
+++ b/Content.Shared/Mind/MindComponent.cs
@@ -124,4 +124,9 @@ public void AddMemory(Memory memory)
[ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))]
// TODO remove this after moving IPlayerManager functions to shared
public ICommonSession? Session { get; set; }
+
+ // ADT
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("preventGhostingSendMessage")]
+ public bool PreventGhostingSendMessage = true;
}
diff --git a/Content.Shared/Polymorph/PolymorphPrototype.cs b/Content.Shared/Polymorph/PolymorphPrototype.cs
index 6d010711d2e..b1392924c01 100644
--- a/Content.Shared/Polymorph/PolymorphPrototype.cs
+++ b/Content.Shared/Polymorph/PolymorphPrototype.cs
@@ -1,5 +1,6 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
+using Content.Shared.Humanoid; // ADT-Changeling-Tweak
namespace Content.Shared.Polymorph;
@@ -123,3 +124,13 @@ public enum PolymorphInventoryChange : byte
Drop,
Transfer,
}
+// ADT-Changeling-Tweak-Start
+public struct PolymorphHumanoidData
+{
+ public EntityPrototype EntityPrototype;
+ public MetaDataComponent MetaDataComponent;
+ public HumanoidAppearanceComponent HumanoidAppearanceComponent;
+ public string DNA;
+ public EntityUid EntityUid;
+}
+// ADT-Changeling-Tweak-End
diff --git a/Content.Shared/Stealth/Components/StealthComponent.cs b/Content.Shared/Stealth/Components/StealthComponent.cs
index 0e32e90ba16..fd05af98142 100644
--- a/Content.Shared/Stealth/Components/StealthComponent.cs
+++ b/Content.Shared/Stealth/Components/StealthComponent.cs
@@ -80,11 +80,13 @@ public sealed class StealthComponentState : ComponentState
public readonly float Visibility;
public readonly TimeSpan? LastUpdated;
public readonly bool Enabled;
+ public string Desc; // ADT tweak
- public StealthComponentState(float stealthLevel, TimeSpan? lastUpdated, bool enabled)
+ public StealthComponentState(float stealthLevel, TimeSpan? lastUpdated, bool enabled, string desc) // ADT tweak
{
Visibility = stealthLevel;
LastUpdated = lastUpdated;
Enabled = enabled;
+ Desc = desc; // ADT tweak
}
}
diff --git a/Content.Shared/Stealth/SharedStealthSystem.cs b/Content.Shared/Stealth/SharedStealthSystem.cs
index 1bab55589fd..335ea6c9573 100644
--- a/Content.Shared/Stealth/SharedStealthSystem.cs
+++ b/Content.Shared/Stealth/SharedStealthSystem.cs
@@ -1,13 +1,12 @@
using Content.Shared.Examine;
using Content.Shared.Mobs;
-using Content.Shared.Mobs.Systems;
using Content.Shared.Stealth.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Timing;
namespace Content.Shared.Stealth;
-public abstract class SharedStealthSystem : EntitySystem
+public abstract partial class SharedStealthSystem : EntitySystem // ADT partial
{
[Dependency] private readonly IGameTiming _timing = default!;
@@ -25,11 +24,13 @@ public override void Initialize()
SubscribeLocalEvent(OnExamineAttempt);
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnMobStateChanged);
+
+ InitializeADT(); // ADT
}
private void OnExamineAttempt(EntityUid uid, StealthComponent component, ExamineAttemptEvent args)
{
- if (!component.Enabled || GetVisibility(uid, component) > component.ExamineThreshold)
+ if (!component.Enabled || GetVisibility(uid, component) > component.ExamineThreshold || !CheckStealthWhitelist(args.Examiner, uid)) // ADT tweaked
return;
// Don't block examine for owner or children of the cloaked entity.
@@ -98,7 +99,7 @@ protected virtual void OnInit(EntityUid uid, StealthComponent component, Compone
private void OnStealthGetState(EntityUid uid, StealthComponent component, ref ComponentGetState args)
{
- args.State = new StealthComponentState(component.LastVisibility, component.LastUpdated, component.Enabled);
+ args.State = new StealthComponentState(component.LastVisibility, component.LastUpdated, component.Enabled, component.ExaminedDesc); // ADT tweaked
}
private void OnStealthHandleState(EntityUid uid, StealthComponent component, ref ComponentHandleState args)
@@ -109,6 +110,7 @@ private void OnStealthHandleState(EntityUid uid, StealthComponent component, ref
SetEnabled(uid, cast.Enabled, component);
component.LastVisibility = cast.Visibility;
component.LastUpdated = cast.LastUpdated;
+ component.ExaminedDesc = cast.Desc; // ADT tweaked
}
private void OnMove(EntityUid uid, StealthOnMoveComponent component, ref MoveEvent args)
diff --git a/Content.Shared/Store/ListingPrototype.cs b/Content.Shared/Store/ListingPrototype.cs
index 4e00f3f47db..227006c50dd 100644
--- a/Content.Shared/Store/ListingPrototype.cs
+++ b/Content.Shared/Store/ListingPrototype.cs
@@ -164,6 +164,9 @@ public ListingData(
[DataField]
public EntProtoId? ProductAction;
+ [DataField("mindAction")] // ADT-Changeling-Tweak
+ public bool MindAction = true;
+
///
/// The listing ID of the related upgrade listing. Can be used to link a to an
/// upgrade or to use standalone as an upgrade
@@ -443,4 +446,4 @@ public sealed partial class DiscountCategoryPrototype : IPrototype
///
[DataField]
public int? MaxItems { get; private set; }
-}
\ No newline at end of file
+}
diff --git a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs
index 82ffc5e51fc..87a4434d91c 100644
--- a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs
+++ b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs
@@ -1,4 +1,5 @@
using System.Numerics;
+using Content.Shared.Damage;
using Robust.Shared.GameStates;
using Robust.Shared.Physics.Components;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
@@ -47,6 +48,17 @@ public sealed partial class MeleeThrowOnHitComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public bool Enabled = true;
+
+ // ADT tweak start
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public DamageSpecifier? CollideDamage;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public DamageSpecifier? ToCollideDamage;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool DownOnHit = false;
+ // ADT tweak end
}
///
@@ -96,6 +108,14 @@ public sealed partial class MeleeThrownComponent : Component
///
[DataField]
public BodyStatus PreviousStatus;
+
+ // ADT tweak start
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public DamageSpecifier? CollideDamage;
+
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public DamageSpecifier? ToCollideDamage;
+ // ADT tweak end
}
///
diff --git a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs
index 78863562330..de68bdd4a13 100644
--- a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs
+++ b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs
@@ -1,5 +1,7 @@
using System.Numerics;
using Content.Shared.Construction.Components;
+using Content.Shared.Damage;
+using Content.Shared.Standing;
using Content.Shared.Weapons.Melee.Components;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Physics;
@@ -18,6 +20,8 @@ public sealed class MeleeThrowOnHitSystem : EntitySystem
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
+ [Dependency] private readonly StandingStateSystem _standing = default!; // ADT-Changeling-Tweak
+ [Dependency] private readonly DamageableSystem _damage = default!; // ADT-Changeling-Tweak
///
public override void Initialize()
@@ -57,9 +61,14 @@ private void OnMeleeHit(Entity ent, ref MeleeHitEvent
{
Velocity = angle.Normalized() * comp.Speed,
Lifetime = comp.Lifetime,
- MinLifetime = comp.MinLifetime
+ MinLifetime = comp.MinLifetime,
+ CollideDamage = comp.CollideDamage, // ADT tweak
+ ToCollideDamage = comp.ToCollideDamage // ADT tweak
};
AddComp(hit, thrownComp);
+
+ if (comp.DownOnHit) // ADT tweak
+ _standing.Down(hit);
}
}
@@ -97,6 +106,11 @@ private void OnStartCollide(Entity ent, ref StartCollideEv
if (_timing.CurTime < comp.MinLifetimeTime)
return;
+ if (ent.Comp.CollideDamage != null) // ADT tweak
+ _damage.TryChangeDamage(ent.Owner, ent.Comp.CollideDamage);
+ if (ent.Comp.ToCollideDamage != null) // ADT tweak
+ _damage.TryChangeDamage(args.OtherEntity, ent.Comp.ToCollideDamage);
+
RemCompDeferred(ent, ent.Comp);
}
diff --git a/Resources/Audio/Ambience/Antag/changeling_start.ogg b/Resources/Audio/Ambience/Antag/changeling_start.ogg
new file mode 100644
index 00000000000..1132ccca29c
Binary files /dev/null and b/Resources/Audio/Ambience/Antag/changeling_start.ogg differ
diff --git a/Resources/Audio/Effects/blobattack.ogg b/Resources/Audio/Effects/blobattack.ogg
new file mode 100644
index 00000000000..c9fcfbee448
Binary files /dev/null and b/Resources/Audio/Effects/blobattack.ogg differ
diff --git a/Resources/Locale/ru-RU/ADT/changeling/action_changeling.ftl b/Resources/Locale/ru-RU/ADT/changeling/action_changeling.ftl
new file mode 100644
index 00000000000..4e9ac9fa7d7
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/action_changeling.ftl
@@ -0,0 +1,86 @@
+action-evolution-menu = Меню эволюции
+action-evolution-menu-decs = Открывает меню эволюции, в котором можно улучшить свои показатели для адаптации к внешней среде.
+
+action-absorb-dna = Поглотить оболочку цели
+action-absorb-dna-desc = Поглощает цель и её ДНК. [color=red]Она должна быть в критическом или мёртвом состоянии и обязательно гуманоидом[/color], чтобы можно было забрать образцы ДНК.
+
+action-cycle-dna = Выбор ДНК поглощённых
+action-cycle-dna-desc = Выбирает ДНК поглощённого для трансформации.
+
+action-transform = Трансформация
+action-transform-desc = Трансформирует вас в выбранную цепочку ДНК. [color=#db03fc]Использует 5 химикатов.[/color]
+
+action-regenerate = Регенерация
+action-regenerate-desc = Позволяет быстро регенерировать, заживляя серьезные раны и восстанавливая объем крови. [color=#db03fc]Использует 10 химикатов[/color] и может быть использовано [color=red]только в критическом состоянии.[/color]
+
+action-extract-dna-sting = Скрытый сбор ДНК
+action-extract-dna-sting-desc = Забирает пробу ДНК цели. Не информирует цель о том, что её ужалили. [color=#db03fc]Использует 25 химикатов.[/color]
+
+action-toggle-arm-blade = Переключить руку-клинок
+action-toggle-arm-blade-desc = Превращает одну из ваших свободных рук в причудливый клинок, сделанный из костей и плоти. Также позволяет вскрывать двери как ломом. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-toggle-chitinous-armor = Переключить хитиновую броню
+action-toggle-chitinous-armor-desc = Превращает ваше тело во всепоглощающую хитиновую броню. [color=#db03fc]Использует 20 химикатов[/color] и [color=red]замедляет химическую регенерацию на 25% в активном состоянии.[/color]
+
+action-toggle-chameleon-skin = Переключить маскировку
+action-toggle-chameleon-skin-desc = Пигментация вашей кожи быстро меняется в соответствии с окружающей средой, делая вас невидимым после нескольких секунд неподвижного стояния. [color=#db03fc]Использует 25 химикатов.[/color]
+
+action-activate-dissonant-shriek = Активируйте диссонирующий рёв
+action-activate-dissonant-shriek-desc = Вы напрягаете голосовые связки, чтобы издать высокочастотный звук, который перегружает близлежащую электронику. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-stasis-death = Регенеративный стазис
+action-stasis-death-desc = Войдите в стазис, подобный смерти для дальнейшей [color=green]полной[/color] регенерации. Можно использовать даже в мёртвом состоянии. [color=#db03fc]Использует 25 химикатов.[/color]
+
+action-refresh-ling = Очистить ДНК
+action-refresh-ling-desc = Очистите собранные цепочки ДНК, получив взамен [color=#db03fc]2 очка эволюции[/color].
+
+action-adrenaline = Выброс адреналина
+action-adrenaline-desc = Ваше тело моментально вырабатывает химикаты, отключающие болевые рецепторы и останавливающие кровотечение. [color=#db03fc]Использует 10 химикатов.[/color]
+
+action-blind-sting = Жало ослепления
+action-blind-sting-desc = Ужальте кого-либо скрытым жалом и ослепите его на 18 секунд. [color=#db03fc]Использует 15 химикатов.[/color]
+
+action-mute-sting = Жало безмолвия
+action-mute-sting-desc = Ужальте кого-либо скрытым жалом и временно лишите его возможности говорить. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-drug-sting = Галлюценогенное жало
+action-drug-sting-desc = Введите кому-либо большое количество нетоксичного, но крайне мощного галлюценогена. Цель ни о чём не догадается, пока вокруг неё не начнёт происходить хаос. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-fleshmend = Исцеление плоти
+action-fleshmend-desc = Ваше тело моментально заживляет многие раны и ожоги. [color=#db03fc]Использует 25 химикатов.[/color]
+
+action-lingmuscles = Напряжённые мышцы
+action-lingmuscles-desc = Ваши мышцы ног начинают сокращаться, позволяя вам бегать с крайне высокой скоростью. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-lesser-form = Низшая форма
+action-lesser-form-desc = Превратитесь в обезьяну, либо из обезьяны в выбранную форму. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-toggle-arm-shield = Переключить органический щит
+action-toggle-arm-shield-desc = Превращает одну из ваших свободных рук в щит, сделанный из костей и плоти. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-resort = Последний шанс
+action-resort-desc = Разорвите собственное тело и высвободите свою настоящую форму для последующей кладки личинок в новое тело.
+
+action-eggs = Отложить яйца
+action-eggs-desc = Отложите яйца в бездыханный труп для продолжения рода улья.
+
+action-hatch = Вылупиться
+action-hatch-desc = Разорвите оболочку и вернитесь в облике нового генокрада.
+
+action-biodegrade = Плевок кислотой
+action-biodegrade-desc = Синтезируйте крайне едкую кислоту и уничтожьте ей надетые на вас наручники. [color=#db03fc]Использует 15 химикатов.[/color]
+
+action-resonant = Резонантный рёв
+action-resonant-desc = Дезориентируйте окружающих вас не-генокрадов с помощью высокочастотного звука. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-transform-sting = Жало трансформации
+action-transform-sting-desc = Заставьте выбранную цель превратиться в того, кого в данный момент вы выбрали. [color=#db03fc]Использует 50 химикатов.[/color]
+
+action-toggle-arm-hammer = Рука-молот
+action-toggle-arm-hammer-desc = Превращает одну из ваших рук в громадный молот из плоти. [color=#db03fc]Использует 25 химикатов.[/color]
+
+action-digi-camo = Цифровой камуфляж
+action-digi-camo-desc = Начните двигаться особым образом, предотвращая ваше обнаружение позитронными сенсорами. [color=#db03fc]Использует 20 химикатов.[/color]
+
+action-bone-shard = Костяной сюрикен
+action-bone-shard-desc = Создайте из своих костей сюрикен. [color=#db03fc]Использует 15 химикатов,[/color] [color=crimson]наносит 20 единиц урона.[/color]
diff --git a/Resources/Locale/ru-RU/ADT/changeling/alerts.ftl b/Resources/Locale/ru-RU/ADT/changeling/alerts.ftl
new file mode 100644
index 00000000000..93a5b7adf1f
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/alerts.ftl
@@ -0,0 +1,2 @@
+alerts-changeling-chemicals-name = Химические вещества
+alerts-changeling-chemicals-desc = Количество химических веществ в вашем теле. Они используются для способностей. Восстанавливаются через время.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/ADT/changeling/animals.ftl b/Resources/Locale/ru-RU/ADT/changeling/animals.ftl
new file mode 100644
index 00000000000..dcc24ee40e7
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/animals.ftl
@@ -0,0 +1,4 @@
+ent-ADTMobMonkeyChangeling = обезьяна
+ .desc = Новая церковь неодарвинистов действительно верит, что КАЖДОЕ животное произошло от обезьяны. На вкус они как свинина, а убивать их весело и приятно.
+ent-ADTChangelingHeadslug = червь генокрада
+ .desc = Отвратительное нечто, оставшееся от генокрада. Почему вы просто стоите и смотрите?! Убейте это, пока не поздно!
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/ADT/changeling/antags.ftl b/Resources/Locale/ru-RU/ADT/changeling/antags.ftl
new file mode 100644
index 00000000000..886f25dc8b4
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/antags.ftl
@@ -0,0 +1,6 @@
+roles-antag-changeling-name = Генокрад
+roles-antag-changeling-objective = Используйте свои особые инопланетные способности, чтобы помочь в достижении ваших целей.
+
+admin-verb-make-changeling = Сделать цель генокрадом.
+
+admin-verb-text-make-changeling = Сделать генокрадом
diff --git a/Resources/Locale/ru-RU/ADT/changeling/currency.ftl b/Resources/Locale/ru-RU/ADT/changeling/currency.ftl
new file mode 100644
index 00000000000..2fb32475a43
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/currency.ftl
@@ -0,0 +1 @@
+store-currency-display-evolution-points = Очки Эволюции
diff --git a/Resources/Locale/ru-RU/ADT/changeling/objectives.ftl b/Resources/Locale/ru-RU/ADT/changeling/objectives.ftl
new file mode 100644
index 00000000000..d5297d6e5c2
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/objectives.ftl
@@ -0,0 +1,15 @@
+ent-EscapeLingShuttleObjective = Доберитесь до Центкома живым и свободным.
+ .desc = Мы должны пройти через станцию Центрального Командования.
+
+absorb-dna-name = Поглотите { $count } штамма ДНК.
+absorb-dna-desc = Нам нужно { $count } полностью поглощённых ДНК для дальнейшей эволюции.
+
+ling-kill-desc = Мы должны убить их.
+objective-condition-steal-personality-title = Украдите личность { $targetName }, в должности { CAPITALIZE($job) }.
+objective-condition-steal-head-personality-title = Украдите личность { $targetName }, в должности { CAPITALIZE($job) }. Цель НЕ ДОЛЖНА пережить смену.
+ling-steal-personality-desc = Нам нужно это тело.
+
+objective-condition-changeling-commandidcard = Украдите любую ID карту командования, кроме карты капитана.
+objective-condition-changeling-smileextract = Вы должны украсть экстракт Смайла. Он содержит соединение, которое будет очень полезно для улья.
+
+changeling-issuer = Генокрад
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/ADT/changeling/objects.ftl b/Resources/Locale/ru-RU/ADT/changeling/objects.ftl
new file mode 100644
index 00000000000..96a5dff7457
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/objects.ftl
@@ -0,0 +1,11 @@
+ent-ADTArmBlade = рука-клинок
+ .desc = Гротескный клинок из костей и плоти, который рассекает людей, как горячий нож масло.
+ent-ADTArmShield = органический щит
+ .desc = Крупное месиво из плоти, формирующее собой нечто наподобие щита, что достаточно эффективно блокирует некоторые виды урона.
+ent-ADTArmace = рука-молот
+ .desc = Громадный костяной молот, обволакиваемый плотью. Крайне увесистый, и очень хорошо пробивает стены.
+ent-ADTThrowingStarChangeling = костяной сюрикен
+ .desc = Комок из плоти и острых выпирающих костей в форме сюрикена. Тем не менее, он выглядит так, словно в любой момент может рассыпаться в прах.
+
+changeling-headslug-inside = [color=white]Внутри тела двигается что-то живое...[/color]
+changeling-headslug-inside-soon = [color=crimson]Что-то пытается выбраться из тела![/color]
diff --git a/Resources/Locale/ru-RU/ADT/changeling/preset-changeling.ftl b/Resources/Locale/ru-RU/ADT/changeling/preset-changeling.ftl
new file mode 100644
index 00000000000..c9a7b4865b1
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/preset-changeling.ftl
@@ -0,0 +1,93 @@
+## CHANGELINGS
+
+adt-rotting-ling-eggs = [color=#ffd6d6]Внутри тела видны странные личинки...[/color]
+ling-round-end-name = генокрад
+objective-issuer-changeling = [color=red]Разум улья[/color]
+changelings-title = Генокрады
+changelings-description = дурацкие воришки ДНК
+changelings-not-enough-ready-players = Недостаточно игроков нажали "Готов"! Всего было {$readyPlayersCount} готовых игроков из {$minimumPlayers} нужных. Режим "Генокрады" не запустится.
+changelings-no-one-ready = Никто не нажал "Готов"! Режим "Генокрады" начать нельзя.
+# Ling role
+changeling-role-greeting =
+ Вы являетесь Генокрадом, впитавшим форму {$character-name} и превратившимся в него.
+ Ваши цели перечислены в специальном меню, используйте ваши способности, чтобы выполнить их.
+changeling-role-greeting-short =
+ Вы являетесь Генокрадом, впитавшим форму
+ {$character-name} и превратившимся в него.
+ Используйте ваши способности, чтобы выполнить цели.
+# Ling abilities
+changeling-not-enough-chemicals = Недостаточно химических веществ!
+changeling-armblade-fail = Вам нужна свободная рука!
+changeling-armblade-success-others = Вокруг руки {THE($user)} образуется причудливое лезвие!
+changeling-armblade-success-self = Ваша рука изгибается и мутирует, превращаясь в смертоносный клинок.
+changeling-armblade-retract-others = Клинок {CAPITALIZE(THE($target))} впитывается обратно в руку!
+changeling-armblade-retract-self = Вы впитываете клинок обратно в свою руку.
+changeling-armor-success-others = Тело {CAPITALIZE(THE($target))} набирает бронированную защитную массу!
+changeling-armor-success-self = Ваше тело набирает защитную массу.
+changeling-armor-retract-others = Броня {CAPITALIZE(THE($target))} отслаивается.
+changeling-armor-retract-self = Ваша броня отслаивается.
+changeling-regenerate-others-success = {CAPITALIZE(THE($user))} быстро излечивает все раны, издавая громкий, странный звук!
+changeling-regenerate-self-success = Вы чувствуете зуд, как внутри, так и снаружи, когда ваши ткани восстанавливаются снова и снова!
+changeling-regenerate-fail-not-crit = Вы не в критическом состоянии!
+changeling-regenerate-fail-dead = Вы мертвы!
+changeling-chameleon-toggle-on = Ваша кожа переливается прозрачной оболочкой...
+changeling-chameleon-toggle-off = Ваша кожа возвращается к нормальному виду.
+changeling-dna-stage-1 = Это существо подходит для взятия ДНК. Вы должны стоять неподвижно...
+changeling-dna-stage-2-self = Вы вытягиваете жало.
+changeling-dna-stage-2-others = {CAPITALIZE(THE($user))} вытягивает жало!
+changeling-dna-stage-3-self = Вы укалываете {THE($target)} своим жалом!
+changeling-dna-stage-3-others = {CAPITALIZE(THE($user))} укалывает {THE($target)} жалом!
+changeling-dna-success = Вы впитали ДНК {THE($target)}.
+changeling-dna-success-ling = Вы впитали ДНК {THE($target)}. Это был другой генокрад! Вы набрали 5 очков эволюции.
+changeling-dna-fail-nohuman = {CAPITALIZE(THE($target))} не гуманоид.
+changeling-dna-fail-notdead = {CAPITALIZE(THE($target))} не критическом состоянии или мёртв.
+changeling-dna-interrupted = Поглощение ДНК {THE($target)} было прервано.
+changeling-dna-alreadyabsorbed = ДНК {CAPITALIZE(THE($target))} уже собраны!
+changeling-dna-nodna = {CAPITALIZE(THE($target))} не имеет ДНК!
+changeling-dna-switchdna = Переключился на ДНК {$target}.
+changeling-transform-activate = Вы превратились в {$target}.
+changeling-transform-fail-already = Вы уже превратились в {$target}!
+changeling-transform-fail-mutation = Ваше тело слишком искажено для превращения!
+changeling-sting-fail-self = Ужалить {THE($target)} не вышло!
+changeling-sting-fail-target = Вы чувствуёте лёгкое покалывание.
+changeling-dna-sting = Вы забираете образец ДНК {THE($target)}.
+changeling-dna-sting-fail-nodna = {CAPITALIZE(THE($target))} не имеет ДНК!
+changeling-dna-sting-fail-alreadydna = У вас уже есть ДНК {THE($target)}!
+changeling-stasis-death-self-success = Вы впадаете в стазис.
+changeling-stasis-death-self-revive = Вы восстаёте из мёртвых!
+changeling-refresh-not-ready = Сначала поглотите существо.
+changeling-adrenaline-self-success = Боль начинает уходить.
+changeling-refresh-self-success = Успешно очищена цепочка ДНК.
+changeling-omnizine-self-success = Ваша плоть начинает восстанавливаться.
+changeling-success-sting = Вы успешно ужалили {CAPITALIZE(THE($target))}!
+changeling-dna-sting-fail-full = Вы не сможете собрать ещё одну цепочку ДНК!
+changeling-lingmuscles = Ваши мышцы быстро меняются!
+changeling-lesser-form-activate-monkey = Вы превратились в обезьяну!
+changeling-transform-fail-lesser-form = Вы не можете использовать данную способность в этой форме!
+changeling-armshield-fail = Нужна свободная рука!
+changeling-armshield-success-others = Вокруг руки {THE($user)} образуется массивный щит!
+changeling-armshield-success-self = Ваша рука изгибается и мутирует, превращаясь в огромный массивный щит.
+changeling-armshield-retract-others = Щит {CAPITALIZE(THE($target))} впитывается обратно в руку!
+changeling-armshield-retract-self = Вы впитываете щит обратно в свою руку.
+changeling-armshield-broke-others = Щит {CAPITALIZE(THE($user))} разорвался и впитался обратно!
+changeling-armshield-broke-self = Ваш щит был пробит!
+changeling-eggs-self-start = Вы начинаете откладывать личинки в {CAPITALIZE(THE($target))}.
+changeling-eggs-self-success = Вы успешно оставили кладку в {CAPITALIZE(THE($target))}.
+changeling-eggs-interrupted = Кладка была прервана!
+changeling-egg-others = Личинки в теле {THE($user)} начинают активно шевелиться и разрастаться!
+changeling-egg-self = Личинки прорастают, готовясь вырваться наружу.
+changeling-biodegrade-start = Вы начинаете расплавлять наручники.
+changeling-biodegrade-interrupted = Освобождение было прервано!
+changeling-biodegrade-fail-nocuffs = На вас нет наручников.
+changeling-transform-fail-nodna = У вас нет сохранённых ДНК!
+changeling-armace-success-others = Кости и плоть руки {THE($user)} преобразуются в огромный молот!
+changeling-armace-success-self = Ваша рука изгибается и мутирует, превращаясь в огромный молот.
+changeling-armace-retract-others = Молот {CAPITALIZE(THE($target))} впитывается обратно в руку!
+changeling-armace-retract-self = Вы впитываете молот обратно в свою руку.
+defibrillator-changeling-slug = Внутри тела обнаружен паразит.
+changeling-slug-almost-ready = Скоро вы выберетесь наружу.
+changeling-digital-camo-toggle-on = Вы скрываетесь от камер.
+changeling-digital-camo-toggle-off = Вы снова двигаетесь нормально.
+changeling-digital-camo-desc = [color=white]{CAPITALIZE($user)} двигается неестественными рывками.[/color]
+changeling-digi-camo-fail-chameleon = Сначала выключите хамелеон.
+changeling-chameleon-fail-digi-camo = Сначала выключите цифровой камуфляж.
diff --git a/Resources/Locale/ru-RU/ADT/changeling/store_changeling.ftl b/Resources/Locale/ru-RU/ADT/changeling/store_changeling.ftl
new file mode 100644
index 00000000000..cc3220c83a8
--- /dev/null
+++ b/Resources/Locale/ru-RU/ADT/changeling/store_changeling.ftl
@@ -0,0 +1,59 @@
+listing-arm-blade = Рука-клинок
+listing-arm-blade-desc = Превращает одну из ваших рук в клинок, сделанный из кости и плоти. Клинок наносит 40 повреждений за удар, позволяет с легкостью отрубать конечности.
+
+listing-chitinous-armor = Хитиновая броня
+listing-chitinous-armor-desc = Наращивает на вашем теле массивный хитиновый покров, хорошо защищающий от физических повреждений. Немного замедляет регенерацию химикатов, пока активна.
+
+listing-chameleon-skin = Хамелеон
+listing-chameleon-skin-desc = Измените пигментацию своей кожи для маскировки и слияния с окружением. Маскировка быстро спадает при движении.
+
+listing-dissonant-shriek = Диссонирующий рёв
+listing-dissonant-shriek-desc = Позволяет вам издать высокочастотный рёв, перегружающий ближающую электронику.
+
+listing-blind-sting = Жало ослепления
+listing-blind-sting-desc = Полностью ослепляет цель на непродолжительный срок.
+
+listing-adrenaline = Выброс адреналина
+listing-adrenaline-desc = Временно отключить болевые рецепторы для более быстрого передвижения с травмами.
+
+listing-fleshmend = Исцеление плоти
+listing-fleshmend-desc = Ваше тело моментально заживляет многие раны и ожоги.
+
+listing-mute-sting = Жало безмолвия
+listing-mute-sting-desc = Лишает цель возможности говорить на некоторое время.
+
+listing-strained-muscles = Напряжённые мышцы
+listing-strained-muscles-desc = Ваши мышцы ног начинают сокращаться, позволяя вам бегать с крайне высокой скоростью. Пока активно, тратит вашу выносливость, и в итоге может привести к перенагрузке. Пока активно, вас невозможно сбить с ног.
+
+listing-lesser-form = Низшая форма
+listing-lesser-form-desc = Превратитесь в обезьяну. В форме обезьяны вы свободно можете использовать только жала. Вы сможете вернуться в форму гуманоида по желанию.
+
+listing-drug-sting = Галлюценогенное жало
+listing-drug-sting-desc = Вводит цели большое количество галлюценогена. Цель ни о чём не догадается, пока вокруг неё не начнёт происходить хаос.
+
+listing-arm-shield = Органический щит
+listing-arm-shield-desc = Превращает одну из ваших свободных рук в массивный щит, сделанный из плоти. Каждое поглощение усиливает его.
+
+listing-last-resort = Последний шанс
+listing-last-resort-desc = Разорвите собственное тело и высвободите свою настоящую форму для последующей кладки личинок в новое тело. Данную способность можно использовать лишь единожды.
+
+listing-biodegrade = Плевок кислотой
+listing-biodegrade-desc = Уничтожьте надетые на вас наручники. Окружающие могут заметить использование этой способности.
+
+listing-resonant-shriek = Резонантный рёв
+listing-resonant-shriek-desc = Дезориентируйте окружающих вас не-генокрадов с помощью высокочастотного звука.
+
+listing-transform-sting = Жало трансформации
+listing-transform-sting-desc = Заставьте цель принять выбранную вами форму.
+
+listing-arm-mace = Рука-молот
+listing-arm-mace-desc = Превращает одну из ваших рук в громадный молот из плоти. Молот наносит большое количество структурного урона, а так же откидывает цели.
+
+listing-digi-camo = Цифровой камуфляж
+listing-digi-camo-desc = Начните двигаться особым образом, предотвращая ваше обнаружение позитронными сенсорами. В этот список входят ИИ станции, киборги и КПБ. Тем не менее, ваши странные движения могут вызвать вопросы у экипажа.
+
+listing-bone-shard = Костяной сюрикен
+listing-bone-shard-desc = Создайте из своих костей острый сюрикен, что просуществует 30 секунд. Этим вы нанесёте себе небольшой урон.
+
+changeling-refresh = Сброс ДНК
+changeling-refresh-desc = Сбросьте все свои способности для выбора новых.
diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Objectives/steal-target-groups.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Objectives/steal-target-groups.ftl
index d46aa9a73ed..bf7a09305c3 100644
--- a/Resources/Locale/ru-RU/ADT/prototypes/Objectives/steal-target-groups.ftl
+++ b/Resources/Locale/ru-RU/ADT/prototypes/Objectives/steal-target-groups.ftl
@@ -1,2 +1,4 @@
steal-target-groups-clothing-mask-gas-ce = противогаз старшего инженера
steal-target-groups-adt-mobile-defibrillator = мобильный дефибриллятор
+steal-target-groups-command-id = ID карта члена командования
+steal-target-groups-smile-extract = экстракт Смайла
diff --git a/Resources/Locale/ru-RU/store/currency.ftl b/Resources/Locale/ru-RU/store/currency.ftl
index 339201d06d1..62ad9412cae 100644
--- a/Resources/Locale/ru-RU/store/currency.ftl
+++ b/Resources/Locale/ru-RU/store/currency.ftl
@@ -12,6 +12,4 @@ store-currency-display-telecrystal = ТК
store-currency-display-stolen-essence = Украденная эссенция
store-currency-display-wizcoin = Маг₭øин™
-store-currency-display-evolution-points = Очки Эволюции
-
store-currency-display-tradeunit = ЕТ
diff --git a/Resources/Maps/Ruins/corvax_sanctus.yml b/Resources/Maps/Ruins/corvax_sanctus.yml
deleted file mode 100644
index c41f87c0608..00000000000
--- a/Resources/Maps/Ruins/corvax_sanctus.yml
+++ /dev/null
@@ -1,1739 +0,0 @@
-meta:
- format: 6
- postmapinit: false
-tilemap:
- 0: Space
- 12: FloorAstroGrass
- 3: FloorBrassFilled
- 1: FloorCave
- 2: FloorElevatorShaft
- 4: FloorHullReinforced
- 136: FloorWoodLargeLight
- 138: FloorWoodLight
- 139: FloorWoodParquet
- 146: Lattice
- 147: Plating
-entities:
-- proto: ""
- entities:
- - uid: 2
- components:
- - type: MetaData
- name: ""
- - type: Transform
- pos: 0.390625,-0.390625
- parent: invalid
- - type: MapGrid
- chunks:
- 0,0:
- ind: 0,0
- tiles: AQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- version: 6
- 0,-1:
- ind: 0,-1
- tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAkwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAwAAAAAAAQAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- version: 6
- -1,0:
- ind: -1,0
- tiles: AAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- version: 6
- -1,-1:
- ind: -1,-1
- tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAAgAAAAAAAgAAAAAAAwAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAkwAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAkwAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAQAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAwAAAAAAAgAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAQAAAAAAAwAAAAAAAgAAAAAABAAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAQAAAAAAAgAAAAAAAgAAAAAAAQAAAAAAAgAAAAAAAQAAAAAAAQAAAAAAAwAAAAAAAgAAAAAAAQAAAAAA
- version: 6
- -2,-1:
- ind: -2,-1
- tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- version: 6
- - type: Broadphase
- - type: Physics
- bodyStatus: InAir
- angularDamping: 0.05
- linearDamping: 0.05
- fixedRotation: False
- bodyType: Dynamic
- - type: Fixtures
- fixtures: {}
- - type: OccluderTree
- - type: SpreaderGrid
- - type: Shuttle
- - type: GridPathfinding
- - type: Gravity
- gravityShakeSound: !type:SoundPathSpecifier
- path: /Audio/Effects/alert.ogg
- - type: DecalGrid
- chunkCollection:
- version: 2
- nodes:
- - node:
- color: '#FFFFFFFF'
- id: Basalt1
- decals:
- 54: -14,-2
- 103: -7,-13
- - node:
- color: '#FFFFFFFF'
- id: Basalt2
- decals:
- 56: -12,3
- 105: -11,-10
- - node:
- color: '#FFFFFFFF'
- id: Basalt3
- decals:
- 63: 1,-1
- 107: -13,-4
- - node:
- color: '#FFFFFFFF'
- id: Basalt5
- decals:
- 57: -4,5
- 58: 6,-8
- 59: 1,-13
- 60: -9,-6
- - node:
- color: '#FFFFFFFF'
- id: Basalt7
- decals:
- 53: -15,-6
- 61: -10,-5
- 64: 2,-3
- 106: -15,-9
- - node:
- color: '#FFFFFFFF'
- id: Basalt8
- decals:
- 55: -8,5
- 62: -2,-8
- - node:
- color: '#FFFFFFFF'
- id: Basalt9
- decals:
- 104: -1,-14
- - node:
- color: '#FFFFFFFF'
- id: Dirt
- decals:
- 65: -8,-6
- 66: -8,-5
- 67: -10,-4
- 68: -9,-4
- 69: -8,-3
- 71: -3,-10
- 72: -2,-10
- 73: 1,-6
- 74: 1,-5
- 75: 2,-2
- 76: 3,-3
- 77: 3,-4
- 78: -2,1
- 79: -4,1
- 80: -5,1
- 81: -3,-1
- 82: -4,0
- 83: -4,-2
- 84: -6,-4
- 85: -10,-2
- 86: -5,2
- 87: -1,2
- 88: -8,-1
- 89: -7,-3
- 90: -5,-11
- 93: 1,-8
- 94: 2,-7
- 95: 2,-6
- 96: 3,-7
- 97: 3,-6
- 98: 0,-4
- 99: 0,-3
- 100: -3,-8
- 102: -7,-10
- 124: -4,-12
- 125: -4,-11
- 126: -4,-8
- 127: -4,-9
- 128: -2,-11
- - node:
- color: '#9C2020FF'
- id: body
- decals:
- 46: -2,-7
- - node:
- color: '#1D1D21FF'
- id: splatter
- decals:
- 50: -6,-3
- 51: -2,-2
- 52: -5,-2
- - node:
- color: '#571212FF'
- id: splatter
- decals:
- 47: -5,-7
- 48: -6,-6
- 49: -1,-6
- - type: GridAtmosphere
- version: 2
- data:
- chunkSize: 4
- - type: GasTileOverlay
- - type: RadiationGridResistance
-- proto: AltarFangs
- entities:
- - uid: 51
- components:
- - type: Transform
- pos: -1.5,-5.5
- parent: 2
- - uid: 274
- components:
- - type: Transform
- pos: -4.5,-5.5
- parent: 2
-- proto: AltarHeaven
- entities:
- - uid: 60
- components:
- - type: Transform
- pos: -4.5,-2.5
- parent: 2
- - uid: 252
- components:
- - type: Transform
- pos: -1.5,-2.5
- parent: 2
-- proto: ArmBlade
- entities:
- - uid: 75
- components:
- - type: Transform
- pos: -9.542018,-1.4161515
- parent: 2
-- proto: BibleNecronomicon
- entities:
- - uid: 153
- components:
- - type: Transform
- pos: 4.5,-8.5
- parent: 2
-- proto: Bloodpack
- entities:
- - uid: 111
- components:
- - type: Transform
- pos: -1.5,-6.5
- parent: 2
-- proto: BookNarsieLegend
- entities:
- - uid: 44
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: 3.5,-6.5
- parent: 2
-- proto: ButchCleaver
- entities:
- - uid: 11
- components:
- - type: Transform
- pos: 3.5,1.5
- parent: 2
-- proto: CandleInfinite
- entities:
- - uid: 42
- components:
- - type: Transform
- pos: -4.5,-9.5
- parent: 2
- - uid: 224
- components:
- - type: Transform
- pos: -1.5,1.5
- parent: 2
-- proto: CandleRedSmallInfinite
- entities:
- - uid: 41
- components:
- - type: Transform
- pos: -7.5,-2.5
- parent: 2
- - uid: 106
- components:
- - type: Transform
- pos: -0.5914495,0.29293394
- parent: 2
- - uid: 142
- components:
- - type: Transform
- pos: -0.1695745,-4.863316
- parent: 2
- - uid: 143
- components:
- - type: Transform
- pos: -5.8258247,-7.6133156
- parent: 2
- - uid: 173
- components:
- - type: Transform
- pos: -7.3570747,-2.191441
- parent: 2
- - uid: 222
- components:
- - type: Transform
- pos: 0.5,-1.5
- parent: 2
- - uid: 223
- components:
- - type: Transform
- pos: -6.5,-7.5
- parent: 2
-- proto: CandleSmall
- entities:
- - uid: 228
- components:
- - type: Transform
- pos: -5.5,-10.5
- parent: 2
-- proto: ChairBrass
- entities:
- - uid: 199
- components:
- - type: Transform
- pos: -0.5,1.5
- parent: 2
- - uid: 208
- components:
- - type: Transform
- pos: -6.5,1.5
- parent: 2
- - uid: 210
- components:
- - type: Transform
- pos: -1.5,0.5
- parent: 2
-- proto: ChairRitual
- entities:
- - uid: 52
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -0.5,-8.5
- parent: 2
- - uid: 53
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: 0.5,-8.5
- parent: 2
- - uid: 64
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: 0.5,-9.5
- parent: 2
- - uid: 235
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -5.5,-9.5
- parent: 2
- - uid: 238
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -4.5,-8.5
- parent: 2
- - uid: 243
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -0.5,-9.5
- parent: 2
-- proto: ClockworkGirder
- entities:
- - uid: 63
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -0.5,-1.5
- parent: 2
- - uid: 70
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -5.5,-1.5
- parent: 2
-- proto: ClockworkShield
- entities:
- - uid: 45
- components:
- - type: Transform
- pos: -4.5,-2.5
- parent: 2
-- proto: ClockworkWindow
- entities:
- - uid: 74
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: 1.5,1.5
- parent: 2
- - uid: 80
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: 1.5,-8.5
- parent: 2
- - uid: 167
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: 1.5,-9.5
- parent: 2
- - uid: 179
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -8.5,0.5
- parent: 2
- - uid: 192
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -7.5,1.5
- parent: 2
- - uid: 236
- components:
- - type: Transform
- pos: 2.5,-8.5
- parent: 2
-- proto: ClothingHeadHatHoodCulthood
- entities:
- - uid: 254
- components:
- - type: Transform
- pos: 2.5,-3.5
- parent: 2
-- proto: ClothingHeadHatRedwizard
- entities:
- - uid: 5
- components:
- - type: Transform
- pos: -10.5,-9.5
- parent: 2
-- proto: ClothingHeadHelmetCult
- entities:
- - uid: 255
- components:
- - type: Transform
- pos: -7.5,-5.5
- parent: 2
-- proto: ClothingOuterRobesCult
- entities:
- - uid: 3
- components:
- - type: Transform
- pos: -5.5,0.5
- parent: 2
-- proto: ClothingOuterWizardRed
- entities:
- - uid: 1
- components:
- - type: Transform
- pos: -10.5,-9.5
- parent: 2
-- proto: ClothingShoesCult
- entities:
- - uid: 256
- components:
- - type: Transform
- pos: -2.5,-8.5
- parent: 2
-- proto: ComplexXenoArtifact
- entities:
- - uid: 244
- components:
- - type: Transform
- pos: -2.955439,-3.9142942
- parent: 2
-- proto: CrystalGrey
- entities:
- - uid: 137
- components:
- - type: Transform
- pos: -5.5,-13.5
- parent: 2
- - uid: 138
- components:
- - type: Transform
- pos: -11.5,0.5
- parent: 2
- - uid: 139
- components:
- - type: Transform
- pos: -11.5,-11.5
- parent: 2
- - uid: 140
- components:
- - type: Transform
- pos: 5.5,-6.5
- parent: 2
- - uid: 141
- components:
- - type: Transform
- pos: -0.5,4.5
- parent: 2
-- proto: CrystalOrange
- entities:
- - uid: 38
- components:
- - type: Transform
- pos: 6.5,-0.5
- parent: 2
- - uid: 205
- components:
- - type: Transform
- pos: -14.5,-6.5
- parent: 2
- - uid: 206
- components:
- - type: Transform
- pos: -6.5,4.5
- parent: 2
- - uid: 215
- components:
- - type: Transform
- pos: 2.5,-12.5
- parent: 2
-- proto: DrinkBloodGlass
- entities:
- - uid: 233
- components:
- - type: Transform
- pos: -1.5,-5.5
- parent: 2
-- proto: FloorTileItemBrassFilled
- entities:
- - uid: 46
- components:
- - type: Transform
- pos: -1.5,-3.5
- parent: 2
- - uid: 160
- components:
- - type: Transform
- pos: -6.5,-4.5
- parent: 2
- - uid: 168
- components:
- - type: Transform
- pos: -3.5,-9.5
- parent: 2
- - uid: 187
- components:
- - type: Transform
- pos: 2.5,-2.5
- parent: 2
- - uid: 188
- components:
- - type: Transform
- pos: -3.5,-0.5
- parent: 2
- - uid: 272
- components:
- - type: Transform
- pos: -8.5,-1.5
- parent: 2
-- proto: FloorTileItemElevatorShaft
- entities:
- - uid: 26
- components:
- - type: Transform
- pos: -6.5,-0.5
- parent: 2
- - uid: 71
- components:
- - type: Transform
- pos: -2.5,2.5
- parent: 2
- - uid: 72
- components:
- - type: Transform
- pos: -2.5,-6.5
- parent: 2
- - uid: 273
- components:
- - type: Transform
- pos: 1.5,-6.5
- parent: 2
-- proto: FloraRockSolid01
- entities:
- - uid: 110
- components:
- - type: Transform
- pos: -8.5,-11.5
- parent: 2
- - uid: 149
- components:
- - type: Transform
- pos: 3.5,-9.5
- parent: 2
-- proto: FloraRockSolid02
- entities:
- - uid: 112
- components:
- - type: Transform
- pos: -14.5,-4.5
- parent: 2
- - uid: 115
- components:
- - type: Transform
- pos: -3.5,4.5
- parent: 2
-- proto: FloraRockSolid03
- entities:
- - uid: 114
- components:
- - type: Transform
- pos: -13.5,-0.5
- parent: 2
-- proto: HamtrHarness
- entities:
- - uid: 69
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -5.5,-2.5
- parent: 2
-- proto: HamtrLArm
- entities:
- - uid: 144
- components:
- - type: Transform
- pos: -6.5,-3.5
- parent: 2
-- proto: HonkerHarness
- entities:
- - uid: 209
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -4.5,-1.5
- parent: 2
-- proto: KitchenSpike
- entities:
- - uid: 247
- components:
- - type: Transform
- pos: -1.5,-6.5
- parent: 2
- - uid: 258
- components:
- - type: Transform
- pos: -4.5,-6.5
- parent: 2
- - uid: 260
- components:
- - type: Transform
- pos: -5.5,-5.5
- parent: 2
- - uid: 261
- components:
- - type: Transform
- pos: -0.5,-5.5
- parent: 2
-- proto: LeftArmArachnid
- entities:
- - uid: 152
- components:
- - type: Transform
- pos: -0.5,-5.5
- parent: 2
-- proto: MaterialWoodPlank1
- entities:
- - uid: 8
- components:
- - type: Transform
- pos: -5.5,-8.5
- parent: 2
- - uid: 200
- components:
- - type: Transform
- pos: -1.5,-8.5
- parent: 2
-- proto: PinionAirlock
- entities:
- - uid: 4
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -10.5,-4.5
- parent: 2
- - uid: 161
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -3.5,3.5
- parent: 2
- - uid: 164
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -10.5,-3.5
- parent: 2
-- proto: PinionAirlockAssembly
- entities:
- - uid: 48
- components:
- - type: Transform
- pos: -3.5,-11.5
- parent: 2
- - uid: 163
- components:
- - type: Transform
- pos: 4.5,-4.5
- parent: 2
- - uid: 165
- components:
- - type: Transform
- pos: -2.5,3.5
- parent: 2
- - uid: 257
- components:
- - type: Transform
- pos: -2.5,-11.5
- parent: 2
-- proto: PlushieNar
- entities:
- - uid: 259
- components:
- - type: Transform
- pos: -3.5,-5.5
- parent: 2
-- proto: PlushieRatvar
- entities:
- - uid: 246
- components:
- - type: Transform
- pos: -2.5,-2.5
- parent: 2
-- proto: RandomGreyStalagmite
- entities:
- - uid: 217
- components:
- - type: Transform
- pos: -5.5,2.5
- parent: 2
- - uid: 218
- components:
- - type: Transform
- pos: 0.5,-7.5
- parent: 2
- - uid: 219
- components:
- - type: Transform
- pos: 0.5,1.5
- parent: 2
- - uid: 220
- components:
- - type: Transform
- pos: -8.5,-6.5
- parent: 2
- - uid: 231
- components:
- - type: Transform
- pos: -4.5,-7.5
- parent: 2
-- proto: RightArmVox
- entities:
- - uid: 146
- components:
- - type: Transform
- pos: -5.5,-5.5
- parent: 2
-- proto: RipleyHarness
- entities:
- - uid: 249
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -1.5,-1.5
- parent: 2
-- proto: RitualDagger
- entities:
- - uid: 245
- components:
- - type: Transform
- pos: -4.5,-5.5
- parent: 2
-- proto: ShadowBasaltFour
- entities:
- - uid: 175
- components:
- - type: Transform
- pos: -0.5,-7.5
- parent: 2
-- proto: ShadowBasaltOne
- entities:
- - uid: 195
- components:
- - type: Transform
- pos: -8.5,-4.5
- parent: 2
-- proto: ShadowBasaltRandom
- entities:
- - uid: 174
- components:
- - type: Transform
- pos: -4.5,-0.5
- parent: 2
-- proto: ShadowBasaltTwo
- entities:
- - uid: 7
- components:
- - type: Transform
- pos: -9.5,-6.5
- parent: 2
- - uid: 176
- components:
- - type: Transform
- pos: -1.5,-3.5
- parent: 2
-- proto: ShardGlassClockwork
- entities:
- - uid: 25
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -8.5,-7.5
- parent: 2
- - uid: 82
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -6.5,-6.5
- parent: 2
- - uid: 85
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -6.5,-9.5
- parent: 2
- - uid: 158
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: 1.5,-1.5
- parent: 2
- - uid: 159
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -7.5,-0.5
- parent: 2
- - uid: 162
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -0.5,-0.5
- parent: 2
-- proto: SheetBrass1
- entities:
- - uid: 170
- components:
- - type: Transform
- pos: -5.5,1.5
- parent: 2
- - uid: 186
- components:
- - type: Transform
- pos: -4.5,0.5
- parent: 2
-- proto: SheetBrass10
- entities:
- - uid: 207
- components:
- - type: Transform
- pos: 0.5,0.5
- parent: 2
-- proto: SheetClockworkGlass1
- entities:
- - uid: 232
- components:
- - type: Transform
- pos: -1.5,-2.5
- parent: 2
-- proto: SpaceTickSpawner
- entities:
- - uid: 40
- components:
- - type: Transform
- pos: 4.5,-8.5
- parent: 2
- - uid: 151
- components:
- - type: Transform
- pos: 4.5,-8.5
- parent: 2
- - uid: 212
- components:
- - type: Transform
- pos: 4.5,-8.5
- parent: 2
-- proto: SpawnMobCarpHolo
- entities:
- - uid: 147
- components:
- - type: Transform
- pos: 0.5,-6.5
- parent: 2
-- proto: SpawnMobCarpMagic
- entities:
- - uid: 216
- components:
- - type: Transform
- pos: -9.5,-6.5
- parent: 2
-- proto: SpawnMobHellspawn
- entities:
- - uid: 43
- components:
- - type: Transform
- pos: -6.5,-1.5
- parent: 2
-- proto: TableBrass
- entities:
- - uid: 169
- components:
- - type: Transform
- pos: -9.5,-1.5
- parent: 2
-- proto: VimHarness
- entities:
- - uid: 68
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -0.5,-2.5
- parent: 2
-- proto: WallCult
- entities:
- - uid: 9
- components:
- - type: Transform
- pos: -6.5,2.5
- parent: 2
- - uid: 10
- components:
- - type: Transform
- pos: 0.5,-10.5
- parent: 2
- - uid: 13
- components:
- - type: Transform
- pos: -5.5,-1.5
- parent: 2
- - uid: 14
- components:
- - type: Transform
- pos: 0.5,2.5
- parent: 2
- - uid: 15
- components:
- - type: Transform
- pos: -0.5,-6.5
- parent: 2
- - uid: 16
- components:
- - type: Transform
- pos: -11.5,-5.5
- parent: 2
- - uid: 17
- components:
- - type: Transform
- pos: -5.5,3.5
- parent: 2
- - uid: 19
- components:
- - type: Transform
- pos: -9.5,-8.5
- parent: 2
- - uid: 20
- components:
- - type: Transform
- pos: -10.5,-1.5
- parent: 2
- - uid: 27
- components:
- - type: Transform
- pos: 4.5,-7.5
- parent: 2
- - uid: 29
- components:
- - type: Transform
- pos: 0.5,-11.5
- parent: 2
- - uid: 30
- components:
- - type: Transform
- pos: -5.5,-6.5
- parent: 2
- - uid: 31
- components:
- - type: Transform
- pos: -5.5,-11.5
- parent: 2
- - uid: 33
- components:
- - type: Transform
- pos: 3.5,-0.5
- parent: 2
- - uid: 34
- components:
- - type: Transform
- pos: -4.5,3.5
- parent: 2
- - uid: 35
- components:
- - type: Transform
- pos: 3.5,-7.5
- parent: 2
- - uid: 37
- components:
- - type: Transform
- pos: -0.5,-1.5
- parent: 2
- - uid: 49
- components:
- - type: Transform
- pos: -1.5,-11.5
- parent: 2
- - uid: 62
- components:
- - type: Transform
- pos: 1.5,-10.5
- parent: 2
- - uid: 73
- components:
- - type: Transform
- pos: -7.5,-10.5
- parent: 2
- - uid: 79
- components:
- - type: Transform
- pos: 5.5,-2.5
- parent: 2
- - uid: 81
- components:
- - type: Transform
- pos: -10.5,-7.5
- parent: 2
- - uid: 83
- components:
- - type: Transform
- pos: -10.5,-2.5
- parent: 2
- - uid: 89
- components:
- - type: Transform
- pos: 4.5,-0.5
- parent: 2
- - uid: 91
- components:
- - type: Transform
- pos: -6.5,-11.5
- parent: 2
- - uid: 92
- components:
- - type: Transform
- pos: -10.5,-0.5
- parent: 2
- - uid: 93
- components:
- - type: Transform
- pos: -11.5,-2.5
- parent: 2
- - uid: 94
- components:
- - type: Transform
- pos: -9.5,-0.5
- parent: 2
- - uid: 97
- components:
- - type: Transform
- pos: 3.5,0.5
- parent: 2
- - uid: 166
- components:
- - type: Transform
- pos: -0.5,-11.5
- parent: 2
- - uid: 172
- components:
- - type: Transform
- pos: -6.5,3.5
- parent: 2
- - uid: 177
- components:
- - type: Transform
- pos: -1.5,-12.5
- parent: 2
- - uid: 180
- components:
- - type: Transform
- pos: -0.5,3.5
- parent: 2
- - uid: 184
- components:
- - type: Transform
- pos: -1.5,4.5
- parent: 2
- - uid: 185
- components:
- - type: Transform
- pos: 4.5,-2.5
- parent: 2
- - uid: 189
- components:
- - type: Transform
- pos: -10.5,-5.5
- parent: 2
- - uid: 190
- components:
- - type: Transform
- pos: 1.5,2.5
- parent: 2
- - uid: 191
- components:
- - type: Transform
- pos: -4.5,4.5
- parent: 2
- - uid: 193
- components:
- - type: Transform
- pos: 4.5,-1.5
- parent: 2
- - uid: 194
- components:
- - type: Transform
- pos: 5.5,-5.5
- parent: 2
- - uid: 196
- components:
- - type: Transform
- pos: -10.5,-6.5
- parent: 2
- - uid: 198
- components:
- - type: Transform
- pos: 4.5,-6.5
- parent: 2
- - uid: 203
- components:
- - type: Transform
- pos: -7.5,2.5
- parent: 2
- - uid: 204
- components:
- - type: Transform
- pos: -9.5,0.5
- parent: 2
- - uid: 250
- components:
- - type: Transform
- pos: -9.5,-7.5
- parent: 2
- - uid: 264
- components:
- - type: Transform
- pos: -1.5,3.5
- parent: 2
- - uid: 265
- components:
- - type: Transform
- pos: 4.5,-5.5
- parent: 2
- - uid: 267
- components:
- - type: Transform
- pos: 0.5,3.5
- parent: 2
- - uid: 270
- components:
- - type: Transform
- pos: -4.5,-11.5
- parent: 2
- - uid: 271
- components:
- - type: Transform
- pos: -6.5,-10.5
- parent: 2
- - uid: 275
- components:
- - type: Transform
- pos: 3.5,-8.5
- parent: 2
- - uid: 278
- components:
- - type: Transform
- pos: -4.5,-12.5
- parent: 2
-- proto: WallRock
- entities:
- - uid: 6
- components:
- - type: Transform
- pos: 5.5,0.5
- parent: 2
- - uid: 12
- components:
- - type: Transform
- pos: -8.5,2.5
- parent: 2
- - uid: 18
- components:
- - type: Transform
- pos: -12.5,-0.5
- parent: 2
- - uid: 22
- components:
- - type: Transform
- pos: -9.5,3.5
- parent: 2
- - uid: 23
- components:
- - type: Transform
- pos: -7.5,4.5
- parent: 2
- - uid: 28
- components:
- - type: Transform
- pos: -11.5,-10.5
- parent: 2
- - uid: 36
- components:
- - type: Transform
- pos: -9.5,-10.5
- parent: 2
- - uid: 39
- components:
- - type: Transform
- pos: -16.5,-3.5
- parent: 2
- - uid: 47
- components:
- - type: Transform
- pos: 0.5,-13.5
- parent: 2
- - uid: 50
- components:
- - type: Transform
- pos: -11.5,-1.5
- parent: 2
- - uid: 54
- components:
- - type: Transform
- pos: 3.5,-12.5
- parent: 2
- - uid: 55
- components:
- - type: Transform
- pos: 5.5,-13.5
- parent: 2
- - uid: 56
- components:
- - type: Transform
- pos: 4.5,-9.5
- parent: 2
- - uid: 57
- components:
- - type: Transform
- pos: -15.5,-2.5
- parent: 2
- - uid: 58
- components:
- - type: Transform
- pos: -12.5,1.5
- parent: 2
- - uid: 59
- components:
- - type: Transform
- pos: -9.5,-11.5
- parent: 2
- - uid: 61
- components:
- - type: Transform
- pos: 4.5,-12.5
- parent: 2
- - uid: 65
- components:
- - type: Transform
- pos: -11.5,-9.5
- parent: 2
- - uid: 66
- components:
- - type: Transform
- pos: -8.5,3.5
- parent: 2
- - uid: 67
- components:
- - type: Transform
- pos: -10.5,-11.5
- parent: 2
- - uid: 76
- components:
- - type: Transform
- pos: 6.5,-10.5
- parent: 2
- - uid: 77
- components:
- - type: Transform
- pos: 5.5,-12.5
- parent: 2
- - uid: 84
- components:
- - type: Transform
- pos: -4.5,-13.5
- parent: 2
- - uid: 88
- components:
- - type: Transform
- pos: -10.5,0.5
- parent: 2
- - uid: 95
- components:
- - type: Transform
- pos: -13.5,-6.5
- parent: 2
- - uid: 96
- components:
- - type: Transform
- pos: -7.5,-9.5
- parent: 2
- - uid: 98
- components:
- - type: Transform
- pos: -5.5,4.5
- parent: 2
- - uid: 100
- components:
- - type: Transform
- pos: 3.5,3.5
- parent: 2
- - uid: 101
- components:
- - type: Transform
- pos: 8.5,-3.5
- parent: 2
- - uid: 102
- components:
- - type: Transform
- pos: 9.5,-5.5
- parent: 2
- - uid: 103
- components:
- - type: Transform
- pos: 7.5,-2.5
- parent: 2
- - uid: 104
- components:
- - type: Transform
- pos: -7.5,-12.5
- parent: 2
- - uid: 105
- components:
- - type: Transform
- pos: 8.5,-6.5
- parent: 2
- - uid: 107
- components:
- - type: Transform
- pos: -7.5,-11.5
- parent: 2
- - uid: 109
- components:
- - type: Transform
- pos: -9.5,-9.5
- parent: 2
- - uid: 113
- components:
- - type: Transform
- pos: -2.5,-12.5
- parent: 2
- - uid: 116
- components:
- - type: Transform
- pos: 2.5,0.5
- parent: 2
- - uid: 118
- components:
- - type: Transform
- pos: 5.5,3.5
- parent: 2
- - uid: 119
- components:
- - type: Transform
- pos: 3.5,2.5
- parent: 2
- - uid: 120
- components:
- - type: Transform
- pos: 1.5,0.5
- parent: 2
- - uid: 121
- components:
- - type: Transform
- pos: 7.5,-7.5
- parent: 2
- - uid: 122
- components:
- - type: Transform
- pos: 0.5,-0.5
- parent: 2
- - uid: 123
- components:
- - type: Transform
- pos: 2.5,3.5
- parent: 2
- - uid: 124
- components:
- - type: Transform
- pos: 4.5,1.5
- parent: 2
- - uid: 125
- components:
- - type: Transform
- pos: -0.5,6.5
- parent: 2
- - uid: 126
- components:
- - type: Transform
- pos: 6.5,-2.5
- parent: 2
- - uid: 127
- components:
- - type: Transform
- pos: 7.5,-1.5
- parent: 2
- - uid: 128
- components:
- - type: Transform
- pos: -2.5,6.5
- parent: 2
- - uid: 129
- components:
- - type: Transform
- pos: 5.5,-0.5
- parent: 2
- - uid: 130
- components:
- - type: Transform
- pos: 7.5,-3.5
- parent: 2
- - uid: 131
- components:
- - type: Transform
- pos: 6.5,-4.5
- parent: 2
- - uid: 132
- components:
- - type: Transform
- pos: 5.5,-3.5
- parent: 2
- - uid: 134
- components:
- - type: Transform
- pos: 6.5,-5.5
- parent: 2
- - uid: 135
- components:
- - type: Transform
- pos: 8.5,-4.5
- parent: 2
- - uid: 136
- components:
- - type: Transform
- pos: -5.5,-12.5
- parent: 2
- - uid: 145
- components:
- - type: Transform
- pos: -3.5,-13.5
- parent: 2
- - uid: 150
- components:
- - type: Transform
- pos: -4.5,-14.5
- parent: 2
- - uid: 154
- components:
- - type: Transform
- pos: 5.5,-9.5
- parent: 2
- - uid: 155
- components:
- - type: Transform
- pos: 4.5,-10.5
- parent: 2
- - uid: 156
- components:
- - type: Transform
- pos: 3.5,-11.5
- parent: 2
- - uid: 157
- components:
- - type: Transform
- pos: 1.5,-13.5
- parent: 2
- - uid: 171
- components:
- - type: Transform
- pos: -9.5,1.5
- parent: 2
- - uid: 178
- components:
- - type: Transform
- pos: -8.5,-8.5
- parent: 2
- - uid: 181
- components:
- - type: Transform
- pos: -11.5,-6.5
- parent: 2
- - uid: 183
- components:
- - type: Transform
- pos: -11.5,-0.5
- parent: 2
- - uid: 197
- components:
- - type: Transform
- pos: -11.5,-7.5
- parent: 2
- - uid: 202
- components:
- - type: Transform
- pos: -7.5,0.5
- parent: 2
- - uid: 211
- components:
- - type: Transform
- pos: -3.5,7.5
- parent: 2
- - uid: 213
- components:
- - type: Transform
- pos: -0.5,-15.5
- parent: 2
- - uid: 214
- components:
- - type: Transform
- pos: -15.5,-8.5
- parent: 2
- - uid: 221
- components:
- - type: Transform
- pos: -14.5,-10.5
- parent: 2
- - uid: 225
- components:
- - type: Transform
- pos: -12.5,-7.5
- parent: 2
- - uid: 226
- components:
- - type: Transform
- pos: -14.5,-7.5
- parent: 2
- - uid: 227
- components:
- - type: Transform
- pos: -13.5,-8.5
- parent: 2
- - uid: 229
- components:
- - type: Transform
- pos: -12.5,-8.5
- parent: 2
- - uid: 230
- components:
- - type: Transform
- pos: -13.5,-7.5
- parent: 2
- - uid: 234
- components:
- - type: Transform
- pos: 4.5,-3.5
- parent: 2
- - uid: 237
- components:
- - type: Transform
- pos: -12.5,3.5
- parent: 2
- - uid: 239
- components:
- - type: Transform
- pos: -8.5,5.5
- parent: 2
- - uid: 240
- components:
- - type: Transform
- pos: 2.5,5.5
- parent: 2
- - uid: 241
- components:
- - type: Transform
- pos: -14.5,0.5
- parent: 2
- - uid: 242
- components:
- - type: Transform
- pos: 1.5,5.5
- parent: 2
- - uid: 248
- components:
- - type: Transform
- pos: 3.5,-4.5
- parent: 2
- - uid: 251
- components:
- - type: Transform
- pos: -7.5,-7.5
- parent: 2
- - uid: 253
- components:
- - type: Transform
- pos: -6.5,-8.5
- parent: 2
- - uid: 262
- components:
- - type: Transform
- pos: -11.5,-8.5
- parent: 2
- - uid: 263
- components:
- - type: Transform
- pos: -12.5,-9.5
- parent: 2
- - uid: 268
- components:
- - type: Transform
- pos: -8.5,-12.5
- parent: 2
- - uid: 269
- components:
- - type: Transform
- pos: -10.5,1.5
- parent: 2
- - uid: 277
- components:
- - type: Transform
- pos: -12.5,-10.5
- parent: 2
- - uid: 279
- components:
- - type: Transform
- pos: -7.5,-8.5
- parent: 2
- - uid: 281
- components:
- - type: Transform
- pos: -12.5,-2.5
- parent: 2
-- proto: WallRockArtifactFragment
- entities:
- - uid: 86
- components:
- - type: Transform
- pos: -10.5,-8.5
- parent: 2
- - uid: 201
- components:
- - type: Transform
- pos: -8.5,-9.5
- parent: 2
-- proto: WallRockBananium
- entities:
- - uid: 99
- components:
- - type: Transform
- pos: 5.5,-8.5
- parent: 2
- - uid: 133
- components:
- - type: Transform
- pos: 7.5,-4.5
- parent: 2
-- proto: WallRockGold
- entities:
- - uid: 24
- components:
- - type: Transform
- pos: -9.5,2.5
- parent: 2
- - uid: 276
- components:
- - type: Transform
- pos: -8.5,1.5
- parent: 2
-- proto: WallRockUranium
- entities:
- - uid: 117
- components:
- - type: Transform
- pos: 2.5,1.5
- parent: 2
- - uid: 148
- components:
- - type: Transform
- pos: -3.5,-12.5
- parent: 2
-- proto: WindowClockworkDirectional
- entities:
- - uid: 21
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -5.5,-2.5
- parent: 2
- - uid: 32
- components:
- - type: Transform
- pos: -1.5,-1.5
- parent: 2
- - uid: 78
- components:
- - type: Transform
- pos: -4.5,-1.5
- parent: 2
- - uid: 87
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -0.5,-2.5
- parent: 2
- - uid: 90
- components:
- - type: Transform
- rot: 1.5707963267948966 rad
- pos: -5.5,-5.5
- parent: 2
- - uid: 182
- components:
- - type: Transform
- rot: -1.5707963267948966 rad
- pos: -0.5,-5.5
- parent: 2
- - uid: 266
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -1.5,-6.5
- parent: 2
- - uid: 280
- components:
- - type: Transform
- rot: 3.141592653589793 rad
- pos: -4.5,-6.5
- parent: 2
-...
diff --git a/Resources/Prototypes/ADT/Actions/changeling.yml b/Resources/Prototypes/ADT/Actions/changeling.yml
new file mode 100644
index 00000000000..888e4f51d6f
--- /dev/null
+++ b/Resources/Prototypes/ADT/Actions/changeling.yml
@@ -0,0 +1,426 @@
+- type: entity
+ id: ActionChangelingEvolutionMenu
+ name: action-evolution-menu
+ description: action-evolution-menu-decs
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: changelingsting
+ event: !type:ChangelingEvolutionMenuActionEvent
+ priority: -70
+
+- type: entity
+ id: ActionChangelingAbsorb
+ name: action-absorb-dna
+ description: action-absorb-dna-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: absorb_dna
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ event: !type:LingAbsorbActionEvent
+ useDelay: 5
+ canTargetSelf: false
+ priority: -60
+
+- type: entity
+ id: ActionChangelingTransform
+ name: action-transform
+ description: action-transform-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: transform
+ itemIconStyle: BigAction
+ event: !type:ChangelingTransformActionEvent
+ useDelay: 5
+ priority: -69
+
+- type: entity
+ id: ActionLingRegenerate
+ name: action-regenerate
+ description: action-regenerate-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ checkCanInteract: false
+ checkConsciousness: false
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: regenerate
+ itemIconStyle: BigAction
+ event: !type:LingRegenerateActionEvent
+ useDelay: 115
+ priority: -66
+
+- type: entity
+ id: ActionLingStingExtract
+ name: action-extract-dna-sting
+ description: action-extract-dna-sting-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: sting_extract
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ event: !type:LingStingExtractActionEvent
+ useDelay: 30
+ canTargetSelf: false
+ priority: -65
+
+- type: entity
+ id: ActionArmBlade
+ name: action-toggle-arm-blade
+ description: action-toggle-arm-blade-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: armblade
+ itemIconStyle: BigAction
+ event: !type:ArmBladeActionEvent
+ useDelay: 1
+ priority: -50
+
+- type: entity
+ id: ActionLingArmor
+ name: action-toggle-chitinous-armor
+ description: action-toggle-chitinous-armor-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: chitinous_armor
+ itemIconStyle: BigAction
+ event: !type:LingArmorActionEvent
+ useDelay: 15
+ priority: -49
+
+- type: entity
+ id: ActionLingInvisible
+ name: action-toggle-chameleon-skin
+ description: action-toggle-chameleon-skin-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: chameleon_skin
+ itemIconStyle: BigAction
+ event: !type:LingInvisibleActionEvent
+ useDelay: 1
+ priority: -48
+
+- type: entity
+ id: ActionLingEMP
+ name: action-activate-dissonant-shriek
+ description: action-activate-dissonant-shriek-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: dissonant_shriek
+ itemIconStyle: BigAction
+ useDelay: 15
+ event: !type:LingEMPActionEvent
+ priority: -47
+ # Stasis Death
+
+- type: entity
+ id: ActionStasisDeath
+ name: action-stasis-death
+ description: action-stasis-death-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ checkCanInteract: false
+ checkConsciousness: false
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: fake_death
+ iconOn:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: revive
+ itemIconStyle: BigAction
+ event: !type:StasisDeathActionEvent
+ useDelay: 90
+ priority: -46
+
+ # Blind sting
+- type: entity
+ id: ActionLingBlindSting
+ name: action-blind-sting
+ description: action-blind-sting-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: sting_blind
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ event: !type:BlindStingEvent
+ useDelay: 2
+ canTargetSelf: false
+ priority: -64
+
+ # Adrenaline
+- type: entity
+ id: ActionLingAdrenaline
+ name: action-adrenaline
+ description: action-adrenaline-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: adrenaline
+ itemIconStyle: BigAction
+ event: !type:AdrenalineActionEvent
+ useDelay: 90
+ priority: -45
+
+ # Fleshmend
+- type: entity
+ id: ActionLingFleshmend
+ name: action-fleshmend
+ description: action-fleshmend-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: fleshmend
+ itemIconStyle: BigAction
+ event: !type:FleshmendActionEvent
+ useDelay: 90
+ priority: -44
+
+ # Mute sting
+- type: entity
+ id: ActionLingMuteSting
+ name: action-mute-sting
+ description: action-mute-sting-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: sting_mute
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ event: !type:MuteStingEvent
+ useDelay: 5
+ canTargetSelf: false
+ priority: -63
+
+ # Drug sting
+- type: entity
+ id: ActionLingDrugSting
+ name: action-drug-sting
+ description: action-drug-sting-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: sting_lsd
+ itemIconStyle: BigAction
+ whitelist:
+ components:
+ - Body
+ event: !type:DrugStingEvent
+ useDelay: 5
+ canTargetSelf: false
+ priority: -62
+
+ # Muscles
+- type: entity
+ id: ActionLingMuscles
+ name: action-lingmuscles
+ description: action-lingmuscles-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: strained_muscles
+ itemIconStyle: BigAction
+ event: !type:ChangelingMusclesActionEvent
+ useDelay: 1
+ priority: -43
+
+ # Lesser form
+- type: entity
+ id: ActionLingLesserForm
+ name: action-lesser-form
+ description: action-lesser-form-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: lesser_form
+ iconOn:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: human_form
+ itemIconStyle: BigAction
+ checkCanInteract: false
+ event: !type:ChangelingLesserFormActionEvent
+ useDelay: 10
+ priority: -67
+
+ # Arm shield
+- type: entity
+ id: ActionArmShield
+ name: action-toggle-arm-shield
+ description: action-toggle-arm-shield-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: organic_shield
+ itemIconStyle: BigAction
+ event: !type:ArmShieldActionEvent
+ useDelay: 1
+ priority: -51
+
+ # Last Resort
+- type: entity
+ id: ActionLingLastResort
+ name: action-resort
+ description: action-resort-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: last_resort
+ itemIconStyle: BigAction
+ checkCanInteract: false
+ event: !type:LastResortActionEvent
+ useDelay: 1
+ priority: -61
+
+ # Biodegrade
+- type: entity
+ id: ActionLingBiodegrade
+ name: action-biodegrade
+ description: action-biodegrade-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: biodegrade
+ itemIconStyle: BigAction
+ checkCanInteract: false
+ event: !type:LingBiodegradeActionEvent
+ useDelay: 10
+ priority: -61
+
+ # Resonant
+- type: entity
+ id: ActionLingResonant
+ name: action-resonant
+ description: action-resonant-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: resonant_shriek
+ itemIconStyle: BigAction
+ checkCanInteract: false
+ event: !type:LingResonantShriekEvent
+ useDelay: 10
+ priority: -61
+
+ # TSting
+- type: entity
+ id: ActionLingTransformSting
+ name: action-transform-sting
+ description: action-transform-sting-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: EntityTargetAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: sting_transform
+ itemIconStyle: BigAction
+ event: !type:TransformationStingEvent
+ whitelist:
+ components:
+ - Body
+ canTargetSelf: false
+ useDelay: 10
+ priority: -61
+
+ # Arm Hammer
+- type: entity
+ id: ActionArmace
+ name: action-toggle-arm-hammer
+ description: action-toggle-arm-hammer-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: armhammer
+ itemIconStyle: BigAction
+ event: !type:ArmaceActionEvent
+ useDelay: 1
+ priority: -51
+
+ # Digital Camo
+- type: entity
+ id: ActionDigiCamo
+ name: action-digi-camo
+ description: action-digi-camo-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: digital_camo
+ itemIconStyle: BigAction
+ event: !type:DigitalCamouflageEvent
+ useDelay: 1
+ priority: -55
+
+ # Bone shard
+- type: entity
+ id: ActionBoneShard
+ name: action-bone-shard
+ description: action-bone-shard-desc
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: InstantAction
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: bone_shard
+ itemIconStyle: BigAction
+ event: !type:ChangelingBoneShardEvent
+ useDelay: 15
+ priority: -55
diff --git a/Resources/Prototypes/ADT/Alerts/alerts.yml b/Resources/Prototypes/ADT/Alerts/alerts.yml
index 996eaf7c4eb..7d451a5d3a5 100644
--- a/Resources/Prototypes/ADT/Alerts/alerts.yml
+++ b/Resources/Prototypes/ADT/Alerts/alerts.yml
@@ -152,3 +152,27 @@
description: alerts-shadekin-power-desc
minSeverity: 0
maxSeverity: 4
+
+- type: alert
+ id: Chemicals
+ icons:
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals0
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals1
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals2
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals3
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals4
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals5
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals6
+ - sprite: /Textures/ADT/Changeling/Alerts/chemicals_counter.rsi
+ state: chemicals7
+ name: alerts-changeling-chemicals-name
+ description: alerts-changeling-chemicals-desc
+ minSeverity: 0
+ maxSeverity: 7
diff --git a/Resources/Prototypes/ADT/Catalog/ling_catalog.yml b/Resources/Prototypes/ADT/Catalog/ling_catalog.yml
new file mode 100644
index 00000000000..1917a74a510
--- /dev/null
+++ b/Resources/Prototypes/ADT/Catalog/ling_catalog.yml
@@ -0,0 +1,300 @@
+- type: listing
+ id: ChangelingArmBlade
+ name: listing-arm-blade
+ description: listing-arm-blade-desc
+ productAction: ActionArmBlade
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingArmor
+ name: listing-chitinous-armor
+ description: listing-chitinous-armor-desc
+ productAction: ActionLingArmor
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingChameleonSkin
+ name: listing-chameleon-skin
+ description: listing-chameleon-skin-desc
+ productAction: ActionLingInvisible
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingEMP
+ name: listing-dissonant-shriek
+ description: listing-dissonant-shriek-desc
+ productAction: ActionLingEMP
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingBlindSting
+ name: listing-blind-sting
+ description: listing-blind-sting-desc
+ productAction: ActionLingBlindSting
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingAdrenaline
+ name: listing-adrenaline
+ description: listing-adrenaline-desc
+ productAction: ActionLingAdrenaline
+ mindAction: false
+ cost:
+ EvolutionPoints: 1
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingFleshmend
+ name: listing-fleshmend
+ description: listing-fleshmend-desc
+ productAction: ActionLingFleshmend
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingMuteSting
+ name: listing-mute-sting
+ description: listing-mute-sting-desc
+ productAction: ActionLingMuteSting
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingMuscles
+ name: listing-strained-muscles
+ description: listing-strained-muscles-desc
+ productAction: ActionLingMuscles
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingLesserForm
+ name: listing-lesser-form
+ description: listing-lesser-form-desc
+ productAction: ActionLingLesserForm
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingDrugSting
+ name: listing-drug-sting
+ description: listing-drug-sting-desc
+ productAction: ActionLingDrugSting
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingArmShield
+ name: listing-arm-shield
+ description: listing-arm-shield-desc
+ productAction: ActionArmShield
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingLastResort
+ name: listing-last-resort
+ description: listing-last-resort-desc
+ productAction: ActionLingLastResort
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+ - !type:ChangelingLastResortNotUsedCondition
+
+- type: listing
+ id: ChangelingBiodegrade
+ name: listing-biodegrade
+ description: listing-biodegrade-desc
+ productAction: ActionLingBiodegrade
+ mindAction: false
+ cost:
+ EvolutionPoints: 1
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingResonant
+ name: listing-resonant-shriek
+ description: listing-resonant-shriek-desc
+ productAction: ActionLingResonant
+ mindAction: false
+ cost:
+ EvolutionPoints: 1
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingTransformSting
+ name: listing-transform-sting
+ description: listing-transform-sting-desc
+ productAction: ActionLingTransformSting
+ mindAction: false
+ cost:
+ EvolutionPoints: 3
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingArmace
+ name: listing-arm-mace
+ description: listing-arm-mace-desc
+ productAction: ActionArmace
+ mindAction: false
+ cost:
+ EvolutionPoints: 4
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingDigiCamo
+ name: listing-digi-camo
+ description: listing-digi-camo-desc
+ productAction: ActionDigiCamo
+ mindAction: false
+ cost:
+ EvolutionPoints: 2
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingBoneShard
+ name: listing-bone-shard
+ description: listing-bone-shard-desc
+ productAction: ActionBoneShard
+ mindAction: false
+ cost:
+ EvolutionPoints: 1
+ categories:
+ - ChangelingAbilities
+ conditions:
+ - !type:ListingLimitedStockCondition
+ stock: 1
+ - !type:ChangelingActionNotPresentCondition
+
+- type: listing
+ id: ChangelingRefresh
+ name: changeling-refresh
+ description: changeling-refresh-desc
+ productEvent: !type:ChangelingRefreshEvent
+ raiseOnBuyer: true
+ cost:
+ EvolutionPoints: 0
+ categories:
+ - ChangelingAbilities
+ icon: Interface/Actions/firestarter.png
+ conditions:
+ - !type:ChangelingCanRefreshCondition
+ - !type:ChangelingActionNotPresentCondition
diff --git a/Resources/Prototypes/ADT/Changeling/polymorph.yml b/Resources/Prototypes/ADT/Changeling/polymorph.yml
new file mode 100644
index 00000000000..692e2ac108c
--- /dev/null
+++ b/Resources/Prototypes/ADT/Changeling/polymorph.yml
@@ -0,0 +1,12 @@
+ # ling human morph
+ - type: polymorph
+ id: ChangelingHumanoidMorph
+ configuration:
+ entity: MobHuman
+ forced: true
+ transferName: false
+ transferHumanoidAppearance: false
+ inventory: Transfer
+ revertOnDeath: false
+ revertOnCrit: false
+ allowRepeatedMorphs: true
diff --git a/Resources/Prototypes/ADT/Entities/Mobs/Player/changeling.yml b/Resources/Prototypes/ADT/Entities/Mobs/Player/changeling.yml
new file mode 100644
index 00000000000..a0302f247f6
--- /dev/null
+++ b/Resources/Prototypes/ADT/Entities/Mobs/Player/changeling.yml
@@ -0,0 +1,127 @@
+- type: entity
+ id: ADTMobMonkeyChangeling
+ parent: MobMonkey
+ suffix: changeling
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: LanguageSpeaker # Frontier
+ speaks:
+ - Monkey
+ understands:
+ - GalacticCommon
+ - Monkey
+
+- type: polymorph
+ id: ADTChangelingLesserForm
+ configuration:
+ entity: ADTMobMonkeyChangeling
+ forced: true
+ inventory: Drop
+ allowRepeatedMorphs: true
+ revertOnDeath: false
+ revertOnCrit: false
+
+- type: entity
+ name: changeling slug
+ parent: SimpleMobBase
+ id: ADTChangelingHeadslug
+ description: e
+ components:
+ - type: Body
+ prototype: Mouse
+ - type: Speech
+ speechSounds: Squeak
+ speechVerb: SmallMob
+ - type: Sprite
+ drawdepth: SmallMobs
+ sprite: ADT/Changeling/Mobs/headslug.rsi
+ layers:
+ - map: ["enum.DamageStateVisualLayers.Base"]
+ state: headslug
+ - type: Item
+ size: Tiny
+ - type: NpcFactionMember
+ factions:
+ - Mouse
+ - type: HTN
+ rootTask:
+ task: MouseCompound
+ - type: Physics
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeCircle
+ radius: 0.2
+ density: 100
+ mask:
+ - SmallMobMask
+ layer:
+ - SmallMobLayer
+ - type: MobState
+ - type: Deathgasp
+ - type: MobStateActions
+ actions:
+ Critical:
+ - ActionCritSuccumb
+ - ActionCritFakeDeath
+ - ActionCritLastWords
+ - type: MobThresholds
+ thresholds:
+ 0: Alive
+ 69: Critical
+ 70: Dead
+ - type: MovementSpeedModifier
+ baseWalkSpeed : 5
+ baseSprintSpeed : 5
+ - type: DamageStateVisuals
+ states:
+ Alive:
+ Base: headslug
+ Critical:
+ Base: headslug_dead
+ Dead:
+ Base: headslug_dead
+ - type: Food
+ # - type: Tag
+ # tags:
+ # - ShoesRequiredStepTriggerImmune # По-моему из за этой хуйни падал сервер
+ - type: Respirator
+ damage:
+ types:
+ Asphyxiation: 0.25
+ damageRecovery:
+ types:
+ Asphyxiation: -0.25
+ - type: Barotrauma
+ damage:
+ types:
+ Blunt: 0.1
+ - type: Vocal
+ sounds:
+ Male: Mouse
+ Female: Mouse
+ Unsexed: Mouse
+ wilhelmProbability: 0.001
+ - type: CombatMode
+ - type: Bloodstream
+ bloodMaxVolume: 50
+ - type: CanEscapeInventory
+ - type: MobPrice
+ price: 5000
+ - type: BadFood
+ - type: NonSpreaderZombie
+ - type: LanguageSpeaker # Frontier
+ speaks:
+ - Xeno
+ understands:
+ - Xeno
+ - type: MeleeWeapon
+ soundHit:
+ path: /Audio/Weapons/pierce.ogg
+ angle: 30
+ animation: WeaponArcPunch
+ damage:
+ types:
+ Piercing: 7
+ - type: ChangelingHeadslug
diff --git a/Resources/Prototypes/ADT/Entities/Mobs/Species/ipc.yml b/Resources/Prototypes/ADT/Entities/Mobs/Species/ipc.yml
index 3c7fadf86cb..5a1b672fec6 100644
--- a/Resources/Prototypes/ADT/Entities/Mobs/Species/ipc.yml
+++ b/Resources/Prototypes/ADT/Entities/Mobs/Species/ipc.yml
@@ -118,11 +118,12 @@
- RobotTalk
- type: Tag
tags:
- # - ChangelingBlacklist
# - ShoesRequiredStepTriggerImmune
- CanPilot
- FootstepSound
- DoorBumpOpener
+ - ChangelingBlacklist
+ - ADTSiliconStealthWhitelist
- type: Inventory
templateId: ipc
- type: SizeAttributeWhitelist # Frontier
diff --git a/Resources/Prototypes/ADT/Entities/Mobs/Species/novakid.yml b/Resources/Prototypes/ADT/Entities/Mobs/Species/novakid.yml
index 1b369b201aa..77f1f16b3b0 100644
--- a/Resources/Prototypes/ADT/Entities/Mobs/Species/novakid.yml
+++ b/Resources/Prototypes/ADT/Entities/Mobs/Species/novakid.yml
@@ -154,6 +154,13 @@
shortscale: 0.9
- type: BloodCough
postingSayDamage: blood-cough-novakid
+ - type: Tag
+ tags:
+ - CanPilot
+ - FootstepSound
+ - DoorBumpOpener
+ - AnomalyHost
+ - ChangelingBlacklist
- type: entity
save: false
diff --git a/Resources/Prototypes/ADT/Entities/Objects/Shields/changeling_shield.yml b/Resources/Prototypes/ADT/Entities/Objects/Shields/changeling_shield.yml
new file mode 100644
index 00000000000..7eddc7e7515
--- /dev/null
+++ b/Resources/Prototypes/ADT/Entities/Objects/Shields/changeling_shield.yml
@@ -0,0 +1,38 @@
+- type: entity
+ name: armshield
+ parent: BaseItem
+ id: ADTArmShield
+ description: Meat.
+ components:
+ - type: Sprite
+ sprite: ADT/Changeling/Objects/armshield.rsi
+ state: icon
+ - type: Item
+ sprite: ADT/Changeling/Objects/armshield.rsi
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ right:
+ - state: inhand-right
+ size: Ginormous
+ - type: Blocking
+ passiveBlockModifier:
+ coefficients:
+ Blunt: 0.85
+ Slash: 0.85
+ Piercing: 0.85
+ Heat: 0.8
+ activeBlockModifier:
+ coefficients:
+ Blunt: 0.75
+ Slash: 0.75
+ Piercing: 0.75
+ Heat: 0.7
+ flatReductions:
+ Blunt: 0.5
+ Slash: 0.5
+ Piercing: 0.5
+ Heat: 1
+ - type: Damageable
+ damageContainer: Shield
+ - type: ChangelingShield
diff --git a/Resources/Prototypes/ADT/Entities/Objects/Shields/fill.txt b/Resources/Prototypes/ADT/Entities/Objects/Shields/fill.txt
deleted file mode 100644
index b4954caf47d..00000000000
--- a/Resources/Prototypes/ADT/Entities/Objects/Shields/fill.txt
+++ /dev/null
@@ -1 +0,0 @@
-# Данный файл существует по причине того что Githab плохо дружит с пустыми папками, при работе с этой папкой этот файл можно спокойно удалить
\ No newline at end of file
diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/changeling.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/changeling.yml
new file mode 100644
index 00000000000..f7e686b0e5c
--- /dev/null
+++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/changeling.yml
@@ -0,0 +1,71 @@
+- type: entity
+ name: arm blade
+ parent: BaseKnife
+ id: ADTArmBlade
+ description: A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter.
+ components:
+ - type: Sprite
+ sprite: ADT/Changeling/Objects/armblade.rsi
+ state: icon
+ - type: MeleeWeapon
+ wideAnimationRotation: 90
+ attackRate: 0.75
+ damage:
+ types:
+ Slash: 25
+ Piercing: 15
+ - type: Item
+ size: Ginormous
+ sprite: ADT/Changeling/Objects/armblade.rsi
+ - type: Tool
+ qualities:
+ - Prying
+ - Slicing
+ speedModifier: 0.5
+ - type: Prying
+ pryPowered: true
+ - type: DisarmMalus
+ malus: 0
+ - type: Reflect
+ reflectProb: 0.5
+
+- type: entity
+ name: arm mace
+ parent: BaseItem
+ id: ADTArmace
+ description: Meat.
+ components:
+ - type: Sprite
+ sprite: ADT/Changeling/Objects/armmace.rsi
+ state: icon
+ - type: MeleeWeapon
+ attackRate: 0.5
+ wideAnimationRotation: -135
+ damage:
+ types:
+ Blunt: 25
+ Structural: 60
+ soundHit:
+ collection: MetalThud
+ - type: Item
+ size: Ginormous
+ sprite: ADT/Changeling/Objects/armmace.rsi
+ inhandVisuals:
+ left:
+ - state: inhand-left
+ right:
+ - state: inhand-right
+ - type: Tool
+ qualities:
+ - Rolling
+ speedModifier: 0.75
+ - type: MeleeThrowOnHit
+ speed: 15
+ lifetime: 0.15
+ collideDamage:
+ types:
+ Blunt: 12
+ toCollideDamage:
+ types:
+ Structural: 75
+ downOnHit: false
diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/fill.txt b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/fill.txt
deleted file mode 100644
index b4954caf47d..00000000000
--- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/fill.txt
+++ /dev/null
@@ -1 +0,0 @@
-# Данный файл существует по причине того что Githab плохо дружит с пустыми папками, при работе с этой папкой этот файл можно спокойно удалить
\ No newline at end of file
diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/throwing_stars.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/throwing_stars.yml
new file mode 100644
index 00000000000..2fbe4a65fdb
--- /dev/null
+++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Throwable/throwing_stars.yml
@@ -0,0 +1,12 @@
+- type: entity
+ parent: ThrowingStar
+ id: ADTThrowingStarChangeling
+ name: bone shard
+ components:
+ - type: Sprite
+ sprite: ADT/Changeling/Objects/bone_shard.rsi
+ layers:
+ - state: icon
+ map: ["base"]
+ - type: TimedDespawn
+ lifetime: 30
diff --git a/Resources/Prototypes/ADT/GameRules/fill.txt b/Resources/Prototypes/ADT/GameRules/fill.txt
deleted file mode 100644
index b4954caf47d..00000000000
--- a/Resources/Prototypes/ADT/GameRules/fill.txt
+++ /dev/null
@@ -1 +0,0 @@
-# Данный файл существует по причине того что Githab плохо дружит с пустыми папками, при работе с этой папкой этот файл можно спокойно удалить
\ No newline at end of file
diff --git a/Resources/Prototypes/ADT/GameRules/roundstart.yml b/Resources/Prototypes/ADT/GameRules/roundstart.yml
index ef5a870356d..164028a7d16 100644
--- a/Resources/Prototypes/ADT/GameRules/roundstart.yml
+++ b/Resources/Prototypes/ADT/GameRules/roundstart.yml
@@ -92,3 +92,31 @@
- type: BasicStationEventScheduler
scheduledGameRules: !type:NestedSelector
tableId: ExtendedGameRulesTable
+
+- type: entity
+ parent: BaseGameRule
+ id: ChangelingGameRule
+ components:
+ - type: ChangelingRule
+ - type: GameRule
+ minPlayers: 20
+ - type: AntagSelection
+ definitions:
+ - prefRoles: [ Changeling ]
+ max: 5
+ playerRatio: 15
+ blacklist:
+ components:
+ - AntagImmune
+ tags:
+ - ChangelingBlacklist
+ lateJoinAdditional: true
+ mindRoles:
+ - MindRoleChangeling
+ components:
+ - type: Changeling
+ agentName: ling-round-end-name
+ - type: AntagRandomObjectives
+ sets:
+ - groups: ChangelingObjectiveGroups
+ maxDifficulty: 5
diff --git a/Resources/Prototypes/ADT/Objectives/changeling.yml b/Resources/Prototypes/ADT/Objectives/changeling.yml
new file mode 100644
index 00000000000..0dba8675f47
--- /dev/null
+++ b/Resources/Prototypes/ADT/Objectives/changeling.yml
@@ -0,0 +1,130 @@
+- type: entity
+ abstract: true
+ parent: BaseObjective
+ id: BaseChangelingObjective
+ components:
+ - type: Objective
+ issuer: changeling-issuer
+ - type: RoleRequirement
+ roles:
+ mindRoles:
+ - ChangelingRole
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: [BaseChangelingObjective, BaseLivingObjective]
+ id: DnaAbsorbObjective
+ name: Absorb 4 DNAs.
+ components:
+ - type: Objective
+ difficulty: 1.5
+ unique: true
+ icon:
+ sprite: ADT/Changeling/Actions/actions_ling.rsi
+ state: absorb_dna
+ - type: AbsorbDnaCondition
+ objectiveText: absorb-dna-name
+ descriptionText: absorb-dna-desc
+
+- type: entity
+ abstract: true
+ parent: BaseTargetObjective
+ id: BasePersonalityStealObjective
+ components:
+ - type: Objective
+ unique: false
+ icon:
+ sprite: Objects/Weapons/Guns/Pistols/viper.rsi
+ state: icon
+ - type: ObjectiveBlacklistRequirement
+ blacklist:
+ components:
+ - SocialObjective
+ - type: StealPersonalityCondition
+ requireDead: true
+ - type: PickRandomDna
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: [BaseChangelingObjective, BaseLivingObjective]
+ id: EscapeLingShuttleObjective
+ name: Escape to centcom alive and unrestrained.
+ description: We must get to central command.
+ components:
+ - type: Objective
+ difficulty: 1.2
+ icon:
+ sprite: Structures/Furniture/chairs.rsi
+ state: shuttle
+ - type: EscapeShuttleCondition
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: [BaseChangelingObjective, BaseKillObjective]
+ id: KillRandomPersonObjectiveLing
+ description: ling-kill-desc
+ components:
+ - type: Objective
+ difficulty: 1.5
+ unique: false
+ - type: TargetObjective
+ title: objective-condition-kill-person-title
+ - type: PickRandomPerson
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: [BaseChangelingObjective, BasePersonalityStealObjective]
+ id: StealRandomPersonalityObjectiveLing
+ description: ling-steal-personality-desc
+ components:
+ - type: Objective
+ difficulty: 2
+ unique: true
+ - type: TargetObjective
+ title: objective-condition-steal-head-personality-title
+ - type: PickRandomPerson
+
+#- type: entity
+# categories: [ HideSpawnMenu ]
+# parent: [BaseChangelingObjective, BasePersonalityStealObjective]
+# id: StealRandomHeadPersonalityObjectiveLing
+# description: ling-steal-personality-desc
+# components:
+# - type: Objective
+# difficulty: 1.5
+# unique: false
+# - type: TargetObjective
+# title: objective-condition-steal-head-personality-title
+# - type: PickRandomHead
+# - type: StealPersonalityCondition
+# requireDead: true
+
+- type: entity
+ abstract: true
+ parent: [BaseChangelingObjective, BaseStealObjective]
+ id: BaseChangelingStealObjective
+ components:
+ - type: StealCondition
+ verifyMapExistance: false
+ - type: Objective
+ difficulty: 2.5
+ - type: ObjectiveLimit
+ limit: 1
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: BaseChangelingStealObjective
+ id: CommandIDStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: CommandIDCard
+ descriptionText: objective-condition-changeling-commandidcard
+
+- type: entity
+ categories: [ HideSpawnMenu ]
+ parent: BaseChangelingStealObjective
+ id: SmileExtractStealObjective
+ components:
+ - type: StealCondition
+ stealGroup: MaterialSmileExtract
+ descriptionText: objective-condition-changeling-smileextract
diff --git a/Resources/Prototypes/ADT/Objectives/objectiveGroups.yml b/Resources/Prototypes/ADT/Objectives/objectiveGroups.yml
index 2cc51a10afe..e9e2806ced4 100644
--- a/Resources/Prototypes/ADT/Objectives/objectiveGroups.yml
+++ b/Resources/Prototypes/ADT/Objectives/objectiveGroups.yml
@@ -26,3 +26,40 @@
PhantomStartNightmareObjective: 1
PhantomReincarnateObjective: 1
PhantomTyranyObjective: 1
+
+# Changeling
+- type: weightedRandom
+ id: ChangelingObjectiveGroups
+ weights:
+ ChangelingObjectiveGroupKill: 1
+ ChangelingObjectiveGroupState: 1
+ ChangelingObjectiveGroupSteal: 1
+ ChangelingObjectiveGroupPersonalitySteal: 1
+ ChangelingObjectiveGroupAbsorbDna: 1 # почему ты блять не работаешь
+
+- type: weightedRandom
+ id: ChangelingObjectiveGroupSteal
+ weights:
+ CommandIDStealObjective: 1
+ SmileExtractStealObjective: 1
+
+- type: weightedRandom
+ id: ChangelingObjectiveGroupKill
+ weights:
+ KillRandomPersonObjectiveLing: 1
+
+- type: weightedRandom
+ id: ChangelingObjectiveGroupState
+ weights:
+ EscapeLingShuttleObjective: 1
+
+- type: weightedRandom
+ id: ChangelingObjectiveGroupPersonalitySteal
+ weights:
+ StealRandomPersonalityObjectiveLing: 1
+ #StealRandomHeadPersonalityObjectiveLing: 1
+
+- type: weightedRandom
+ id: ChangelingObjectiveGroupAbsorbDna
+ weights:
+ DnaAbsorbObjective: 1
diff --git a/Resources/Prototypes/ADT/Objectives/stealTargetGroups.yml b/Resources/Prototypes/ADT/Objectives/stealTargetGroups.yml
index d6398f274cb..39e307d07e3 100644
--- a/Resources/Prototypes/ADT/Objectives/stealTargetGroups.yml
+++ b/Resources/Prototypes/ADT/Objectives/stealTargetGroups.yml
@@ -19,3 +19,19 @@
sprite:
sprite: ADT/Clothing/Mask/gasCE.rsi
state: icon
+
+# changeling
+
+- type: stealTargetGroup
+ id: CommandIDCard
+ name: steal-target-groups-command-id
+ sprite:
+ sprite: Objects/Misc/id_cards.rsi
+ state: silver
+
+- type: stealTargetGroup
+ id: MaterialSmileExtract
+ name: steal-target-groups-smile-extract
+ sprite:
+ sprite: Mobs/Aliens/slimes.rsi
+ state: rainbow_slime_extract
diff --git a/Resources/Prototypes/ADT/Reagents/medicine.yml b/Resources/Prototypes/ADT/Reagents/medicine.yml
index 0ebe71fdb99..06f0998b9fe 100644
--- a/Resources/Prototypes/ADT/Reagents/medicine.yml
+++ b/Resources/Prototypes/ADT/Reagents/medicine.yml
@@ -420,6 +420,10 @@
type: Add
time: 2.5
refresh: false
+ - !type:HallucinationsReagentEffect
+ proto: Changeling
+ type: Remove
+ time: 7
- !type:PopupMessage
type: Local
visualType: Small
diff --git a/Resources/Prototypes/ADT/Reagents/narcotics.yml b/Resources/Prototypes/ADT/Reagents/narcotics.yml
index aaff83a34d4..c2c32fbfec3 100644
--- a/Resources/Prototypes/ADT/Reagents/narcotics.yml
+++ b/Resources/Prototypes/ADT/Reagents/narcotics.yml
@@ -67,30 +67,3 @@
types:
Poison: 2
# End edit by Filo
-
-- type: reagent
- id: LingDrugs
- name: reagent-name-space-drugs
- group: Narcotics
- desc: reagent-desc-space-drugs
- physicalDesc: reagent-physical-desc-syrupy
- flavor: bitter
- color: "#63806e"
- metabolisms:
- Narcotic:
- effects:
- - !type:GenericStatusEffect
- key: SeeingRainbows
- component: SeeingRainbows
- type: Add
- time: 5
- refresh: false
- - !type:GenericStatusEffect
- key: ADTHallucinations
- component: LingHallucinations
- type: Add
- time: 10
- refresh: false
- conditions:
- - !type:ReagentThreshold
- min: 15
diff --git a/Resources/Prototypes/ADT/Roles/Antags/changeling.yml b/Resources/Prototypes/ADT/Roles/Antags/changeling.yml
new file mode 100644
index 00000000000..455cf0f73ad
--- /dev/null
+++ b/Resources/Prototypes/ADT/Roles/Antags/changeling.yml
@@ -0,0 +1,10 @@
+- type: antag
+ id: Changeling
+ name: roles-antag-changeling-name
+ antagonist: true
+ setPreference: true
+ objective: roles-antag-changeling-objective
+ requirements:
+ - !type:OverallPlaytimeRequirement
+ time: 270000 #75 hrs
+ #guides: [ Heretics ] закомменчено до появления гайда
diff --git a/Resources/Prototypes/ADT/Roles/Antags/fill.txt b/Resources/Prototypes/ADT/Roles/Antags/fill.txt
deleted file mode 100644
index b4954caf47d..00000000000
--- a/Resources/Prototypes/ADT/Roles/Antags/fill.txt
+++ /dev/null
@@ -1 +0,0 @@
-# Данный файл существует по причине того что Githab плохо дружит с пустыми папками, при работе с этой папкой этот файл можно спокойно удалить
\ No newline at end of file
diff --git a/Resources/Prototypes/ADT/Roles/MindRoles/mind_roles.yml b/Resources/Prototypes/ADT/Roles/MindRoles/mind_roles.yml
index b320ce4d340..761562b63a1 100644
--- a/Resources/Prototypes/ADT/Roles/MindRoles/mind_roles.yml
+++ b/Resources/Prototypes/ADT/Roles/MindRoles/mind_roles.yml
@@ -20,3 +20,13 @@
antagPrototype: Heretic
exclusiveAntag: true
- type: HereticRole
+
+- type: entity
+ parent: BaseMindRoleAntag
+ id: MindRoleChangeling
+ name: Changeling Role
+ components:
+ - type: MindRole
+ antagPrototype: Changeling
+ exclusiveAntag: true
+ - type: ChangelingRole
diff --git a/Resources/Prototypes/ADT/Store/categories.yml b/Resources/Prototypes/ADT/Store/categories.yml
index f451cd24eda..aa8afce3f82 100644
--- a/Resources/Prototypes/ADT/Store/categories.yml
+++ b/Resources/Prototypes/ADT/Store/categories.yml
@@ -7,3 +7,8 @@
id: ADTUplinkERTMisc
name: прочее
priority: 2
+
+#ling
+- type: storeCategory
+ id: ChangelingAbilities
+ name: store-category-abilities
diff --git a/Resources/Prototypes/ADT/Store/currency.yml b/Resources/Prototypes/ADT/Store/currency.yml
index 12759541855..4c5f0b30ef2 100644
--- a/Resources/Prototypes/ADT/Store/currency.yml
+++ b/Resources/Prototypes/ADT/Store/currency.yml
@@ -4,3 +4,8 @@
cash :
1: SpaceCash
displayName: store-currency-display-space-cash
+
+- type: currency
+ id: EvolutionPoints
+ displayName: store-currency-display-evolution-points
+ canWithdraw: false
diff --git a/Resources/Prototypes/ADT/game_presets.yml b/Resources/Prototypes/ADT/game_presets.yml
index 141223d7e03..491ec77c556 100644
--- a/Resources/Prototypes/ADT/game_presets.yml
+++ b/Resources/Prototypes/ADT/game_presets.yml
@@ -28,3 +28,18 @@
- SubGamemodesRule
- BasicStationEventScheduler
- MeteorSwarmScheduler
+
+- type: gamePreset
+ id: Changeling
+ alias:
+ - changeling
+ name: changelings-title
+ minPlayers: 25
+ showInVote: true
+ description: changelings-description
+ rules:
+ - ChangelingGameRule
+ - BasicRoundstartVariation
+ - SubGamemodesRule
+ - BasicStationEventScheduler
+ - MeteorSwarmScheduler
diff --git a/Resources/Prototypes/ADT/tags.yml b/Resources/Prototypes/ADT/tags.yml
index 9f0eb2c5542..9de14c84fe7 100644
--- a/Resources/Prototypes/ADT/tags.yml
+++ b/Resources/Prototypes/ADT/tags.yml
@@ -139,6 +139,15 @@
- type: Tag
id: ADTMagazineRifleAR12
+- type: Tag
+ id: ChangelingBlacklist
+
+- type: Tag
+ id: MaskBlocker
+
+- type: Tag
+ id: GlassesBlocker
+
- type: Tag
id: ADTMobileDefibrillator
@@ -157,6 +166,9 @@
- type: Tag
id: ADTMedipen
+- type: Tag
+ id: ADTSiliconStealthWhitelist
+
- type: Tag
id: ADTCandies
diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml
index d80e36bde1f..500fac01ace 100644
--- a/Resources/Prototypes/Actions/types.yml
+++ b/Resources/Prototypes/Actions/types.yml
@@ -19,6 +19,7 @@
icon: Interface/Actions/scream.png
event: !type:ScreamActionEvent
checkCanInteract: false
+ priority: -99 # ADT tweak
- type: entity
id: ActionTurnUndead
diff --git a/Resources/Prototypes/Alerts/alerts.yml b/Resources/Prototypes/Alerts/alerts.yml
index bc1fc1a08c0..a5340d9a8a8 100644
--- a/Resources/Prototypes/Alerts/alerts.yml
+++ b/Resources/Prototypes/Alerts/alerts.yml
@@ -25,6 +25,7 @@
- alertType: Magboots
- alertType: Pacified
- alertType: Crawling #ADT crawling
+ - alertType: Chemicals # ADT Changeling
- type: entity
id: AlertSpriteView
categories: [ HideSpawnMenu ]
diff --git a/Resources/Prototypes/Corvax/Entities/Stations/nanotrasen.yml b/Resources/Prototypes/Corvax/Entities/Stations/nanotrasen.yml
index d636cc5229c..17bdd5a6e72 100644
--- a/Resources/Prototypes/Corvax/Entities/Stations/nanotrasen.yml
+++ b/Resources/Prototypes/Corvax/Entities/Stations/nanotrasen.yml
@@ -41,7 +41,7 @@
- /Maps/Ruins/corvax_ore.yml
- /Maps/Ruins/corvax_research_station.yml
- /Maps/Ruins/corvax_rnd_debris.yml
- - /Maps/Ruins/corvax_sanctus.yml
+ # - /Maps/Ruins/corvax_sanctus.yml
- /Maps/Ruins/corvax_syndi_base.yml
- /Maps/Ruins/corvax_ussp_debris.yml
- /Maps/Ruins/corvax_ussp_asteroid.yml
diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
index ee30bd26387..2276040495f 100644
--- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
+++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
@@ -247,6 +247,7 @@
- DoorBumpOpener
- FootstepSound
- CanPilot
+ - ADTSiliconStealthWhitelist # ADT tweak
- type: Emoting
# ADT-CollectiveMind-Tweak-Start
- type: CollectiveMind
diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
index 35946628e5b..2b48d9ff352 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
@@ -400,6 +400,8 @@
- HideContextMenu
- StationAi
- NoConsoleSound
+ - ADTSiliconStealthWhitelist # ADT tweak
+
# Start-ADT-Tweak: Ai chat
- type: HighlightWordsInChat
highlightWords:
diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml
index c9e85b124e5..b4f315a4124 100644
--- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml
+++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml
@@ -36,6 +36,8 @@
enum.SlimeHairUiKey.Key:
type: SlimeHairBoundUserInterface
# ADT-SlimeHair-End
+ enum.StoreUiKey.Key: # Чтобы не ломался генокрад
+ type: StoreBoundUserInterface # Чтобы не ломался генокрад
# to prevent bag open/honk spam
- type: UseDelay
delay: 0.5
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
index 612f7da0472..ac4d1cc3ac2 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
@@ -734,6 +734,8 @@
- type: Tag
tags:
- Meat
+ - type: StealTarget
+ stealGroup: MaterialSmileExtract
- type: entity
name: steak
diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
index 57a600b088b..60a629d81bf 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
@@ -229,6 +229,8 @@
heldPrefix: silver
- type: PresetIdCard
job: Quartermaster
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
@@ -376,6 +378,8 @@
heldPrefix: silver
- type: PresetIdCard
job: HeadOfPersonnel
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
@@ -390,6 +394,8 @@
heldPrefix: silver
- type: PresetIdCard
job: ChiefEngineer
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
@@ -404,6 +410,8 @@
heldPrefix: silver
- type: PresetIdCard
job: ChiefMedicalOfficer
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
@@ -418,6 +426,8 @@
heldPrefix: silver
- type: PresetIdCard
job: ResearchDirector
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
@@ -432,6 +442,8 @@
heldPrefix: silver
- type: PresetIdCard
job: HeadOfSecurity
+ - type: StealTarget
+ stealGroup: CommandIDCard
- type: entity
parent: IDCardStandard
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml
index 398c04aee6e..60fee93ac30 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml
@@ -1,23 +1,23 @@
-- type: entity
- name: arm blade
- parent: BaseItem
- id: ArmBlade
- description: A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter.
- components:
- - type: Sharp
- - type: Execution
- doAfterDuration: 4.0
- - type: Sprite
- sprite: Objects/Weapons/Melee/armblade.rsi
- state: icon
- - type: MeleeWeapon
- wideAnimationRotation: 90
- attackRate: 0.75
- damage:
- types:
- Slash: 25
- Piercing: 15
- - type: Item
- size: Normal
- sprite: Objects/Weapons/Melee/armblade.rsi
- - type: Prying
+# - type: entity
+# name: arm blade
+# parent: BaseItem
+# id: ArmBlade
+# description: A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter.
+# components:
+# - type: Sharp
+# - type: Execution
+# doAfterDuration: 4.0
+# - type: Sprite
+# sprite: Objects/Weapons/Melee/armblade.rsi
+# state: icon
+# - type: MeleeWeapon
+# wideAnimationRotation: 90
+# attackRate: 0.75
+# damage:
+# types:
+# Slash: 25
+# Piercing: 15
+# - type: Item
+# size: Normal
+# sprite: Objects/Weapons/Melee/armblade.rsi
+# - type: Prying
diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml
index 4f97136b1c6..b83b5d3998f 100644
--- a/Resources/Prototypes/Entities/Stations/base.yml
+++ b/Resources/Prototypes/Entities/Stations/base.yml
@@ -77,7 +77,7 @@
- /Maps/Ruins/corvax_ore.yml
- /Maps/Ruins/corvax_research_station.yml
- /Maps/Ruins/corvax_rnd_debris.yml
- - /Maps/Ruins/corvax_sanctus.yml
+ # - /Maps/Ruins/corvax_sanctus.yml
- /Maps/Ruins/corvax_syndi_base.yml
- /Maps/Ruins/corvax_ussp_debris.yml
- /Maps/Ruins/corvax_ussp_asteroid.yml
diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml
index dc41238a69b..38379b24309 100644
--- a/Resources/Prototypes/GameRules/roundstart.yml
+++ b/Resources/Prototypes/GameRules/roundstart.yml
@@ -24,6 +24,8 @@
prob: 0.5
- id: HereticGameRule # goob edit
prob: 0.2
+ - id: ChangelingGameRule # ADT-Changeling-Tweak
+ prob: 0.1
- type: entity
id: DeathMatch31
diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml
index 651e750eec7..cbc3fba6950 100644
--- a/Resources/Prototypes/Reagents/narcotics.yml
+++ b/Resources/Prototypes/Reagents/narcotics.yml
@@ -261,6 +261,11 @@
type: Add
time: 16
refresh: false
+ - !type:HallucinationsReagentEffect
+ proto: Changeling
+ type: Add
+ time: 4
+ refresh: false
- type: reagent
id: Nicotine
@@ -321,6 +326,11 @@
type: Add
time: 5
refresh: false
+ - !type:HallucinationsReagentEffect
+ proto: Changeling
+ type: Add
+ time: 4
+ refresh: false
- type: reagent
id: Bananadine
@@ -339,6 +349,11 @@
type: Add
time: 5
refresh: false
+ - !type:HallucinationsReagentEffect
+ proto: Changeling
+ type: Add
+ time: 4
+ refresh: false
# Probably replace this one with sleeping chem when putting someone in a comatose state is easier
- type: reagent
@@ -521,3 +536,8 @@
type: Add
time: 5
refresh: false
+ - !type:HallucinationsReagentEffect
+ proto: Changeling
+ type: Add
+ time: 4
+ refresh: false
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/absorb_dna.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/absorb_dna.png
new file mode 100644
index 00000000000..c7a65d00495
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/absorb_dna.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/adrenaline.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/adrenaline.png
new file mode 100644
index 00000000000..744864efc46
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/adrenaline.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armblade.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armblade.png
new file mode 100644
index 00000000000..eda9084981e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armblade.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armhammer.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armhammer.png
new file mode 100644
index 00000000000..0f1ff31e34f
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/armhammer.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/augmented_eyesight.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/augmented_eyesight.png
new file mode 100644
index 00000000000..857f8414d4a
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/augmented_eyesight.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/background.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/background.png
new file mode 100644
index 00000000000..6fd7d2db6f2
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/background.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/biodegrade.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/biodegrade.png
new file mode 100644
index 00000000000..3b143b37d99
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/biodegrade.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/bone_shard.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/bone_shard.png
new file mode 100644
index 00000000000..8bc52989a4c
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/bone_shard.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chameleon_skin.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chameleon_skin.png
new file mode 100644
index 00000000000..c355d8485a8
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chameleon_skin.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changeling_channel.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changeling_channel.png
new file mode 100644
index 00000000000..845c212dc5a
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changeling_channel.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changelingsting.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changelingsting.png
new file mode 100644
index 00000000000..1c39f4f8254
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/changelingsting.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chitinous_armor.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chitinous_armor.png
new file mode 100644
index 00000000000..7c41fb0cc9d
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/chitinous_armor.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/darkness_adaptation.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/darkness_adaptation.png
new file mode 100644
index 00000000000..995c23e6f72
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/darkness_adaptation.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/digital_camo.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/digital_camo.png
new file mode 100644
index 00000000000..73b523dc5b3
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/digital_camo.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/dissonant_shriek.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/dissonant_shriek.png
new file mode 100644
index 00000000000..50254888796
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/dissonant_shriek.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fake_death.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fake_death.png
new file mode 100644
index 00000000000..103fbd4d171
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fake_death.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fleshmend.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fleshmend.png
new file mode 100644
index 00000000000..b5b78d62d98
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/fleshmend.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_absorb.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_absorb.png
new file mode 100644
index 00000000000..e0846bca05a
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_absorb.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_head.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_head.png
new file mode 100644
index 00000000000..e55dcda0d66
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_head.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_link.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_link.png
new file mode 100644
index 00000000000..a16cd75c94e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/hive_link.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/human_form.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/human_form.png
new file mode 100644
index 00000000000..1b814a7ee0c
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/human_form.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/last_resort.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/last_resort.png
new file mode 100644
index 00000000000..6e2be0b2121
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/last_resort.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/lesser_form.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/lesser_form.png
new file mode 100644
index 00000000000..7edf36065c0
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/lesser_form.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/meta.json b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/meta.json
new file mode 100644
index 00000000000..aac08bf1f0c
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/meta.json
@@ -0,0 +1,134 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "taken from tg at https://github.com/tgstation/tgstation/commit/3e9ea4d77cdf4173777e665b2b4f4ba8cecf2c03#diff-06a6d3876124f6bb0adf70a4dffab8d82b9a7ae0abf9ec0ebc22211ca9d8ad4b. Sprites made by KREKS (#.kreks. discord), ported to Space Station 14 by Username228 (#serj3428 discord)",
+ "states": [
+ {
+ "name": "absorb_dna"
+ },
+ {
+ "name": "adrenaline"
+ },
+ {
+ "name": "armblade"
+ },
+ {
+ "name": "augmented_eyesight"
+ },
+ {
+ "name": "biodegrade"
+ },
+ {
+ "name": "chameleon_skin"
+ },
+ {
+ "name": "changeling_channel"
+ },
+ {
+ "name": "chitinous_armor"
+ },
+ {
+ "name": "changelingsting"
+ },
+ {
+ "name": "darkness_adaptation"
+ },
+ {
+ "name": "digital_camo"
+ },
+ {
+ "name": "dissonant_shriek"
+ },
+ {
+ "name": "fake_death"
+ },
+ {
+ "name": "fleshmend"
+ },
+ {
+ "name": "hive_absorb"
+ },
+ {
+ "name": "hive_head"
+ },
+ {
+ "name": "hive_link"
+ },
+ {
+ "name": "human_form"
+ },
+ {
+ "name": "lesser_form"
+ },
+ {
+ "name": "last_resort"
+ },
+ {
+ "name": "mimic_voice"
+ },
+ {
+ "name": "organic_shield"
+ },
+ {
+ "name": "organic_suit"
+ },
+ {
+ "name": "panacea"
+ },
+ {
+ "name": "regenerate"
+ },
+ {
+ "name": "resonant_shriek"
+ },
+ {
+ "name": "revive"
+ },
+ {
+ "name": "spread_infestation"
+ },
+ {
+ "name": "sting_armblade"
+ },
+ {
+ "name": "sting_blind"
+ },
+ {
+ "name": "sting_cryo"
+ },
+ {
+ "name": "sting_extract"
+ },
+ {
+ "name": "sting_lsd"
+ },
+ {
+ "name": "sting_mute"
+ },
+ {
+ "name": "sting_transform"
+ },
+ {
+ "name": "strained_muscles"
+ },
+ {
+ "name": "tentacle"
+ },
+ {
+ "name": "transform"
+ },
+ {
+ "name": "armhammer"
+ },
+ {
+ "name": "background"
+ },
+ {
+ "name": "bone_shard"
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/mimic_voice.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/mimic_voice.png
new file mode 100644
index 00000000000..8e36b8cbfa6
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/mimic_voice.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_shield.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_shield.png
new file mode 100644
index 00000000000..60275564cc3
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_shield.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_suit.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_suit.png
new file mode 100644
index 00000000000..61fb8fe845e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/organic_suit.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/panacea.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/panacea.png
new file mode 100644
index 00000000000..df37fd67203
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/panacea.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/regenerate.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/regenerate.png
new file mode 100644
index 00000000000..26cc976c52c
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/regenerate.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/resonant_shriek.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/resonant_shriek.png
new file mode 100644
index 00000000000..3a3d222b312
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/resonant_shriek.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/revive.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/revive.png
new file mode 100644
index 00000000000..ad3b4da407e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/revive.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/spread_infestation.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/spread_infestation.png
new file mode 100644
index 00000000000..5550b21eddc
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/spread_infestation.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_armblade.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_armblade.png
new file mode 100644
index 00000000000..fbb06b86037
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_armblade.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_blind.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_blind.png
new file mode 100644
index 00000000000..0f3ae0e4e20
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_blind.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_cryo.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_cryo.png
new file mode 100644
index 00000000000..81c10e6ed13
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_cryo.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_extract.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_extract.png
new file mode 100644
index 00000000000..26c2a105317
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_extract.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_lsd.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_lsd.png
new file mode 100644
index 00000000000..dc8b67b2003
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_lsd.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_mute.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_mute.png
new file mode 100644
index 00000000000..fbe83cc881a
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_mute.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_transform.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_transform.png
new file mode 100644
index 00000000000..e6cb0c82dde
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/sting_transform.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/strained_muscles.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/strained_muscles.png
new file mode 100644
index 00000000000..f6a5cadb423
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/strained_muscles.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/tentacle.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/tentacle.png
new file mode 100644
index 00000000000..3ebf73396a7
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/tentacle.png differ
diff --git a/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/transform.png b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/transform.png
new file mode 100644
index 00000000000..b53771f4581
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Actions/actions_ling.rsi/transform.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals0.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals0.png
new file mode 100644
index 00000000000..5d4f1b73098
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals0.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals1.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals1.png
new file mode 100644
index 00000000000..b59f46bf28e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals1.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals2.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals2.png
new file mode 100644
index 00000000000..8b333510621
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals2.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals3.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals3.png
new file mode 100644
index 00000000000..7d22c2a9b6f
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals3.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals4.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals4.png
new file mode 100644
index 00000000000..98f6fc0764a
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals4.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals5.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals5.png
new file mode 100644
index 00000000000..11252a4c16c
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals5.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals6.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals6.png
new file mode 100644
index 00000000000..36211437c09
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals6.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals7.png b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals7.png
new file mode 100644
index 00000000000..6c93a576e35
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/chemicals7.png differ
diff --git a/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/meta.json b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/meta.json
new file mode 100644
index 00000000000..5463dcfdfab
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Alerts/chemicals_counter.rsi/meta.json
@@ -0,0 +1,35 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by Dutch-VanDerLinde (github)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "chemicals0"
+ },
+ {
+ "name": "chemicals1"
+ },
+ {
+ "name": "chemicals2"
+ },
+ {
+ "name": "chemicals3"
+ },
+ {
+ "name": "chemicals4"
+ },
+ {
+ "name": "chemicals5"
+ },
+ {
+ "name": "chemicals6"
+ },
+ {
+ "name": "chemicals7"
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug.png b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug.png
new file mode 100644
index 00000000000..65a29e5423f
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug.png differ
diff --git a/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug_dead.png b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug_dead.png
new file mode 100644
index 00000000000..5aebe0014ff
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/headslug_dead.png differ
diff --git a/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/meta.json b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/meta.json
new file mode 100644
index 00000000000..07396b10887
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Mobs/headslug.rsi/meta.json
@@ -0,0 +1,18 @@
+{
+ "version": 1,
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from https://github.com/tgstation/tgstation/blob/master/icons/mob/simple/animal.dmi",
+ "states": [
+ {
+ "name": "headslug",
+ "directions": 4
+ },
+ {
+ "name": "headslug_dead"
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/icon.png b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/icon.png
new file mode 100644
index 00000000000..d362e6d1f43
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/icon.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-left.png b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-left.png
new file mode 100644
index 00000000000..759aa26500e
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-left.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-right.png b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-right.png
new file mode 100644
index 00000000000..0f8b2404f82
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/inhand-right.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/meta.json b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/meta.json
new file mode 100644
index 00000000000..715d260a1be
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Objects/armblade.rsi/meta.json
@@ -0,0 +1,82 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "taken from tg at https://github.com/tgstation/tgstation/commit/3e9ea4d77cdf4173777e665b2b4f4ba8cecf2c03#diff-06a6d3876124f6bb0adf70a4dffab8d82b9a7ae0abf9ec0ebc22211ca9d8ad4b. Sprites made by KREKS (#.kreks. discord), ported to Space Station 14 by Username228 (#serj3428 discord)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/icon.png b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/icon.png
new file mode 100644
index 00000000000..5b9a2cc3e4c
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/icon.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-left.png b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-left.png
new file mode 100644
index 00000000000..199f64d02ff
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-left.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-right.png b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-right.png
new file mode 100644
index 00000000000..74ce77b9db2
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/inhand-right.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/meta.json b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/meta.json
new file mode 100644
index 00000000000..06bca78f2c1
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Objects/armmace.rsi/meta.json
@@ -0,0 +1,22 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by Username228 (#serj3428 discord)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/icon.png b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/icon.png
new file mode 100644
index 00000000000..9e75fa61e16
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/icon.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-left.png b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-left.png
new file mode 100644
index 00000000000..f54fadf4a84
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-left.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-right.png b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-right.png
new file mode 100644
index 00000000000..f3511818023
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/inhand-right.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/meta.json b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/meta.json
new file mode 100644
index 00000000000..2422b8124cc
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Objects/armshield.rsi/meta.json
@@ -0,0 +1,22 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "taken from tg at https://github.com/tgstation/tgstation/commit/3e9ea4d77cdf4173777e665b2b4f4ba8cecf2c03#diff-06a6d3876124f6bb0adf70a4dffab8d82b9a7ae0abf9ec0ebc22211ca9d8ad4b. Sprites made by KREKS (#.kreks. discord), ported to Space Station 14 by Username228 (#serj3428 discord)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/icon.png b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/icon.png
new file mode 100644
index 00000000000..7661444b00f
Binary files /dev/null and b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/icon.png differ
diff --git a/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json
new file mode 100644
index 00000000000..d4e300c160c
--- /dev/null
+++ b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json
@@ -0,0 +1,14 @@
+{
+ "version": 1,
+ "license": "CC0-1.0",
+ "copyright": "https://github.com/RealFakeSoof with references from deltanedas (github)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ }
+ ]
+ }
diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/icon.png b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/icon.png
new file mode 100644
index 00000000000..96fe562db8a
Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/icon.png differ
diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-left.png b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-left.png
new file mode 100644
index 00000000000..78d2cc1d60d
Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-left.png differ
diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-right.png b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-right.png
new file mode 100644
index 00000000000..0bf22f8b69a
Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/inhand-right.png differ
diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/meta.json
new file mode 100644
index 00000000000..715d260a1be
--- /dev/null
+++ b/Resources/Textures/ADT/Objects/Weapons/Melee/armtentacle.rsi/meta.json
@@ -0,0 +1,82 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "taken from tg at https://github.com/tgstation/tgstation/commit/3e9ea4d77cdf4173777e665b2b4f4ba8cecf2c03#diff-06a6d3876124f6bb0adf70a4dffab8d82b9a7ae0abf9ec0ebc22211ca9d8ad4b. Sprites made by KREKS (#.kreks. discord), ported to Space Station 14 by Username228 (#serj3428 discord)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.2,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ }
+ ]
+}