302 lines
6.8 KiB
C#
302 lines
6.8 KiB
C#
using Godot;
|
|
using Godot.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
public partial class ResearchList : PanelContainer
|
|
{
|
|
[Export] private GraphEdit researchGraph;
|
|
private System.Collections.Generic.Dictionary<string, Vector2> nodePositions = new System.Collections.Generic.Dictionary<string, Vector2>();
|
|
private bool hasArrangedNodes = false;
|
|
|
|
private List<Research> currentResearch = new List<Research>();
|
|
private List<Research> toDelete = new List<Research>();
|
|
|
|
public override void _Ready()
|
|
{
|
|
RecalculateResearchStates();
|
|
if (Visible) SetupGraph();
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if(currentResearch.Count > 0) toDelete = new List<Research>();
|
|
foreach (Research research in currentResearch)
|
|
{
|
|
ResearchResult result = research.Execute(delta);
|
|
if (result == ResearchResult.FINISHED)
|
|
{
|
|
toDelete.Add(research);
|
|
RecalculateResearchStates();
|
|
SetupGraph();
|
|
}
|
|
else if (result == ResearchResult.FAILED)
|
|
{
|
|
research.state = ResearchState.AVAILABLE;
|
|
toDelete.Add(research);
|
|
RecalculateResearchStates();
|
|
SetupGraph();
|
|
}
|
|
}
|
|
foreach (Research delete in toDelete)
|
|
{
|
|
currentResearch.Remove(delete);
|
|
}
|
|
}
|
|
|
|
public void SetupGraph()
|
|
{
|
|
RememberNodePositions();
|
|
ClearGraph();
|
|
CreateResearchNodes();
|
|
CreateResearchConnections();
|
|
|
|
if (!hasArrangedNodes)
|
|
{
|
|
researchGraph.ArrangeNodes();
|
|
hasArrangedNodes = true;
|
|
}
|
|
}
|
|
|
|
private void RememberNodePositions()
|
|
{
|
|
foreach (Node child in researchGraph.GetChildren())
|
|
{
|
|
GraphNode node = child as GraphNode;
|
|
if (node == null) continue;
|
|
|
|
nodePositions[node.Name] = node.PositionOffset;
|
|
}
|
|
}
|
|
|
|
private void ClearGraph()
|
|
{
|
|
foreach (Dictionary connection in researchGraph.GetConnectionList())
|
|
{
|
|
researchGraph.DisconnectNode(
|
|
connection["from_node"].AsStringName(),
|
|
(int)connection["from_port"],
|
|
connection["to_node"].AsStringName(),
|
|
(int)connection["to_port"]
|
|
);
|
|
}
|
|
|
|
foreach (Node child in researchGraph.GetChildren())
|
|
{
|
|
if (child is GraphNode)
|
|
{
|
|
researchGraph.RemoveChild(child);
|
|
child.QueueFree();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateResearchNodes()
|
|
{
|
|
foreach (Research research in GameData.availableResearch.Values)
|
|
{
|
|
GraphNode node = CreateResearchNode(
|
|
research.data.Id,
|
|
research.data.Texture,
|
|
research.state
|
|
);
|
|
|
|
researchGraph.AddChild(node);
|
|
}
|
|
}
|
|
|
|
private void CreateResearchConnections()
|
|
{
|
|
foreach (Research research in GameData.availableResearch.Values)
|
|
{
|
|
string prerequisite = research.data.Research;
|
|
string current = research.data.Id;
|
|
|
|
if (string.IsNullOrEmpty(prerequisite)) continue;
|
|
|
|
if (!researchGraph.HasNode(prerequisite) || !researchGraph.HasNode(current)) continue;
|
|
|
|
researchGraph.ConnectNode(
|
|
prerequisite,
|
|
0,
|
|
current,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
private GraphNode CreateResearchNode(string id, string texturePath, ResearchState state)
|
|
{
|
|
Texture2D texture = GD.Load<Texture2D>(texturePath);
|
|
Color stateColor = GetColorByState(state);
|
|
string tooltipText = GetResearchTooltip(GameData.availableResearch[id]);
|
|
|
|
TextureRect icon = new TextureRect
|
|
{
|
|
Texture = texture,
|
|
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
|
|
CustomMinimumSize = new Vector2(64, 64),
|
|
SelfModulate = stateColor
|
|
};
|
|
|
|
Button button = new Button
|
|
{
|
|
Text = GetResearchButtonText(GameData.availableResearch[id], state),
|
|
Disabled = state != ResearchState.AVAILABLE || !GameData.availableResearch[id].CanStart(),
|
|
TooltipText = tooltipText
|
|
};
|
|
|
|
button.Pressed += () => OnResearchPressed(id);
|
|
|
|
GraphNode node = new GraphNode
|
|
{
|
|
Name = id,
|
|
Title = Research.GetReadableName(id),
|
|
SelfModulate = stateColor,
|
|
TooltipText = tooltipText
|
|
};
|
|
|
|
if (nodePositions.ContainsKey(id))
|
|
{
|
|
node.PositionOffset = nodePositions[id];
|
|
}
|
|
|
|
node.SetSlot(
|
|
0,
|
|
true,
|
|
0,
|
|
Colors.White,
|
|
true,
|
|
0,
|
|
Colors.White
|
|
);
|
|
|
|
node.AddChild(icon);
|
|
node.AddChild(button);
|
|
|
|
return node;
|
|
}
|
|
|
|
private void OnResearchPressed(string id)
|
|
{
|
|
Research research = GameData.availableResearch[id];
|
|
if (!research.CanStart()) return;
|
|
if (currentResearch.Contains(research)) return;
|
|
|
|
research.state = ResearchState.RESEARCHING;
|
|
currentResearch.Add(research);
|
|
RecalculateResearchStates();
|
|
SetupGraph();
|
|
}
|
|
|
|
private string GetResearchButtonText(Research research, ResearchState state)
|
|
{
|
|
if (state == ResearchState.RESEARCHED) return "Done";
|
|
if (state == ResearchState.RESEARCHING) return "Researching";
|
|
if (state == ResearchState.LOCKED) return "Locked";
|
|
if (!research.CanStart()) return "Missing items";
|
|
|
|
return "Research";
|
|
}
|
|
|
|
private string GetResearchTooltip(Research research)
|
|
{
|
|
StringBuilder tooltip = new StringBuilder(Research.GetReadableName(research.data.Id));
|
|
tooltip.AppendLine();
|
|
tooltip.AppendLine();
|
|
tooltip.AppendLine("Costs:");
|
|
|
|
if (research.data.Inputs.Count <= 0)
|
|
{
|
|
tooltip.AppendLine("- None");
|
|
}
|
|
|
|
foreach (Ingredient ingredient in research.data.Inputs)
|
|
{
|
|
tooltip.Append("- ");
|
|
tooltip.Append(ItemData.GetReadableName(ingredient.Item));
|
|
tooltip.Append(": ");
|
|
tooltip.Append(GameData.inventory.GetItemAmount(ingredient.Item));
|
|
tooltip.Append("/");
|
|
tooltip.AppendLine(ingredient.Amount.ToString());
|
|
}
|
|
|
|
tooltip.AppendLine();
|
|
tooltip.Append("Time: ");
|
|
tooltip.AppendLine(research.data.CraftTime.ToString("0"));
|
|
|
|
if (research.data.Effects == null || research.data.Effects.Count <= 0)
|
|
{
|
|
return tooltip.ToString();
|
|
}
|
|
|
|
tooltip.AppendLine();
|
|
tooltip.AppendLine("Effects:");
|
|
|
|
foreach (ResearchEffect effect in research.data.Effects)
|
|
{
|
|
tooltip.Append("- ");
|
|
tooltip.AppendLine(effect.GetDisplayText());
|
|
}
|
|
|
|
return tooltip.ToString();
|
|
}
|
|
|
|
private void RecalculateResearchStates()
|
|
{
|
|
bool changedState = true;
|
|
|
|
while (changedState)
|
|
{
|
|
changedState = false;
|
|
|
|
foreach (Research research in GameData.availableResearch.Values)
|
|
{
|
|
ResearchState newState = GetUpdatedResearchState(research);
|
|
|
|
if (research.state == newState) continue;
|
|
|
|
research.state = newState;
|
|
changedState = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private ResearchState GetUpdatedResearchState(Research research)
|
|
{
|
|
if (research.state == ResearchState.RESEARCHED)
|
|
{
|
|
return ResearchState.RESEARCHED;
|
|
}
|
|
|
|
if (research.data.Research.Length <= 0)
|
|
{
|
|
return ResearchState.RESEARCHED;
|
|
}
|
|
|
|
if (research.state == ResearchState.RESEARCHING)
|
|
{
|
|
return ResearchState.RESEARCHING;
|
|
}
|
|
|
|
if (GameData.availableResearch[research.data.Research].state == ResearchState.RESEARCHED)
|
|
{
|
|
return ResearchState.AVAILABLE;
|
|
}
|
|
|
|
return ResearchState.LOCKED;
|
|
}
|
|
|
|
private Color GetColorByState(ResearchState state)
|
|
{
|
|
return state switch
|
|
{
|
|
ResearchState.AVAILABLE => Colors.White,
|
|
ResearchState.LOCKED => new Color(0.6f, 0.6f, 0.6f, 0.5f),
|
|
ResearchState.RESEARCHED => new Color(0.7f, 1f, 0.7f, 1f),
|
|
ResearchState.RESEARCHING => new Color(0.3f, 1f, 0.3f, 1f),
|
|
_ => Colors.Red
|
|
};
|
|
}
|
|
}
|