tweaking building logic
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user