tweaking building logic

This commit is contained in:
hz
2026-05-18 21:21:34 -05:00
parent 984a82bf48
commit 973eda5b44
4 changed files with 94 additions and 9 deletions
@@ -28,6 +28,8 @@ var train_button: Button
var unit_label: Label
var training_label: Label
var training_bar: ProgressBar
var building_label: Label
var building_bar: ProgressBar
var training_started_unix := 0.0
var training_completes_unix := 0.0
var training_completion_refresh_requested := false
@@ -215,6 +217,27 @@ func _build_ui() -> void:
training_bar.add_theme_stylebox_override("fill", _progress_style(Color(0.28, 0.62, 0.72), Color(0.43, 0.82, 0.92)))
training_box.add_child(training_bar)
var building_box := VBoxContainer.new()
building_box.custom_minimum_size = Vector2(150, 0)
building_box.add_theme_constant_override("separation", 4)
bottom_content.add_child(building_box)
building_label = Label.new()
building_label.text = "Build: idle"
building_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
building_label.add_theme_font_size_override("font_size", 12)
building_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
building_box.add_child(building_label)
building_bar = ProgressBar.new()
building_bar.custom_minimum_size = Vector2(150, 8)
building_bar.max_value = 1.0
building_bar.value = 0.0
building_bar.show_percentage = false
building_bar.add_theme_stylebox_override("background", _progress_style(Color(0.035, 0.055, 0.055), Color(0.18, 0.28, 0.26)))
building_bar.add_theme_stylebox_override("fill", _progress_style(Color(0.62, 0.42, 0.22), Color(0.86, 0.62, 0.34)))
building_box.add_child(building_bar)
train_button = _small_button("Train Scout 50g")
train_button.pressed.connect(_train_scout)
bottom_content.add_child(train_button)
@@ -388,6 +411,7 @@ func _on_visible_request_completed(result: int, response_code: int, _headers: Pa
var username: String = str(session.get("username", ""))
var visible_locations: Array = parsed
grid_view.set_visible_locations(visible_locations, username)
_sync_active_building_timer(visible_locations, username)
coordinate_label.text = "Visible territory loaded. Sight extends 3 hexes beyond controlled land."
_refresh_player_state()
resources_timer.start()
@@ -644,6 +668,7 @@ func _on_build_request_completed(result: int, response_code: int, _headers: Pack
building_started_unix = _parse_utc_timestamp(str(location.get("buildingStartedAtUtc", "")))
building_completes_unix = _parse_utc_timestamp(str(location.get("buildingCompletesAtUtc", "")))
building_completion_refresh_requested = false
_update_building_timer()
coordinate_label.text = "Log Camp construction started. Completion takes 1 minute."
_load_visible_locations()
_refresh_player_state()
@@ -693,19 +718,61 @@ func _update_training_bar() -> void:
func _update_building_timer() -> void:
if not building_bar or not building_label:
return
if building_started_unix <= 0.0 or building_completes_unix <= 0.0:
building_bar.value = 0.0
building_label.text = "Build: idle"
return
var remaining: int = int(max(0, int(ceil(building_completes_unix - Time.get_unix_time_from_system()))))
var now: float = Time.get_unix_time_from_system()
var duration: float = max(1.0, building_completes_unix - building_started_unix)
var elapsed: float = clamp(now - building_started_unix, 0.0, duration)
var remaining: int = int(max(0, int(ceil(building_completes_unix - now))))
building_bar.value = elapsed / duration
if remaining > 0:
return
building_label.text = "Log Camp: %ds" % remaining
else:
building_label.text = "Log Camp: ready"
if not building_completion_refresh_requested:
if remaining <= 0 and not building_completion_refresh_requested:
building_completion_refresh_requested = true
_load_visible_locations()
_refresh_player_state()
func _sync_active_building_timer(locations: Array, username: String) -> void:
var best_started := 0.0
var best_completes := 0.0
for item in locations:
if typeof(item) != TYPE_DICTIONARY:
continue
var location: Dictionary = item
if str(location.get("ownerUsername", "")) != username:
continue
if str(location.get("buildingType", "")) != "LogCamp":
continue
if str(location.get("buildingStatus", "")) != "Building":
continue
var started: float = _parse_utc_timestamp(str(location.get("buildingStartedAtUtc", "")))
var completes: float = _parse_utc_timestamp(str(location.get("buildingCompletesAtUtc", "")))
if completes <= 0.0:
continue
if best_completes <= 0.0 or completes < best_completes:
best_started = started
best_completes = completes
building_started_unix = best_started
building_completes_unix = best_completes
building_completion_refresh_requested = false
_update_building_timer()
func _parse_utc_timestamp(timestamp: String) -> float:
if timestamp.is_empty():
return 0.0
@@ -303,9 +303,26 @@ func _draw_log_camp_marker(center: Vector2, height: float) -> void:
func _draw_building_marker(center: Vector2, height: float) -> void:
var marker_center: Vector2 = center + Vector2(0, -height * zoom - 1.0)
var radius: float = 7.0 * zoom
draw_arc(marker_center, radius, 0.0, TAU, 24, Color(0.95, 0.76, 0.28), 2.0 * zoom)
draw_line(marker_center + Vector2(-radius * 0.7, radius * 0.7), marker_center + Vector2(radius * 0.7, -radius * 0.7), Color(0.95, 0.76, 0.28), 2.0 * zoom)
var width: float = 20.0 * zoom
var scaffold_height: float = 15.0 * zoom
var post_color := Color(0.96, 0.68, 0.22)
var shadow_color := Color(0.18, 0.12, 0.06)
var left: Vector2 = marker_center + Vector2(-width * 0.45, scaffold_height * 0.45)
var right: Vector2 = marker_center + Vector2(width * 0.45, scaffold_height * 0.45)
var top_left: Vector2 = marker_center + Vector2(-width * 0.32, -scaffold_height * 0.42)
var top_right: Vector2 = marker_center + Vector2(width * 0.32, -scaffold_height * 0.42)
var peak: Vector2 = marker_center + Vector2(0, -scaffold_height * 0.78)
draw_line(left + Vector2(1, 1) * zoom, top_left + Vector2(1, 1) * zoom, shadow_color, 3.0 * zoom)
draw_line(right + Vector2(1, 1) * zoom, top_right + Vector2(1, 1) * zoom, shadow_color, 3.0 * zoom)
draw_line(top_left + Vector2(1, 1) * zoom, top_right + Vector2(1, 1) * zoom, shadow_color, 3.0 * zoom)
draw_line(left, top_left, post_color, 2.0 * zoom)
draw_line(right, top_right, post_color, 2.0 * zoom)
draw_line(top_left, peak, post_color.lightened(0.08), 2.0 * zoom)
draw_line(peak, top_right, post_color.lightened(0.08), 2.0 * zoom)
draw_line(top_left, top_right, post_color, 2.0 * zoom)
draw_line(left.lerp(top_left, 0.52), right.lerp(top_right, 0.52), post_color.darkened(0.08), 2.0 * zoom)
draw_line(left, right.lerp(top_right, 0.2), post_color.darkened(0.12), 1.5 * zoom)
func _tile_data(q: int, r: int) -> Dictionary:
+2 -1
View File
@@ -43,7 +43,8 @@ unclaimed visible location consumes one completed Scout.
Buildings are stored on location records. The first building type is `LogCamp`,
which can be built on controlled Forest territory, takes 60 seconds to build,
and adds 5 wood per minute to the owning player's resource generation after it
finishes.
finishes. Each location has one building slot; a building under construction
occupies that slot.
Timer settings are stored in the MongoDB `GameSettings` collection and are
seeded on first read:
@@ -137,7 +137,7 @@ public class LocationService
if (!string.IsNullOrWhiteSpace(location.BuildingType))
{
throw new InvalidOperationException("This location already has a building.");
throw new InvalidOperationException("This location already has a building or construction in progress.");
}
if (!string.Equals(location.Terrain, "Forest", StringComparison.OrdinalIgnoreCase))
@@ -166,7 +166,7 @@ public class LocationService
if (updated is null)
{
throw new InvalidOperationException("This location already has a building.");
throw new InvalidOperationException("This location already has a building or construction in progress.");
}
return updated;