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?;{ftU7Fy!UN#t>0sx|ruv{$i!2#or7mNJ&w(D?5c47kSZ;S;|003~Dqx?5%oaF5Qu<36t{jCP1aZ(WHr8c^m
zV*+4wGY55hg(b?Fu%Y?^~K}04Pj?4z*^8Nn37YD^(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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