tracking units

This commit is contained in:
hz
2026-05-19 05:20:28 -05:00
parent e78eb24543
commit b0b270f4d8
8 changed files with 258 additions and 22 deletions
@@ -432,7 +432,12 @@ func _can_build_mine_on_selected_tile() -> bool:
func _can_build_barracks_on_selected_tile() -> bool:
return _can_build_on_selected_tile("")
if not _can_build_on_selected_tile(""):
return false
var location: Dictionary = grid_view.get_visible_location(selected_q, selected_r)
var kind: String = str(location.get("kind", ""))
return kind != "Home"
func _can_build_on_selected_tile(required_terrain: String) -> bool:
@@ -813,6 +818,13 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack
completed_scout_count = int(units.get("completedScouts", 0))
completed_archer_count = int(units.get("completedArchers", 0))
if grid_view:
grid_view.set_completed_archers(completed_archer_count)
var unit_instances: Array = []
var raw_units = units.get("units", [])
if typeof(raw_units) == TYPE_ARRAY:
unit_instances = raw_units
grid_view.set_unit_instances(unit_instances)
unit_label.text = "Scouts: %d | Archers: %d | Queue: %d" % [completed_scout_count, completed_archer_count, training.size()]
_update_action_buttons()
@@ -861,6 +873,10 @@ func _request_unit_training(unit_type: String) -> void:
else:
train_button.disabled = true
coordinate_label.text = "Starting %s training..." % unit_type
var request_body := { "unitType": unit_type }
if unit_type == "Archer":
request_body["q"] = selected_q
request_body["r"] = selected_r
var error: int = train_unit_request.request(
LOCATIONS_BASE_URL + "/api/units/train",
PackedStringArray([
@@ -868,7 +884,7 @@ func _request_unit_training(unit_type: String) -> void:
"Authorization: Bearer %s" % access_token
]),
HTTPClient.METHOD_POST,
JSON.stringify({ "unitType": unit_type })
JSON.stringify(request_body)
)
if error != OK:
_update_action_buttons()
@@ -22,6 +22,8 @@ var tiles: Array[Dictionary] = []
var visible_tiles: Dictionary = {}
var owned_tiles: Dictionary = {}
var rival_tiles: Dictionary = {}
var completed_archer_count := 0
var unit_instances: Array[Dictionary] = []
func _ready() -> void:
@@ -174,6 +176,10 @@ func _draw_tile(tile: Dictionary) -> void:
elif not building_type.is_empty():
_draw_building_marker(center, height)
var archer_count := _archer_count_at(q, r)
if archer_count > 0:
_draw_archer_unit_marker(center, height, archer_count)
func _draw_control_regions(sorted_tiles: Array) -> void:
for control in ["owned", "rival"]:
@@ -417,6 +423,44 @@ func _draw_building_marker(center: Vector2, height: float) -> void:
draw_line(left, right.lerp(top_right, 0.2), post_color.darkened(0.12), 1.5 * zoom)
func _draw_archer_unit_marker(center: Vector2, height: float, count: int) -> void:
var marker_center: Vector2 = center + Vector2(18.0 * zoom, -height * zoom - 14.0 * zoom)
var marker_scale: float = zoom
var cloak_color := Color(0.20, 0.38, 0.26)
var hood_color := Color(0.12, 0.23, 0.16)
var bow_color := Color(0.72, 0.50, 0.26)
var string_color := Color(0.92, 0.86, 0.66)
var arrow_color := Color(0.86, 0.78, 0.56)
var outline_color := Color(0.04, 0.06, 0.05)
var badge_color := Color(0.08, 0.12, 0.11)
var badge_border := Color(0.76, 0.62, 0.28)
draw_circle(marker_center + Vector2(1, 2) * marker_scale, 10.0 * marker_scale, Color(0.01, 0.02, 0.02, 0.55))
var body := PackedVector2Array([
marker_center + Vector2(-7.0, 8.0) * marker_scale,
marker_center + Vector2(0.0, -9.0) * marker_scale,
marker_center + Vector2(8.0, 8.0) * marker_scale
])
draw_colored_polygon(body, cloak_color)
draw_polyline(_closed_points(body), outline_color, 1.2 * marker_scale)
draw_circle(marker_center + Vector2(0.0, -6.0) * marker_scale, 4.5 * marker_scale, hood_color)
var bow_center: Vector2 = marker_center + Vector2(8.0, -1.0) * marker_scale
draw_arc(bow_center, 10.0 * marker_scale, deg_to_rad(-82), deg_to_rad(82), 16, bow_color, 2.0 * marker_scale)
draw_line(bow_center + Vector2(1.8, -9.8) * marker_scale, bow_center + Vector2(1.8, 9.8) * marker_scale, string_color, 1.0 * marker_scale)
draw_line(marker_center + Vector2(1.0, -1.0) * marker_scale, marker_center + Vector2(18.0, -1.0) * marker_scale, arrow_color, 1.6 * marker_scale)
draw_line(marker_center + Vector2(18.0, -1.0) * marker_scale, marker_center + Vector2(14.0, -4.0) * marker_scale, arrow_color, 1.2 * marker_scale)
draw_line(marker_center + Vector2(18.0, -1.0) * marker_scale, marker_center + Vector2(14.0, 2.0) * marker_scale, arrow_color, 1.2 * marker_scale)
if count > 1:
var badge_center: Vector2 = marker_center + Vector2(10.0, 9.0) * marker_scale
draw_circle(badge_center, 6.0 * marker_scale, badge_color)
draw_arc(badge_center, 6.0 * marker_scale, 0.0, TAU, 18, badge_border, 1.4 * marker_scale)
var font := ThemeDB.fallback_font
draw_string(font, badge_center + Vector2(-3.5, 3.5) * marker_scale, str(min(count, 9)), HORIZONTAL_ALIGNMENT_LEFT, -1, 9 * marker_scale, Color(0.93, 0.86, 0.58))
func _tile_data(q: int, r: int) -> Dictionary:
for tile in tiles:
if int(tile["q"]) == q and int(tile["r"]) == r:
@@ -474,6 +518,19 @@ func has_owned_neighbor(q: int, r: int) -> bool:
return false
func set_completed_archers(count: int) -> void:
completed_archer_count = max(0, count)
queue_redraw()
func set_unit_instances(units: Array) -> void:
unit_instances.clear()
for item in units:
if typeof(item) == TYPE_DICTIONARY:
unit_instances.append(item)
queue_redraw()
func _tile_key(q: int, r: int) -> String:
return "%d,%d" % [q, r]
@@ -530,6 +587,9 @@ func _tile_display_label(key: String, data: Dictionary) -> String:
building_label = " | Mine" if building_status == "Built" or building_status.is_empty() else " | Mine building"
elif building_type == "Barracks":
building_label = " | Barracks" if building_status == "Built" or building_status.is_empty() else " | Barracks building"
var archer_count := _archer_count_at(int(data.get("q", 0)), int(data.get("r", 0)))
if archer_count > 0:
building_label += " | Archers: %d" % archer_count
if home_tile == Vector2i(int(data.get("q", 0)), int(data.get("r", 0))):
return "%s | Your home%s" % [terrain, building_label]
@@ -544,6 +604,38 @@ func _tile_display_label(key: String, data: Dictionary) -> String:
return "%s | Unclaimed%s" % [terrain, building_label]
func _archer_station_tile() -> Vector2i:
var station := Vector2i(9999, 9999)
for key in owned_tiles.keys():
var location: Dictionary = owned_tiles[key]
var building_type: String = _nullable_string(location.get("buildingType", ""))
var building_status: String = _nullable_string(location.get("buildingStatus", ""))
if building_type != "Barracks":
continue
if not (building_status == "Built" or building_status.is_empty()):
continue
var candidate := Vector2i(int(location.get("q", 0)), int(location.get("r", 0)))
if station.x == 9999 or candidate.y < station.y or (candidate.y == station.y and candidate.x < station.x):
station = candidate
return home_tile if station.x == 9999 else station
func _archer_count_at(q: int, r: int) -> int:
var count := 0
for unit in unit_instances:
if str(unit.get("unitType", "")) != "Archer":
continue
if int(unit.get("q", 0)) == q and int(unit.get("r", 0)) == r:
count += 1
if count == 0 and completed_archer_count > 0 and Vector2i(q, r) == _archer_station_tile():
count = completed_archer_count
return count
func _owner_username(location: Dictionary) -> String:
var owner_value: Variant = location.get("ownerUsername", "")
if owner_value == null: