From 2cfdc4a52fac01492db6be7b6ef1bedf9e778bab Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Sat, 8 Jun 2024 18:46:09 +0300 Subject: [PATCH] Solution normalizer (#227) * dropper * add stabilizer * fuck, now * Update CP14SolutionNormalizerComponent.cs --- .../CP14SolutionNormalizerComponent.cs | 40 +++++++++++ .../Alchemy/CP14SolutionNormalizerSystem.cs | 67 ++++++++++++++++++ .../EntitySystems/SharedInjectorSystem.cs | 2 +- .../Entities/Objects/Specific/chemistry.yml | 2 + .../Objects/Specific/Alchemy/tools.yml | 54 +++++++++++++- .../Structures/Specific/Alchemy/heater.yml | 1 + .../Specific/Alchemy/normalizer.yml | 54 ++++++++++++++ .../Specific/Alchemy/dropper.rsi/dropper.png | Bin 0 -> 257 bytes .../Specific/Alchemy/dropper.rsi/liq-1.png | Bin 0 -> 117 bytes .../Specific/Alchemy/dropper.rsi/liq-2.png | Bin 0 -> 119 bytes .../Specific/Alchemy/dropper.rsi/meta.json | 20 ++++++ .../Specific/Alchemy/normalizer.rsi/base.png | Bin 0 -> 726 bytes .../Specific/Alchemy/normalizer.rsi/liq-1.png | Bin 0 -> 146 bytes .../Specific/Alchemy/normalizer.rsi/liq-2.png | Bin 0 -> 158 bytes .../Specific/Alchemy/normalizer.rsi/liq-3.png | Bin 0 -> 167 bytes .../Specific/Alchemy/normalizer.rsi/liq-4.png | Bin 0 -> 197 bytes .../Specific/Alchemy/normalizer.rsi/liq-5.png | Bin 0 -> 227 bytes .../Specific/Alchemy/normalizer.rsi/meta.json | 51 +++++++++++++ .../Alchemy/normalizer.rsi/rotate_back.png | Bin 0 -> 527 bytes .../Alchemy/normalizer.rsi/rotate_front.png | Bin 0 -> 413 bytes 20 files changed, 288 insertions(+), 3 deletions(-) create mode 100644 Content.Server/_CP14/Alchemy/CP14SolutionNormalizerComponent.cs create mode 100644 Content.Server/_CP14/Alchemy/CP14SolutionNormalizerSystem.cs create mode 100644 Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/normalizer.yml create mode 100644 Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/dropper.png create mode 100644 Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/liq-1.png create mode 100644 Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/liq-2.png create mode 100644 Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/meta.json create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/base.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-1.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-2.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-3.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-4.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-5.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/meta.json create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_back.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_front.png diff --git a/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerComponent.cs b/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerComponent.cs new file mode 100644 index 0000000000..680b8905f2 --- /dev/null +++ b/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerComponent.cs @@ -0,0 +1,40 @@ + +using Content.Shared.FixedPoint; +using Robust.Shared.Audio; + +namespace Content.Server._CP14.Alchemy; + +/// +/// gradually rounds down all reagents in the specified solution +/// +[RegisterComponent, Access(typeof(CP14SolutionNormalizerSystem))] +public sealed partial class CP14SolutionNormalizerComponent : Component +{ + [DataField(required: true)] + public string Solution = string.Empty; + + /// + /// will round down any reagent in solution until it is divisible by this value + /// + [DataField] + public float Factor = 0.25f; + + /// + /// the reagent will flow gradually by the specified number until it becomes normalized + /// + [DataField] + public FixedPoint2 LeakageQuantity = 0.05f; + + [DataField] + public TimeSpan UpdateFrequency = TimeSpan.FromSeconds(4f); + + [DataField] + public TimeSpan NextUpdateTime = TimeSpan.Zero; + + [DataField] + public SoundSpecifier NormalizeSound = new SoundPathSpecifier("/Audio/Ambience/Objects/drain.ogg") + { + Params = AudioParams.Default.WithVariation(0.03f) + }; +} + diff --git a/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerSystem.cs b/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerSystem.cs new file mode 100644 index 0000000000..b8c4305a2c --- /dev/null +++ b/Content.Server/_CP14/Alchemy/CP14SolutionNormalizerSystem.cs @@ -0,0 +1,67 @@ +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Timing; + +namespace Content.Server._CP14.Alchemy; + +public sealed partial class CP14SolutionNormalizerSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var normalizer, out var containerManager)) + { + if (_timing.CurTime <= normalizer.NextUpdateTime) + continue; + + normalizer.NextUpdateTime = _timing.CurTime + normalizer.UpdateFrequency; + + var solutionManager = new Entity(uid, containerManager); + + if (!_solutionContainer.TryGetSolution(solutionManager, + normalizer.Solution, + out var solutionEnt, + out var solution)) + continue; + + if (solution.Volume == 0) + continue; + + Dictionary affect = new(); + foreach (var (id, quantity) in solution.Contents) + { + FixedPoint2 roundedQuantity = Math.Floor((float) quantity / normalizer.Factor) * normalizer.Factor; + + var leakQuantity = quantity - roundedQuantity; + + if (leakQuantity == 0) continue; + + if (quantity - normalizer.LeakageQuantity < roundedQuantity) + affect.Add(id, leakQuantity); + else + affect.Add(id, normalizer.LeakageQuantity); + } + + if (affect.Count > 0) + { + //Telegraphy + _audio.PlayPvs(normalizer.NormalizeSound, uid); + + foreach (var (id, count) in affect) + { + _solutionContainer.RemoveReagent(solutionEnt.Value, id, count); + } + } + } + } +} diff --git a/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs index 1620344652..e282d8c375 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs @@ -16,7 +16,7 @@ public abstract class SharedInjectorSystem : EntitySystem /// /// Default transfer amounts for the set-transfer verb. /// - public static readonly FixedPoint2[] TransferAmounts = { 1, 5, 10, 15 }; + public static readonly FixedPoint2[] TransferAmounts = {0.25f, 1, 5, 10, 15};//{ 1, 5, 10, 15 }; // CP14 0.25 needed [Dependency] protected readonly SharedPopupSystem Popup = default!; [Dependency] protected readonly SharedSolutionContainerSystem SolutionContainers = default!; diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index dd15a90baa..9a41b21d13 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -264,6 +264,7 @@ name: dropper parent: BaseItem description: Used to transfer small amounts of chemical solution between containers. + noSpawn: true id: Dropper components: - type: Sprite @@ -307,6 +308,7 @@ name: borgdropper parent: Dropper description: Used to transfer small amounts of chemical solution between containers. Extended for use by medical borgs. + noSpawn: true id: BorgDropper components: - type: Sprite diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Specific/Alchemy/tools.yml b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Alchemy/tools.yml index 2f52f61057..084713d834 100644 --- a/Resources/Prototypes/_CP14/Entities/Objects/Specific/Alchemy/tools.yml +++ b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Alchemy/tools.yml @@ -46,7 +46,7 @@ ignoreMobs: true minTransferAmount: 10 maxTransferAmount: 100 - transferAmount: 50 + transferAmount: 15 toggleState: 1 # draw - type: UserInterface interfaces: @@ -153,4 +153,54 @@ - 0,0,1,1 - type: CP14Mortar solution: mortar - containerId: storagebase \ No newline at end of file + containerId: storagebase + +- type: entity + parent: BaseItem + id: CP14Dropper + name: dropper + description: Small dropper for managing very small values of liquids + components: + - type: MixableSolution + solution: vial + - type: FitsInDispenser + solution: vial + - type: RefillableSolution + solution: vial + - type: DrainableSolution + solution: vial + - type: ExaminableSolution + solution: vial + - type: DrawableSolution + solution: vial + - type: InjectableSolution + solution: vial + - type: SolutionItemStatus + solution: vial + - type: SolutionContainerManager + solutions: + vial: + maxVol: 2 + - type: UserInterface + interfaces: + enum.TransferAmountUiKey.Key: + type: TransferAmountBoundUserInterface + - type: Appearance + - type: Injector + solutionName: vial + injectOnly: false + ignoreMobs: true + minTransferAmount: 0.25 + maxTransferAmount: 1 + transferAmount: 0.25 + toggleState: 1 # draw + - type: Sprite + sprite: _CP14/Objects/Specific/Alchemy/dropper.rsi + layers: + - state: dropper + - state: liq-1 + map: ["enum.SolutionContainerLayers.Fill"] + visible: false + - type: SolutionContainerVisuals + maxFillLevels: 2 + fillBaseName: liq- \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/heater.yml b/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/heater.yml index 6f6b2bbfa1..2a8544e3a9 100644 --- a/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/heater.yml +++ b/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/heater.yml @@ -3,6 +3,7 @@ parent: BaseStructure abstract: true components: + - type: InteractionOutline - type: Fixtures fixtures: fix1: diff --git a/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/normalizer.yml b/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/normalizer.yml new file mode 100644 index 0000000000..a2e6ef6983 --- /dev/null +++ b/Resources/Prototypes/_CP14/Entities/Structures/Specific/Alchemy/normalizer.yml @@ -0,0 +1,54 @@ +- type: entity + id: CP14AlchemyNormalizer + parent: BaseStructureDynamic + name: solution stabilizer + description: An alchemical device that removes fine precipitates from solutions, and stabilizes it for further work + placement: + mode: PlaceFree + components: + # TODO: energy consuming (magic or fireplace) + - type: InteractionOutline + - type: Sprite + drawdepth: Items + noRot: true + offset: 0, 0.2 + sprite: _CP14/Structures/Specific/Alchemy/normalizer.rsi + layers: + - state: rotate_back + - state: liq-1 + map: ["enum.SolutionContainerLayers.Fill"] + visible: false + - state: base + - state: rotate_front + state: base + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 125 + mask: + - TabletopMachineMask + - type: SolutionContainerManager + solutions: + normalizer: + maxVol: 50 + - type: DrainableSolution + solution: normalizer + - type: ExaminableSolution + solution: normalizer + - type: MixableSolution + solution: normalizer + - type: RefillableSolution + solution: normalizer + - type: DrawableSolution + solution: normalizer + - type: DumpableSolution + solution: normalizer + - type: CP14SolutionNormalizer + solution: normalizer + - type: Appearance + - type: SolutionContainerVisuals + maxFillLevels: 5 + fillBaseName: liq- \ No newline at end of file diff --git a/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/dropper.png b/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/dropper.png new file mode 100644 index 0000000000000000000000000000000000000000..e1026b1205ca439f060ce8943fef2b4d0d34c4a5 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}yFFbTLn2z= zURuq?6ew`)<9_iYp<*8o>50u&P&?e@XdvyYHd!I9x&MLn4+gsy{=~4&x%{gO1oTs{ zDsU%#)Zv)+^Qz>&nT?E!EdowQOg`;7uK)ScGH33cA`HKTHbuQRWAK{aeE#0+m)qE9 ze6e<({HEpPhbq(NV6R1e2)NNnpc6aaUS7m8^dl?&+^XclcFnwt`Ee+Jl N;OXk;vd$@?2>{~uBa;9C literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/liq-2.png b/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/liq-2.png new file mode 100644 index 0000000000000000000000000000000000000000..929d6b17eb6d9e3fc251cd7e12f57479d49e5cc4 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}hMq2tArY-_ z&ny&VP~c%XxIp<*eRC$W)&ZA<8(Yo)3o;ydf34)k-QBC!*%}|e&u}1^J)4(>NpW?| QMxbT}Pgg&ebxsLQ0B8Osf&c&j literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/meta.json b/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/meta.json new file mode 100644 index 0000000000..7e21d2df46 --- /dev/null +++ b/Resources/Textures/_CP14/Objects/Specific/Alchemy/dropper.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "All rights reserved for the CrystallPunk14 project only", + "copyright": "Created by TheShuEd (Github) for CrystallPunk14", + "states": [ + { + "name": "dropper" + }, + { + "name": "liq-1" + }, + { + "name": "liq-2" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/base.png b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/base.png new file mode 100644 index 0000000000000000000000000000000000000000..425e9e3efde995845a09df0c863c452b5756031e GIT binary patch literal 726 zcmV;{0xA88P)Px%kV!;AR9J=WR!?YBaUB0t#`f0UR2;rop#u>%BhcBYL(n>`(=gCc83YgNu%y^Q zc4%}eSa=wLrw%U`Gh!Pgowmz@4xQ%ol3PfS5^G8i=N#&CVF&%m^SPeC2aX8*z=QX` z|307h`+dLf_ka#M=-?mYgxZ9a^{u#)|N5mN+p!2B#L4gC1^{I9#hBEuXBj&Hn9mzV z)Ci#xu(G}tmlLPc8PRhP764$W%f)k?(I6K>BjO~D00KF=&QgZXQikUsETq#JQ5r)F z4Q(L9cAFTs+f>Y#QhL^mkNNw4lxt2CFvK#~NZhdqDCSG4Y`z#97|@R^5p8d0-|Jb% z4(*x#whADKM!&pL@{?Ymg=zr+kPZa|pWE7C3oa+XdHuZFT2xK=`rfT!IXP)Sa{1g= zq(cGWs2n9wjbZ%ljmp#K-_X~48ok<6;P0G8GQu>(n4Luk3p?1){l?yY88g#^u-$yu zvOd)oBqI!FrUwB4!op4yIf(&)hY!v*Jhw$aMl1l49ssDly~GZ{Xps7t245>s^#C_H zyO|LS$cTj_3CMji!hpnale3#NwW+6|H0}>&^TilG1Ovo2w^m(>sZnQL#E+{!f9-QT z(l!Bot51e;;n4;F#B38h0NCS;f;5KMIlxfQX_tW9t_BxBzwiR^E_J!;vpzNIY>K^- zdKn-&Z4*#k-fE+Hbk!3ufyON$CnF)IZNipw`svw3CAX_->UcSU+-@}VK&v~%<;RPP z9E#3)-c=#@b88XU^!*rfm=y)DMw5tVe>QB-T_OBe9@W2Ow;hfO0QlV2`f_V^hX^hw z003{IQB^fnA4Y^=%weurEmd3M>o3*BZNWV6sz|q~gZ~nL0O5oe0pBPA%m4rY07*qo IM6N<$g37T>NB{r; literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-1.png b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-1.png new file mode 100644 index 0000000000000000000000000000000000000000..05fb50034cdd69b1d5a6e96e498b4dc5a1a366db GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}KAtX)ArY-_ z&u!#9V8G)Ncr&Gaw)1a(#oQ+*h8AkBESXIIr|x2&D+yE@ARzd-``oJVdET1}Z+@BV8G*YQ8-2My?u*qYtQl>A%-d}ZYycr!_j%<@y@O@uOe(ZuNLJV84-F+REy?V~fo9SmFpSe2So^#;= P&@u*3S3j3^P6hg literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-5.png b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/liq-5.png new file mode 100644 index 0000000000000000000000000000000000000000..020c8d59a05d5225a110e55982f84d1d3c934b14 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}b3I)gLn2z= zUU|#OtjNRm;QA%mBZhbCJ1ksPf|u-{Vtp~`!4i>Ae}p{s>S7t5&-uME!8aiE?McO! zt9RC2&r>jdz3M{gnpLOHSUp?6r<~c9g<(R_tJbu_t=Hs!zhGL&I&VuY>+%`?4lWal z=h>MkU6NS*vU-{Dk1!dAqH_m}{-2xKGq>Prg?di6M0MS4`)i!H-@Ch9zB@H2ukf7Z acXPX$ccMZ2gTd3)&t;ucLK6V>U0<~T literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/meta.json b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/meta.json new file mode 100644 index 0000000000..d45fe7fd2e --- /dev/null +++ b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/meta.json @@ -0,0 +1,51 @@ +{ + "version": 1, + "license": "All rights reserved for the CrystallPunk14 project only", + "copyright": "Created by TheShuEd for CrystallPunk14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base" + }, + { + "name": "liq-1" + }, + { + "name": "liq-2" + }, + { + "name": "liq-3" + }, + { + "name": "liq-4" + }, + { + "name": "liq-5" + }, + { + "name": "rotate_back", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "rotate_front", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_back.png b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_back.png new file mode 100644 index 0000000000000000000000000000000000000000..8db70515768f4011d640e8943e4d9a6895422e0d GIT binary patch literal 527 zcmV+q0`UEbP)Px$$w@>(RCt{2+OcZFKo|$`&$eS*eSuOsO2JX+;M6IQCvdm;0QD*C6WHCoAY{ti z&MpBdgy7&LcqVJO4kdE2r`{!(NYejr3E{$hxl8VjpNvri-SD|f(R zwWh^ty*q!kpHff2^?Vceqiopg^6Td1?)Er8LdydeW17v|C7E{2&KjlRd<0T!E#1`LD70N>(U?JT%Z-|Jb9N_; zx(Qv*+>^fM!(P|u3Xx)U+T7~2PX3n@2SyJY;_PZ5hr+#Hc7EuU)$EH_(PZnk-<&>}u{+5Uv& zSX;whmmf=ipEDy>irP020N|J+Cc#R53y2+XXn%lidc0EK0?7RX0000O^aF4k=e=}} REQ|mE002ovPDHLkV1f!-?-&38 literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_front.png b/Resources/Textures/_CP14/Structures/Specific/Alchemy/normalizer.rsi/rotate_front.png new file mode 100644 index 0000000000000000000000000000000000000000..48b27ceeb5963d4000d37528063ab1b0722e840d GIT binary patch literal 413 zcmV;O0b>4%P)Px$S4l)cRCt{2+C56dKoke?QMMK@-~rO4&k+XZ1nJ`mk~T$Bx(ATh+Y5nIsVr73 z1qmz*LATgyA-mej*okiAo8;wVcK^RFFrP1zVaOXH00000ERh9DbGCQR+1L=4n{8S| zzAhr4B@k!Sf?1&S)#b&{v%I|thssL`<&sc&tjmn+l^9K%Ly{ zd(&z#UEMxD$5URV0AMlcI$FBUzXu`dI*D|hK@UO){r7hcm^#V}I%+2$0000000000 zfZk<+(%kuaXo2&-0GJpf^4xt|^;^7%d|g&`dU!jfi&>Y->t@e24wAB}+1u