From dd73908949356f7d1c42b1be03fedc12f47e8fe4 Mon Sep 17 00:00:00 2001 From: iertis Date: Mon, 4 Aug 2025 22:29:20 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BD=D0=BE=D0=B2=D0=B0=20=D0=B0=D0=B1?= =?UTF-8?q?=D0=B4=D1=83=D0=BA=D1=82=D0=BE=D1=80=D1=8B=20(#2705)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abductor/EntitySystems/AbductorSystem.cs | 194 ++++++++++-------- .../Systems/SharedMoverController.Relay.cs | 22 ++ .../Components/TeleportLocationsComponent.cs | 5 + .../Systems/SharedTeleportLocationsSystem.cs | 5 + .../Audio/_Sunrise/Abductor/attributions.yml | 1 + .../_sunrise/abductors/abductor-console.ftl | 3 +- .../_strings/_sunrise/abductors/abductor.ftl | 2 + .../_Sunrise/Catalog/Fills/Items/medical.yml | 26 +++ .../Entities/Mobs/Player/abductor.yml | 2 + .../Objects/Misc/identification_cards.yml | 23 +++ .../Objects/Weapons/Melee/silencer.yml | 2 +- .../Objects/Weapons/Melee/wonderprod.yml | 2 +- .../_Sunrise/Entities/Specific/abductor.yml | 21 ++ .../Prototypes/_Sunrise/Reagents/toxins.yml | 42 ++++ .../Prototypes/_Sunrise/Store/abductor.yml | 12 +- .../Objects/Misc/id_cards.rsi/abductor.png | Bin 0 -> 466 bytes .../Objects/Misc/id_cards.rsi/meta.json | 3 + 17 files changed, 272 insertions(+), 93 deletions(-) create mode 100644 Resources/Prototypes/_Sunrise/Catalog/Fills/Items/medical.yml create mode 100644 Resources/Textures/_Sunrise/Objects/Misc/id_cards.rsi/abductor.png diff --git a/Content.Server/_Sunrise/Antags/Abductor/EntitySystems/AbductorSystem.cs b/Content.Server/_Sunrise/Antags/Abductor/EntitySystems/AbductorSystem.cs index a6fbfe6712..80d3075a19 100644 --- a/Content.Server/_Sunrise/Antags/Abductor/EntitySystems/AbductorSystem.cs +++ b/Content.Server/_Sunrise/Antags/Abductor/EntitySystems/AbductorSystem.cs @@ -16,6 +16,7 @@ using Content.Shared.Hands.EntitySystems; using Robust.Server.GameObjects; using Content.Shared.Tag; using Robust.Server.Containers; +using Robust.Shared.Toolshed.TypeParsers; namespace Content.Server._Sunrise.Antags.Abductor; @@ -35,6 +36,8 @@ public sealed partial class AbductorSystem : SharedAbductorSystem [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!; + private EntityUid? _opener; + public override void Initialize() { SubscribeLocalEvent(OnBeforeActivatableUIOpen); @@ -43,6 +46,7 @@ public sealed partial class AbductorSystem : SharedAbductorSystem SubscribeLocalEvent(OnAbductorGetVis); Subs.BuiEvents(AbductorCameraConsoleUIKey.Key, subs => subs.Event(OnAbductorBeaconChosenBuiMsg)); + InitializeActions(); InitializeGizmo(); InitializeConsole(); @@ -60,110 +64,78 @@ public sealed partial class AbductorSystem : SharedAbductorSystem private void OnAbductorBeaconChosenBuiMsg(Entity ent, ref AbductorBeaconChosenBuiMsg args) { OnCameraExit(args.Actor); - if (ent.Comp.RemoteEntityProto != null) + + EntityUid eye; + + _opener = args.Actor; + var beacon = _entityManager.GetEntity(args.Beacon.NetEnt); + var beaconCoords = Transform(beacon).Coordinates; + + if (ent.Comp.RemoteEntity != null && TryGetEntity(ent.Comp.RemoteEntity, out var existingEye)) { - var beacon = _entityManager.GetEntity(args.Beacon.NetEnt); - var eye = SpawnAtPosition(ent.Comp.RemoteEntityProto, Transform(beacon).Coordinates); - ent.Comp.RemoteEntity = GetNetEntity(eye); - - if (TryComp(args.Actor, out var handsComponent)) - { - foreach (var hand in _hands.EnumerateHands(args.Actor, handsComponent)) - { - if (hand.HeldEntity == null) - continue; - - if (HasComp(hand.HeldEntity)) - continue; - - _hands.DoDrop(args.Actor, hand, true, handsComponent); - } - - if (_virtualItem.TrySpawnVirtualItemInHand(ent.Owner, args.Actor, out var virtItem1)) - { - EnsureComp(virtItem1.Value); - } - - if (_virtualItem.TrySpawnVirtualItemInHand(ent.Owner, args.Actor, out var virtItem2)) - { - EnsureComp(virtItem2.Value); - } - } - - var visibility = EnsureComp(eye); - - Dirty(ent); - - if (TryComp(args.Actor, out EyeComponent? eyeComp)) - { - _eye.RefreshVisibilityMask(args.Actor); - _eye.SetTarget(args.Actor, eye, eyeComp); - _eye.SetDrawFov(args.Actor, false); - - if (!TryComp(eye, out RemoteEyeSourceContainerComponent? remoteEyeSourceContainerComponent)) - { - remoteEyeSourceContainerComponent = new RemoteEyeSourceContainerComponent { Actor = args.Actor }; - AddComp(eye, remoteEyeSourceContainerComponent); - } - else - remoteEyeSourceContainerComponent.Actor = args.Actor; - Dirty(eye, remoteEyeSourceContainerComponent); - } - - AddActions(args); - - _mover.SetRelay(args.Actor, eye); + eye = existingEye.Value; + _xformSys.SetCoordinates(eye, beaconCoords); } - } - - private void OnCameraExit(EntityUid actor) - { - AbductorScientistComponent? scientistComp = null; - AbductorAgentComponent? agentComp = null; - - if (TryComp(actor, out var comp) && TryComp(actor, out scientistComp) || TryComp(actor, out agentComp)) + else { - EntityUid? console = null; - - if (scientistComp != null && scientistComp.Console.HasValue) - console = scientistComp.Console.Value; - else if (agentComp != null && agentComp.Console.HasValue) - console = agentComp.Console.Value; - - if (console == null || comp == null) + if (ent.Comp.RemoteEntityProto == null) return; - var relay = comp.RelayEntity; - RemComp(actor, comp); + eye = SpawnAtPosition(ent.Comp.RemoteEntityProto, Transform(beacon).Coordinates); + ent.Comp.RemoteEntity = GetNetEntity(eye); - _virtualItem.DeleteInHandsMatching(actor, console.Value); + EnsureComp(eye); - if (TryComp(actor, out EyeComponent? eyeComp)) - { - _eye.SetVisibilityMask(actor, eyeComp.VisibilityMask ^ (int)VisibilityFlags.Abductor, eyeComp); - _eye.SetDrawFov(actor, true); - } - RemoveActions(actor); - QueueDel(relay); + var remoteEyeSource = EnsureComp(eye); + remoteEyeSource.Actor = args.Actor; + + Dirty(eye, remoteEyeSource); } + + AddVirtualItems(args.Actor, ent); + SetEye(args.Actor, eye, args); + Dirty(ent); + } + private void OnCameraExit(EntityUid actor) + { + if (!HasComp(actor)) + return; + + EntityUid? console = null; + + if (TryComp(actor, out var scientistComp) && scientistComp.Console is { } scientistConsole) + console = scientistConsole; + + if (TryComp(actor, out var agentComp) && agentComp.Console is { } agentConsole) + console = agentConsole; + + if (console == null) + return; + + RemoveEye(actor); + _virtualItem.DeleteInHandsMatching(actor, console.Value); + + _opener = null; } private void OnActivatableUIOpenAttemptEvent(Entity ent, ref ActivatableUIOpenAttemptEvent args) { if (!HasComp(args.User) && !HasComp(args.User)) args.Cancel(); + + if (_opener != null && _opener != args.User) + { + _popup.PopupEntity(Loc.GetString("console-occupied"), args.User, args.User); + args.Cancel(); + } } private void OnBeforeActivatableUIOpen(Entity ent, ref BeforeActivatableUIOpenEvent args) { - AbductorAgentComponent? agentComp = null; - - if (!TryComp(args.User, out var scientistComp) && !TryComp(args.User, out agentComp)) - return; - - if (scientistComp != null) + if (TryComp(args.User, out var scientistComp)) scientistComp.Console = ent.Owner; - else if (agentComp != null) + + if (TryComp(args.User, out var agentComp)) agentComp.Console = ent.Owner; var stations = _stationSystem.GetStations(); @@ -175,8 +147,6 @@ public sealed partial class AbductorSystem : SharedAbductorSystem || !TryComp(station, out MetaDataComponent? stationMetaData)) return; - var mapId = Transform(grid).MapID; - if (!_entityManager.TryGetComponent(grid, out var navMap)) return; @@ -190,4 +160,54 @@ public sealed partial class AbductorSystem : SharedAbductorSystem _uiSystem.SetUiState(ent.Owner, AbductorCameraConsoleUIKey.Key, new AbductorCameraConsoleBuiState() { Stations = result }); } + + private void SetEye(EntityUid uid, EntityUid eye, AbductorBeaconChosenBuiMsg args) + { + if (!TryComp(uid, out EyeComponent? eyeComp)) + return; + + AddComp(uid, new StationAiOverlayComponent { AllowCrossGrid = true }); + + _eye.RefreshVisibilityMask(uid); + _eye.SetTarget(uid, eye, eyeComp); + _eye.SetDrawFov(uid, false); + + AddActions(args); + _mover.SetRelay(uid, eye); + } + + private void RemoveEye(EntityUid uid) + { + if (!TryComp(uid, out EyeComponent? eyeComp)) + return; + + RemComp(uid); + RemComp(uid); + + _eye.SetTarget(uid, null); + _eye.SetVisibilityMask(uid, eyeComp.VisibilityMask ^ (int)VisibilityFlags.Abductor, eyeComp); + _eye.SetDrawFov(uid, true); + + RemoveActions(uid); + } + + private void AddVirtualItems(EntityUid uid, EntityUid console) + { + if (!TryComp(uid, out var hands)) + return; + + foreach (var hand in _hands.EnumerateHands(uid, hands)) + { + if (hand.HeldEntity == null || HasComp(hand.HeldEntity)) + continue; + + _hands.DoDrop(uid, hand, true, hands); + } + + if (_virtualItem.TrySpawnVirtualItemInHand(console, uid, out var virtItem1)) + EnsureComp(virtItem1.Value); + + if (_virtualItem.TrySpawnVirtualItemInHand(console, uid, out var virtItem2)) + EnsureComp(virtItem2.Value); + } } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs b/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs index 79c593cbe7..cfad62689b 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Relay.cs @@ -62,6 +62,28 @@ public abstract partial class SharedMoverController Dirty(relayEntity, targetComp); _blocker.UpdateCanMove(uid); } + // Sunrise-start + public void RemoveRelay(EntityUid uid) + { + if (!TryComp(uid, out var moverComp)) + return; + + var relay = moverComp.RelayEntity; + + if (TryComp(relay, out MovementRelayTargetComponent? targetComp)) + { + targetComp.Source = EntityUid.Invalid; + Dirty(relay, targetComp); + RemCompDeferred(relay); + PhysicsSystem.UpdateIsPredicted(relay); + } + + Dirty(uid, moverComp); + RemCompDeferred(uid); + PhysicsSystem.UpdateIsPredicted(uid); + _blocker.UpdateCanMove(uid); + } + // Sunrise-end private void OnRelayShutdown(Entity entity, ref ComponentShutdown args) { diff --git a/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs b/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs index ef5d6c5b2c..cc3a16b1bb 100644 --- a/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs +++ b/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs @@ -45,6 +45,11 @@ public sealed partial class TeleportLocationsComponent : Component /// [DataField] public LocId? Speech; + + // Sunrise-start + [DataField] + public bool DeleteAfterUse; + // Sunrise-end } /// diff --git a/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs b/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs index eb4be36ced..4abfe2e659 100644 --- a/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs +++ b/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs @@ -55,5 +55,10 @@ public abstract partial class SharedTeleportLocationsSystem : EntitySystem // Teleport's done, now tell the BUI to close if needed. _ui.CloseUi(ent.Owner, TeleportLocationUiKey.Key); + + // Sunrise-start + if (comp.DeleteAfterUse) + QueueDel(ent); + // Sunrise-end } } diff --git a/Resources/Audio/_Sunrise/Abductor/attributions.yml b/Resources/Audio/_Sunrise/Abductor/attributions.yml index 7a9ec43f7f..f2890f9971 100644 --- a/Resources/Audio/_Sunrise/Abductor/attributions.yml +++ b/Resources/Audio/_Sunrise/Abductor/attributions.yml @@ -4,5 +4,6 @@ source: "https://github.com/ss14Starlight/space-station-14" - files: ["holopaper_open"] + license: "Custom" copyright: 'ZAPSPLAT' source: "https://www.zapsplat.com/sound-effect-category/rollover/" diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor-console.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor-console.ftl index bca0142019..2da10f37e8 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor-console.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor-console.ftl @@ -29,5 +29,6 @@ abductors-ui-shop-WeaponAlien = Инопланетный пистолет abductors-ui-shop-ClothingHeadHelmetAbductor = Шлем abductors-ui-shop-AbductorGizmo = Гизмо abductors-ui-shop-AbductorExtractor = Экстрактор сердца -abductors-ui-shop-MedkitCombat = Боевая аптечка +abductors-ui-shop-MedkitUniversal = Универсальная аптечка +abductors-ui-shop-Teleporter = Одноразовый телепорт abductors-ui-shop-VendingMachineRestockAbductorDispenser = Пополнение диспенсера diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor.ftl index 9c051a9a1f..7c96ed8088 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/abductors/abductor.ftl @@ -20,3 +20,5 @@ gizmo-is-successfully-filled = Гизмо успешно заполнен gizmo-is-not-in-pockets = В карманах нету гизмо! owo-organ-transformation = ВЫ КОШКОФИЦИРОВАЛИСЬ!! need-stop-carry = Нельзя переместиться пока кто-то на руках! +console-occupied = Консоль уже занята кем-то! +teleportation-device-window-title = Устройство телепортации diff --git a/Resources/Prototypes/_Sunrise/Catalog/Fills/Items/medical.yml b/Resources/Prototypes/_Sunrise/Catalog/Fills/Items/medical.yml new file mode 100644 index 0000000000..f37cd3ff59 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/Catalog/Fills/Items/medical.yml @@ -0,0 +1,26 @@ +- type: entity + id: MedkitUniversalFilled + name: universal medkit + desc: Contains all types of medicine that you need. + suffix: Filled + parent: MedkitCombat + components: + - type: StorageFill + contents: + - id: MedicatedSuture + amount: 2 + - id: RegenerativeMesh + amount: 2 + - id: PillCanisterHyronalin + - id: BurnAutoInjector + amount: 2 + - id: BruteAutoInjector + amount: 2 + - id: SyringeSaline + amount: 2 + - id: PillCanisterDylovene + - type: Storage + grid: + - 0,0,3,3 + - type: Item + size: Huge diff --git a/Resources/Prototypes/_Sunrise/Entities/Mobs/Player/abductor.yml b/Resources/Prototypes/_Sunrise/Entities/Mobs/Player/abductor.yml index 2a0f988cfc..ca9948d8a4 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Mobs/Player/abductor.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Mobs/Player/abductor.yml @@ -61,6 +61,7 @@ gloves: ClothingHandsGlovesCombat shoes: ClothingShoesBootsCombat pocket1: AbductorGizmo + id: AbductorIDCard - type: startingGear id: AbductorAgentGear @@ -74,6 +75,7 @@ pocket2: WeaponAlien belt: ClothingAbductorBeltFilled outerClothing: ClothingOuterArmorAbductor + id: AbductorIDCard inhand: - Wonderprod diff --git a/Resources/Prototypes/_Sunrise/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/_Sunrise/Entities/Objects/Misc/identification_cards.yml index ac8f9c90ea..c247709ebc 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Objects/Misc/identification_cards.yml @@ -374,3 +374,26 @@ - state: idstationminer - type: PresetIdCard job: MiningSpecialist + +- type: entity + parent: [ IDCardStandard ] + id: AbductorIDCard + name: abductor ID card + components: + - type: Sprite + sprite: _Sunrise/Objects/Misc/id_cards.rsi + layers: + - state: abductor + - type: Access # get your access from your victims. + - type: AgentIDCard + - type: IdCard + bypassLogging: true + canMicrowave: false + jobTitle: job-name-unknown + - type: ActivatableUI + key: enum.AgentIDCardUiKey.Key + inHandsOnly: true + - type: UserInterface + interfaces: + enum.AgentIDCardUiKey.Key: + type: AgentIDCardBoundUserInterface diff --git a/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/silencer.yml b/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/silencer.yml index 3010a5dbdc..5e824309e5 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/silencer.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/silencer.yml @@ -30,5 +30,5 @@ - type: InjectOnHit limit: 20 reagents: - - ReagentId: MuteToxin + - ReagentId: MuteToxinAbductor Quantity: 5 diff --git a/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/wonderprod.yml b/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/wonderprod.yml index 4f311a6703..93b32fefc0 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/wonderprod.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Objects/Weapons/Melee/wonderprod.yml @@ -86,7 +86,7 @@ - type: InjectOnHit limit: 20 reagents: - - ReagentId: Nocturine + - ReagentId: NocturineAbductor Quantity: 2.5 damage: !type:ItemSwitchState diff --git a/Resources/Prototypes/_Sunrise/Entities/Specific/abductor.yml b/Resources/Prototypes/_Sunrise/Entities/Specific/abductor.yml index 63b3d3e195..8624b21534 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Specific/abductor.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Specific/abductor.yml @@ -13,3 +13,24 @@ - state: green_bit shader: unshaded - state: refill_medical + +- type: entity + id: AbductorTeleport + name: teleport device + parent: [ BaseItem, BaseMagicalContraband ] + components: + - type: UserInterface + interfaces: + enum.TeleportLocationUiKey.Key: + type: TeleportLocationsBoundUserInterface + - type: ActivatableUI + key: enum.TeleportLocationUiKey.Key + - type: Sprite + sprite: Objects/Devices/hand_teleporter.rsi + state: icon + - type: TeleportLocations + name: teleportation-device-window-title + teleportEffect: RadiationPulse + closeAfterTeleport: true + deleteAfterUse: true + diff --git a/Resources/Prototypes/_Sunrise/Reagents/toxins.yml b/Resources/Prototypes/_Sunrise/Reagents/toxins.yml index e1c14cf8f5..b3d4466183 100644 --- a/Resources/Prototypes/_Sunrise/Reagents/toxins.yml +++ b/Resources/Prototypes/_Sunrise/Reagents/toxins.yml @@ -144,3 +144,45 @@ damage: types: Poison: 5 + +- type: reagent + id: MuteToxinAbductor + name: reagent-name-mute-toxin + group: Narcotics + desc: reagent-desc-mute-toxin + physicalDesc: reagent-physical-desc-syrupy + color: "#000000" + boilingPoint: 255.0 + meltingPoint: 36.0 + metabolisms: + Narcotic: + effects: + - !type:GenericStatusEffect + key: Muted + component: Muted + type: Add + time: 80 + refresh: true + +- type: reagent + id: NocturineAbductor + name: reagent-name-nocturine + group: Narcotics + desc: reagent-desc-nocturine + physicalDesc: reagent-physical-desc-powdery + color: "#128e80" + boilingPoint: 444.0 + meltingPoint: 128.0 + metabolisms: + Narcotic: + effects: + - !type:GenericStatusEffect + conditions: + - !type:ReagentThreshold + reagent: NocturineAbductor + min: 8 + key: ForcedSleep + component: ForcedSleeping + refresh: true + type: Add + time: 120 diff --git a/Resources/Prototypes/_Sunrise/Store/abductor.yml b/Resources/Prototypes/_Sunrise/Store/abductor.yml index 7fbf68ca2a..9f2ff4486c 100644 --- a/Resources/Prototypes/_Sunrise/Store/abductor.yml +++ b/Resources/Prototypes/_Sunrise/Store/abductor.yml @@ -17,10 +17,16 @@ productEntity: AbductorGizmo - type: abductorListing - id: MedkitCombat - name: abductors-ui-shop-MedkitCombat + id: MedkitUniversal + name: abductors-ui-shop-MedkitUniversal + cost: 2 + productEntity: MedkitUniversalFilled + +- type: abductorListing + id: AbductorTeleport + name: abductors-ui-shop-Teleporter cost: 1 - productEntity: MedkitCombatFilled + productEntity: AbductorTeleport - type: abductorListing id: WeaponAlien diff --git a/Resources/Textures/_Sunrise/Objects/Misc/id_cards.rsi/abductor.png b/Resources/Textures/_Sunrise/Objects/Misc/id_cards.rsi/abductor.png new file mode 100644 index 0000000000000000000000000000000000000000..8290ad966e96842dbe6520b2af96747602b7f02f GIT binary patch literal 466 zcmV;@0WJQCP)Px$j7da6R9J=Wl|N6yKp2M~3^FLfj?UlA+^PcJYUi-ek``vq2&}cOOorr3}Fbq3L zqE4ry%;iN?RXmf)_)gMnHpA3b3jj!`(?N6DVO&@W`hgp>VjIP>-6)oQZK2WufLg6a zE|;TUX}Qkdou9~Y>9j;|G_U~BD6g6`Lc93Ll-q=@Ut4)E83X#v&zrHqAgK+yYsca2}! zZNTY(=!1DKcnU})5-?dfdn@B+8~%)BOyz(myf6n+%bT+B^meEmfJqa&6%H(5JGLR4 z@b&Xe#^?0_Ok8ji;;PIr47*S$P_Ng?X0ys;C{6%?X*wP7gQoy5#L5L-Yd~)_kk1S6 zfmy`f!}!9oEX#2UriG|bIuMV?eT$hb9)yMbj>8t$XfzstU-5ssGJ;