From 60ad045f86730aa6a4ec8d72ba8e970922cd147b Mon Sep 17 00:00:00 2001 From: 21Melkuu <79728504+21Melkuu@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:04:00 +0300 Subject: [PATCH] ReactiveTeleportArmorRD (#1802) * NeSMOTRET' * x2 * ewe chyt' chyt' u ya ymry * pochti!!! * Spriteri RABOTAT' * ChanceFix * DexRev * kto prochital tot sdox * microfix * ache) * hz * gnomaLoxGonaLust) * cheki * probel * probel2 * cheki * Update Resources/Locale/ru-RU/ss220/prototypes/entities/clothing/outerclothing/reactivearmor.ftl Co-authored-by: Ady4ik <141335742+Ady4ik@users.noreply.github.com> * Update Resources/Prototypes/Catalog/Fills/Lockers/heads.yml Co-authored-by: Ady4ik <141335742+Ady4ik@users.noreply.github.com> * fix typosti * NASRANO --------- Co-authored-by: Ady4ik <141335742+Ady4ik@users.noreply.github.com> --- .../ReactiveTeleportArmorComponent.cs | 12 ++ .../ReactiveTeleportArmorSystem.cs | 179 ++++++++++++++++++ .../TeleportOnDamageComponent.cs | 44 +++++ .../ss220/clothing/OuterClothing/armor.ftl | 3 + .../components/reactivearnor-component.ftl | 1 + .../ss220/objectives/steal-target-groups.ftl | 3 +- .../clothing/outerclothing/reactivearmor.ftl | 2 + .../Catalog/Fills/Lockers/heads.yml | 3 +- .../Prototypes/Objectives/objectiveGroups.yml | 1 + .../OuterClothing/reactive_armor_rd.yml | 57 ++++++ .../SS220/Objectives/stealTargetGroups.yml | 9 +- .../Prototypes/SS220/Objectives/traitor.yml | 10 + .../equipped-OUTERCLOTHING.png | Bin 0 -> 932 bytes .../Armor/reactive_armor.rsi/icon-on.png | Bin 0 -> 539 bytes .../Armor/reactive_armor.rsi/icon.png | Bin 0 -> 418 bytes .../Armor/reactive_armor.rsi/inhand-left.png | Bin 0 -> 583 bytes .../Armor/reactive_armor.rsi/inhand-right.png | Bin 0 -> 552 bytes .../Armor/reactive_armor.rsi/meta.json | 33 ++++ .../on-equipped-OUTERCLOTHING.png | Bin 0 -> 4298 bytes 19 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorComponent.cs create mode 100644 Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorSystem.cs create mode 100644 Content.Server/SS220/ReactiveTeleportArmor/TeleportOnDamageComponent.cs create mode 100644 Resources/Locale/ru-RU/ss220/clothing/components/reactivearnor-component.ftl create mode 100644 Resources/Locale/ru-RU/ss220/prototypes/entities/clothing/outerclothing/reactivearmor.ftl create mode 100644 Resources/Prototypes/SS220/Entities/Clothing/OuterClothing/reactive_armor_rd.yml create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/equipped-OUTERCLOTHING.png create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/icon-on.png create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/icon.png create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/inhand-left.png create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/inhand-right.png create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/meta.json create mode 100644 Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/on-equipped-OUTERCLOTHING.png diff --git a/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorComponent.cs b/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorComponent.cs new file mode 100644 index 00000000000000..c891e460a5bbc1 --- /dev/null +++ b/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorComponent.cs @@ -0,0 +1,12 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.tx +namespace Content.Server.SS220.ReactiveTeleportArmor +{ + /// + /// Intermediate component to work with TeleportOnDamageComponent + /// + [RegisterComponent] + public sealed partial class ReactiveTeleportArmorComponent : Component + { + + } +} diff --git a/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorSystem.cs b/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorSystem.cs new file mode 100644 index 00000000000000..d776a420701ba4 --- /dev/null +++ b/Content.Server/SS220/ReactiveTeleportArmor/ReactiveTeleportArmorSystem.cs @@ -0,0 +1,179 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Robust.Shared.Random; +using Content.Shared.Damage; +using Content.Shared.Movement.Pulling.Systems; +using Content.Shared.Movement.Pulling.Components; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Map.Components; +using System.Numerics; +using Content.Shared.Physics; +using Robust.Shared.Collections; +using Content.Shared.Clothing; +using Content.Shared.Clothing.EntitySystems; +using Content.Server.Explosion.EntitySystems; +using Content.Shared.Item; +using Content.Shared.Item.ItemToggle; +using Content.Shared.Item.ItemToggle.Components; +using Content.Shared.Timing; +using Timer = Robust.Shared.Timing.Timer; + +namespace Content.Server.SS220.ReactiveTeleportArmor +{ + internal class ReactiveTeleportArmorSystem : EntitySystem + { + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedTransformSystem _xform = default!; + [Dependency] private readonly PullingSystem _pullingSystem = default!; + [Dependency] private readonly EntityLookupSystem _lookupSystem = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; + [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly SharedItemSystem _item = default!; + [Dependency] private readonly ClothingSystem _clothing = default!; + [Dependency] private readonly ItemToggleSystem _toggle = default!; + + private EntityQuery _physicsQuery; + private HashSet> _targetGrids = []; + + public override void Initialize() + { + _physicsQuery = GetEntityQuery(); + + base.Initialize(); + SubscribeLocalEvent(TeleporWhenDamaged); + SubscribeLocalEvent(OnEquip); + SubscribeLocalEvent(OnUnequip); + SubscribeLocalEvent(ToggleDone); + } + + private void OnEquip(Entity ent, ref ClothingGotEquippedEvent args) + { + EnsureComp(args.Wearer, out var comp); + comp.SavedUid = ent; + } + + private void OnUnequip(Entity ent, ref ClothingGotUnequippedEvent args) + { + RemComp(args.Wearer); + } + + private void ToggleDone(Entity ent, ref ItemToggledEvent args) + { + var prefix = args.Activated ? "on" : null; + _item.SetHeldPrefix(ent, prefix); + _clothing.SetEquippedPrefix(ent, prefix); + } + + + private void TeleporWhenDamaged(Entity ent, ref DamageChangedEvent args) + { + if (!TryComp(ent, out var armor)) + return; + + var xform = Transform(ent.Owner); + var targetCoords = SelectRandomTileInRange(xform, armor.TeleportRadius); + + if (!args.DamageIncreased || args.DamageDelta == null) + return; + ///teleport entity if taken damage && coord = !null && armor is on && !cooldown + if (args.DamageDelta.GetTotal() >= ent.Comp.WakeThreshold && targetCoords != null && _toggle.IsActivated(ent.Comp.SavedUid) && !ent.Comp.OnCoolDown) + { + ent.Comp.OnCoolDown = true; + + // We need stop the user from being pulled so they don't just get "attached" with whoever is pulling them. + // This can for example happen when the user is cuffed and being pulled. + if (TryComp(ent.Owner, out var pull) && _pullingSystem.IsPulled(ent.Owner, pull)) + _pullingSystem.TryStopPull(ent.Owner, pull); + + if (_random.Prob(ent.Comp.TeleportChance)) + { + _xform.SetCoordinates(ent.Owner, targetCoords.Value); + _audio.PlayPvs(armor.TeleportSound, ent.Owner); + SelectRandomTileInRange(xform, armor.TeleportRadius); + } + else + { + _explosion.TriggerExplosive(ent.Comp.SavedUid); + } + Timer.Spawn(ent.Comp.CoolDownTime, () => ent.Comp.OnCoolDown = false); + } + } + + private EntityCoordinates? SelectRandomTileInRange(TransformComponent userXform, float radius) + { + var userCoords = userXform.Coordinates.ToMap(EntityManager, _xform); + _targetGrids.Clear(); + _lookupSystem.GetEntitiesInRange(userCoords, radius, _targetGrids); + Entity? targetGrid = null; + + if (_targetGrids.Count == 0) + return null; + + // Give preference to the grid the entity is currently on. + // This does not guarantee that if the probability fails that the owner's grid won't be picked. + // In reality the probability is higher and depends on the number of grids. + if (userXform.GridUid != null && TryComp(userXform.GridUid, out var gridComp)) + { + var userGrid = new Entity(userXform.GridUid.Value, gridComp); + if (_random.Prob(0.5f)) + { + _targetGrids.Remove(userGrid); + targetGrid = userGrid; + } + } + + if (targetGrid == null) + targetGrid = _random.GetRandom().PickAndTake(_targetGrids); + + EntityCoordinates? targetCoords = null; + + var valid = false; + + var range = (float)Math.Sqrt(radius); + var box = Box2.CenteredAround(userCoords.Position, new Vector2(range, range)); + var tilesInRange = _mapSystem.GetTilesEnumerator(targetGrid.Value.Owner, targetGrid.Value.Comp, box, false); + var tileList = new ValueList(); + + while (tilesInRange.MoveNext(out var tile)) + { + tileList.Add(tile.GridIndices); + } + + while (tileList.Count != 0) + { + var tile = tileList.RemoveSwap(_random.Next(tileList.Count)); + valid = true; + foreach (var entity in _mapSystem.GetAnchoredEntities(targetGrid.Value.Owner, targetGrid.Value.Comp, + tile)) + { + if (!_physicsQuery.TryGetComponent(entity, out var body)) + continue; + + if (body.BodyType != BodyType.Static || + !body.Hard || + (body.CollisionLayer & (int)CollisionGroup.MobMask) == 0) + continue; + + valid = false; + break; + } + + if (valid) + { + targetCoords = new EntityCoordinates(targetGrid.Value.Owner, + _mapSystem.TileCenterToVector(targetGrid.Value, tile)); + break; + } + } + + if (!valid || _targetGrids.Count != 0) // if we don't do the check here then PickAndTake will blow up on an empty set. + targetGrid = _random.GetRandom().PickAndTake(_targetGrids); + + return targetCoords; + + } + } +} diff --git a/Content.Server/SS220/ReactiveTeleportArmor/TeleportOnDamageComponent.cs b/Content.Server/SS220/ReactiveTeleportArmor/TeleportOnDamageComponent.cs new file mode 100644 index 00000000000000..3b57078c30f325 --- /dev/null +++ b/Content.Server/SS220/ReactiveTeleportArmor/TeleportOnDamageComponent.cs @@ -0,0 +1,44 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt + +using Robust.Shared.Audio; +using Content.Shared.FixedPoint; + +namespace Content.Server.SS220.ReactiveTeleportArmor; + +/// +/// Randomly teleports entity when damaged. +/// +[RegisterComponent] +public sealed partial class TeleportOnDamageComponent : Component +{ + /// + /// Up to how far to teleport the user + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float TeleportRadius = 50f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg"); + + /// + /// How much damage of any type it takes to wake this entity. + /// + [DataField] + public FixedPoint2 WakeThreshold = FixedPoint2.New(4); + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float TeleportChance = .9f; + + /// + /// Need if you want to interact with the entity that provided the TeleportOnDamageComponent. + /// + [ViewVariables] + public EntityUid SavedUid; + + public bool OnCoolDown = false; + + [DataField] + public TimeSpan CoolDownTime = TimeSpan.FromSeconds(10); +} + + diff --git a/Resources/Locale/ru-RU/ss220/clothing/OuterClothing/armor.ftl b/Resources/Locale/ru-RU/ss220/clothing/OuterClothing/armor.ftl index df7d791a829962..1f8048a9d57e50 100644 --- a/Resources/Locale/ru-RU/ss220/clothing/OuterClothing/armor.ftl +++ b/Resources/Locale/ru-RU/ss220/clothing/OuterClothing/armor.ftl @@ -1,2 +1,5 @@ ent-ClothingOuterArmorCentcomNavalCarapace = флотский панцирь .desc = Панцирь, который носят офицеры Командования флота. + +ent-ClothingOuterReactiveArmor = экспериментальная реактивная броня + .desc = Новейший прототип брони, основанный на ядре аномалии. Ходят слухи, что учёные NT разрабатывают более стабильную и многозадачную версию. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/clothing/components/reactivearnor-component.ftl b/Resources/Locale/ru-RU/ss220/clothing/components/reactivearnor-component.ftl new file mode 100644 index 00000000000000..88b24f9de3ee98 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/clothing/components/reactivearnor-component.ftl @@ -0,0 +1 @@ +toggle-reactivearmor-verb-get-data-text = Переключить реактивную броню \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/objectives/steal-target-groups.ftl b/Resources/Locale/ru-RU/ss220/objectives/steal-target-groups.ftl index 7b31e2361e5a3c..775c49d9e4b95c 100644 --- a/Resources/Locale/ru-RU/ss220/objectives/steal-target-groups.ftl +++ b/Resources/Locale/ru-RU/ss220/objectives/steal-target-groups.ftl @@ -6,4 +6,5 @@ steal-target-groups-wrist-watch-gold = наручные часы командо steal-target-groups-expensive-lighter-syndicate = { ent-ExpensiveLighterSyndicate } steal-target-groups-expensive-lighter-nanotrasen = { ent-ExpensiveLighterNanotrasen } steal-target-groups-expensive-lighter-shield = { ent-ExpensiveLighterShield } -steal-target-groups-expensive-lighter-detective = { ent-ExpensiveLighterDetective } \ No newline at end of file +steal-target-groups-expensive-lighter-detective = { ent-ExpensiveLighterDetective } +steal-target-groups-reactive-armor = { ent-ClothingOuterReactiveArmor } \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss220/prototypes/entities/clothing/outerclothing/reactivearmor.ftl b/Resources/Locale/ru-RU/ss220/prototypes/entities/clothing/outerclothing/reactivearmor.ftl new file mode 100644 index 00000000000000..c9045af7cb3521 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/prototypes/entities/clothing/outerclothing/reactivearmor.ftl @@ -0,0 +1,2 @@ +ent-ActionToggleReactiveArmor = Переключить реактивную броню + .desc = Включает или выключает реактивную броню. \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml b/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml index 052a7683c401a8..d8b7c5f8cbe481 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/heads.yml @@ -288,6 +288,7 @@ - id: ClothingWristWatchGold # SS220 Wrist Watch - id: Telescopichka # SS220 Telescopic Baton - id: CigPackRnD #SS220 Cigarettes + - id: ClothingOuterReactiveArmor #SS220 New RD highrisk # Hardsuit table, used for suit storage as well - type: entityTable @@ -402,4 +403,4 @@ - id: JetpackBlue - id: SpaceCash1000 - id: BeachBall - - id: BikeHorn + - id: BikeHorn \ No newline at end of file diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index d40ac57df7e771..101775b8fe5fb0 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -21,6 +21,7 @@ EngravedKnuckledusterStealObjective: 1 #SS220 New Qm highrisk CaptainGunStealObjective: 0.5 CaptainJetpackStealObjective: 0.5 + ClothingOuterReactiveArmorObjective: 0.5 #SS220 New RD highrisk HandTeleporterStealObjective: 0.5 SecretDocumentsStealObjective: 0.5 MultiPhaseEnergyGunStealObjective: 0.5 #SS220 MultiPhaze Energy Gun diff --git a/Resources/Prototypes/SS220/Entities/Clothing/OuterClothing/reactive_armor_rd.yml b/Resources/Prototypes/SS220/Entities/Clothing/OuterClothing/reactive_armor_rd.yml new file mode 100644 index 00000000000000..08dc53b6be394b --- /dev/null +++ b/Resources/Prototypes/SS220/Entities/Clothing/OuterClothing/reactive_armor_rd.yml @@ -0,0 +1,57 @@ +- type: entity + parent: [ClothingOuterBaseLarge, AllowSuitStorageClothing, BaseToggleClothing] + id: ClothingOuterReactiveArmor + name: experimental reactive armor + description: The latest armor prototype based on the anomaly core. There are rumors that NT scientists are developing a more stable and multitasking version. + components: + - type: Sprite + sprite: SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi + layers: + - state: icon + map: [ "enum.ToggleVisuals.Layer" ] + - type: Clothing + sprite: SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi + - type: Appearance + - type: GenericVisualizer + visuals: + enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Layer: + True: {state: icon-on} + False: {state: icon} + - type: Armor + modifiers: + coefficients: + Blunt: 0.5 + Slash: 0.5 + Piercing: 0.6 + Heat: 0.5 + Caustic: 0.9 + - type: HeldSpeedModifier + - type: ToggleClothing + action: ActionToggleReactiveArmor + - type: ToggleVerb + text: toggle-reactivearmor-verb-get-data-text + - type: GroupExamine + - type: ReactiveTeleportArmor + - type: Explosive + explosionType: Default + maxIntensity: 2 + totalIntensity: 1.5 + intensitySlope: 1 + canCreateVacuum: false + deleteAfterExplosion: false + repeatable: true + - type: Tag + tags: + - HighRiskItem + +- type: entity + id: ActionToggleReactiveArmor + name: Toggle Reactive armor + description: Toggles the armor on and off. + components: + - type: InstantAction + useDelay: 5 + priority: -9 + itemIconStyle: BigItem + event: !type:ToggleActionEvent \ No newline at end of file diff --git a/Resources/Prototypes/SS220/Objectives/stealTargetGroups.yml b/Resources/Prototypes/SS220/Objectives/stealTargetGroups.yml index be84ba10e894aa..9b666fe77c65ce 100644 --- a/Resources/Prototypes/SS220/Objectives/stealTargetGroups.yml +++ b/Resources/Prototypes/SS220/Objectives/stealTargetGroups.yml @@ -20,6 +20,13 @@ state: icon - type: stealTargetGroup + id: ClothingOuterReactiveArmor + name: steal-target-groups-reactive-armor + sprite: + sprite: SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi + state: icon + +- type: stealTargetGroup id: WristWatchGold name: steal-target-groups-wrist-watch-gold sprite: @@ -60,4 +67,4 @@ name: steal-target-groups-salvage-shuttle-console-board sprite: sprite: Objects/Misc/module.rsi - state: cpuboard \ No newline at end of file + state: cpuboard diff --git a/Resources/Prototypes/SS220/Objectives/traitor.yml b/Resources/Prototypes/SS220/Objectives/traitor.yml index 1157d31ccff947..f2b1567da8b351 100644 --- a/Resources/Prototypes/SS220/Objectives/traitor.yml +++ b/Resources/Prototypes/SS220/Objectives/traitor.yml @@ -21,3 +21,13 @@ - type: StealCondition stealGroup: WeaponMultiPhaseEnergyGun owner: job-name-hos + +- type: entity + parent: BaseTraitorStealObjective + id: ClothingOuterReactiveArmorObjective + components: + - type: NotJobRequirement + job: ResearchDirector + - type: StealCondition + stealGroup: ClothingOuterReactiveArmor + owner: job-name-rd diff --git a/Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/equipped-OUTERCLOTHING.png new file mode 100644 index 0000000000000000000000000000000000000000..35ee0bbeff5b0d0750f50708f889ca81082d4c1b GIT binary patch literal 932 zcmV;V16%xwP)Px&L`g(JRCt{2nlWqJKorOSE*%^K79NbGkRg+d=wO^7&>_%x>37H{$S3m$=+?z8 zbSQMN@lZ@WWeCy}8H5C;ri(hnPdOz3-vb0e5ClOGgnAsd z?M$bA*SM}%sq<9(Hd?yEX`EoSjvifi*tWAy*8%{9;j;F9P4qim3u&C>=lIw}|7~4y z$2o%SI*397k(H?;0sx|ruv{$i!2#or7mNJ&w(D?5c47kSZ;S;|003~Dqx?5%oaF5Qu<36t{jCP1aZ(WHr8c^m zV*+4wGY55hg(bNn37YD^(Y;``j#_D)U~)1*6cQ#UgS`!2#daMK1&P>Mr~eL?JyQXzG&y9%`oD989~NRM$JR_my>3M06#m#xD3lVG$5 z{7XE`0A3CK7U_peOIX6YYMJSNcv}$A=v01 zPz4Kekwnv^ae{HT2W*~1&qX@~%CDQ8mfly91Q%$i+E4YZ4q7WfecY(*W9I89}4>~Rn$8^PXGV_4rN$LW=%~1DgXcg2mk;800000(o>TF0000%KsAqrCjlRA3!%}7=?5kM>f`8 z@nLU^r-N|(e63NZ)~K@|AV4OGOaj9w)L%7j-kuxLievgGJz8;0d+q_RqwvCeMi7xJ z7o5*mDOdEqUMvc4km%=o;fu(6v6#x23by>(*_N!@B4Tz7lTl<1qmZ&)#q)iFN)x~lP zhrIo~z{=MxHj~p-{#r26fX1W-I*ubsxzcf*lm@O-+gJk{S_?s?Nh^-=e4kbv6I7a) z8dMgHop2JRf-OtS&&S5|Px$LP z8H5Z0Z|=~_xCyBxZvlOa(VcYv?>iYoAP@*#8&b|{pLiDoU*S?4j#Y7X?*1;WhocC9 z{eJ6Q_tsThh%vDg6nlkIQQa0f%>%WoiB1Dj&gvwc1N@5Tl-iJ{ueBB2uGh`}SPEh( zoK18ZD7CR~)rb#A5sTf53|Q<|sL=zZHfQHtaB7pCuN8kXUu>dDlecS|FSX$_d*ku> zrL(^CWw9obbk6GI9U;a|PN}?!U%I51xN+TRi`sFVV&gvIUIw6huC8-$-I?8SkM$mhl@?Z=vb)PHKKw5zDHh7#K07$p zr6BY4!U8|BEuJq5o;aNSR;Ho()uvv>ZaK&O^Aab%`_9|r+4h{V0}i-0P042K&wP8| z;+w$XbJElPN337cwB?(xZARQ~kF~YIbLX9mZAp9{dCK(bg2){UwhL-I?4Pc{r<~$? zB2S4=`AfCu!Zm9+Zk`oCx$FFllo{9dMf%o1&UnZC$e`)2t;_Xq0&VI$uV1`nKJ^KY zXR6q`y6%c>Uy5-);93e`_86 zvwTOvwb&zZjsLG&>AtDpow!DJePh&e)k$Af#Jp4&Z_VHG?d+__Hm{nuKC}402`Kc@ z{=kWdQ>H=tbx!IiA%VhfZ*8|-y|z6^Y??CiF9fZNjEOQ_oRQ2wX_mWyu7hnx(yIjV zz%Sl=x~)C3~6@ Jvd$@?2>@K42V(#L literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/inhand-right.png b/Resources/Textures/SS220/Clothing/OuterClothing/Armor/reactive_armor.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3111714b5d00dc878382f3aa8d88d53ee13f4b GIT binary patch literal 552 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