1 Commits

Author SHA1 Message Date
Nicola ad65698773 Merge pull request 'Finished first EA Version' (#1) from dev into main
Reviewed-on: #1
2026-05-19 20:01:10 +02:00
24 changed files with 63 additions and 388 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
-7
View File
@@ -15,10 +15,3 @@ script = ExtResource("2_j80uv")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1405728816]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.05883789, 0.29821777, -0.01171875)
shape = SubResource("BoxShape3D_vquur")
[node name="SpotLight3D" type="SpotLight3D" parent="." unique_id=1638370223]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.37939095, -0.31055498)
light_energy = 16.0
spot_range = 4.0
spot_attenuation = 0.0
spot_angle = 75.0
-24
View File
@@ -96,28 +96,4 @@ public class RobotSaveData
public float Maintenance { get; set; }
public bool IsCoolingDown { get; set; }
public bool IsBroken { get; set; }
public List<NodeSaveData> RunningProgramNodes { get; set; }
public string ProgramStartNode { get; set; }
public string CurrentNode { get; set; }
public bool IsExecuting { get; set; }
}
public class NodeSaveData
{
public string NodeType { get; set; }
public string EditorNodeId { get; set; }
public string NextEditorNodeId { get; set; }
public string NegativeEditorNodeId { get; set; }
public string NodeContent { get; set; }
public string LastExecutionMessage { get; set; }
public string ItemId { get; set; }
public string Comparator { get; set; }
public int Amount { get; set; }
public int AmountExecuted { get; set; }
public double ElapsedCraftTime { get; set; }
public int AmountCrafted { get; set; }
public bool HasTargetPosition { get; set; }
public int TargetX { get; set; }
public int TargetY { get; set; }
public int TargetZ { get; set; }
}
+1
View File
@@ -137,6 +137,7 @@ public static class SaveGameDataApplier
Tile tile = layer.tiles[savedTile.X, savedTile.Y];
tile.collapsedMesh = savedTile.CollapsedMesh;
tile.containsLight = savedTile.ContainsLight;
tile.containsDecoration = savedTile.ContainsDecoration;
tile.containsResource = savedTile.ContainsResource;
tile.wasVisited = savedTile.WasVisited;
+1
View File
@@ -135,6 +135,7 @@ public static class SaveGameDataFactory
X = tile.GridPosition.X,
Y = tile.GridPosition.Y,
CollapsedMesh = tile.collapsedMesh,
ContainsLight = tile.containsLight,
ContainsDecoration = tile.containsDecoration,
ContainsResource = tile.containsResource,
WasVisited = tile.wasVisited,
-28
View File
@@ -55,32 +55,4 @@ public class CraftNode : ProgramNode
{
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Amount = amount;
if (selectedItem != null)
{
saveData.ElapsedCraftTime = selectedItem.elapsedCraftTime;
saveData.AmountCrafted = selectedItem.amountCrafted;
}
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item
{
data = GameData.availableItems[saveData.ItemId],
elapsedCraftTime = saveData.ElapsedCraftTime,
amountCrafted = saveData.AmountCrafted
};
}
}
+4 -30
View File
@@ -7,7 +7,6 @@ public class ExploreNode : ProgramNode
public Vector3 startPosition;
public Vector3I targetPosition;
public List<Vector3> pathPoints;
public bool hasTargetPosition;
public ExploreNode()
{
@@ -17,7 +16,7 @@ public class ExploreNode : ProgramNode
public override NodeResult Execute(Robot robot, double delta)
{
if (pathPoints == null && !hasTargetPosition && !TrySelectTarget())
if (pathPoints == null && !TrySelectTarget())
{
lastExecutionMessage = "No tiles left to explore";
return NodeResult.SUCCESS;
@@ -42,18 +41,18 @@ public class ExploreNode : ProgramNode
private bool TrySelectTarget()
{
int safetyCounter = 0;
int layerRange = Math.Max(GameData.lowestLayer, 1);
int maximumAttempts = (int)Math.Pow(GameData.layerSize, 2) * 2;
while (safetyCounter <= maximumAttempts)
{
targetPosition = new Vector3I(
GameData.rand.Next(GameData.layerSize),
GameData.rand.Next(GameData.lowestLayer + 1),
GameData.rand.Next(layerRange),
GameData.rand.Next(GameData.layerSize)
);
if (!GameData.map[targetPosition.Y].tiles[targetPosition.X, targetPosition.Z].wasVisited)
{
hasTargetPosition = true;
return true;
}
@@ -96,7 +95,6 @@ public class ExploreNode : ProgramNode
lastExecutionMessage = "Current exploration finished";
pathPoints = null;
hasTargetPosition = false;
return NodeResult.RUNNING;
}
@@ -122,8 +120,7 @@ public class ExploreNode : ProgramNode
{
return new ExploreNode
{
targetPosition = targetPosition,
hasTargetPosition = hasTargetPosition
targetPosition = targetPosition
};
}
@@ -131,27 +128,4 @@ public class ExploreNode : ProgramNode
{
return $"Name: {DisplayText}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.TargetX = targetPosition.X;
saveData.TargetY = targetPosition.Y;
saveData.TargetZ = targetPosition.Z;
saveData.HasTargetPosition = hasTargetPosition || pathPoints != null;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
hasTargetPosition = saveData.HasTargetPosition;
if (!hasTargetPosition) return;
targetPosition = new Vector3I(
saveData.TargetX,
saveData.TargetY,
saveData.TargetZ
);
}
}
+2 -17
View File
@@ -14,12 +14,12 @@ public class ForNode : ProgramNode
public override NodeResult Execute(Robot robot, double delta)
{
bool isConditionFulfilled = DetermineCondition();
amountExecuted++;
if (isConditionFulfilled)
{
amountExecuted = 0;
}
amountExecuted++;
return isConditionFulfilled ? NodeResult.CONDITIONFALSE : NodeResult.SUCCESS;
return isConditionFulfilled ? NodeResult.SUCCESS : NodeResult.CONDITIONFALSE;
}
private bool DetermineCondition()
@@ -42,21 +42,6 @@ public class ForNode : ProgramNode
return $"Name: {DisplayText}, AmountExecuted: {amountExecuted}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.Amount = amount;
saveData.AmountExecuted = amountExecuted;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
amountExecuted = saveData.AmountExecuted;
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes
-20
View File
@@ -60,26 +60,6 @@ public class IfNode : ProgramNode
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Comparator = comparator;
saveData.Amount = amount;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
comparator = saveData.Comparator;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item { data = GameData.availableItems[saveData.ItemId] };
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes
-22
View File
@@ -98,26 +98,4 @@ public class MoveNode : ProgramNode
{
return $"Name: {DisplayText}, Position: ({targetPosition.X}|{targetPosition.Y}|{targetPosition.Z})";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.TargetX = targetPosition.X;
saveData.TargetY = targetPosition.Y;
saveData.TargetZ = targetPosition.Z;
saveData.HasTargetPosition = true;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
if (!saveData.HasTargetPosition) return;
targetPosition = new Vector3I(
saveData.TargetX,
saveData.TargetY,
saveData.TargetZ
);
}
}
-57
View File
@@ -14,52 +14,6 @@ public abstract class ProgramNode
public abstract ProgramNode Duplicate();
public abstract string Save();
public virtual NodeSaveData CreateSaveData()
{
return new NodeSaveData
{
NodeType = DisplayText,
EditorNodeId = EditorNodeId,
NextEditorNodeId = nextNode?.EditorNodeId,
NegativeEditorNodeId = NegativeNode?.EditorNodeId,
NodeContent = Save(),
LastExecutionMessage = lastExecutionMessage
};
}
public virtual void Load(NodeSaveData saveData)
{
EditorNodeId = saveData.EditorNodeId;
lastExecutionMessage = saveData.LastExecutionMessage;
}
public void RestoreConnections(
NodeSaveData saveData,
Dictionary<string, ProgramNode> availableNodes
)
{
nextNode = GetSavedConnection(saveData.NextEditorNodeId, availableNodes);
NegativeNode = GetSavedConnection(saveData.NegativeEditorNodeId, availableNodes);
}
public static ProgramNode CreateFromSaveData(NodeSaveData saveData)
{
return saveData.NodeType?.ToLower() switch
{
"start" => new StartNode(),
"move" => new MoveNode(),
"explore" => new ExploreNode(),
"harvest" => new HarvestNode(),
"craft" => new CraftNode(),
"if" => new IfNode(),
"while" => new WhileNode(),
"for" => new ForNode(),
"maintain" => new MaintainNode(),
"sacrifice" => new SacrificeNode(),
_ => null
};
}
public ProgramNode DuplicateForRuntime(string editorNodeId)
{
ProgramNode duplicate = Duplicate();
@@ -111,15 +65,4 @@ public abstract class ProgramNode
return availableNodes[nodeName];
}
private ProgramNode GetSavedConnection(
string nodeId,
Dictionary<string, ProgramNode> availableNodes
)
{
if (string.IsNullOrEmpty(nodeId)) return null;
if (!availableNodes.ContainsKey(nodeId)) return null;
return availableNodes[nodeId];
}
}
-20
View File
@@ -60,26 +60,6 @@ public class WhileNode : ProgramNode
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
}
public override NodeSaveData CreateSaveData()
{
NodeSaveData saveData = base.CreateSaveData();
saveData.ItemId = selectedItem?.data.Id;
saveData.Comparator = comparator;
saveData.Amount = amount;
return saveData;
}
public override void Load(NodeSaveData saveData)
{
base.Load(saveData);
amount = saveData.Amount;
comparator = saveData.Comparator;
if (string.IsNullOrEmpty(saveData.ItemId)) return;
if (!GameData.availableItems.ContainsKey(saveData.ItemId)) return;
selectedItem = new Item { data = GameData.availableItems[saveData.ItemId] };
}
public override void SetNextNode(
List<Godot.Collections.Dictionary> connections,
Dictionary<StringName, ProgramNode> availableNodes
+1 -82
View File
@@ -23,7 +23,6 @@ public partial class Robot : Node3D
public bool isBroken = false;
public string robotType = "iron_robot";
public bool showOnMap = true;
public List<ProgramNode> nodes = new List<ProgramNode>();
private RobotTypeStats TypeStats =>
GameData.robotStats.RobotTypes.TryGetValue(robotType, out RobotTypeStats stats)
@@ -108,7 +107,6 @@ public partial class Robot : Node3D
programStartNode = nodes[0];
currentNode = nodes[0];
currentMessage = "";
this.nodes = nodes;
}
public void StopExecution(string message)
@@ -175,11 +173,7 @@ public partial class Robot : Node3D
Heat = heat,
Maintenance = maintenance,
IsCoolingDown = isCoolingDown,
IsBroken = isBroken,
RunningProgramNodes = CreateProgramSaveData(),
ProgramStartNode = programStartNode?.EditorNodeId,
CurrentNode = currentNode?.EditorNodeId,
IsExecuting = isExecuting
IsBroken = isBroken
};
}
@@ -194,7 +188,6 @@ public partial class Robot : Node3D
maintenance = saveData.Maintenance;
isCoolingDown = saveData.IsCoolingDown;
isBroken = saveData.IsBroken;
LoadProgramState(saveData);
}
private bool CanExecute(double delta)
@@ -290,78 +283,4 @@ public partial class Robot : Node3D
isCoolingDown = false;
}
}
private List<NodeSaveData> CreateProgramSaveData()
{
List<NodeSaveData> result = new List<NodeSaveData>();
if (nodes == null) return result;
foreach (ProgramNode node in nodes)
{
if (node == null) continue;
result.Add(node.CreateSaveData());
}
return result;
}
private void LoadProgramState(RobotSaveData saveData)
{
nodes = new List<ProgramNode>();
programStartNode = null;
currentNode = null;
isExecuting = false;
if (saveData.RunningProgramNodes == null || saveData.RunningProgramNodes.Count <= 0)
{
return;
}
Dictionary<string, ProgramNode> loadedNodes = new Dictionary<string, ProgramNode>();
foreach (NodeSaveData nodeSaveData in saveData.RunningProgramNodes)
{
ProgramNode node = ProgramNode.CreateFromSaveData(nodeSaveData);
if (node == null) continue;
node.Load(nodeSaveData);
nodes.Add(node);
if (!string.IsNullOrEmpty(node.EditorNodeId) && !loadedNodes.ContainsKey(node.EditorNodeId))
{
loadedNodes.Add(node.EditorNodeId, node);
}
}
foreach (NodeSaveData nodeSaveData in saveData.RunningProgramNodes)
{
if (string.IsNullOrEmpty(nodeSaveData.EditorNodeId)) continue;
if (!loadedNodes.ContainsKey(nodeSaveData.EditorNodeId)) continue;
loadedNodes[nodeSaveData.EditorNodeId].RestoreConnections(nodeSaveData, loadedNodes);
}
programStartNode = GetLoadedNode(saveData.ProgramStartNode, loadedNodes);
if (programStartNode == null && nodes.Count > 0)
{
programStartNode = nodes[0];
}
currentNode = GetLoadedNode(saveData.CurrentNode, loadedNodes);
if (currentNode == null)
{
currentNode = programStartNode;
}
isExecuting = saveData.IsExecuting && currentNode != null;
}
private ProgramNode GetLoadedNode(
string nodeId,
Dictionary<string, ProgramNode> loadedNodes
)
{
if (string.IsNullOrEmpty(nodeId)) return null;
if (!loadedNodes.ContainsKey(nodeId)) return null;
return loadedNodes[nodeId];
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ public class SurvivalState
public void Update(double delta)
{
if (isDead || GameData.debugMode) return;
if (isDead) return;
elapsedSeconds += delta;
float drainModifier = IsInGracePeriod() ? 0.35f : 1f;
+3 -64
View File
@@ -23,7 +23,6 @@ public partial class TestRunner : Node
Run("Resource extraction and save data roundtrip", TestResourceSaveRoundtrip);
Run("Endless resources extract slower", TestEndlessResourcesExtractSlower);
Run("Robot save data roundtrip keeps robot state", TestRobotSaveRoundtrip);
Run("Robot save data roundtrip keeps running program", TestRobotProgramSaveRoundtrip);
Run("Maintain node consumes matching gear", TestMaintainNodeConsumesMatchingGear);
Run("Sacrifice node makes resource endless", TestSacrificeNodeMakesResourceEndless);
Run("No robot recovery detects loss", TestNoRobotRecoveryDetectsLoss);
@@ -230,66 +229,6 @@ public partial class TestRunner : Node
AssertTrue(loadedRobot.isCoolingDown, "robot cooling state");
}
private void TestRobotProgramSaveRoundtrip()
{
StartNode startNode = new StartNode { EditorNodeId = "start" };
ForNode forNode = new ForNode
{
EditorNodeId = "loop",
amount = 3,
amountExecuted = 2
};
CraftNode craftNode = new CraftNode
{
EditorNodeId = "craft",
selectedItem = new Item
{
data = GameData.availableItems["stone"],
elapsedCraftTime = 0.5,
amountCrafted = 1
},
amount = 2
};
HarvestNode harvestNode = new HarvestNode { EditorNodeId = "done" };
startNode.nextNode = forNode;
forNode.nextNode = craftNode;
forNode.NegativeNode = harvestNode;
craftNode.nextNode = forNode;
Robot robot = new Robot
{
Name = "Loop Bot",
currentProgram = "Looping",
isExecuting = true,
programStartNode = startNode,
currentNode = craftNode,
nodes = new List<ProgramNode> { startNode, forNode, craftNode, harvestNode }
};
RobotSaveData saveData = robot.CreateSaveData();
Robot loadedRobot = new Robot();
loadedRobot.LoadSaveData(saveData);
AssertTrue(loadedRobot.isExecuting, "loaded robot should still execute");
AssertEqual("craft", loadedRobot.currentNode.EditorNodeId, "current node id");
AssertEqual("start", loadedRobot.programStartNode.EditorNodeId, "start node id");
AssertEqual(4, loadedRobot.nodes.Count, "loaded node count");
ForNode loadedForNode = loadedRobot.nodes[1] as ForNode;
CraftNode loadedCraftNode = loadedRobot.nodes[2] as CraftNode;
AssertEqual(3, loadedForNode.amount, "for amount");
AssertEqual(2, loadedForNode.amountExecuted, "for amount executed");
AssertTrue(ReferenceEquals(loadedCraftNode, loadedForNode.nextNode), "for success branch");
AssertTrue(ReferenceEquals(loadedRobot.nodes[3], loadedForNode.NegativeNode), "for negative branch");
AssertTrue(ReferenceEquals(loadedForNode, loadedCraftNode.nextNode), "craft loops back");
AssertEqual("stone", loadedCraftNode.selectedItem.data.Id, "craft item");
AssertEqual(2, loadedCraftNode.amount, "craft amount");
AssertClose(0.5f, (float)loadedCraftNode.selectedItem.elapsedCraftTime, 0.001f, "craft elapsed");
AssertEqual(1, loadedCraftNode.selectedItem.amountCrafted, "craft crafted amount");
}
private void TestMaintainNodeConsumesMatchingGear()
{
Robot robot = new Robot
@@ -536,9 +475,9 @@ public partial class TestRunner : Node
amount = 2
};
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "first iteration");
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "second iteration");
AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "loop finished");
AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "first iteration");
AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "second iteration");
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "loop finished");
}
private void TestRuntimeNodeKeepsEditorIdWithoutSharingState()
-1
View File
@@ -39,7 +39,6 @@ public partial class CodingWindow : PanelContainer
if (focused is LineEdit || focused is TextEdit) return;
if (selectedNode == null) return;
if (selectedNode == highlightedNode) highlightedNode = null;
editorWindow.RemoveChild(selectedNode);
selectedNode.QueueFree();
}
+1 -2
View File
@@ -101,11 +101,10 @@ public partial class RobotList : PanelContainer
robot.Position = GameData.map[0].tiles[0, 0].Position;
robot.robotType = spawnId;
GetNode("/root/Main/World").AddChild(robot);
LightHandler.lights.Add(robot.GetNode("./SpotLight3D") as SpotLight3D);
robot.Name = $"Robot #{GameData.robots.Count}";
GameData.robots.Add(robot);
spawnId = "";
LightHandler.RedrawLights(GameData.lightColor);
ReloadRobots();
ReloadSelectableRobots();
}
-1
View File
@@ -49,7 +49,6 @@ public partial class TutorialBubble : PanelContainer
"The inventory (Default: [I]) stores everything your robots collect. Gates and research both consume items from it.",
"Each gate blocks the next layer. When you have the required items, use Open Gate in the top bar.",
"The required ingredients can be found by hovering over the Open Gate button.",
"You can swap between layers using the [Q] (up one layer) and [E] (down one layer) keys.",
"The map (Default: [M]) shows what your robots have discovered. Exploration matters because resources are hidden in the ruin.",
"Deeper layers contain more advanced resources. Unlocking the gate at the lowest point allows you to leave the ruin.",
"Be careful: resources are not endless at the beginning. Converting a robot to a drill unit with Sacrifice makes them endless.",
+3 -3
View File
@@ -3,13 +3,13 @@ using System.Collections.Generic;
public static class LightHandler
{
public static List<SpotLight3D> lights = new List<SpotLight3D>();
public static List<OmniLight3D> lights = new List<OmniLight3D>();
public static void RedrawLights(Color color)
{
List<SpotLight3D> availableLights = new List<SpotLight3D>();
List<OmniLight3D> availableLights = new List<OmniLight3D>();
foreach (SpotLight3D light in lights)
foreach (OmniLight3D light in lights)
{
if (!GodotObject.IsInstanceValid(light)) continue;
-5
View File
@@ -270,11 +270,6 @@ public partial class Map : PanelContainer
tooltipText += GetRobotTooltip(robotsOnTile, tooltipText.Length > 0);
}
if (tile.collapsedMesh == "gate" && tile.wasVisited)
{
tileTexture = AddBorder(tileTexture, Colors.Red, RobotBorderWidth);
}
texture.Texture = tileTexture;
texture.TooltipText = tooltipText;
}
+28 -2
View File
@@ -11,7 +11,7 @@ public partial class Tile
public Vector2I GridPosition;
public Node3D ContentNode;
public bool containsDecoration, containsResource;
public bool containsLight, containsDecoration, containsResource;
public GameResource resource;
public bool wasVisited;
public event EventHandler OnTileVisited;
@@ -74,6 +74,7 @@ public partial class Tile
public void Reset(Dictionary<string, MeshInstance3D> tileMeshes)
{
collapsedMesh = null;
containsLight = false;
containsDecoration = false;
containsResource = false;
resource = null;
@@ -85,11 +86,36 @@ public partial class Tile
{
foreach (Placeholder placeholder in placeholders)
{
if (containsResource && placeholder.name == "resource") SpawnResource(contentMeshes["resource"], placeholder, transform);
if (containsLight && placeholder.name == "light") SpawnLight(contentMeshes["light"], placeholder, transform);
else if (containsResource && placeholder.name == "resource") SpawnResource(contentMeshes["resource"], placeholder, transform);
else if (containsDecoration && placeholder.name != "light" && placeholder.name != "resource") SpawnDecorations(contentMeshes, placeholder, transform);
}
}
private void SpawnLight(MeshInstance3D lightMesh, Placeholder placeholder, Transform3D transform)
{
MeshInstance3D light = new MeshInstance3D
{
Mesh = lightMesh.Mesh,
Position = placeholder.transform.Origin
};
OmniLight3D lightSource = new OmniLight3D()
{
OmniAttenuation = 2f,
LightColor = GameData.lightColor,
ShadowEnabled = true,
LightEnergy = 100f,
LightIndirectEnergy = 1.5f,
OmniRange = 20f,
Position = placeholder.transform.Origin
};
lightSource.Position.MoveToward(transform.Origin, 0.1f);
LightHandler.lights.Add(lightSource);
light.AddChild(lightSource);
ContentNode.AddChild(light);
light.LookAt(transform.Origin, Vector3.Up);
}
private void SpawnResource(MeshInstance3D resourceMesh, Placeholder placeholder, Transform3D transform)
{
MeshInstance3D resource = new MeshInstance3D
+18 -2
View File
@@ -142,8 +142,6 @@ public partial class World : Node3D
robot.Position = map[0].tiles[0, 0].Position;
AddChild(robot);
robots.Add(robot);
LightHandler.lights.Add(robot.GetNode("./SpotLight3D") as SpotLight3D);
LightHandler.RedrawLights(lightColor);
}
private void SpawnSavedRobots(List<RobotSaveData> savedRobots)
@@ -195,6 +193,7 @@ public partial class World : Node3D
{
map[0].tiles[0, 0].wasVisited = true;
map[0].tiles[0, 0].containsDecoration = true;
map[0].tiles[0, 0].containsLight = true;
map[0].tiles[0, 0].containsResource = false;
map[0].tiles[0, 0].ContentNode.Visible = true;
}
@@ -235,10 +234,22 @@ public partial class World : Node3D
private void DistributeTileContent(Layer layer)
{
int currentDecoration = 0;
int currentLight = 0;
int currentResource = 0;
int posX, posY;
while (currentLight < layerSize * 3)
{
posX = rand.Next(layerSize);
posY = rand.Next(layerSize);
if (CannotContainLight(layer.tiles[posX, posY])) continue;
if (layer.tiles[posX, posY].containsLight) continue;
layer.tiles[posX, posY].containsLight = true;
currentLight++;
}
while (currentDecoration < layerSize)
{
posX = rand.Next(layerSize);
@@ -262,6 +273,11 @@ public partial class World : Node3D
}
}
private bool CannotContainLight(Tile tile)
{
return tile.collapsedMesh == "junction" || tile.collapsedMesh == "gate";
}
private void HandleRenderData(List<TileRenderData> renderData)
{
multiMeshHandler.Build(renderData);