|
|
|
@@ -2,7 +2,9 @@ extends Control
|
|
|
|
|
|
|
|
|
|
const SESSION_PATH := "user://auth_session.json"
|
|
|
|
|
const LOCATIONS_BASE_URL := "https://tloc.ranaze.com"
|
|
|
|
|
const AUTH_BASE_URL := "https://tauth.ranaze.com"
|
|
|
|
|
const RESOURCE_REFRESH_SECONDS := 15.0
|
|
|
|
|
const TOKEN_REFRESH_PROMPT_SECONDS := 120.0
|
|
|
|
|
const HexGridView := preload("res://scenes/game/hex_grid_view.gd")
|
|
|
|
|
|
|
|
|
|
var coordinate_label: Label
|
|
|
|
@@ -15,21 +17,29 @@ var units_request: HTTPRequest
|
|
|
|
|
var train_unit_request: HTTPRequest
|
|
|
|
|
var claim_request: HTTPRequest
|
|
|
|
|
var build_request: HTTPRequest
|
|
|
|
|
var refresh_request: HTTPRequest
|
|
|
|
|
var resources_timer: Timer
|
|
|
|
|
var auth_check_timer: Timer
|
|
|
|
|
var refresh_dialog: ConfirmationDialog
|
|
|
|
|
var session: Dictionary = {}
|
|
|
|
|
var escape_overlay: Control
|
|
|
|
|
var escape_panel: PanelContainer
|
|
|
|
|
var gold_label: Label
|
|
|
|
|
var tick_bar: ProgressBar
|
|
|
|
|
var tick_label: Label
|
|
|
|
|
var resource_text := "Gold: --\nWood: --\nOre: --"
|
|
|
|
|
var gold_tick_anchor_unix := 0.0
|
|
|
|
|
var gold_tick_seconds := 60.0
|
|
|
|
|
var train_button: Button
|
|
|
|
|
var unit_label: Label
|
|
|
|
|
var training_box: VBoxContainer
|
|
|
|
|
var training_label: Label
|
|
|
|
|
var training_bar: ProgressBar
|
|
|
|
|
var building_box: VBoxContainer
|
|
|
|
|
var building_label: Label
|
|
|
|
|
var building_bar: ProgressBar
|
|
|
|
|
var progress_panel: PanelContainer
|
|
|
|
|
var action_buttons: HBoxContainer
|
|
|
|
|
var training_started_unix := 0.0
|
|
|
|
|
var training_completes_unix := 0.0
|
|
|
|
|
var training_completion_refresh_requested := false
|
|
|
|
@@ -40,19 +50,24 @@ var active_building_label := "Build"
|
|
|
|
|
var claim_button: Button
|
|
|
|
|
var build_log_camp_button: Button
|
|
|
|
|
var build_mine_button: Button
|
|
|
|
|
var build_barracks_button: Button
|
|
|
|
|
var selected_q := 0
|
|
|
|
|
var selected_r := 0
|
|
|
|
|
var selected_can_claim := false
|
|
|
|
|
var selected_can_build_log_camp := false
|
|
|
|
|
var selected_can_build_mine := false
|
|
|
|
|
var selected_can_build_barracks := false
|
|
|
|
|
var selected_is_home := false
|
|
|
|
|
var completed_scout_count := 0
|
|
|
|
|
var refresh_prompt_active := false
|
|
|
|
|
var refresh_request_active := false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
session = _load_session()
|
|
|
|
|
_build_ui()
|
|
|
|
|
_assign_home_location()
|
|
|
|
|
_start_auth_watch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
|
|
@@ -100,10 +115,10 @@ func _build_ui() -> void:
|
|
|
|
|
top_margin.add_theme_constant_override("margin_bottom", 12)
|
|
|
|
|
top_bar.add_child(top_margin)
|
|
|
|
|
|
|
|
|
|
var top_content := HBoxContainer.new()
|
|
|
|
|
top_content.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
|
|
|
top_content.add_theme_constant_override("separation", 16)
|
|
|
|
|
top_margin.add_child(top_content)
|
|
|
|
|
var title_row := HBoxContainer.new()
|
|
|
|
|
title_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
|
|
|
title_row.add_theme_constant_override("separation", 16)
|
|
|
|
|
top_margin.add_child(title_row)
|
|
|
|
|
|
|
|
|
|
var title := Label.new()
|
|
|
|
|
title.text = "Territory Map"
|
|
|
|
@@ -112,11 +127,11 @@ func _build_ui() -> void:
|
|
|
|
|
title.add_theme_color_override("font_color", Color(0.94, 0.96, 0.9))
|
|
|
|
|
if title_font:
|
|
|
|
|
title.add_theme_font_override("font", title_font)
|
|
|
|
|
top_content.add_child(title)
|
|
|
|
|
title_row.add_child(title)
|
|
|
|
|
|
|
|
|
|
var legend := HBoxContainer.new()
|
|
|
|
|
legend.add_theme_constant_override("separation", 12)
|
|
|
|
|
top_content.add_child(legend)
|
|
|
|
|
title_row.add_child(legend)
|
|
|
|
|
|
|
|
|
|
legend.add_child(_legend_item(Color(1.0, 0.76, 0.16), "Home"))
|
|
|
|
|
legend.add_child(_legend_item(Color(0.16, 0.86, 0.92), "Yours"))
|
|
|
|
@@ -124,38 +139,11 @@ func _build_ui() -> void:
|
|
|
|
|
legend.add_child(_legend_item(Color(0.38, 0.56, 0.36), "Open"))
|
|
|
|
|
legend.add_child(_legend_item(Color(0.045, 0.065, 0.065), "Unknown"))
|
|
|
|
|
|
|
|
|
|
gold_label = Label.new()
|
|
|
|
|
gold_label.text = "Gold: --"
|
|
|
|
|
gold_label.add_theme_font_size_override("font_size", 15)
|
|
|
|
|
gold_label.add_theme_color_override("font_color", Color(0.95, 0.78, 0.32))
|
|
|
|
|
top_content.add_child(gold_label)
|
|
|
|
|
|
|
|
|
|
var tick_box := VBoxContainer.new()
|
|
|
|
|
tick_box.custom_minimum_size = Vector2(130, 0)
|
|
|
|
|
tick_box.add_theme_constant_override("separation", 4)
|
|
|
|
|
top_content.add_child(tick_box)
|
|
|
|
|
|
|
|
|
|
tick_label = Label.new()
|
|
|
|
|
tick_label.text = "Next: --"
|
|
|
|
|
tick_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
|
|
|
tick_label.add_theme_font_size_override("font_size", 12)
|
|
|
|
|
tick_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
tick_box.add_child(tick_label)
|
|
|
|
|
|
|
|
|
|
tick_bar = ProgressBar.new()
|
|
|
|
|
tick_bar.custom_minimum_size = Vector2(130, 8)
|
|
|
|
|
tick_bar.max_value = 1.0
|
|
|
|
|
tick_bar.value = 0.0
|
|
|
|
|
tick_bar.show_percentage = false
|
|
|
|
|
tick_bar.add_theme_stylebox_override("background", _progress_style(Color(0.035, 0.055, 0.055), Color(0.18, 0.28, 0.26)))
|
|
|
|
|
tick_bar.add_theme_stylebox_override("fill", _progress_style(Color(0.82, 0.65, 0.2), Color(0.9, 0.78, 0.36)))
|
|
|
|
|
tick_box.add_child(tick_bar)
|
|
|
|
|
|
|
|
|
|
var user_label := Label.new()
|
|
|
|
|
user_label.text = _session_name()
|
|
|
|
|
user_label.add_theme_font_size_override("font_size", 15)
|
|
|
|
|
user_label.add_theme_color_override("font_color", Color(0.63, 0.78, 0.75))
|
|
|
|
|
top_content.add_child(user_label)
|
|
|
|
|
title_row.add_child(user_label)
|
|
|
|
|
|
|
|
|
|
var map_frame := PanelContainer.new()
|
|
|
|
|
map_frame.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
|
|
@@ -163,13 +151,20 @@ func _build_ui() -> void:
|
|
|
|
|
map_frame.add_theme_stylebox_override("panel", _panel_style(Color(0.065, 0.09, 0.09, 0.92), Color(0.19, 0.28, 0.27), 1, 0))
|
|
|
|
|
layout.add_child(map_frame)
|
|
|
|
|
|
|
|
|
|
var map_layer := Control.new()
|
|
|
|
|
map_layer.clip_contents = true
|
|
|
|
|
map_layer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
|
|
|
map_layer.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
|
|
|
map_frame.add_child(map_layer)
|
|
|
|
|
|
|
|
|
|
grid_view = HexGridView.new()
|
|
|
|
|
grid_view.clip_contents = true
|
|
|
|
|
grid_view.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
|
|
|
grid_view.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
|
|
|
grid_view.set_anchors_preset(Control.PRESET_FULL_RECT)
|
|
|
|
|
grid_view.tile_hovered.connect(_on_tile_hovered)
|
|
|
|
|
grid_view.tile_selected.connect(_on_tile_selected)
|
|
|
|
|
map_frame.add_child(grid_view)
|
|
|
|
|
map_layer.add_child(grid_view)
|
|
|
|
|
|
|
|
|
|
_build_map_overlays(map_layer)
|
|
|
|
|
|
|
|
|
|
var bottom_bar := PanelContainer.new()
|
|
|
|
|
bottom_bar.custom_minimum_size = Vector2(0, 46)
|
|
|
|
@@ -183,85 +178,56 @@ func _build_ui() -> void:
|
|
|
|
|
bottom_margin.add_theme_constant_override("margin_bottom", 8)
|
|
|
|
|
bottom_bar.add_child(bottom_margin)
|
|
|
|
|
|
|
|
|
|
var bottom_content := HBoxContainer.new()
|
|
|
|
|
bottom_content.add_theme_constant_override("separation", 16)
|
|
|
|
|
bottom_margin.add_child(bottom_content)
|
|
|
|
|
var status_row := HBoxContainer.new()
|
|
|
|
|
status_row.add_theme_constant_override("separation", 10)
|
|
|
|
|
bottom_margin.add_child(status_row)
|
|
|
|
|
|
|
|
|
|
coordinate_label = Label.new()
|
|
|
|
|
coordinate_label.text = "Drag to pan. Mouse wheel zooms. Select a tile to inspect territory."
|
|
|
|
|
coordinate_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
|
|
|
coordinate_label.clip_text = true
|
|
|
|
|
coordinate_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
|
|
|
coordinate_label.add_theme_font_size_override("font_size", 14)
|
|
|
|
|
coordinate_label.add_theme_color_override("font_color", Color(0.72, 0.8, 0.78))
|
|
|
|
|
bottom_content.add_child(coordinate_label)
|
|
|
|
|
status_row.add_child(coordinate_label)
|
|
|
|
|
|
|
|
|
|
unit_label = Label.new()
|
|
|
|
|
unit_label.text = "Scouts: -- | Queue: --"
|
|
|
|
|
unit_label.custom_minimum_size = Vector2(142, 0)
|
|
|
|
|
unit_label.add_theme_font_size_override("font_size", 14)
|
|
|
|
|
unit_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
bottom_content.add_child(unit_label)
|
|
|
|
|
|
|
|
|
|
var training_box := VBoxContainer.new()
|
|
|
|
|
training_box.custom_minimum_size = Vector2(150, 0)
|
|
|
|
|
training_box.add_theme_constant_override("separation", 4)
|
|
|
|
|
bottom_content.add_child(training_box)
|
|
|
|
|
|
|
|
|
|
training_label = Label.new()
|
|
|
|
|
training_label.text = "Training: idle"
|
|
|
|
|
training_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
|
|
|
training_label.add_theme_font_size_override("font_size", 12)
|
|
|
|
|
training_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
training_box.add_child(training_label)
|
|
|
|
|
|
|
|
|
|
training_bar = ProgressBar.new()
|
|
|
|
|
training_bar.custom_minimum_size = Vector2(150, 8)
|
|
|
|
|
training_bar.max_value = 1.0
|
|
|
|
|
training_bar.value = 0.0
|
|
|
|
|
training_bar.show_percentage = false
|
|
|
|
|
training_bar.add_theme_stylebox_override("background", _progress_style(Color(0.035, 0.055, 0.055), Color(0.18, 0.28, 0.26)))
|
|
|
|
|
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)
|
|
|
|
|
action_buttons = HBoxContainer.new()
|
|
|
|
|
action_buttons.custom_minimum_size = Vector2(112, 0)
|
|
|
|
|
action_buttons.size_flags_horizontal = Control.SIZE_SHRINK_END
|
|
|
|
|
action_buttons.add_theme_constant_override("separation", 6)
|
|
|
|
|
status_row.add_child(action_buttons)
|
|
|
|
|
|
|
|
|
|
train_button = _small_button("Train Scout 50g")
|
|
|
|
|
train_button.visible = false
|
|
|
|
|
train_button.pressed.connect(_train_scout)
|
|
|
|
|
bottom_content.add_child(train_button)
|
|
|
|
|
action_buttons.add_child(train_button)
|
|
|
|
|
|
|
|
|
|
claim_button = _small_button("Claim 1 Scout")
|
|
|
|
|
claim_button.disabled = true
|
|
|
|
|
claim_button.visible = false
|
|
|
|
|
claim_button.pressed.connect(_claim_selected_tile)
|
|
|
|
|
bottom_content.add_child(claim_button)
|
|
|
|
|
action_buttons.add_child(claim_button)
|
|
|
|
|
|
|
|
|
|
build_log_camp_button = _small_button("Build Log Camp")
|
|
|
|
|
build_log_camp_button.disabled = true
|
|
|
|
|
build_log_camp_button.visible = false
|
|
|
|
|
build_log_camp_button.pressed.connect(_build_log_camp)
|
|
|
|
|
bottom_content.add_child(build_log_camp_button)
|
|
|
|
|
action_buttons.add_child(build_log_camp_button)
|
|
|
|
|
|
|
|
|
|
build_mine_button = _small_button("Build Mine")
|
|
|
|
|
build_mine_button.disabled = true
|
|
|
|
|
build_mine_button.visible = false
|
|
|
|
|
build_mine_button.pressed.connect(_build_mine)
|
|
|
|
|
bottom_content.add_child(build_mine_button)
|
|
|
|
|
action_buttons.add_child(build_mine_button)
|
|
|
|
|
|
|
|
|
|
build_barracks_button = _small_button("Build Barracks")
|
|
|
|
|
build_barracks_button.visible = false
|
|
|
|
|
build_barracks_button.pressed.connect(_build_barracks)
|
|
|
|
|
action_buttons.add_child(build_barracks_button)
|
|
|
|
|
|
|
|
|
|
unit_label = Label.new()
|
|
|
|
|
unit_label.text = "Scouts: -- | Queue: --"
|
|
|
|
|
unit_label.custom_minimum_size = Vector2(126, 0)
|
|
|
|
|
unit_label.add_theme_font_size_override("font_size", 14)
|
|
|
|
|
unit_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
status_row.add_child(unit_label)
|
|
|
|
|
|
|
|
|
|
http_request = HTTPRequest.new()
|
|
|
|
|
http_request.request_completed.connect(_on_home_request_completed)
|
|
|
|
@@ -291,15 +257,144 @@ func _build_ui() -> void:
|
|
|
|
|
build_request.request_completed.connect(_on_build_request_completed)
|
|
|
|
|
add_child(build_request)
|
|
|
|
|
|
|
|
|
|
refresh_request = HTTPRequest.new()
|
|
|
|
|
refresh_request.request_completed.connect(_on_refresh_request_completed)
|
|
|
|
|
add_child(refresh_request)
|
|
|
|
|
|
|
|
|
|
auth_check_timer = Timer.new()
|
|
|
|
|
auth_check_timer.wait_time = 15.0
|
|
|
|
|
auth_check_timer.autostart = false
|
|
|
|
|
auth_check_timer.timeout.connect(_check_auth_expiry)
|
|
|
|
|
add_child(auth_check_timer)
|
|
|
|
|
|
|
|
|
|
resources_timer = Timer.new()
|
|
|
|
|
resources_timer.wait_time = RESOURCE_REFRESH_SECONDS
|
|
|
|
|
resources_timer.autostart = false
|
|
|
|
|
resources_timer.timeout.connect(_refresh_player_state)
|
|
|
|
|
add_child(resources_timer)
|
|
|
|
|
|
|
|
|
|
_build_refresh_dialog()
|
|
|
|
|
_build_escape_menu()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _build_map_overlays(map_layer: Control) -> void:
|
|
|
|
|
var resource_panel := PanelContainer.new()
|
|
|
|
|
resource_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
|
resource_panel.anchor_left = 1.0
|
|
|
|
|
resource_panel.anchor_right = 1.0
|
|
|
|
|
resource_panel.anchor_top = 0.0
|
|
|
|
|
resource_panel.anchor_bottom = 0.0
|
|
|
|
|
resource_panel.offset_left = -230
|
|
|
|
|
resource_panel.offset_right = -16
|
|
|
|
|
resource_panel.offset_top = 16
|
|
|
|
|
resource_panel.offset_bottom = 128
|
|
|
|
|
resource_panel.add_theme_stylebox_override("panel", _panel_style(Color(0.045, 0.07, 0.07, 0.78), Color(0.18, 0.28, 0.26), 1, 4))
|
|
|
|
|
map_layer.add_child(resource_panel)
|
|
|
|
|
|
|
|
|
|
var resource_margin := MarginContainer.new()
|
|
|
|
|
resource_margin.add_theme_constant_override("margin_left", 12)
|
|
|
|
|
resource_margin.add_theme_constant_override("margin_right", 12)
|
|
|
|
|
resource_margin.add_theme_constant_override("margin_top", 10)
|
|
|
|
|
resource_margin.add_theme_constant_override("margin_bottom", 10)
|
|
|
|
|
resource_panel.add_child(resource_margin)
|
|
|
|
|
|
|
|
|
|
var resource_stack := VBoxContainer.new()
|
|
|
|
|
resource_stack.add_theme_constant_override("separation", 6)
|
|
|
|
|
resource_margin.add_child(resource_stack)
|
|
|
|
|
|
|
|
|
|
gold_label = Label.new()
|
|
|
|
|
gold_label.text = resource_text
|
|
|
|
|
gold_label.add_theme_font_size_override("font_size", 14)
|
|
|
|
|
gold_label.add_theme_color_override("font_color", Color(0.95, 0.78, 0.32))
|
|
|
|
|
resource_stack.add_child(gold_label)
|
|
|
|
|
|
|
|
|
|
tick_label = Label.new()
|
|
|
|
|
tick_label.text = "Next: --"
|
|
|
|
|
tick_label.add_theme_font_size_override("font_size", 12)
|
|
|
|
|
tick_label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
resource_stack.add_child(tick_label)
|
|
|
|
|
|
|
|
|
|
tick_bar = ProgressBar.new()
|
|
|
|
|
tick_bar.custom_minimum_size = Vector2(180, 8)
|
|
|
|
|
tick_bar.max_value = 1.0
|
|
|
|
|
tick_bar.value = 0.0
|
|
|
|
|
tick_bar.show_percentage = false
|
|
|
|
|
tick_bar.add_theme_stylebox_override("background", _progress_style(Color(0.035, 0.055, 0.055), Color(0.18, 0.28, 0.26)))
|
|
|
|
|
tick_bar.add_theme_stylebox_override("fill", _progress_style(Color(0.82, 0.65, 0.2), Color(0.9, 0.78, 0.36)))
|
|
|
|
|
resource_stack.add_child(tick_bar)
|
|
|
|
|
|
|
|
|
|
progress_panel = PanelContainer.new()
|
|
|
|
|
progress_panel.visible = false
|
|
|
|
|
progress_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
|
progress_panel.anchor_left = 0.0
|
|
|
|
|
progress_panel.anchor_right = 0.0
|
|
|
|
|
progress_panel.anchor_top = 0.0
|
|
|
|
|
progress_panel.anchor_bottom = 0.0
|
|
|
|
|
progress_panel.offset_left = 16
|
|
|
|
|
progress_panel.offset_right = 220
|
|
|
|
|
progress_panel.offset_top = 16
|
|
|
|
|
progress_panel.offset_bottom = 130
|
|
|
|
|
progress_panel.add_theme_stylebox_override("panel", _panel_style(Color(0.045, 0.07, 0.07, 0.78), Color(0.18, 0.28, 0.26), 1, 4))
|
|
|
|
|
map_layer.add_child(progress_panel)
|
|
|
|
|
|
|
|
|
|
var progress_margin := MarginContainer.new()
|
|
|
|
|
progress_margin.add_theme_constant_override("margin_left", 12)
|
|
|
|
|
progress_margin.add_theme_constant_override("margin_right", 12)
|
|
|
|
|
progress_margin.add_theme_constant_override("margin_top", 10)
|
|
|
|
|
progress_margin.add_theme_constant_override("margin_bottom", 10)
|
|
|
|
|
progress_panel.add_child(progress_margin)
|
|
|
|
|
|
|
|
|
|
var progress_stack := VBoxContainer.new()
|
|
|
|
|
progress_stack.add_theme_constant_override("separation", 8)
|
|
|
|
|
progress_margin.add_child(progress_stack)
|
|
|
|
|
|
|
|
|
|
training_box = _progress_overlay_item("Training")
|
|
|
|
|
progress_stack.add_child(training_box)
|
|
|
|
|
training_label = training_box.get_child(0) as Label
|
|
|
|
|
training_bar = training_box.get_child(1) as ProgressBar
|
|
|
|
|
|
|
|
|
|
building_box = _progress_overlay_item("Build")
|
|
|
|
|
progress_stack.add_child(building_box)
|
|
|
|
|
building_label = building_box.get_child(0) as Label
|
|
|
|
|
building_bar = building_box.get_child(1) as ProgressBar
|
|
|
|
|
building_bar.add_theme_stylebox_override("fill", _progress_style(Color(0.62, 0.42, 0.22), Color(0.86, 0.62, 0.34)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _progress_overlay_item(label_text: String) -> VBoxContainer:
|
|
|
|
|
var box := VBoxContainer.new()
|
|
|
|
|
box.visible = false
|
|
|
|
|
box.custom_minimum_size = Vector2(180, 0)
|
|
|
|
|
box.add_theme_constant_override("separation", 4)
|
|
|
|
|
|
|
|
|
|
var label := Label.new()
|
|
|
|
|
label.text = label_text
|
|
|
|
|
label.add_theme_font_size_override("font_size", 12)
|
|
|
|
|
label.add_theme_color_override("font_color", Color(0.72, 0.82, 0.78))
|
|
|
|
|
box.add_child(label)
|
|
|
|
|
|
|
|
|
|
var bar := ProgressBar.new()
|
|
|
|
|
bar.custom_minimum_size = Vector2(180, 8)
|
|
|
|
|
bar.max_value = 1.0
|
|
|
|
|
bar.value = 0.0
|
|
|
|
|
bar.show_percentage = false
|
|
|
|
|
bar.add_theme_stylebox_override("background", _progress_style(Color(0.035, 0.055, 0.055), Color(0.18, 0.28, 0.26)))
|
|
|
|
|
bar.add_theme_stylebox_override("fill", _progress_style(Color(0.28, 0.62, 0.72), Color(0.43, 0.82, 0.92)))
|
|
|
|
|
box.add_child(bar)
|
|
|
|
|
|
|
|
|
|
return box
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _build_refresh_dialog() -> void:
|
|
|
|
|
refresh_dialog = ConfirmationDialog.new()
|
|
|
|
|
refresh_dialog.title = "Session expiring"
|
|
|
|
|
refresh_dialog.dialog_text = "Your session is about to expire. Refresh it now?"
|
|
|
|
|
refresh_dialog.ok_button_text = "Refresh"
|
|
|
|
|
refresh_dialog.cancel_button_text = "Log Out"
|
|
|
|
|
refresh_dialog.confirmed.connect(_refresh_auth_token)
|
|
|
|
|
refresh_dialog.canceled.connect(_logout)
|
|
|
|
|
add_child(refresh_dialog)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _on_tile_hovered(q: int, r: int, terrain: String) -> void:
|
|
|
|
|
if coordinate_label:
|
|
|
|
|
coordinate_label.text = "Hex q:%d r:%d | %s" % [q, r, terrain]
|
|
|
|
@@ -312,14 +407,8 @@ func _on_tile_selected(q: int, r: int, terrain: String) -> void:
|
|
|
|
|
selected_is_home = _selected_tile_is_home()
|
|
|
|
|
selected_can_build_log_camp = _can_build_log_camp_on_selected_tile()
|
|
|
|
|
selected_can_build_mine = _can_build_mine_on_selected_tile()
|
|
|
|
|
if train_button:
|
|
|
|
|
train_button.visible = selected_is_home
|
|
|
|
|
if claim_button:
|
|
|
|
|
claim_button.disabled = not _can_claim_selected_tile()
|
|
|
|
|
if build_log_camp_button:
|
|
|
|
|
build_log_camp_button.disabled = not selected_can_build_log_camp
|
|
|
|
|
if build_mine_button:
|
|
|
|
|
build_mine_button.disabled = not selected_can_build_mine
|
|
|
|
|
selected_can_build_barracks = _can_build_barracks_on_selected_tile()
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
if coordinate_label:
|
|
|
|
|
coordinate_label.text = "Selected q:%d r:%d | %s territory" % [q, r, terrain]
|
|
|
|
|
|
|
|
|
@@ -332,6 +421,10 @@ func _can_build_mine_on_selected_tile() -> bool:
|
|
|
|
|
return _can_build_on_selected_tile("Ore")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _can_build_barracks_on_selected_tile() -> bool:
|
|
|
|
|
return _can_build_on_selected_tile("")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _can_build_on_selected_tile(required_terrain: String) -> bool:
|
|
|
|
|
if not grid_view:
|
|
|
|
|
return false
|
|
|
|
@@ -343,13 +436,31 @@ func _can_build_on_selected_tile(required_terrain: String) -> bool:
|
|
|
|
|
var username: String = str(session.get("username", ""))
|
|
|
|
|
var owner_username: String = str(location.get("ownerUsername", ""))
|
|
|
|
|
var terrain: String = str(location.get("terrain", ""))
|
|
|
|
|
var building_type: String = str(location.get("buildingType", ""))
|
|
|
|
|
var building_type: String = _nullable_string(location.get("buildingType", ""))
|
|
|
|
|
|
|
|
|
|
return owner_username == username and terrain == required_terrain and building_type.is_empty()
|
|
|
|
|
return owner_username == username and building_type.is_empty() and (required_terrain.is_empty() or terrain == required_terrain)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _can_claim_selected_tile() -> bool:
|
|
|
|
|
return selected_can_claim and completed_scout_count > 0
|
|
|
|
|
return selected_can_claim and completed_scout_count > 0 and grid_view and grid_view.has_owned_neighbor(selected_q, selected_r)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _update_action_buttons() -> void:
|
|
|
|
|
if train_button:
|
|
|
|
|
train_button.visible = selected_is_home
|
|
|
|
|
train_button.disabled = false
|
|
|
|
|
if claim_button:
|
|
|
|
|
claim_button.visible = _can_claim_selected_tile()
|
|
|
|
|
claim_button.disabled = false
|
|
|
|
|
if build_log_camp_button:
|
|
|
|
|
build_log_camp_button.visible = selected_can_build_log_camp
|
|
|
|
|
build_log_camp_button.disabled = false
|
|
|
|
|
if build_mine_button:
|
|
|
|
|
build_mine_button.visible = selected_can_build_mine
|
|
|
|
|
build_mine_button.disabled = false
|
|
|
|
|
if build_barracks_button:
|
|
|
|
|
build_barracks_button.visible = selected_can_build_barracks
|
|
|
|
|
build_barracks_button.disabled = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _selected_tile_is_home() -> bool:
|
|
|
|
@@ -391,6 +502,97 @@ func _load_session() -> Dictionary:
|
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _start_auth_watch() -> void:
|
|
|
|
|
_check_auth_expiry()
|
|
|
|
|
if auth_check_timer:
|
|
|
|
|
auth_check_timer.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _check_auth_expiry() -> void:
|
|
|
|
|
if session.is_empty() or refresh_prompt_active or refresh_request_active:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var expires_unix := _parse_utc_timestamp(str(session.get("exp", "")))
|
|
|
|
|
if expires_unix <= 0.0:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var seconds_remaining := expires_unix - Time.get_unix_time_from_system()
|
|
|
|
|
if seconds_remaining <= 0.0:
|
|
|
|
|
_logout_deferred()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if seconds_remaining <= TOKEN_REFRESH_PROMPT_SECONDS:
|
|
|
|
|
_prompt_refresh_or_logout("Your session expires in %d seconds. Refresh it now?" % int(ceil(seconds_remaining)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _prompt_refresh_or_logout(message: String) -> void:
|
|
|
|
|
if refresh_prompt_active or refresh_request_active:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
refresh_prompt_active = true
|
|
|
|
|
if refresh_dialog:
|
|
|
|
|
refresh_dialog.dialog_text = message
|
|
|
|
|
refresh_dialog.popup_centered()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _refresh_auth_token() -> void:
|
|
|
|
|
refresh_prompt_active = false
|
|
|
|
|
var username := str(session.get("username", ""))
|
|
|
|
|
var refresh_token := str(session.get("refreshToken", ""))
|
|
|
|
|
if username.is_empty() or refresh_token.is_empty():
|
|
|
|
|
_logout()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
refresh_request_active = true
|
|
|
|
|
var error: int = refresh_request.request(
|
|
|
|
|
AUTH_BASE_URL + "/api/auth/refresh",
|
|
|
|
|
PackedStringArray(["Content-Type: application/json"]),
|
|
|
|
|
HTTPClient.METHOD_POST,
|
|
|
|
|
JSON.stringify({
|
|
|
|
|
"username": username,
|
|
|
|
|
"refreshToken": refresh_token
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
if error != OK:
|
|
|
|
|
refresh_request_active = false
|
|
|
|
|
_logout()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _on_refresh_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
|
|
|
|
refresh_request_active = false
|
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300:
|
|
|
|
|
_logout()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var parsed = JSON.parse_string(body.get_string_from_utf8())
|
|
|
|
|
if typeof(parsed) != TYPE_DICTIONARY:
|
|
|
|
|
_logout()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var refreshed: Dictionary = parsed
|
|
|
|
|
session["accessToken"] = refreshed.get("accessToken", session.get("accessToken", ""))
|
|
|
|
|
session["exp"] = refreshed.get("exp", session.get("exp", ""))
|
|
|
|
|
get_tree().set_meta("auth_session", session)
|
|
|
|
|
_save_session_if_present(session)
|
|
|
|
|
coordinate_label.text = "Session refreshed."
|
|
|
|
|
_check_auth_expiry()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _save_session(next_session: Dictionary) -> void:
|
|
|
|
|
var file := FileAccess.open(SESSION_PATH, FileAccess.WRITE)
|
|
|
|
|
if file:
|
|
|
|
|
file.store_string(JSON.stringify(next_session))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _save_session_if_present(next_session: Dictionary) -> void:
|
|
|
|
|
if FileAccess.file_exists(SESSION_PATH):
|
|
|
|
|
_save_session(next_session)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _logout_deferred() -> void:
|
|
|
|
|
call_deferred("_logout")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _assign_home_location() -> void:
|
|
|
|
|
var access_token: String = str(session.get("accessToken", ""))
|
|
|
|
|
if access_token.is_empty():
|
|
|
|
@@ -484,7 +686,8 @@ func _refresh_player_state() -> void:
|
|
|
|
|
func _load_resources() -> void:
|
|
|
|
|
var access_token: String = str(session.get("accessToken", ""))
|
|
|
|
|
if access_token.is_empty():
|
|
|
|
|
gold_label.text = "Gold: --"
|
|
|
|
|
resource_text = "Gold: --\nWood: --\nOre: --"
|
|
|
|
|
gold_label.text = resource_text
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if resources_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
|
|
|
@@ -498,17 +701,20 @@ func _load_resources() -> void:
|
|
|
|
|
HTTPClient.METHOD_GET
|
|
|
|
|
)
|
|
|
|
|
if error != OK:
|
|
|
|
|
gold_label.text = "Gold: ?"
|
|
|
|
|
coordinate_label.text = "Resource request could not start. Error: %d" % error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _on_resources_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300:
|
|
|
|
|
gold_label.text = "Gold: ?"
|
|
|
|
|
if response_code == 401:
|
|
|
|
|
_prompt_refresh_or_logout("Your session expired. Refresh it now?")
|
|
|
|
|
return
|
|
|
|
|
coordinate_label.text = "Resource request failed. result=%d status=%d body=%s" % [result, response_code, body.get_string_from_utf8()]
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var parsed = JSON.parse_string(body.get_string_from_utf8())
|
|
|
|
|
if typeof(parsed) != TYPE_DICTIONARY:
|
|
|
|
|
gold_label.text = "Gold: ?"
|
|
|
|
|
coordinate_label.text = "Resource service returned invalid JSON."
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var resources: Dictionary = parsed
|
|
|
|
@@ -518,7 +724,8 @@ func _on_resources_request_completed(result: int, response_code: int, _headers:
|
|
|
|
|
var wood_per_minute: int = int(resources.get("woodPerMinute", 0))
|
|
|
|
|
var ore: int = int(resources.get("ore", 0))
|
|
|
|
|
var ore_per_minute: int = int(resources.get("orePerMinute", 0))
|
|
|
|
|
gold_label.text = "Gold: %d (+%d/min) | Wood: %d (+%d/min) | Ore: %d (+%d/min)" % [gold, gold_per_minute, wood, wood_per_minute, ore, ore_per_minute]
|
|
|
|
|
resource_text = "Gold: %d (+%d/min)\nWood: %d (+%d/min)\nOre: %d (+%d/min)" % [gold, gold_per_minute, wood, wood_per_minute, ore, ore_per_minute]
|
|
|
|
|
gold_label.text = resource_text
|
|
|
|
|
|
|
|
|
|
var anchor_text: String = str(resources.get("lastGoldGeneratedAtUtc", ""))
|
|
|
|
|
gold_tick_anchor_unix = _parse_utc_timestamp(anchor_text)
|
|
|
|
@@ -565,8 +772,7 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack
|
|
|
|
|
|
|
|
|
|
completed_scout_count = int(units.get("completedScouts", 0))
|
|
|
|
|
unit_label.text = "Scouts: %d | Queue: %d" % [completed_scout_count, training.size()]
|
|
|
|
|
if claim_button:
|
|
|
|
|
claim_button.disabled = not _can_claim_selected_tile()
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
|
|
|
|
|
if training.is_empty():
|
|
|
|
|
training_started_unix = 0.0
|
|
|
|
@@ -640,6 +846,9 @@ func _claim_selected_tile() -> void:
|
|
|
|
|
if completed_scout_count <= 0:
|
|
|
|
|
coordinate_label.text = "Train a scout before claiming territory."
|
|
|
|
|
return
|
|
|
|
|
if not grid_view.has_owned_neighbor(selected_q, selected_r):
|
|
|
|
|
coordinate_label.text = "Claims must be adjacent to controlled territory."
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var access_token: String = str(session.get("accessToken", ""))
|
|
|
|
|
if access_token.is_empty():
|
|
|
|
@@ -661,7 +870,7 @@ func _claim_selected_tile() -> void:
|
|
|
|
|
JSON.stringify({ "q": selected_q, "r": selected_r })
|
|
|
|
|
)
|
|
|
|
|
if error != OK:
|
|
|
|
|
claim_button.disabled = false
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
coordinate_label.text = "Could not contact the locations service."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -669,17 +878,17 @@ func _on_claim_request_completed(result: int, response_code: int, _headers: Pack
|
|
|
|
|
var text: String = body.get_string_from_utf8()
|
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS:
|
|
|
|
|
coordinate_label.text = "Scout claim request failed."
|
|
|
|
|
claim_button.disabled = not selected_can_claim
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if response_code < 200 or response_code >= 300:
|
|
|
|
|
coordinate_label.text = "Scout claim failed: %s" % text
|
|
|
|
|
claim_button.disabled = not selected_can_claim
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
_refresh_player_state()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
selected_can_claim = false
|
|
|
|
|
claim_button.disabled = true
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
coordinate_label.text = "Scout claimed q:%d r:%d. Territory expanded." % [selected_q, selected_r]
|
|
|
|
|
_load_visible_locations()
|
|
|
|
|
_refresh_player_state()
|
|
|
|
@@ -701,6 +910,14 @@ func _build_mine() -> void:
|
|
|
|
|
_request_building("Mine")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _build_barracks() -> void:
|
|
|
|
|
if not selected_can_build_barracks:
|
|
|
|
|
coordinate_label.text = "Select controlled territory without a building."
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
_request_building("Barracks")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _request_building(building_type: String) -> void:
|
|
|
|
|
var access_token: String = str(session.get("accessToken", ""))
|
|
|
|
|
if access_token.is_empty():
|
|
|
|
@@ -710,10 +927,13 @@ func _request_building(building_type: String) -> void:
|
|
|
|
|
if build_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if building_type == "Mine":
|
|
|
|
|
build_mine_button.disabled = true
|
|
|
|
|
else:
|
|
|
|
|
build_log_camp_button.disabled = true
|
|
|
|
|
match building_type:
|
|
|
|
|
"Mine":
|
|
|
|
|
build_mine_button.disabled = true
|
|
|
|
|
"Barracks":
|
|
|
|
|
build_barracks_button.disabled = true
|
|
|
|
|
_:
|
|
|
|
|
build_log_camp_button.disabled = true
|
|
|
|
|
|
|
|
|
|
coordinate_label.text = "Building %s at q:%d r:%d..." % [building_type, selected_q, selected_r]
|
|
|
|
|
var error: int = build_request.request(
|
|
|
|
@@ -726,8 +946,7 @@ func _request_building(building_type: String) -> void:
|
|
|
|
|
JSON.stringify({ "q": selected_q, "r": selected_r, "buildingType": building_type })
|
|
|
|
|
)
|
|
|
|
|
if error != OK:
|
|
|
|
|
build_log_camp_button.disabled = not selected_can_build_log_camp
|
|
|
|
|
build_mine_button.disabled = not selected_can_build_mine
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
coordinate_label.text = "Could not contact the locations service."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -735,25 +954,23 @@ func _on_build_request_completed(result: int, response_code: int, _headers: Pack
|
|
|
|
|
var text: String = body.get_string_from_utf8()
|
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS:
|
|
|
|
|
coordinate_label.text = "Build request failed."
|
|
|
|
|
build_log_camp_button.disabled = not selected_can_build_log_camp
|
|
|
|
|
build_mine_button.disabled = not selected_can_build_mine
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if response_code < 200 or response_code >= 300:
|
|
|
|
|
coordinate_label.text = "Build failed: %s" % text
|
|
|
|
|
build_log_camp_button.disabled = not selected_can_build_log_camp
|
|
|
|
|
build_mine_button.disabled = not selected_can_build_mine
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
_refresh_player_state()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
selected_can_build_log_camp = false
|
|
|
|
|
selected_can_build_mine = false
|
|
|
|
|
build_log_camp_button.disabled = true
|
|
|
|
|
build_mine_button.disabled = true
|
|
|
|
|
selected_can_build_barracks = false
|
|
|
|
|
_update_action_buttons()
|
|
|
|
|
var parsed = JSON.parse_string(text)
|
|
|
|
|
if typeof(parsed) == TYPE_DICTIONARY:
|
|
|
|
|
var location: Dictionary = parsed
|
|
|
|
|
active_building_label = _building_display_name(str(location.get("buildingType", "Building")))
|
|
|
|
|
active_building_label = _building_display_name(_nullable_string(location.get("buildingType", "Building")))
|
|
|
|
|
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
|
|
|
|
@@ -787,10 +1004,13 @@ func _update_training_bar() -> void:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if training_started_unix <= 0.0 or training_completes_unix <= 0.0:
|
|
|
|
|
training_box.visible = false
|
|
|
|
|
training_bar.value = 0.0
|
|
|
|
|
training_label.text = "Training: idle"
|
|
|
|
|
_update_progress_panel_visibility()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
training_box.visible = true
|
|
|
|
|
var now: float = Time.get_unix_time_from_system()
|
|
|
|
|
var duration: float = max(1.0, training_completes_unix - training_started_unix)
|
|
|
|
|
var elapsed: float = clamp(now - training_started_unix, 0.0, duration)
|
|
|
|
@@ -804,6 +1024,7 @@ func _update_training_bar() -> void:
|
|
|
|
|
_load_units()
|
|
|
|
|
else:
|
|
|
|
|
training_label.text = "Training: %ds" % remaining
|
|
|
|
|
_update_progress_panel_visibility()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _update_building_timer() -> void:
|
|
|
|
@@ -811,10 +1032,13 @@ func _update_building_timer() -> void:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if building_started_unix <= 0.0 or building_completes_unix <= 0.0:
|
|
|
|
|
building_box.visible = false
|
|
|
|
|
building_bar.value = 0.0
|
|
|
|
|
building_label.text = "Build: idle"
|
|
|
|
|
_update_progress_panel_visibility()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
building_box.visible = true
|
|
|
|
|
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)
|
|
|
|
@@ -830,6 +1054,12 @@ func _update_building_timer() -> void:
|
|
|
|
|
building_completion_refresh_requested = true
|
|
|
|
|
_load_visible_locations()
|
|
|
|
|
_refresh_player_state()
|
|
|
|
|
_update_progress_panel_visibility()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _update_progress_panel_visibility() -> void:
|
|
|
|
|
if progress_panel:
|
|
|
|
|
progress_panel.visible = (training_box and training_box.visible) or (building_box and building_box.visible)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _sync_active_building_timer(locations: Array, username: String) -> void:
|
|
|
|
@@ -844,7 +1074,7 @@ func _sync_active_building_timer(locations: Array, username: String) -> void:
|
|
|
|
|
var location: Dictionary = item
|
|
|
|
|
if str(location.get("ownerUsername", "")) != username:
|
|
|
|
|
continue
|
|
|
|
|
var building_type: String = str(location.get("buildingType", ""))
|
|
|
|
|
var building_type: String = _nullable_string(location.get("buildingType", ""))
|
|
|
|
|
if building_type.is_empty():
|
|
|
|
|
continue
|
|
|
|
|
if str(location.get("buildingStatus", "")) != "Building":
|
|
|
|
@@ -872,6 +1102,8 @@ func _building_display_name(building_type: String) -> String:
|
|
|
|
|
return "Log Camp"
|
|
|
|
|
"Mine":
|
|
|
|
|
return "Mine"
|
|
|
|
|
"Barracks":
|
|
|
|
|
return "Barracks"
|
|
|
|
|
_:
|
|
|
|
|
return "Build"
|
|
|
|
|
|
|
|
|
@@ -895,6 +1127,12 @@ func _parse_utc_timestamp(timestamp: String) -> float:
|
|
|
|
|
return Time.get_unix_time_from_datetime_string(normalized)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _nullable_string(value: Variant) -> String:
|
|
|
|
|
if value == null:
|
|
|
|
|
return ""
|
|
|
|
|
return str(value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _build_escape_menu() -> void:
|
|
|
|
|
escape_overlay = Control.new()
|
|
|
|
|
escape_overlay.visible = false
|
|
|
|
@@ -995,8 +1233,10 @@ func _menu_button(text_value: String) -> Button:
|
|
|
|
|
|
|
|
|
|
func _small_button(text_value: String) -> Button:
|
|
|
|
|
var button := _menu_button(text_value)
|
|
|
|
|
button.custom_minimum_size = Vector2(128, 32)
|
|
|
|
|
button.add_theme_font_size_override("font_size", 13)
|
|
|
|
|
button.custom_minimum_size = Vector2(108, 32)
|
|
|
|
|
button.add_theme_font_size_override("font_size", 11)
|
|
|
|
|
button.clip_text = true
|
|
|
|
|
button.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
|
|
|
return button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|