Changed craft times for all items,buildings, researches and added research that can change game stats/effects.

This commit is contained in:
2026-05-09 13:27:01 +02:00
parent 9f32152fb8
commit 677d8595db
14 changed files with 828 additions and 477 deletions
+2 -1
View File
@@ -15,12 +15,13 @@ public partial class GameData
public static bool canMove = true;
public static int maxRobotCount = 1000;
public static List<Robot> robots = new List<Robot>();
public static float robotSpeed = 20f;
public static float robotSpeed = 10f;
public static float tileWidth = 6;
public static float tileHeight = 4;
public static SortedDictionary<string, ItemData> availableItems = ResourceLoader.LoadItems();
public static Dictionary<string, Research> availableResearch = ResourceLoader.LoadResearch();
public static SurvivalState survival = new SurvivalState();
public static RobotStats robotStats = new RobotStats();
public static Color primaryColor = new Color("#276ac2");
public static Color lightColor = new Color("#7efff5");
+9 -2
View File
@@ -25,13 +25,20 @@ public class Research
elapsedResearchTime += delta;
if (elapsedResearchTime >= data.CraftTime)
{
state = ResearchState.RESEARCHED;
Complete();
return ResearchResult.FINISHED;
}
return ResearchResult.RESEARCHING;
}
public void Complete()
{
if (state == ResearchState.RESEARCHED) return;
state = ResearchState.RESEARCHED;
GameData.robotStats.Apply(data.Effects);
}
public static string GetReadableName(string input)
{
string noUnderscore = input.Replace("_", " ").ToLower();
@@ -18,6 +18,9 @@ public class ResearchData
[JsonPropertyName("texture")]
public string Texture { get; set; }
[JsonPropertyName("effects")]
public List<ResearchEffect> Effects { get; set; }
public string GetReadableName()
{
string noUnderscore = Id.Replace("_", " ").ToLower();
@@ -0,0 +1,24 @@
using System.Text.Json.Serialization;
public class ResearchEffect
{
[JsonPropertyName("stat")]
public string Stat { get; set; }
[JsonPropertyName("value")]
public float Value { get; set; }
public string GetDisplayText()
{
return Stat switch
{
"robot_speed_bonus" => $"Robot speed +{Value * 100f:0}%",
"robot_energy_use_reduction" => $"Robot energy use -{Value * 100f:0}%",
"robot_heat_gain_reduction" => $"Robot heat gain -{Value * 100f:0}%",
"robot_cooling_bonus" => $"Robot cooling +{Value * 100f:0}%",
"robot_maintenance_loss_reduction" => $"Robot maintenance loss -{Value * 100f:0}%",
"robot_minimum_efficiency_bonus" => $"Damaged robot efficiency +{Value * 100f:0}%",
_ => Stat
};
}
}
@@ -0,0 +1 @@
uid://c6k1b1inavgyj
+2 -1
View File
@@ -3,5 +3,6 @@ public enum ResearchState
UNDEFINED,
RESEARCHED,
AVAILABLE,
LOCKED
LOCKED,
RESEARCHING
}
+8 -7
View File
@@ -49,7 +49,7 @@ public partial class Robot : Node3D
}
else if (currentMessage.Length <= 0)
{
CoolDown(delta, IdleHeatLossPerSecond);
CoolDown(delta, GameData.robotStats.GetCoolingRate(IdleHeatLossPerSecond));
currentMessage = "No script executing";
}
@@ -68,7 +68,7 @@ public partial class Robot : Node3D
public float GetMovementSpeed()
{
return GameData.robotSpeed * GetWorkEfficiency();
return GameData.robotStats.GetMovementSpeed(GameData.robotSpeed) * GetWorkEfficiency();
}
public float GetWorkEfficiency()
@@ -76,7 +76,8 @@ public partial class Robot : Node3D
if (isBroken) return 0f;
if (maintenance >= 50f) return 1f;
return Math.Clamp(0.35f + maintenance / 100f, 0.35f, 1f);
float minimumEfficiency = GameData.robotStats.GetMinimumEfficiency();
return Math.Clamp(minimumEfficiency + maintenance / 100f, minimumEfficiency, 1f);
}
public void Maintain()
@@ -102,19 +103,19 @@ public partial class Robot : Node3D
if (isCoolingDown)
{
CoolDown(delta, ActiveHeatLossPerSecond);
CoolDown(delta, GameData.robotStats.GetCoolingRate(ActiveHeatLossPerSecond));
currentMessage = $"Cooling down ({heat:0}%)";
return false;
}
if (!GameData.survival.TryConsumeEnergy(EnergyUsePerSecond * (float)delta))
if (!GameData.survival.TryConsumeEnergy(GameData.robotStats.GetEnergyUse(EnergyUsePerSecond) * (float)delta))
{
currentMessage = "Not enough energy";
return false;
}
heat = Math.Clamp(heat + HeatGainPerSecond * (float)delta, 0f, 100f);
maintenance = Math.Clamp(maintenance - MaintenanceLossPerSecond * (float)delta, 0f, 100f);
heat = Math.Clamp(heat + GameData.robotStats.GetHeatGain(HeatGainPerSecond) * (float)delta, 0f, 100f);
maintenance = Math.Clamp(maintenance - GameData.robotStats.GetMaintenanceLoss(MaintenanceLossPerSecond) * (float)delta, 0f, 100f);
if (heat >= 100f)
{
+81
View File
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
public class RobotStats
{
private const float BaseMinimumEfficiency = 0.35f;
private float speedBonus = 0f;
private float energyUseReduction = 0f;
private float heatGainReduction = 0f;
private float coolingBonus = 0f;
private float maintenanceLossReduction = 0f;
private float minimumEfficiencyBonus = 0f;
public float GetMovementSpeed(float baseSpeed)
{
return baseSpeed * (1f + speedBonus);
}
public float GetEnergyUse(float baseEnergyUse)
{
return baseEnergyUse * (1f - Math.Clamp(energyUseReduction, 0f, 0.8f));
}
public float GetHeatGain(float baseHeatGain)
{
return baseHeatGain * (1f - Math.Clamp(heatGainReduction, 0f, 0.8f));
}
public float GetCoolingRate(float baseCoolingRate)
{
return baseCoolingRate * (1f + coolingBonus);
}
public float GetMaintenanceLoss(float baseMaintenanceLoss)
{
return baseMaintenanceLoss * (1f - Math.Clamp(maintenanceLossReduction, 0f, 0.8f));
}
public float GetMinimumEfficiency()
{
return Math.Clamp(BaseMinimumEfficiency + minimumEfficiencyBonus, BaseMinimumEfficiency, 0.85f);
}
public void Apply(List<ResearchEffect> effects)
{
if (effects == null) return;
foreach (ResearchEffect effect in effects)
{
Apply(effect);
}
}
private void Apply(ResearchEffect effect)
{
if (effect == null) return;
switch (effect.Stat)
{
case "robot_speed_bonus":
speedBonus += effect.Value;
break;
case "robot_energy_use_reduction":
energyUseReduction += effect.Value;
break;
case "robot_heat_gain_reduction":
heatGainReduction += effect.Value;
break;
case "robot_cooling_bonus":
coolingBonus += effect.Value;
break;
case "robot_maintenance_loss_reduction":
maintenanceLossReduction += effect.Value;
break;
case "robot_minimum_efficiency_bonus":
minimumEfficiencyBonus += effect.Value;
break;
}
}
}
@@ -0,0 +1 @@
uid://djuorq37m01xc
+57 -3
View File
@@ -1,5 +1,7 @@
using Godot;
using Godot.Collections;
using System.Collections.Generic;
using System.Text;
public partial class ResearchList : PanelContainer
{
@@ -7,12 +9,33 @@ public partial class ResearchList : PanelContainer
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)
{
if (research.Execute(delta) == ResearchResult.FINISHED)
{
toDelete.Add(research);
RecalculateResearchStates();
SetupGraph();
}
}
foreach (Research delete in toDelete)
{
currentResearch.Remove(delete);
}
}
public void SetupGraph()
{
RememberNodePositions();
@@ -98,6 +121,7 @@ public partial class ResearchList : PanelContainer
{
Texture2D texture = GD.Load<Texture2D>(texturePath);
Color stateColor = GetColorByState(state);
string tooltipText = GetResearchTooltip(GameData.availableResearch[id]);
TextureRect icon = new TextureRect
{
@@ -110,7 +134,8 @@ public partial class ResearchList : PanelContainer
Button button = new Button
{
Text = "Research",
Disabled = state != ResearchState.AVAILABLE
Disabled = state != ResearchState.AVAILABLE,
TooltipText = tooltipText
};
button.Pressed += () => OnResearchPressed(id);
@@ -119,7 +144,8 @@ public partial class ResearchList : PanelContainer
{
Name = id,
Title = Research.GetReadableName(id),
SelfModulate = stateColor
SelfModulate = stateColor,
TooltipText = tooltipText
};
if (nodePositions.ContainsKey(id))
@@ -145,11 +171,33 @@ public partial class ResearchList : PanelContainer
private void OnResearchPressed(string id)
{
GameData.availableResearch[id].state = ResearchState.RESEARCHED;
GameData.availableResearch[id].state = ResearchState.RESEARCHING;
currentResearch.Add(GameData.availableResearch[id]);
RecalculateResearchStates();
SetupGraph();
}
private string GetResearchTooltip(Research research)
{
if (research.data.Effects == null || research.data.Effects.Count <= 0)
{
return Research.GetReadableName(research.data.Id);
}
StringBuilder tooltip = new StringBuilder(Research.GetReadableName(research.data.Id));
tooltip.AppendLine();
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;
@@ -182,6 +230,11 @@ public partial class ResearchList : PanelContainer
return ResearchState.RESEARCHED;
}
if (research.state == ResearchState.RESEARCHING)
{
return ResearchState.RESEARCHING;
}
if (GameData.availableResearch[research.data.Research].state == ResearchState.RESEARCHED)
{
return ResearchState.AVAILABLE;
@@ -197,6 +250,7 @@ public partial class ResearchList : PanelContainer
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
};
}
+1
View File
@@ -94,6 +94,7 @@ public partial class World : Node3D
private void ResetRunState()
{
survival = new SurvivalState();
robotStats = new RobotStats();
inventory = new Inventory();
availableResearch = ResourceLoader.LoadResearch();
robots.Clear();