From a472adf74bef905d7a49f3870a6ca00f0720882a Mon Sep 17 00:00:00 2001 From: Nicola Date: Sat, 9 May 2026 20:12:53 +0200 Subject: [PATCH] Added new nodes to DSL for a wider variety of commands and scripts. --- Prefabs/DSL/ElseNode.tscn | 47 +++++++++++ Prefabs/DSL/ForNode.tscn | 55 +++++++++++++ Prefabs/DSL/IfNode.tscn | 76 +++++++++++++++++ Prefabs/DSL/UntilNode.tscn | 47 +++++++++++ Prefabs/DSL/WhileNode.tscn | 76 +++++++++++++++++ Scenes/Game.tscn | 7 +- Scripts/Core/GameData.cs | 4 +- Scripts/Core/ResourceLoader.cs | 7 +- Scripts/DSL/NodeResult.cs | 3 +- Scripts/DSL/Nodes/CraftNode.cs | 4 +- Scripts/DSL/Nodes/ElseNode.cs | 33 ++++++++ Scripts/DSL/Nodes/ElseNode.cs.uid | 1 + Scripts/DSL/Nodes/ForNode.cs | 48 +++++++++++ Scripts/DSL/Nodes/ForNode.cs.uid | 1 + Scripts/DSL/Nodes/HarvestNode.cs | 4 + Scripts/DSL/Nodes/IfNode.cs | 111 +++++++++++++++++++++++++ Scripts/DSL/Nodes/IfNode.cs.uid | 1 + Scripts/DSL/Nodes/ProgramNode.cs | 1 + Scripts/DSL/Nodes/UntilNode.cs | 32 ++++++++ Scripts/DSL/Nodes/UntilNode.cs.uid | 1 + Scripts/DSL/Nodes/WhileNode.cs | 113 ++++++++++++++++++++++++++ Scripts/DSL/Nodes/WhileNode.cs.uid | 1 + Scripts/Gameplay/Research/Research.cs | 2 +- Scripts/Gameplay/Robots/Robot.cs | 48 ++++++++++- Scripts/UI/DSL/CodingWindow.cs | 4 + Scripts/UI/DSL/NodeDisplay.cs | 91 +++++++++++++++++++-- 26 files changed, 797 insertions(+), 21 deletions(-) create mode 100644 Prefabs/DSL/ElseNode.tscn create mode 100644 Prefabs/DSL/ForNode.tscn create mode 100644 Prefabs/DSL/IfNode.tscn create mode 100644 Prefabs/DSL/UntilNode.tscn create mode 100644 Prefabs/DSL/WhileNode.tscn create mode 100644 Scripts/DSL/Nodes/ElseNode.cs create mode 100644 Scripts/DSL/Nodes/ElseNode.cs.uid create mode 100644 Scripts/DSL/Nodes/ForNode.cs create mode 100644 Scripts/DSL/Nodes/ForNode.cs.uid create mode 100644 Scripts/DSL/Nodes/IfNode.cs create mode 100644 Scripts/DSL/Nodes/IfNode.cs.uid create mode 100644 Scripts/DSL/Nodes/UntilNode.cs create mode 100644 Scripts/DSL/Nodes/UntilNode.cs.uid create mode 100644 Scripts/DSL/Nodes/WhileNode.cs create mode 100644 Scripts/DSL/Nodes/WhileNode.cs.uid diff --git a/Prefabs/DSL/ElseNode.tscn b/Prefabs/DSL/ElseNode.tscn new file mode 100644 index 0000000..f60752f --- /dev/null +++ b/Prefabs/DSL/ElseNode.tscn @@ -0,0 +1,47 @@ +[gd_scene format=3 uid="uid://drcb0eqe78k0p"] + +[ext_resource type="Script" uid="uid://b6kxwmuhmruul" path="res://Scripts/UI/DSL/NodeDisplay.cs" id="1_rl00f"] +[ext_resource type="Texture2D" uid="uid://wq8yc0u0ee33" path="res://Assets/Images/TrashSymbol.png" id="2_swrbs"] + +[node name="Else" type="PanelContainer" unique_id=247502695 node_paths=PackedStringArray("editorDisplay", "listDisplay")] +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_bottom = 31.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_rl00f") +editorDisplay = NodePath("EditorDisplay") +listDisplay = NodePath("ListDisplay") + +[node name="EditorDisplay" type="PanelContainer" parent="." unique_id=1839537826] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="EditorDisplay" unique_id=945032897] +layout_mode = 2 +alignment = 1 + +[node name="Flavour" type="RichTextLabel" parent="EditorDisplay/HBoxContainer" unique_id=1994560318] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Else" +fit_content = true +autowrap_mode = 0 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="TextureButton" type="TextureButton" parent="EditorDisplay/HBoxContainer" unique_id=479938935] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +texture_normal = ExtResource("2_swrbs") + +[node name="ListDisplay" type="Button" parent="." unique_id=200731038] +visible = false +layout_mode = 2 +tooltip_text = "Stops skipping from If-nodes" +text = "Else" + +[connection signal="pressed" from="EditorDisplay/HBoxContainer/TextureButton" to="." method="DeleteNodePressed"] diff --git a/Prefabs/DSL/ForNode.tscn b/Prefabs/DSL/ForNode.tscn new file mode 100644 index 0000000..2e5a87e --- /dev/null +++ b/Prefabs/DSL/ForNode.tscn @@ -0,0 +1,55 @@ +[gd_scene format=3 uid="uid://co7op7et6is8p"] + +[ext_resource type="Script" uid="uid://b6kxwmuhmruul" path="res://Scripts/UI/DSL/NodeDisplay.cs" id="1_xshi5"] +[ext_resource type="Texture2D" uid="uid://wq8yc0u0ee33" path="res://Assets/Images/TrashSymbol.png" id="2_mtk18"] + +[node name="Craft" type="PanelContainer" unique_id=247502695 node_paths=PackedStringArray("editorDisplay", "listDisplay")] +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_bottom = 31.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_xshi5") +editorDisplay = NodePath("EditorDisplay") +listDisplay = NodePath("ListDisplay") + +[node name="EditorDisplay" type="PanelContainer" parent="." unique_id=1839537826] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="EditorDisplay" unique_id=945032897] +layout_mode = 2 +alignment = 1 + +[node name="Flavour" type="RichTextLabel" parent="EditorDisplay/HBoxContainer" unique_id=1994560318] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +text = "For:" +fit_content = true +autowrap_mode = 0 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Amount" type="SpinBox" parent="EditorDisplay/HBoxContainer" unique_id=1195061461] +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +alignment = 1 +prefix = "x" + +[node name="TextureButton" type="TextureButton" parent="EditorDisplay/HBoxContainer" unique_id=479938935] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +texture_normal = ExtResource("2_mtk18") + +[node name="ListDisplay" type="Button" parent="." unique_id=200731038] +visible = false +layout_mode = 2 +tooltip_text = "Repeats the following blocks to the next for, until or while block the selected amount of times." +text = "For" + +[connection signal="pressed" from="EditorDisplay/HBoxContainer/TextureButton" to="." method="DeleteNodePressed"] diff --git a/Prefabs/DSL/IfNode.tscn b/Prefabs/DSL/IfNode.tscn new file mode 100644 index 0000000..c43e75b --- /dev/null +++ b/Prefabs/DSL/IfNode.tscn @@ -0,0 +1,76 @@ +[gd_scene format=3 uid="uid://ctmad6foidkvp"] + +[ext_resource type="Script" uid="uid://b6kxwmuhmruul" path="res://Scripts/UI/DSL/NodeDisplay.cs" id="1_ygi5c"] +[ext_resource type="Texture2D" uid="uid://wq8yc0u0ee33" path="res://Assets/Images/TrashSymbol.png" id="2_a5cwv"] + +[node name="If" type="PanelContainer" unique_id=247502695 node_paths=PackedStringArray("editorDisplay", "listDisplay")] +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_bottom = 31.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_ygi5c") +editorDisplay = NodePath("EditorDisplay") +listDisplay = NodePath("ListDisplay") + +[node name="EditorDisplay" type="PanelContainer" parent="." unique_id=1839537826] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="EditorDisplay" unique_id=945032897] +layout_mode = 2 +alignment = 1 + +[node name="Flavour" type="RichTextLabel" parent="EditorDisplay/HBoxContainer" unique_id=1994560318] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +text = "If:" +fit_content = true +autowrap_mode = 0 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Item" type="OptionButton" parent="EditorDisplay/HBoxContainer" unique_id=117577134] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Comparator" type="OptionButton" parent="EditorDisplay/HBoxContainer" unique_id=539633915] +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 6 +popup/item_0/text = "is equal to" +popup/item_0/id = 0 +popup/item_1/text = "is bigger than" +popup/item_1/id = 1 +popup/item_2/text = "is less than" +popup/item_2/id = 2 +popup/item_3/text = "is not" +popup/item_3/id = 3 +popup/item_4/text = "is less than or equal to" +popup/item_4/id = 4 +popup/item_5/text = "is bigger than or equal to" +popup/item_5/id = 5 + +[node name="Amount" type="SpinBox" parent="EditorDisplay/HBoxContainer" unique_id=1195061461] +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +alignment = 1 +prefix = "x" + +[node name="TextureButton" type="TextureButton" parent="EditorDisplay/HBoxContainer" unique_id=479938935] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +texture_normal = ExtResource("2_a5cwv") + +[node name="ListDisplay" type="Button" parent="." unique_id=200731038] +visible = false +layout_mode = 2 +tooltip_text = "Allows branching in the code with a condition based on item in your inventory. (Skips everything until another If or Else block if condition is false)" +text = "If" + +[connection signal="pressed" from="EditorDisplay/HBoxContainer/TextureButton" to="." method="DeleteNodePressed"] diff --git a/Prefabs/DSL/UntilNode.tscn b/Prefabs/DSL/UntilNode.tscn new file mode 100644 index 0000000..a3a79ce --- /dev/null +++ b/Prefabs/DSL/UntilNode.tscn @@ -0,0 +1,47 @@ +[gd_scene format=3 uid="uid://ypfwubnl4oju"] + +[ext_resource type="Script" uid="uid://b6kxwmuhmruul" path="res://Scripts/UI/DSL/NodeDisplay.cs" id="1_kmf0m"] +[ext_resource type="Texture2D" uid="uid://wq8yc0u0ee33" path="res://Assets/Images/TrashSymbol.png" id="2_71nn3"] + +[node name="Craft" type="PanelContainer" unique_id=247502695 node_paths=PackedStringArray("editorDisplay", "listDisplay")] +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_bottom = 31.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_kmf0m") +editorDisplay = NodePath("EditorDisplay") +listDisplay = NodePath("ListDisplay") + +[node name="EditorDisplay" type="PanelContainer" parent="." unique_id=1839537826] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="EditorDisplay" unique_id=945032897] +layout_mode = 2 +alignment = 1 + +[node name="Flavour" type="RichTextLabel" parent="EditorDisplay/HBoxContainer" unique_id=1994560318] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Until" +fit_content = true +autowrap_mode = 0 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="TextureButton" type="TextureButton" parent="EditorDisplay/HBoxContainer" unique_id=479938935] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +texture_normal = ExtResource("2_71nn3") + +[node name="ListDisplay" type="Button" parent="." unique_id=200731038] +visible = false +layout_mode = 2 +tooltip_text = "Stops any while- or for-loop and returns to their node position." +text = "Until" + +[connection signal="pressed" from="EditorDisplay/HBoxContainer/TextureButton" to="." method="DeleteNodePressed"] diff --git a/Prefabs/DSL/WhileNode.tscn b/Prefabs/DSL/WhileNode.tscn new file mode 100644 index 0000000..32a15f6 --- /dev/null +++ b/Prefabs/DSL/WhileNode.tscn @@ -0,0 +1,76 @@ +[gd_scene format=3 uid="uid://bwiaqvl0d4x8v"] + +[ext_resource type="Script" uid="uid://b6kxwmuhmruul" path="res://Scripts/UI/DSL/NodeDisplay.cs" id="1_q0rc7"] +[ext_resource type="Texture2D" uid="uid://wq8yc0u0ee33" path="res://Assets/Images/TrashSymbol.png" id="2_yhncq"] + +[node name="While" type="PanelContainer" unique_id=247502695 node_paths=PackedStringArray("editorDisplay", "listDisplay")] +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_bottom = 31.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_q0rc7") +editorDisplay = NodePath("EditorDisplay") +listDisplay = NodePath("ListDisplay") + +[node name="EditorDisplay" type="PanelContainer" parent="." unique_id=1839537826] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="EditorDisplay" unique_id=945032897] +layout_mode = 2 +alignment = 1 + +[node name="Flavour" type="RichTextLabel" parent="EditorDisplay/HBoxContainer" unique_id=1994560318] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +text = "While:" +fit_content = true +autowrap_mode = 0 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Item" type="OptionButton" parent="EditorDisplay/HBoxContainer" unique_id=117577134] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Comparator" type="OptionButton" parent="EditorDisplay/HBoxContainer" unique_id=539633915] +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 6 +popup/item_0/text = "is equal to" +popup/item_0/id = 0 +popup/item_1/text = "is bigger than" +popup/item_1/id = 1 +popup/item_2/text = "is less than" +popup/item_2/id = 2 +popup/item_3/text = "is not" +popup/item_3/id = 3 +popup/item_4/text = "is less than or equal to" +popup/item_4/id = 4 +popup/item_5/text = "is bigger than or equal to" +popup/item_5/id = 5 + +[node name="Amount" type="SpinBox" parent="EditorDisplay/HBoxContainer" unique_id=1195061461] +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +alignment = 1 +prefix = "x" + +[node name="TextureButton" type="TextureButton" parent="EditorDisplay/HBoxContainer" unique_id=479938935] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.2 +texture_normal = ExtResource("2_yhncq") + +[node name="ListDisplay" type="Button" parent="." unique_id=200731038] +visible = false +layout_mode = 2 +tooltip_text = "Allows repetition in the code with a condition based on item in your inventory. (Skips everything until another while, for or until block if condition is false)" +text = "While" + +[connection signal="pressed" from="EditorDisplay/HBoxContainer/TextureButton" to="." method="DeleteNodePressed"] diff --git a/Scenes/Game.tscn b/Scenes/Game.tscn index d1cdbdc..3ba5c4d 100644 --- a/Scenes/Game.tscn +++ b/Scenes/Game.tscn @@ -204,12 +204,10 @@ size_flags_vertical = 3 [node name="CodingWindow" type="PanelContainer" parent="CanvasLayer/UIHandler/MainUI/Content" unique_id=1576652491 node_paths=PackedStringArray("codeBlocks", "editorWindow", "availableScripts", "scriptName", "nameInput")] visible = false layout_mode = 1 -anchors_preset = 11 -anchor_left = 1.0 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_left = -524.0 -grow_horizontal = 0 +grow_horizontal = 2 grow_vertical = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_7lihs") script = ExtResource("6_7lihs") @@ -262,6 +260,7 @@ size_flags_vertical = 3 [node name="CodeBlocks" type="ScrollContainer" parent="CanvasLayer/UIHandler/MainUI/Content/CodingWindow/VBoxContainer/Scripting" unique_id=1196874464] layout_mode = 2 size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.5 theme_override_styles/panel = SubResource("StyleBoxFlat_fgofq") [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/UIHandler/MainUI/Content/CodingWindow/VBoxContainer/Scripting/CodeBlocks" unique_id=1751038712] diff --git a/Scripts/Core/GameData.cs b/Scripts/Core/GameData.cs index d793ffd..7775937 100644 --- a/Scripts/Core/GameData.cs +++ b/Scripts/Core/GameData.cs @@ -4,7 +4,7 @@ using Godot; public partial class GameData { - public static bool debugMode = false; + public static bool debugMode = true; public static Random rand = new Random(seed); public static Layer[] map; @@ -18,8 +18,8 @@ public partial class GameData public static float robotSpeed = 10f; public static float tileWidth = 6; public static float tileHeight = 4; - public static SortedDictionary availableItems = ResourceLoader.LoadItems(); public static Dictionary availableResearch = ResourceLoader.LoadResearch(); + public static SortedDictionary availableItems = ResourceLoader.LoadItems(); public static SurvivalState survival = new SurvivalState(); public static RobotStats robotStats = new RobotStats(); public static Dictionary> gateUnlocks; diff --git a/Scripts/Core/ResourceLoader.cs b/Scripts/Core/ResourceLoader.cs index 1a1ab5f..650430b 100644 --- a/Scripts/Core/ResourceLoader.cs +++ b/Scripts/Core/ResourceLoader.cs @@ -69,7 +69,12 @@ public partial class ResourceLoader { new MoveNode(), GD.Load("res://Prefabs/DSL/MoveNode.tscn") }, { new HarvestNode(), GD.Load("res://Prefabs/DSL/HarvestNode.tscn") }, { new CraftNode(), GD.Load("res://Prefabs/DSL/CraftNode.tscn") }, - { new ExploreNode(), GD.Load("res://Prefabs/DSL/ExploreNode.tscn") } + { new ExploreNode(), GD.Load("res://Prefabs/DSL/ExploreNode.tscn") }, + { new IfNode(), GD.Load("res://Prefabs/DSL/IfNode.tscn") }, + { new ElseNode(), GD.Load("res://Prefabs/DSL/ElseNode.tscn") }, + { new UntilNode(), GD.Load("res://Prefabs/DSL/UntilNode.tscn") }, + { new ForNode(), GD.Load("res://Prefabs/DSL/ForNode.tscn") }, + { new WhileNode(), GD.Load("res://Prefabs/DSL/WhileNode.tscn") } }; return nodes; } diff --git a/Scripts/DSL/NodeResult.cs b/Scripts/DSL/NodeResult.cs index 59ca8be..d4f0b63 100644 --- a/Scripts/DSL/NodeResult.cs +++ b/Scripts/DSL/NodeResult.cs @@ -2,5 +2,6 @@ public enum NodeResult { SUCCESS, FAILURE, - RUNNING + RUNNING, + CONDITIONFALSE } \ No newline at end of file diff --git a/Scripts/DSL/Nodes/CraftNode.cs b/Scripts/DSL/Nodes/CraftNode.cs index d6cdd42..a9d1e7c 100644 --- a/Scripts/DSL/Nodes/CraftNode.cs +++ b/Scripts/DSL/Nodes/CraftNode.cs @@ -44,7 +44,7 @@ public class CraftNode : ProgramNode { HBoxContainer valueContainer = display.GetNode("./EditorDisplay/HBoxContainer/"); OptionButton items = valueContainer.GetNode("./Item"); - string readableItem = items.GetItemText(items.GetSelectedId()); + string readableItem = items.GetItemText(items.GetSelectedId()).Split(":")[0]; if (GameData.availableItems.ContainsKey(ItemData.GetIndex(readableItem))) { selectedItem = new Item { data = GameData.availableItems[ItemData.GetIndex(readableItem)] }; @@ -79,7 +79,7 @@ public class CraftNode : ProgramNode { for (int i = 0; i < options.ItemCount; i++) { - if (ItemData.GetIndex(options.GetItemText(i)) == selectedItem.data.Id) + if (ItemData.GetIndex(options.GetItemText(i).Split(":")[0]) == selectedItem.data.Id) { options.Select(i); break; diff --git a/Scripts/DSL/Nodes/ElseNode.cs b/Scripts/DSL/Nodes/ElseNode.cs new file mode 100644 index 0000000..27bfcc2 --- /dev/null +++ b/Scripts/DSL/Nodes/ElseNode.cs @@ -0,0 +1,33 @@ +using Godot; + +public class ElseNode : ProgramNode +{ + public ElseNode() + { + DisplayText = "Else"; + } + public override NodeResult Execute(Robot robot, double delta) + { + return NodeResult.SUCCESS; + } + + public override void ReadParameters(NodeDisplay display) + { + } + + public override ProgramNode Duplicate() + { + ElseNode duplicate = new ElseNode(); + return duplicate; + } + + public override void Setup(NodeDisplay display) + { + + } + + public override string Save() + { + return $"Name: {DisplayText}"; + } +} diff --git a/Scripts/DSL/Nodes/ElseNode.cs.uid b/Scripts/DSL/Nodes/ElseNode.cs.uid new file mode 100644 index 0000000..aeed4df --- /dev/null +++ b/Scripts/DSL/Nodes/ElseNode.cs.uid @@ -0,0 +1 @@ +uid://dxpf6nsijqq1d diff --git a/Scripts/DSL/Nodes/ForNode.cs b/Scripts/DSL/Nodes/ForNode.cs new file mode 100644 index 0000000..4ae0ba4 --- /dev/null +++ b/Scripts/DSL/Nodes/ForNode.cs @@ -0,0 +1,48 @@ +using Godot; + +public class ForNode : ProgramNode +{ + public int amountExecuted; + public int amount; + public ForNode() + { + DisplayText = "For"; + } + public override NodeResult Execute(Robot robot, double delta) + { + bool isConditionFulfilled = DetermineCondition(); + amountExecuted++; + return isConditionFulfilled? NodeResult.SUCCESS : NodeResult.CONDITIONFALSE; + } + + private bool DetermineCondition() + { + return amountExecuted < amount; + } + + public override void ReadParameters(NodeDisplay display) + { + HBoxContainer valueContainer = display.GetNode("./EditorDisplay/HBoxContainer/"); + amount = (int)valueContainer.GetNode("./Amount").Value; + } + + public override ProgramNode Duplicate() + { + ForNode duplicate = new ForNode() + { + amount = amount, + amountExecuted = 0 + }; + return duplicate; + } + + public override void Setup(NodeDisplay display) + { + + } + + public override string Save() + { + return $"Name: {DisplayText}, AmountExecuted: {amountExecuted}, Amount: {amount}"; + } +} diff --git a/Scripts/DSL/Nodes/ForNode.cs.uid b/Scripts/DSL/Nodes/ForNode.cs.uid new file mode 100644 index 0000000..2732624 --- /dev/null +++ b/Scripts/DSL/Nodes/ForNode.cs.uid @@ -0,0 +1 @@ +uid://s1gp2fdow25r diff --git a/Scripts/DSL/Nodes/HarvestNode.cs b/Scripts/DSL/Nodes/HarvestNode.cs index 1aa2514..96d791c 100644 --- a/Scripts/DSL/Nodes/HarvestNode.cs +++ b/Scripts/DSL/Nodes/HarvestNode.cs @@ -30,6 +30,10 @@ public class HarvestNode : ProgramNode lastExecutionMessage = "Not enough space"; return NodeResult.FAILURE; } + else + { + return NodeResult.SUCCESS; + } } return NodeResult.RUNNING; } diff --git a/Scripts/DSL/Nodes/IfNode.cs b/Scripts/DSL/Nodes/IfNode.cs new file mode 100644 index 0000000..66b423a --- /dev/null +++ b/Scripts/DSL/Nodes/IfNode.cs @@ -0,0 +1,111 @@ +using Godot; + +public class IfNode : ProgramNode +{ + public Item selectedItem; + public int amount; + public string comparator; + public IfNode() + { + DisplayText = "If"; + } + public override NodeResult Execute(Robot robot, double delta) + { + if (selectedItem == null) + { + lastExecutionMessage = "No Item selected"; + return NodeResult.FAILURE; + } + + bool isConditionFulfilled = DetermineCondition(); + return isConditionFulfilled? NodeResult.SUCCESS : NodeResult.CONDITIONFALSE; + } + + private bool DetermineCondition() + { + int inventoryAmount = GameData.inventory.GetItemAmount(selectedItem.data.Id); + switch (comparator) + { + case "is bigger than": + return inventoryAmount > amount; + case "is less than": + return inventoryAmount < amount; + case "is not": + return inventoryAmount != amount; + case "is less than or equal to": + return inventoryAmount <= amount; + case "is bigger than or equal to": + return inventoryAmount >= amount; + default: + return inventoryAmount == amount; + } + } + + public override void ReadParameters(NodeDisplay display) + { + HBoxContainer valueContainer = display.GetNode("./EditorDisplay/HBoxContainer/"); + OptionButton items = valueContainer.GetNode("./Item"); + string readableItem = items.GetItemText(items.GetSelectedId()).Split(":")[0]; + if (GameData.availableItems.ContainsKey(ItemData.GetIndex(readableItem))) + { + selectedItem = new Item { data = GameData.availableItems[ItemData.GetIndex(readableItem)] }; + } + amount = (int)valueContainer.GetNode("./Amount").Value; + + OptionButton comparators = valueContainer.GetNode("./Comparator"); + comparator = comparators.GetItemText(comparators.GetSelectedId()); + } + + public override ProgramNode Duplicate() + { + IfNode duplicate = new IfNode() + { + selectedItem = selectedItem, + amount = amount, + comparator = comparator + }; + return duplicate; + } + + public override void Setup(NodeDisplay display) + { + OptionButton options = display.GetNode("./EditorDisplay/HBoxContainer/Item"); + options.AddItem("Select item..."); + foreach (ItemData item in GameData.availableItems.Values) + { + if (GameData.availableResearch[item.Research].state != ResearchState.RESEARCHED) continue; + options.AddItem(item.GetReadableName()); + } + + if (selectedItem != null) + { + for (int i = 0; i < options.ItemCount; i++) + { + if (ItemData.GetIndex(options.GetItemText(i).Split(":")[0]) == selectedItem.data.Id) + { + options.Select(i); + break; + } + } + } + + OptionButton comparators = display.GetNode("./EditorDisplay/HBoxContainer/Comparator"); + + if (comparator != null) + { + for (int i = 0; i < comparators.ItemCount; i++) + { + if (comparators.GetItemText(i) == comparator) + { + comparators.Select(i); + break; + } + } + } + } + + public override string Save() + { + return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}"; + } +} diff --git a/Scripts/DSL/Nodes/IfNode.cs.uid b/Scripts/DSL/Nodes/IfNode.cs.uid new file mode 100644 index 0000000..7b21bd5 --- /dev/null +++ b/Scripts/DSL/Nodes/IfNode.cs.uid @@ -0,0 +1 @@ +uid://cosidbtpmcj16 diff --git a/Scripts/DSL/Nodes/ProgramNode.cs b/Scripts/DSL/Nodes/ProgramNode.cs index 091c1e7..ae57f0b 100644 --- a/Scripts/DSL/Nodes/ProgramNode.cs +++ b/Scripts/DSL/Nodes/ProgramNode.cs @@ -3,6 +3,7 @@ using Godot; public abstract class ProgramNode { public ProgramNode nextNode; + public ProgramNode previousNode; public string DisplayText; public string lastExecutionMessage; diff --git a/Scripts/DSL/Nodes/UntilNode.cs b/Scripts/DSL/Nodes/UntilNode.cs new file mode 100644 index 0000000..f4a76ae --- /dev/null +++ b/Scripts/DSL/Nodes/UntilNode.cs @@ -0,0 +1,32 @@ +using Godot; + +public class UntilNode : ProgramNode +{ + public UntilNode() + { + DisplayText = "Until"; + } + public override NodeResult Execute(Robot robot, double delta) + { + return NodeResult.SUCCESS; + } + + public override void ReadParameters(NodeDisplay display) + { + } + + public override ProgramNode Duplicate() + { + UntilNode duplicate = new UntilNode(); + return duplicate; + } + + public override void Setup(NodeDisplay display) + { + } + + public override string Save() + { + return $"Name: {DisplayText}"; + } +} diff --git a/Scripts/DSL/Nodes/UntilNode.cs.uid b/Scripts/DSL/Nodes/UntilNode.cs.uid new file mode 100644 index 0000000..f32e926 --- /dev/null +++ b/Scripts/DSL/Nodes/UntilNode.cs.uid @@ -0,0 +1 @@ +uid://cq0j38wd84pc7 diff --git a/Scripts/DSL/Nodes/WhileNode.cs b/Scripts/DSL/Nodes/WhileNode.cs new file mode 100644 index 0000000..a246f00 --- /dev/null +++ b/Scripts/DSL/Nodes/WhileNode.cs @@ -0,0 +1,113 @@ +using Godot; + +public class WhileNode : ProgramNode +{ + public Item selectedItem; + public int amount; + public string comparator; + public WhileNode() + { + DisplayText = "While"; + } + public override NodeResult Execute(Robot robot, double delta) + { + + if (selectedItem == null) + { + lastExecutionMessage = "No Item selected"; + return NodeResult.FAILURE; + } + + bool isConditionFulfilled = DetermineCondition(); + return isConditionFulfilled? NodeResult.SUCCESS : NodeResult.CONDITIONFALSE; + } + + private bool DetermineCondition() + { + int inventoryAmount = GameData.inventory.GetItemAmount(selectedItem.data.Id); + switch (comparator) + { + case "is bigger than": + return inventoryAmount > amount; + case "is less than": + return inventoryAmount < amount; + case "is not": + return inventoryAmount != amount; + case "is less than or equal to": + return inventoryAmount <= amount; + case "is bigger than or equal to": + return inventoryAmount >= amount; + default: + return inventoryAmount == amount; + } + } + + public override void ReadParameters(NodeDisplay display) + { + HBoxContainer valueContainer = display.GetNode("./EditorDisplay/HBoxContainer/"); + OptionButton items = valueContainer.GetNode("./Item"); + + string readableItem = items.GetItemText(items.GetSelectedId()).Split(":")[0]; + if (GameData.availableItems.ContainsKey(ItemData.GetIndex(readableItem))) + { + selectedItem = new Item { data = GameData.availableItems[ItemData.GetIndex(readableItem)] }; + } + amount = (int)valueContainer.GetNode("./Amount").Value; + + OptionButton comparators = valueContainer.GetNode("./Comparator"); + comparator = comparators.GetItemText(comparators.GetSelectedId()); + } + + public override ProgramNode Duplicate() + { + WhileNode duplicate = new WhileNode() + { + selectedItem = selectedItem, + amount = amount, + comparator = comparator + }; + return duplicate; + } + + public override void Setup(NodeDisplay display) + { + OptionButton options = display.GetNode("./EditorDisplay/HBoxContainer/Item"); + options.AddItem("Select item..."); + foreach (ItemData item in GameData.availableItems.Values) + { + if (GameData.availableResearch[item.Research].state != ResearchState.RESEARCHED) continue; + options.AddItem(item.GetReadableName()); + } + + if (selectedItem != null) + { + for (int i = 0; i < options.ItemCount; i++) + { + if (ItemData.GetIndex(options.GetItemText(i).Split(":")[0]) == selectedItem.data.Id) + { + options.Select(i); + break; + } + } + } + + OptionButton comparators = display.GetNode("./EditorDisplay/HBoxContainer/Comparator"); + + if (comparator != null) + { + for (int i = 0; i < comparators.ItemCount; i++) + { + if (comparators.GetItemText(i) == comparator) + { + comparators.Select(i); + break; + } + } + } + } + + public override string Save() + { + return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}"; + } +} diff --git a/Scripts/DSL/Nodes/WhileNode.cs.uid b/Scripts/DSL/Nodes/WhileNode.cs.uid new file mode 100644 index 0000000..4e67bee --- /dev/null +++ b/Scripts/DSL/Nodes/WhileNode.cs.uid @@ -0,0 +1 @@ +uid://hmecauiiaggc diff --git a/Scripts/Gameplay/Research/Research.cs b/Scripts/Gameplay/Research/Research.cs index e438eda..22c2888 100644 --- a/Scripts/Gameplay/Research/Research.cs +++ b/Scripts/Gameplay/Research/Research.cs @@ -8,7 +8,7 @@ public class Research public Research(ResearchData data) { this.data = data; - state = ResearchState.UNDEFINED; + state = data.Id == "basics" ? ResearchState.RESEARCHED : ResearchState.UNDEFINED; } public ResearchResult Execute(double delta) diff --git a/Scripts/Gameplay/Robots/Robot.cs b/Scripts/Gameplay/Robots/Robot.cs index a42f317..8a5999f 100644 --- a/Scripts/Gameplay/Robots/Robot.cs +++ b/Scripts/Gameplay/Robots/Robot.cs @@ -36,7 +36,23 @@ public partial class Robot : Node3D switch (currentNode.Execute(this, delta)) { case NodeResult.SUCCESS: - currentNode = currentNode.nextNode; + if (currentNode.DisplayText == "Until") + { + while (true) + { + currentNode = currentNode.previousNode; + if (currentNode == null) + { + isExecuting = false; + break; + } + if (currentNode.DisplayText == "For" || currentNode.DisplayText == "While") break; + } + } + else + { + currentNode = currentNode.nextNode; + } if (currentNode == null) { isExecuting = false; @@ -51,6 +67,36 @@ public partial class Robot : Node3D case NodeResult.RUNNING: currentMessage = ""; break; + case NodeResult.CONDITIONFALSE: + string sourceNode = currentNode.DisplayText; + while (true) + { + currentNode = currentNode.nextNode; + if (currentNode == null) + { + isExecuting = false; + break; + } + if (sourceNode == "If") + { + if (currentNode.DisplayText == "If" || currentNode.DisplayText == "Else") break; + } + else + { + if (currentNode.DisplayText == "While" || currentNode.DisplayText == "For" || currentNode.DisplayText == "Until") + { + if (currentNode.nextNode == null) + { + isExecuting = false; + break; + } + currentNode = currentNode.nextNode; + break; + } + } + + } + break; } } } diff --git a/Scripts/UI/DSL/CodingWindow.cs b/Scripts/UI/DSL/CodingWindow.cs index 6a733e0..f0f7ff4 100644 --- a/Scripts/UI/DSL/CodingWindow.cs +++ b/Scripts/UI/DSL/CodingWindow.cs @@ -112,6 +112,10 @@ public partial class CodingWindow : PanelContainer { nodes[i - 1].nextNode = nodes[i]; } + if (i > 0) + { + nodes[i].previousNode = nodes[i-1]; + } } if (robot == null) return; diff --git a/Scripts/UI/DSL/NodeDisplay.cs b/Scripts/UI/DSL/NodeDisplay.cs index b57c3cb..5c4de3a 100644 --- a/Scripts/UI/DSL/NodeDisplay.cs +++ b/Scripts/UI/DSL/NodeDisplay.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Godot; @@ -68,6 +69,26 @@ public partial class NodeDisplay : PanelContainer result.node = new CraftNode(); result.LoadCraft(nodeSanitized); break; + case "while": + result.node = new WhileNode(); + result.LoadWhile(nodeSanitized); + break; + case "until": + result.node = new UntilNode(); + result.LoadUntil(nodeSanitized); + break; + case "for": + result.node = new ForNode(); + result.LoadFor(nodeSanitized); + break; + case "if": + result.node = new IfNode(); + result.LoadIf(nodeSanitized); + break; + case "else": + result.node = new ElseNode(); + result.LoadElse(nodeSanitized); + break; default: result.QueueFree(); return null; @@ -76,6 +97,62 @@ public partial class NodeDisplay : PanelContainer return result; } + private void LoadElse(string content) { } + + private void LoadIf(string content) + { + HBoxContainer valueContainer = GetNode("./EditorDisplay/HBoxContainer/"); + string[] parts = content.Split(","); + string itemString = parts[1].Replace("Item:", "").Trim(); + string comparatorString = parts[2].Replace("Comparator:", "").Trim(); + if (itemString.ToLower() != "empty") + { + IfNode ifNode = node as IfNode; + if (ifNode != null) + { + ifNode.selectedItem = new Item { data = GameData.availableItems[itemString] }; + ifNode.comparator = comparatorString; + } + } + string amountString = parts[3].Replace("Amount:", "").Trim(); + valueContainer.GetNode("./Amount").Value = int.Parse(amountString); + } + + private void LoadFor(string content) + { + HBoxContainer valueContainer = GetNode("./EditorDisplay/HBoxContainer/"); + string[] parts = content.Split(","); + string amountExecuted = parts[1].Replace("AmountExecuted:", "").Trim(); + ForNode forNode = node as ForNode; + if (forNode != null) + { + forNode.amountExecuted = int.Parse(amountExecuted); + } + string amountString = parts[2].Replace("Amount:", "").Trim(); + valueContainer.GetNode("./Amount").Value = int.Parse(amountString); + } + + private void LoadUntil(string content) { } + + private void LoadWhile(string content) + { + HBoxContainer valueContainer = GetNode("./EditorDisplay/HBoxContainer/"); + string[] parts = content.Split(","); + string itemString = parts[1].Replace("Item:", "").Trim(); + string comparatorString = parts[2].Replace("Comparator:", "").Trim(); + if (itemString.ToLower() != "empty") + { + WhileNode whileNode = node as WhileNode; + if (whileNode != null) + { + whileNode.selectedItem = new Item { data = GameData.availableItems[itemString] }; + whileNode.comparator = comparatorString; + } + } + string amountString = parts[3].Replace("Amount:", "").Trim(); + valueContainer.GetNode("./Amount").Value = int.Parse(amountString); + } + private static PackedScene GetPrefab(string nodeName, Dictionary DSLNodes) { foreach (ProgramNode programNode in DSLNodes.Keys) @@ -89,15 +166,13 @@ public partial class NodeDisplay : PanelContainer return null; } - public void LoadHarvest(string content) - { - } + public void LoadHarvest(string content) { } public void LoadMove(string content) { HBoxContainer valueContainer = GetNode("./EditorDisplay/HBoxContainer/"); string[] parts = content.Split(","); - string positionValues = parts[1].Replace("Position: ", "").Replace("(", "").Replace(")", ""); + string positionValues = parts[1].Replace("Position:", "").Replace("(", "").Replace(")", "").Trim(); int posX = int.Parse(positionValues.Split("|")[0]); int posY = int.Parse(positionValues.Split("|")[1]); int posZ = int.Parse(positionValues.Split("|")[2]); @@ -112,15 +187,13 @@ public partial class NodeDisplay : PanelContainer } } - public void LoadExplore(string content) - { - } + public void LoadExplore(string content) { } public void LoadCraft(string content) { HBoxContainer valueContainer = GetNode("./EditorDisplay/HBoxContainer/"); string[] parts = content.Split(","); - string itemString = parts[1].Replace("Item: ", "").Replace(" ", ""); + string itemString = parts[1].Replace("Item:", "").Trim(); if (itemString.ToLower() != "empty") { CraftNode craftNode = node as CraftNode; @@ -129,7 +202,7 @@ public partial class NodeDisplay : PanelContainer craftNode.selectedItem = new Item { data = GameData.availableItems[itemString] }; } } - string amountString = parts[2].Replace("Amount: ", ""); + string amountString = parts[2].Replace("Amount:", "").Trim(); valueContainer.GetNode("./Amount").Value = int.Parse(amountString); } }