diff --git a/Gradients/DefaultTheme.tres b/Gradients/DefaultTheme.tres new file mode 100644 index 0000000..e210ad0 --- /dev/null +++ b/Gradients/DefaultTheme.tres @@ -0,0 +1,60 @@ +[gd_resource type="Theme" load_steps=11 format=3 uid="uid://dks3mt6h14i2s"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8pucy"] + +[sub_resource type="StyleBoxLine" id="StyleBoxLine_8pucy"] +color = Color(0.12156863, 0.22745098, 0.3254902, 1) +thickness = 2 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8pucy"] +bg_color = Color(0.15294118, 0.42352942, 0.6627451, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_v3gly"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ihngy"] +content_margin_left = 10.0 +content_margin_top = 10.0 +content_margin_right = 10.0 +content_margin_bottom = 10.0 +bg_color = Color(0.15294118, 0.42352942, 0.6627451, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1l7gl"] +content_margin_left = 12.0 +content_margin_right = 12.0 +bg_color = Color(0.0414, 0.264653, 0.46, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jnd74"] +content_margin_left = 12.0 +content_margin_right = 12.0 +bg_color = Color(0.153647, 0.421958, 0.662925, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uvwpq"] +content_margin_left = 12.0 +content_margin_right = 12.0 +bg_color = Color(0.153647, 0.421958, 0.662925, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kspi0"] +content_margin_left = 12.0 +content_margin_right = 12.0 +bg_color = Color(0.0414, 0.264653, 0.46, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ynn0i"] +bg_color = Color(0.0414, 0.264653, 0.46, 1) + +[resource] +Button/styles/focus = SubResource("StyleBoxEmpty_8pucy") +HSeparator/styles/separator = SubResource("StyleBoxLine_8pucy") +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 +Panel/styles/panel = SubResource("StyleBoxFlat_8pucy") +PanelContainer/styles/panel = SubResource("StyleBoxFlat_v3gly") +TabContainer/constants/side_margin = 0 +TabContainer/styles/panel = SubResource("StyleBoxFlat_ihngy") +TabContainer/styles/tab_disabled = SubResource("StyleBoxFlat_1l7gl") +TabContainer/styles/tab_focus = SubResource("StyleBoxFlat_jnd74") +TabContainer/styles/tab_hovered = SubResource("StyleBoxFlat_uvwpq") +TabContainer/styles/tab_selected = SubResource("StyleBoxFlat_jnd74") +TabContainer/styles/tab_unselected = SubResource("StyleBoxFlat_kspi0") +TabContainer/styles/tabbar_background = SubResource("StyleBoxFlat_ynn0i") diff --git a/Gradients/OverlayBasic.tres b/Gradients/OverlayBasic.tres new file mode 100644 index 0000000..e9f875c --- /dev/null +++ b/Gradients/OverlayBasic.tres @@ -0,0 +1,8 @@ +[gd_resource type="Gradient" format=3 uid="uid://tinbxo2rfy43"] + +[resource] +interpolation_mode = 2 +interpolation_color_space = 2 +offsets = PackedFloat32Array(0, 0.68480724, 1) +colors = PackedColorArray(0.20874, 0.63, 0.2016, 0.5254902, 0.2054, 0.6535935, 0.79, 1, 1, 1, 1, 1) +metadata/_snap_count = 2 diff --git a/Gradients/OverlayBasicFontColor.tres b/Gradients/OverlayBasicFontColor.tres new file mode 100644 index 0000000..aaf8877 --- /dev/null +++ b/Gradients/OverlayBasicFontColor.tres @@ -0,0 +1,8 @@ +[gd_resource type="Gradient" format=3 uid="uid://cwib7d3acghwy"] + +[resource] +interpolation_mode = 1 +interpolation_color_space = 2 +offsets = PackedFloat32Array(0, 0.7596372, 1) +colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1) +metadata/_snap_count = 2 diff --git a/Gradients/OverlayBasicNegative.tres b/Gradients/OverlayBasicNegative.tres new file mode 100644 index 0000000..3f51e15 --- /dev/null +++ b/Gradients/OverlayBasicNegative.tres @@ -0,0 +1,8 @@ +[gd_resource type="Gradient" format=3 uid="uid://dxdol27lvcj8n"] + +[resource] +interpolation_mode = 2 +interpolation_color_space = 2 +offsets = PackedFloat32Array(0, 0.68480724, 1) +colors = PackedColorArray(0.6278897, 0.41815576, 0.8109275, 0.5254902, 0.9236453, 0.41345683, 0.37540042, 1, 1, 1, 1, 1) +metadata/_snap_count = 2 diff --git a/Gradients/ResourcesTheme.tres b/Gradients/ResourcesTheme.tres new file mode 100644 index 0000000..c1d65fa --- /dev/null +++ b/Gradients/ResourcesTheme.tres @@ -0,0 +1,21 @@ +[gd_resource type="Theme" load_steps=3 format=3 uid="uid://s3apw670qymv"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0jf1r"] +bg_color = Color(0, 0, 0, 0.65882355) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(1, 1, 1, 0.21176471) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lycib"] +bg_color = Color(1, 1, 1, 0.22352941) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.8, 0.8, 0.8, 0) + +[resource] +ProgressBar/styles/background = SubResource("StyleBoxFlat_0jf1r") +ProgressBar/styles/fill = SubResource("StyleBoxFlat_lycib") diff --git a/ResourceScripts/BuildingData.gd b/ResourceScripts/BuildingData.gd new file mode 100644 index 0000000..d1cd6d7 --- /dev/null +++ b/ResourceScripts/BuildingData.gd @@ -0,0 +1,29 @@ +extends Resource +class_name BuildingData + +enum RenderStyle { + RandomBuilding, + Full, + Outline, + Triangle, + Circles +} + +@export_group("Basic") +@export var tile_name: String +@export var area_type: GridInput.AreaType = GridInput.AreaType.Rectangle +@export var style: RenderStyle = RenderStyle.RandomBuilding +@export_color_no_alpha var color: Color + +@export_group("Fields") +@export var field_requirements: Array[FieldRequirement] = [] +@export var field_emissions: Array[FieldEmission] = [] + +@export_group("Resources") +@export var resource_requirements: Array[ResourceAmount] = [] +@export var resource_consumption: Array[ResourceAmount] = [] +@export var resource_prouction: Array[ResourceAmount] = [] +@export var resource_stockpiles: Array[ResourceAmount] = [] + +@export_group("Linkages") +@export var upgrade_paths: Array[BuildingData] = [] diff --git a/ResourceScripts/BuildingData.gd.uid b/ResourceScripts/BuildingData.gd.uid new file mode 100644 index 0000000..5fd4e56 --- /dev/null +++ b/ResourceScripts/BuildingData.gd.uid @@ -0,0 +1 @@ +uid://y688w7tmv2dr diff --git a/ResourceScripts/FieldEmission.gd b/ResourceScripts/FieldEmission.gd new file mode 100644 index 0000000..d30ef68 --- /dev/null +++ b/ResourceScripts/FieldEmission.gd @@ -0,0 +1,21 @@ +extends Resource + +class_name FieldEmission + +enum Falloff { + Linear, + Flat +} + +@export var field: Grid.Field +@export var amount: int = 10 +@export var range: float = 3 +@export var falloff: Falloff = Falloff.Linear + +func get_field_value_for_distance(distance: float) -> int: + if distance == 0: return 0 + match falloff: + Falloff.Linear: + return max(0, floor(remap(distance, 0, range, amount, 1))) + Falloff.Flat: return amount if distance <= range else 0 + return 0 diff --git a/ResourceScripts/FieldEmission.gd.uid b/ResourceScripts/FieldEmission.gd.uid new file mode 100644 index 0000000..b62543f --- /dev/null +++ b/ResourceScripts/FieldEmission.gd.uid @@ -0,0 +1 @@ +uid://cggmew2iau84h diff --git a/ResourceScripts/FieldRequirements/FieldComparison.gd b/ResourceScripts/FieldRequirements/FieldComparison.gd new file mode 100644 index 0000000..97b86e0 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldComparison.gd @@ -0,0 +1,11 @@ +class_name FieldComparison +extends FieldRequirement + +enum Operation { + LessThan, + GreaterThan +} + +@export var field_left: Grid.Field +@export var operation: Operation +@export var field_right: Grid.Field diff --git a/ResourceScripts/FieldRequirements/FieldComparison.gd.uid b/ResourceScripts/FieldRequirements/FieldComparison.gd.uid new file mode 100644 index 0000000..accf7b5 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldComparison.gd.uid @@ -0,0 +1 @@ +uid://bi1mtw4wldwbl diff --git a/ResourceScripts/FieldRequirements/FieldMax.gd b/ResourceScripts/FieldRequirements/FieldMax.gd new file mode 100644 index 0000000..a4887a3 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldMax.gd @@ -0,0 +1,5 @@ +class_name FieldMax +extends FieldRequirement + +@export var field: Grid.Field +@export var max: int = 0 diff --git a/ResourceScripts/FieldRequirements/FieldMax.gd.uid b/ResourceScripts/FieldRequirements/FieldMax.gd.uid new file mode 100644 index 0000000..e77aac9 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldMax.gd.uid @@ -0,0 +1 @@ +uid://5h2g03dsx026 diff --git a/ResourceScripts/FieldRequirements/FieldMin.gd b/ResourceScripts/FieldRequirements/FieldMin.gd new file mode 100644 index 0000000..fde3d96 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldMin.gd @@ -0,0 +1,5 @@ +class_name FieldMin +extends FieldRequirement + +@export var field: Grid.Field +@export var min: int = 0 diff --git a/ResourceScripts/FieldRequirements/FieldMin.gd.uid b/ResourceScripts/FieldRequirements/FieldMin.gd.uid new file mode 100644 index 0000000..0d0e3a0 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldMin.gd.uid @@ -0,0 +1 @@ +uid://b3ly4vy7xaynq diff --git a/ResourceScripts/FieldRequirements/FieldRange.gd b/ResourceScripts/FieldRequirements/FieldRange.gd new file mode 100644 index 0000000..27bcc5e --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldRange.gd @@ -0,0 +1,6 @@ +class_name FieldRange +extends FieldRequirement + +@export var field: Grid.Field +@export var min: int = 0 +@export var max: int = 0 diff --git a/ResourceScripts/FieldRequirements/FieldRange.gd.uid b/ResourceScripts/FieldRequirements/FieldRange.gd.uid new file mode 100644 index 0000000..d60efb8 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldRange.gd.uid @@ -0,0 +1 @@ +uid://bgq3m714l64fl diff --git a/ResourceScripts/FieldRequirements/FieldRequirement.gd b/ResourceScripts/FieldRequirements/FieldRequirement.gd new file mode 100644 index 0000000..5545ec8 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldRequirement.gd @@ -0,0 +1,39 @@ +extends Resource +class_name FieldRequirement + + +func is_satisfied_at_position(grid: Grid, pos: Vector2i) -> bool: + match self.get_script(): + FieldMin: + var req = self as FieldMin + var value = grid.get_field_value_at(req.field, pos) + var min = req.min + return value >= min + FieldMax: + var req = self as FieldMax + var value = grid.get_field_value_at(req.field, pos) + var max = req.max + return value <= max + FieldRange: + var req = self as FieldMax + var value = grid.get_field_value_at(req.field, pos) + var min = req.min + var max = req.max + return min <= value <= max + FieldComparison: + var req = self as FieldComparison + var left = grid.get_field_value_at(req.field_left, pos) + var right = grid.get_field_value_at(req.field_right, pos) + match req.operation: + FieldComparison.Operation.LessThan: left < right + FieldComparison.Operation.GreaterThan: left > right + assert(false, "Unknown Field Requirement!") + return false + + + + #var current_field_value = grid.get_field_value_at(requirement.field, tile_pos) + #if requirement.enforce_min && current_field_value < requirement.minimum: return false + #if requirement.enforce_max && current_field_value > requirement.maximum: return false + + return true diff --git a/ResourceScripts/FieldRequirements/FieldRequirement.gd.uid b/ResourceScripts/FieldRequirements/FieldRequirement.gd.uid new file mode 100644 index 0000000..1e7ec40 --- /dev/null +++ b/ResourceScripts/FieldRequirements/FieldRequirement.gd.uid @@ -0,0 +1 @@ +uid://c2winf4nct0u7 diff --git a/ResourceScripts/ResourceAmount.gd b/ResourceScripts/ResourceAmount.gd new file mode 100644 index 0000000..7bbf5aa --- /dev/null +++ b/ResourceScripts/ResourceAmount.gd @@ -0,0 +1,6 @@ +extends Resource + +class_name ResourceAmount + +@export var resource: ResourceController.ResourceType +@export var amount: int = 0 diff --git a/ResourceScripts/ResourceAmount.gd.uid b/ResourceScripts/ResourceAmount.gd.uid new file mode 100644 index 0000000..958f818 --- /dev/null +++ b/ResourceScripts/ResourceAmount.gd.uid @@ -0,0 +1 @@ +uid://nroinmreopp4 diff --git a/ResourceTracker.tscn b/ResourceTracker.tscn new file mode 100644 index 0000000..d0a32a5 --- /dev/null +++ b/ResourceTracker.tscn @@ -0,0 +1,38 @@ +[gd_scene load_steps=2 format=3 uid="uid://botck0aro5i65"] + +[ext_resource type="Script" uid="uid://cf3f8iyagxl08" path="res://Scripts/ResourceTracker.gd" id="1_qky28"] + +[node name="PanelContainer" type="PanelContainer" node_paths=PackedStringArray("bar", "name_label", "value_label", "changes")] +script = ExtResource("1_qky28") +bar = NodePath("ProgressBar") +name_label = NodePath("MarginContainer/HBoxContainer/Name") +value_label = NodePath("MarginContainer/HBoxContainer/Values") +changes = NodePath("MarginContainer/HBoxContainer/Changes") +decreased_color = Color(0.93333334, 0.39215687, 0.39215687, 1) +increased_color = Color(0.6627451, 0.7764706, 0.5647059, 1) + +[node name="ProgressBar" type="ProgressBar" parent="."] +layout_mode = 2 +size_flags_vertical = 1 +value = 50.0 +show_percentage = false + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="Name" type="Label" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +text = "Undefined" + +[node name="Values" type="Label" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Undefined" +horizontal_alignment = 1 + +[node name="Changes" type="Label" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 +text = "undefined" diff --git a/Scripts/BuildButton.gd b/Scripts/BuildButton.gd new file mode 100644 index 0000000..3b5c3cc --- /dev/null +++ b/Scripts/BuildButton.gd @@ -0,0 +1,27 @@ +extends Button +class_name BuildButton + +enum CreationAction { + Reservation, + Creation, +} + +enum CursorStyle { + Single, + Area, + Line +} + +#@export var building: Resource +@export var cursor_style: CursorStyle +@export var creation_action: CreationAction +@export var building: BuildingData + +var menu: BuildMenu + +func _ready(): + menu = Util.find_parent_type(self, BuildMenu) + text = building.tile_name + +func _pressed(): + menu.build_button_pressed(self) diff --git a/Scripts/BuildButton.gd.uid b/Scripts/BuildButton.gd.uid new file mode 100644 index 0000000..e6af8fc --- /dev/null +++ b/Scripts/BuildButton.gd.uid @@ -0,0 +1 @@ +uid://p8y4cfg2aonj diff --git a/Scripts/BuildMenu.gd b/Scripts/BuildMenu.gd new file mode 100644 index 0000000..8dcbdc6 --- /dev/null +++ b/Scripts/BuildMenu.gd @@ -0,0 +1,34 @@ +extends VBoxContainer + +class_name BuildMenu + +@export var grid_input: GridInput +@export var grid: Grid + +func build_button_pressed(button: BuildButton): + grid_input.request_area( + button.building, + request_confirmed, + request_cancelled, + GridInput.Style.Build, + button.building.area_type, + false + ) + +func tile_is_valid_at_location(building: BuildingData, tile_pos: Vector2i) -> bool: + for requirement in building.field_requirements: + if !requirement.is_satisfied_at_position(self.grid, tile_pos): + return false + return true + + +func request_confirmed(building: BuildingData, area: Rect2i) -> void: + for x in range(area.position.x, area.position.x + area.size.x): + for y in range(area.position.y, area.position.y + area.size.y): + if !tile_is_valid_at_location(building, Vector2i(x, y)): continue + var new_tile = Building.new(Vector2i(x, y), Vector2i.ONE, building) + grid.add_child(new_tile) + + +func request_cancelled(building: BuildingData) -> void: + pass diff --git a/Scripts/BuildMenu.gd.uid b/Scripts/BuildMenu.gd.uid new file mode 100644 index 0000000..c337c9a --- /dev/null +++ b/Scripts/BuildMenu.gd.uid @@ -0,0 +1 @@ +uid://d1lhn37ijatdp diff --git a/Scripts/Building.gd b/Scripts/Building.gd new file mode 100644 index 0000000..38d30cf --- /dev/null +++ b/Scripts/Building.gd @@ -0,0 +1,206 @@ +@tool +extends TileTransform +class_name Building + +var triangle_points = PackedVector2Array([ + Vector2(0, -20) * 0.85 + Vector2.DOWN * 3, + Vector2(-20, 15) * 0.85 + Vector2.DOWN * 3, + Vector2(20, 15) * 0.85 + Vector2.DOWN * 3, + Vector2(0, -20) * 0.85 + Vector2.DOWN * 3, +]) + +var history: Array[BuildingData] = [] +var data: BuildingData = null + +func attempt_upgrade(new_data: BuildingData) -> bool: + var old_data = data + for resource_requirement in new_data.resource_requirements: + var resource = resource_requirement.resource + var required = resource_requirement.amount + var current = ResourceController.get_resource_value(resource) + if current < required: + return false + for field_requirement in new_data.field_requirements: + if !field_requirement.is_satisfied_at_position(self.grid, self.tile_pos): + return false + + for resource_requirement in new_data.resource_requirements: + var resource = resource_requirement.resource + var required = resource_requirement.amount + ResourceController.consume_resource(resource, required) + + grid.unregister_building(self) + for storage in data.resource_stockpiles: + ResourceController.remove_storage(storage) + data = new_data + grid.register_building(self) + for storage in data.resource_stockpiles: + ResourceController.add_storage(storage) + queue_redraw() + history.push_front(old_data) + return true + +func attempt_upgrades() -> bool: + if randf() > 0.1: return false + for upgrade_path in data.upgrade_paths: + if attempt_upgrade(upgrade_path): + return true + return false + +func _init(_tile_pos: Vector2i, _size: Vector2i, building_data: BuildingData): + self.data = building_data + self.tile_pos = _tile_pos + self.size = _size + +func _ready(): + super._ready() + grid.register_building(self) + for storage in data.resource_stockpiles: + ResourceController.add_storage(storage) + ResourceController.upgrade.connect(_upgrade_downgrade) + ResourceController.produce.connect(_resource_produce) + ResourceController.consume.connect(_resource_consume) + +func _downgrade_or_die(): + + while history.size() > 0: + var downgrade_data = history.pop_front() + if attempt_upgrade(downgrade_data): + history.pop_front() + return + queue_free() + +func _upgrade_downgrade(): + attempt_upgrades() + if death_timer >= max_death: + _downgrade_or_die() + +var death_timer = 0 +var max_death = 5 + +func _resource_produce(): + for resource_data in data.resource_prouction: + ResourceController.add_resource(resource_data.resource, resource_data.amount) +func _resource_consume(): + var good_cycle = true + for resource_data in data.resource_consumption: + good_cycle = good_cycle and ResourceController.consume_resource( + resource_data.resource, + resource_data.amount + ) + + # i know it says resource consumption but this is also where we make sure + # our fields still make sense, okay? + + for field_requirement in data.field_requirements: + if !field_requirement.is_satisfied_at_position(self.grid, self.tile_pos): + good_cycle = false + #var field_value = grid.get_field_value_at(field_requirement.field, tile_pos) + #if field_requirement.enforce_min and field_value < field_requirement.minimum: + #good_cycle = false + #if field_requirement.enforce_max and field_value > field_requirement.maximum: + #good_cycle = false + + if !good_cycle: + death_timer += 1 + queue_redraw() + elif death_timer != 0: + death_timer = 0 + queue_redraw() + +func _draw(): + seed(get_instance_id()) + match data.style: + BuildingData.RenderStyle.RandomBuilding: _draw_building() + BuildingData.RenderStyle.Full: _render_full() + BuildingData.RenderStyle.Outline: _render_outline() + BuildingData.RenderStyle.Triangle: _render_triangle() + BuildingData.RenderStyle.Circles: _render_circles() + if death_timer > 0: _draw_death_timer_overlay() + +func _exit_tree(): + grid.unregister_building(self) + for storage in data.resource_stockpiles: + ResourceController.remove_storage(storage) + ResourceController.upgrade.disconnect(_upgrade_downgrade) + ResourceController.produce.disconnect(_resource_produce) + ResourceController.consume.disconnect(_resource_consume) + +func randf_norm(): + return (randf() + randf() + randf() + randf() + randf()) / 5.0 + +func random_box_within(bounds: Rect2, min_size: float = 0.2, max_size: float = 0.6) -> Rect2: + var size = bounds.size * Vector2( + randf_norm() * (max_size - min_size) + min_size, + randf_norm() * (max_size - min_size) + min_size + ) + var position = (bounds.size - size) * Vector2(randf(), randf()) + return Rect2(bounds.position + position, size) + +func _get_render_bounds() -> Rect2: + var dimensions = self.size * (self.grid.cell_size if self.grid != null else 100) + return Rect2(dimensions / -2.0, dimensions) + +func _draw_building(): + var render_bounds = _get_render_bounds() + + var bottom_box = random_box_within(render_bounds, 0.2, 0.6) + #draw_rect(_get_render_bounds(), data.color.darkened(0.5), true) + draw_rect(bottom_box, self.data.color, true) + #draw_rect(render_bounds, self.data.color, false, 2) + _draw_rect_inset(render_bounds, data.color, 4) + +func _render_full(): + draw_rect(_get_render_bounds(), data.color, true) + +func _render_outline(): + var bounds = _get_render_bounds().grow(-8) + var left = bounds.grow_side(SIDE_RIGHT, -(bounds.size.y - 4)) + var right = bounds.grow_side(SIDE_LEFT, -(bounds.size.y - 4)) + var top = bounds.grow_side(SIDE_BOTTOM, -(bounds.size.y - 4)) + var bottom = bounds.grow_side(SIDE_TOP, -(bounds.size.y - 4)) + draw_dashed_line(bounds.position, bounds.position + Vector2.RIGHT * bounds.size.x, data.color, 4, 6) + draw_dashed_line(bounds.position, bounds.position + Vector2.DOWN * bounds.size.y, data.color, 4, 6) + draw_dashed_line(bounds.position + bounds.size, bounds.position + bounds.size + Vector2.LEFT * bounds.size.x, data.color, 4, 6) + draw_dashed_line(bounds.position + bounds.size, bounds.position + bounds.size + Vector2.UP * bounds.size.y, data.color, 4, 6) + +func _render_triangle(): + draw_colored_polygon(triangle_points, data.color) + +func _render_circles(): + var bounds = _get_render_bounds() + for idx in range(3): + var radius = min(bounds.size.x, bounds.size.y) / 4.0 * randf_norm() + var inner_bounds = bounds.grow(-radius) + var point = inner_bounds.position \ + + Vector2(randf(), randf()) * inner_bounds.size + draw_circle(point, radius, data.color, true, -1, true) + +func _draw_rect_inset(rect: Rect2, color: Color, width: float): + var left = rect.grow_side(SIDE_RIGHT, -(rect.size.y - width)) + var right = rect.grow_side(SIDE_LEFT, -(rect.size.y - width)) + var top = rect.grow_side(SIDE_BOTTOM, -(rect.size.y - width)) + var bottom = rect.grow_side(SIDE_TOP, -(rect.size.y - width)) + draw_rect(left, color, true) + draw_rect(right, color, true) + draw_rect(top, color, true) + draw_rect(bottom, color, true) + +func _draw_death_timer_overlay(): + var bounds = _get_render_bounds() + var font_size = 18 + var color = Color.GOLDENROD if death_timer < max_death * 0.8 else Color("ee6464") + var outline_color = Color.BLACK if death_timer < max_death * 0.8 else Color.BLACK + draw_colored_polygon(triangle_points, color) + draw_polyline(triangle_points, outline_color, 3.0, true) + draw_polyline(triangle_points, color, 1.0, true) + var height = ThemeDB.fallback_font.get_height(font_size) + draw_string( + ThemeDB.fallback_font, + Vector2.LEFT * 5.0 + Vector2.DOWN * 11.5, + "!", + HORIZONTAL_ALIGNMENT_CENTER, + 10.5, + font_size, + outline_color + ) diff --git a/Scripts/Building.gd.uid b/Scripts/Building.gd.uid new file mode 100644 index 0000000..88dd82e --- /dev/null +++ b/Scripts/Building.gd.uid @@ -0,0 +1 @@ +uid://dskk0dwdutvv3 diff --git a/Scripts/Calendar.gd b/Scripts/Calendar.gd new file mode 100644 index 0000000..0359195 --- /dev/null +++ b/Scripts/Calendar.gd @@ -0,0 +1,8 @@ +extends Label + +func _ready(): + Clock.day_passed.connect(_update_text) + _update_text() + +func _update_text(): + text = Clock.get_date_string() diff --git a/Scripts/Calendar.gd.uid b/Scripts/Calendar.gd.uid new file mode 100644 index 0000000..72b42bd --- /dev/null +++ b/Scripts/Calendar.gd.uid @@ -0,0 +1 @@ +uid://rr8s2u7xswtc diff --git a/Scripts/Clock.gd b/Scripts/Clock.gd new file mode 100644 index 0000000..035178c --- /dev/null +++ b/Scripts/Clock.gd @@ -0,0 +1,46 @@ +extends Node + +const months = [ + "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +] + +var counter: float = 0 +const day_length = 2 +var day_count: int = 0 + +var month = 1 +var date = 1 +var year = 2000 + +signal day_passed +signal resource_produce +signal resource_consume + +func _process(delta: float): + counter += delta + if counter > day_length: + counter -= day_length + day_count += 1 + date += 1 + if date == 31: + date -= 30 + month += 1 + if month == 13: + month -= 12 + year += 1 + resource_produce.emit() + resource_consume.emit() + day_passed.emit() + +func _nth_str(n: int): + if n == 0: return "0th" + if n >= 4 and n <= 20: return str(n) + "th" + if n % 10 == 1: return "1st" + if n % 10 == 2: return "2nd" + if n % 10 == 3: return "3rd" + return str(n) + "th" + +func get_date_string(): + return months[month - 1] + " " + _nth_str(date) + ", " + str(year) diff --git a/Scripts/Clock.gd.uid b/Scripts/Clock.gd.uid new file mode 100644 index 0000000..2db238d --- /dev/null +++ b/Scripts/Clock.gd.uid @@ -0,0 +1 @@ +uid://csx4bl2w2o10d diff --git a/Scripts/CursorPool.gd b/Scripts/CursorPool.gd new file mode 100644 index 0000000..5831f68 --- /dev/null +++ b/Scripts/CursorPool.gd @@ -0,0 +1,132 @@ +extends Node2D +class_name CursorPool + +enum AnimationState { + Normal, # lerps box center and size to desired. + Exploding, # Normal but diff lerp speeds. + Area, # lerps each box side to desired box side + Fading, # standard box motion, opacity fades slowly. +} + +class Cursor: + var box: Rect2 + var opacity: float + var desired_box: Rect2 + var desired_opacity: float + var color: Color + var animation: AnimationState = AnimationState.Normal + +var cursors: Array[Cursor] = [] +var current_cursor: Cursor = null + +func new_cursor(color: Color) -> Cursor: + var cursor = Cursor.new() + cursors.append(cursor) + if cursors.size() > 10: cursors.remove_at(0) + cursor.box = get_viewport_rect() + cursor.box.size = Vector2.ONE * max(cursor.box.size.x, cursor.box.size.y) + cursor.box = Rect2(cursor.box.position + cursor.box.size / -2.0, cursor.box.size).grow(100) + cursor.opacity = -2.0 + cursor.animation = AnimationState.Normal + cursor.desired_box = cursor.box + cursor.desired_opacity = 1.0 + cursor.color = color + current_cursor = cursor + + return cursor + +# cursor removal type beats. +func fade_out() -> void: + if current_cursor == null: return + current_cursor.animation = AnimationState.Fading + current_cursor.desired_opacity = 0.0 +func explode() -> void: + if current_cursor == null: return + current_cursor.animation = AnimationState.Exploding + current_cursor.desired_box = current_cursor.desired_box.grow(10) + current_cursor.desired_opacity = 0.0 + +# override / util +func _process(delta) -> void: + for d in cursors: + match d.animation: + AnimationState.Normal: _update_display_animation_active(d, delta) + AnimationState.Exploding: _update_display_animation_exploding(d, delta) + AnimationState.Fading: _update_display_animation_fading(d, delta) + AnimationState.Area: _update_display_animation_area(d, delta) + queue_redraw() +func _draw(): + for d in cursors: + draw_rect(d.box, _lerp_opacity(d.color, d.opacity), true) +func _lerp_opacity(c: Color, t: float) -> Color: + return Color(c.r, c.g, c.b, c.a * t) + +# === Display Animations +func _update_display_animation_active(d: Cursor, delta): + var old_size = d.box.size + var desired_size = d.desired_box.size + var new_size = lerp(old_size, desired_size, delta * 30 * Util.animation_speed) + #if old_size.length_squared() > desired_size.length_squared(): + #new_size = lerp(old_size, desired_size, delta * 30 * animation_speed) + #else: + #new_size = lerp(old_size, desired_size, delta * 30 * animation_speed) + var old_center = d.box.get_center() + var desired_center = d.desired_box.get_center() + var new_center = lerp(old_center, desired_center, delta * 50 * Util.animation_speed) + d.box = Rect2(new_center - new_size / 2.0, new_size) + d.opacity = lerp(d.opacity, d.desired_opacity, delta * 20 * Util.animation_speed) +func _update_display_animation_exploding(d: Cursor, delta): + var old_size = d.box.size + var desired_size = d.desired_box.size + var new_size = lerp(old_size, desired_size, delta * 20 * Util.animation_speed) + var old_center = d.box.get_center() + var desired_center = d.desired_box.get_center() + var new_center = lerp(old_center, desired_center, delta * 50 * Util.animation_speed) + d.box = Rect2(new_center - new_size / 2.0, new_size) + d.opacity = lerp(d.opacity, d.desired_opacity, delta * 15 * Util.animation_speed) +func _update_display_animation_fading(d: Cursor, delta): + var current_top = min(d.box.position.y, d.box.position.y + d.box.size.y) + var current_bottom = max(d.box.position.y, d.box.position.y + d.box.size.y) + var current_left = min(d.box.position.x, d.box.position.x + d.box.size.x) + var current_right = max(d.box.position.x, d.box.position.x + d.box.size.x) + + var desired_top = min(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y) + var desired_bottom = max(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y) + var desired_left = min(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x) + var desired_right = max(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x) + + var new_top = lerp(current_top, desired_top, delta * Util.animation_speed * 40) + var new_bottom = lerp(current_bottom, desired_bottom, delta * Util.animation_speed * 40) + var new_left = lerp(current_left, desired_left, delta * Util.animation_speed * 40) + var new_right = lerp(current_right, desired_right, delta * Util.animation_speed * 40) + + d.box = Rect2( + new_left, + new_top, + new_right - new_left, + new_bottom - new_top + ) + d.opacity = lerp(d.opacity, d.desired_opacity, delta * 10 * Util.animation_speed) +func _update_display_animation_area(d: Cursor, delta): + var current_top = min(d.box.position.y, d.box.position.y + d.box.size.y) + var current_bottom = max(d.box.position.y, d.box.position.y + d.box.size.y) + var current_left = min(d.box.position.x, d.box.position.x + d.box.size.x) + var current_right = max(d.box.position.x, d.box.position.x + d.box.size.x) + + var desired_top = min(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y) + var desired_bottom = max(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y) + var desired_left = min(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x) + var desired_right = max(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x) + + var new_top = lerp(current_top, desired_top, delta * Util.animation_speed * 40) + var new_bottom = lerp(current_bottom, desired_bottom, delta * Util.animation_speed * 40) + var new_left = lerp(current_left, desired_left, delta * Util.animation_speed * 40) + var new_right = lerp(current_right, desired_right, delta * Util.animation_speed * 40) + + d.box = Rect2( + new_left, + new_top, + new_right - new_left, + new_bottom - new_top + ) + d.opacity = lerp(d.opacity, d.desired_opacity, delta * 20 * Util.animation_speed) diff --git a/Scripts/CursorPool.gd.uid b/Scripts/CursorPool.gd.uid new file mode 100644 index 0000000..a91ef94 --- /dev/null +++ b/Scripts/CursorPool.gd.uid @@ -0,0 +1 @@ +uid://du3m15i8ahlu5 diff --git a/Scripts/DebugMenu.gd b/Scripts/DebugMenu.gd new file mode 100644 index 0000000..5b88c48 --- /dev/null +++ b/Scripts/DebugMenu.gd @@ -0,0 +1,21 @@ +extends VBoxContainer + +@export var grid: Grid +@export var overlay_enabled_button: Button +@export var overlay_selection_button: OptionButton +@export var overlay_display_values: Button + +func _ready(): + var grid_fields = Grid.Field.keys() + for idx in range(grid_fields.size()): + overlay_selection_button.add_item(grid_fields[idx], idx) + overlay_enabled_button.toggled.connect(update_overlay) + overlay_display_values.toggled.connect(update_overlay) + overlay_selection_button.item_selected.connect(update_overlay) + +func update_overlay(data): + grid.debug_overlay_display_values = overlay_display_values.button_pressed + if !overlay_enabled_button.button_pressed: + grid.disable_debug_field_overlay() + else: + grid.enable_field_debug_overlay(overlay_selection_button.selected) diff --git a/Scripts/DebugMenu.gd.uid b/Scripts/DebugMenu.gd.uid new file mode 100644 index 0000000..4f182b6 --- /dev/null +++ b/Scripts/DebugMenu.gd.uid @@ -0,0 +1 @@ +uid://cj8bj60oyrc4f diff --git a/Scripts/Entity.gd b/Scripts/Entity.gd deleted file mode 100644 index 4c137e9..0000000 --- a/Scripts/Entity.gd +++ /dev/null @@ -1,20 +0,0 @@ -@tool - -extends Node2D -class_name WorldEntity - -var grid: Grid - -func _ready(): - if Engine.is_editor_hint(): - grid = get_tree().edited_scene_root.find_child("Grid") - else: - grid = $/root/Root/Grid - - Util.find(Grid) - -func _process(_delta): - pass - -func _draw(): - draw_circle(Vector2.ZERO, 100, Color.WHITE) \ No newline at end of file diff --git a/Scripts/Entity.gd.uid b/Scripts/Entity.gd.uid deleted file mode 100644 index b916963..0000000 --- a/Scripts/Entity.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://denhgj0vxywle diff --git a/Scripts/FPSCounter.gd b/Scripts/FPSCounter.gd new file mode 100644 index 0000000..01f739b --- /dev/null +++ b/Scripts/FPSCounter.gd @@ -0,0 +1,4 @@ +extends Label + +func _process(delta: float) -> void: + set_text("FPS " + str(Engine.get_frames_per_second())) diff --git a/Scripts/FPSCounter.gd.uid b/Scripts/FPSCounter.gd.uid new file mode 100644 index 0000000..9ead58a --- /dev/null +++ b/Scripts/FPSCounter.gd.uid @@ -0,0 +1 @@ +uid://j6fc2qc5t3qa diff --git a/Scripts/Grid.gd b/Scripts/Grid.gd index 5385001..9786a16 100644 --- a/Scripts/Grid.gd +++ b/Scripts/Grid.gd @@ -10,6 +10,8 @@ extends Node2D set(val): cell_size = val _calc_dims() +@export var grid_color: Color = Color.DARK_GREEN +@export var line_color: Color = Color.DARK_GREEN.darkened(0.2) var total_width: int var total_height: int @@ -17,54 +19,91 @@ var total_height: int var thickness: int var off: Vector2 -var residents_field: Array[int] +enum Field { + Logistics, + Residents, + Commercial, + Foragable, + Forested +} + +var fields: Dictionary[Field, Array] = {} @onready var selection_manager: SelectionManager = Util.find(SelectionManager) +func ensure_field(field: Field): + if field in fields: return + fields[field] = [] + fields[field].resize(cells ** 2) + for idx in range(cells ** 2): fields[field][idx] = 0 + func _enter_tree(): _calc_dims() func _ready(): _calc_dims() - Engine.is_editor_hint() - residents_field.resize(cells ** 2) - for idx in len(residents_field): - residents_field[idx] = 0 func _calc_dims(): total_width = cells * cell_size total_height = cells * cell_size - thickness = 1 + thickness = 2 off = Vector2(total_width / -2, total_height / -2) -func _process(_delta): - queue_redraw() - func _draw(): var r = Rect2(off, Vector2(total_width, total_height)) - draw_rect(r, Color("222222"), true) - var line_color = Color(1, 1, 1, 0.3) + draw_rect(r, grid_color, true) for i in range(cells + 1): draw_line(Vector2(i * cell_size, 0) + off, Vector2(i * cell_size, total_height) + off, line_color, thickness, false) for i in range(cells + 1): draw_line(Vector2(0, i * cell_size) + off, Vector2(total_width, i * cell_size) + off, line_color, thickness, false) + + if !debug_overlay_enabled: return + + if !fields.has(debug_overlay_field): return + var field = fields[debug_overlay_field] + var field_min = field.min() + var field_max = field.max() + for x in range(cells): for y in range(cells): - var world_pos = Vector2i(x, y) - var tile = _get_tile_at_tile_pos(world_pos) - if tile == null: - continue - var t = Rect2( - tile2world(world_pos), - Vector2.ONE * cell_size + var index = tile_pos2index(Vector2i(x, y)) + if field[index] == 0: continue + var true_value = field[index] + if true_value <= 0: continue + var t = inverse_lerp(0, field_max if true_value > 0 else abs(field_min), abs(true_value)) + var grad = overlay_gradient if true_value > 0 else overlay_gradient_negative + var font_grad = overlay_font_color_gradient if true_value > 0 else overlay_font_color_gradient + var color = grad.sample(t) + var world_rect = tile2world_rect(Rect2i(x, y, 1, 1)) + draw_rect(world_rect, color, true) + + if !debug_overlay_display_values: continue + var world_pos = self.tile2world(Vector2i(x, y)) + var debug_str = str(field[index]) + draw_string( + ThemeDB.fallback_font, + world_pos + Vector2.DOWN * cell_size / 2.0, + debug_str, + HORIZONTAL_ALIGNMENT_CENTER, + cell_size, + 10, + font_grad.sample(t) ) - draw_rect(t, Color("773322")) + #var tile = _get_tile_at_tile_pos(world_pos) + #if tile == null: + #continue + #print(tile) + #var t = Rect2( + #tile2world(world_pos), + #Vector2.ONE * cell_size + #) + #draw_rect(t, Color("773322")) -func tile2world(tile: Vector2i) -> Vector2i: +func tile2world(tile: Vector2i) -> Vector2: return Vector2(tile) * cell_size + off -func tile2world_rect(tile: Rect2i) -> Rect2: +func tile2world_rect(tile: Rect2) -> Rect2: return Rect2(Vector2(tile.position) * cell_size + off, tile.size * cell_size) func tile2world_size(tile_size: Vector2i) -> Vector2: @@ -93,13 +132,13 @@ func quantize_on_objects(world_position: Vector2) -> Rect2: return tile.get_worldbox() return quantize(world_position, Vector2.ONE) -func _get_tile_at_tile_pos(pos: Vector2i) -> TileTransform: +func _get_building_at(pos: Vector2i) -> Building: for tile in things: if tile.get_tilebox().has_point(pos): return tile return null -func _get_tile_at_world_pos(pos: Vector2) -> TileTransform: +func _get_tile_at_world_pos(pos: Vector2) -> Building: #var world_pos = world2tile_f(pos) for tile in things: if tile.get_worldbox().has_point(pos): @@ -124,15 +163,84 @@ var things_dict: Dictionary = {} func tile_pos2index(pos: Vector2i) -> int: return pos.x + pos.y * self.cells -func idnex2tile_pos(idx: int) -> Vector2i: +func index2tile_pos(idx: int) -> Vector2i: return Vector2i( idx % self.cells, floor(idx / self.cells) ) -func register_tile(tile: TileTransform) -> void: +func increase_field_value(emissions_data: FieldEmission, position: Vector2i): + ensure_field(emissions_data.field) + var field = fields[emissions_data.field] + # field[tile_pos2index(position)] = max(amt, field[tile_pos2index(position)]) + for x_offset in range(- emissions_data.range - 1, emissions_data.range + 1): + for y_offset in range(- emissions_data.range - 1, emissions_data.range + 1): + var offset = Vector2i(x_offset, y_offset) + var new_pos = position + offset + if new_pos.x < 0: continue + if new_pos.y < 0: continue + if new_pos.x >= cells: continue + if new_pos.y >= cells: continue + var field_addition = emissions_data.get_field_value_for_distance(offset.length()) + if field_addition == 0: continue + var index = tile_pos2index(new_pos) + field[index] += field_addition + +func decrease_field_Value(emissions_data: FieldEmission, position: Vector2i): + ensure_field(emissions_data.field) + var field = fields[emissions_data.field] + # field[tile_pos2index(position)] = max(amt, field[tile_pos2index(position)]) + for x_offset in range(- emissions_data.range - 1, emissions_data.range + 1): + for y_offset in range(- emissions_data.range - 1, emissions_data.range + 1): + var offset = Vector2i(x_offset, y_offset) + var new_pos = position + offset + if new_pos.x < 0: continue + if new_pos.y < 0: continue + if new_pos.x >= cells: continue + if new_pos.y >= cells: continue + var field_addition = emissions_data.get_field_value_for_distance(offset.length()) + if field_addition == 0: continue + var index = tile_pos2index(new_pos) + field[index] -= field_addition + +var overlay_gradient: Gradient = preload("res://Gradients/OverlayBasic.tres") +var overlay_gradient_negative: Gradient = preload("res://Gradients/OverlayBasicNegative.tres") +var overlay_font_color_gradient: Gradient = preload("res://Gradients/OverlayBasicFontColor.tres") +@export var debug_overlay_enabled: bool = true +@export var debug_overlay_field: Field = Field.Logistics +@export var debug_overlay_display_values: bool = false + +func enable_field_debug_overlay(field: Field): + debug_overlay_enabled = true + debug_overlay_field = field + queue_redraw() + +func disable_debug_field_overlay(): + debug_overlay_enabled = false + queue_redraw() + +func unregister_building(tile: Building) -> void: + things.erase(tile) + var tilebox = tile.get_tilebox() + for x_off in range(tilebox.size.x): + for y_off in range(tilebox.size.y): + for emission in tile.data.field_emissions: + decrease_field_Value(emission, tilebox.position + Vector2i(x_off, y_off)) + queue_redraw() + +func register_building(tile: Building) -> void: things.append(tile) - + var tilebox = tile.get_tilebox() + for x_off in range(tilebox.size.x): + for y_off in range(tilebox.size.y): + for emission in tile.data.field_emissions: + increase_field_value(emission, tilebox.position + Vector2i(x_off, y_off)) + queue_redraw() func remove_tile(tile: TileTransform) -> void: things.erase(tile) + +func get_field_value_at(field: Field, tile_pos: Vector2i): + if field not in fields: return 0 + var value = fields[field][tile_pos2index(tile_pos)] + return value diff --git a/Scripts/GridInput.gd b/Scripts/GridInput.gd index b2fd9f3..55a8c4e 100644 --- a/Scripts/GridInput.gd +++ b/Scripts/GridInput.gd @@ -1,213 +1,207 @@ extends Node2D +class_name GridInput @onready var grid: Grid = $/root/Root/Grid -@export var highlight_color: Color = Color(1, 1, 1, 0.2) -@export var deletion_color: Color = Color(1, 1, 1, 0.2) - -var animation_speed = 0.8 - -enum AnimationState { - Active, - Fading, - Exploding -} - -enum CursorMode { - Selection, - Deletion -} - -class Display: - var mode: CursorMode - var box: Rect2 - var desired_box: Rect2 - var opacity: float - var confirmed_callback: Callable - var cancelled_callback: Callable - var dragging: bool = false - var drag_from: Rect2 - var state: AnimationState = AnimationState.Fading - -var display_count = 10 -var displays: Array[Display] = [] -var display_idx = -1 - -var display: Display: - get(): - return displays[display_idx] if display_idx >= 0 else null - -func new_display(): - if display_idx < 0: - display_idx += display_count - display_idx += 1 - display_idx = display_idx % display_count - display.dragging = false - display.box = get_viewport_rect() - display.box.size = Vector2.ONE * max(display.box.size.x, display.box.size.y) - display.box = Rect2(display.box.position + display.box.size / -2.0, display.box.size).grow(100) - display.opacity = -2.0 - display.state = AnimationState.Active - display.desired_box = display.box - -func end_display(): - if display == null: return - if display.state == AnimationState.Active: - display.state = AnimationState.Fading - if display.state == AnimationState.Exploding: - display.desired_box = display.desired_box.grow(30) - display_idx -= display_count - -var left_dragging = false -var left_mouse_down = false -var left_mouse_down_start_pos: Vector2 = Vector2.ZERO - -func _is_mouse_pos_significant() -> bool: - return (get_local_mouse_position() - left_mouse_down_start_pos).length_squared() > 50 - -#eventually, replace this weird shit with an array of old rects that are fading out -#let them fade out, and just remove them. have a method to abandon the current box -#and start a new one that just follows the normal box-booting procedure. -#if you're not in the grid, it simply wont be created yet. have to have a has_box prop -#or something like that. but this is good enough for now +var highlight_color: Color = Color(0.075, 0.536, 0.75, 0.38) +var build_color: Color = Color(0.087, 0.62, 0.087, 0.514) +var deletion_color: Color = Color(0.76, 0.237, 0.106, 0.4) +var current_color = highlight_color +var cursor_pool: CursorPool func _ready(): - selection_manager = Util.find(SelectionManager) - displays.resize(display_count) - for idx in range(displays.size()): - displays[idx] = Display.new() - displays[idx].opacity = 0.0 - displays[idx].state = AnimationState.Fading + cursor_pool = Util.find_child_type(self, CursorPool) - mouse_in_grid = grid.contains_world_pos(get_local_mouse_position()) - if mouse_in_grid: - new_display() - - -func _lerp_opacity(c: Color, t: float) -> Color: - return Color(c.r, c.g, c.b, c.a * t) - -func update_display_animations(delta): - for d in displays: - var old_size = d.box.size - var desired_size = d.desired_box.size - var new_size = 0.0 - - match d.state: - AnimationState.Exploding: - new_size = lerp(old_size, desired_size, delta * 3 * animation_speed) - AnimationState.Active, \ - AnimationState.Fading: - if old_size.length_squared() > desired_size.length_squared(): - new_size = lerp(old_size, desired_size, delta * 30 * animation_speed) - else: - new_size = lerp(old_size, desired_size, delta * 30 * animation_speed) - - var old_center = d.box.get_center() - var desired_center = d.desired_box.get_center() - var new_center = lerp(old_center, desired_center, delta * 50 * animation_speed) - - d.box = Rect2(new_center - new_size / 2.0, new_size) - - match d.state: - AnimationState.Fading: - d.opacity = lerp(d.opacity, 0.0, delta * 10 * animation_speed) - AnimationState.Active: - d.opacity = lerp(d.opacity, 1.0, delta * 20 * animation_speed) - AnimationState.Exploding: - d.opacity = lerp(d.opacity, -1.0, delta * 5 * animation_speed) - -var mouse_in_grid: bool = false -var mousing_over: Rect2 -func _process(delta): - queue_redraw() - var mouse = get_local_mouse_position() - var new_mousing_over = grid.quantize_on_objects(mouse) - var new_mouse_in_grid = grid.contains_world_pos(mouse) - - if mouse_in_grid && !new_mouse_in_grid: - end_display() - if !mouse_in_grid && new_mouse_in_grid: - new_display() - display.mode = CursorMode.Deletion - if new_mousing_over != mousing_over && display == null && new_mouse_in_grid: - new_display() - - mouse_in_grid = new_mouse_in_grid - mousing_over = new_mousing_over - - update_display_animations(delta) - - # only do anything new if we have a mouse on the grid! - if !mouse_in_grid: return - if display == null: return - - display.desired_box = mousing_over - -func _draw(): - #draw_rect(mousing_over.grow(-8), Color.FIREBRICK, true) - for d in displays: - match d.mode: - CursorMode.Selection: - draw_rect(d.box, _lerp_opacity(highlight_color, d.opacity), true) - CursorMode.Deletion: - draw_rect(d.box, _lerp_opacity(deletion_color, d.opacity), true) -enum State { - # Selection will automatically go do selection things - Selection, - # whereas these hoes will just call callbacks. - LineDrag, - Area, +enum AreaType { + Rectangle, + Line, + None, } +var current_marquee_type: AreaType = AreaType.Rectangle -var state: State = State.Selection -var selection_manager: SelectionManager - -func _begin_drag(pos: Vector2): - display.drag_from - print("drag from", pos) - -func _dragging(pos: Vector2): - pass - -func _end_drag(pos: Vector2): - print("to", pos) - -func _click(pos: Vector2): - print("click at", pos) - if display == null: - new_display() - display.state = AnimationState.Exploding - end_display() - - var tile = grid._get_tile_at_world_pos(pos) - if tile == null: - selection_manager.clear() - return - selection_manager.select_array([tile]) - -func _double_click(pos: Vector2): - pass - -func _right_click(pos: Vector2): - pass - +# === RAW MOUSE EVENTS === +# first we process inputs raw and separate them out into something digestable +# This uses some state data! +var _left_dragging = false +var _left_mouse_down = false +var _left_mouse_down_start_pos: Vector2 = Vector2.ZERO +func __is_mouse_pos_significant() -> bool: + return (get_local_mouse_position() - _left_mouse_down_start_pos).length_squared() > 50 func _input(event: InputEvent): if event is InputEventMouseMotion: - if left_mouse_down: - if not left_dragging and _is_mouse_pos_significant(): - left_dragging = true + if _left_mouse_down: + if not _left_dragging and __is_mouse_pos_significant(): + _left_dragging = true _begin_drag(get_local_mouse_position()) - elif left_dragging: - _dragging(get_local_mouse_position()) + elif _left_dragging: + _update_drag(get_local_mouse_position()) + else: + _update_hover(get_local_mouse_position()) elif event is InputEventMouseButton: if event.button_index == 1: - left_mouse_down = event.pressed + _left_mouse_down = event.pressed if event.pressed: - left_mouse_down_start_pos = get_local_mouse_position() + _left_mouse_down_start_pos = get_local_mouse_position() else: - if left_dragging: - left_dragging = false + if _left_dragging: + _left_dragging = false _end_drag(get_local_mouse_position()) else: - _click(get_local_mouse_position()) + _left_click(get_local_mouse_position()) + elif event.button_index == 2 && event.pressed: + _right_click(get_local_mouse_position()) + +# for now, lets pretend these are simple :) +func _left_click(pos: Vector2): + if !grid.contains_world_pos(pos): return + var tile_pos = grid.world2tile(pos) + _grid_clicked(tile_pos) +func _right_click(pos: Vector2): + _cancel_operation() + cursor_pool.explode() + if !mouse_in_grid: return + cursor_pool.new_cursor(current_color) + _update_cursor() + +var mouse_in_grid: bool = false # TODO init this correctly lol +func __mouse_may_have_left_or_entered_grid(pos: Vector2): + var new_mouse_in_grid = grid.contains_world_pos(pos) + var mouse_entered_grid = new_mouse_in_grid && !mouse_in_grid + var mouse_left_grid = !new_mouse_in_grid && mouse_in_grid + mouse_in_grid = new_mouse_in_grid + if mouse_entered_grid: _mouse_enter_grid() + elif mouse_left_grid: _mouse_leave_grid() +func _update_hover(pos: Vector2): + __mouse_may_have_left_or_entered_grid(pos) + if !mouse_in_grid: return + _mouse_hover_grid(pos) + +# while dragging will attempt to begin marquee selection +var in_marquee: bool = false +var marquee_start_tile: Vector2i = Vector2i.ZERO +func __get_current_marquee_area(pos: Vector2i): + var marquee_end_tile = grid.world2tile(pos) + match current_marquee_type: + AreaType.Rectangle: + return Rect2i(marquee_start_tile, Vector2i.ONE).merge(Rect2i(marquee_end_tile, Vector2i.ONE)) + AreaType.Line: + var vertical = Rect2i(marquee_start_tile, Vector2i.ONE).merge(Rect2i(Vector2i(marquee_start_tile.x, marquee_end_tile.y), Vector2i.ONE)) + var horizontal = Rect2i(marquee_start_tile, Vector2i.ONE).merge(Rect2i(Vector2i(marquee_end_tile.x, marquee_start_tile.y), Vector2i.ONE)) + return vertical if vertical.get_area() > horizontal.get_area() else horizontal +func _begin_drag(pos: Vector2): + __mouse_may_have_left_or_entered_grid(pos) + if !mouse_in_grid: return + in_marquee = true + marquee_start_tile = grid.world2tile(pos) + _begin_marquee(marquee_start_tile) +func _update_drag(pos: Vector2): + __mouse_may_have_left_or_entered_grid(pos) + if !mouse_in_grid: return + if !in_marquee: return + var new_area = __get_current_marquee_area(pos) + _update_marquee(new_area) +func _end_drag(pos: Vector2): + if !in_marquee: + cursor_pool.new_cursor(current_color) + _update_cursor() + return + var final_area = __get_current_marquee_area(pos) + if !mouse_in_grid: + _cancel_marquee() + else: + _end_marquee(final_area) + in_marquee = false + +# === PROCESSED GAME INTERACTION EVENTS === +func _mouse_enter_grid(): + if !in_marquee && !_left_dragging: + cursor_pool.new_cursor(current_color) + if in_marquee: + cursor_pool.new_cursor(current_color) + cursor_pool.current_cursor.animation = \ + cursor_pool.AnimationState.Area +func _mouse_leave_grid(): + cursor_pool.fade_out() +func _mouse_hover_grid(world_pos: Vector2): + _update_cursor() + +func _cancel_operation(): + clear_request() + +func _begin_marquee(tile_pos: Vector2i): + cursor_pool.current_cursor.desired_box = \ + grid.tile2world_rect(Rect2i(tile_pos, Vector2i.ONE)) + cursor_pool.current_cursor.animation = CursorPool.AnimationState.Area +func _update_marquee(area: Rect2i): + cursor_pool.current_cursor.desired_box = \ + grid.tile2world_rect(area) +func _end_marquee(area: Rect2i): + _area_selected(area) + cursor_pool.explode() + cursor_pool.new_cursor(current_color) + _update_cursor() +func _cancel_marquee(): + cursor_pool.explode() + if !mouse_in_grid: return + cursor_pool.new_cursor(current_color) +func _grid_clicked(tile_pos: Vector2i): + _area_selected(Rect2i(tile_pos, Vector2i.ONE)) + cursor_pool.explode() + cursor_pool.new_cursor(current_color) + _update_cursor() + pass + +func _update_cursor(world_pos = get_local_mouse_position()): + cursor_pool.current_cursor.desired_box = \ + grid.quantize_on_objects(world_pos) + +enum Style { + Highlight, + Build, + Delete +} + +class Request: + var context: Variant + var confirmed + var cancelled +var request: Request = null +var one_shot: bool = false +@export var selection_manager: SelectionManager + +func _area_selected(area: Rect2i): + if request != null: + request.confirmed.call(request.context, area) + if one_shot: _reset() + return + if area.size == Vector2i.ONE: + var item = grid._get_building_at(area.position) + if item != null: + selection_manager.select_array([item]) + return + if item == null: + selection_manager.clear() + +func clear_request(): + if request == null: return + request.cancelled.call(request.context) + request = null + _reset() + +func request_area(ctx, confirm, cancel, style: Style, area_type: AreaType, one_shot: bool): + request = Request.new() + request.confirmed = confirm + request.cancelled = cancel + request.context = ctx + current_marquee_type = area_type + _set_style(style) + +func _reset(): + _set_style(Style.Highlight) + current_marquee_type = AreaType.Rectangle + +func _set_style(style: Style): + match style: + Style.Highlight: current_color = highlight_color + Style.Build: current_color = build_color + Style.Delete: current_color = deletion_color diff --git a/Scripts/ResourceController.gd b/Scripts/ResourceController.gd new file mode 100644 index 0000000..ff76e19 --- /dev/null +++ b/Scripts/ResourceController.gd @@ -0,0 +1,113 @@ +extends Node + +enum ResourceType { + Logs, + Labor, + Berries, + Food +} + +const res_names = { + #ResourceType.Logs: "Logs" +} + +signal produce +signal consume +signal upgrade + +signal resource_type_added +signal resource_stats_updated + +class ResourceStats: + var max: int + var value: int + var delta: int + +var stock: Dictionary[ResourceType, int] = {} + +var storage: Dictionary[ResourceType, int] = {} + +func add_storage(data: ResourceAmount): + ensure_resource(data.resource) + storage[data.resource] += data.amount +func remove_storage(data: ResourceAmount): + ensure_resource(data.resource) + storage[data.resource] -= data.amount + if stock[data.resource] > storage[data.resource]: + stock[data.resource] = storage[data.resource] + +func _ready(): + Clock.day_passed.connect(_tick_resources) + +func _tick_resources(): + var stats: Dictionary[ResourceType, ResourceStats] = {} + for resource in stock.keys(): + var stat = ResourceStats.new() + stat.delta = -stock[resource] + stat.max = storage[resource] + stats[resource] = stat + produce.emit() + consume.emit() + for resource in stock.keys(): + if !stats.has(resource): + var stat = ResourceStats.new() + stat.delta = stock[resource] + stat.max = storage[resource] + stats[resource] = stat + continue + stats[resource].delta += stock[resource] + # \/ this really should change here but like shrug + stats[resource].max = storage[resource] + for resource in stock.keys(): + var max = storage[resource] + stock[resource] = clamp(stock[resource], 0, storage[resource]) + stats[resource].value = stock[resource] + + upgrade.emit() + + for resource in stock: + if !stats.has(resource): + var stat = ResourceStats.new() + stat.value = stock[resource] + stat.delta = stock[resource] + stat.max = storage[resource] + stats[resource] = stat + continue + stats[resource].value = stock[resource] + stats[resource].max = storage[resource] + + for resource in stats.keys(): + var stat = stats[resource] + resource_stats_updated.emit(resource, stat) + +func ensure_resource(resource: ResourceType): + if resource in stock: return + stock[resource] = 0 + storage[resource] = 0 + resource_type_added.emit(resource) + +func consume_resource(resource: ResourceType, amount: int) -> bool: + if !stock.has(resource): return false + if stock[resource] == 0: + return false + stock[resource] -= amount + var failed = stock[resource] < 0 + if failed: + stock[resource] = 0 + return !failed + +func add_resource(resource_type: ResourceType, amount: int): + ensure_resource(resource_type) + stock[resource_type] += amount + +func get_resource_value(resource_type: ResourceType) -> int: + if !stock.has(resource_type): return 0 + return stock[resource_type] + +func get_resource_name(resource: ResourceType) -> String: + if resource in res_names: return res_names[resource] + return str(ResourceType.keys()[resource]) + +func get_resource_storage(resource: ResourceType): + if !storage.has(resource): return 0 + return storage[resource] diff --git a/Scripts/ResourceController.gd.uid b/Scripts/ResourceController.gd.uid new file mode 100644 index 0000000..06ca4e5 --- /dev/null +++ b/Scripts/ResourceController.gd.uid @@ -0,0 +1 @@ +uid://bv7oy4xlo7osf diff --git a/Scripts/ResourceTracker.gd b/Scripts/ResourceTracker.gd new file mode 100644 index 0000000..c406522 --- /dev/null +++ b/Scripts/ResourceTracker.gd @@ -0,0 +1,29 @@ +extends PanelContainer +class_name ResourceTracker + +@export var bar: ProgressBar +@export var name_label: Label +@export var value_label: Label +@export var changes: Label + +@export var decreased_color: Color +@export var increased_color: Color + +func set_increment(value: int): + changes.text = ("+ " + str(value)) if value > 0 \ + else ("- " + str(abs(value))) if value < 0 \ + else ("--") + var color = increased_color if value > 0 \ + else decreased_color if value < 0 \ + else Color.WHITE + if changes.label_settings == null: changes.label_settings = LabelSettings.new() + changes.label_settings.font_color = color + +func set_resource_name(name: String): + name_label.text = name + +func set_val_and_max(value: int, max: int): + value_label.text = str(value) + " / " + str(max) + bar.min_value = 0 + bar.max_value = max if max != 0 else 1 + bar.value = value diff --git a/Scripts/ResourceTracker.gd.uid b/Scripts/ResourceTracker.gd.uid new file mode 100644 index 0000000..083ebc9 --- /dev/null +++ b/Scripts/ResourceTracker.gd.uid @@ -0,0 +1 @@ +uid://cf3f8iyagxl08 diff --git a/Scripts/ResourcesPanel.gd b/Scripts/ResourcesPanel.gd new file mode 100644 index 0000000..0aa260d --- /dev/null +++ b/Scripts/ResourcesPanel.gd @@ -0,0 +1,26 @@ +extends VBoxContainer + +var trackers: Dictionary[ResourceController.ResourceType, ResourceTracker] = {} +var resource_tracker_scene: PackedScene = preload("res://ResourceTracker.tscn") + +func _ready(): + var header = Label.new() + header.text = "Resources" + add_child(header) + + for resource in ResourceController.stock.keys(): + add_resource_ui(resource) + ResourceController.resource_type_added.connect(add_resource_ui) + ResourceController.resource_stats_updated.connect(_update_resource) + +func _update_resource(resource_type: ResourceController.ResourceType, stats: ResourceController.ResourceStats): + if !trackers.has(resource_type): add_resource_ui(resource_type) + var tracker = trackers[resource_type] + tracker.set_val_and_max(stats.value, stats.max) + tracker.set_increment(stats.delta) + +func add_resource_ui(resource_type: ResourceController.ResourceType): + var tracker: ResourceTracker = resource_tracker_scene.instantiate() + add_child(tracker) + tracker.set_resource_name(ResourceController.get_resource_name(resource_type)) + trackers[resource_type] = tracker diff --git a/Scripts/ResourcesPanel.gd.uid b/Scripts/ResourcesPanel.gd.uid new file mode 100644 index 0000000..5e48dd7 --- /dev/null +++ b/Scripts/ResourcesPanel.gd.uid @@ -0,0 +1 @@ +uid://cg3qqaogq7h8q diff --git a/Scripts/SelectionManager.gd b/Scripts/SelectionManager.gd index 57aeaff..26454b7 100644 --- a/Scripts/SelectionManager.gd +++ b/Scripts/SelectionManager.gd @@ -1,11 +1,11 @@ extends Node2D class_name SelectionManager -const SIGNAL_SELECTION_CHANGED = "selection-changed" +signal selection_updated @export var selected_box_hidden_color = Color(1, 1, 1, 0) @export var selected_box_color = Color(1, 1, 1, 0.6) -@onready var selection: Array[TileTransform] = [] +@onready var selection: Array[Building] = [] var anim_t: float = 0.0 func _process(delta): @@ -16,19 +16,17 @@ func _process(delta): func clear(): anim_t = 0 selection = [] - emit_signal(SIGNAL_SELECTION_CHANGED) - print("clear selection ", len(selection)) + selection_updated.emit(selection) -func append_array(items: Array[TileTransform]): +func append_array(items: Array[Building]): selection.append_array(items) - emit_signal(SIGNAL_SELECTION_CHANGED) + selection_updated.emit(selection) -func select_array(items: Array[TileTransform]): +func select_array(items: Array[Building]): clear() if items.is_empty(): return append_array(items) - print("selected ", len(selection)) func _draw(): if selection.is_empty(): diff --git a/Scripts/TileRenderer.gd b/Scripts/TileRenderer.gd deleted file mode 100644 index dc5cd9a..0000000 --- a/Scripts/TileRenderer.gd +++ /dev/null @@ -1,47 +0,0 @@ -@tool - -extends Node2D -class_name TileRenderer - -@export var base_color: Color = Color.SPRING_GREEN -@export var top_color: Color = Color.WEB_GREEN - -var drawbox: Rect2 -var drawbox_top: Rect2 -var tile_transform: TileTransform -var grid: Grid -var text_pos: Vector2 - -func _ready(): - tile_transform = Util.find_parent_type(self, TileTransform) - grid = Util.find_parent_type(self, Grid) - -func _process(_delta): - queue_redraw() - -func _draw(): - _update_drawbox() - draw_rect(drawbox, base_color, true) - draw_rect(drawbox_top, top_color, true) - draw_string(ThemeDB.fallback_font, text_pos, "House", HORIZONTAL_ALIGNMENT_CENTER, drawbox_top.size.x, 12) - - -func _update_drawbox(): - - var size = self.tile_transform.size * (self.grid.cell_size if self.grid != null else 100) - var box = Rect2(size / -2.0, size) - - if not is_node_ready(): - return - - self.drawbox = box - self.drawbox_top = Rect2( - drawbox.position.x + 2.0, - drawbox.position.y + drawbox.size.y - 18.0, - drawbox.size.x - 4.0, - 16.0 - ) - # drawbox_top.size.y = 16 - text_pos = drawbox_top.position - text_pos.y += drawbox_top.size.y - 3 - diff --git a/Scripts/TileRenderer.gd.uid b/Scripts/TileRenderer.gd.uid deleted file mode 100644 index d5c0084..0000000 --- a/Scripts/TileRenderer.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://2mbjbn23ry8t diff --git a/Scripts/TileTransform.gd b/Scripts/TileTransform.gd index 001dded..4ccf31d 100644 --- a/Scripts/TileTransform.gd +++ b/Scripts/TileTransform.gd @@ -2,43 +2,26 @@ extends Node2D class_name TileTransform -enum State { - CLEAN, - UPDATE_POSITION - # UPDATE_TILE_POS -} - -@export var quantize_in_editor = true: - set(val): - quantize_in_editor = val - _quantize() @export var size: Vector2i = Vector2i.ONE: set(val): size = val - _quantize() - -# - - - - - - - - - - - - - - - - + update_world_from_tile() + queue_redraw() +@export var tile_pos: Vector2i = Vector2i.ZERO: + set(val): + tile_pos = val + update_world_from_tile() + queue_redraw() var grid: Grid -var _worldbox: Rect2 = Rect2(0, 0, 0, 0) -var _tilebox: Rect2i = Rect2i(0, 0, 0, 0) - -var state: State = State.CLEAN -var has_adjusted_positions_this_frame = false func _ready(): + if Engine.is_editor_hint(): set_notify_transform(true) grid = Util.find_parent_type(self, Grid) - grid.register_tile(self) - set_notify_transform(true) - _quantize() - -func _process(_delta): - has_adjusted_positions_this_frame = false - if state == State.UPDATE_POSITION: - _quantize() + update_world_from_tile() func _enter_tree(): - set_notify_transform(true) + if Engine.is_editor_hint(): set_notify_transform(true) func _exit_tree(): if grid != null: @@ -46,44 +29,19 @@ func _exit_tree(): func _notification(what: int) -> void: if what == NOTIFICATION_TRANSFORM_CHANGED: - _quantize() + if Engine.is_editor_hint(): _editor_position_changed() -func _tile_pos_updated(): - pass +func update_world_from_tile(): + if grid == null: return + var worldbox = grid.tile2world_rect(Rect2i(tile_pos, size)) + position = worldbox.get_center() -func _size_updated(): - pass - -func _position_updated(): - pass - -func _quantize(): - if Engine.is_editor_hint() && !quantize_in_editor: - return - if grid == null: - return - if has_adjusted_positions_this_frame: - state = State.UPDATE_POSITION - return +func _editor_position_changed(): var top_left_world_pos = position - grid.tile2world_size(size - Vector2i.ONE) / 2 - var tile_pos = grid.world2tile(top_left_world_pos) - _worldbox = grid.tile2world_rect(Rect2i(tile_pos, size)) - position = _worldbox.get_center() - print("updated " + self.name + "'s world box to: " + str(self._worldbox)) - state = State.CLEAN - has_adjusted_positions_this_frame = true - -func _derive(): - pass - -func _update_boxes(): - pass - -# func set_tile_pos(pos: Vector2i): -# pass + tile_pos = grid.world2tile(top_left_world_pos) func get_worldbox(): - return Rect2(_worldbox) + return grid.tile2world_rect(get_tilebox()) func get_tilebox(): - return Rect2i(_tilebox) + return Rect2i(tile_pos, size) diff --git a/Scripts/Util.gd b/Scripts/Util.gd index eda0c77..b22df1a 100644 --- a/Scripts/Util.gd +++ b/Scripts/Util.gd @@ -1,20 +1,22 @@ @tool extends Node -func find(type): +# probably move this to some sort of settings at some point +var animation_speed = 0.8 + +func find(type: Script): var root = null if Engine.is_editor_hint(): root = get_tree().edited_scene_root else: root = get_tree().root - return _find_type_on_base(root, type) + return find_child_type(root, type) func find_parent_type(node: Node, type: Script): var current_node = node if node == null: return null - #print("Searching for " + type.get_global_name() + " from " + node.name) var i = 0 while current_node != null and i < 10: @@ -24,11 +26,11 @@ func find_parent_type(node: Node, type: Script): current_node = current_node.get_parent() return null; -func _find_type_on_base(base: Node, type): +func find_child_type(base: Node, type: Script): if is_instance_of(base, type): return base for child in base.get_children(): - var found_node = _find_type_on_base(child, type) + var found_node = find_child_type(child, type) if found_node != null: return found_node return null diff --git a/SelectionUI.gd b/SelectionUI.gd new file mode 100644 index 0000000..b6412fb --- /dev/null +++ b/SelectionUI.gd @@ -0,0 +1,48 @@ +extends VBoxContainer + +@export var selection_manager: SelectionManager +@export var name_label: Label +@export var selection_panel: Control +@export var content_panel: Container +var grid: Grid + +func _ready(): + selection_manager.selection_updated.connect(_selection_updated) + grid = Util.find(Grid) + +func deselect(): + name_label.text = "Nothing Selected" + if !selection_panel.hidden: selection_panel.hide() + for child in content_panel.get_children(): child.queue_free() + +func select_single(item: Building): + name_label.text = item.data.tile_name + selection_panel.show() + for child in content_panel.get_children(): child.queue_free() + + for upgrade in item.data.upgrade_paths: + var container = FoldableContainer.new() + container.folded = false + container.title = upgrade.tile_name + content_panel.add_child(container) + for thing in upgrade.field_requirements: + match thing.get_script(): + FieldMin: + var req = thing as FieldMin + var checkbox = CheckBox.new() + checkbox.text = str(Grid.Field.keys()[req.field]) + checkbox.button_pressed = req.is_satisfied_at_position(grid, item.tile_pos) + checkbox.disabled = true + container.add_child(checkbox) + FieldMax: + var req = thing as FieldMax + var checkbox = CheckBox.new() + checkbox.text = str(Grid.Field.keys()[req.field]) + checkbox.button_pressed = req.is_satisfied_at_position(grid, item.tile_pos) + checkbox.disabled = true + container.add_child(checkbox) + + +func _selection_updated(things: Array[Building]): + if things.size() == 0: deselect() + if things.size() == 1: select_single(things[0]) diff --git a/SelectionUI.gd.uid b/SelectionUI.gd.uid new file mode 100644 index 0000000..605c55d --- /dev/null +++ b/SelectionUI.gd.uid @@ -0,0 +1 @@ +uid://ngiejslhl66p diff --git a/Tiles/Farm/Forest.tres b/Tiles/Farm/Forest.tres new file mode 100644 index 0000000..6df9f6b --- /dev/null +++ b/Tiles/Farm/Forest.tres @@ -0,0 +1,28 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=8 format=3 uid="uid://doqny7m7x1jnl"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_gaxmn"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_wkv8k"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_jwb6i"] +[ext_resource type="Script" uid="uid://5h2g03dsx026" path="res://ResourceScripts/FieldRequirements/FieldMax.gd" id="3_wkv8k"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_ig22d"] + +[sub_resource type="Resource" id="Resource_xr6hc"] +script = ExtResource("1_gaxmn") +field = 4 +range = 2.4 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_jwb6i"] +script = ExtResource("3_wkv8k") +field = 4 +metadata/_custom_type_script = "uid://5h2g03dsx026" + +[resource] +script = ExtResource("4_ig22d") +tile_name = "Forest" +style = 3 +color = Color(0.11764706, 0.45882353, 0.19215687, 1) +field_requirements = Array[ExtResource("2_wkv8k")]([SubResource("Resource_jwb6i")]) +field_emissions = Array[ExtResource("1_gaxmn")]([SubResource("Resource_xr6hc")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Farm/Reservation.tres b/Tiles/Farm/Reservation.tres new file mode 100644 index 0000000..f896fef --- /dev/null +++ b/Tiles/Farm/Reservation.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=6 format=3 uid="uid://c2ajd2c6fu04d"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_sgs2a"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_kjhvl"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_d636l"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_rxh8u"] +[ext_resource type="Resource" uid="uid://bpi8ngu73jg15" path="res://Tiles/Farm/Wild Field.tres" id="5_kjhvl"] + +[resource] +script = ExtResource("4_rxh8u") +tile_name = "Farmland" +style = 2 +color = Color(0.182, 0.7, 0.29423332, 1) +upgrade_paths = Array[ExtResource("4_rxh8u")]([ExtResource("5_kjhvl")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Farm/Wild Field.tres b/Tiles/Farm/Wild Field.tres new file mode 100644 index 0000000..3f044ed --- /dev/null +++ b/Tiles/Farm/Wild Field.tres @@ -0,0 +1,37 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=9 format=3 uid="uid://bpi8ngu73jg15"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_xr6hc"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_vby5q"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_2of5e"] +[ext_resource type="Script" uid="uid://5h2g03dsx026" path="res://ResourceScripts/FieldRequirements/FieldMax.gd" id="3_hfx08"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_hfx08"] + +[sub_resource type="Resource" id="Resource_xr6hc"] +script = ExtResource("1_xr6hc") +field = 3 +amount = 1 +range = 2.4 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_vby5q"] +script = ExtResource("1_xr6hc") +field = 4 +amount = 1 +range = 3.4 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_yitr5"] +script = ExtResource("3_hfx08") +field = 1 +metadata/_custom_type_script = "uid://5h2g03dsx026" + +[resource] +script = ExtResource("4_hfx08") +tile_name = "Wild Field" +style = 1 +color = Color(0.11764706, 0.45882353, 0.19215687, 1) +field_requirements = Array[ExtResource("2_vby5q")]([SubResource("Resource_yitr5")]) +field_emissions = Array[ExtResource("1_xr6hc")]([SubResource("Resource_xr6hc"), SubResource("Resource_vby5q")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Housing/Housing.tres b/Tiles/Housing/Housing.tres new file mode 100644 index 0000000..f0eaff1 --- /dev/null +++ b/Tiles/Housing/Housing.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=7 format=3 uid="uid://bydddpqn0s43j"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_urkof"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_ad1a7"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_vifl3"] +[ext_resource type="Resource" uid="uid://bayaly21u33xj" path="res://Tiles/Housing/SmallLogCabin.tres" id="4_vifl3"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_y6hfj"] +[ext_resource type="Resource" uid="uid://ducxyya4a00oa" path="res://Tiles/Housing/Resting Spot.tres" id="6_ad1a7"] + +[resource] +script = ExtResource("4_y6hfj") +tile_name = "Housing" +style = 2 +color = Color(0.93333334, 0.39215687, 0.39215687, 1) +upgrade_paths = Array[ExtResource("4_y6hfj")]([ExtResource("4_vifl3"), ExtResource("6_ad1a7")]) diff --git a/Tiles/Housing/Resting Spot.tres b/Tiles/Housing/Resting Spot.tres new file mode 100644 index 0000000..501ffac --- /dev/null +++ b/Tiles/Housing/Resting Spot.tres @@ -0,0 +1,50 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=12 format=3 uid="uid://ducxyya4a00oa"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_ub44p"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_dege1"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_u7fxu"] +[ext_resource type="Script" uid="uid://5h2g03dsx026" path="res://ResourceScripts/FieldRequirements/FieldMax.gd" id="3_vev7e"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_vev7e"] +[ext_resource type="Resource" uid="uid://bayaly21u33xj" path="res://Tiles/Housing/SmallLogCabin.tres" id="5_2lp62"] + +[sub_resource type="Resource" id="Resource_ub44p"] +script = ExtResource("1_ub44p") +field = 1 +amount = 1 +range = 6.0 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_2lp62"] +script = ExtResource("3_vev7e") +field = 1 +metadata/_custom_type_script = "uid://5h2g03dsx026" + +[sub_resource type="Resource" id="Resource_vev7e"] +script = ExtResource("3_u7fxu") +resource = 3 +amount = 1 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_dege1"] +script = ExtResource("3_u7fxu") +resource = 1 +amount = 1 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_u7fxu"] +script = ExtResource("3_u7fxu") +resource = 1 +amount = 5 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[resource] +script = ExtResource("4_vev7e") +tile_name = "Resting Spot" +color = Color(0.16799998, 0.6272, 0.84, 1) +field_requirements = Array[ExtResource("2_dege1")]([SubResource("Resource_2lp62")]) +field_emissions = Array[ExtResource("1_ub44p")]([SubResource("Resource_ub44p")]) +resource_consumption = Array[ExtResource("3_u7fxu")]([SubResource("Resource_vev7e")]) +resource_prouction = Array[ExtResource("3_u7fxu")]([SubResource("Resource_dege1")]) +resource_stockpiles = Array[ExtResource("3_u7fxu")]([SubResource("Resource_u7fxu")]) +upgrade_paths = Array[ExtResource("4_vev7e")]([ExtResource("5_2lp62")]) diff --git a/Tiles/Housing/SmallLogCabin.tres b/Tiles/Housing/SmallLogCabin.tres new file mode 100644 index 0000000..7967ad0 --- /dev/null +++ b/Tiles/Housing/SmallLogCabin.tres @@ -0,0 +1,48 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=11 format=3 uid="uid://bayaly21u33xj"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_8x1k6"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_a3657"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_704a6"] +[ext_resource type="Script" uid="uid://b3ly4vy7xaynq" path="res://ResourceScripts/FieldRequirements/FieldMin.gd" id="3_o1qah"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_abho1"] + +[sub_resource type="Resource" id="Resource_rmy5c"] +script = ExtResource("1_8x1k6") +field = 1 +amount = 1 +range = 3.4 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_m7mkw"] +script = ExtResource("3_o1qah") +min = 1 +metadata/_custom_type_script = "uid://b3ly4vy7xaynq" + +[sub_resource type="Resource" id="Resource_0amp2"] +script = ExtResource("3_704a6") +resource = 3 +amount = 3 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_3d64m"] +script = ExtResource("3_704a6") +resource = 1 +amount = 1 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_abho1"] +script = ExtResource("3_704a6") +amount = 60 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[resource] +script = ExtResource("4_abho1") +tile_name = "Small Log Cabin" +color = Color(0.4117647, 0.22745098, 0.11764706, 1) +field_requirements = Array[ExtResource("2_a3657")]([SubResource("Resource_m7mkw")]) +field_emissions = Array[ExtResource("1_8x1k6")]([SubResource("Resource_rmy5c")]) +resource_requirements = Array[ExtResource("3_704a6")]([SubResource("Resource_abho1")]) +resource_consumption = Array[ExtResource("3_704a6")]([SubResource("Resource_0amp2")]) +resource_prouction = Array[ExtResource("3_704a6")]([SubResource("Resource_3d64m")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Industry/Foraging Camp.tres b/Tiles/Industry/Foraging Camp.tres new file mode 100644 index 0000000..3eab8e6 --- /dev/null +++ b/Tiles/Industry/Foraging Camp.tres @@ -0,0 +1,50 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=11 format=3 uid="uid://ctnjk4bt5mlps"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_3r0pf"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_8u1an"] +[ext_resource type="Script" uid="uid://b3ly4vy7xaynq" path="res://ResourceScripts/FieldRequirements/FieldMin.gd" id="3_v4xpb"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_vkbw8"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_v4xpb"] + +[sub_resource type="Resource" id="Resource_3r0pf"] +script = ExtResource("1_3r0pf") +field = 3 +amount = -4 +range = 5.0 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_hi55i"] +script = ExtResource("3_v4xpb") +field = 3 +min = 6 +metadata/_custom_type_script = "uid://b3ly4vy7xaynq" + +[sub_resource type="Resource" id="Resource_vkbw8"] +script = ExtResource("3_vkbw8") +resource = 1 +amount = 1 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_v4xpb"] +script = ExtResource("3_vkbw8") +resource = 3 +amount = 5 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_8fufg"] +script = ExtResource("3_vkbw8") +resource = 3 +amount = 100 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[resource] +script = ExtResource("4_v4xpb") +tile_name = "Foraging Camp" +color = Color(0.15294118, 0.42352942, 0.6627451, 1) +field_requirements = Array[ExtResource("2_8u1an")]([SubResource("Resource_hi55i")]) +field_emissions = Array[ExtResource("1_3r0pf")]([SubResource("Resource_3r0pf")]) +resource_consumption = Array[ExtResource("3_vkbw8")]([SubResource("Resource_vkbw8")]) +resource_prouction = Array[ExtResource("3_vkbw8")]([SubResource("Resource_v4xpb")]) +resource_stockpiles = Array[ExtResource("3_vkbw8")]([SubResource("Resource_8fufg")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Industry/Gathering Camp.tres b/Tiles/Industry/Gathering Camp.tres new file mode 100644 index 0000000..fa50b50 --- /dev/null +++ b/Tiles/Industry/Gathering Camp.tres @@ -0,0 +1,16 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=7 format=3 uid="uid://bl6ps1ycelcxx"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_olh0m"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_olh0m"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_uba8x"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_ex0ko"] +[ext_resource type="Resource" uid="uid://behst2ge8nu8e" path="res://Tiles/Industry/Logging Camp.tres" id="5_adjmk"] +[ext_resource type="Resource" uid="uid://ctnjk4bt5mlps" path="res://Tiles/Industry/Foraging Camp.tres" id="6_lmdb6"] + +[resource] +script = ExtResource("4_ex0ko") +tile_name = "Gathering Camp" +style = 2 +color = Color(0.65, 0.57135, 0.43549997, 1) +upgrade_paths = Array[ExtResource("4_ex0ko")]([ExtResource("6_lmdb6"), ExtResource("5_adjmk")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Industry/Logging Camp.tres b/Tiles/Industry/Logging Camp.tres new file mode 100644 index 0000000..8a3fa16 --- /dev/null +++ b/Tiles/Industry/Logging Camp.tres @@ -0,0 +1,50 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=11 format=3 uid="uid://behst2ge8nu8e"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_ln2xb"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_ln2xb"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_50uuq"] +[ext_resource type="Script" uid="uid://b3ly4vy7xaynq" path="res://ResourceScripts/FieldRequirements/FieldMin.gd" id="3_lrtjs"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_rgqp8"] + +[sub_resource type="Resource" id="Resource_3r0pf"] +script = ExtResource("1_ln2xb") +field = 3 +amount = -4 +range = 4.9 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_50uuq"] +script = ExtResource("3_lrtjs") +field = 4 +min = 10 +metadata/_custom_type_script = "uid://b3ly4vy7xaynq" + +[sub_resource type="Resource" id="Resource_vkbw8"] +script = ExtResource("3_50uuq") +resource = 1 +amount = 1 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_v4xpb"] +script = ExtResource("3_50uuq") +resource = 3 +amount = 10 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[sub_resource type="Resource" id="Resource_8fufg"] +script = ExtResource("3_50uuq") +resource = 3 +amount = 100 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[resource] +script = ExtResource("4_rgqp8") +tile_name = "Gathering Camp" +color = Color(0.42, 0.19725999, 0.058799993, 1) +field_requirements = Array[ExtResource("2_ln2xb")]([SubResource("Resource_50uuq")]) +field_emissions = Array[ExtResource("1_ln2xb")]([SubResource("Resource_3r0pf")]) +resource_consumption = Array[ExtResource("3_50uuq")]([SubResource("Resource_vkbw8")]) +resource_prouction = Array[ExtResource("3_50uuq")]([SubResource("Resource_v4xpb")]) +resource_stockpiles = Array[ExtResource("3_50uuq")]([SubResource("Resource_8fufg")]) +metadata/_custom_type_script = "uid://y688w7tmv2dr" diff --git a/Tiles/Road/Cleared Path.tres b/Tiles/Road/Cleared Path.tres new file mode 100644 index 0000000..efec298 --- /dev/null +++ b/Tiles/Road/Cleared Path.tres @@ -0,0 +1,28 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=7 format=3 uid="uid://djc16ouv6gmv1"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_g7euo"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_f70jb"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_0x3jy"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="4_hq0rs"] + +[sub_resource type="Resource" id="Resource_bu2mc"] +script = ExtResource("1_g7euo") +amount = 1 +range = 2.4 +falloff = 1 +metadata/_custom_type_script = "uid://cggmew2iau84h" + +[sub_resource type="Resource" id="Resource_1q03n"] +script = ExtResource("3_0x3jy") +resource = 1 +amount = 10 +metadata/_custom_type_script = "uid://nroinmreopp4" + +[resource] +script = ExtResource("4_hq0rs") +tile_name = "Cleared Path" +area_type = 1 +style = 1 +color = Color(1, 1, 1, 1) +field_emissions = Array[ExtResource("1_g7euo")]([SubResource("Resource_bu2mc")]) +resource_requirements = Array[ExtResource("3_0x3jy")]([SubResource("Resource_1q03n")]) diff --git a/Tiles/Road/Path.tres b/Tiles/Road/Path.tres new file mode 100644 index 0000000..3b3b503 --- /dev/null +++ b/Tiles/Road/Path.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="BuildingData" load_steps=6 format=3 uid="uid://b4jvgwx5i6785"] + +[ext_resource type="Script" uid="uid://cggmew2iau84h" path="res://ResourceScripts/FieldEmission.gd" id="1_bu2mc"] +[ext_resource type="Script" uid="uid://y688w7tmv2dr" path="res://ResourceScripts/BuildingData.gd" id="1_mip7k"] +[ext_resource type="Script" uid="uid://c2winf4nct0u7" path="res://ResourceScripts/FieldRequirements/FieldRequirement.gd" id="2_gmo0p"] +[ext_resource type="Script" uid="uid://nroinmreopp4" path="res://ResourceScripts/ResourceAmount.gd" id="3_g11go"] +[ext_resource type="Resource" uid="uid://djc16ouv6gmv1" path="res://Tiles/Road/Cleared Path.tres" id="5_r5pii"] + +[resource] +script = ExtResource("1_mip7k") +tile_name = "Path" +area_type = 1 +style = 2 +color = Color(1, 1, 1, 1) +upgrade_paths = Array[ExtResource("1_mip7k")]([ExtResource("5_r5pii")]) diff --git a/Tiles/farm.tscn b/Tiles/farm.tscn deleted file mode 100644 index 8d900f2..0000000 --- a/Tiles/farm.tscn +++ /dev/null @@ -1,12 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://cgygrdlj7ty6s"] - -[ext_resource type="Script" uid="uid://cqhn1h452g2li" path="res://Scripts/TileTransform.gd" id="1_jjdrc"] -[ext_resource type="Script" uid="uid://2mbjbn23ry8t" path="res://Scripts/TileRenderer.gd" id="2_p4boj"] - -[node name="Farm" type="Node2D"] -script = ExtResource("1_jjdrc") - -[node name="TileRenderer" type="Node2D" parent="."] -script = ExtResource("2_p4boj") -base_color = Color(0.0828, 0.36, 0.13362, 1) -top_color = Color(0.0108, 0.18, 0.04182, 1) diff --git a/World.tscn b/World.tscn index 93d44dc..e2cea50 100644 --- a/World.tscn +++ b/World.tscn @@ -1,9 +1,22 @@ -[gd_scene load_steps=5 format=3 uid="uid://co6md8v2b8hhu"] +[gd_scene load_steps=18 format=3 uid="uid://co6md8v2b8hhu"] [ext_resource type="Script" uid="uid://8lkq20gwkrvx" path="res://Scripts/Grid.gd" id="1_2s04l"] [ext_resource type="Script" uid="uid://cuqcfju7y8ply" path="res://Scripts/SelectionManager.gd" id="1_anesy"] -[ext_resource type="PackedScene" uid="uid://cgygrdlj7ty6s" path="res://Tiles/farm.tscn" id="2_7ixwv"] [ext_resource type="Script" uid="uid://xe60g0el2j5x" path="res://Scripts/GridInput.gd" id="3_62nr3"] +[ext_resource type="Script" uid="uid://du3m15i8ahlu5" path="res://Scripts/CursorPool.gd" id="3_fvag4"] +[ext_resource type="Script" uid="uid://j6fc2qc5t3qa" path="res://Scripts/FPSCounter.gd" id="5_eu7l1"] +[ext_resource type="Theme" uid="uid://dks3mt6h14i2s" path="res://Gradients/DefaultTheme.tres" id="6_bah7m"] +[ext_resource type="Script" uid="uid://d1lhn37ijatdp" path="res://Scripts/BuildMenu.gd" id="6_wygdx"] +[ext_resource type="Script" uid="uid://p8y4cfg2aonj" path="res://Scripts/BuildButton.gd" id="7_bah7m"] +[ext_resource type="Resource" uid="uid://bydddpqn0s43j" path="res://Tiles/Housing/Housing.tres" id="9_fvag4"] +[ext_resource type="Resource" uid="uid://c2ajd2c6fu04d" path="res://Tiles/Farm/Reservation.tres" id="10_b2ar6"] +[ext_resource type="Resource" uid="uid://b4jvgwx5i6785" path="res://Tiles/Road/Path.tres" id="10_kva58"] +[ext_resource type="Resource" uid="uid://bl6ps1ycelcxx" path="res://Tiles/Industry/Gathering Camp.tres" id="11_ee7l0"] +[ext_resource type="Script" uid="uid://cj8bj60oyrc4f" path="res://Scripts/DebugMenu.gd" id="11_kva58"] +[ext_resource type="Script" uid="uid://cg3qqaogq7h8q" path="res://Scripts/ResourcesPanel.gd" id="12_f5c0m"] +[ext_resource type="Script" uid="uid://ngiejslhl66p" path="res://SelectionUI.gd" id="13_1fphk"] +[ext_resource type="Script" uid="uid://rr8s2u7xswtc" path="res://Scripts/Calendar.gd" id="13_6w02q"] +[ext_resource type="Theme" uid="uid://s3apw670qymv" path="res://Gradients/ResourcesTheme.tres" id="15_gn8l5"] [node name="Root" type="Node2D"] @@ -11,25 +24,176 @@ [node name="Grid" type="Node2D" parent="."] script = ExtResource("1_2s04l") -cells = 10 +cells = 15 cell_size = 48 +grid_color = Color(0.6627451, 0.7764706, 0.5647059, 1) +line_color = Color(1, 1, 1, 0) +debug_overlay_enabled = false +debug_overlay_display_values = null -[node name="Tiles" type="Node" parent="Grid"] - -[node name="Farm" parent="Grid" instance=ExtResource("2_7ixwv")] -position = Vector2(-96, 192) -size = Vector2i(6, 2) - -[node name="Farm2" parent="Grid" instance=ExtResource("2_7ixwv")] -position = Vector2(-144, -120) -size = Vector2i(2, 3) - -[node name="Farm3" parent="Grid" instance=ExtResource("2_7ixwv")] -position = Vector2(168, -72) - -[node name="GridInput" type="Node2D" parent="."] +[node name="GridInput" type="Node2D" parent="." node_paths=PackedStringArray("selection_manager")] script = ExtResource("3_62nr3") -highlight_color = Color(1, 1, 1, 0.301961) +selection_manager = NodePath("../SelectionManager") + +[node name="CursorPool" type="Node2D" parent="GridInput"] +script = ExtResource("3_fvag4") [node name="SelectionManager" type="Node2D" parent="."] script = ExtResource("1_anesy") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="Left Panel" type="Panel" parent="CanvasLayer"] +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 300.0 +theme = ExtResource("6_bah7m") + +[node name="TabContainer" type="TabContainer" parent="CanvasLayer/Left Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +current_tab = 1 + +[node name="Build" type="TabBar" parent="CanvasLayer/Left Panel/TabContainer"] +visible = false +layout_mode = 2 +metadata/_tab_index = 0 + +[node name="VBox" type="VBoxContainer" parent="CanvasLayer/Left Panel/TabContainer/Build" node_paths=PackedStringArray("grid_input", "grid")] +layout_mode = 0 +offset_right = 280.0 +offset_bottom = 826.0 +script = ExtResource("6_wygdx") +grid_input = NodePath("../../../../../GridInput") +grid = NodePath("../../../../../Grid") + +[node name="Label" type="Label" parent="CanvasLayer/Left Panel/TabContainer/Build/VBox"] +layout_mode = 2 +text = "Zoning" + +[node name="Build Road" type="Button" parent="CanvasLayer/Left Panel/TabContainer/Build/VBox"] +layout_mode = 2 +text = "Road" +script = ExtResource("7_bah7m") +building = ExtResource("10_kva58") + +[node name="Build House" type="Button" parent="CanvasLayer/Left Panel/TabContainer/Build/VBox"] +layout_mode = 2 +text = "Housing" +script = ExtResource("7_bah7m") +building = ExtResource("9_fvag4") + +[node name="Farmland" type="Button" parent="CanvasLayer/Left Panel/TabContainer/Build/VBox"] +layout_mode = 2 +text = "Housing" +script = ExtResource("7_bah7m") +building = ExtResource("10_b2ar6") + +[node name="Foraging Camp" type="Button" parent="CanvasLayer/Left Panel/TabContainer/Build/VBox"] +layout_mode = 2 +text = "Housing" +script = ExtResource("7_bah7m") +building = ExtResource("11_ee7l0") + +[node name="Debug" type="TabBar" parent="CanvasLayer/Left Panel/TabContainer"] +layout_mode = 2 +metadata/_tab_index = 1 + +[node name="Overlay Controller" type="VBoxContainer" parent="CanvasLayer/Left Panel/TabContainer/Debug" node_paths=PackedStringArray("grid", "overlay_enabled_button", "overlay_selection_button", "overlay_display_values")] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("11_kva58") +grid = NodePath("../../../../../Grid") +overlay_enabled_button = NodePath("Enable") +overlay_selection_button = NodePath("Select Field") +overlay_display_values = NodePath("Display Values") + +[node name="Enable" type="CheckButton" parent="CanvasLayer/Left Panel/TabContainer/Debug/Overlay Controller"] +layout_mode = 2 +text = "Field Overlay" + +[node name="Display Values" type="CheckButton" parent="CanvasLayer/Left Panel/TabContainer/Debug/Overlay Controller"] +layout_mode = 2 +text = "Display Values" + +[node name="Select Field" type="OptionButton" parent="CanvasLayer/Left Panel/TabContainer/Debug/Overlay Controller"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Selection" type="TabBar" parent="CanvasLayer/Left Panel/TabContainer"] +visible = false +layout_mode = 2 +metadata/_tab_index = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Left Panel/TabContainer/Selection" node_paths=PackedStringArray("selection_manager", "name_label", "selection_panel", "content_panel")] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("13_1fphk") +selection_manager = NodePath("../../../../../SelectionManager") +name_label = NodePath("Label") +selection_panel = NodePath("..") +content_panel = NodePath("VBoxContainer") + +[node name="Label" type="Label" parent="CanvasLayer/Left Panel/TabContainer/Selection/VBoxContainer"] +layout_mode = 2 +text = "Selected Item Name" + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Left Panel/TabContainer/Selection/VBoxContainer"] +layout_mode = 2 + +[node name="Right Panel" type="Panel" parent="CanvasLayer"] +anchors_preset = 11 +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -273.0 +grow_horizontal = 0 +grow_vertical = 2 +theme = ExtResource("6_bah7m") + +[node name="MarginContainer" type="MarginContainer" parent="CanvasLayer/Right Panel"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/Right Panel/MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/Right Panel/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Calendar" type="Label" parent="CanvasLayer/Right Panel/MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 1 +text = "Calendar" +script = ExtResource("13_6w02q") + +[node name="FPS" type="Label" parent="CanvasLayer/Right Panel/MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 1 +text = "FPS: 9999" +script = ExtResource("5_eu7l1") + +[node name="HSeparator" type="HSeparator" parent="CanvasLayer/Right Panel/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Resource Panels" type="VBoxContainer" parent="CanvasLayer/Right Panel/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme = ExtResource("15_gn8l5") +script = ExtResource("12_f5c0m") diff --git a/addons/CustomEditors/BuildingDataHelper.gd b/addons/CustomEditors/BuildingDataHelper.gd new file mode 100644 index 0000000..adf0dc7 --- /dev/null +++ b/addons/CustomEditors/BuildingDataHelper.gd @@ -0,0 +1,19 @@ + +extends EditorInspectorPlugin + +func _can_handle(object): + return object is BuildingData + +func _parse_begin(object): + # Example: Add a label at the top + var label = Label.new() + label.text = "Custom Editor for MyData!" + add_custom_control(label) + return true + +func _parse_property(object, type, path, hint, hint_text, usage, wide): + return true +func _parse_group(object, name): + return false +func _parse_category(object, name): + return true diff --git a/addons/tile_helper/TileHelper.gd.uid b/addons/CustomEditors/BuildingDataHelper.gd.uid similarity index 100% rename from addons/tile_helper/TileHelper.gd.uid rename to addons/CustomEditors/BuildingDataHelper.gd.uid diff --git a/addons/CustomEditors/CustomEditors.gd b/addons/CustomEditors/CustomEditors.gd new file mode 100644 index 0000000..d80b385 --- /dev/null +++ b/addons/CustomEditors/CustomEditors.gd @@ -0,0 +1,10 @@ +@tool +extends EditorPlugin + +var inspector = preload("res://addons/CustomEditors/BuildingDataHelper.gd").new() + +func _enter_tree(): + add_inspector_plugin(inspector) + +func _exit_tree(): + remove_inspector_plugin(inspector) diff --git a/addons/CustomEditors/CustomEditors.gd.uid b/addons/CustomEditors/CustomEditors.gd.uid new file mode 100644 index 0000000..0fad1f5 --- /dev/null +++ b/addons/CustomEditors/CustomEditors.gd.uid @@ -0,0 +1 @@ +uid://uuouru33qiot diff --git a/addons/CustomEditors/plugin.cfg b/addons/CustomEditors/plugin.cfg new file mode 100644 index 0000000..a091bf5 --- /dev/null +++ b/addons/CustomEditors/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Custom Editors" +description="" +author="Valerie" +version="1.0" +script="CustomEditors.gd" diff --git a/addons/tile_helper/TileHelper.gd b/addons/tile_helper/TileHelper.gd deleted file mode 100644 index 7d874e3..0000000 --- a/addons/tile_helper/TileHelper.gd +++ /dev/null @@ -1,13 +0,0 @@ -@tool -extends EditorPlugin - -func _handles(object): - return object is Tile - -func _enter_tree(): - # Initialization of the plugin goes here. - pass - -func _exit_tree(): - # Clean-up of the plugin goes here. - pass diff --git a/addons/tile_helper/plugin.cfg b/addons/tile_helper/plugin.cfg deleted file mode 100644 index 111b378..0000000 --- a/addons/tile_helper/plugin.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[plugin] - -name="Tile Helper" -description="" -author="" -version="" -script="TileHelper.gd" diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..bf55280 --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,42 @@ +[preset.0] + +name="Linux" +platform="Linux" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="../../../Downloads/CityGame.x86_64" +patches=PackedStringArray() +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=false +texture_format/s3tc_bptc=true +texture_format/etc2_astc=false +shader_baker/enabled=false +binary_format/architecture="x86_64" +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="#!/usr/bin/env bash +export DISPLAY=:0 +unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" +\"{temp_dir}/{exe_name}\" {cmd_args}" +ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash +kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") +rm -rf \"{temp_dir}\"" diff --git a/icon.svg b/icon.svg deleted file mode 100644 index b370ceb..0000000 --- a/icon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/icon.svg.import b/icon.svg.import deleted file mode 100644 index 85f2f06..0000000 --- a/icon.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://txyjconsf31o" -path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://icon.svg" -dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot index b5c662b..0869fe4 100644 --- a/project.godot +++ b/project.godot @@ -12,23 +12,24 @@ config_version=5 config/name="MobileGame" run/main_scene="res://World.tscn" -config/features=PackedStringArray("4.4", "Mobile") -config/icon="res://icon.svg" +config/features=PackedStringArray("4.5", "Mobile") [autoload] Util="*res://Scripts/Util.gd" +ResourceController="*res://Scripts/ResourceController.gd" +Clock="*res://Scripts/Clock.gd" [display] window/size/viewport_width=1600 window/size/viewport_height=900 +window/vsync/vsync_mode=0 -[editor_plugins] +[gui] -enabled=PackedStringArray() +theme/default_font_multichannel_signed_distance_field=true [rendering] -renderer/rendering_method="mobile" -environment/defaults/default_clear_color=Color(0, 0, 0, 1) +environment/defaults/default_clear_color=Color(0.8745098, 0.8745098, 0.8745098, 1)