diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 87cea4e3d2f..3075a881180 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -1,6 +1,7 @@ using Content.Client.Clothing; using Content.Client.Examine; using Content.Client.Verbs.UI; +using Content.Shared._White.Targeting; using Content.Shared.Interaction; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; @@ -46,7 +47,22 @@ public override void Initialize() _equipEventsQueue.Enqueue((comp, args))); SubscribeLocalEvent((_, comp, args) => _equipEventsQueue.Enqueue((comp, args))); + + // PARSEC EDIT START + SubscribeLocalEvent(RefreshInventorySlots); + // PARSEC EDIT END + } + + // PARSEC EDIT START + public void RefreshInventorySlots(EntityUid uid, InventorySlotsComponent component, RefreshInventorySlotsEvent args) + { + if (component.SlotData.TryGetValue(args.SlotName, out var slotData) + && _playerManager.LocalEntity == uid) + { + OnSlotRemoved?.Invoke(slotData); + } } + // PARSEC EDIT END public override void Update(float frameTime) { diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml index 54aeffe72c9..d0aac694bd8 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml @@ -9,6 +9,7 @@ xmlns:hotbar="clr-namespace:Content.Client.UserInterface.Systems.Hotbar.Widgets" xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" xmlns:inventory="clr-namespace:Content.Client.UserInterface.Systems.Inventory.Widgets" + xmlns:targetdoll="clr-namespace:Content.Client._White.Targeting.Ui" Name="DefaultHud" VerticalExpand="False" VerticalAlignment="Bottom" @@ -28,6 +29,7 @@ + diff --git a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs index e630b0c480e..a2335ae3f7f 100644 --- a/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/DefaultGameScreen.xaml.cs @@ -23,6 +23,7 @@ public DefaultGameScreen() SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5); SetAnchorAndMarginPreset(Chat, LayoutPreset.TopRight, margin: 10); SetAnchorAndMarginPreset(Alerts, LayoutPreset.TopRight, margin: 10); + SetAnchorAndMarginPreset(Targeting, LayoutPreset.BottomRight, margin: 10); // PARSEC Chat.OnResized += ChatOnResized; Chat.OnChatResizeFinish += ChatOnResizeFinish; diff --git a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml index f8e204c9d18..6b49729b73c 100644 --- a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml +++ b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml @@ -10,6 +10,7 @@ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" xmlns:inventory="clr-namespace:Content.Client.UserInterface.Systems.Inventory.Widgets" + xmlns:targetdoll="clr-namespace:Content.Client._White.Targeting.Ui" Name="SeparatedChatHud" VerticalExpand="False" VerticalAlignment="Bottom" @@ -20,6 +21,7 @@ + diff --git a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs index 45a29e03f1d..2d85a3e4b2c 100644 --- a/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs +++ b/Content.Client/UserInterface/Screens/SeparatedChatGameScreen.xaml.cs @@ -23,6 +23,7 @@ public SeparatedChatGameScreen() SetAnchorAndMarginPreset(Ghost, LayoutPreset.BottomWide, margin: 80); SetAnchorAndMarginPreset(Hotbar, LayoutPreset.BottomWide, margin: 5); SetAnchorAndMarginPreset(Alerts, LayoutPreset.CenterRight, margin: 10); + SetAnchorAndMarginPreset(Targeting, LayoutPreset.BottomRight, margin: 10); // PARSEC ScreenContainer.OnSplitResizeFinished += () => OnChatResized?.Invoke(new Vector2(ScreenContainer.SplitFraction, 0)); diff --git a/Content.Client/_White/Targeting/Systems/TargetingSystem.cs b/Content.Client/_White/Targeting/Systems/TargetingSystem.cs new file mode 100644 index 00000000000..24db925d6d2 --- /dev/null +++ b/Content.Client/_White/Targeting/Systems/TargetingSystem.cs @@ -0,0 +1,74 @@ +using Content.Shared._White.Targeting; +using Content.Shared._White.Targeting.Components; +using Robust.Client.Player; +using Robust.Shared.Player; + +namespace Content.Client._White.Targeting.Systems; + +public sealed class TargetingSystem : EntitySystem +{ + [Dependency] private readonly IPlayerManager _playerManager = default!; + + public event Action? TargetingStartup; + public event Action? TargetingShutdown; + public event Action? PartStatusStartup; + public event Action? PartStatusUpdate; + public event Action? PartStatusShutdown; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(PlayerAttached); + SubscribeLocalEvent(PlayerDetached); + + SubscribeLocalEvent(OnTargetingStartup); + SubscribeLocalEvent(OnTargetingShutdown); + + SubscribeNetworkEvent(OnTargetingIntegrityChange); + } + + private void PlayerAttached(EntityUid uid, TargetingComponent component, LocalPlayerAttachedEvent args) + { + TargetingStartup?.Invoke(component); + PartStatusStartup?.Invoke(component); + } + + private void PlayerDetached(EntityUid uid, TargetingComponent component, LocalPlayerDetachedEvent args) + { + TargetingShutdown?.Invoke(); + PartStatusShutdown?.Invoke(); + } + + private void OnTargetingStartup(EntityUid uid, TargetingComponent component, ComponentStartup args) + { + if (_playerManager.LocalEntity != uid) + return; + + TargetingStartup?.Invoke(component); + PartStatusStartup?.Invoke(component); + } + + private void OnTargetingShutdown(EntityUid uid, TargetingComponent component, ComponentShutdown args) + { + if (_playerManager.LocalEntity != uid) + return; + + TargetingShutdown?.Invoke(); + PartStatusShutdown?.Invoke(); + } + + private void OnTargetingIntegrityChange(TargetingIntegrityChangeEvent args) + { + if(!TryGetEntity(args.Entity, out var uid)) + return; + + if(!TryComp(uid, out TargetingComponent? component)) + return; + + if (!_playerManager.LocalEntity.Equals(uid) || !args.NeedRefresh) + return; + + PartStatusUpdate?.Invoke(component); + } +} diff --git a/Content.Client/_White/Targeting/TargetingController.cs b/Content.Client/_White/Targeting/TargetingController.cs new file mode 100644 index 00000000000..3b00b8e3c50 --- /dev/null +++ b/Content.Client/_White/Targeting/TargetingController.cs @@ -0,0 +1,80 @@ +using Content.Client._White.Targeting.Systems; +using Content.Client._White.Targeting.Ui; +using Content.Client.Gameplay; +using Content.Shared._White.Targeting; +using Content.Shared._White.Targeting.Components; +using Robust.Client.Player; +using Robust.Client.UserInterface.Controllers; + +namespace Content.Client._White.Targeting; + +public sealed class TargetingController : UIController, IOnStateEntered, IOnSystemChanged +{ + [Dependency] private readonly IEntityManager _entManager = default!; + [Dependency] private readonly IEntityNetworkManager _net = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + + private TargetingComponent? _targetingComponent; + private TargetingWidget? TargetingControl => UIManager.GetActiveUIWidgetOrNull(); + + public void OnSystemLoaded(TargetingSystem system) + { + system.TargetingStartup += AddTargetingControl; + system.TargetingShutdown += RemoveTargetingControl; + } + + public void OnSystemUnloaded(TargetingSystem system) + { + system.TargetingStartup -= AddTargetingControl; + system.TargetingShutdown -= RemoveTargetingControl; + } + + public void OnStateEntered(GameplayState state) + { + if (TargetingControl == null) + return; + + TargetingControl.SetTargetDollVisible(_targetingComponent != null); + + if (_targetingComponent != null) + TargetingControl.SetBodyPartsVisible(_targetingComponent.TargetBodyPart); + } + + public void AddTargetingControl(TargetingComponent component) + { + _targetingComponent = component; + + if (TargetingControl != null) + { + TargetingControl.SetTargetDollVisible(_targetingComponent != null); + + if (_targetingComponent != null) + TargetingControl.SetBodyPartsVisible(_targetingComponent.TargetBodyPart); + } + + } + + public void RemoveTargetingControl() + { + TargetingControl?.SetTargetDollVisible(false); + + _targetingComponent = null; + } + + public void CycleTarget(TargetingBodyParts bodyPart) + { + if (_playerManager.LocalEntity is not { } user + || _entManager.GetComponent(user) is not { } targetingComponent + || TargetingControl == null) + return; + + var player = _entManager.GetNetEntity(user); + + if (bodyPart == targetingComponent.TargetBodyPart) + return; + + var msg = new TargetingChangeBodyPartEvent(player, bodyPart); + _net.SendSystemNetworkMessage(msg); + TargetingControl?.SetBodyPartsVisible(bodyPart); + } +} diff --git a/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml b/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml new file mode 100644 index 00000000000..ad0690e8f21 --- /dev/null +++ b/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml.cs b/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml.cs new file mode 100644 index 00000000000..bf41ccfd605 --- /dev/null +++ b/Content.Client/_White/Targeting/Ui/TargetingWidget.xaml.cs @@ -0,0 +1,84 @@ +using System.Linq; +using Content.Shared._White.Targeting.Components; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._White.Targeting.Ui; + +[GenerateTypedNameReferences] +public sealed partial class TargetingWidget : UIWidget +{ + private readonly TargetingController _controller; + private readonly Dictionary _bodyPartControls; + + public TargetingWidget() + { + RobustXamlLoader.Load(this); + _controller = UserInterfaceManager.GetUIController(); + + _bodyPartControls = GetBodyPartTextureButtons(); + + foreach (var bodyPartButton in _bodyPartControls) + { + bodyPartButton.Value.MouseFilter = MouseFilterMode.Stop; + + bodyPartButton.Value.OnPressed += _ => SetActiveBodyPart(bodyPartButton.Key); + bodyPartButton.Value.OnMouseEntered += _ => SetHoverBodyPart(bodyPartButton.Key); + bodyPartButton.Value.OnMouseExited += _ => SetHoverBodyPart(bodyPartButton.Key); + + TargetDoll.Texture = Theme.ResolveTexture("targeting_doll"); + } + } + + private Dictionary GetBodyPartTextureButtons() + { + return new Dictionary + { + { TargetingBodyParts.Head, HeadButton }, + { TargetingBodyParts.Chest, ChestButton }, + { TargetingBodyParts.Stomach, StomachButton }, + { TargetingBodyParts.LeftArm, LeftArmButton }, + { TargetingBodyParts.LeftHand, LeftHandButton }, + { TargetingBodyParts.RightArm, RightArmButton }, + { TargetingBodyParts.RightHand, RightHandButton }, + { TargetingBodyParts.LeftLeg, LeftLegButton }, + { TargetingBodyParts.LeftFoot, LeftFootButton }, + { TargetingBodyParts.RightLeg, RightLegButton }, + { TargetingBodyParts.RightFoot, RightFootButton }, + }; + } + + private void SetActiveBodyPart(TargetingBodyParts bodyPart) + { + _controller.CycleTarget(bodyPart); + } + + public void SetBodyPartsVisible(TargetingBodyParts bodyPart) + { + foreach (var bodyPartButton in _bodyPartControls) + { + bodyPartButton.Value.Children.First().Visible = bodyPartButton.Key == bodyPart; + if (bodyPartButton.Value.Children.Last().Visible && bodyPartButton.Key == bodyPart) + bodyPartButton.Value.Children.Last().Visible = false; + } + } + + protected override void OnThemeUpdated() + { + TargetDoll.Texture = Theme.ResolveTexture("target_doll"); + } + + public void SetTargetDollVisible(bool visible) + { + Visible = visible; + } + + public void SetHoverBodyPart(TargetingBodyParts bodyPart) + { + foreach (var bodyPartButton in _bodyPartControls.Where(bodyPartButton => bodyPartButton.Key == bodyPart && !bodyPartButton.Value.Children.First().Visible)) + { + bodyPartButton.Value.Children.Last().Visible = !bodyPartButton.Value.Children.Last().Visible; + } + } +} diff --git a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs index d9af71f0014..0d120cc2d3d 100644 --- a/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs +++ b/Content.Server/Atmos/EntitySystems/BarotraumaSystem.cs @@ -279,7 +279,7 @@ public override void Update(float frameTime) private void ActLowPressure(EntityUid uid, BarotraumaComponent barotrauma) { // Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear. - _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * Atmospherics.LowPressureDamage, true, false); + _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * Atmospherics.LowPressureDamage, true, false, sever: false); if (!barotrauma.TakingDamage) { @@ -299,7 +299,7 @@ private void ActHighPressure(EntityUid uid, BarotraumaComponent barotrauma, floa ); // Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear. - _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * damageScale, true, false); + _damageableSystem.TryChangeDamage(uid, barotrauma.Damage * damageScale, true, false, sever: false); if (!barotrauma.TakingDamage) { diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index e10158cf357..a4d4b0e7eab 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -10,8 +10,8 @@ using Content.Shared.Movement.Events; using Content.Shared.Movement.Systems; using Robust.Shared.Audio; -using Robust.Shared.Timing; using System.Numerics; +using Robust.Shared.Timing; namespace Content.Server.Body.Systems; @@ -22,6 +22,7 @@ public sealed class BodySystem : SharedBodySystem [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedMindSystem _mindSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; public override void Initialize() { @@ -92,9 +93,15 @@ protected override void RemovePart( if (layer is null) return; + _appearance.SetData(bodyEnt, layer, true); // PARSEC + var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value); _humanoidSystem.SetLayersVisibility( - bodyEnt, layers, visible: false, permanent: true, humanoid); + bodyEnt, + layers, + visible: false, + permanent: true, + humanoid); } public override HashSet GibBody( @@ -119,8 +126,13 @@ public override HashSet GibBody( if (xform.MapUid is null) return new HashSet(); - var gibs = base.GibBody(bodyId, gibOrgans, body, launchGibs: launchGibs, - splatDirection: splatDirection, splatModifier: splatModifier, splatCone:splatCone); + var gibs = base.GibBody(bodyId, + gibOrgans, + body, + launchGibs: launchGibs, + splatDirection: splatDirection, + splatModifier: splatModifier, + splatCone:splatCone); var ev = new BeingGibbedEvent(gibs); RaiseLocalEvent(bodyId, ref ev); diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs index 9dc201723d8..dcdafc8454a 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs @@ -445,8 +445,7 @@ private void ProcessEntity( foreach (var (entity, damage) in _toDamage) { // TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin. - _damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: ignoreResistances); // WD EDIT - + _damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: ignoreResistances, sever: true); // WD EDIT } } diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index ef0425ce372..b17a946d37e 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Server._White.Other.ChangeThrowForceSystem; +using Content.Server.Body.Systems; using Content.Server.Damage.Components; using Content.Server.Inventory; using Content.Server.Stack; @@ -8,6 +9,7 @@ using Content.Shared._White.MagGloves; using Content.Shared.ActionBlocker; using Content.Shared.Body.Part; +using Content.Shared.Body.Systems; using Content.Shared.CombatMode; using Content.Shared.Damage.Systems; using Content.Shared.Ensnaring.Components; @@ -42,6 +44,7 @@ public sealed class HandsSystem : SharedHandsSystem [Dependency] private readonly PullingSystem _pullingSystem = default!; [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly CultItemSystem _cultItem = default!; + [Dependency] private readonly SharedBodySystem _body = default!; // Parsec public override void Initialize() { @@ -59,11 +62,34 @@ public override void Initialize() SubscribeLocalEvent(OnExploded); + // PARSEC SUBS EDIT + SubscribeLocalEvent(HandleBodyPartEnabled); + SubscribeLocalEvent(HandleBodyPartDisabled); + // PARSEC SUBS EDIT END + CommandBinds.Builder .Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem)) .Register(); } + // PARSEC EDIT START + private void HandleBodyPartEnabled(EntityUid uid, HandsComponent component, ref TargetingBodyPartEnabledEvent args) + { + BeforeAddHand(uid, component, args.Entity, args.BodyPartComponent, SharedBodySystem.GetPartSlotContainerId(args.BodyPartComponent.ParentSlot?.Id ?? string.Empty)); + } + + private void HandleBodyPartDisabled(EntityUid uid, HandsComponent component, ref TargetingBodyPartDisabledEvent args) + { + if(TerminatingOrDeleted(uid)) + return; + + if (args.BodyPartComponent.PartType != BodyPartType.Hand) + return; + + RemoveHand(uid, SharedBodySystem.GetPartSlotContainerId(args.BodyPartComponent.ParentSlot?.Id ?? string.Empty)); + } + // PARSEC EDIT END + public override void Shutdown() { base.Shutdown(); @@ -109,22 +135,33 @@ private void OnDisarmed(EntityUid uid, HandsComponent component, DisarmedEvent a args.Handled = true; // no shove/stun. } - private void HandleBodyPartAdded(EntityUid uid, HandsComponent component, ref BodyPartAddedEvent args) + private void BeforeAddHand(EntityUid uid, HandsComponent component, EntityUid partUid, BodyPartComponent? partComponent, string partSlot) { - if (args.Part.Comp.PartType != BodyPartType.Hand) + if (partComponent is null || partComponent.PartType != BodyPartType.Hand) return; - // If this annoys you, which it should. - // Ping Smugleaf. - var location = args.Part.Comp.Symmetry switch + var location = partComponent.Symmetry switch { BodyPartSymmetry.None => HandLocation.Middle, BodyPartSymmetry.Left => HandLocation.Left, BodyPartSymmetry.Right => HandLocation.Right, - _ => throw new ArgumentOutOfRangeException(nameof(args.Part.Comp.Symmetry)) + _ => throw new ArgumentOutOfRangeException(nameof(partComponent.Symmetry)) + { + HelpLink = null, + HResult = 0, + Source = null + } }; - AddHand(uid, args.Slot, location); + if (_body.TryGetParentBodyPart(partUid, out _, out var parentPartComp) && partComponent.Enabled && parentPartComp.Enabled) + { + AddHand(uid, partSlot, location); + } + } + + private void HandleBodyPartAdded(EntityUid uid, HandsComponent component, ref BodyPartAddedEvent args) + { + BeforeAddHand(uid, component, args.Part.Owner, args.Part.Comp, args.Slot); } private void HandleBodyPartRemoved(EntityUid uid, HandsComponent component, ref BodyPartRemovedEvent args) diff --git a/Content.Server/Medical/HealingSystem.cs b/Content.Server/Medical/HealingSystem.cs index 70336c8b27f..d29d778ed55 100644 --- a/Content.Server/Medical/HealingSystem.cs +++ b/Content.Server/Medical/HealingSystem.cs @@ -1,11 +1,15 @@ +using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.Medical.Components; using Content.Server.Popups; using Content.Server.Stack; +using Content.Shared._White.Targeting.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Audio; +using Content.Shared.Body.Part; +using Content.Shared.Body.Systems; using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.DoAfter; @@ -37,6 +41,7 @@ public sealed class HealingSystem : EntitySystem [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SharedBodySystem _body = default!; // PARSEC public override void Initialize() { @@ -85,6 +90,19 @@ entity.Comp.DamageContainerID is not null && if (healed == null && healing.BloodlossModifier != 0) return; + if (healed != null && healed.GetTotal() == 0) + { + if (TryComp(args.User, out var user) + && TryComp(args.Target, out var target) + && healing.Damage.GetTotal() < 0) + { + var (type, symmetry) = _body.ConvertTargetBodyPart(user.TargetBodyPart); + if (_body.GetBodyChildrenOfType(args.Target.Value, type).FirstOrDefault() is { } bodyPart + && bodyPart.Component.PartIntegrity < BodyPartComponent.MaxPartIntegrity) + _body.TryChangePartIntegrity(bodyPart, healing.Damage.GetTotal().Float(), false, target.TargetBodyPart, out _); + } + } + var total = healed?.GetTotal() ?? FixedPoint2.Zero; // Re-verify that we can heal the damage. diff --git a/Content.Server/_White/Targeting/Systems/TargetingSystem.cs b/Content.Server/_White/Targeting/Systems/TargetingSystem.cs new file mode 100644 index 00000000000..c57e44477fd --- /dev/null +++ b/Content.Server/_White/Targeting/Systems/TargetingSystem.cs @@ -0,0 +1,56 @@ +using Content.Shared._White.Targeting; +using Content.Shared._White.Targeting.Components; +using Content.Shared.Body.Systems; +using Content.Shared.Mobs; +using Robust.Server.Audio; +using Robust.Shared.Audio; + +namespace Content.Server._White.Targeting.Systems; + +public sealed class TargetingSystem : EntitySystem +{ + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly SharedBodySystem _bodySystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeNetworkEvent(OnTargetChange); + SubscribeLocalEvent(OnMobStateChange); + } + + private void OnTargetChange(TargetingChangeBodyPartEvent message, EntitySessionEventArgs args) + { + if (!TryComp(GetEntity(message.Entity), out var target)) + return; + + target.TargetBodyPart = message.BodyPart; + + Dirty(GetEntity(message.Entity), target); + } + + private void OnMobStateChange(EntityUid uid, TargetingComponent component, MobStateChangedEvent args) + { + var changed = false; + + if (args.NewMobState == MobState.Dead) + { + foreach (TargetingBodyParts part in Enum.GetValues(typeof(TargetingBodyParts))) + { + component.TargetIntegrities[part] = TargetIntegrity.Dead; + changed = true; + } + } + else if (args is { OldMobState: MobState.Dead, NewMobState: MobState.Alive or MobState.Critical }) + { + component.TargetIntegrities = _bodySystem.GetBodyPartStatus(uid); + changed = true; + } + + if (changed) + { + Dirty(uid, component); + RaiseNetworkEvent(new TargetingIntegrityChangeEvent(GetNetEntity(uid)), uid); + } + } +} diff --git a/Content.Shared/Body/Organ/OrganComponent.cs b/Content.Shared/Body/Organ/OrganComponent.cs index 3048927b5fb..6152edfe3df 100644 --- a/Content.Shared/Body/Organ/OrganComponent.cs +++ b/Content.Shared/Body/Organ/OrganComponent.cs @@ -13,4 +13,7 @@ public sealed partial class OrganComponent : Component /// [DataField, AutoNetworkedField] public EntityUid? Body; + + [DataField] + public string SlotId = ""; } diff --git a/Content.Shared/Body/Part/BodyPartComponent.cs b/Content.Shared/Body/Part/BodyPartComponent.cs index c4e65c06a3f..bd576d8fd48 100644 --- a/Content.Shared/Body/Part/BodyPartComponent.cs +++ b/Content.Shared/Body/Part/BodyPartComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Body.Components; using Content.Shared.Body.Systems; +using Content.Shared.Containers.ItemSlots; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Serialization; @@ -79,6 +80,34 @@ private List OrganSlotsVV return temp; } } + + //parsec edit start + [DataField, AutoNetworkedField] + public float PartIntegrity = 70f; + public const float MaxPartIntegrity = 70; + + [DataField, AutoNetworkedField] + public bool Enabled = true; + + [DataField] + public float PartHealingTime = 30; + public float PartHealingTimer = 0; + + [DataField] + public float SelfHealingAmount = 5; + + [DataField] + public string ContainerName { get; set; } = "part_slot"; + + [DataField, AutoNetworkedField] + public ItemSlot ItemInsertionSlot = new(); + + [DataField, AutoNetworkedField] + public EntityUid? OwnerBodyPart; + + [DataField, AutoNetworkedField] + public BodyPartSlot? ParentSlot; + //parsec edit end } /// diff --git a/Content.Shared/Body/Part/BodyPartEvents.cs b/Content.Shared/Body/Part/BodyPartEvents.cs index 0d8d2c8a268..95eba35a35f 100644 --- a/Content.Shared/Body/Part/BodyPartEvents.cs +++ b/Content.Shared/Body/Part/BodyPartEvents.cs @@ -5,3 +5,12 @@ namespace Content.Shared.Body.Part; [ByRefEvent] public readonly record struct BodyPartRemovedEvent(string Slot, Entity Part); + +[ByRefEvent] +public readonly record struct TargetingBodyPartEnableChangedEvent(bool IsEnabled); + +[ByRefEvent] +public readonly record struct TargetingBodyPartEnabledEvent(EntityUid Entity, BodyPartComponent BodyPartComponent); + +[ByRefEvent] +public readonly record struct TargetingBodyPartDisabledEvent(EntityUid Entity, BodyPartComponent BodyPartComponent); diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index 250f90db8f3..f542d1d0a32 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -4,15 +4,18 @@ using Content.Shared.Body.Organ; using Content.Shared.Body.Part; using Content.Shared.Body.Prototypes; +using Content.Shared.Damage; using Content.Shared.DragDrop; using Content.Shared.Gibbing.Components; using Content.Shared.Gibbing.Events; using Content.Shared.Gibbing.Systems; using Content.Shared.Inventory; +using Content.Shared.Standing.Systems; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Map; +using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Shared.Body.Systems; @@ -29,6 +32,7 @@ public partial class SharedBodySystem [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly GibbingSystem _gibbingSystem = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; // PARSEC private const float GibletLaunchImpulse = 8; private const float GibletLaunchImpulseVariance = 3; @@ -42,7 +46,38 @@ private void InitializeBody() SubscribeLocalEvent(OnBodyInit); SubscribeLocalEvent(OnBodyMapInit); SubscribeLocalEvent(OnBodyCanDrag); + + // PARSEC EDIT START + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent(OnStandAttempt); + // PARSEC EDIT END + } + + // PARSEC EDIT START + private void OnStandAttempt(Entity ent, ref StandAttemptEvent args) + { + if (ent.Comp.LegEntities.Count == 0) + args.Cancel(); + } + + private void OnDamageChanged(Entity ent, ref DamageChangedEvent args) + { + if (args.PartDamageMultiplier == 0 + || args.TargetBodyPart is null + || args.DamageDelta is null + || !args.DamageIncreased + && !args.DamageDecreased) + return; + + var (targetType, targetSymmetry) = ConvertTargetBodyPart(args.TargetBodyPart.Value); + foreach (var part in GetBodyChildrenOfType(ent, targetType, ent.Comp) + .Where(part => part.Component.Symmetry == targetSymmetry)) + { + if (_gameTiming.IsFirstTimePredicted) + ApplyPartDamage(part, args.DamageDelta, targetType, args.TargetBodyPart.Value, args.Sever, args.PartDamageMultiplier); + } } + // PARSEC EDIT END private void OnBodyInserted(Entity ent, ref EntInsertedIntoContainerMessage args) { diff --git a/Content.Shared/Body/Systems/SharedBodySystem.IntegrityPart.cs b/Content.Shared/Body/Systems/SharedBodySystem.IntegrityPart.cs new file mode 100644 index 00000000000..1b8f71814aa --- /dev/null +++ b/Content.Shared/Body/Systems/SharedBodySystem.IntegrityPart.cs @@ -0,0 +1,340 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Content.Shared._White.Targeting; +using Content.Shared._White.Targeting.Components; +using Content.Shared.Body.Components; +using Content.Shared.Body.Part; +using Content.Shared.Damage; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.Standing; +using Robust.Shared.CPUJob.JobQueues; +using Robust.Shared.CPUJob.JobQueues.Queues; +using Robust.Shared.Network; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared.Body.Systems; + +public partial class SharedBodySystem +{ + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + private readonly string[] _damageTypes = ["Slash", "Pierce", "Blunt"]; + + private const double PartIntegrityJobTime = 0.005; + private readonly JobQueue _PartIntegrityJobQueue = new(PartIntegrityJobTime); + + public sealed class PartIntegrityJob : Job + { + private readonly SharedBodySystem _self; + private readonly Entity _ent; + public PartIntegrityJob(SharedBodySystem self, Entity ent, double maxTime, CancellationToken cancellation = default) : base(maxTime, cancellation) + { + _self = self; + _ent = ent; + } + + public PartIntegrityJob(SharedBodySystem self, Entity ent, double maxTime, IStopwatch stopwatch, CancellationToken cancellation = default) : base(maxTime, stopwatch, cancellation) + { + _self = self; + _ent = ent; + } + + protected override Task Process() + { + _self.ProcessPartIntegrityTick(_ent); + + return Task.FromResult(null); + } + } + + private EntityQuery _queryTargeting; + private void InitializePartIntegrity() + { + _queryTargeting = GetEntityQuery(); + } + + private void ProcessPartIntegrityTick(Entity entity) + { + if (entity.Comp is { Body: {} body, PartIntegrity: > 50 and < BodyPartComponent.MaxPartIntegrity } + && _queryTargeting.HasComp(body) + && !_mobState.IsDead(body)) + { + var healing = entity.Comp.SelfHealingAmount; + if (healing + entity.Comp.PartIntegrity > BodyPartComponent.MaxPartIntegrity) + healing = entity.Comp.PartIntegrity - BodyPartComponent.MaxPartIntegrity; + + TryChangePartIntegrity(entity, + healing, + false, + GetTargetBodyPart(entity), + out _); + } + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + _PartIntegrityJobQueue.Process(); + + if (!_timing.IsFirstTimePredicted) + return; + + using var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out var part)) + { + part.PartHealingTime += frameTime; + + if (part.PartHealingTimer >= part.PartHealingTime) + { + part.PartHealingTimer = 0; + _PartIntegrityJobQueue.EnqueueJob(new PartIntegrityJob(this, (ent, part), PartIntegrityJobTime)); + } + } + } + + /// + /// Propagates damage to the specified parts of the entity. + /// + private void ApplyPartDamage(Entity partEnt, + DamageSpecifier damage, + BodyPartType targetType, + TargetingBodyParts targetPart, + bool canSever, + float partMultiplier) + { + if (partEnt.Comp.Body is null) + return; + + foreach (var (damageType, damageValue) in damage.DamageDict) + { + if (damageValue.Float() == 0 + || TryEvadeDamage(partEnt.Comp.Body.Value, GetEvadeChance(targetType))) + continue; + + var modifier = GetDamageModifier(damageType); + var partModifier = GetPartDamageModifier(targetType); + var partIntegrityDamage = damageValue.Float() * modifier * partModifier * partMultiplier; + + TryChangePartIntegrity(partEnt, + partIntegrityDamage, + canSever && _damageTypes.Contains(damageType), + targetPart, + out var severed); + + if (severed) + break; + } + } + + public void TryChangePartIntegrity(Entity partEnt, + float partIntegrity, + bool canSever, + TargetingBodyParts? targetPart, + out bool severed) + { + severed = false; + if (!_timing.IsFirstTimePredicted || !_queryTargeting.HasComp(partEnt.Comp.Body)) + return; + + var partIdSlot = GetParentPartAndSlotOrNull(partEnt)?.Slot; + var originalPartIntegrity = partEnt.Comp.PartIntegrity; + partEnt.Comp.PartIntegrity = Math.Min(BodyPartComponent.MaxPartIntegrity, partEnt.Comp.PartIntegrity - partIntegrity); + + if (canSever + && !partEnt.Comp.Enabled + && partEnt.Comp.PartIntegrity <= 0 + && partIdSlot is not null) + severed = true; + + switch (partEnt.Comp.Enabled) + { + case true + when partEnt.Comp.PartIntegrity <= 15.0f: + { + var ev = new TargetingBodyPartEnableChangedEvent(false); + RaiseLocalEvent(partEnt, ref ev); + break; + } + + case false + when partEnt.Comp.PartIntegrity >= 80.0f: + { + var ev = new TargetingBodyPartEnableChangedEvent(true); + RaiseLocalEvent(partEnt, ref ev); + break; + } + } + + if (partEnt.Comp.PartIntegrity != originalPartIntegrity + && _queryTargeting.TryComp(partEnt.Comp.Body, out var targeting) + && HasComp(partEnt.Comp.Body)) + { + var newPartIntegrity = GetPartIntegrityThreshold(partEnt.Comp.PartIntegrity, severed, partEnt.Comp.Enabled); + + if (targetPart is not null && targeting.TargetIntegrities[targetPart.Value] != TargetIntegrity.Dead) + { + targeting.TargetIntegrities[targetPart.Value] = newPartIntegrity; + Dirty(partEnt.Comp.Body.Value, targeting); + } + + if (_net.IsServer) + RaiseNetworkEvent(new TargetingIntegrityChangeEvent(GetNetEntity(partEnt.Comp.Body.Value)), partEnt.Comp.Body.Value); + } + + if (severed && partIdSlot is not null) + DropPart(partEnt); + + Dirty(partEnt, partEnt.Comp); + } + + public Dictionary GetBodyPartStatus(EntityUid entityUid) + { + var result = new Dictionary(); + + if (!TryComp(entityUid, out var body)) + return result; + + foreach (TargetingBodyParts part in Enum.GetValues(typeof(TargetingBodyParts))) + { + result[part] = TargetIntegrity.Severed; + } + + foreach (var partComponent in GetBodyChildren(entityUid, body)) + { + var targetBodyPart = GetTargetBodyPart(partComponent.Component.PartType, partComponent.Component.Symmetry); + + if (targetBodyPart != null) + { + result[targetBodyPart.Value] = GetPartIntegrityThreshold(partComponent.Component.PartIntegrity, false, partComponent.Component.Enabled); + } + } + + return result; + } + + public TargetingBodyParts? GetTargetBodyPart(Entity part) + { + return GetTargetBodyPart(part.Comp.PartType, part.Comp.Symmetry); + } + + public TargetingBodyParts? GetTargetBodyPart(BodyPartComponent part) + { + return GetTargetBodyPart(part.PartType, part.Symmetry); + } + + public TargetingBodyParts? GetTargetBodyPart(BodyPartType type, BodyPartSymmetry symmetry) + { + return (type, symmetry) switch + { + (BodyPartType.Head, _) => TargetingBodyParts.Head, + (BodyPartType.Torso, _) => TargetingBodyParts.Chest, + (BodyPartType.Arm, BodyPartSymmetry.Left) => TargetingBodyParts.LeftArm, + (BodyPartType.Arm, BodyPartSymmetry.Right) => TargetingBodyParts.RightArm, + (BodyPartType.Leg, BodyPartSymmetry.Left) => TargetingBodyParts.LeftLeg, + (BodyPartType.Leg, BodyPartSymmetry.Right) => TargetingBodyParts.RightLeg, + _ => null + }; + } + + public (BodyPartType Type, BodyPartSymmetry Symmetry) ConvertTargetBodyPart(TargetingBodyParts targetPart) + { + return targetPart switch + { + TargetingBodyParts.Head => (BodyPartType.Head, BodyPartSymmetry.None), + TargetingBodyParts.Chest => (BodyPartType.Torso, BodyPartSymmetry.None), + TargetingBodyParts.Stomach => (BodyPartType.Torso, BodyPartSymmetry.None), + TargetingBodyParts.LeftArm => (BodyPartType.Arm, BodyPartSymmetry.Left), + TargetingBodyParts.LeftHand => (BodyPartType.Hand, BodyPartSymmetry.Left), + TargetingBodyParts.RightArm => (BodyPartType.Arm, BodyPartSymmetry.Right), + TargetingBodyParts.RightHand => (BodyPartType.Hand, BodyPartSymmetry.Right), + TargetingBodyParts.LeftLeg => (BodyPartType.Leg, BodyPartSymmetry.Left), + TargetingBodyParts.LeftFoot => (BodyPartType.Foot, BodyPartSymmetry.Left), + TargetingBodyParts.RightLeg => (BodyPartType.Leg, BodyPartSymmetry.Right), + TargetingBodyParts.RightFoot => (BodyPartType.Foot, BodyPartSymmetry.Right), + _ => (BodyPartType.Torso, BodyPartSymmetry.None) + }; + + } + + public float GetDamageModifier(string damageType) + { + return damageType switch + { + "Blunt" => 0.8f, + "Slash" => 1.2f, + "Pierce" => 0.5f, + "Heat" => 1.0f, + "Cold" => 1.0f, + "Shock" => 0.8f, + "Poison" => 0.8f, + "Radiation" => 0.8f, + "Cellular" => 0.8f, + _ => 0.5f + }; + } + + public float GetPartDamageModifier(BodyPartType partType) + { + return partType switch + { + BodyPartType.Head => 0.5f, + BodyPartType.Torso => 1.0f, + BodyPartType.Arm => 0.7f, + BodyPartType.Leg => 0.7f, + _ => 0.5f + }; + } + + public TargetIntegrity GetPartIntegrityThreshold(float PartIntegrity, bool severed, bool enabled) + { + if (severed) + return TargetIntegrity.Severed; + + if (!enabled) + return TargetIntegrity.Disabled; + + return PartIntegrity switch + { + <= 10.0f => TargetIntegrity.CriticallyWounded, + <= 25.0f => TargetIntegrity.HeavilyWounded, + <= 40.0f => TargetIntegrity.ModeratelyWounded, + <= 60.0f => TargetIntegrity.SomewhatWounded, + <= 80.0f => TargetIntegrity.LightlyWounded, + _ => TargetIntegrity.Healthy + }; + } + + public float GetEvadeChance(BodyPartType partType) + { + return partType switch + { + BodyPartType.Head => 0.70f, + BodyPartType.Arm => 0.20f, + BodyPartType.Leg => 0.20f, + BodyPartType.Torso => 0f, + _ => 0f + }; + } + + public bool CanEvadeDamage(EntityUid uid) + { + return TryComp(uid, out var mobState) + && TryComp(uid, out var standingState) + && !_mobState.IsCritical(uid, mobState) + && !_mobState.IsDead(uid, mobState) + && standingState.CurrentState != StandingState.Lying; + } + + public bool TryEvadeDamage(EntityUid uid, float evadeChance) + { + if (!CanEvadeDamage(uid)) + return false; + + return _random.NextFloat() < evadeChance; + } +} diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index ee79faa0b8e..9d17aa360fc 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -1,12 +1,16 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Shared._White.Targeting; using Content.Shared.Body.Components; using Content.Shared.Body.Events; using Content.Shared.Body.Organ; using Content.Shared.Body.Part; +using Content.Shared.Containers.ItemSlots; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; +using Content.Shared.Inventory; using Content.Shared.Movement.Components; +using Content.Shared.Random; using Robust.Shared.Containers; using Robust.Shared.Utility; @@ -14,6 +18,9 @@ namespace Content.Shared.Body.Systems; public partial class SharedBodySystem { + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; + [Dependency] private readonly ItemSlotsSystem _slots = default!; + [Dependency] private readonly InventorySystem _inventorySystem = default!; private void InitializeParts() { // TODO: This doesn't handle comp removal on child ents. @@ -21,7 +28,195 @@ private void InitializeParts() // If you modify this also see the Body partial for root parts. SubscribeLocalEvent(OnBodyPartInserted); SubscribeLocalEvent(OnBodyPartRemoved); + + // PARSEC EDIT START + SubscribeLocalEvent(MapInit); + SubscribeLocalEvent(BodyPartRemoved); + SubscribeLocalEvent(TargetingPartEnableChanged); + // PARSEC EDIT END + } + + // PARSEC EDIT START + private void MapInit(Entity ent, ref MapInitEvent args) + { + if (ent.Comp.PartType != BodyPartType.Torso) + return; + + _slots.AddItemSlot(ent, ent.Comp.ContainerName, ent.Comp.ItemInsertionSlot); + Dirty(ent, ent.Comp); + } + + private void BodyPartRemoved(Entity ent, ref ComponentRemove args) + { + if (ent.Comp.PartType == BodyPartType.Torso) + { + _slots.RemoveItemSlot(ent, ent.Comp.ItemInsertionSlot); + } + } + + protected virtual void DropPart(Entity partEnt) + { + if (partEnt.Comp.Body is not null + && TryGetPartSlotContainerName(partEnt.Comp.PartType, out var containerNames) + && GetBodyPartCount(partEnt.Comp.Body.Value, partEnt.Comp.PartType) == 1) + { + foreach (var containerName in containerNames) + { + _inventorySystem.SetSlotStatus(partEnt.Comp.Body.Value, containerName, true); + var ev = new RefreshInventorySlotsEvent(containerName); + RaiseLocalEvent(partEnt.Comp.Body.Value, ev); + } + } + + if (TryComp(partEnt, out TransformComponent? transform) && _gameTiming.IsFirstTimePredicted) + { + var ev = new TargetingBodyPartEnableChangedEvent(false); + RaiseLocalEvent(partEnt, ref ev); + SharedTransform.AttachToGridOrMap(partEnt, transform); + _randomHelper.RandomOffset(partEnt, 0.5f); + } + } + + private void RemovePartEffect(Entity partEnt, Entity bodyEnt) + { + if (TerminatingOrDeleted(bodyEnt) || !Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false)) + return; + + if (partEnt.Comp.Children.Any()) + { + foreach (var slotId in partEnt.Comp.Children.Keys) + { + Standing.Down(bodyEnt); + if (Containers.TryGetContainer(partEnt, GetPartSlotContainerId(slotId), out var container) && + container is ContainerSlot slot && + slot.ContainedEntity is { } childEntity && + TryComp(childEntity, out BodyPartComponent? childPart)) + { + var ev = new TargetingBodyPartEnableChangedEvent(false); + RaiseLocalEvent(childEntity, ref ev); + DropPart((childEntity, childPart)); + } + } + Dirty(bodyEnt, bodyEnt.Comp); + } + + } + + private void TargetingPartEnableChanged(Entity partEnt, ref TargetingBodyPartEnableChangedEvent args) + { + partEnt.Comp.Enabled = args.IsEnabled; + Dirty(partEnt, partEnt.Comp); + + if (args.IsEnabled) + EnablePart(partEnt); + else + DisablePart(partEnt); + } + + private void EnablePart(Entity partEnt) + { + if (!TryComp(partEnt.Comp.Body, out BodyComponent? body)) + return; + + switch (partEnt.Comp.PartType) + { + case BodyPartType.Leg: + AddLeg(partEnt, (partEnt.Comp.Body.Value, body)); + break; + + case BodyPartType.Arm: + { + var hand = GetBodyChildrenOfType(partEnt.Comp.Body.Value, BodyPartType.Hand).FirstOrDefault(); + if (hand != default) + { + var ev = new TargetingBodyPartEnabledEvent(partEnt.Owner, partEnt.Comp); + RaiseLocalEvent(partEnt.Comp.Body.Value, ref ev); + } + break; + } + + case BodyPartType.Hand: + { + var ev = new TargetingBodyPartEnabledEvent(partEnt.Owner, partEnt.Comp); + RaiseLocalEvent(partEnt.Comp.Body.Value, ref ev); + break; + } + } + } + + private void DisablePart(Entity partEnt) + { + if (!TryComp(partEnt.Comp.Body, out BodyComponent? body)) + return; + + switch (partEnt.Comp.PartType) + { + case BodyPartType.Leg: + RemoveLeg(partEnt, (partEnt.Comp.Body.Value, body)); + break; + + case BodyPartType.Arm: + { + var hand = GetBodyChildrenOfType(partEnt.Comp.Body.Value, BodyPartType.Hand).FirstOrDefault(); + if (hand != default) + { + var ev = new TargetingBodyPartDisabledEvent(partEnt.Owner, partEnt.Comp); + RaiseLocalEvent(partEnt.Comp.Body.Value, ref ev); + } + + break; + } + + case BodyPartType.Hand: + { + var ev = new TargetingBodyPartDisabledEvent(partEnt.Owner, partEnt.Comp); + RaiseLocalEvent(partEnt.Comp.Body.Value, ref ev); + break; + } + } + } + + public bool TryGetBodyPartOrgans( + EntityUid uid, + Type type, + [NotNullWhen(true)] out List<(EntityUid Id, OrganComponent Organ)>? organs, + BodyPartComponent? part = null) + { + if (!Resolve(uid, ref part)) + { + organs = null; + return false; + } + + var list = (from organ in GetPartOrgans(uid, part) where HasComp(organ.Id, type) select (organ.Id, organ.Component)).ToList(); + + if (list.Count != 0) + { + organs = list; + return true; + } + + organs = null; + return false; + } + + private bool TryGetPartSlotContainerName(BodyPartType partType, out HashSet containerNames) + { + containerNames = partType switch + { + BodyPartType.Arm => ["gloves"], + BodyPartType.Leg => ["shoes"], + BodyPartType.Head => ["eyes", "ears", "head", "mask"], + _ => [] + }; + return containerNames.Count > 0; + } + + public int GetBodyPartCount(EntityUid bodyId, BodyPartType partType, BodyComponent? body = null) + { + return !Resolve(bodyId, ref body, logMissing: false) ? 0 : GetBodyChildren(bodyId, body).Count(part => part.Component.PartType == partType); } + // PARSEC EDIT END private void OnBodyPartInserted(Entity ent, ref EntInsertedIntoContainerMessage args) { @@ -127,13 +322,15 @@ protected virtual void RemovePart( { Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false); Dirty(partEnt, partEnt.Comp); - partEnt.Comp.Body = null; + partEnt.Comp.OwnerBodyPart = partEnt.Comp.Body; // parsec + partEnt.Comp.ParentSlot = null; // parsec var ev = new BodyPartRemovedEvent(slotId, partEnt); RaiseLocalEvent(bodyEnt, ref ev); RemoveLeg(partEnt, bodyEnt); PartRemoveDamage(bodyEnt, partEnt); + RemovePartEffect(partEnt, bodyEnt); // parsec } private void AddLeg(Entity legEnt, Entity bodyEnt) @@ -416,8 +613,8 @@ public bool AttachPart( BodyPartComponent? part = null) { return Resolve(parentPartId, ref parentPart, logMissing: false) - && parentPart.Children.TryGetValue(slotId, out var slot) - && AttachPart(parentPartId, slot, partId, parentPart, part); + && parentPart.Children.TryGetValue(slotId, out var slot) + && AttachPart(parentPartId, slot, partId, parentPart, part); } /// @@ -444,6 +641,7 @@ public bool AttachPart( return false; } + part.ParentSlot = slot; return Containers.Insert(partId, container); } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.cs b/Content.Shared/Body/Systems/SharedBodySystem.cs index 020d5b4be47..845df2e0436 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.cs @@ -43,6 +43,7 @@ public override void Initialize() InitializeBody(); InitializeParts(); + InitializePartIntegrity(); // Parsec } /// diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index 6b84bfc0128..f3d3e7099d2 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -9,10 +9,12 @@ using Content.Shared.Radiation.Events; using Content.Shared.Rejuvenate; using Content.Shared._White; +using Content.Shared._White.Targeting.Components; using Robust.Shared.Configuration; using Robust.Shared.GameStates; using Robust.Shared.Network; using Robust.Shared.Prototypes; +using Robust.Shared.Random; using Robust.Shared.Utility; namespace Content.Shared.Damage @@ -24,6 +26,7 @@ public sealed class DamageableSystem : EntitySystem [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IRobustRandom _random = default!; private float DamageGetModifier { get; set; } @@ -49,6 +52,27 @@ public override void Initialize() _mindContainerQuery = GetEntityQuery(); } + // PARSEC EDIT START + public TargetingBodyParts? GetRandomBodyPart(EntityUid uid, TargetingComponent? target = null) + { + if (!Resolve(uid, ref target)) + return null; + + var totalWeight = target.TargetingChance.Values.Sum(); + var randomValue = _random.NextFloat() * totalWeight; + + foreach (var (part, weight) in target.TargetingChance) + { + if (randomValue <= weight) + return part; + + randomValue -= weight; + } + + return TargetingBodyParts.Chest; + } + // PARSEC EDIT END + /// /// Initialize a damageable component /// @@ -107,11 +131,32 @@ public void SetDamage(EntityUid uid, DamageableComponent damageable, DamageSpeci /// This updates cached damage information, flags the component as dirty, and raises a damage changed event. /// The damage changed event is used by other systems, such as damage thresholds. /// - public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSpecifier? damageDelta = null, - bool interruptsDoAfters = true, EntityUid? origin = null) + public void DamageChanged(EntityUid uid, + DamageableComponent component, + DamageSpecifier? damageDelta = null, + bool interruptsDoAfters = true, + EntityUid? origin = null, + bool sever = true, + float partDamageMultiplier = 1F) { component.Damage.GetDamagePerGroup(_prototypeManager, component.DamagePerGroup); component.TotalDamage = component.Damage.GetTotal(); + TargetingBodyParts? targetingBodyPart = null; // PARSEC EDIT + + // START PARSEC EDIT + if (TryComp(uid, out var target)) + { + if (origin.HasValue && TryComp(origin.Value, out var targeter)) + { + targetingBodyPart = targeter.TargetBodyPart; + } + else + { + targetingBodyPart = GetRandomBodyPart(uid, target); + } + } + // END PARSEC EDIT + Dirty(uid, component); if (_appearanceQuery.TryGetComponent(uid, out var appearance) && damageDelta != null) @@ -119,7 +164,8 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp var data = new DamageVisualizerGroupData(component.DamagePerGroup.Keys.ToList()); _appearance.SetData(uid, DamageVisualizerKeys.DamageUpdateGroups, data, appearance); } - RaiseLocalEvent(uid, new DamageChangedEvent(component, damageDelta, interruptsDoAfters, origin)); + + RaiseLocalEvent(uid, new DamageChangedEvent(component, damageDelta, interruptsDoAfters, origin, targetingBodyPart, sever, partDamageMultiplier)); } /// @@ -134,8 +180,14 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp /// Returns a with information about the actual damage changes. This will be /// null if the user had no applicable components that can take damage. /// - public DamageSpecifier? TryChangeDamage(EntityUid? uid, DamageSpecifier damage, bool ignoreResistances = false, - bool interruptsDoAfters = true, DamageableComponent? damageable = null, EntityUid? origin = null) + public DamageSpecifier? TryChangeDamage(EntityUid? uid, + DamageSpecifier damage, + bool ignoreResistances = false, + bool interruptsDoAfters = true, + DamageableComponent? damageable = null, + EntityUid? origin = null, + bool? sever = true, + float? partDamageMultiplier = 1F) { if (!uid.HasValue || !_damageableQuery.Resolve(uid.Value, ref damageable, false)) { @@ -198,7 +250,15 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp } if (delta.DamageDict.Count > 0) - DamageChanged(uid.Value, damageable, delta, interruptsDoAfters, origin); + { + DamageChanged(uid.Value, + damageable, + delta, + interruptsDoAfters, + origin, + sever ?? true, + partDamageMultiplier ?? 1.00f); + } return delta; } @@ -358,11 +418,31 @@ public sealed class DamageChangedEvent : EntityEventArgs /// public readonly EntityUid? Origin; - public DamageChangedEvent(DamageableComponent damageable, DamageSpecifier? damageDelta, bool interruptsDoAfters, EntityUid? origin) + // PARSEC EDIT START + public readonly float PartDamageMultiplier; + + public readonly bool Sever; + + public readonly TargetingBodyParts? TargetBodyPart; + + public readonly bool DamageDecreased; + // PARSEC EDIT END + + public DamageChangedEvent(DamageableComponent damageable, + DamageSpecifier? damageDelta, + bool interruptsDoAfters, + EntityUid? origin, + TargetingBodyParts? targetBodyPart = null, + bool sever = true, + float partDamageMultiplier = 1F) { Damageable = damageable; DamageDelta = damageDelta; Origin = origin; + TargetBodyPart = targetBodyPart; + Sever = sever; + PartDamageMultiplier = partDamageMultiplier; + if (DamageDelta == null) return; @@ -374,6 +454,12 @@ public DamageChangedEvent(DamageableComponent damageable, DamageSpecifier? damag DamageIncreased = true; break; } + + if (damageChange < 0) + { + DamageDecreased = true; + break; + } } InterruptsDoAfters = interruptsDoAfters && DamageIncreased; } diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index 19831278b0a..9ea527652db 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -1,17 +1,56 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Inventory.Events; +using Content.Shared.Random; using Content.Shared.Storage; using Robust.Shared.Containers; using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.Manager; using Robust.Shared.Utility; namespace Content.Shared.Inventory; public partial class InventorySystem : EntitySystem { + [Dependency] private readonly RandomHelperSystem _randomHelper = default!; // PARSEC + [Dependency] private readonly ISerializationManager _serializationManager = default!; // PARSEC [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IViewVariablesManager _vvm = default!; + // PARSEC EDIT START + public void SetSlotStatus(EntityUid uid, string slotName, bool isDisabled, InventoryComponent? inventory = null) + { + if (!Resolve(uid, ref inventory)) + return; + + foreach (var slot in inventory.Slots) + { + if (slot.Name != slotName) + continue; + + + if (!TryGetSlotContainer(uid, slotName, out var container, out _, inventory)) + break; + + if (isDisabled) + { + if (container.ContainedEntity is { } entityUid && TryComp(entityUid, out TransformComponent? transform) && _gameTiming.IsFirstTimePredicted) + { + _transform.AttachToGridOrMap(entityUid, transform); + _randomHelper.RandomOffset(entityUid, 0.5f); + } + _containerSystem.ShutdownContainer(container); + } + else + _containerSystem.EnsureContainer(uid, slotName); + + slot.Disabled = isDisabled; + break; + } + + Dirty(uid, inventory); + } + // PARSEC EDIT END + private void InitializeSlots() { SubscribeLocalEvent(OnInit); @@ -57,6 +96,8 @@ protected virtual void OnInit(EntityUid uid, InventoryComponent component, Compo if (!_prototypeManager.TryIndex(component.TemplateId, out InventoryTemplatePrototype? invTemplate)) return; + _serializationManager.CopyTo(invTemplate.Slots, ref component.Slots, notNullableOverride: true); // PARSEC + component.Slots = invTemplate.Slots; component.Containers = new ContainerSlot[component.Slots.Length]; for (var i = 0; i < component.Containers.Length; i++) @@ -115,7 +156,7 @@ public bool TryGetSlot(EntityUid uid, string slot, [NotNullWhen(true)] out SlotD foreach (var slotDef in inventory.Slots) { - if (!slotDef.Name.Equals(slot)) + if (!slotDef.Name.Equals(slot) || slotDef.Disabled) continue; slotDefinition = slotDef; return true; @@ -203,7 +244,7 @@ public bool MoveNext([NotNullWhen(true)] out ContainerSlot? container) var i = _nextIdx++; var slot = _slots[i]; - if ((slot.SlotFlags & _flags) == 0) + if ((slot.SlotFlags & _flags) == 0 || slot.Disabled) continue; container = _containers[i]; @@ -221,7 +262,7 @@ public bool NextItem(out EntityUid item) var i = _nextIdx++; var slot = _slots[i]; - if ((slot.SlotFlags & _flags) == 0) + if ((slot.SlotFlags & _flags) == 0 || slot.Disabled) continue; var container = _containers[i]; diff --git a/Content.Shared/Inventory/InventoryTemplatePrototype.cs b/Content.Shared/Inventory/InventoryTemplatePrototype.cs index a4d77767e37..67d3022c231 100644 --- a/Content.Shared/Inventory/InventoryTemplatePrototype.cs +++ b/Content.Shared/Inventory/InventoryTemplatePrototype.cs @@ -55,4 +55,7 @@ public sealed partial class SlotDefinition /// Entity blacklist for CanEquip checks. /// [DataField("blacklist")] public EntityWhitelist? Blacklist = null; + + [DataField] + public bool Disabled; // PARSEC } diff --git a/Content.Shared/_White/Targeting/Components/TargetingComponent.cs b/Content.Shared/_White/Targeting/Components/TargetingComponent.cs new file mode 100644 index 00000000000..14da2560ced --- /dev/null +++ b/Content.Shared/_White/Targeting/Components/TargetingComponent.cs @@ -0,0 +1,73 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._White.Targeting.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class TargetingComponent : Component +{ + [ViewVariables, AutoNetworkedField] + public TargetingBodyParts TargetBodyPart = TargetingBodyParts.Chest; + + [DataField] + public Dictionary TargetingChance = new() + { + { TargetingBodyParts.Head, 0.1f }, + { TargetingBodyParts.Chest, 0.4f }, + { TargetingBodyParts.LeftArm, 0.125f }, + { TargetingBodyParts.RightArm, 0.125f }, + { TargetingBodyParts.LeftLeg, 0.125f }, + { TargetingBodyParts.Stomach, 0.125f }, + { TargetingBodyParts.RightFoot, 0.100f }, + { TargetingBodyParts.LeftFoot, 0.100f }, + { TargetingBodyParts.RightHand, 0.100f }, + { TargetingBodyParts.LeftHand, 0.100f } + }; + + [ViewVariables, AutoNetworkedField] + public Dictionary TargetIntegrities = new() + { + { TargetingBodyParts.Head, TargetIntegrity.Healthy }, + { TargetingBodyParts.Chest, TargetIntegrity.Healthy }, + { TargetingBodyParts.LeftArm, TargetIntegrity.Healthy }, + { TargetingBodyParts.RightArm, TargetIntegrity.Healthy }, + { TargetingBodyParts.LeftLeg, TargetIntegrity.Healthy }, + { TargetingBodyParts.RightLeg, TargetIntegrity.Healthy }, + { TargetingBodyParts.Stomach, TargetIntegrity.Healthy }, + { TargetingBodyParts.RightHand, TargetIntegrity.Healthy }, + { TargetingBodyParts.LeftHand, TargetIntegrity.Healthy }, + { TargetingBodyParts.RightFoot, TargetIntegrity.Healthy }, + { TargetingBodyParts.LeftFoot, TargetIntegrity.Healthy }, + }; + + // Maybe in future, not now, very bad sound + //[DataField, ViewVariables(VVAccess.ReadWrite)] + //public SoundSpecifier SoundToggle = new SoundPathSpecifier("/Audio/White/Targeting/targetingToggle.ogg"); +} + +public enum TargetingBodyParts +{ + Head, + Chest, + LeftArm, + RightArm, + LeftLeg, + RightLeg, + Stomach, + LeftHand, + RightHand, + LeftFoot, + RightFoot +} + +public enum TargetIntegrity +{ + Healthy, + LightlyWounded, + SomewhatWounded, + ModeratelyWounded, + HeavilyWounded, + CriticallyWounded, + Severed, + Dead, + Disabled, +} diff --git a/Content.Shared/_White/Targeting/TargetingEvents.cs b/Content.Shared/_White/Targeting/TargetingEvents.cs new file mode 100644 index 00000000000..e9c631f1099 --- /dev/null +++ b/Content.Shared/_White/Targeting/TargetingEvents.cs @@ -0,0 +1,38 @@ +using Content.Shared._White.Targeting.Components; +using Robust.Shared.Serialization; + +namespace Content.Shared._White.Targeting; + +[Serializable, NetSerializable] +public sealed class TargetingChangeBodyPartEvent : EntityEventArgs +{ + public NetEntity Entity { get; } + public TargetingBodyParts BodyPart { get; } + public TargetingChangeBodyPartEvent(NetEntity entity, TargetingBodyParts bodyPart) + { + Entity = entity; + BodyPart = bodyPart; + } +} + +[Serializable, NetSerializable] +public sealed class TargetingIntegrityChangeEvent : EntityEventArgs +{ + public NetEntity Entity { get; } + public bool NeedRefresh { get; } + public TargetingIntegrityChangeEvent(NetEntity entity, bool needRefresh = true) + { + Entity = entity; + NeedRefresh = needRefresh; + } +} + +public sealed class RefreshInventorySlotsEvent : EntityEventArgs +{ + public string SlotName { get; } + + public RefreshInventorySlotsEvent(string slotName) + { + SlotName = slotName; + } +} diff --git a/Resources/Audio/White/Targeting/targetingToggle.ogg b/Resources/Audio/White/Targeting/targetingToggle.ogg new file mode 100644 index 00000000000..4d1fa9f3325 Binary files /dev/null and b/Resources/Audio/White/Targeting/targetingToggle.ogg differ diff --git a/Resources/Prototypes/Body/Organs/human.yml b/Resources/Prototypes/Body/Organs/human.yml index 69081020ce0..c35a2a8fb5c 100644 --- a/Resources/Prototypes/Body/Organs/human.yml +++ b/Resources/Prototypes/Body/Organs/human.yml @@ -43,6 +43,7 @@ - type: Sprite state: brain - type: Organ + slotId: "brain" - type: Input context: "ghost" - type: Brain @@ -74,6 +75,8 @@ name: eyes description: "I see you!" components: + - type: Organ + slotId: eyes - type: Sprite layers: - state: eyeball-l @@ -119,6 +122,8 @@ - state: lung-l - state: lung-r - type: Lung + - type: Organ + slotId: lungs - type: Metabolizer removeEmpty: true solutionOnBody: false @@ -148,6 +153,8 @@ name: heart description: "I feel bad for the heartless bastard who lost this." components: + - type: Organ + slotId: heart - type: Sprite state: heart-on # The heart 'metabolizes' medicines and poisons that aren't filtered out by other organs. @@ -167,6 +174,8 @@ name: stomach description: "Gross. This is hard to stomach." components: + - type: Organ + slotId: stomach - type: Sprite state: stomach - type: SolutionContainerManager @@ -196,6 +205,8 @@ name: liver description: "Pairing suggestion: chianti and fava beans." components: + - type: Organ + slotId: liver - type: Sprite state: liver - type: Metabolizer # The liver metabolizes certain chemicals only, like alcohol. diff --git a/Resources/Prototypes/Body/Prototypes/a_ghost.yml b/Resources/Prototypes/Body/Prototypes/a_ghost.yml index 09784c3ef53..f04ed70197e 100644 --- a/Resources/Prototypes/Body/Prototypes/a_ghost.yml +++ b/Resources/Prototypes/Body/Prototypes/a_ghost.yml @@ -6,17 +6,17 @@ torso: part: TorsoHuman connections: - - right_arm - - left_arm - right_arm: + - right arm + - left arm + right arm: part: RightArmHuman connections: - - right_hand - left_arm: + - right hand + left arm: part: LeftArmHuman connections: - - left_hand - right_hand: + - left hand + right hand: part: RightHandHuman - left_hand: + left hand: part: LeftHandHuman diff --git a/Resources/Prototypes/Body/Prototypes/human.yml b/Resources/Prototypes/Body/Prototypes/human.yml index 94c77a27d73..7a0f3bb5a7b 100644 --- a/Resources/Prototypes/Body/Prototypes/human.yml +++ b/Resources/Prototypes/Body/Prototypes/human.yml @@ -13,37 +13,37 @@ torso: part: TorsoHuman connections: - - right_arm - - left_arm - - right_leg - - left_leg + - right arm + - left arm + - right leg + - left leg organs: heart: OrganHumanHeart lungs: OrganHumanLungs stomach: OrganHumanStomach liver: OrganHumanLiver kidneys: OrganHumanKidneys - right_arm: + right arm: part: RightArmHuman connections: - - right_hand - left_arm: + - right hand + left arm: part: LeftArmHuman connections: - - left_hand - right_hand: + - left hand + right hand: part: RightHandHuman - left_hand: + left hand: part: LeftHandHuman - right_leg: + right leg: part: RightLegHuman connections: - - right_foot - left_leg: + - right foot + left leg: part: LeftLegHuman connections: - - left_foot - right_foot: + - left foot + right foot: part: RightFootHuman - left_foot: + left foot: part: LeftFootHuman diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 0466cfd26d8..05661a96381 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -239,6 +239,7 @@ amount: 5 - type: Speech speechSounds: Alto + - type: Targeting - type: DamageForceSay - type: Vocal sounds: @@ -280,6 +281,7 @@ id: BaseMobSpeciesOrganic abstract: true components: + - type: Targeting - type: Barotrauma damage: types: @@ -336,6 +338,7 @@ id: BaseSpeciesDummy abstract: true components: + - type: Targeting - type: Hands - type: Inventory - type: InventorySlots diff --git a/Resources/Textures/Interface/Ashen/targeting_doll.png b/Resources/Textures/Interface/Ashen/targeting_doll.png new file mode 100644 index 00000000000..48bde9834f3 Binary files /dev/null and b/Resources/Textures/Interface/Ashen/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Clockwork/targeting_doll.png b/Resources/Textures/Interface/Clockwork/targeting_doll.png new file mode 100644 index 00000000000..46e6ac9e1d0 Binary files /dev/null and b/Resources/Textures/Interface/Clockwork/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Default/targeting_doll.png b/Resources/Textures/Interface/Default/targeting_doll.png new file mode 100644 index 00000000000..78404dd74cc Binary files /dev/null and b/Resources/Textures/Interface/Default/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Minimalist/targeting_doll.png b/Resources/Textures/Interface/Minimalist/targeting_doll.png new file mode 100644 index 00000000000..48bde9834f3 Binary files /dev/null and b/Resources/Textures/Interface/Minimalist/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Plasmafire/targeting_doll.png b/Resources/Textures/Interface/Plasmafire/targeting_doll.png new file mode 100644 index 00000000000..dc718d1bc25 Binary files /dev/null and b/Resources/Textures/Interface/Plasmafire/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Retro/targeting_doll.png b/Resources/Textures/Interface/Retro/targeting_doll.png new file mode 100644 index 00000000000..a60975c7a4b Binary files /dev/null and b/Resources/Textures/Interface/Retro/targeting_doll.png differ diff --git a/Resources/Textures/Interface/Slimecore/targeting_doll.png b/Resources/Textures/Interface/Slimecore/targeting_doll.png new file mode 100644 index 00000000000..78404dd74cc Binary files /dev/null and b/Resources/Textures/Interface/Slimecore/targeting_doll.png differ diff --git a/Resources/Textures/White/Targeting/Doll/head.png b/Resources/Textures/White/Targeting/Doll/head.png new file mode 100644 index 00000000000..ae7e1873b7e Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/head.png differ diff --git a/Resources/Textures/White/Targeting/Doll/head_hover.png b/Resources/Textures/White/Targeting/Doll/head_hover.png new file mode 100644 index 00000000000..c953d846162 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/head_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftarm.png b/Resources/Textures/White/Targeting/Doll/leftarm.png new file mode 100644 index 00000000000..6a3878161e6 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftarm.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftarm_hover.png b/Resources/Textures/White/Targeting/Doll/leftarm_hover.png new file mode 100644 index 00000000000..e69308ff583 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftarm_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftfoot.png b/Resources/Textures/White/Targeting/Doll/leftfoot.png new file mode 100644 index 00000000000..a445715729f Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftfoot.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftfoot_hover.png b/Resources/Textures/White/Targeting/Doll/leftfoot_hover.png new file mode 100644 index 00000000000..b094ee0a466 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftfoot_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/lefthand.png b/Resources/Textures/White/Targeting/Doll/lefthand.png new file mode 100644 index 00000000000..3ee7b8b7a96 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/lefthand.png differ diff --git a/Resources/Textures/White/Targeting/Doll/lefthand_hover.png b/Resources/Textures/White/Targeting/Doll/lefthand_hover.png new file mode 100644 index 00000000000..fa0526b6f99 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/lefthand_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftleg.png b/Resources/Textures/White/Targeting/Doll/leftleg.png new file mode 100644 index 00000000000..4cec83a8687 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftleg.png differ diff --git a/Resources/Textures/White/Targeting/Doll/leftleg_hover.png b/Resources/Textures/White/Targeting/Doll/leftleg_hover.png new file mode 100644 index 00000000000..3914b94fdb7 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/leftleg_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/mouth.png b/Resources/Textures/White/Targeting/Doll/mouth.png new file mode 100644 index 00000000000..da12f632d1e Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/mouth.png differ diff --git a/Resources/Textures/White/Targeting/Doll/mouth_hover.png b/Resources/Textures/White/Targeting/Doll/mouth_hover.png new file mode 100644 index 00000000000..d1ea568a11e Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/mouth_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightarm.png b/Resources/Textures/White/Targeting/Doll/rightarm.png new file mode 100644 index 00000000000..aa33a31faa4 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightarm.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightarm_hover.png b/Resources/Textures/White/Targeting/Doll/rightarm_hover.png new file mode 100644 index 00000000000..f1873705275 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightarm_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightfoot.png b/Resources/Textures/White/Targeting/Doll/rightfoot.png new file mode 100644 index 00000000000..399d298c18e Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightfoot.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightfoot_hover.png b/Resources/Textures/White/Targeting/Doll/rightfoot_hover.png new file mode 100644 index 00000000000..d1e4d2b9c76 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightfoot_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/righthand.png b/Resources/Textures/White/Targeting/Doll/righthand.png new file mode 100644 index 00000000000..ae489df8bf8 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/righthand.png differ diff --git a/Resources/Textures/White/Targeting/Doll/righthand_hover.png b/Resources/Textures/White/Targeting/Doll/righthand_hover.png new file mode 100644 index 00000000000..097e5516959 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/righthand_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightleg.png b/Resources/Textures/White/Targeting/Doll/rightleg.png new file mode 100644 index 00000000000..77bc5d17453 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightleg.png differ diff --git a/Resources/Textures/White/Targeting/Doll/rightleg_hover.png b/Resources/Textures/White/Targeting/Doll/rightleg_hover.png new file mode 100644 index 00000000000..2bc97d85309 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/rightleg_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/stomach.png b/Resources/Textures/White/Targeting/Doll/stomach.png new file mode 100644 index 00000000000..66958a609da Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/stomach.png differ diff --git a/Resources/Textures/White/Targeting/Doll/stomach_hover.png b/Resources/Textures/White/Targeting/Doll/stomach_hover.png new file mode 100644 index 00000000000..b6fcd4468fc Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/stomach_hover.png differ diff --git a/Resources/Textures/White/Targeting/Doll/torso.png b/Resources/Textures/White/Targeting/Doll/torso.png new file mode 100644 index 00000000000..4c381498815 Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/torso.png differ diff --git a/Resources/Textures/White/Targeting/Doll/torso_hover.png b/Resources/Textures/White/Targeting/Doll/torso_hover.png new file mode 100644 index 00000000000..d6cd3462c1c Binary files /dev/null and b/Resources/Textures/White/Targeting/Doll/torso_hover.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_0.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_0.png new file mode 100644 index 00000000000..b20ce001ba6 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_1.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_1.png new file mode 100644 index 00000000000..591b6a5bab5 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_2.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_2.png new file mode 100644 index 00000000000..71f09fc7f6b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_3.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_3.png new file mode 100644 index 00000000000..fa9f954321c Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_4.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_4.png new file mode 100644 index 00000000000..ada865a05fe Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_5.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_5.png new file mode 100644 index 00000000000..eefec17cf60 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/chest_6unused.png b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_6unused.png new file mode 100644 index 00000000000..c289a454bdb Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/chest.rsi/chest_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/chest.rsi/meta.json b/Resources/Textures/White/Targeting/Status/chest.rsi/meta.json new file mode 100644 index 00000000000..b175f743e72 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/chest.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "chest_0" + }, + { + "name": "chest_1" + }, + { + "name": "chest_2" + }, + { + "name": "chest_3" + }, + { + "name": "chest_4" + }, + { + "name": "chest_5" + }, + { + "name": "chest_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_0.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_0.png new file mode 100644 index 00000000000..2e46e3a8cf1 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_1.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_1.png new file mode 100644 index 00000000000..7df0059c12c Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_2.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_2.png new file mode 100644 index 00000000000..8a6e3add67f Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_3.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_3.png new file mode 100644 index 00000000000..6d7966fc141 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_4.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_4.png new file mode 100644 index 00000000000..cc36cf23ca4 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_5.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_5.png new file mode 100644 index 00000000000..c23961f396b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/groin_6unused.png b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_6unused.png new file mode 100644 index 00000000000..0bb632ba388 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/groin.rsi/groin_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/groin.rsi/meta.json b/Resources/Textures/White/Targeting/Status/groin.rsi/meta.json new file mode 100644 index 00000000000..06ca3f6bd1c --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/groin.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "groin_0" + }, + { + "name": "groin_1" + }, + { + "name": "groin_2" + }, + { + "name": "groin_3" + }, + { + "name": "groin_4" + }, + { + "name": "groin_5" + }, + { + "name": "groin_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_0.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_0.png new file mode 100644 index 00000000000..f547b0bc961 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_1.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_1.png new file mode 100644 index 00000000000..0ba1a77dfd9 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_2.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_2.png new file mode 100644 index 00000000000..1cb55b4fe97 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_3.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_3.png new file mode 100644 index 00000000000..d797b40a161 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_4.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_4.png new file mode 100644 index 00000000000..fbc1678ce5d Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_5.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_5.png new file mode 100644 index 00000000000..4d024c61f7f Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/head_6unused.png b/Resources/Textures/White/Targeting/Status/head.rsi/head_6unused.png new file mode 100644 index 00000000000..74b58c642bb Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/head.rsi/head_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/head.rsi/meta.json b/Resources/Textures/White/Targeting/Status/head.rsi/meta.json new file mode 100644 index 00000000000..d0faf3a6eb2 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/head.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "head_0" + }, + { + "name": "head_1" + }, + { + "name": "head_2" + }, + { + "name": "head_3" + }, + { + "name": "head_4" + }, + { + "name": "head_5" + }, + { + "name": "head_6unused" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_0.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_0.png new file mode 100644 index 00000000000..22c7982489b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_1.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_1.png new file mode 100644 index 00000000000..cd3b5d4c1c8 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_2.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_2.png new file mode 100644 index 00000000000..e4db1961679 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_3.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_3.png new file mode 100644 index 00000000000..d6a204a18a9 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_4.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_4.png new file mode 100644 index 00000000000..2c9e81508b3 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_5.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_5.png new file mode 100644 index 00000000000..a00a6b1822e Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_6unused.png b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_6unused.png new file mode 100644 index 00000000000..efc7380c270 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftarm.rsi/leftarm_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftarm.rsi/meta.json b/Resources/Textures/White/Targeting/Status/leftarm.rsi/meta.json new file mode 100644 index 00000000000..33dfab0d90d --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/leftarm.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "leftarm_0" + }, + { + "name": "leftarm_1" + }, + { + "name": "leftarm_2" + }, + { + "name": "leftarm_3" + }, + { + "name": "leftarm_4" + }, + { + "name": "leftarm_5" + }, + { + "name": "leftarm_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_0.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_0.png new file mode 100644 index 00000000000..af6e8eb45e5 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_1.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_1.png new file mode 100644 index 00000000000..b8e10c8c48c Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_2.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_2.png new file mode 100644 index 00000000000..31feb63b7bc Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_3.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_3.png new file mode 100644 index 00000000000..274855e4194 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_4.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_4.png new file mode 100644 index 00000000000..b3e5dfefa16 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_5.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_5.png new file mode 100644 index 00000000000..bdaec2557cb Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_6unused.png b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_6unused.png new file mode 100644 index 00000000000..9822dfba4cb Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/leftfoot_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftfoot.rsi/meta.json b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/meta.json new file mode 100644 index 00000000000..3e6b122ac9c --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/leftfoot.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "leftfoot_0" + }, + { + "name": "leftfoot_1" + }, + { + "name": "leftfoot_2" + }, + { + "name": "leftfoot_3" + }, + { + "name": "leftfoot_4" + }, + { + "name": "leftfoot_5" + }, + { + "name": "leftfoot_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_0.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_0.png new file mode 100644 index 00000000000..f56984a54eb Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_1.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_1.png new file mode 100644 index 00000000000..e5a7aea1b40 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_2.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_2.png new file mode 100644 index 00000000000..43c72f0b210 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_3.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_3.png new file mode 100644 index 00000000000..3114a1995cd Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_4.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_4.png new file mode 100644 index 00000000000..83c4daefabf Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_5.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_5.png new file mode 100644 index 00000000000..2b33680d438 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_6unused.png b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_6unused.png new file mode 100644 index 00000000000..7d2ed496616 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/lefthand.rsi/lefthand_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/lefthand.rsi/meta.json b/Resources/Textures/White/Targeting/Status/lefthand.rsi/meta.json new file mode 100644 index 00000000000..21597c125ff --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/lefthand.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "lefthand_0" + }, + { + "name": "lefthand_1" + }, + { + "name": "lefthand_2" + }, + { + "name": "lefthand_3" + }, + { + "name": "lefthand_4" + }, + { + "name": "lefthand_5" + }, + { + "name": "lefthand_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_0.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_0.png new file mode 100644 index 00000000000..9f8193be960 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_1.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_1.png new file mode 100644 index 00000000000..ab0c3e410da Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_2.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_2.png new file mode 100644 index 00000000000..6390bbf7ab6 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_3.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_3.png new file mode 100644 index 00000000000..9159aebd456 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_4.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_4.png new file mode 100644 index 00000000000..9dcd84fffdf Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_5.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_5.png new file mode 100644 index 00000000000..75bd581d69b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_6unused.png b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_6unused.png new file mode 100644 index 00000000000..d36a43c441d Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/leftleg.rsi/leftleg_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/leftleg.rsi/meta.json b/Resources/Textures/White/Targeting/Status/leftleg.rsi/meta.json new file mode 100644 index 00000000000..05a89188295 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/leftleg.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "leftleg_0" + }, + { + "name": "leftleg_1" + }, + { + "name": "leftleg_2" + }, + { + "name": "leftleg_3" + }, + { + "name": "leftleg_4" + }, + { + "name": "leftleg_5" + }, + { + "name": "leftleg_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/meta.json b/Resources/Textures/White/Targeting/Status/rightarm.rsi/meta.json new file mode 100644 index 00000000000..a6751d91bda --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/rightarm.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "rightarm_0" + }, + { + "name": "rightarm_1" + }, + { + "name": "rightarm_2" + }, + { + "name": "rightarm_3" + }, + { + "name": "rightarm_4" + }, + { + "name": "rightarm_5" + }, + { + "name": "rightarm_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_0.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_0.png new file mode 100644 index 00000000000..44c8aca6329 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_1.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_1.png new file mode 100644 index 00000000000..035e0ae12e9 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_2.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_2.png new file mode 100644 index 00000000000..f6db2e12a9b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_3.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_3.png new file mode 100644 index 00000000000..cd974fdeea6 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_4.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_4.png new file mode 100644 index 00000000000..0a5977cfaf8 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_5.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_5.png new file mode 100644 index 00000000000..9f894b1bfb3 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_6unused.png b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_6unused.png new file mode 100644 index 00000000000..35eec2905a5 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightarm.rsi/rightarm_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/meta.json b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/meta.json new file mode 100644 index 00000000000..15d0b7aa855 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "rightfoot_0" + }, + { + "name": "rightfoot_1" + }, + { + "name": "rightfoot_2" + }, + { + "name": "rightfoot_3" + }, + { + "name": "rightfoot_4" + }, + { + "name": "rightfoot_5" + }, + { + "name": "rightfoot_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_0.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_0.png new file mode 100644 index 00000000000..573e32ca106 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_1.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_1.png new file mode 100644 index 00000000000..967639b3fd1 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_2.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_2.png new file mode 100644 index 00000000000..bff7d8016d0 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_3.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_3.png new file mode 100644 index 00000000000..d74824df983 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_4.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_4.png new file mode 100644 index 00000000000..50f6abc2c34 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_5.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_5.png new file mode 100644 index 00000000000..06ab1d2519d Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_6unused.png b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_6unused.png new file mode 100644 index 00000000000..ebc654d70e9 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightfoot.rsi/rightfoot_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/meta.json b/Resources/Textures/White/Targeting/Status/righthand.rsi/meta.json new file mode 100644 index 00000000000..0652c3f04d5 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/righthand.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "righthand_0" + }, + { + "name": "righthand_1" + }, + { + "name": "righthand_2" + }, + { + "name": "righthand_3" + }, + { + "name": "righthand_4" + }, + { + "name": "righthand_5" + }, + { + "name": "righthand_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_0.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_0.png new file mode 100644 index 00000000000..a69056bb651 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_1.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_1.png new file mode 100644 index 00000000000..e14168b2e7d Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_2.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_2.png new file mode 100644 index 00000000000..b12b15e883b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_3.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_3.png new file mode 100644 index 00000000000..a030aa0980c Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_4.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_4.png new file mode 100644 index 00000000000..4afd3e7f531 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_5.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_5.png new file mode 100644 index 00000000000..797e0683e8b Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_6unused.png b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_6unused.png new file mode 100644 index 00000000000..87e8f18ef82 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/righthand.rsi/righthand_6unused.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/meta.json b/Resources/Textures/White/Targeting/Status/rightleg.rsi/meta.json new file mode 100644 index 00000000000..b056021b841 --- /dev/null +++ b/Resources/Textures/White/Targeting/Status/rightleg.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Tgstation sprites taken at commit https://github.com/tgstation/tgstation/commit/c7e14784b35b1a136351c396d3a546f461ee2451", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "rightleg_0" + }, + { + "name": "rightleg_1" + }, + { + "name": "rightleg_2" + }, + { + "name": "rightleg_3" + }, + { + "name": "rightleg_4" + }, + { + "name": "rightleg_5" + }, + { + "name": "rightleg_6unused" + } + ] +} diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_0.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_0.png new file mode 100644 index 00000000000..f773330b026 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_0.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_1.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_1.png new file mode 100644 index 00000000000..786b0777c38 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_1.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_2.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_2.png new file mode 100644 index 00000000000..2ac7cbafa6d Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_2.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_3.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_3.png new file mode 100644 index 00000000000..2f9690690d7 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_3.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_4.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_4.png new file mode 100644 index 00000000000..ec62ccb0627 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_4.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_5.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_5.png new file mode 100644 index 00000000000..70ccb309add Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_5.png differ diff --git a/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_6unused.png b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_6unused.png new file mode 100644 index 00000000000..9c4ee1f9038 Binary files /dev/null and b/Resources/Textures/White/Targeting/Status/rightleg.rsi/rightleg_6unused.png differ