Clean up store system (#28463)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Store;
|
||||
using JetBrains.Annotations;
|
||||
using System.Linq;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Store.Ui;
|
||||
@@ -13,9 +14,6 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
|
||||
[ViewVariables]
|
||||
private StoreMenu? _menu;
|
||||
|
||||
[ViewVariables]
|
||||
private string _windowName = Loc.GetString("store-ui-default-title");
|
||||
|
||||
[ViewVariables]
|
||||
private string _search = string.Empty;
|
||||
|
||||
@@ -28,7 +26,9 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
_menu = new StoreMenu(_windowName);
|
||||
_menu = new StoreMenu();
|
||||
if (EntMan.TryGetComponent<StoreComponent>(Owner, out var store))
|
||||
_menu.Title = Loc.GetString(store.Name);
|
||||
|
||||
_menu.OpenCentered();
|
||||
_menu.OnClose += Close;
|
||||
@@ -64,25 +64,15 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_menu == null)
|
||||
return;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case StoreUpdateState msg:
|
||||
_listings = msg.Listings;
|
||||
|
||||
_menu.UpdateBalance(msg.Balance);
|
||||
_menu?.UpdateBalance(msg.Balance);
|
||||
UpdateListingsWithSearchFilter();
|
||||
_menu.SetFooterVisibility(msg.ShowFooter);
|
||||
_menu.UpdateRefund(msg.AllowRefund);
|
||||
break;
|
||||
case StoreInitializeState msg:
|
||||
_windowName = msg.Name;
|
||||
if (_menu != null && _menu.Window != null)
|
||||
{
|
||||
_menu.Window.Title = msg.Name;
|
||||
}
|
||||
_menu?.SetFooterVisibility(msg.ShowFooter);
|
||||
_menu?.UpdateRefund(msg.AllowRefund);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public sealed partial class StoreMenu : DefaultWindow
|
||||
|
||||
private List<ListingData> _cachedListings = new();
|
||||
|
||||
public StoreMenu(string name)
|
||||
public StoreMenu()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
@@ -40,9 +40,6 @@ public sealed partial class StoreMenu : DefaultWindow
|
||||
WithdrawButton.OnButtonDown += OnWithdrawButtonDown;
|
||||
RefundButton.OnButtonDown += OnRefundButtonDown;
|
||||
SearchBar.OnTextChanged += _ => SearchTextUpdated?.Invoke(this, SearchBar.Text);
|
||||
|
||||
if (Window != null)
|
||||
Window.Title = name;
|
||||
}
|
||||
|
||||
public void UpdateBalance(Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> balance)
|
||||
|
||||
@@ -25,6 +25,7 @@ using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using Content.Server.GameTicking.Components;
|
||||
using Content.Shared.Store.Components;
|
||||
|
||||
namespace Content.Server.GameTicking.Rules;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ using Robust.Shared.Random;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Movement.Pulling.Components;
|
||||
using Content.Shared.Movement.Pulling.Systems;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Server.PDA.Ringer;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Server.Traitor.Uplink;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.Chat;
|
||||
@@ -15,6 +16,7 @@ using Content.Shared.Light;
|
||||
using Content.Shared.Light.Components;
|
||||
using Content.Shared.Light.EntitySystems;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
@@ -152,7 +154,7 @@ namespace Content.Server.PDA
|
||||
|
||||
var address = GetDeviceNetAddress(uid);
|
||||
var hasInstrument = HasComp<InstrumentComponent>(uid);
|
||||
var showUplink = HasComp<StoreComponent>(uid) && IsUnlocked(uid);
|
||||
var showUplink = HasComp<UplinkComponent>(uid) && IsUnlocked(uid);
|
||||
|
||||
UpdateStationName(uid, pda);
|
||||
UpdateAlertLevel(uid, pda);
|
||||
@@ -237,8 +239,8 @@ namespace Content.Server.PDA
|
||||
return;
|
||||
|
||||
// check if its locked again to prevent malicious clients opening locked uplinks
|
||||
if (TryComp<StoreComponent>(uid, out var store) && IsUnlocked(uid))
|
||||
_store.ToggleUi(msg.Actor, uid, store);
|
||||
if (HasComp<UplinkComponent>(uid) && IsUnlocked(uid))
|
||||
_store.ToggleUi(msg.Actor, uid);
|
||||
}
|
||||
|
||||
private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaLockUplinkMessage msg)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Shared.PDA;
|
||||
using Content.Shared.PDA.Ringer;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
@@ -17,6 +17,7 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Revenant;
|
||||
using Content.Shared.Revenant.Components;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Store.Components;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Store.Conditions;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Store.Systems;
|
||||
@@ -58,7 +60,7 @@ public sealed partial class StoreSystem
|
||||
if (args.Length == 2 && NetEntity.TryParse(args[0], out var uidNet) && TryGetEntity(uidNet, out var uid))
|
||||
{
|
||||
if (TryComp<StoreComponent>(uid, out var store))
|
||||
return CompletionResult.FromHintOptions(store.CurrencyWhitelist, "<currency prototype>");
|
||||
return CompletionResult.FromHintOptions(store.CurrencyWhitelist.Select(p => p.ToString()), "<currency prototype>");
|
||||
}
|
||||
|
||||
return CompletionResult.Empty;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Store.Systems;
|
||||
|
||||
@@ -80,7 +81,11 @@ public sealed partial class StoreSystem
|
||||
/// <param name="categories">What categories to filter by.</param>
|
||||
/// <param name="storeEntity">The physial entity of the store. Can be null.</param>
|
||||
/// <returns>The available listings.</returns>
|
||||
public IEnumerable<ListingData> GetAvailableListings(EntityUid buyer, HashSet<ListingData>? listings, HashSet<string> categories, EntityUid? storeEntity = null)
|
||||
public IEnumerable<ListingData> GetAvailableListings(
|
||||
EntityUid buyer,
|
||||
HashSet<ListingData>? listings,
|
||||
HashSet<ProtoId<StoreCategoryPrototype>> categories,
|
||||
EntityUid? storeEntity = null)
|
||||
{
|
||||
listings ??= GetAllListings();
|
||||
|
||||
@@ -117,7 +122,7 @@ public sealed partial class StoreSystem
|
||||
/// <param name="listing">The listing itself.</param>
|
||||
/// <param name="categories">The categories to check through.</param>
|
||||
/// <returns>If the listing was present in one of the categories.</returns>
|
||||
public bool ListingHasCategory(ListingData listing, HashSet<string> categories)
|
||||
public bool ListingHasCategory(ListingData listing, HashSet<ProtoId<StoreCategoryPrototype>> categories)
|
||||
{
|
||||
foreach (var cat in categories)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server.Store.Systems;
|
||||
|
||||
@@ -10,6 +10,7 @@ using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Content.Shared.UserInterface;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
@@ -82,16 +83,11 @@ public sealed partial class StoreSystem
|
||||
/// <param name="user">The person who if opening the store ui. Listings are filtered based on this.</param>
|
||||
/// <param name="store">The store entity itself</param>
|
||||
/// <param name="component">The store component being refreshed.</param>
|
||||
/// <param name="ui"></param>
|
||||
public void UpdateUserInterface(EntityUid? user, EntityUid store, StoreComponent? component = null)
|
||||
{
|
||||
if (!Resolve(store, ref component))
|
||||
return;
|
||||
|
||||
// TODO: Why is the state not being set unless this?
|
||||
if (!_ui.HasUi(store, StoreUiKey.Key))
|
||||
return;
|
||||
|
||||
//this is the person who will be passed into logic for all listing filtering.
|
||||
if (user != null) //if we have no "buyer" for this update, then don't update the listings
|
||||
{
|
||||
@@ -259,7 +255,8 @@ public sealed partial class StoreSystem
|
||||
}
|
||||
|
||||
//log dat shit.
|
||||
_admin.Add(LogType.StorePurchase, LogImpact.Low,
|
||||
_admin.Add(LogType.StorePurchase,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(buyer):player} purchased listing \"{ListingLocalisationHelpers.GetLocalisedNameOrEntityName(listing, _prototypeManager)}\" from {ToPrettyString(uid)}");
|
||||
|
||||
listing.PurchaseAmount++; //track how many times something has been purchased
|
||||
|
||||
@@ -5,11 +5,10 @@ using Content.Shared.Implants.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Store;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Store.Systems;
|
||||
@@ -44,7 +43,6 @@ public sealed partial class StoreSystem : EntitySystem
|
||||
private void OnMapInit(EntityUid uid, StoreComponent component, MapInitEvent args)
|
||||
{
|
||||
RefreshAllListings(component);
|
||||
InitializeFromPreset(component.Preset, uid, component);
|
||||
component.StartingMap = Transform(uid).MapUid;
|
||||
}
|
||||
|
||||
@@ -54,7 +52,6 @@ public sealed partial class StoreSystem : EntitySystem
|
||||
if (MetaData(uid).EntityLifeStage == EntityLifeStage.MapInitialized)
|
||||
{
|
||||
RefreshAllListings(component);
|
||||
InitializeFromPreset(component.Preset, uid, component);
|
||||
}
|
||||
|
||||
var ev = new StoreAddedEvent();
|
||||
@@ -167,43 +164,6 @@ public sealed partial class StoreSystem : EntitySystem
|
||||
UpdateUserInterface(null, uid, store);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a store based on a preset ID
|
||||
/// </summary>
|
||||
/// <param name="preset">The ID of a store preset prototype</param>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="component">The store being initialized</param>
|
||||
public void InitializeFromPreset(string? preset, EntityUid uid, StoreComponent component)
|
||||
{
|
||||
if (preset == null)
|
||||
return;
|
||||
|
||||
if (!_proto.TryIndex<StorePresetPrototype>(preset, out var proto))
|
||||
return;
|
||||
|
||||
InitializeFromPreset(proto, uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a store based on a given preset
|
||||
/// </summary>
|
||||
/// <param name="preset">The StorePresetPrototype</param>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="component">The store being initialized</param>
|
||||
public void InitializeFromPreset(StorePresetPrototype preset, EntityUid uid, StoreComponent component)
|
||||
{
|
||||
component.Preset = preset.ID;
|
||||
component.CurrencyWhitelist.UnionWith(preset.CurrencyWhitelist);
|
||||
component.Categories.UnionWith(preset.Categories);
|
||||
if (component.Balance == new Dictionary<string, FixedPoint2>() && preset.InitialBalance != null) //if we don't have a value stored, use the preset
|
||||
TryAddCurrency(preset.InitialBalance, uid, component);
|
||||
|
||||
if (_ui.HasUi(uid, StoreUiKey.Key))
|
||||
{
|
||||
_ui.SetUiState(uid, StoreUiKey.Key, new StoreInitializeState(preset.StoreName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CurrencyInsertAttemptEvent : CancellableEntityEventArgs
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
using Content.Shared.Store;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.SurplusBundle;
|
||||
|
||||
/// <summary>
|
||||
@@ -12,14 +9,6 @@ public sealed partial class SurplusBundleComponent : Component
|
||||
/// <summary>
|
||||
/// Total price of all content inside bundle.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
[DataField("totalPrice")]
|
||||
[DataField]
|
||||
public int TotalPrice = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The preset that will be used to get all the listings.
|
||||
/// Currently just defaults to the basic uplink.
|
||||
/// </summary>
|
||||
[DataField("storePreset", customTypeSerializer: typeof(PrototypeIdSerializer<StorePresetPrototype>))]
|
||||
public string StorePreset = "StorePresetUplink";
|
||||
}
|
||||
|
||||
@@ -3,76 +3,67 @@ using Content.Server.Storage.EntitySystems;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Store;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink.SurplusBundle;
|
||||
|
||||
public sealed class SurplusBundleSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
|
||||
private ListingData[] _listings = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SurplusBundleComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
SubscribeLocalEvent<SurplusBundleComponent, ComponentInit>(OnInit);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, SurplusBundleComponent component, ComponentInit args)
|
||||
{
|
||||
var storePreset = _prototypeManager.Index<StorePresetPrototype>(component.StorePreset);
|
||||
|
||||
_listings = _store.GetAvailableListings(uid, null, storePreset.Categories).ToArray();
|
||||
|
||||
Array.Sort(_listings, (a, b) => (int) (b.Cost.Values.Sum() - a.Cost.Values.Sum())); //this might get weird with multicurrency but don't think about it
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, SurplusBundleComponent component, MapInitEvent args)
|
||||
{
|
||||
FillStorage(uid, component);
|
||||
}
|
||||
|
||||
private void FillStorage(EntityUid uid, SurplusBundleComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
if (!TryComp<StoreComponent>(uid, out var store))
|
||||
return;
|
||||
|
||||
var cords = Transform(uid).Coordinates;
|
||||
FillStorage((uid, component, store));
|
||||
}
|
||||
|
||||
var content = GetRandomContent(component.TotalPrice);
|
||||
private void FillStorage(Entity<SurplusBundleComponent, StoreComponent> ent)
|
||||
{
|
||||
var cords = Transform(ent).Coordinates;
|
||||
var content = GetRandomContent(ent);
|
||||
foreach (var item in content)
|
||||
{
|
||||
var ent = EntityManager.SpawnEntity(item.ProductEntity, cords);
|
||||
_entityStorage.Insert(ent, uid);
|
||||
var dode = Spawn(item.ProductEntity, cords);
|
||||
_entityStorage.Insert(dode, ent);
|
||||
}
|
||||
}
|
||||
|
||||
// wow, is this leetcode reference?
|
||||
private List<ListingData> GetRandomContent(FixedPoint2 targetCost)
|
||||
private List<ListingData> GetRandomContent(Entity<SurplusBundleComponent, StoreComponent> ent)
|
||||
{
|
||||
var ret = new List<ListingData>();
|
||||
if (_listings.Length == 0)
|
||||
|
||||
var listings = _store.GetAvailableListings(ent, null, ent.Comp2.Categories)
|
||||
.OrderBy(p => p.Cost.Values.Sum())
|
||||
.ToList();
|
||||
|
||||
if (listings.Count == 0)
|
||||
return ret;
|
||||
|
||||
var totalCost = FixedPoint2.Zero;
|
||||
var index = 0;
|
||||
while (totalCost < targetCost)
|
||||
while (totalCost < ent.Comp1.TotalPrice)
|
||||
{
|
||||
// All data is sorted in price descending order
|
||||
// Find new item with the lowest acceptable price
|
||||
// All expansive items will be before index, all acceptable after
|
||||
var remainingBudget = targetCost - totalCost;
|
||||
while (_listings[index].Cost.Values.Sum() > remainingBudget)
|
||||
var remainingBudget = ent.Comp1.TotalPrice - totalCost;
|
||||
while (listings[index].Cost.Values.Sum() > remainingBudget)
|
||||
{
|
||||
index++;
|
||||
if (index >= _listings.Length)
|
||||
if (index >= listings.Count)
|
||||
{
|
||||
// Looks like no cheap items left
|
||||
// It shouldn't be case for ss14 content
|
||||
@@ -82,8 +73,8 @@ public sealed class SurplusBundleSystem : EntitySystem
|
||||
}
|
||||
|
||||
// Select random listing and add into crate
|
||||
var randomIndex = _random.Next(index, _listings.Length);
|
||||
var randomItem = _listings[randomIndex];
|
||||
var randomIndex = _random.Next(index, listings.Count);
|
||||
var randomItem = listings[randomIndex];
|
||||
ret.Add(randomItem);
|
||||
totalCost += randomItem.Cost.Values.Sum();
|
||||
}
|
||||
|
||||
7
Content.Server/Traitor/Uplink/UplinkComponent.cs
Normal file
7
Content.Server/Traitor/Uplink/UplinkComponent.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Content.Server.Traitor.Uplink;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for identifying something as a hidden uplink and showing the UI.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class UplinkComponent : Component;
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.PDA;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
|
||||
namespace Content.Server.Traitor.Uplink
|
||||
{
|
||||
@@ -17,18 +18,6 @@ namespace Content.Server.Traitor.Uplink
|
||||
[ValidatePrototypeId<CurrencyPrototype>]
|
||||
public const string TelecrystalCurrencyPrototype = "Telecrystal";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of TC on an "uplink"
|
||||
/// Mostly just here for legacy systems based on uplink.
|
||||
/// </summary>
|
||||
/// <param name="component"></param>
|
||||
/// <returns>the amount of TC</returns>
|
||||
public int GetTCBalance(StoreComponent component)
|
||||
{
|
||||
FixedPoint2? tcBalance = component.Balance.GetValueOrDefault(TelecrystalCurrencyPrototype);
|
||||
return tcBalance?.Int() ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an uplink to the target
|
||||
/// </summary>
|
||||
@@ -37,7 +26,7 @@ namespace Content.Server.Traitor.Uplink
|
||||
/// <param name="uplinkPresetId">The id of the storepreset</param>
|
||||
/// <param name="uplinkEntity">The entity that will actually have the uplink functionality. Defaults to the PDA if null.</param>
|
||||
/// <returns>Whether or not the uplink was added successfully</returns>
|
||||
public bool AddUplink(EntityUid user, FixedPoint2? balance, string uplinkPresetId = "StorePresetUplink", EntityUid? uplinkEntity = null)
|
||||
public bool AddUplink(EntityUid user, FixedPoint2? balance, EntityUid? uplinkEntity = null)
|
||||
{
|
||||
// Try to find target item
|
||||
if (uplinkEntity == null)
|
||||
@@ -47,11 +36,10 @@ namespace Content.Server.Traitor.Uplink
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureComp<UplinkComponent>(uplinkEntity.Value);
|
||||
var store = EnsureComp<StoreComponent>(uplinkEntity.Value);
|
||||
_store.InitializeFromPreset(uplinkPresetId, uplinkEntity.Value, store);
|
||||
store.AccountOwner = user;
|
||||
store.Balance.Clear();
|
||||
|
||||
if (balance != null)
|
||||
{
|
||||
store.Balance.Clear();
|
||||
|
||||
@@ -1,46 +1,41 @@
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Store;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||
|
||||
namespace Content.Server.Store.Components;
|
||||
namespace Content.Shared.Store.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This component manages a store which players can use to purchase different listings
|
||||
/// through the ui. The currency, listings, and categories are defined in yaml.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class StoreComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The default preset for the store. Is overriden by default values specified on the component.
|
||||
/// </summary>
|
||||
[DataField("preset", customTypeSerializer: typeof(PrototypeIdSerializer<StorePresetPrototype>))]
|
||||
public string? Preset;
|
||||
[DataField]
|
||||
public LocId Name = "store-ui-default-title";
|
||||
|
||||
/// <summary>
|
||||
/// All the listing categories that are available on this store.
|
||||
/// The available listings are partially based on the categories.
|
||||
/// </summary>
|
||||
[DataField("categories", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<StoreCategoryPrototype>))]
|
||||
public HashSet<string> Categories = new();
|
||||
[DataField]
|
||||
public HashSet<ProtoId<StoreCategoryPrototype>> Categories = new();
|
||||
|
||||
/// <summary>
|
||||
/// The total amount of currency that can be used in the store.
|
||||
/// The string represents the ID of te currency prototype, where the
|
||||
/// float is that amount.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("balance", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<FixedPoint2, CurrencyPrototype>))]
|
||||
public Dictionary<string, FixedPoint2> Balance = new();
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> Balance = new();
|
||||
|
||||
/// <summary>
|
||||
/// The list of currencies that can be inserted into this store.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly), DataField("currencyWhitelist", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<CurrencyPrototype>))]
|
||||
public HashSet<string> CurrencyWhitelist = new();
|
||||
[DataField]
|
||||
public HashSet<ProtoId<CurrencyPrototype>> CurrencyWhitelist = new();
|
||||
|
||||
/// <summary>
|
||||
/// The person who "owns" the store/account. Used if you want the listings to be fixed
|
||||
@@ -52,6 +47,7 @@ public sealed partial class StoreComponent : Component
|
||||
/// <summary>
|
||||
/// All listings, including those that aren't available to the buyer
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public HashSet<ListingData> Listings = new();
|
||||
|
||||
/// <summary>
|
||||
@@ -70,7 +66,7 @@ public sealed partial class StoreComponent : Component
|
||||
/// The total balance spent in this store. Used for refunds.
|
||||
/// </summary>
|
||||
[ViewVariables, DataField]
|
||||
public Dictionary<string, FixedPoint2> BalanceSpent = new();
|
||||
public Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> BalanceSpent = new();
|
||||
|
||||
/// <summary>
|
||||
/// Controls if the store allows refunds
|
||||
@@ -95,7 +91,7 @@ public sealed partial class StoreComponent : Component
|
||||
/// <summary>
|
||||
/// The sound played to the buyer when a purchase is succesfully made.
|
||||
/// </summary>
|
||||
[DataField("buySuccessSound")]
|
||||
[DataField]
|
||||
public SoundSpecifier BuySuccessSound = new SoundPathSpecifier("/Audio/Effects/kaching.ogg");
|
||||
#endregion
|
||||
}
|
||||
@@ -30,20 +30,6 @@ public sealed class StoreUpdateState : BoundUserInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initializes miscellaneous data about the store.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class StoreInitializeState : BoundUserInterfaceState
|
||||
{
|
||||
public readonly string Name;
|
||||
|
||||
public StoreInitializeState(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class StoreRequestUpdateInterfaceMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
|
||||
@@ -8,3 +8,6 @@ store-ui-traitor-warning = Operatives must lock their uplinks after use to avoid
|
||||
store-withdraw-button-ui = Withdraw {$currency}
|
||||
store-ui-button-out-of-stock = {""} (Out of Stock)
|
||||
store-not-account-owner = This {$store} is not bound to you!
|
||||
|
||||
store-preset-name-uplink = Uplink
|
||||
store-preset-name-spellbook = Spellbook
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
- type: entity
|
||||
id: CrateSyndicateSurplusBundle
|
||||
parent: CrateSyndicate
|
||||
parent: [ CrateSyndicate, StorePresetUplink ]
|
||||
name: Syndicate surplus crate
|
||||
description: Contains 50 telecrystals worth of completely random Syndicate items. It can be useless junk or really good.
|
||||
components:
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
- type: entity
|
||||
id: CrateSyndicateSuperSurplusBundle
|
||||
parent: CrateSyndicate
|
||||
parent: [ CrateSyndicate, StorePresetUplink ]
|
||||
name: Syndicate super surplus crate
|
||||
description: Contains 125 telecrystals worth of completely random Syndicate items.
|
||||
components:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
- type: entity
|
||||
abstract: true
|
||||
parent: BaseItem
|
||||
parent: [ BaseItem, StorePresetUplink ] #PDA's have uplinks so they have to inherit the data.
|
||||
id: BasePDA
|
||||
name: PDA
|
||||
description: Personal Data Assistant.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
id: WizardsGrimoire
|
||||
name: wizards grimoire
|
||||
suffix: Wizard
|
||||
parent: BaseItem
|
||||
parent: [ BaseItem, StorePresetSpellbook ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/books.rsi
|
||||
@@ -46,7 +46,6 @@
|
||||
- type: Store
|
||||
refundAllowed: true
|
||||
ownerOnly: true # get your own tome!
|
||||
preset: StorePresetSpellbook
|
||||
balance:
|
||||
WizCoin: 10 # prices are balanced around this 10 point maximum and how strong the spells are
|
||||
|
||||
@@ -55,12 +54,11 @@
|
||||
id: WizardsGrimoireNoRefund
|
||||
name: wizards grimoire
|
||||
suffix: Wizard, No Refund
|
||||
parent: WizardsGrimoire
|
||||
parent: [ WizardsGrimoire, StorePresetSpellbook ]
|
||||
components:
|
||||
- type: Store
|
||||
refundAllowed: false
|
||||
ownerOnly: true # get your own tome!
|
||||
preset: StorePresetSpellbook
|
||||
balance:
|
||||
WizCoin: 10 # prices are balanced around this 10 point maximum and how strong the spells are
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
- Cuffable # useless if you cant be cuffed
|
||||
|
||||
- type: entity
|
||||
parent: BaseSubdermalImplant
|
||||
parent: [ BaseSubdermalImplant, StorePresetUplink ]
|
||||
id: UplinkImplant
|
||||
name: uplink implant
|
||||
description: This implant lets the user access a hidden Syndicate uplink at will.
|
||||
@@ -155,7 +155,6 @@
|
||||
components:
|
||||
- Hands # prevent mouse buying grenade penguin since its not telepathic
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 0
|
||||
- type: UserInterface
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
# Uplinks
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
parent: [ BaseItem, StorePresetUplink ]
|
||||
id: BaseUplinkRadio
|
||||
name: syndicate uplink
|
||||
description: Suspiciously looking old radio...
|
||||
@@ -68,7 +68,6 @@
|
||||
- type: ActivatableUI
|
||||
key: enum.StoreUiKey.Key
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 0
|
||||
|
||||
@@ -78,7 +77,6 @@
|
||||
suffix: 20 TC
|
||||
components:
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 20
|
||||
|
||||
@@ -88,7 +86,6 @@
|
||||
suffix: 25 TC
|
||||
components:
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 25
|
||||
|
||||
@@ -99,7 +96,6 @@
|
||||
suffix: 40 TC, NukeOps
|
||||
components:
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 40
|
||||
- type: Tag
|
||||
@@ -112,7 +108,6 @@
|
||||
suffix: 60 TC, LoneOps
|
||||
components:
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 60
|
||||
- type: Tag
|
||||
@@ -125,6 +120,5 @@
|
||||
suffix: DEBUG
|
||||
components:
|
||||
- type: Store
|
||||
preset: StorePresetUplink
|
||||
balance:
|
||||
Telecrystal: 99999
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
- type: storePreset
|
||||
- type: entity
|
||||
id: StorePresetUplink
|
||||
storeName: Uplink
|
||||
categories:
|
||||
- UplinkWeaponry
|
||||
- UplinkAmmo
|
||||
- UplinkExplosives
|
||||
- UplinkChemicals
|
||||
- UplinkDeception
|
||||
- UplinkDisruption
|
||||
- UplinkImplants
|
||||
- UplinkAllies
|
||||
- UplinkWearables
|
||||
- UplinkJob
|
||||
- UplinkPointless
|
||||
currencyWhitelist:
|
||||
- Telecrystal
|
||||
abstract: true
|
||||
components:
|
||||
- type: Store
|
||||
name: store-preset-name-uplink
|
||||
categories:
|
||||
- UplinkWeaponry
|
||||
- UplinkAmmo
|
||||
- UplinkExplosives
|
||||
- UplinkChemicals
|
||||
- UplinkDeception
|
||||
- UplinkDisruption
|
||||
- UplinkImplants
|
||||
- UplinkAllies
|
||||
- UplinkWearables
|
||||
- UplinkJob
|
||||
- UplinkPointless
|
||||
currencyWhitelist:
|
||||
- Telecrystal
|
||||
balance:
|
||||
Telecrystal: 0
|
||||
|
||||
- type: storePreset
|
||||
- type: entity
|
||||
id: StorePresetSpellbook
|
||||
storeName: Spellbook
|
||||
categories:
|
||||
- SpellbookOffensive #Fireball, Rod Form
|
||||
- SpellbookDefensive #Magic Missile, Wall of Force
|
||||
- SpellbookUtility #Body Swap, Lich, Teleport, Knock, Polymorph
|
||||
- SpellbookEquipment #Battlemage Robes, Staff of Locker
|
||||
- SpellbookEvents #Summon Weapons, Summon Ghosts
|
||||
currencyWhitelist:
|
||||
abstract: true
|
||||
components:
|
||||
- type: Store
|
||||
name: store-preset-name-spellbook
|
||||
categories:
|
||||
- SpellbookOffensive #Fireball, Rod Form
|
||||
- SpellbookDefensive #Magic Missile, Wall of Force
|
||||
- SpellbookUtility #Body Swap, Lich, Teleport, Knock, Polymorph
|
||||
- SpellbookEquipment #Battlemage Robes, Staff of Locker
|
||||
- SpellbookEvents #Summon Weapons, Summon Ghosts
|
||||
currencyWhitelist:
|
||||
- WizCoin
|
||||
|
||||
Reference in New Issue
Block a user