Skip to content
Closed

Exped #545

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 200 additions & 88 deletions Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,189 +8,301 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

using System.Linq;
using Content.Client.Computer;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.CCVar;
using Content.Shared.Procedural;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Salvage;
using Content.Shared.Salvage.Expeditions;
using Content.Shared.Salvage.Expeditions.Modifiers;
using JetBrains.Annotations;
using Content.Shared.Shuttles.BUIStates;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

namespace Content.Client.Salvage.UI;

[UsedImplicitly]
public sealed class SalvageExpeditionConsoleBoundUserInterface : BoundUserInterface
[GenerateTypedNameReferences]
public sealed partial class SalvageExpeditionWindow : FancyWindow,
IComputerWindow<EmergencyConsoleBoundUserInterfaceState>
{
[ViewVariables]
private OfferingWindow? _window;
private readonly IConfigurationManager _cfgManager;
private readonly IGameTiming _timing;
private readonly IPrototypeManager _prototype;
private readonly SharedSalvageSystem _salvage;

[Dependency] private readonly IConfigurationManager _cfgManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
public event Action<ushort>? ClaimMission;
private bool _claimed;
private bool _cooldown;
private TimeSpan _nextOffer;

public SalvageExpeditionConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
public SalvageExpeditionWindow()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
_cfgManager = IoCManager.Resolve<IConfigurationManager>();
_timing = IoCManager.Resolve<IGameTiming>();
_prototype = IoCManager.Resolve<IPrototypeManager>();
_salvage = IoCManager.Resolve<IEntityManager>().EntitySysManager.GetEntitySystem<SharedSalvageSystem>();
}

protected override void Open()
public void UpdateState(SalvageExpeditionConsoleState state)
{
base.Open();
_window = this.CreateWindowCenteredLeft<OfferingWindow>();
_window.Title = Loc.GetString("salvage-expedition-window-title");
}

protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);

if (state is not SalvageExpeditionConsoleState current || _window == null)
return;

_window.Progression = null;
_window.Cooldown = TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.SalvageExpeditionCooldown));
_window.NextOffer = current.NextOffer;
_window.Claimed = current.Claimed;
_window.ClearOptions();
var salvage = _entManager.System<SalvageSystem>();
_claimed = state.Claimed;
_cooldown = state.Cooldown;
_nextOffer = state.NextOffer;
Container.DisposeAllChildren();

for (var i = 0; i < current.Missions.Count; i++)
for (var i = 0; i < state.Missions.Count; i++)
{
var missionParams = current.Missions[i];
var missionParams = state.Missions[i];
var config = missionParams.MissionType;
var mission = _salvage.GetMission(missionParams.MissionType, missionParams.Difficulty, missionParams.Seed);

var offering = new OfferingWindowOption();
offering.Title = Loc.GetString($"salvage-expedition-type");
// Mission title
var missionStripe = new StripeBack()
{
Margin = new Thickness(0f, -5f, 0f, 0f)
};

var difficultyId = "Moderate";
var difficultyProto = _protoManager.Index<SalvageDifficultyPrototype>(difficultyId);
// TODO: Selectable difficulty soon.
var mission = salvage.GetMission(difficultyProto, missionParams.Seed);
missionStripe.AddChild(new Label()
{
Text = Loc.GetString($"salvage-expedition-type-{config.ToString()}"),
HorizontalAlignment = HAlignment.Center,
Margin = new Thickness(0f, 5f, 0f, 5f),
});

var lBox = new BoxContainer()
{
Orientation = BoxContainer.LayoutOrientation.Vertical
};

// Difficulty
// Details
offering.AddContent(new Label()
lBox.AddChild(new Label()
{
Text = Loc.GetString("salvage-expedition-window-difficulty")
});

var difficultyColor = difficultyProto.Color;
Color difficultyColor;

switch (missionParams.Difficulty)
{
case DifficultyRating.Minimal:
difficultyColor = Color.FromHex("#52B4E996");
break;
case DifficultyRating.Minor:
difficultyColor = Color.FromHex("#9FED5896");
break;
case DifficultyRating.Moderate:
difficultyColor = Color.FromHex("#EFB34196");
break;
case DifficultyRating.Hazardous:
difficultyColor = Color.FromHex("#DE3A3A96");
break;
case DifficultyRating.Extreme:
difficultyColor = Color.FromHex("#D381C996");
break;
default:
throw new ArgumentOutOfRangeException();
}

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-difficulty-Moderate"),
Text = Loc.GetString($"salvage-expedition-difficulty-{missionParams.Difficulty.ToString()}"),
FontColorOverride = difficultyColor,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

offering.AddContent(new Label
// Details
var details = _salvage.GetMissionDescription(mission);

lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-difficulty-players"),
HorizontalAlignment = Control.HAlignment.Left,
Text = Loc.GetString("salvage-expedition-window-details")
});

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = difficultyProto.RecommendedPlayers.ToString(),
Text = details,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

// Details
offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-window-hostiles")
});

var faction = mission.Faction;

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = string.IsNullOrWhiteSpace(Loc.GetString(_protoManager.Index<SalvageFactionPrototype>(faction).Description))
? LogAndReturnDefaultFactionDescription(faction)
: Loc.GetString(_protoManager.Index<SalvageFactionPrototype>(faction).Description),
Text = faction,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

string LogAndReturnDefaultFactionDescription(string faction)
{
Logger.Error($"Description is null or white space for SalvageFactionPrototype: {faction}");
return Loc.GetString(_protoManager.Index<SalvageFactionPrototype>(faction).ID);
}


// Duration
offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-window-duration")
});

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = mission.Duration.ToString(),
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

// Biome
offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-window-biome")
});

var biome = mission.Biome;

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = string.IsNullOrWhiteSpace(Loc.GetString(_protoManager.Index<SalvageBiomeModPrototype>(biome).Description))
? LogAndReturnDefaultBiomDescription(biome)
: Loc.GetString(_protoManager.Index<SalvageBiomeModPrototype>(biome).Description),
Text = Loc.GetString(_prototype.Index<SalvageBiomeMod>(biome).ID),
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

string LogAndReturnDefaultBiomDescription(string biome)
{
Logger.Error($"Description is null or white space for SalvageBiomeModPrototype: {biome}");
return Loc.GetString(_protoManager.Index<SalvageBiomeModPrototype>(biome).ID);
}

// Modifiers
offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = Loc.GetString("salvage-expedition-window-modifiers")
});

var mods = mission.Modifiers;

offering.AddContent(new Label
lBox.AddChild(new Label
{
Text = string.Join("\n", mods.Select(o => "- " + o)).TrimEnd(),
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = Control.HAlignment.Left,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});

offering.ClaimPressed += args =>
lBox.AddChild(new Label()
{
Text = Loc.GetString("salvage-expedition-window-rewards")
});

var rewards = new Dictionary<string, int>();
foreach (var reward in mission.Rewards)
{
var name = _prototype.Index<EntityPrototype>(reward).Name;
var count = rewards.GetOrNew(name);
count++;
rewards[name] = count;
}

// there will always be 3 or more rewards so no need for 0 check
lBox.AddChild(new Label()
{
Text = string.Join("\n", rewards.Select(o => "- " + o.Key + (o.Value > 1 ? $" x {o.Value}" : ""))).TrimEnd(),
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f)
});

// Claim
var claimButton = new Button()
{
HorizontalExpand = true,
VerticalAlignment = VAlignment.Bottom,
Pressed = state.ActiveMission == missionParams.Index,
ToggleMode = true,
Disabled = state.Claimed || state.Cooldown,
};

claimButton.Label.Margin = new Thickness(0f, 5f);

claimButton.OnPressed += args =>
{
ClaimMission?.Invoke(missionParams.Index);
};

if (state.ActiveMission == missionParams.Index)
{
claimButton.Text = Loc.GetString("salvage-expedition-window-claimed");
claimButton.AddStyleClass(StyleBase.ButtonCaution);
}
else
{
claimButton.Text = Loc.GetString("salvage-expedition-window-claim");
}

var box = new PanelContainer
{
SendMessage(new ClaimSalvageMessage()
PanelOverride = new StyleBoxFlat(new Color(30, 30, 34)),
HorizontalExpand = true,
Margin = new Thickness(5f, 0f),
Children =
{
Index = missionParams.Index,
});
new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
Children =
{
missionStripe,
lBox,
new Control() {VerticalExpand = true},
claimButton,
},
Margin = new Thickness(5f, 5f)
}
}
};

offering.Claimed = current.ActiveMission == missionParams.Index;
offering.Disabled = current.Claimed || current.Cooldown;
LayoutContainer.SetAnchorPreset(box, LayoutContainer.LayoutPreset.Wide);

Container.AddChild(box);
}
}

protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);

if (_claimed)
{
NextOfferBar.Value = 0f;
NextOfferText.Text = "00:00";
return;
}

var remaining = _nextOffer - _timing.CurTime;

if (remaining < TimeSpan.Zero)
{
NextOfferBar.Value = 1f;
NextOfferText.Text = "00:00";
}
else
{
var cooldown = _cooldown
? TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.SalvageExpeditionFailedCooldown))
: TimeSpan.FromSeconds(_cfgManager.GetCVar(CCVars.SalvageExpeditionCooldown));

_window.AddOption(offering);
NextOfferBar.Value = 1f - (float) (remaining / cooldown);
NextOfferText.Text = $"{remaining.Minutes:00}:{remaining.Seconds:00}";
}
}
}
}
Loading