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.Player; 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!; [Dependency] private readonly IPlayerManager _player = default!; private readonly CP14ClientTradingPlatformSystem _tradingSystem; private readonly CP14ClientStationEconomySystem _economySystem; private readonly SharedAudioSystem _audio = default!; private CP14TradingPlatformUiState? _cacheState; private Entity? _cachedUser; private Entity? _cachedPlatform; private IEnumerable _allPositions = []; private IEnumerable _allFactions = []; private ProtoId? _selectedFaction; private CP14TradingPositionPrototype? _selectedPosition; public event Action>? 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(); _economySystem = _e.System(); _audio = _e.System(); GraphControl.OnOffsetChanged += offset => { ParallaxBackground.Offset = -offset * 0.25f + new Vector2(1000, 1000); //hardcoding is bad }; GraphControl.OnNodeSelected += SelectNode; BuyButton.OnPressed += BuyPressed; } 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(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.Reputation[_selectedPosition.Faction] >= _selectedPosition.ReputationLevel; Name.Text = _tradingSystem.GetTradeName(_selectedPosition); Description.Text = _tradingSystem.GetTradeDescription(_selectedPosition); LocationView.Texture = _selectedPosition.Icon.Frame0(); BuyButton.Disabled = !unlocked; UnlockCost.Text = _selectedPosition.ReputationLevel.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; } private void CacheSkillProto() { _allPositions = _proto.EnumeratePrototypes(); _allFactions = _proto.EnumeratePrototypes().OrderBy(tree => Loc.GetString(tree.Name)); UpdateGraphControl(); } public void UpdateState(CP14TradingPlatformUiState state) { _cacheState = state; if (!_e.TryGetComponent(_player.LocalEntity, out var repComp)) return; _cachedUser = (_player.LocalEntity.Value, repComp); var plat = _e.GetEntity(state.Platform); if (!_e.TryGetComponent(plat, out var platComp)) return; _cachedPlatform = (plat, platComp); UpdateGraphControl(); } private void UpdateGraphControl() { if (_cachedUser is null) return; HashSet nodeTreeElements = new(); var edges = new HashSet<(string, string)>(); foreach (var position in _allPositions) { if (position.Faction != _selectedFaction) continue; var unlocked = _cachedUser.Value.Comp.Reputation[position.Faction] >= position.ReputationLevel; var active = _tradingSystem.CanBuyPosition((_cachedUser.Value.Owner, _cachedUser.Value.Comp), position); var node = new CP14NodeTreeElement(position.ID, unlocked, active, new Vector2(position.ReputationLevel.Float() * 50, position.UiPosition * 50) , position.Icon); nodeTreeElements.Add(node); } 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(); } }