From d259191d3df1f83393a100f1386f94896e7bfbc3 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:22:06 +0300 Subject: [PATCH] Cargo system (#487) * simple storeship arriving * pupu * ship cycling * buy positions prototypes * i hate UI * PriceControl * second tab ui * baloon! pallets! * update shop in town * setup billboard timer * split to sell and buy categories * renaming gaming * actually selling * fix infinity selling * improve timer * move description too rigt part UI * bar selling * iron cabinet * purge currency categories * remove town balance, add money box * special proposal, FTLImmune anchor * fix UI * remove tests buying * Update CP14StoreWindow.xaml.cs * currency converter * currency clean up * Update CP14CargoSystem.cs * clean up part 2 * rider petpet * coins audio * coin improvment * Update coins.yml * translate * more coins roundstart * Update wallet.yml * Update wallet.yml * generate coin problem fix * refactor proto reading * fixes * huh * shuttle logshit fix, add to tavern map * Update CP14StationTravelingStoreShipTargetComponent.cs --- .../TravelingStoreShip/CP14PriceControl.xaml | 22 + .../CP14PriceControl.xaml.cs | 46 + .../CP14StoreBoundUserInterface.cs | 34 + .../CP14StoreProductControl.xaml | 15 + .../CP14StoreProductControl.xaml.cs | 44 + .../TravelingStoreShip/CP14StoreWindow.xaml | 31 + .../CP14StoreWindow.xaml.cs | 79 + .../_CP14/Currency/CP14CurrencySystem.cs | 216 +++ .../CP14CurrencyCollectConditionComponent.cs | 6 - .../CP14CurrencyCollectConditionSystem.cs | 20 +- .../CP14CargoSystem.Shuttle.cs | 87 + .../TravelingStoreShip/CP14CargoSystem.UI.cs | 87 + .../TravelingStoreShip/CP14CargoSystem.cs | 205 +++ .../CP14TravelingStoreshipComponent.cs | 8 + ...P14TravelingStoreshipFTLTargetComponent.cs | 10 + Content.Shared/Verbs/VerbCategory.cs | 2 + .../_CP14/Currency/CP14CurrencyComponent.cs | 8 +- .../CP14CurrencyConverterComponent.cs | 25 + .../_CP14/Currency/CP14CurrencySystem.cs | 62 - .../Currency/CP14SharedCurrencySystem.cs | 54 + .../CP14CargoMoneyBoxComponent.cs | 9 + .../CP14CargoStoreComponent.cs | 11 + .../CP14SellingPalettComponent.cs | 11 + .../CP14SharedCargoSystem.cs | 5 + ...tationTravelingStoreShipTargetComponent.cs | 46 + .../_CP14/TravelingStoreShip/CP14StoreUI.cs | 64 + .../BuyServices/CP14BuyItemsService.cs | 32 + .../CP14StoreBuyPositionPrototype.cs | 46 + .../CP14StoreSellPositionPrototype.cs | 46 + .../SellServices/CP14SellStackService.cs | 57 + .../SellServices/CP14SellWhitelistService.cs | 52 + Resources/Audio/_CP14/Items/attributions.yml | 7 +- Resources/Audio/_CP14/Items/coins1.ogg | Bin 0 -> 9891 bytes Resources/Audio/_CP14/Items/coins2.ogg | Bin 0 -> 11753 bytes Resources/Audio/_CP14/Items/coins3.ogg | Bin 0 -> 9458 bytes Resources/Audio/_CP14/Items/coins_fall.ogg | Bin 0 -> 13758 bytes .../travelingStoreship/positions_buy.ftl | 2 + .../travelingStoreship/positions_sell.ftl | 8 + .../_CP14/travelingStoreship/services.ftl | 8 + .../en-US/_CP14/travelingStoreship/ui.ftl | 9 + .../ru-RU/_CP14/currency/currency_comp.ftl | 10 +- .../ru-RU/_CP14/speech/speech-chatsan.ftl | 18 +- .../travelingStoreship/positions_buy.ftl | 2 + .../travelingStoreship/positions_sell.ftl | 8 + .../_CP14/travelingStoreship/services.ftl | 8 + .../ru-RU/_CP14/travelingStoreship/ui.ftl | 9 + Resources/Maps/_CP14/Ships/balloon.yml | 348 ++++ Resources/Maps/_CP14/dev_map.yml | 1114 ++---------- Resources/Maps/_CP14/tavern.yml | 1570 +++++------------ .../Prototypes/Accents/word_replacements.yml | 12 +- .../_CP14/Entities/Objects/Economy/coins.yml | 25 +- .../_CP14/Entities/Objects/Economy/wallet.yml | 8 +- .../Objects/Weapons/Melee/battleHammer.yml | 4 +- .../Objects/Weapons/Melee/battleStaff.yml | 4 +- .../Entities/Objects/Weapons/Melee/dagger.yml | 4 +- .../Objects/Weapons/Melee/handheldAxe.yml | 4 +- .../Objects/Weapons/Melee/lightHammer.yml | 4 +- .../Entities/Objects/Weapons/Melee/mace.yml | 4 +- .../Entities/Objects/Weapons/Melee/sickle.yml | 4 +- .../Entities/Objects/Weapons/Melee/sword.yml | 4 +- .../Objects/Weapons/Melee/twoHandedSword.yml | 4 +- .../_CP14/Entities/Stations/base.yml | 15 + .../_CP14/Entities/Stations/expedition.yml | 7 - .../Structures/Furniture/dressers.yml | 44 +- .../Entities/Structures/Furniture/pallets.yml | 72 + .../Specific/Economy/cash_converter.yml | 50 + .../_CP14/Entities/Structures/test.yml | 22 + .../Structures/trabeling_storeship_anchor.yml | 19 + Resources/Prototypes/_CP14/Entities/fire.yml | 2 +- Resources/Prototypes/_CP14/Maps/debug.yml | 2 +- .../_CP14/SoundCollections/items.yml | 9 +- Resources/Prototypes/_CP14/Store/buy.yml | 14 + Resources/Prototypes/_CP14/Store/sell.yml | 41 + .../_CP14/Interface/Misc/coins.rsi/c.png | Bin 0 -> 157 bytes .../_CP14/Interface/Misc/coins.rsi/g.png | Bin 0 -> 205 bytes .../_CP14/Interface/Misc/coins.rsi/meta.json | 23 + .../_CP14/Interface/Misc/coins.rsi/p.png | Bin 0 -> 244 bytes .../_CP14/Interface/Misc/coins.rsi/s.png | Bin 0 -> 172 bytes .../Structures/Furniture/pallets.rsi/buy.png | Bin 0 -> 144 bytes .../Furniture/pallets.rsi/meta.json | 20 + .../Structures/Furniture/pallets.rsi/sell.png | Bin 0 -> 145 bytes .../Furniture/pallets.rsi/wooden.png | Bin 0 -> 605 bytes .../Specific/Economy/cash_device.rsi/base.png | Bin 0 -> 1190 bytes .../Economy/cash_device.rsi/meta.json | 15 + .../Dressers/iron_cabinet.rsi/icon-open.png | Bin 0 -> 2044 bytes .../Dressers/iron_cabinet.rsi/icon.png | Bin 0 -> 1831 bytes .../Dressers/iron_cabinet.rsi/meta.json | 19 + .../icon-open.png | Bin .../icon.png | Bin .../meta.json | 0 .../traveling_storeship_anchor.rsi/base.png | Bin 0 -> 1440 bytes .../traveling_storeship_anchor.rsi/meta.json | 15 + Resources/migration.yml | 3 + 93 files changed, 2793 insertions(+), 2241 deletions(-) create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml.cs create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14StoreBoundUserInterface.cs create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml.cs create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml create mode 100644 Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml.cs create mode 100644 Content.Server/_CP14/Currency/CP14CurrencySystem.cs create mode 100644 Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.Shuttle.cs create mode 100644 Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.UI.cs create mode 100644 Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.cs create mode 100644 Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipComponent.cs create mode 100644 Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipFTLTargetComponent.cs create mode 100644 Content.Shared/_CP14/Currency/CP14CurrencyConverterComponent.cs delete mode 100644 Content.Shared/_CP14/Currency/CP14CurrencySystem.cs create mode 100644 Content.Shared/_CP14/Currency/CP14SharedCurrencySystem.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14CargoMoneyBoxComponent.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14CargoStoreComponent.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14SellingPalettComponent.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14SharedCargoSystem.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14StationTravelingStoreShipTargetComponent.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/CP14StoreUI.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/Prototype/BuyServices/CP14BuyItemsService.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreBuyPositionPrototype.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreSellPositionPrototype.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellStackService.cs create mode 100644 Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellWhitelistService.cs create mode 100644 Resources/Audio/_CP14/Items/coins1.ogg create mode 100644 Resources/Audio/_CP14/Items/coins2.ogg create mode 100644 Resources/Audio/_CP14/Items/coins3.ogg create mode 100644 Resources/Audio/_CP14/Items/coins_fall.ogg create mode 100644 Resources/Locale/en-US/_CP14/travelingStoreship/positions_buy.ftl create mode 100644 Resources/Locale/en-US/_CP14/travelingStoreship/positions_sell.ftl create mode 100644 Resources/Locale/en-US/_CP14/travelingStoreship/services.ftl create mode 100644 Resources/Locale/en-US/_CP14/travelingStoreship/ui.ftl create mode 100644 Resources/Locale/ru-RU/_CP14/travelingStoreship/positions_buy.ftl create mode 100644 Resources/Locale/ru-RU/_CP14/travelingStoreship/positions_sell.ftl create mode 100644 Resources/Locale/ru-RU/_CP14/travelingStoreship/services.ftl create mode 100644 Resources/Locale/ru-RU/_CP14/travelingStoreship/ui.ftl create mode 100644 Resources/Maps/_CP14/Ships/balloon.yml create mode 100644 Resources/Prototypes/_CP14/Entities/Stations/base.yml delete mode 100644 Resources/Prototypes/_CP14/Entities/Stations/expedition.yml create mode 100644 Resources/Prototypes/_CP14/Entities/Structures/Furniture/pallets.yml create mode 100644 Resources/Prototypes/_CP14/Entities/Structures/Specific/Economy/cash_converter.yml create mode 100644 Resources/Prototypes/_CP14/Entities/Structures/test.yml create mode 100644 Resources/Prototypes/_CP14/Entities/Structures/trabeling_storeship_anchor.yml create mode 100644 Resources/Prototypes/_CP14/Store/buy.yml create mode 100644 Resources/Prototypes/_CP14/Store/sell.yml create mode 100644 Resources/Textures/_CP14/Interface/Misc/coins.rsi/c.png create mode 100644 Resources/Textures/_CP14/Interface/Misc/coins.rsi/g.png create mode 100644 Resources/Textures/_CP14/Interface/Misc/coins.rsi/meta.json create mode 100644 Resources/Textures/_CP14/Interface/Misc/coins.rsi/p.png create mode 100644 Resources/Textures/_CP14/Interface/Misc/coins.rsi/s.png create mode 100644 Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/buy.png create mode 100644 Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/meta.json create mode 100644 Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/sell.png create mode 100644 Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/wooden.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Economy/cash_device.rsi/base.png create mode 100644 Resources/Textures/_CP14/Structures/Specific/Economy/cash_device.rsi/meta.json create mode 100644 Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon-open.png create mode 100644 Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon.png create mode 100644 Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/meta.json rename Resources/Textures/_CP14/Structures/Storage/Dressers/{wood_dresser.rsi => wood_cabinet.rsi}/icon-open.png (100%) rename Resources/Textures/_CP14/Structures/Storage/Dressers/{wood_dresser.rsi => wood_cabinet.rsi}/icon.png (100%) rename Resources/Textures/_CP14/Structures/Storage/Dressers/{wood_dresser.rsi => wood_cabinet.rsi}/meta.json (100%) create mode 100644 Resources/Textures/_CP14/Structures/traveling_storeship_anchor.rsi/base.png create mode 100644 Resources/Textures/_CP14/Structures/traveling_storeship_anchor.rsi/meta.json diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml b/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml new file mode 100644 index 0000000000..50268eb9a3 --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml @@ -0,0 +1,22 @@ + + + + + + diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml.cs b/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml.cs new file mode 100644 index 0000000000..9df5bee7a0 --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14PriceControl.xaml.cs @@ -0,0 +1,46 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Client._CP14.TravelingStoreShip; + +[GenerateTypedNameReferences] +public sealed partial class CP14PriceControl : Control +{ + [Dependency] private readonly IEntityManager _entity = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private readonly SpriteSystem _sprite; + + public CP14PriceControl(int price) + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _sprite = _entity.System(); + + var rsiPath = new ResPath("_CP14/Interface/Misc/coins.rsi"); + + var total = price; + + var gp = total / 100; + total %= 100; + + var sp = total / 10; + total %= 10; + + var cp = total; + + CopperView.Texture = _sprite.Frame0(new SpriteSpecifier.Rsi(rsiPath, "c")); + CopperText.Text = cp.ToString(); + + SilverView.Texture = _sprite.Frame0(new SpriteSpecifier.Rsi(rsiPath, "s")); + SilverText.Text = sp.ToString(); + + GoldView.Texture = _sprite.Frame0(new SpriteSpecifier.Rsi(rsiPath, "g")); + GoldText.Text = gp.ToString(); + } +} diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14StoreBoundUserInterface.cs b/Content.Client/_CP14/TravelingStoreShip/CP14StoreBoundUserInterface.cs new file mode 100644 index 0000000000..6725d0cc82 --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14StoreBoundUserInterface.cs @@ -0,0 +1,34 @@ +using Content.Shared._CP14.TravelingStoreShip; +using JetBrains.Annotations; +using Robust.Client.UserInterface; + +namespace Content.Client._CP14.TravelingStoreShip; + +public sealed class CP14StoreBoundUserInterface : BoundUserInterface +{ + private CP14StoreWindow? _window; + + public CP14StoreBoundUserInterface(EntityUid owner, [NotNull] Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = this.CreateWindow(); + } + + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + switch (state) + { + case CP14StoreUiState storeState: + _window?.UpdateUI(storeState); + break; + } + } +} diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml b/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml new file mode 100644 index 0000000000..12c8ac7ceb --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml @@ -0,0 +1,15 @@ + + + diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml.cs b/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml.cs new file mode 100644 index 0000000000..9dd352e2cb --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14StoreProductControl.xaml.cs @@ -0,0 +1,44 @@ +using Content.Shared._CP14.TravelingStoreShip; +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; + +namespace Content.Client._CP14.TravelingStoreShip; + +[GenerateTypedNameReferences] +public sealed partial class CP14StoreProductControl : Control +{ + [Dependency] private readonly IEntityManager _entity = default!; + + private readonly SpriteSystem _sprite; + + public CP14StoreProductControl(CP14StoreUiProductEntry entry) + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _sprite = _entity.System(); + + UpdateName(entry.Name); + UpdateView(entry.Icon); + UpdatePrice(entry.Price); + } + + private void UpdatePrice(int price) + { + PriceHolder.RemoveAllChildren(); + PriceHolder.AddChild(new CP14PriceControl(price)); + } + + private void UpdateName(string name) + { + ProductName.Text = $"[bold]{name}[/bold]"; + } + + private void UpdateView(SpriteSpecifier spriteSpecifier) + { + View.Texture = _sprite.Frame0(spriteSpecifier); + } +} diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml b/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml new file mode 100644 index 0000000000..e19bf9f787 --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml.cs b/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml.cs new file mode 100644 index 0000000000..00f7080119 --- /dev/null +++ b/Content.Client/_CP14/TravelingStoreShip/CP14StoreWindow.xaml.cs @@ -0,0 +1,79 @@ +using Content.Shared._CP14.TravelingStoreShip; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Timing; + +namespace Content.Client._CP14.TravelingStoreShip; + +[GenerateTypedNameReferences] +public sealed partial class CP14StoreWindow : DefaultWindow +{ + [Dependency] private readonly IGameTiming _timing = default!; + + private TimeSpan? _nextTravelTime; + private bool _onStation; + + public CP14StoreWindow() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + Tabs.SetTabTitle(0, Loc.GetString("cp14-store-ui-tab-buy")); + Tabs.SetTabTitle(1, Loc.GetString("cp14-store-ui-tab-sell")); + } + + public void UpdateUI(CP14StoreUiState state) + { + UpdateProducts(state); + + _nextTravelTime = state.NextTravelTime; + _onStation = state.OnStation; + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + //Updating time + if (_nextTravelTime is not null) + { + var time = _nextTravelTime.Value - _timing.CurTime; + + TravelTimeLabel.Text = + $"{Loc.GetString(_onStation ? "cp14-store-ui-next-travel-out" : "cp14-store-ui-next-travel-in")} {Math.Max(time.Minutes, 0):00}:{Math.Max(time.Seconds, 0):00}"; + } + } + + private void UpdateProducts(CP14StoreUiState state) + { + BuyProductsContainer.RemoveAllChildren(); + SellProductsContainer.RemoveAllChildren(); + + foreach (var product in state.ProductsBuy) + { + var control = new CP14StoreProductControl(product); + control.ProductButton.OnPressed += _ => + { + SelectProduct(product); + }; + BuyProductsContainer.AddChild(control); + } + + foreach (var product in state.ProductsSell) + { + var control = new CP14StoreProductControl(product); + control.ProductButton.OnPressed += _ => + { + SelectProduct(product); + }; + SellProductsContainer.AddChild(control); + } + } + + private void SelectProduct(CP14StoreUiProductEntry? entry) + { + SelectedName.Text = entry is null ? string.Empty : $"[bold]{entry.Value.Name}[/bold]"; + SelectedDesc.Text = entry is null ? string.Empty : entry.Value.Desc; + } +} diff --git a/Content.Server/_CP14/Currency/CP14CurrencySystem.cs b/Content.Server/_CP14/Currency/CP14CurrencySystem.cs new file mode 100644 index 0000000000..78b0d56174 --- /dev/null +++ b/Content.Server/_CP14/Currency/CP14CurrencySystem.cs @@ -0,0 +1,216 @@ +using Content.Server.Popups; +using Content.Server.Stack; +using Content.Shared._CP14.Currency; +using Content.Shared.Examine; +using Content.Shared.Interaction; +using Content.Shared.Stacks; +using Content.Shared.Verbs; +using Content.Shared.Whitelist; +using Robust.Server.Audio; +using Robust.Shared.Audio; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Server._CP14.Currency; + +public sealed partial class CP14CurrencySystem : CP14SharedCurrencySystem +{ + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + [Dependency] private readonly StackSystem _stack = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnConverterExamine); + + SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent>(OnGetVerb); + } + + private void OnExamine(Entity currency, ref ExaminedEvent args) + { + var total = GetTotalCurrency(currency, currency.Comp); + + var push = Loc.GetString("cp14-currency-examine-title"); + push += GetCurrencyPrettyString(total); + args.PushMarkup(push); + } + + private void OnConverterExamine(Entity ent, ref ExaminedEvent args) + { + var push = $"{Loc.GetString("cp14-currency-converter-examine-title")} {GetCurrencyPrettyString(ent.Comp.Balance)}"; + args.PushMarkup(push); + } + + private void OnInteractUsing(Entity ent, ref InteractUsingEvent args) + { + if (!TryComp(args.Used, out var currency)) + return; + + if (ent.Comp.Whitelist is not null && !_whitelist.IsValid(ent.Comp.Whitelist, args.Used)) + return; + + var delta = GetTotalCurrency(args.Used); + ent.Comp.Balance += delta; + QueueDel(args.Used); + + _popup.PopupEntity(Loc.GetString("cp14-currency-converter-insert", ("cash", delta)), ent, args.User); + _audio.PlayPvs(ent.Comp.InsertSound, ent, AudioParams.Default.WithMaxDistance(3)); + } + + private void OnGetVerb(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + var transform = Transform(ent); + var coord = transform.Coordinates.Offset(transform.LocalRotation.RotateVec(ent.Comp.SpawnOffset)); + Verb copperVerb = new() + { + Text = Loc.GetString("cp14-currency-converter-get-cp"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/_CP14/Objects/Economy/cp_coin.rsi/coin10.png")), + Category = VerbCategory.CP14CurrencyConvert, + Priority = 1, + CloseMenu = false, + Act = () => + { + if (ent.Comp.Balance < CP.Value) + return; + + ent.Comp.Balance -= CP.Value; + + var newEnt = Spawn(CP.Key, coord); + _stack.TryMergeToContacts(newEnt); + _audio.PlayPvs(ent.Comp.InsertSound, ent, AudioParams.Default.WithMaxDistance(3).WithPitchScale(0.9f)); + }, + }; + args.Verbs.Add(copperVerb); + Verb silverVerb = new() + { + Text = Loc.GetString("cp14-currency-converter-get-sp"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/_CP14/Objects/Economy/sp_coin.rsi/coin10.png")), + Category = VerbCategory.CP14CurrencyConvert, + Priority = 2, + CloseMenu = false, + Act = () => + { + if (ent.Comp.Balance < SP.Value) + return; + + ent.Comp.Balance -= SP.Value; + var newEnt = Spawn(SP.Key, coord); + _stack.TryMergeToContacts(newEnt); + _audio.PlayPvs(ent.Comp.InsertSound, ent, AudioParams.Default.WithMaxDistance(3).WithPitchScale(1.1f)); + }, + }; + args.Verbs.Add(silverVerb); + Verb goldVerb = new() + { + Text = Loc.GetString("cp14-currency-converter-get-gp"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/_CP14/Objects/Economy/gp_coin.rsi/coin10.png")), + Category = VerbCategory.CP14CurrencyConvert, + Priority = 3, + CloseMenu = false, + Act = () => + { + if (ent.Comp.Balance < GP.Value) + return; + + ent.Comp.Balance -= GP.Value; + var newEnt = Spawn(GP.Key, coord); + _stack.TryMergeToContacts(newEnt); + _audio.PlayPvs(ent.Comp.InsertSound, ent, AudioParams.Default.WithMaxDistance(3).WithPitchScale(1.3f)); + }, + }; + args.Verbs.Add(goldVerb); + Verb platinumVerb = new() + { + Text = Loc.GetString("cp14-currency-converter-get-pp"), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/_CP14/Objects/Economy/pp_coin.rsi/coin10.png")), + Category = VerbCategory.CP14CurrencyConvert, + Priority = 4, + CloseMenu = false, + Act = () => + { + if (ent.Comp.Balance < PP.Value) + return; + + ent.Comp.Balance -= PP.Value; + var newEnt = Spawn(PP.Key, coord); + _stack.TryMergeToContacts(newEnt); + _audio.PlayPvs(ent.Comp.InsertSound, ent, AudioParams.Default.WithMaxDistance(3).WithPitchScale(1.5f)); + }, + }; + args.Verbs.Add(platinumVerb); + } + + public HashSet GenerateMoney(EntProtoId currencyType, int target, EntityCoordinates coordinates) + { + return GenerateMoney(currencyType, target, coordinates, out _); + } + + public HashSet GenerateMoney(EntProtoId currencyType, int target, EntityCoordinates coordinates, out int remainder) + { + remainder = target; + HashSet spawns = new(); + + if (!_proto.TryIndex(currencyType, out var indexedCurrency)) + return spawns; + + var ent = Spawn(currencyType, coordinates); + if (ProcessEntity(ent, ref remainder, spawns)) + return spawns; + + while (remainder > 0) + { + var newEnt = Spawn(currencyType, coordinates); + if (ProcessEntity(newEnt, ref remainder, spawns)) + break; + } + + return spawns; + } + + private bool ProcessEntity(EntityUid ent, ref int remainder, HashSet spawns) + { + var singleCurrency = GetTotalCurrency(ent); + + if (singleCurrency > remainder) + { + QueueDel(ent); + return true; + } + + spawns.Add(ent); + remainder -= singleCurrency; + + if (TryComp(ent, out var stack)) + { + AdjustStack(ent, stack, singleCurrency, ref remainder); + } + + return false; + } + + private void AdjustStack(EntityUid ent, StackComponent stack, float singleCurrency, ref int remainder) + { + var singleStackCurrency = singleCurrency / stack.Count; + var stackLeftSpace = stack.MaxCountOverride - stack.Count; + + if (stackLeftSpace is not null) + { + var addedStack = MathF.Min((float)stackLeftSpace, MathF.Floor(remainder / singleStackCurrency)); + + if (addedStack > 0) + { + _stack.SetCount(ent, stack.Count + (int)addedStack); + remainder -= (int)(addedStack * singleStackCurrency); + } + } + } +} diff --git a/Content.Server/_CP14/Objectives/Components/CP14CurrencyCollectConditionComponent.cs b/Content.Server/_CP14/Objectives/Components/CP14CurrencyCollectConditionComponent.cs index 3113679ed6..3f1a74524b 100644 --- a/Content.Server/_CP14/Objectives/Components/CP14CurrencyCollectConditionComponent.cs +++ b/Content.Server/_CP14/Objectives/Components/CP14CurrencyCollectConditionComponent.cs @@ -9,12 +9,6 @@ public sealed partial class CP14CurrencyCollectConditionComponent : Component [DataField] public int Currency = 1000; - /// - /// Limits the goal to collecting values from a specific category. - /// - [DataField] - public string? Category; - [DataField(required: true)] public LocId ObjectiveText; diff --git a/Content.Server/_CP14/Objectives/Systems/CP14CurrencyCollectConditionSystem.cs b/Content.Server/_CP14/Objectives/Systems/CP14CurrencyCollectConditionSystem.cs index 3261f7d7d9..0257ec62c6 100644 --- a/Content.Server/_CP14/Objectives/Systems/CP14CurrencyCollectConditionSystem.cs +++ b/Content.Server/_CP14/Objectives/Systems/CP14CurrencyCollectConditionSystem.cs @@ -13,7 +13,7 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem { [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly SharedObjectivesSystem _objectives = default!; - [Dependency] private readonly CP14CurrencySystem _currency = default!; + [Dependency] private readonly CP14SharedCurrencySystem _currency = default!; private EntityQuery _containerQuery; @@ -35,7 +35,7 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem private void OnAfterAssign(Entity condition, ref ObjectiveAfterAssignEvent args) { _metaData.SetEntityName(condition.Owner, Loc.GetString(condition.Comp.ObjectiveText), args.Meta); - _metaData.SetEntityDescription(condition.Owner, Loc.GetString(condition.Comp.ObjectiveDescription, ("coins", _currency.GetPrettyCurrency(condition.Comp.Currency))), args.Meta); + _metaData.SetEntityDescription(condition.Owner, Loc.GetString(condition.Comp.ObjectiveDescription, ("coins", _currency.GetCurrencyPrettyString(condition.Comp.Currency))), args.Meta); _objectives.SetIcon(condition.Owner, condition.Comp.ObjectiveSprite); } @@ -71,7 +71,7 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem foreach (var entity in container.ContainedEntities) { // check if this is the item - count += CheckCurrency(entity, condition); + count += _currency.GetTotalCurrency(entity); // if it is a container check its contents if (_containerQuery.TryGetComponent(entity, out var containerManager)) @@ -88,7 +88,7 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem private void CheckEntity(EntityUid entity, CP14CurrencyCollectConditionComponent condition, ref Stack containerStack, ref int counter) { // check if this is the item - counter += CheckCurrency(entity, condition); + counter += _currency.GetTotalCurrency(entity); //we don't check the inventories of sentient entity if (!TryComp(entity, out _)) @@ -98,16 +98,4 @@ public sealed class CP14CurrencyCollectConditionSystem : EntitySystem containerStack.Push(containerManager); } } - - private int CheckCurrency(EntityUid entity, CP14CurrencyCollectConditionComponent condition) - { - // check if this is the target - if (!TryComp(entity, out var target)) - return 0; - - if (target.Category != condition.Category) - return 0; - - return _currency.GetTotalCurrency(entity); - } } diff --git a/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.Shuttle.cs b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.Shuttle.cs new file mode 100644 index 0000000000..ca94a5456b --- /dev/null +++ b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.Shuttle.cs @@ -0,0 +1,87 @@ +using System.Numerics; +using Content.Server.Shuttles.Components; +using Content.Server.Shuttles.Events; +using Content.Shared._CP14.TravelingStoreShip; +using Content.Shared._CP14.TravelingStoreShip.Prototype; +using Robust.Shared.Map; +using Robust.Shared.Random; + +namespace Content.Server._CP14.TravelingStoreShip; + +public sealed partial class CP14CargoSystem +{ + private EntityQuery _blacklistQuery; + private void InitializeShuttle() + { + _blacklistQuery = GetEntityQuery(); + SubscribeLocalEvent(OnFTLCompleted); + } + + private void UpdateShuttle() + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var ship)) + { + if (_timing.CurTime < ship.NextTravelTime || ship.NextTravelTime == TimeSpan.Zero) + continue; + + if (Transform(ship.Shuttle).MapUid == Transform(ship.TradePostMap).MapUid) + { + // if landed on trade post + ship.NextTravelTime = _timing.CurTime + ship.StationWaitTime; + SendShuttleToStation((uid, ship)); + } + else + { + // if landed on station + ship.NextTravelTime = _timing.CurTime + ship.TradePostWaitTime; + SendShuttleToTradepost((uid, ship)); + } + } + } + + private void SendShuttleToStation(Entity station, float startupTime = 0f) + { + var targetPoints = new List(); + var targetEnumerator = EntityQueryEnumerator(); //TODO - different method position location + while (targetEnumerator.MoveNext(out var uid, out _, out _)) + { + targetPoints.Add(uid); + } + if (targetPoints.Count == 0) + return; + + var target = _random.Pick(targetPoints); + var targetXform = Transform(target); + + var shuttleComp = Comp(station.Comp.Shuttle); + + _shuttles.FTLToCoordinates(station.Comp.Shuttle, shuttleComp, targetXform.Coordinates, targetXform.LocalRotation, hyperspaceTime: 5f, startupTime: startupTime); + } + + private void SendShuttleToTradepost(Entity station) + { + var shuttleComp = Comp(station.Comp.Shuttle); + + _shuttles.FTLToCoordinates(station.Comp.Shuttle, shuttleComp, new EntityCoordinates(station.Comp.TradePostMap, Vector2.Zero), Angle.Zero, hyperspaceTime: 5f); + } + + private void OnFTLCompleted(Entity ent, ref FTLCompletedEvent args) + { + if (!TryComp(ent.Comp.Station, out var station)) + return; + + if (Transform(ent).MapUid == Transform(station.TradePostMap).MapUid) //Landed on tradepost + { + station.OnStation = false; + + SellingThings((ent.Comp.Station, station)); + UpdateStorePositions((ent.Comp.Station, station)); + } + else //Landed on station + { + station.OnStation = true; + } + UpdateAllStores(); + } +} diff --git a/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.UI.cs b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.UI.cs new file mode 100644 index 0000000000..74a692869a --- /dev/null +++ b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.UI.cs @@ -0,0 +1,87 @@ +using System.Text; +using Content.Shared._CP14.TravelingStoreShip; +using Content.Shared.UserInterface; + +namespace Content.Server._CP14.TravelingStoreShip; + +public sealed partial class CP14CargoSystem +{ + public void InitializeStore() + { + SubscribeLocalEvent(OnBeforeUIOpen); + } + + private void TryInitStore(Entity ent) + { + //TODO: There's no support for multiple stations. (settlements). + var stations = _station.GetStations(); + + if (stations.Count == 0) + return; + + if (!TryComp(stations[0], out var station)) + return; + + ent.Comp.Station = new Entity(stations[0], station); + } + + private void OnBeforeUIOpen(Entity ent, ref BeforeActivatableUIOpenEvent args) + { + if (ent.Comp.Station is null) + TryInitStore(ent); + + UpdateUIProducts(ent); + } + + //TODO: redo + private void UpdateAllStores() + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var store)) + { + UpdateUIProducts((uid, store)); + } + } + + private void UpdateUIProducts(Entity ent) + { + if (ent.Comp.Station is null) + return; + + var prodBuy = new HashSet(); + var prodSell = new HashSet(); + + foreach (var proto in ent.Comp.Station.Value.Comp.CurrentBuyPositions) + { + if (!_proto.TryIndex(proto.Key, out var indexedProto)) + continue; + + var name = Loc.GetString(indexedProto.Name); + var desc = new StringBuilder(); + desc.Append(Loc.GetString(indexedProto.Desc) + "\n"); + foreach (var service in indexedProto.Services) + { + desc.Append(service.GetDescription(_proto, EntityManager)); + } + + prodBuy.Add(new CP14StoreUiProductEntry(proto.Key.Id, indexedProto.Icon, name, desc.ToString(), proto.Value)); + } + + foreach (var proto in ent.Comp.Station.Value.Comp.CurrentSellPositions) + { + if (!_proto.TryIndex(proto.Key, out var indexedProto)) + continue; + + var name = Loc.GetString(indexedProto.Name); + + var desc = new StringBuilder(); + desc.Append(Loc.GetString(indexedProto.Desc) + "\n"); + desc.Append(indexedProto.Service.GetDescription(_proto, EntityManager)); + + prodSell.Add(new CP14StoreUiProductEntry(proto.Key.Id, indexedProto.Icon, name, desc.ToString(), proto.Value)); + } + + var stationComp = ent.Comp.Station.Value.Comp; + _userInterface.SetUiState(ent.Owner, CP14StoreUiKey.Key, new CP14StoreUiState(prodBuy, prodSell, stationComp.OnStation, stationComp.NextTravelTime)); + } +} diff --git a/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.cs b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.cs new file mode 100644 index 0000000000..c6c3ac855b --- /dev/null +++ b/Content.Server/_CP14/TravelingStoreShip/CP14CargoSystem.cs @@ -0,0 +1,205 @@ +using Content.Server._CP14.Currency; +using Content.Server.Shuttles.Systems; +using Content.Server.Station.Events; +using Content.Server.Station.Systems; +using Content.Shared._CP14.Currency; +using Content.Shared._CP14.TravelingStoreShip; +using Content.Shared._CP14.TravelingStoreShip.Prototype; +using Content.Shared.Storage.EntitySystems; +using Robust.Server.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server._CP14.TravelingStoreShip; + +public sealed partial class CP14CargoSystem : CP14SharedCargoSystem +{ + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly MapLoaderSystem _loader = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly ShuttleSystem _shuttles = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly UserInterfaceSystem _userInterface = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly CP14CurrencySystem _currency = default!; + [Dependency] private readonly SharedStorageSystem _storage = default!; + + private EntityQuery _xformQuery; + + private IEnumerable? _buyProto; + private IEnumerable? _sellProto; + + + public override void Initialize() + { + base.Initialize(); + InitializeStore(); + InitializeShuttle(); + + _xformQuery = GetEntityQuery(); + + _buyProto = _proto.EnumeratePrototypes(); + _sellProto = _proto.EnumeratePrototypes(); + + SubscribeLocalEvent(OnProtoReload); + SubscribeLocalEvent(OnPostInit); + } + + private void OnProtoReload(PrototypesReloadedEventArgs ev) + { + _buyProto = _proto.EnumeratePrototypes(); + _sellProto = _proto.EnumeratePrototypes(); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + UpdateShuttle(); + } + + private void OnPostInit(Entity station, ref StationPostInitEvent args) + { + if (!Deleted(station.Comp.Shuttle)) + return; + + var tradepostMap = _mapManager.CreateMap(); + + if (!_loader.TryLoad(tradepostMap, station.Comp.ShuttlePath.ToString(), out var shuttleUids)) + return; + + var shuttle = shuttleUids[0]; + station.Comp.Shuttle = shuttle; + station.Comp.TradePostMap = _mapManager.GetMapEntityId(tradepostMap); + var travelingStoreShipComp = EnsureComp(station.Comp.Shuttle); + travelingStoreShipComp.Station = station; + + station.Comp.NextTravelTime = _timing.CurTime + TimeSpan.FromSeconds(10f); + UpdateStorePositions(station); + } + + private void UpdateStorePositions(Entity station) + { + station.Comp.CurrentBuyPositions.Clear(); + station.Comp.CurrentSellPositions.Clear(); + + if (_buyProto is not null) + { + foreach (var buyPos in _buyProto) + { + station.Comp.CurrentBuyPositions.Add(buyPos, buyPos.Price.Next(_random)); + } + } + if (_sellProto is not null) + { + foreach (var sellPos in _sellProto) + { + station.Comp.CurrentSellPositions.Add(sellPos, sellPos.Price.Next(_random)); + } + } + } + + private void SellingThings(Entity station) + { + var shuttle = station.Comp.Shuttle; + + //Get all entities sent to trading posts + var toSell = new HashSet(); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _, out var palletXform)) + { + if (palletXform.ParentUid != shuttle || !palletXform.Anchored) + continue; + + var sentEntities = new HashSet(); + + _lookup.GetEntitiesInRange(uid, 1, sentEntities, LookupFlags.Dynamic | LookupFlags.Sundries); + + foreach (var ent in sentEntities) + { + if (toSell.Contains(ent) || !_xformQuery.TryGetComponent(ent, out _)) + continue; + + toSell.Add(ent); + } + } + + var cash = 0; + foreach (var sellPos in station.Comp.CurrentSellPositions) + { + if (!_proto.TryIndex(sellPos.Key, out var indexedPos)) + continue; + + while (indexedPos.Service.TrySell(EntityManager, toSell)) + { + cash += sellPos.Value; + } + } + + var moneyBox = GetMoneyBox(station); + if (moneyBox is not null) + { + var coord = Transform(moneyBox.Value).Coordinates; + + if (cash > 0) + { + var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.PP.Key, cash, coord, out var remainder); + cash = remainder; + foreach (var coin in coins) + { + _storage.Insert(moneyBox.Value, coin, out _); + } + } + + if (cash > 0) + { + var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.GP.Key, cash, coord, out var remainder); + cash = remainder; + foreach (var coin in coins) + { + _storage.Insert(moneyBox.Value, coin, out _); + } + } + + if (cash > 0) + { + var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.SP.Key, cash, coord, out var remainder); + cash = remainder; + foreach (var coin in coins) + { + _storage.Insert(moneyBox.Value, coin, out _); + } + } + + if (cash > 0) + { + var coins = _currency.GenerateMoney(CP14SharedCurrencySystem.CP.Key, cash, coord); + foreach (var coin in coins) + { + _storage.Insert(moneyBox.Value, coin, out _); + } + } + } + } + + private EntityUid? GetMoneyBox(Entity station) + { + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out _, out var xform)) + { + if (xform.GridUid != station.Comp.Shuttle) + continue; + + return uid; + } + + return null; + } +} diff --git a/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipComponent.cs b/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipComponent.cs new file mode 100644 index 0000000000..1d82d9b381 --- /dev/null +++ b/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server._CP14.TravelingStoreShip; + +[RegisterComponent, Access(typeof(CP14CargoSystem)), AutoGenerateComponentPause] +public sealed partial class CP14TravelingStoreShipComponent : Component +{ + [DataField] + public EntityUid Station; +} diff --git a/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipFTLTargetComponent.cs b/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipFTLTargetComponent.cs new file mode 100644 index 0000000000..4f09246886 --- /dev/null +++ b/Content.Server/_CP14/TravelingStoreShip/CP14TravelingStoreshipFTLTargetComponent.cs @@ -0,0 +1,10 @@ + +namespace Content.Server._CP14.TravelingStoreShip; + +/// +/// One of the possible points where an traveling store ship might land +/// +[RegisterComponent, Access(typeof(CP14CargoSystem))] +public sealed partial class CP14TravelingStoreShipFTLTargetComponent : Component +{ +} diff --git a/Content.Shared/Verbs/VerbCategory.cs b/Content.Shared/Verbs/VerbCategory.cs index d1d0becf38..29a5f6c73d 100644 --- a/Content.Shared/Verbs/VerbCategory.cs +++ b/Content.Shared/Verbs/VerbCategory.cs @@ -90,5 +90,7 @@ namespace Content.Shared.Verbs public static readonly VerbCategory PowerLevel = new("verb-categories-power-level", null); public static readonly VerbCategory CP14RitualBook = new("cp14-verb-categories-ritual-book", null); //CP14 + + public static readonly VerbCategory CP14CurrencyConvert = new("cp14-verb-categories-currency-converter", null); //CP14 } } diff --git a/Content.Shared/_CP14/Currency/CP14CurrencyComponent.cs b/Content.Shared/_CP14/Currency/CP14CurrencyComponent.cs index 23285b82a3..ce712d2c40 100644 --- a/Content.Shared/_CP14/Currency/CP14CurrencyComponent.cs +++ b/Content.Shared/_CP14/Currency/CP14CurrencyComponent.cs @@ -4,15 +4,9 @@ namespace Content.Shared._CP14.Currency; /// Reflects the market value of an item, to guide players through the economy. /// -[RegisterComponent, Access(typeof(CP14CurrencySystem))] +[RegisterComponent, Access(typeof(CP14SharedCurrencySystem))] public sealed partial class CP14CurrencyComponent : Component { [DataField] public int Currency = 1; - - /// - /// allows you to categorize different valuable items in order to, for example, give goals for buying weapons, or earning money specifically. - /// - [DataField] - public string? Category; } diff --git a/Content.Shared/_CP14/Currency/CP14CurrencyConverterComponent.cs b/Content.Shared/_CP14/Currency/CP14CurrencyConverterComponent.cs new file mode 100644 index 0000000000..5348094b4a --- /dev/null +++ b/Content.Shared/_CP14/Currency/CP14CurrencyConverterComponent.cs @@ -0,0 +1,25 @@ +using System.Numerics; +using Content.Shared.Whitelist; +using Robust.Shared.Audio; + +namespace Content.Shared._CP14.Currency; + +/// +/// Reflects the market value of an item, to guide players through the economy. +/// + +[RegisterComponent] +public sealed partial class CP14CurrencyConverterComponent : Component +{ + [DataField] + public int Balance; + + [DataField] + public EntityWhitelist? Whitelist; + + [DataField] + public Vector2 SpawnOffset = new Vector2(0, -0.4f); + + [DataField] + public SoundSpecifier InsertSound = new SoundCollectionSpecifier("CP14Coins"); +} diff --git a/Content.Shared/_CP14/Currency/CP14CurrencySystem.cs b/Content.Shared/_CP14/Currency/CP14CurrencySystem.cs deleted file mode 100644 index 79d0c7dd53..0000000000 --- a/Content.Shared/_CP14/Currency/CP14CurrencySystem.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Content.Shared.Examine; -using Content.Shared.Stacks; - -namespace Content.Shared._CP14.Currency; - -public sealed partial class CP14CurrencySystem : EntitySystem -{ - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnExamine); - } - - private void OnExamine(Entity currency, ref ExaminedEvent args) - { - var total = GetTotalCurrency(currency, currency.Comp); - - var push = Loc.GetString("cp14-currency-examine-title"); - push += GetPrettyCurrency(total); - args.PushMarkup(push); - } - - public string GetPrettyCurrency(int currency) - { - var total = currency; - - if (total <= 0) - return string.Empty; - - var gp = total / 100; - total %= 100; - - var sp = total / 10; - total %= 10; - - var cp = total; - - var push = string.Empty; - - if (gp > 0) push += " " + Loc.GetString("cp14-currency-examine-gp", ("coin", gp)); - if (sp > 0) push += " " + Loc.GetString("cp14-currency-examine-sp", ("coin", sp)); - if (cp > 0) push += " " + Loc.GetString("cp14-currency-examine-cp", ("coin", cp)); - - return push; - } - - public int GetTotalCurrency(EntityUid uid, CP14CurrencyComponent? currency = null) - { - if (!Resolve(uid, ref currency)) - return 0; - - var total = currency.Currency; - - if (TryComp(uid, out var stack)) - { - total *= stack.Count; - } - - return total; - } -} diff --git a/Content.Shared/_CP14/Currency/CP14SharedCurrencySystem.cs b/Content.Shared/_CP14/Currency/CP14SharedCurrencySystem.cs new file mode 100644 index 0000000000..e1efc4b15a --- /dev/null +++ b/Content.Shared/_CP14/Currency/CP14SharedCurrencySystem.cs @@ -0,0 +1,54 @@ +using System.Text; +using Content.Shared.Stacks; +using Robust.Shared.Prototypes; +namespace Content.Shared._CP14.Currency; + +public partial class CP14SharedCurrencySystem : EntitySystem +{ + public static readonly KeyValuePair CP = new("CP14CopperCoin1", 1); + public static readonly KeyValuePair SP = new("CP14SilverCoin1", 10); + public static readonly KeyValuePair GP = new("CP14GoldCoin1", 100); + public static readonly KeyValuePair PP = new("CP14PlatinumCoin1", 1000); + + public string GetCurrencyPrettyString(int currency) + { + var total = currency; + + if (total <= 0) + return string.Empty; + + var gp = total / 100; + total %= 100; + + var sp = total / 10; + total %= 10; + + var cp = total; + + var sb = new StringBuilder(); + + if (gp > 0) + sb.Append( " " + Loc.GetString("cp14-currency-examine-gp", ("coin", gp))); + if (sp > 0) + sb.Append( " " + Loc.GetString("cp14-currency-examine-sp", ("coin", sp))); + if (cp > 0) + sb.Append( " " + Loc.GetString("cp14-currency-examine-cp", ("coin", cp))); + + return sb.ToString(); + } + + public int GetTotalCurrency(EntityUid uid, CP14CurrencyComponent? currency = null) + { + if (!Resolve(uid, ref currency)) + return 0; + + var total = currency.Currency; + + if (TryComp(uid, out var stack)) + { + total *= stack.Count; + } + + return total; + } +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14CargoMoneyBoxComponent.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14CargoMoneyBoxComponent.cs new file mode 100644 index 0000000000..1fa6473692 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14CargoMoneyBoxComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Shared._CP14.TravelingStoreShip; + +/// +/// marks an entity into which trade with the city will put money when selling, or take it when buying. +/// +[RegisterComponent] +public sealed partial class CP14CargoMoneyBoxComponent : Component +{ +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14CargoStoreComponent.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14CargoStoreComponent.cs new file mode 100644 index 0000000000..07bf641536 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14CargoStoreComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared._CP14.TravelingStoreShip; + +/// +/// Allows users to view information on city trading opportunities +/// +[RegisterComponent] +public sealed partial class CP14CargoStoreComponent : Component +{ + [DataField] + public Entity? Station = null; +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14SellingPalettComponent.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14SellingPalettComponent.cs new file mode 100644 index 0000000000..89692e4c47 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14SellingPalettComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared._CP14.TravelingStoreShip; + +[RegisterComponent] +public sealed partial class CP14SellingPalettComponent : Component +{ +} + +[RegisterComponent] +public sealed partial class CP14BuyingPalettComponent : Component +{ +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14SharedCargoSystem.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14SharedCargoSystem.cs new file mode 100644 index 0000000000..3e3f84d3ff --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14SharedCargoSystem.cs @@ -0,0 +1,5 @@ +namespace Content.Shared._CP14.TravelingStoreShip; + +public class CP14SharedCargoSystem : EntitySystem +{ +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14StationTravelingStoreShipTargetComponent.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14StationTravelingStoreShipTargetComponent.cs new file mode 100644 index 0000000000..4f8b4f9e17 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14StationTravelingStoreShipTargetComponent.cs @@ -0,0 +1,46 @@ +using Content.Shared._CP14.TravelingStoreShip.Prototype; +using Content.Shared.Destructible.Thresholds; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared._CP14.TravelingStoreShip; + +/// +/// Add to the station so that traveling store ship starts running on it +/// +[RegisterComponent] +public sealed partial class CP14StationTravelingStoreShipTargetComponent : Component +{ + [DataField] + public EntityUid Shuttle; + + [DataField] + public EntityUid TradePostMap; + + [DataField] + public bool OnStation; + + [DataField] + public ResPath ShuttlePath = new("/Maps/_CP14/Ships/balloon.yml"); + + [DataField] + public TimeSpan NextTravelTime = TimeSpan.Zero; + + [DataField] + public TimeSpan StationWaitTime = TimeSpan.FromMinutes(6); + + [DataField] + public TimeSpan TradePostWaitTime = TimeSpan.FromMinutes(4); + + [DataField] + public Dictionary, int> CurrentBuyPositions = new(); //Proto, price + + [DataField] + public MinMax SpecialBuyPositionCount = new(1, 2); + + [DataField] + public Dictionary, int> CurrentSellPositions = new(); //Proto, price + + [DataField] + public MinMax SpecialSellPositionCount = new(1, 2); +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/CP14StoreUI.cs b/Content.Shared/_CP14/TravelingStoreShip/CP14StoreUI.cs new file mode 100644 index 0000000000..c9081e98d9 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/CP14StoreUI.cs @@ -0,0 +1,64 @@ +using Content.Shared._CP14.Workbench; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared._CP14.TravelingStoreShip; + +[Serializable, NetSerializable] +public enum CP14StoreUiKey +{ + Key, +} + +[Serializable, NetSerializable] +public sealed class CP14StoreUiState : BoundUserInterfaceState +{ + public readonly HashSet ProductsBuy; + public readonly HashSet ProductsSell; + + public bool OnStation; + public readonly TimeSpan NextTravelTime; + + public CP14StoreUiState(HashSet productsBuy, HashSet productsSell, bool onStation, TimeSpan time) + { + ProductsBuy = productsBuy; + ProductsSell = productsSell; + OnStation = onStation; + NextTravelTime = time; + } +} + +[Serializable, NetSerializable] +public readonly struct CP14StoreUiProductEntry : IEquatable +{ + public readonly string ProtoId; + public readonly SpriteSpecifier Icon; + public readonly string Name; + public readonly string Desc; + public readonly int Price; + + public CP14StoreUiProductEntry(string protoId, SpriteSpecifier icon, string name, string desc, int price) + { + ProtoId = protoId; + Icon = icon; + Name = name; + Desc = desc; + Price = price; + } + + public bool Equals(CP14StoreUiProductEntry other) + { + return ProtoId == other.ProtoId; + } + + public override bool Equals(object? obj) + { + return obj is CP14StoreUiProductEntry other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(ProtoId, Icon, Name, Desc, Price); + } +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/Prototype/BuyServices/CP14BuyItemsService.cs b/Content.Shared/_CP14/TravelingStoreShip/Prototype/BuyServices/CP14BuyItemsService.cs new file mode 100644 index 0000000000..60737691da --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/Prototype/BuyServices/CP14BuyItemsService.cs @@ -0,0 +1,32 @@ +using System.Text; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.TravelingStoreShip.Prototype.BuyServices; + +public sealed partial class CP14BuyItemsService : CP14StoreBuyService +{ + [DataField(required: true)] + public Dictionary Product = new(); + + public override void Buy(EntityManager entManager, EntityUid station) + { + foreach (var pai in Product) + { + Logger.Debug($"куплено: {pai.Key} x{pai.Value}"); + } + } + + public override string? GetDescription(IPrototypeManager prototype, IEntityManager entSys) + { + var sb = new StringBuilder(); + sb.Append(Loc.GetString("cp14-store-service-buy-items") + " \n"); + foreach (var pai in Product) + { + if (!prototype.TryIndex(pai.Key, out var indexedProto)) + continue; + + sb.Append($"{indexedProto.Name} x{pai.Value} \n"); + } + return sb.ToString(); + } +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreBuyPositionPrototype.cs b/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreBuyPositionPrototype.cs new file mode 100644 index 0000000000..9e0786741a --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreBuyPositionPrototype.cs @@ -0,0 +1,46 @@ +using Content.Shared.Destructible.Thresholds; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared._CP14.TravelingStoreShip.Prototype; + +/// +/// Stores the price and product/service pair that players can buy. +/// +[Prototype("storePositionBuy")] +public sealed partial class CP14StoreBuyPositionPrototype : IPrototype +{ + [IdDataField, ViewVariables] + public string ID { get; private set; } = default!; + + /// + /// if true, this item becomes available for purchase only after unlocking by other purchases + /// + [DataField] + public bool Unlockable = false; + + [DataField(required: true)] + public MinMax Price = new(); + + [DataField(required: true)] + public LocId Name = string.Empty; + + [DataField] + public LocId Desc = string.Empty; + + [DataField(required: true)] + public SpriteSpecifier Icon = default!; + + [DataField(required: true)] + public List Services = new(); +} + +[ImplicitDataDefinitionForInheritors] +[MeansImplicitUse] +public abstract partial class CP14StoreBuyService +{ + public abstract void Buy(EntityManager entManager, EntityUid station); + + public abstract string? GetDescription(IPrototypeManager prototype, IEntityManager entSys); +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreSellPositionPrototype.cs b/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreSellPositionPrototype.cs new file mode 100644 index 0000000000..aa5afda5bc --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/Prototype/CP14StoreSellPositionPrototype.cs @@ -0,0 +1,46 @@ +using Content.Shared.Destructible.Thresholds; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared._CP14.TravelingStoreShip; + +/// +/// Stores the price and product/service pair that players can buy. +/// +[Prototype("storePositionSell")] +public sealed partial class CP14StoreSellPositionPrototype : IPrototype +{ + [IdDataField, ViewVariables] + public string ID { get; private set; } = default!; + + /// + /// if true, this item becomes available for purchase only after unlocking by other purchases + /// + [DataField] + public bool Unlockable = false; + + [DataField(required: true)] + public MinMax Price = new(); + + [DataField(required: true)] + public LocId Name = string.Empty; + + [DataField] + public LocId Desc = string.Empty; + + [DataField(required: true)] + public SpriteSpecifier Icon = default!; + + [DataField(required: true)] + public CP14StoreSellService Service = default!; +} + +[ImplicitDataDefinitionForInheritors] +[MeansImplicitUse] +public abstract partial class CP14StoreSellService +{ + public abstract bool TrySell(EntityManager entManager, HashSet entities); + + public abstract string? GetDescription(IPrototypeManager prototype, IEntityManager entSys); +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellStackService.cs b/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellStackService.cs new file mode 100644 index 0000000000..766b8714ad --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellStackService.cs @@ -0,0 +1,57 @@ +using Content.Shared.Stacks; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.TravelingStoreShip.Prototype.SellServices; + +public sealed partial class CP14SellStackService : CP14StoreSellService +{ + [DataField(required: true)] + public ProtoId StackId = new(); + + [DataField(required: true)] + public int Count = 1; + + public override bool TrySell(EntityManager entManager, HashSet entities) + { + var stackSystem = entManager.System(); + + Dictionary, int> suitable = new(); + + int needCount = Count; + foreach (var ent in entities) + { + if (needCount <= 0) + break; + + if (!entManager.TryGetComponent(ent, out var stack) || stack.StackTypeId != StackId.Id) + continue; + + var consumed = Math.Min(needCount, stack.Count); + suitable.Add((ent,stack), consumed); + needCount -= consumed; + } + + if (needCount > 0) + return false; + + foreach (var selledEnt in suitable) + { + if (selledEnt.Key.Comp.Count == selledEnt.Value) + { + entities.Remove(selledEnt.Key); + entManager.QueueDeleteEntity(selledEnt.Key); + } + else + { + stackSystem.Use(selledEnt.Key, selledEnt.Value); + } + } + + return true; + } + + public override string? GetDescription(IPrototypeManager prototype, IEntityManager entSys) + { + return null; + } +} diff --git a/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellWhitelistService.cs b/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellWhitelistService.cs new file mode 100644 index 0000000000..6305f22256 --- /dev/null +++ b/Content.Shared/_CP14/TravelingStoreShip/Prototype/SellServices/CP14SellWhitelistService.cs @@ -0,0 +1,52 @@ +using Content.Shared.Whitelist; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.TravelingStoreShip.Prototype.SellServices; + +public sealed partial class CP14SellWhitelistService : CP14StoreSellService +{ + [DataField(required: true)] + public EntityWhitelist Whitelist = new(); + + [DataField(required: true)] + public int Count = 1; + + public override bool TrySell(EntityManager entManager, HashSet entities) + { + var whitelistSystem = entManager.System(); + + HashSet suitable = new(); + + int needCount = Count; + foreach (var ent in entities) + { + if (needCount <= 0) + break; + + if (!entManager.TryGetComponent(ent, out var metaData) || metaData.EntityPrototype is null) + continue; + + if (!whitelistSystem.IsValid(Whitelist, ent)) + continue; + + suitable.Add(ent); + needCount -= 1; + } + + if (needCount > 0) + return false; + + foreach (var selledEnt in suitable) + { + entities.Remove(selledEnt); + entManager.QueueDeleteEntity(selledEnt); + } + + return true; + } + + public override string? GetDescription(IPrototypeManager prototype, IEntityManager entSys) + { + return null; + } +} diff --git a/Resources/Audio/_CP14/Items/attributions.yml b/Resources/Audio/_CP14/Items/attributions.yml index cfdc40a237..60e943073e 100644 --- a/Resources/Audio/_CP14/Items/attributions.yml +++ b/Resources/Audio/_CP14/Items/attributions.yml @@ -66,4 +66,9 @@ - files: ["book2.ogg"] license: "CC-BY-4.0" copyright: 'by InspectorJ of Freesound.org. edit to Mono by TheShuEd.' - source: "https://freesound.org/people/InspectorJ/sounds/416179/" \ No newline at end of file + source: "https://freesound.org/people/InspectorJ/sounds/416179/" + +- files: ["coins1.ogg", "coins2.ogg", "coins3.ogg", "coins_fall.ogg"] + license: "CC0-1.0" + copyright: 'by severaltimes of Freesound.org. Cropped by TheShuEd.' + source: "https://freesound.org/people/severaltimes/sounds/173989/" \ No newline at end of file diff --git a/Resources/Audio/_CP14/Items/coins1.ogg b/Resources/Audio/_CP14/Items/coins1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9a10d5d7f80d97111c765e4e521a1bd6cd591bb2 GIT binary patch literal 9891 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 G!2bder+vEs literal 0 HcmV?d00001 diff --git a/Resources/Audio/_CP14/Items/coins2.ogg b/Resources/Audio/_CP14/Items/coins2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8e83ff7da880aeab6e67a024b11242dc38859e09 GIT binary patch literal 11753 zcmb7qby!tT_wPP*cMEtx>d@UN(j2-Q=?>-4Edl}(0tcj|TR=flT0lVQ?vMsWk(Bao z@cX{^eeWOlckeuN=2?5KS!-&2X4dR|H0f&gne`_78 z4CUwL=j9dQ6@;>B+uC?pJG$9J<=wm;J>1<~ZQVR!sG!~*@F%Y>t05<^Ed{Dtdf7O- zi$nj~wRN*51H})ub(M8=rF3k)Z9Obqpt_E(wul?PuClJGyp*iFqZYP8W0M@%J5i`*=;?gr`{yiqG9j7p(3Jrk<<}VDRahq49N>JyHZ>9 zSolWh065*!SPbE0+DZ%&|0-ZbX;v|?;xwzzuo7Ct0ADZk8G-nAVX~$SHmpz+&R$lC z)P{3S86);vF&7a(9-cwNiDW<{|0-_B0R{U4GHq^|Hldc9@u1i-dWUpKDxONJl_QPgj0YSIujB$q8_O*DR8DW2Ie$<8m;K02c`J!88p8|StP z=qhM8y#ZEyW43(b?fsH&%Zw7ojN<>-EbY+84oHJ@+53d{Z&vhR!n~c~J^)-(X>F!n z4^BmdU@t;a(NnJ1Q?(zd+h1pj`>#a+mmN&fq@40PlD)~2!=ysPmC}OD0JZq>^Y!%dqp38J@!Zrh`-!@tM zgV;Abu-$(O>|6Jd2G`AUhU(MnFlbObh7}n@F+(!FX97WTE?*z4kUlP60bce@Q=6K# z$TRGAW{9M+ief0q^1xv)Eli4G|IGG&fd32UO;OP`B)<2qi%1rauXYU1 zDKx2X9ap!Rji?e+axSWyGUg}(9UNBl7g6A%LTz3?#Gt;#M`W4@h>F}Woc~<7pG?EV zbff=~hYx5$Xa4KYx6Z6*;O%Pk%4@zM!feKCc{*r$I_?o=q^(ivf91bJ2S) zDNE1ZDa-#qkdx~WQ<4@_5*4!*70(u(>KL6--jwh1xoYpj|Cs-c91t*Ime*#I|1acp z@X^YG;HlwMJN!FFsZnru@RXefW<&=d$io@xO$ecgd73f;2)CmuXfse7;pX+MpwBU8cG`Qeq z@EH8PBf`NqA_n9j01*~L(MxS5*k+ao0jwy?dWfMIiTEtGk@aj$xhxAYCI(B?zIpT* zQr^kZ9TJ1R4hK(26k71d84f}P4S0eA5cD2MDv!%)jR|TUsg8O{je43XkE`mC%Ii(a zY3ZpM)VYr8+M0|Bj!%G(LRz|dT0*X~x_a{`s^h6@)03`RdR`{=u9m*8^QThdwcw-c zqNkaOkL&EIt;uwp;;ktI(3F>&!KAB>m#Z16{4}|qL8|;@imgGa*P|5M#c8=wFZoHN znUYv8J&1(=>?gj*xpD_ zU6&~%XQzTzJJ`U1L4YIDY zeRLMFTz2v4Ahx`GulzesJNuW9?{J$B7utA`Uh`+Ji}nj`2?uMJpAwztKl1I>BNp1K zINJ{ef^7}`iyh~S_s&1;d}!m@`@px*_LfXzZS440t)2vZcG*+78<_KJ;6vQ^i%%XG;#)rPLqGAbL5I5W4cQ zAo3vKLub&&1NVa>0vR~5H4*<-q0N9Yc2OY(T$#%XPi8X>IUokhL#E2WxFSf5af`Ys z;Et7b`p!;VQ$%p*JS3GYjH`IcNwsp4h7W@Qp$^~70(Uo1FvY)B>Peuz3k8pJr|Lp7 z>y0cVo;W*QI1E$Bl=Dz)$&`~?^~RjlfYc_H&0rHIp$s@c3RxIm{gjg{-zM!pjl-ruQ(RMXpy0Og zNg8k*Q#0UPO@pS&dNQ1cI(yTsHMpi|tp}ufQk@5zPBTnif>6g31rMY&O$-pW*tf6^ zXX~K~$6)xBl{^CNPD5z3f699H65f-BAcB9+dZr17r-PI-44DLnS4L>V;bnCoY;kU2 z>oS5gq|LqAbfnpV(9S2EUk>H8gluQ4nTAQ_$3awj-*83+^(O1N{&GMEzTxQVO?r7P zlHLSH)1c>{-q!H~;h;9|dBd4M2^tsFoA$B=_jyaNTh5fLwc!nCw%*lD%xw`w1ZAXU z+T4fzi#8s--k++dKnE!;5Q^hsNVi((!1?aBR~P_bi6?`>5P>HHMukWjB^WaRSad)D zXh%4|rb8bbfP#@GwA|F`1yRQ>-h$boHxRbb_hMb|DCtGxBo zh{y^w;3F8{TZ29-zQa^F!Mi~fuC1+Hl%l}51w|%l!z=ZMl$DB#ri@=yd#Hn}P)A`B z3p%5*6W1py>u;c!8awlW6kAadm30N*l(DRGSsj&itkATvHdqB5P19+T_6xpGrq26K zucoXj>NdgXM5>O$x>9Is0rB&u@=zTZeQQ?s7&=#pVXg*1fCYR4fCyW7=v|Vhz9^09 z?KCj~q0&)&pRy1HAb{oIe4v@zcvuPc4=?=XKfFAoHveB9Gg1?T=uJJ42k-x@doyWt zp8xP*MK|_tq_83|=w|yHtsp_^KNQKoDeZsNE7XSnqXDX6Gu-Ol6nWt{R&J=9c5f;6 zBJig2cm+HXEzn-u=o*E`v6%V-w~h~n%FrQW7ns7$L`U{PyP=Udu%4_sJlHeZVpUi; zGG&M_GAfzE1eYAVC`l9Dgia_=QP_B2LI6xGY;8c=@@bxII2KVsM@M60EqL3Jv58cY zA5CD2Hh=@mN6`%KFDn<2SDJz2!6d29}9hg9eC5oJ!VDISa0fdB+Uq+kc zR&-OKq5X~eZ|<9DXn!w|()a(0Z!VBG{BRy4Z9%5~&+}~TENmRC++2cO?A+W!0s`|K z9PI2OTs(YhTrBJy0zAAtY-}(AK4BsL1O@j3|6L^+{7M*PC~ z{kOLGuIRLmAAMg}T)6k2hxDemwC`du4+&10lrw0`UfZ;cM$)~;@|b-zjoq)GX4jMU zQSY($aM#`7#&%59?zt|`@7<5Frrx+hjIoh?KdCY!o}}COazDkSe%F&#;~Vveem)3- zx28R_Omdb>^CD39HG1qjpN9L-{Nd`NZC9BI!|0)yRnj3ONhs3NT|XZLesY5&iiOx~ zgLbgK#U%te0!wXQ z`QmZ`VHVCe%$E()1dk~dHYnV4mfMzldj~%Umc`X|hjnSTW}(l~-(!rx-j$pQwHAiwzPO)Tj2m)aq#PlYPe7%QXH@N&L*sH){VA1oF4n`~Ma zBEH8L#yi0cCY-j1`Yc}BHTSO%rQa@ z_I*Go5Z}S0UbDCTl8}u0IAWO?;t-{*QuOc%YWbd_Z|W>FZwCGy)XNDC03ahKEsUfx zF?E<}fa9B5s#`#i5B0?-V@&1Qy^D32f2OKD-NL6~BFC4O+_l4{0q%-GAz9!-avEZj zcZ|ar^@@ThlfNy&NMIyjF&BlF*j9;!{Ml3Xly6)mC@55+$zIMSLN6pr+WFVrr)RM8 zPKMPZAXRBFPT-O(Nck?U>Kn-82sbEDg}$<{i%c^8r5j8@s@O(n?L%>bMinv$IU>WS z;0mLFUbzuM$}oh1ir=$A7&=(*e68y^u1p@&PCqAIpW^E#G~2jp)kEjB9H(;`r4s!W_?Ds zmF9KLXD{qKc(`iQO2i%ee#0xKQ1Op~nlD{|T)3X0boM!}q^&Ys3QN7^n3Wh}x@xa` zgtCpcBB1t%=;gMm8CGaM4vr=b+5K0}&(xOb0ZAkL9BE9u{(!E;j-H>XxiZ)mq#b>< zMqfF$`#I3dMj*gk#&e7|b9P)+qq1H}W4uk8uWst7j}rm%d4L}{nldoS=rBVu)(3#L zjxP37Y~+4>vAiH4sby4t|2qr!M(5Y#Z47RbTp9FGEFkkz&lraX68J(3uxRL`BR;or z+d6iLMUgYp`xwigO}0NXQ_abZqxmEVAdHt!2E#BhU-WWdaCA+ z_&X7PpMC?XLDdWo=$}L(pdn)ShtrT1+peqW|%mFm-j8PdS&DiWXPm*T10v-9iW?~=O+sGn> z;EYtjm;%=;&gI7t-`Kn?b`IQ104R`kQIp0h_k_^#w9}^Jk8K`h7G$$Rq_GR+d{EFr zg^1C@?Zr0TmxxCL8o?K4S6>L$#J};4zseBkAMiyMTuCOaoT?rH{4d3)ojO4}a z{q}2{oGp95hN(v%8qEMm!qm#Bkt?}RTUrffLpe+#l%d#wv}txdeR5e)y(x~g>}h`a zN^H-b4j{-C)Za?TAkDooxDkh5^*GlG0>-K5fd_IlGOGB*wRZuaxx`;<>3ulBBovgx zPSU{KqG1m)Xw+aQ1FFz~REw})>fD@ah7JiFpiwG4fb0IGB&Qkaa9uyGs1NGOi%@vS z4|)=k&q5FDt;;D4i(718kWq9u;{m@P~yaJZ+i%R_r) zHSDpVT;Wil+no^u(&Fa*gN-gW<-u^B&jk^tDv_X6=EN+AH2T=9lHZ0Hi4MRiLo&nZ zn2ED_^&5%QX6mBg?VW4$!-wpvCIJv8J&xr-l18-Sc`+V5x1=tJ^wZXYG_RDeSdLGh zo0{D{C4m(=d=u>llGnGU`5{b3SCKRQcadlpHZt!pc%ITI0fE=bpKEr@$`Kz#MoNeD zS)=rX$aZX;l1`U)ALT&!F>2#!+w0=9Q*8_=qYr#aFH^QQ`93 z!~6AML$*_hlKIW6dvkIW98gN0r(=(+uOpu&E?P<}>{6NTTbBB~HjwL8Oo_=4-f2b3 zp3Ho#sH3n+y!i8i_F!sh$A=In#ds&kBlS`K^PmYu>p36OXA2ST^r4ZJmFX!x$205i z)%Q_0u!c!j94iF_?n#?}CB_F{PKFBlxIgG{dWBWJ;r|iFMN>h9*7u7W4J&><|Ws#68YVS92$LqPSRd*E#G3TdaVF_3GT2U(#u*(W!Z z&qKLZ2rg~Nrd}3tSj&f)YEhDtdpan<=S7BzJ9^1cfD^y%C_WVNih84AOy5ecHpS-h z+T2)SAW%;+Y2g!5X$Jn@Hd@t;>scOJs8I$rjV_aVD>IqF%lh`K`i*`R{%mZ()2kKf zDPzG9`eq4oxjkGuV*;E5D}KR48ri0Z9=5YH9iLo()zssBeJa}mD6C_e9LP%aX%+Xv z3ST%rA*v#>%gUnFHNdT8!aNFZ8G>r;_S~3mRao#F~ZZ`jjGFu^iVf-h4~?8 z-wLGg%bz*cSEQd+9R7JTaPBz=PrjgVXCyw_+Tlq;w~1Ir;fq{BFrIySgZ`9oq@iLl z+|c!xD^tSv8uM`Fx7cad@#2H;0aL$Mu`_U@Tx5xF0r}!8Mv3Yu-E!+EPZqC9I#b5u<8XqRI8ayYAjsD_ zjEnMEx{HwspIw#kr85(KpT)OMhu$@p!rP^tyECdDsnCr$Q}eKyTwQgq!vhLm`!rp~ z5G6KpRr?I#qpzz-h$nRS(Dc;|w+|AR9^w+l@JB?-KJ4iIa8h^dZc_72ZXnPVD2$`j zwonKMno{S~2wwjGp6J9F`i`cuo`XYx9pQk8=I`7V6I63P-#BxvSmhlRwWlChr_v2fd)__Fr7S+>NU| z$Py~Uo2qQZ!yWEA@YTlOaNDKwIF{JzT6^#+T}-m9VAJjHql~coR{X5hyojfJ*B2jb zW0bX}(fG~r$m|F$0y*f_f4}(SH**Tq6dFdBm6nFik3B!1Eg1PD0G?uk-^7T9JMui% zDPv>eLK<^W&Qhk;Cf&9IHLPP-`UF|Mc1)=D_?a z0GT;N&WZjAY5M18TP?hh`(>Nu%s}nvhAh*!sNZRo^s*M&5Gfa|CU!fCg4tv-JhT=- z3{{h^X3}TfcB1X-Rgg*>g;nblA=Xyg%ZWJ?69?f-$5;pF8uj&7S^%f=-1P1bBy9k;d8r^u3i+9v@AKV@-k$pIkMs;B1lgKpr zO)I#wk#mwqI;JbNdR5gzFkFe2l0VLm??sj}BYn{HblPo-DR2kawmgzBS=682;MP@z zwN{z%4l}*juZVTEXlKZw0!X%V&6ixVE}zKuPLdpDPvS_9s|Z;@ID?h+?{h9Kq?|O9 z!I&q5TuP(WU=!~OBXJalzp6=)D2bZQmfV~12N*|pePZG&U(1eVP1kqx8jvnK4wt{b zFVa6gbj>ec(Y`2);}mYC&q@7Ca2}qOwGp?e)W-1P4&PTKO@K@+n4m~eINMAm7b|lILQwqX^piSA;SE3Buf5& zdT>-j?A~JMQFM*MveOZ;sf6nrjjBc|{{>N!q|K@y) zON29{loYibLJKElGV}eq#I-$3&NInZ!Vc|wypzvO2{}0u$hwG)JFM0{o@k0caM`-fL(}p zg_ZdpGYcy>`2Bpb^L=YmZFQR>M#96k7ZX(Ns9yJeDA>DH&BVo(a}L#PxM_=_uYUe< z56@bL_hfkH!Sb_^Kd-Nj4{TcVMHaBT@Y)I)(K3mQ2I)?|rjl{E z`(7+-CtR^Oh(zO@=O6=kPh$|R2wqHwRbtUpdn#q-tKL)5!v*rBv-M)vh3fdWk?z&# zuXFiQ_G-@Wx9-A45rreXg^pRV9uZC2k#>rf-g;=8iJ~3Xqwl2pY_U8mP5!R(V)BiWRXYAVp#1ur<%qxS!v}dP zQAvz7$Pz{P1#dCUPi3NDVWBT;7Odfw1}?AZtRQ*ptmFf={e`0)MjhU?0E@iG9f1$D z$~2cb_5RaYUvYU->yds1nU90Tf6O*QcwP%EaxMREp%r{DKK`i4OnJY8e~FOFWTzLB zV!*jHY6-d8=2}Hh>T?g#M)%<>i+7+(0$SRQ56ZDv#L# zbN(@#`(i%|lZ-xDWLMdI+Dv)brcVXBPmfL&#&XoysJt!Rw|QfKG6<1R7wsRDX0%0M zgw)dl57B-)iAAOWxjwoREPON$RWTPo7%!L@Dbihbeq%Q&Y$F?{en(HQCDsZGS@eV-=Y`H8#|+PStmP80|aBBCGo5g-HNkQg|5p@ykHvM;+?{C;GJX=2wI4 zv=jXN;o(`!mXD6Y-S#8CrBO9dejn(o?aC)>V6t4hx2*EUzv%v3>@l0;Ci19&QGxJ} zM%qRZGEmsoUC5$}-DW~DEafCImn_-4Xk%(0 zc-3@FzV(ExZ>;)PaXDj555tIgXBP2!<7)De(HTq5-z@z&F z9v&yFb9jKJD~tC2!M0N6{WCW^_^Fd+=~RX+c8ihI)8!UfiMg_|5G69_5aP;?j05pgM zCkesUHNQm1W1wSPpm+0?{#Q5Fg-9PC1?T(aKfSuHd=5vfZr#>VJMh)=Nvh&C< zTLT5))0@vaRoy+j;CXT7PKdo_)IRLA$w~a+=*wt>K&yIS;9;SQ9Myp4ou{JUqZ-yrsCf&OMdsi z_@mDHXvt-wsktEZGK%KA*~_TLA`-QhvZh0|bzaud)%Y1avmrgQ2tGg>6=-enF9`{_ zaPEe1e)rJZ_*j+cPyWbHYITP`YAY15_lt}mO`zFgWx zzuya?yr9_?8v?Z7+Nfok94_VAPgwxwxB#UiUH)M*jn8UcHK!kkEr{+nW(nLSkZ4E_5TTzf#b!lJv>cbr9Xm`p!r@Yy$sz0HW z2H;)MK%v%(uTL)g0k;)6G&G>Lzy!xXR?<;T+bN+8qNh?oRv=6RR*Nj<%2weG*jSLp z7eqbxc1k8(qnG?}-qfIyKFC@0b7f7g*N0fxMOF(P8xN9PHBrx7I!6&Q{waSP5FBl; zU0SL{T!wd=1fUF3O{eehEM}}h^ZWN-Rmo*C30|dmTa;KqA{heTDr8E<)s}b`>b%c3E35Pdye!f5%D&XrH@h*#`$+U8rphna$f( z-KiyWu66ZA5_!D4r)>U_dfF#@Fa59~;Vk}edM4ZRP>$@pT3+}YOCnGB)?UNHM&;H? zGG>_`Jiu!pF+~xK4*rP{K!?nnex z6@Ou=ijmRE|HsyS#8kry_tK-^qY{(kp^%pRDL~qa^$u+=BskLajm7X7zEyl4cY0q{ z*WgrZGErFrJJ~ylVU&lm3Nnn~pRbTprhnSG-pu|AAeWAQSMlw~pP7i$=JshqJKMHL zCgS{bBCrRW-yL(A>&Sxp_?Sx02)u2y&Er0bL*C}r>8W!O9Y_O?+Qi;wu>xN<;P!ZL4q ziWTsbB`qhDfdqM)NqlVh=pk;ei4D@xqGVV?f>$}R(T0*EH)cUPkoavqZG95A9 z*cFzo*dDMHAYjAkt%g(HqK>iRMa*#Mo_c_&%#?I&yxY!%T*goY_ze{b1kIHZ(tnt$ z<%#s4$cQkv;CayQkpRAM-!xecxr%xIilo@W>WE<>bc$SM`)Li&&i8lT6y6j*oz9;*-hFeQFHA*IP|lY5RIE)ssN6ns zsgb|R`iU*){ewp}&D5;;#D#>c&eKDc@U7()3H!mSZjHAAMvYG)+(C6XRfm2mVEp1{tLr-|C2_$!IQY>dl=*-;ukf0kvR=xk_Z*| zJ1G#{tA&>ERg5qv4^(<$vjWSEkfo*W1xv^`5ody~jGzNZ-x$G3ozo=KzLE&qJHs{9 z&?HGp1F^Wq)R|z=x&h^K|nyHL%JI&0TmGu z2?gXH;QPM!eeWOlckg-j>}Q>|_FB8vXYIAmXxiH90vNzQ&uyh^LJ`k?6~X}VcJ;8b z_q=3501^PmuM|!7>u){&=okD#k-{(PlG>vA-}s&CA;Z@lf}q^ml!%s#X9|FuZj^>YGJ;9B;%!>)^>2Mg}i3ikux zo=WMk^m%Y8dJ6S^wb za*C|Uj%d9s_NMamEYA_K?QEwJnvHDF5%@qxPkzQ&rss$MrX0tH|bs5yE5uIQf{6-(jm46YD6z&IX2;& zfz)rC?C-<)mpriFe=7Vd_mKkk&2o;qHz$NKARfnxf~k}#nZfHhadJL?KfIVBE?z;U zJXA}EhP}iq^Q!1>3f@sp%q- zh4R0dP~j4u*0+wU-^%r@7E^L8sh=^vQvy0TyyO~D;HEO#BuL}XT;U@k-2+5Leh9&T zZrl%+QBwNx|0tvTFwmK={rSq75eDAQMro+U#&EMa)XHqY%50nkRRq!~^}ovX)WMkm zmvFj*BibsKzb`vfLk9nPga1K}qB})jBJ4vVi)t;4`UKbTPa(|%p>c9~&|P$InvLH? zO;RFtMa(9Jk&_7Iv^R3T0cp}0VAK$>a{M1<7WJRV0b#=|7QdnN-^htyzZ-vBIf=z6 ziR}tGa%Ma67K#dAcb+DB);Y$|jbsNQM*AIray0|Evt@;WT? z|Am}(ewZu>o?0&TgX=j;j)T#`OP=aKHvjp@cpPuPU zXn_lxausQb#7}7bKBRXi`Ps$FK%eZSd&WN*j%Dt5|3)Gh^_Vc_HrC^~47n(GaM9!e z5-@gBhr(osn6|TvHFQ2@7fon8WP75;Rp?7790%%)^sH3tMMlKH*I1o_`Zo*OD)ptb zgkUgm1AjFn1Vl!pfE)xM!DA{(&{2YKWqT0AOR}v;m`c%}17e%mp%cpG*`5<(@I;-< zSC0|pFWGt{V(^?W@Px#Gfj_P=5Gq)JI|e}9w=bbQDW^Rlr2R{693?sKWu`o-rb{l5 zn3mHhjmbzVG{oO}bm zIxl;fnfN%*A0tg>;}ow<8Gxox>IT!!x+rHea{1Yt2!mAl=@g_vD#{`SxjZX3j*_27 zn`xtvCMjks-bkZk_1QxdA~hV8t~H{}s9jb>bHR=*K&b(8p2}reByjOK-1cfz;|Sq# zJ+ny!3hZ}r=F*fwJrd;1r#P<|n9UyvYkQfEBalX32qS&u{IQwQ5lR~oV3LBolpZ^; zP({qo1gv?PnO$1eH#!PfoK4xBL9LyrO*ViNL`|XsR*q1%87Q+8`Pst&L~4L_J<{SN ze5L%fcR%*!%bl0I1Z|vyoi&6l2TSjH(Wu1}=VjZa_s{n?&UzCa7d!cP8a$WYS97%; z2nHezpOo4!mhSv%{?h!Occ+HRAT#Plq}L?mK5C47T2aAPiD?XJSVJF=V$Sn&Re)h-Fkrtw{v7i*1IK@k@#+Rg}4{pfX$O=piw90XkI%&K*u>Ojy!QsbXJM zukYx#qAIH*-k)AHjmd1|O^WrNWT6wC;0zwjc~`N{|$=MJxnDXcfM z(NJ+t`Y^N#Cw~gs3R>Q+uM<;WtY_``dXv(6qySB+%J~`;IP-5(TMvm{cAkCR`3yJ~ zeb7NcQ(_$DpeZ=KXGlyLG$sC-1JqFC?x9qPt^!TL%X>gm+&zY}%G{}FD{gqtoYhcM zPpS!SL4ATsEI3?~Sh2<#2cnX0!|Tpt>yM}}JEvCV6b3b%g^w1jD#hwk9UWe8QCg4I zZ_YT5w3f{{sK4G^uo{xwqP7`s!o48_PLNU-&fhTO;LN`T`=@jG3}}jbW&spjbv{iC z&SPc{T&r2oRC!OP<48wey0s?v49t2+vM1GXxam04Bmsmv^e%WHrEB4Uu*JWEZ5T%n zbr=p)Z+7w+V|Tiz4rgz6Xo5;lx+jUsKz68>ib@7ZDZ|l8Dk@dsIw~sV^&o5sE@A65 zhBk!dUj`j1P9UhmoonzwPFol`|C(i#Tz(QnrS~OgTnI7Uzy*22g;$K*br}#Fh!*q0%OHvg0w;9n%Ix1C&5oM*4k{RP?uRS!tU8tuti3Od} z*nzv3+WH&lrN)l@AjMHqLTz2iKVvMbTwYIY9VJ%*0eVz_I55MYUj7$CtH8L3I~(!Wb%@>D)t>s~Gzz1KfH zc*&)`ODVhrOu9L)vlTQb{f8p^H>LBhcEvg>|7d_}_)J&2msLU7rIkzSvfnF;vjn`U zxUGUm;zO()8$F}2I5tyX;L7pARGD$a*a@z1xzG{)jNOb81n{2hdMG>;R;mUML#K@J zM?@u4nh@RuFG^A*m#Gs*Fa`%-0tCRt!`A_%EQ1SV!|+Io+S}j0eFNThWNadozf}g*9`M5a0wYvD>7t8Vw-odO^MhFBC2=hCA#Z)=$@ciBJtMirq3w%Jp z8%9;IN2yfc`Pb0q{m)(ALz95-=XYlh)RZ!?5|T-gV>yf}G0X4z(uOjyiX1gO#owP9 z@qa0d^y=aXr$UMiXZUOEWt`GF%=5AqaC|Q?cf9LmeW%E$$g&s*!NVg}u=K_VmA;#j ztV<0Yd;XkvxpDaK>9MQ(+TMe+^WS_UCt{ATofaTJ0{zLhm`1E-4&CZs{dj~xN;!G$ zM#&L8975sH@Z}OU%ud{t>~FnA`lL^-5$zn5ZdFSs?4XyCoLN-m(BjuudMgvxxtj%m zVw20^WALmtCkp^ffZKlAhmuXrokw1cu5uz}swtfZ0Q8(vt6H3c_=k7P4h|m)aMEk! z71w28o$_VHi1mFg_gjG+fa3Q%9C_w=P03nmJfOxsaMsUjEq4jn*)fx9@Q^ecxl0eg zAV?s?`vb}e(8lzI&PjN?yl~PB@C!BC9`;t10yxnEPF+)<1T#lD08?UCj; zU>wkg+(T8-C#62H(xs`JHD4F|`>l}^*5bf*ZyibW$5Zju_j?kM^Y{&!0r4OPB>+K= zM{yU{)G*;Ao)XiW;Zb4nlyb0_9Vh?K(P_c@uyx#OCBRMQtf-Bt^ZbS(fp8bfCSw=@-G%Y zw|r9#kT+mF1|(FG^#Y@+hOA#4aZ+}xmPC$Mdw*g)thy;i06c%RTpujJ`-|ng>_#gm za?0O^{|5KgZO2Fy;BOX-{ll8->4eCs%jx7|4;a$vBKnkiz-X_n6&WUIML!>7t5Z%4 zVA0=$%aq!D2BabR!VtEl-TkVb{%*Y)-}8kN1FhMvx)w9Gq$aiJp6SYms(dR}5H&N1^c$AlM$JTT4r|nN2dU;Krp*`$;}(uR!x(*A+md1QkZh#%*JA1r zmUX#^ul@RrM$LJArObfW`TdD`Sx0f*YGZ_iQ^$`lZqEz9`i}iw=u5|R$nIoqTe$g5B=w0OP(-)IKZkbN=+Y#iG^ zPgbm%o?%o=d%nhc-`LP|X3-tMtHlmX<*f3*PxV6nDfrzI^x^z9V2YSmSpGti(ns2l z(|)5C*s>DL2i{}cz;q&z68`QO1q)70dWb&COQnS@F#~e$eWp|Ye z({b8QCCU;`3uZi~ChRQ@Q~evKW=-J-ZDas!lP@DCS<6@R%3478a~P!RP^P>9`PiowUjYU`q)jE(h!(%oJT7l=hDU~2Cgy(E*3ty0rc&T5C(egIXMIaCYP z^va77i^~bNV1gY*zf1c=XZko#;IA@Cjn8p?xE>^7e?X*e_ASrIrnhTrV~skgJ9htQ zp88lscEVQ(i+h`8_oG0S2I732WhTG|J81WZj7#&8z)E7S^K-|ly&H?D<@bShX?B3< z2*;nsoAvent(Z=zi{f`Bk)_;Pc<-Z9oUrk|-eKVa=kYZx<3n$z5AIY!4)V67%T~_! zl`+qYI+{2kZ0qKz0ZK-9oRDM) z5Q}n!sxFY=rF3c53BR=@$4r;+@^PGQE8A@usd{fU^Qhs%Z!N`co0*h2uVTO!w>ZG( zyxlBp?1rxI{B25ywg8^r@MTsioSgO)%*CD$VCtUM0dXjQfWD z4VP%-|8$3;n?Fp=ri300Rdboo;Q%5u?}D1i0395-MW>SN^TB&~v(UyixpZGIZC8p7 zCz&_9MTdc-uEuSD>mvJ}_{7Qu|8QUWsYCZElejx_mhjGKtBN|ps&9=% zFH0x5-unE->yy!7OTm#lj-;LDu-VLvcsNf>J?cajx1hd<{}`1wZe-@>SdSZjP?2aC zUa~J~&R&7&C^Ua15_*ep5E|nAI6GOpcdXwrev+^xc>^y-r>Y*Fmo^@wsQxAPGbPu< z>Xts|JoN^J?>i;J^9K`jKF=U59YhRUFhi#Sb;L83$S|MdLTs5x3S^>)@Y`ezNqQ1O zC50qt%9P^DZvdWXH~it&EEfBp!PK`6m1PV|)i10Yg}&bLZcIB6fSMg8$x$IUS_SK( zgkT?Gnt2};hXb>wBMa|%e!Lha}@+Y9%AP4dqLn$q2v|0WBU`L9@R~8I56Ig`a_PsnoiG(TjVpHm6u+bj?`n-mFKipfm8L z(dEzSEu{Ho;g9MN+1$(XzsE$OXxY&G1Vg$*f2gFJnc5$R?bF0Wk+J6@C9igOd~bEX zOT3Bx#C$9JvsCw3UnM4h2^2G%A&_5ca;)?;T0~an=+x3`jb|K``?SpRv~qFd!ppK8 zz8?xp>(-Dd1z~Z>1v-}J1#WKz;QhfqWzP3POMK(HuJ;Sq|O)}BZs)=1j;eM=h zBLDM6{JgHM+N6#T7j!L7gMZHFidJ7?aLB?J&m+}66drrZBl8VuY*yX#zHiUHiD-3e zIli-;DyT#51OS4od>0J@?V`oEwIsswv<(bMdZd7$8(gf-xaMW`yfh5uh2I}3D~-bF z>4s(Jmh2J;lLmtIts`Qf2ICUnS_a4@a-v<^UcalKMy`-luqkHkH?n2>X?=5;`9l|8 zutRL(AGhdv@0@+!!?Rh@K^0{+vAA~r_E}A3C$2uPrkqndrc!f$FuiX_^(lln0pG$sDV>F-#U2$)`-E_QoUtfH=GM5pih2Aft$;?vS49(CeBf^c z{oDC(a#QhY1y*lo7TGPSxQQ_!FU*x264RAyN!M)`w!2Wjy>>4=lDS$e91$NAPG}W9 z{1;u+O`G0|x7B@={I(Hlop8e;VV_@sY4)CW-|l@0Y=Z0O99QkRo{LVuT`ch z%3}&Mmep?Dhgc(nKUcFPsVjU%Fqe2r5;m|lS%iuyDBcY|+|1d09J8_&yI_yG_jP(4 ztFYnIL0%HK-=AOjvt3IXk3_nD5V#`3B?;+uvb`bJ!(!*m3Yc2sKytD{j`a@Bo76DST~||)~og|S}bN0;=EfeG>MY&6RIC)raiiY1u%%R@^rmTl>d{%?=E(qzFdyH z(0Npg+HP0g4T z8tyKKUm&Z-cf^5@D3(&7b{t-THe4lq)DGT2D6@vV~@`l1kK7=VO!qk~!XpsR8?x>I32d0G|g z)u}r0<^^XJQOyC7FV}s_AFIZp_a=_%RNBLQ28DRZC+Ou*979Msjuq~X{|;CPer+hQ zxoggbdG&Du%iQ39f1J4d8=7y>y$oS%!cdvCqCW1kFF zP^~&d63qJ=aa%6th1eEFkd0rsiThpppz1Se4ER)kBA|r1TM7lZ6wYF|-t3wu@0v~g zJgwlXZyAm4dj*%<^GuU53?;SVdcmfWwaoTFEaXn-F*+NsYxV)V$~Q}wqG!gDl2g5< zBW3_y!zb%#-tK37b3skV7Y{AHI)(|Hi;!gByoO!IJtKHLzI?H+>YwcCj+imKKZ9Gz z!AvI-5x>QeTVK_C?sy&~pt^^iyaOqO422%zwGVumUo)D31S%}uD=B-uK{nx9uuVpm z1#xcn$(40wuHdF=O%Nh!e}7*SkkP=D!~uLeO#N&Ie@D`n%2r`W30qM7XqzsW#tK@w zf3|=B0l~uWd?Ahf2%p#NdfM6Nd?KRcqA~`?iWadirj|6D+=Xa<%71JYmKcv=jqv&@ z&(RrI@8k`|-{R%3*y}pu`6$ay6ue_BlW38=n6<8Ti4xh292Jzh}stdLmzw>{|sOB}IDUp3lTi zi|w-lmx(RQHioSXep+c`2RX=xa)_y*4d1ad(n;7z;VlitytQ^GzU&rnLQizINY9QSQ2YSwFsjp+%aC@{9W3DN{Wd@8Ar?>= z+W7LXk_iui(Rs(iINUQlMd6oP2?2-07{e$W;AHS!qv|09xP1#=_tBZ5yy^DO4}Zb0 zXxMk+ml_-X1}2vrV-4xT2#03GBb)o z0QA<<0kH>Rkb|Ub&$FYI?vCdjFMTj>WVo%IrKiH^pyxW|9i}fj&v#&2ld41j=K95v zd4ys)GIybJc6Q!zPFB3BHkg(YBu?1b!=msV8af`0ep( zf4*SNnKqamKR6-TRfP$VkB}-DQDEPLywn&YQNZMbwKKItvea|vN!naKRJ+rnLtuvu z6u&XOYN*ZtDz0y*Zupg$)OZiE^KWNqAvhS*4Xh~x3#libn^Hz0)XUEBu&~K%YZ!j# zGX>$~O9Q6B6sMUgY2cw7C#zHLPE_qovveM2Hu1hEHWohl(@q$S@!Vz|BS={|2=M>D z(%OhqL0yFP&OAgRYW}(3z%g)!r~5cc^Na4v-Dx`!fNzm58c-tN;qKZ?e?}O+Bbm$ZDdV@9oc?h!!$_ z*}35=d>{O4%Lx3S7T_(x!`J=PSX4;VQ9v4adE|$3+cWu?q~`qP@P^eNT-3lSkDgba zzas#Mdpor%+wqK5Rv12STGw^fT6PY6b$9Q9s{_A=nqIUunNlSEM2FeaEVCJ(=GOQA zmTtF(mj2?09-jo#=a08i(R^?vx@!p?@Z)}BL71G+Q^l}#(>CW;RpX%IqnkJGYSZ(I zjFf%lCTVrCs|m7qFFeDw!hqV=%+rk*80rUEZ@?5ufI;3{RbTqs640$95du2QzM0sjlQUAkug literal 0 HcmV?d00001 diff --git a/Resources/Audio/_CP14/Items/coins_fall.ogg b/Resources/Audio/_CP14/Items/coins_fall.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bae9c26ce23c01ba4c0e6798c0b330710fd82c05 GIT binary patch literal 13758 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 D3s5+f literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Interface/Misc/coins.rsi/g.png b/Resources/Textures/_CP14/Interface/Misc/coins.rsi/g.png new file mode 100644 index 0000000000000000000000000000000000000000..f39c4d7fcadb777c48ba949aead2b09f6fb0c95e GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|+C5zyLnNjq zCnzvTB=-E@fBjE-#rKBBhtFf#+;+a~(OC8Gf86K)f5RsJxBnLXzkYw{lmGwSXZ}wt z(%}Jt_i_dWMJtUrXumczxRaWYkPzOMot6Zo6Mj^R>m69Praj3@n3&~(ju*rQiiJt8OG?u~B)z4*}Q$iB}nqw}e literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/wooden.png b/Resources/Textures/_CP14/Structures/Furniture/pallets.rsi/wooden.png new file mode 100644 index 0000000000000000000000000000000000000000..58f1d53023a941edc8a8a4a9bec7b172f048f36d GIT binary patch literal 605 zcmV-j0;2tiP)Px%7fD1xR9J=WmoaYJKoCVA0U8P@QIHA3MQk^Ar9v)z0o6W)PM1TZ_61TTg_|Ue zkpM9WNgyRUf(S4LGxBh`ByCBFT=+NA?#|zt*`3cJ9TaY^hdDs#y8uK<#>Y>04!~qQ z%DbIne!0p3_;CBh*@Xw->HtFDMT`UA17f{Q;CoDy6cgL>0G!Eqlv`K+1EM5*I)QG- z{TqEdj{CjJ+$>(y+UxA)8oC{~2tba`G}H)uujEvm)!A#F{*^su@q%fR68dg&0%qoB zhO>B4>r`iCJ3(9E;&Zu*4_^b$@a!xH81&v*jpmErG_CInM-L|BQGOowH{<&#-e`6* z9_3dT@A>xQfx!1FYuoVPHOSCbJhmbf?5hY1#DxmXP0g{E;c>rLQbd!C1K%q-HDw6k zwq;<8UI$a3T{WR;l2#u?VzgXkELX982Lt!f^X!@+f&5b$3b%=0k)cRNqSSJd`@TFq z;q&*OR;j&&2jJXX4|D0`hky%3LFnQTG!^AbJEDdzMpv>w5BnvVm;~D}h^rXbIC3f%{*ozG7rm4Tr%7s+T2sf{h6k^q8_MAA zrBvhXrBtI$hHV|MZM`BxcskBHsX?{lZNmfO<5a`E>nO>PkIv%%et4w-zW#b-;2jYq r8S`{qGMuMt=INS&ceEMr$^-ZV>9p|SPx(U`a$lRCt{2n$K$+R}ja)s|uBXK-y&~#PVv1jr+r{ONyxuiLf9CLy}VtIk-lL z(0ecalT`l+Z6F7Ogq%a5gktO%yHZ%MR~%C?>)WMuGY%I&HJ3jv+vi; z&YK;JF}6xO6DauW)eA$Vzo~@TnFavMHkA|pFHYDh?MzfQ_PTwf03e^s3J*5dH(=Rj zsMl^1Wc=p(hM*^#Q@lcU#7%dC>dnh`rsPTd!OGV%I6BSfvr1{G5d7z{^Db_y;4OnI^1XrkU|BA?4Lnb-5s8cC4n zUR|E!>hfHW^SLYz4FiY9$3RIblAhea0I6icwP2lwYtZ`o|pOSK1PBs#0ATXF7$WEv?ny74-*|!~tABsSb$lhJOox2uz zclFjNy6%L(n)B?txxRsVqZw*A=~J?T$YgG@N%clkC@Ft8|G{tF3$`h3%*zxpi?{-` zR@^H<#>;l7Y)#1zWJeIR;9xky>+=lL^96}qoDfM$*(6^9a+F+)5Gwo90MLDZ8T(+C zU1CMYU^rrT)v`?{M^#@*A;T=&M7yPy=gl|irR6o{4lqTsE>~jjHG<9BCXC8h*!1{1xy!K_u~on!Hcc zdBX5J9(vtAjN40hCgsY5xepk{>6jyyus1g^C zDly8LRW-g@Kfu!R+I7x|X8i#6SIanka~5mQxMw6-9WZMm|2K`DwPBo%=V8`oENX1j zJmn7}agCG5@kIy8N$x*EbE!}ZGhAi#EGO|8x0mjG(%<`%RDnF7`g|IVMx)Vu#u&Ok z0J=Xw_Xm(d_Xj}t2TTpt{QC9@=>7oRAE5gKbbmmU%%l4QbbmlHbbo*X z-5&tm9{@o22k8EQMWFiwp!)-Ke}L`}&}cLojpp;^UuM`e_*J?C&;S4c07*qoM6N<$ Ef=2;4-2eap literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Specific/Economy/cash_device.rsi/meta.json b/Resources/Textures/_CP14/Structures/Specific/Economy/cash_device.rsi/meta.json new file mode 100644 index 0000000000..5a6ecdbd18 --- /dev/null +++ b/Resources/Textures/_CP14/Structures/Specific/Economy/cash_device.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "license": "CLA", + "copyright": "Created by Jaraten and TheShuEd (Github) for CrystallPunk 14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon-open.png b/Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon-open.png new file mode 100644 index 0000000000000000000000000000000000000000..3d55bf7cf775a87d11a8d7dd13c9604ba50ce0de GIT binary patch literal 2044 zcmah~c{J1u8~%-DMuV)wEj!mPG`ASrU=YHPFl1jEEi<7{5|d?`ls)8H%65fpGbV&A zWyv~BXf$eU*~(UyTQQbz?jPTG&iB`M&ilU4``2@xbKdj3PofjrS`c~?3IKqht&OEK z2hBMBh7Zh{4U?Du0nopktx*7ZMEWZLKwjEfn!7|kT`!g!ECjU>cdvh-HaEv54j6K{vsFgY9PB4HLm5K6;x9HH z9Xlbtw)vA^UOa#Jl@8tX`yeD`qPLY64(g#{_O)dt{juJ%(sO;pdnR5jTPFa&urP(2 zWNLlFR4;Y|8K>zNv5{4X#d6eSFDkoKb&Ht0@<5`mH0ArK#j%0x@132p$il+3r~E}T zjNC^x4y_E!R>pfWk4Es5k^4HNNo?Qztm^_Dhy` zw@QkpSxn4{#ZD2eBdX{wSrNgkzhur#3j4OP-t#hUicK2sP1V*o#pOTSg{4gp7WK$~ z_*5PbY@$}06up%t30lcZ6V_=4z?{Hp+wD7{JgEg|cU}cNl*qm>OnxX)O5m}q&&fFp z7&AeiN5-+r$1o|4F5KW3pD2K|h5v*~HLUw`an-hpYHox2&@5DV_+!uDR_0cujwV>@ z`3;Kv)m{gQ%m(LBRki$Eq8>HB!EK*t!prl{;@7ExI8&mL`RT`J4;sBs+dr3WYWtz2 zh;|ZB87?GviRa#LuSxyojng@TW%qAz?o;fAb+FUv#+ss*=OeX{m!wSJhq@4iat%$# zO^gnGdV*Ys)P;SoEh@X+s%2qc!)7TAHWQCKZs~K5X*W8!<-DY$QQlE8LJwbrJu9kX zeBCUCEZvUp?)jZiu?>%?aWO0$Xm92^cYS{9{HoAisqs&q3SQP~aWx-7$!_>+al?Uevx z9=qTZI+%E$`ws9}*CQXb;;Cz&-?yp;%;81J^wz3&Nhr|OF94kHL-&AJM8DO?D1MML zDlu8MQWIEcm75bRZQR^g-u4Y=mk4;zSZf@&xu*|B&<^-Up>1JAvktZhkGb&wD`^?< z*uvI!i8cUuy&^QS*%Z@l>a&b8K2pm*4vrLZ9b&rAq)j0l7v#)2o~d16hVWiNM#~-y zzjJED(ZIuF4(~CKKVqgD)Jai;1GC-6NoPOVzz0S{4_b%gc>NQyo;ZeqaKT zSfXRHt;9Ti$xH01jGl^JgG}`2Z{WMIY48)Or=)x2Mcd4>NAE*l!y;XUJ0=bp>5&2*R-!vZ#7>E2I+p_ z67e4zxq@#SI@}e7!57L-+rA{?EksW5>=2F#1nTga=uTu53k|P(MQ;2o&P*bG^f!`|JWEQ&6bXYDxB|RY*Waf>4Ey zyKgWIT78l&!Bwxt$X?McG7d}8ORvik+X)-i5lSmIMszi;di7l?1AGfga&KBoup(&Z zRKIxQ&GIn2Z(fy?QqV>yB!BfhhaWwV6BQ+8oU~H|%(#Iu(|Zo1E+O~I-~FM3(;9Wh z_AMz!WN{uDh~ydAflEKwrOyDLqpYPpQgeb zx5^?ls&52lT0Kr2a0XaSEmkG$JkX0G-8?0K_F_ zXgGVA{}$1zJYW`kerzO2I|&jl+27Hr+LJo^?KL|=u1Q4pT@6=NvR&EyptW*HR~$Az zHUt?>hD{r`$2b?p7QxRXzm>aXo;MJcO6k5iDk>+(Z6KW0_vFk{05jh6%<{$WN*ny; z8N6mUeU4(54(KN_9@Bd!oqyqdVlUR3`PwM)Qw*Q%xGiTb>xVrKQuuF7{?DQ)bqEQO WeQsUqN)X`0Ibdsrwj`tci2nxQ=)|-D literal 0 HcmV?d00001 diff --git a/Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon.png b/Resources/Textures/_CP14/Structures/Storage/Dressers/iron_cabinet.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0dbb232461f0df919b4651b6cc6893b47675b8 GIT binary patch literal 1831 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 CrystallPunk migration zone end