Files
RuinAdventurer/Scripts/Research/ResearchList.cs
T

190 lines
4.0 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Godot;
using Godot.Collections;
public partial class ResearchList : PanelContainer
{
[Export] private GraphEdit researchGraph;
private List<string> reloadKeys = new List<string>();
public override void _Ready()
{
RecalculateResearchStates();
if(Visible) SetupGraph();
}
public void SetupGraph()
{
reloadKeys = new List<string>();
ClearGraph();
CreateResearchNodes();
CreateResearchConnections();
researchGraph.ArrangeNodes();
}
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)
{
GD.Print(research.state);
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);
TextureRect icon = new TextureRect
{
Texture = texture,
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
CustomMinimumSize = new Vector2(64, 64),
SelfModulate = stateColor
};
Button button = new Button
{
Text = "Research",
Disabled = state != ResearchState.AVAILABLE
};
button.Pressed += () => OnResearchPressed(id);
GraphNode node = new GraphNode
{
Name = id,
Title = id,
SelfModulate = stateColor
};
node.SetSlot(
0,
true,
0,
Colors.White,
true,
0,
Colors.White
);
node.AddChild(icon);
node.AddChild(button);
return node;
}
private void OnResearchPressed(string id)
{
GameData.availableResearch[id].state = ResearchState.RESEARCHED;
RecalculateResearchStates();
SetupGraph();
}
private void RecalculateResearchStates()
{
bool changedState;
foreach (string key in GameData.availableResearch.Keys)
{
changedState = false;
if (reloadKeys.Contains(key)) continue;
reloadKeys.Add(key);
//Already researched
if (GameData.availableResearch[key].state == ResearchState.RESEARCHED)
{
changedState = true;
}
//No previous research needed
if (GameData.availableResearch[key].data.Research.Length <= 0)
{
GameData.availableResearch[key].state = ResearchState.RESEARCHED;
changedState = true;
}
//Previous research is unlocked
if (!changedState && GameData.availableResearch[GameData.availableResearch[key].data.Research].state == ResearchState.RESEARCHED)
{
GameData.availableResearch[key].state = ResearchState.AVAILABLE;
changedState = true;
}
if (!changedState)
{
//All others are locked
GameData.availableResearch[key].state = ResearchState.LOCKED;
}
if (reloadKeys.Count != GameData.availableResearch.Keys.Count)
{
RecalculateResearchStates();
}
}
}
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),
_ => Colors.Red
};
}
}