Files
crystall-punk-14/Content.Client/_CP14/Trading/CP14TradingPlatformWindow.xaml.cs
Red cde388f5dd Another Merchant gameplay attempt (#1308)
* setup UI

* setup debug data

* graph control setup

* reputation trade component

* unlocking logic

* smoe real reputation costing

* remove sponsors part, add trading specific UI nodes

* port to default pricing system

* buy cooldown

* fuck off trading cabinets

* real good cooldown UI

* Cool unlock sound

* reputation earning

* cool purchare sound

* coin & sprite work

* delete old guidebooks

* cool purcharing VFX

* better ui

* victoria gardens

* Update migration.yml

* Update migration.yml

* cooldown removed

* contracts

* Update migration.yml

* remove CP14Material

* materials appraise

* food appraise

* auto economy pricing system

* alchemy reagents appraise

* coins resprite

* alchemy appraise 2

* modular weapon appraise

* selling platform

* Update PricingSystem.cs

* Update CP14TradingPlatformSystem.cs

* merchants returns + map update

* Update CP14StationEconomySystem.Price.cs
2025-05-29 00:22:47 +03:00

255 lines
8.6 KiB
C#

using System.Linq;
using System.Numerics;
using Content.Client._CP14.UserInterface;
using Content.Client._CP14.UserInterface.Systems.NodeTree;
using Content.Shared._CP14.Trading;
using Content.Shared._CP14.Trading.Components;
using Content.Shared._CP14.Trading.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Client.Utility;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client._CP14.Trading;
[GenerateTypedNameReferences]
public sealed partial class CP14TradingPlatformWindow : DefaultWindow
{
[Dependency] private readonly ILogManager _log = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IEntityManager _e = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly CP14ClientTradingPlatformSystem _tradingSystem;
private readonly CP14ClientStationEconomySystem _economySystem;
private readonly SharedAudioSystem _audio = default!;
private CP14TradingPlatformUiState? _cacheState;
private Entity<CP14TradingReputationComponent>? _cachedUser;
private Entity<CP14TradingPlatformComponent>? _cachedPlatform;
private IEnumerable<CP14TradingPositionPrototype> _allPositions = [];
private IEnumerable<CP14TradingFactionPrototype> _allFactions = [];
private ProtoId<CP14TradingFactionPrototype>? _selectedFaction;
private CP14TradingPositionPrototype? _selectedPosition;
public event Action<ProtoId<CP14TradingPositionPrototype>>? OnUnlock;
public event Action<ProtoId<CP14TradingPositionPrototype>>? OnBuy;
private ISawmill Sawmill { get; init; }
public CP14TradingPlatformWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
Sawmill = _log.GetSawmill("cp14_trading");
CacheSkillProto();
_proto.PrototypesReloaded += _ => CacheSkillProto();
if (_cachedUser is not null)
{
foreach (var (f, _) in _cachedUser.Value.Comp.Reputation)
{
if (_proto.TryIndex(f, out var indexedFaction))
{
SelectFaction(indexedFaction);
break;
}
}
}
_tradingSystem = _e.System<CP14ClientTradingPlatformSystem>();
_economySystem = _e.System<CP14ClientStationEconomySystem>();
_audio = _e.System<SharedAudioSystem>();
GraphControl.OnOffsetChanged += offset =>
{
ParallaxBackground.Offset = -offset * 0.25f + new Vector2(1000, 1000); //hardcoding is bad
};
GraphControl.OnNodeSelected += SelectNode;
UnlockButton.OnPressed += UnlockPressed;
BuyButton.OnPressed += BuyPressed;
}
private void UnlockPressed(BaseButton.ButtonEventArgs obj)
{
if (_selectedPosition is null)
return;
OnUnlock?.Invoke(_selectedPosition);
if (_cachedUser is not null)
_audio.PlayGlobal(new SoundCollectionSpecifier("CP14CoinImpact"), _cachedUser.Value);
}
private void BuyPressed(BaseButton.ButtonEventArgs obj)
{
if (_selectedPosition is null)
return;
OnBuy?.Invoke(_selectedPosition.ID);
}
private void SelectNode(CP14NodeTreeElement? node)
{
if (node == null)
{
DeselectNode();
return;
}
if (_cacheState == null)
{
Sawmill.Error("Tried to select node without a cached state.");
return;
}
if (!_proto.TryIndex<CP14TradingPositionPrototype>(node.NodeKey, out var indexedPosition))
return;
SelectNode(indexedPosition);
}
private void SelectNode(CP14TradingPositionPrototype? node)
{
if (node is null || _cachedUser is null || _cachedPlatform is null)
{
DeselectNode();
return;
}
if (_cacheState == null)
{
Sawmill.Error("Tried to select node without a cached state.");
return;
}
_selectedPosition = node;
var unlocked = _cachedUser.Value.Comp.UnlockedPositions;
Name.Text = _tradingSystem.GetTradeName(_selectedPosition);
Description.Text = _tradingSystem.GetTradeDescription(_selectedPosition);
LocationView.Texture = _selectedPosition.Icon.Frame0();
UnlockButton.Disabled = !_tradingSystem.CanUnlockPosition((_cachedUser.Value.Owner, _cachedUser.Value.Comp), _selectedPosition);
BuyButton.Disabled = !unlocked.Contains(_selectedPosition);
UnlockCost.Text = _selectedPosition.UnlockReputationCost.ToString();
BuyPriceHolder.RemoveAllChildren();
BuyPriceHolder.AddChild(new CP14PriceControl(_economySystem.GetPrice(_selectedPosition) ?? 0));
}
private void DeselectNode()
{
Name.Text = string.Empty;
Description.Text = string.Empty;
LocationView.Texture = null;
UnlockButton.Disabled = true;
}
private void CacheSkillProto()
{
_allPositions = _proto.EnumeratePrototypes<CP14TradingPositionPrototype>();
_allFactions = _proto.EnumeratePrototypes<CP14TradingFactionPrototype>().OrderBy(tree => Loc.GetString(tree.Name));
}
public void UpdateState(CP14TradingPlatformUiState state)
{
_cacheState = state;
var ent = _e.GetEntity(state.User);
if (!_e.TryGetComponent<CP14TradingReputationComponent>(ent, out var repComp))
return;
_cachedUser = (ent, repComp);
var plat = _e.GetEntity(state.Platform);
if (!_e.TryGetComponent<CP14TradingPlatformComponent>(plat, out var platComp))
return;
_cachedPlatform = (plat, platComp);
UpdateGraphControl();
}
private void UpdateGraphControl()
{
if (_cachedUser is null)
return;
HashSet<CP14NodeTreeElement> nodeTreeElements = new();
var edges = new HashSet<(string, string)>();
foreach (var position in _allPositions)
{
if (position.Faction != _selectedFaction)
continue;
var unlocked = _cachedUser.Value.Comp.UnlockedPositions;
var gained = unlocked.Contains(position);
var active = _tradingSystem.CanUnlockPosition((_cachedUser.Value.Owner, _cachedUser.Value.Comp), position);
var node = new CP14NodeTreeElement(position.ID, gained, active, position.UiPosition * 66, position.Icon);
nodeTreeElements.Add(node);
if (position.Prerequisite != null)
{
edges.Add((position.Prerequisite, position.ID));
}
}
GraphControl.UpdateState(
new CP14NodeTreeUiState(
nodeTreeElements,
edges: edges,
frameIcon: new SpriteSpecifier.Rsi(
new ResPath("/Textures/_CP14/Interface/NodeTree/trading.rsi"),
"frame"),
hoveredIcon: new SpriteSpecifier.Rsi(
new ResPath("/Textures/_CP14/Interface/NodeTree/trading.rsi"),
"hovered"),
selectedIcon: new SpriteSpecifier.Rsi(
new ResPath("/Textures/_CP14/Interface/NodeTree/trading.rsi"),
"selected"),
learnedIcon: new SpriteSpecifier.Rsi(
new ResPath("/Textures/_CP14/Interface/NodeTree/trading.rsi"),
"learned"),
activeLineColor: new Color(172, 102, 190),
lineColor: new Color(83, 40, 121)
)
);
//Faction tabs update
TreeTabsContainer.RemoveAllChildren();
foreach (var (faction, rep) in _cachedUser.Value.Comp.Reputation)
{
if (!_proto.TryIndex(faction, out var indexedFaction))
continue;
var factionButton = new CP14TradingFactionButtonControl(
indexedFaction.Color,
Loc.GetString(indexedFaction.Name),
rep);
factionButton.OnPressed += () =>
{
SelectFaction(indexedFaction);
};
TreeTabsContainer.AddChild(factionButton);
}
SelectNode(_selectedPosition);
}
private void SelectFaction(CP14TradingFactionPrototype faction)
{
_selectedFaction = faction;
TreeName.Text = Loc.GetString("cp14-trading-faction-prefix") + " " + Loc.GetString(faction.Name);
UpdateGraphControl();
}
}