refactor
This commit is contained in:
497
scenes/hud/hud.gd
Normal file
497
scenes/hud/hud.gd
Normal file
@@ -0,0 +1,497 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var hp_bar: ProgressBar = %HpBar
|
||||
@onready var hp_label: Label = %HpLabel
|
||||
@onready var shield_bar: ProgressBar = %ShieldBar
|
||||
@onready var shield_label: Label = %ShieldLabel
|
||||
@onready var xp_bar: ProgressBar = %XpBar
|
||||
@onready var level_label: Label = %LevelLabel
|
||||
@onready var wave_label: Label = %WaveLabel
|
||||
@onready var timer_label: Label = %WaveTimer
|
||||
@onready var village_bar: ProgressBar = %VillageBar
|
||||
@onready var role_icon: Panel = %RoleIcon
|
||||
@onready var role_label: Label = %RoleLabel
|
||||
@onready var ability_box: HBoxContainer = %AbilityBox
|
||||
@onready var death_overlay: Control = %DeathOverlay
|
||||
@onready var death_label: Label = %DeathLabel
|
||||
@onready var chat_log: RichTextLabel = %ChatLog
|
||||
@onready var chat_input: LineEdit = %ChatInput
|
||||
@onready var inventory_panel: Control = %InventoryPanel
|
||||
@onready var inventory_list: VBoxContainer = %InventoryList
|
||||
@onready var crafting_panel: Control = %CraftingPanel
|
||||
@onready var crafting_list: VBoxContainer = %CraftingList
|
||||
@onready var build_panel: Control = %BuildPanel
|
||||
@onready var build_list: HBoxContainer = %BuildList
|
||||
@onready var dialog_panel: Control = %DialogPanel
|
||||
@onready var dialog_npc: Label = %DialogNpc
|
||||
@onready var dialog_log: RichTextLabel = %DialogLog
|
||||
@onready var dialog_input: LineEdit = %DialogInput
|
||||
@onready var map_panel: Control = %MapPanel
|
||||
@onready var map_canvas: Control = %MapCanvas
|
||||
@onready var minimap_canvas: Control = %MinimapCanvas
|
||||
@onready var pause_panel: Control = %PausePanel
|
||||
@onready var game_over_overlay: Control = %GameOverOverlay
|
||||
@onready var ability_buttons: Array = []
|
||||
|
||||
var local_player: Node = null
|
||||
var dialog_npc_node: Node = null
|
||||
var build_selected: int = 0
|
||||
var build_rotation: float = 0.0
|
||||
var build_preview: MeshInstance3D = null
|
||||
var build_active: bool = false
|
||||
var _minimap_accum: float = 0.0
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("dialog_ui")
|
||||
EventBus.health_changed.connect(_on_health_changed)
|
||||
EventBus.shield_changed.connect(_on_shield_changed)
|
||||
EventBus.cooldown_tick.connect(_on_cooldown_tick)
|
||||
EventBus.role_changed.connect(_on_role_changed)
|
||||
EventBus.entity_died.connect(_on_entity_died)
|
||||
EventBus.entity_respawned.connect(_on_respawned)
|
||||
EventBus.wave_started.connect(_on_wave_started)
|
||||
EventBus.wave_timer_tick.connect(_on_wave_tick)
|
||||
EventBus.village_damaged.connect(_on_village_damaged)
|
||||
EventBus.village_destroyed.connect(_on_village_destroyed)
|
||||
EventBus.invasion_started.connect(_on_invasion_started)
|
||||
EventBus.xp_gained.connect(_on_xp_gained)
|
||||
EventBus.level_up.connect(_on_level_up)
|
||||
EventBus.dialog_opened.connect(_on_dialog_opened)
|
||||
EventBus.inventory_changed.connect(_on_inventory_changed)
|
||||
EventBus.chat_message.connect(_on_chat)
|
||||
chat_input.text_submitted.connect(_on_chat_submitted)
|
||||
dialog_input.text_submitted.connect(_on_dialog_submitted)
|
||||
death_overlay.visible = false
|
||||
inventory_panel.visible = false
|
||||
crafting_panel.visible = false
|
||||
build_panel.visible = false
|
||||
dialog_panel.visible = false
|
||||
map_panel.visible = false
|
||||
pause_panel.visible = false
|
||||
game_over_overlay.visible = false
|
||||
set_process(true)
|
||||
_wire_ability_buttons()
|
||||
call_deferred("_populate_build_list")
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if local_player == null:
|
||||
local_player = _find_local_player()
|
||||
if local_player:
|
||||
var role: int = int(Stats.get_stat(local_player, "role", GameState.ROLE_DAMAGE))
|
||||
_on_role_changed(local_player, role)
|
||||
_refresh_vitals()
|
||||
if build_active:
|
||||
_update_build_preview()
|
||||
_update_minimap()
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("inventory"):
|
||||
_toggle_panel(inventory_panel)
|
||||
_refresh_inventory()
|
||||
elif event.is_action_pressed("crafting"):
|
||||
_toggle_panel(crafting_panel)
|
||||
_refresh_crafting()
|
||||
elif event.is_action_pressed("build_mode"):
|
||||
_toggle_build_mode()
|
||||
elif event.is_action_pressed("map"):
|
||||
_toggle_panel(map_panel)
|
||||
elif event.is_action_pressed("chat"):
|
||||
chat_input.grab_focus()
|
||||
_capture_ui(true)
|
||||
elif event.is_action_pressed("pause"):
|
||||
if dialog_panel.visible:
|
||||
dialog_panel.visible = false
|
||||
_capture_ui(false)
|
||||
elif build_active:
|
||||
_toggle_build_mode()
|
||||
elif inventory_panel.visible or crafting_panel.visible or map_panel.visible:
|
||||
inventory_panel.visible = false
|
||||
crafting_panel.visible = false
|
||||
map_panel.visible = false
|
||||
_capture_ui(false)
|
||||
else:
|
||||
_toggle_pause()
|
||||
elif build_active:
|
||||
if event.is_action_pressed("rotate_build"):
|
||||
build_rotation = wrapf(build_rotation + PI * 0.5, 0.0, TAU)
|
||||
elif event.is_action_pressed("ability_1"):
|
||||
_select_build(0)
|
||||
elif event.is_action_pressed("ability_2"):
|
||||
_select_build(1)
|
||||
elif event.is_action_pressed("ability_3"):
|
||||
_select_build(2)
|
||||
elif event.is_action_pressed("ability_4"):
|
||||
_select_build(3)
|
||||
elif event is InputEventMouseButton and event.pressed:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
_try_place()
|
||||
elif event.button_index == MOUSE_BUTTON_MIDDLE:
|
||||
_try_remove()
|
||||
|
||||
func _wire_ability_buttons() -> void:
|
||||
for c in ability_box.get_children():
|
||||
if c is Button:
|
||||
ability_buttons.append(c)
|
||||
|
||||
func _toggle_panel(panel: Control) -> void:
|
||||
panel.visible = not panel.visible
|
||||
_capture_ui(_any_panel_visible())
|
||||
|
||||
func _any_panel_visible() -> bool:
|
||||
return inventory_panel.visible or crafting_panel.visible or dialog_panel.visible or pause_panel.visible
|
||||
|
||||
func _capture_ui(v: bool) -> void:
|
||||
if local_player and local_player.has_method("set_ui_capturing"):
|
||||
local_player.set_ui_capturing(v)
|
||||
|
||||
func _find_local_player() -> Node:
|
||||
for p in get_tree().get_nodes_in_group("player"):
|
||||
if p.is_multiplayer_authority():
|
||||
return p
|
||||
return null
|
||||
|
||||
func _refresh_vitals() -> void:
|
||||
if local_player == null:
|
||||
return
|
||||
var hp: float = float(Stats.get_stat(local_player, "health", 0.0))
|
||||
var max_hp: float = float(Stats.get_stat(local_player, "max_health", 1.0))
|
||||
_on_health_changed(local_player, hp, max_hp)
|
||||
var shield: float = float(Stats.get_stat(local_player, "shield", 0.0))
|
||||
var max_shield: float = float(Stats.get_stat(local_player, "max_shield", 0.0))
|
||||
_on_shield_changed(local_player, shield, max_shield)
|
||||
var xp: float = float(Stats.get_stat(local_player, "xp", 0.0))
|
||||
var to_next: float = float(Stats.get_stat(local_player, "xp_to_next", 50.0))
|
||||
xp_bar.max_value = to_next
|
||||
xp_bar.value = xp
|
||||
level_label.text = "Lv %d" % int(Stats.get_stat(local_player, "level", 1))
|
||||
|
||||
func _on_health_changed(entity: Node, current: float, max: float) -> void:
|
||||
if entity != local_player:
|
||||
return
|
||||
hp_bar.max_value = max
|
||||
hp_bar.value = current
|
||||
hp_label.text = "%d / %d" % [int(current), int(max)]
|
||||
|
||||
func _on_shield_changed(entity: Node, current: float, max: float) -> void:
|
||||
if entity != local_player:
|
||||
return
|
||||
shield_bar.max_value = max if max > 0 else 1
|
||||
shield_bar.value = current
|
||||
shield_label.text = "%d / %d" % [int(current), int(max)]
|
||||
|
||||
func _on_cooldown_tick(entity: Node, cds: PackedFloat32Array, _max_cds: PackedFloat32Array, gcd: float) -> void:
|
||||
if entity != local_player:
|
||||
return
|
||||
for i in range(min(ability_buttons.size(), cds.size())):
|
||||
var btn: Button = ability_buttons[i]
|
||||
if cds[i] > 0.0:
|
||||
btn.text = "%d\n%.1f" % [i + 1, cds[i]]
|
||||
btn.disabled = true
|
||||
elif gcd > 0.0:
|
||||
btn.text = "%d\nGCD" % (i + 1)
|
||||
btn.disabled = true
|
||||
else:
|
||||
btn.text = "%d" % (i + 1)
|
||||
btn.disabled = false
|
||||
|
||||
func _on_role_changed(player: Node, role: int) -> void:
|
||||
if player != local_player and player != _find_local_player():
|
||||
return
|
||||
if local_player == null:
|
||||
local_player = player
|
||||
match role:
|
||||
GameState.ROLE_TANK:
|
||||
role_label.text = "T"
|
||||
role_icon.modulate = Color(0.3, 0.5, 0.95)
|
||||
GameState.ROLE_DAMAGE:
|
||||
role_label.text = "D"
|
||||
role_icon.modulate = Color(0.95, 0.3, 0.3)
|
||||
GameState.ROLE_HEALER:
|
||||
role_label.text = "H"
|
||||
role_icon.modulate = Color(0.4, 0.85, 0.4)
|
||||
|
||||
func _on_entity_died(entity: Node) -> void:
|
||||
if entity != local_player:
|
||||
return
|
||||
death_overlay.visible = true
|
||||
death_label.text = "Respawning..."
|
||||
|
||||
func _on_respawned(entity: Node) -> void:
|
||||
if entity != local_player:
|
||||
return
|
||||
death_overlay.visible = false
|
||||
|
||||
func _on_wave_started(wave: int) -> void:
|
||||
wave_label.text = "Wave %d" % wave
|
||||
|
||||
func _on_wave_tick(seconds: float) -> void:
|
||||
var m := int(seconds) / 60
|
||||
var s := int(seconds) % 60
|
||||
timer_label.text = "%02d:%02d" % [m, s]
|
||||
|
||||
func _on_village_damaged(current: float, max: float) -> void:
|
||||
village_bar.max_value = max
|
||||
village_bar.value = current
|
||||
|
||||
func _on_village_destroyed() -> void:
|
||||
game_over_overlay.visible = true
|
||||
|
||||
func _on_invasion_started() -> void:
|
||||
timer_label.modulate = Color(1.0, 0.4, 0.3)
|
||||
|
||||
func _on_xp_gained(player: Node, _amount: float) -> void:
|
||||
if player != local_player:
|
||||
return
|
||||
var xp: float = float(Stats.get_stat(player, "xp", 0.0))
|
||||
var to_next: float = float(Stats.get_stat(player, "xp_to_next", 50.0))
|
||||
xp_bar.max_value = to_next
|
||||
xp_bar.value = xp
|
||||
|
||||
func _on_level_up(player: Node, new_level: int) -> void:
|
||||
if player != local_player:
|
||||
return
|
||||
level_label.text = "Lv %d" % new_level
|
||||
_refresh_vitals()
|
||||
|
||||
func _on_dialog_opened(player: Node, npc: Node) -> void:
|
||||
if player != local_player:
|
||||
return
|
||||
dialog_panel.visible = true
|
||||
dialog_npc_node = npc
|
||||
dialog_npc.text = npc.profile.display_name
|
||||
dialog_log.text = "[i]" + npc.profile.greeting + "[/i]\n"
|
||||
dialog_input.text = ""
|
||||
dialog_input.grab_focus()
|
||||
_capture_ui(true)
|
||||
|
||||
func _on_dialog_submitted(text: String) -> void:
|
||||
if dialog_npc_node == null:
|
||||
return
|
||||
var dialog_sys: Node = _find_system("DialogSystem")
|
||||
if dialog_sys == null:
|
||||
return
|
||||
dialog_log.append_text("[b]Du:[/b] " + text + "\n[i]...[/i]\n")
|
||||
dialog_input.text = ""
|
||||
dialog_sys.ask(dialog_npc_node, local_player, text)
|
||||
|
||||
func show_answer(text: String) -> void:
|
||||
if dialog_npc_node == null:
|
||||
return
|
||||
dialog_log.text = dialog_log.text.replace("[i]...[/i]\n", "")
|
||||
dialog_log.append_text("[b]" + dialog_npc_node.profile.display_name + ":[/b] " + text + "\n")
|
||||
|
||||
func _on_inventory_changed(player: Node) -> void:
|
||||
if player != local_player:
|
||||
return
|
||||
_refresh_inventory()
|
||||
|
||||
func _refresh_inventory() -> void:
|
||||
for c in inventory_list.get_children():
|
||||
c.queue_free()
|
||||
if local_player == null:
|
||||
return
|
||||
var inv_sys: Node = _find_system("InventorySystem")
|
||||
if inv_sys == null:
|
||||
return
|
||||
var inv: Dictionary = inv_sys.get_inventory(local_player)
|
||||
if inv.is_empty():
|
||||
var lbl := Label.new()
|
||||
lbl.text = "(empty)"
|
||||
inventory_list.add_child(lbl)
|
||||
return
|
||||
for k in inv.keys():
|
||||
var lbl := Label.new()
|
||||
lbl.text = "%s: %d" % [str(k), inv[k]]
|
||||
inventory_list.add_child(lbl)
|
||||
|
||||
func _refresh_crafting() -> void:
|
||||
for c in crafting_list.get_children():
|
||||
c.queue_free()
|
||||
if local_player == null:
|
||||
return
|
||||
var c_sys: Node = _find_system("CraftingSystem")
|
||||
var inv_sys: Node = _find_system("InventorySystem")
|
||||
if c_sys == null or inv_sys == null:
|
||||
return
|
||||
for r in c_sys.get_recipes():
|
||||
var btn := Button.new()
|
||||
var inputs_str: String = ""
|
||||
for k in r.inputs.keys():
|
||||
inputs_str += "%s x%d " % [str(k), r.inputs[k]]
|
||||
btn.text = "%s (%s)" % [r.name, inputs_str.strip_edges()]
|
||||
btn.disabled = not c_sys.can_craft(local_player, r)
|
||||
btn.pressed.connect(func(): c_sys.craft(local_player, r.id); _refresh_crafting())
|
||||
crafting_list.add_child(btn)
|
||||
|
||||
func _populate_build_list() -> void:
|
||||
for c in build_list.get_children():
|
||||
c.queue_free()
|
||||
var b_sys: Node = _find_system("BuildingSystem")
|
||||
if b_sys == null:
|
||||
return
|
||||
var bps: Array = b_sys.get_blueprints()
|
||||
for i in range(bps.size()):
|
||||
var btn := Button.new()
|
||||
btn.text = "%d %s\n%s x%d" % [i + 1, bps[i].name, str(bps[i].material), bps[i].cost]
|
||||
btn.toggle_mode = true
|
||||
btn.button_pressed = (i == 0)
|
||||
btn.pressed.connect(func(): _select_build(i))
|
||||
build_list.add_child(btn)
|
||||
|
||||
func _select_build(idx: int) -> void:
|
||||
build_selected = idx
|
||||
var btns := build_list.get_children()
|
||||
for i in range(btns.size()):
|
||||
if btns[i] is Button:
|
||||
(btns[i] as Button).button_pressed = (i == idx)
|
||||
if build_preview:
|
||||
_update_preview_mesh()
|
||||
|
||||
func _toggle_build_mode() -> void:
|
||||
build_active = not build_active
|
||||
build_panel.visible = build_active
|
||||
if local_player and local_player.has_method("set_build_mode"):
|
||||
local_player.set_build_mode(build_active)
|
||||
if build_active:
|
||||
_create_build_preview()
|
||||
elif build_preview:
|
||||
build_preview.queue_free()
|
||||
build_preview = null
|
||||
|
||||
func _create_build_preview() -> void:
|
||||
if build_preview:
|
||||
build_preview.queue_free()
|
||||
var world: Node = get_tree().current_scene
|
||||
if world == null:
|
||||
return
|
||||
build_preview = MeshInstance3D.new()
|
||||
build_preview.cast_shadow = MeshInstance3D.SHADOW_CASTING_SETTING_OFF
|
||||
world.add_child(build_preview)
|
||||
_update_preview_mesh()
|
||||
|
||||
func _update_preview_mesh() -> void:
|
||||
if build_preview == null:
|
||||
return
|
||||
var b_sys: Node = _find_system("BuildingSystem")
|
||||
if b_sys == null:
|
||||
return
|
||||
var bp: Dictionary = b_sys.get_blueprints()[build_selected]
|
||||
var box := BoxMesh.new()
|
||||
box.size = bp.size
|
||||
build_preview.mesh = box
|
||||
var mat := StandardMaterial3D.new()
|
||||
var c: Color = bp.color
|
||||
c.a = 0.5
|
||||
mat.albedo_color = c
|
||||
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
mat.flags_unshaded = true
|
||||
build_preview.material_override = mat
|
||||
|
||||
func _update_build_preview() -> void:
|
||||
if build_preview == null or local_player == null:
|
||||
return
|
||||
var b_sys: Node = _find_system("BuildingSystem")
|
||||
if b_sys == null:
|
||||
return
|
||||
var pos: Vector3 = _ground_under_cursor()
|
||||
var snapped: Vector3 = b_sys.snap_position(pos)
|
||||
var bp: Dictionary = b_sys.get_blueprints()[build_selected]
|
||||
build_preview.global_position = snapped + Vector3(0, bp.size.y * 0.5, 0)
|
||||
build_preview.rotation.y = build_rotation
|
||||
|
||||
func _ground_under_cursor() -> Vector3:
|
||||
var cam: Camera3D = local_player.camera if local_player.has_method("get") else null
|
||||
if cam == null:
|
||||
return Vector3.ZERO
|
||||
var mouse := get_viewport().get_mouse_position()
|
||||
var from := cam.project_ray_origin(mouse)
|
||||
var dir := cam.project_ray_normal(mouse)
|
||||
if abs(dir.y) < 0.001:
|
||||
return from
|
||||
var t: float = -from.y / dir.y
|
||||
if t <= 0:
|
||||
return from
|
||||
return from + dir * t
|
||||
|
||||
func _try_place() -> void:
|
||||
if local_player == null:
|
||||
return
|
||||
var b_sys: Node = _find_system("BuildingSystem")
|
||||
if b_sys == null:
|
||||
return
|
||||
var bps: Array = b_sys.get_blueprints()
|
||||
var bp: Dictionary = bps[build_selected]
|
||||
var pos: Vector3 = _ground_under_cursor()
|
||||
b_sys.place(local_player, bp.id, pos, build_rotation)
|
||||
|
||||
func _try_remove() -> void:
|
||||
if local_player == null:
|
||||
return
|
||||
var cam: Camera3D = local_player.camera if local_player.has_method("get") else null
|
||||
if cam == null:
|
||||
return
|
||||
var mouse := get_viewport().get_mouse_position()
|
||||
var from := cam.project_ray_origin(mouse)
|
||||
var to := from + cam.project_ray_normal(mouse) * 100.0
|
||||
var space: PhysicsDirectSpaceState3D = local_player.get_world_3d().direct_space_state
|
||||
var query := PhysicsRayQueryParameters3D.create(from, to)
|
||||
query.collision_mask = 16
|
||||
var hit: Dictionary = space.intersect_ray(query)
|
||||
if hit.is_empty():
|
||||
return
|
||||
var node: Node = hit.collider
|
||||
while node and not node.is_in_group("buildings"):
|
||||
node = node.get_parent()
|
||||
if node:
|
||||
var b_sys: Node = _find_system("BuildingSystem")
|
||||
if b_sys:
|
||||
b_sys.remove(local_player, node.get_path())
|
||||
|
||||
func _on_chat(_peer_id: int, sender: String, text: String) -> void:
|
||||
chat_log.append_text("[b]%s:[/b] %s\n" % [sender, text])
|
||||
|
||||
func _on_chat_submitted(text: String) -> void:
|
||||
var c_sys: Node = _find_system("ChatSystem")
|
||||
if c_sys:
|
||||
c_sys.send(text)
|
||||
chat_input.text = ""
|
||||
chat_input.release_focus()
|
||||
_capture_ui(_any_panel_visible())
|
||||
|
||||
func _toggle_pause() -> void:
|
||||
pause_panel.visible = not pause_panel.visible
|
||||
if pause_panel.visible and multiplayer.multiplayer_peer is OfflineMultiplayerPeer:
|
||||
GameState.set_paused(true)
|
||||
else:
|
||||
GameState.set_paused(false)
|
||||
_capture_ui(_any_panel_visible())
|
||||
|
||||
func _on_resume_pressed() -> void:
|
||||
pause_panel.visible = false
|
||||
GameState.set_paused(false)
|
||||
_capture_ui(_any_panel_visible())
|
||||
|
||||
func _on_quit_pressed() -> void:
|
||||
Net.disconnect_net()
|
||||
GameState.set_paused(false)
|
||||
GameState.change_scene(GameState.SCENE_MAIN_MENU)
|
||||
|
||||
func _on_game_over_restart() -> void:
|
||||
Net.disconnect_net()
|
||||
GameState.set_paused(false)
|
||||
GameState.change_scene(GameState.SCENE_MAIN_MENU)
|
||||
|
||||
func _update_minimap() -> void:
|
||||
_minimap_accum += get_process_delta_time()
|
||||
if _minimap_accum < 0.20:
|
||||
return
|
||||
_minimap_accum = 0.0
|
||||
minimap_canvas.queue_redraw()
|
||||
if map_panel.visible:
|
||||
map_canvas.queue_redraw()
|
||||
|
||||
func _find_system(name: String) -> Node:
|
||||
var n: Node = get_tree().root.get_node_or_null("World/Systems/" + name)
|
||||
if n == null:
|
||||
n = get_tree().root.get_node_or_null("Dungeon/Systems/" + name)
|
||||
return n
|
||||
1
scenes/hud/hud.gd.uid
Normal file
1
scenes/hud/hud.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dimp3y1yydhw2
|
||||
@@ -1,237 +1,411 @@
|
||||
[gd_scene format=3]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://b0hud00001"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ability_active"]
|
||||
bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
border_width_bottom = 2
|
||||
border_width_left = 2
|
||||
border_width_right = 2
|
||||
border_width_top = 2
|
||||
border_color = Color(0.8, 0.8, 0.8, 1)
|
||||
[ext_resource type="Script" path="res://scenes/hud/hud.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://scenes/hud/minimap.gd" id="2"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ability_round"]
|
||||
bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
border_width_bottom = 2
|
||||
border_width_left = 2
|
||||
border_width_right = 2
|
||||
border_width_top = 2
|
||||
border_color = Color(0.8, 0.8, 0.8, 1)
|
||||
corner_radius_top_left = 22
|
||||
corner_radius_top_right = 22
|
||||
corner_radius_bottom_right = 22
|
||||
corner_radius_bottom_left = 22
|
||||
[node name="HUD" type="CanvasLayer"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_bg"]
|
||||
bg_color = Color(0.3, 0.1, 0.1, 1)
|
||||
[node name="VitalsPanel" type="PanelContainer" parent="."]
|
||||
offset_left = 12.0
|
||||
offset_top = 12.0
|
||||
offset_right = 312.0
|
||||
offset_bottom = 130.0
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_health_fill"]
|
||||
bg_color = Color(0.2, 0.8, 0.2, 1)
|
||||
[node name="VBox" type="VBoxContainer" parent="VitalsPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_shield_bg"]
|
||||
bg_color = Color(0.1, 0.1, 0.3, 1)
|
||||
[node name="HpRow" type="HBoxContainer" parent="VitalsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_shield_fill"]
|
||||
bg_color = Color(0.2, 0.5, 0.9, 1)
|
||||
|
||||
[node name="HUD" type="CanvasLayer" groups=["hud"]]
|
||||
|
||||
[node name="HealthBar" type="ProgressBar" parent="."]
|
||||
offset_left = 10.0
|
||||
offset_top = 10.0
|
||||
offset_right = 210.0
|
||||
offset_bottom = 30.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_health_bg")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_health_fill")
|
||||
[node name="HpBar" type="ProgressBar" parent="VitalsPanel/VBox/HpRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(220, 18)
|
||||
layout_mode = 2
|
||||
max_value = 100.0
|
||||
value = 100.0
|
||||
show_percentage = false
|
||||
|
||||
[node name="HealthLabel" type="Label" parent="HealthBar"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 12
|
||||
[node name="HpLabel" type="Label" parent="VitalsPanel/VBox/HpRow"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "100/100"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="ShieldBar" type="ProgressBar" parent="."]
|
||||
offset_left = 10.0
|
||||
offset_top = 35.0
|
||||
offset_right = 210.0
|
||||
offset_bottom = 55.0
|
||||
theme_override_styles/background = SubResource("StyleBoxFlat_shield_bg")
|
||||
theme_override_styles/fill = SubResource("StyleBoxFlat_shield_fill")
|
||||
[node name="ShieldRow" type="HBoxContainer" parent="VitalsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ShieldBar" type="ProgressBar" parent="VitalsPanel/VBox/ShieldRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(220, 14)
|
||||
layout_mode = 2
|
||||
max_value = 100.0
|
||||
value = 0.0
|
||||
|
||||
[node name="ShieldLabel" type="Label" parent="VitalsPanel/VBox/ShieldRow"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "0/0"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="XpRow" type="HBoxContainer" parent="VitalsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LevelLabel" type="Label" parent="VitalsPanel/VBox/XpRow"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Lv 1"
|
||||
|
||||
[node name="XpBar" type="ProgressBar" parent="VitalsPanel/VBox/XpRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(180, 12)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
max_value = 50.0
|
||||
value = 50.0
|
||||
show_percentage = false
|
||||
value = 0.0
|
||||
|
||||
[node name="ShieldLabel" type="Label" parent="ShieldBar"]
|
||||
[node name="VillageRow" type="HBoxContainer" parent="VitalsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VillageLabelStatic" type="Label" parent="VitalsPanel/VBox/VillageRow"]
|
||||
layout_mode = 2
|
||||
text = "Village"
|
||||
|
||||
[node name="VillageBar" type="ProgressBar" parent="VitalsPanel/VBox/VillageRow"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(180, 12)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
max_value = 1000.0
|
||||
value = 1000.0
|
||||
|
||||
[node name="WaveBox" type="PanelContainer" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -120.0
|
||||
offset_top = 12.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = 64.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="WaveBox"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="WaveLabel" type="Label" parent="WaveBox/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
horizontal_alignment = 1
|
||||
text = "Wave 1"
|
||||
theme_override_font_sizes/font_size = 18
|
||||
|
||||
[node name="WaveTimer" type="Label" parent="WaveBox/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
horizontal_alignment = 1
|
||||
text = "10:00"
|
||||
|
||||
[node name="MinimapPanel" type="PanelContainer" parent="."]
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -212.0
|
||||
offset_top = 12.0
|
||||
offset_right = -12.0
|
||||
offset_bottom = 212.0
|
||||
|
||||
[node name="MinimapCanvas" type="Control" parent="MinimapPanel"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
script = ExtResource("2")
|
||||
world_size = 80.0
|
||||
|
||||
[node name="AbilityBox" type="HBoxContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -200.0
|
||||
offset_top = -76.0
|
||||
offset_right = 280.0
|
||||
offset_bottom = -12.0
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="RoleIcon" type="Panel" parent="AbilityBox"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="RoleLabel" type="Label" parent="AbilityBox/RoleIcon"]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
text = "D"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
theme_override_font_sizes/font_size = 28
|
||||
|
||||
[node name="A1" type="Button" parent="AbilityBox"]
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
text = "1"
|
||||
|
||||
[node name="A2" type="Button" parent="AbilityBox"]
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
text = "2"
|
||||
|
||||
[node name="A3" type="Button" parent="AbilityBox"]
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
text = "3"
|
||||
|
||||
[node name="A4" type="Button" parent="AbilityBox"]
|
||||
custom_minimum_size = Vector2(56, 56)
|
||||
layout_mode = 2
|
||||
text = "4"
|
||||
|
||||
[node name="ChatPanel" type="PanelContainer" parent="."]
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 12.0
|
||||
offset_top = -200.0
|
||||
offset_right = 360.0
|
||||
offset_bottom = -12.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="ChatPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ChatLog" type="RichTextLabel" parent="ChatPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 140)
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
scroll_following = true
|
||||
fit_content = true
|
||||
|
||||
[node name="ChatInput" type="LineEdit" parent="ChatPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "Press Y to chat, Enter to send"
|
||||
|
||||
[node name="DeathOverlay" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
|
||||
[node name="Background" type="ColorRect" parent="DeathOverlay"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "50/50"
|
||||
color = Color(0.0, 0.0, 0.0, 0.5)
|
||||
|
||||
[node name="DeathLabel" type="Label" parent="DeathOverlay"]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -200.0
|
||||
offset_top = -40.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 40.0
|
||||
text = "Respawning..."
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
theme_override_font_sizes/font_size = 32
|
||||
|
||||
[node name="RespawnTimer" type="Label" parent="."]
|
||||
anchors_preset = 8
|
||||
[node name="InventoryPanel" type="PanelContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -50.0
|
||||
offset_top = -30.0
|
||||
offset_right = 50.0
|
||||
offset_bottom = 30.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 48
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
offset_left = -200.0
|
||||
offset_top = -200.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 200.0
|
||||
|
||||
[node name="AbilityBar" type="HBoxContainer" parent="."]
|
||||
anchors_preset = 7
|
||||
[node name="VBox" type="VBoxContainer" parent="InventoryPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title" type="Label" parent="InventoryPanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Inventory (I)"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="InventoryList" type="VBoxContainer" parent="InventoryPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="CraftingPanel" type="PanelContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -260.0
|
||||
offset_top = -240.0
|
||||
offset_right = 260.0
|
||||
offset_bottom = 240.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="CraftingPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title" type="Label" parent="CraftingPanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Crafting (C)"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="CraftingList" type="VBoxContainer" parent="CraftingPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="BuildPanel" type="PanelContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -130.0
|
||||
offset_top = -60.0
|
||||
offset_right = 130.0
|
||||
offset_bottom = -10.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
theme_override_constants/separation = 5
|
||||
offset_left = 12.0
|
||||
offset_top = -260.0
|
||||
offset_right = 360.0
|
||||
offset_bottom = -210.0
|
||||
|
||||
[node name="ClassIcon" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_round")
|
||||
[node name="VBox" type="VBoxContainer" parent="BuildPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/ClassIcon"]
|
||||
[node name="Title" type="Label" parent="BuildPanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Build Mode (B)"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="BuildList" type="HBoxContainer" parent="BuildPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DialogPanel" type="PanelContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = -200.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 200.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="DialogPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DialogNpc" type="Label" parent="DialogPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "NPC"
|
||||
horizontal_alignment = 1
|
||||
theme_override_font_sizes/font_size = 22
|
||||
|
||||
[node name="DialogLog" type="RichTextLabel" parent="DialogPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 280)
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
scroll_following = true
|
||||
fit_content = true
|
||||
|
||||
[node name="DialogInput" type="LineEdit" parent="DialogPanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
placeholder_text = "Frage stellen, Enter senden"
|
||||
|
||||
[node name="MapPanel" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
|
||||
[node name="Background" type="ColorRect" parent="MapPanel"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "D"
|
||||
color = Color(0.0, 0.0, 0.0, 0.7)
|
||||
|
||||
[node name="MapCanvas" type="Control" parent="MapPanel"]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -300.0
|
||||
offset_top = -300.0
|
||||
offset_right = 300.0
|
||||
offset_bottom = 300.0
|
||||
script = ExtResource("2")
|
||||
world_size = 200.0
|
||||
draw_labels = true
|
||||
|
||||
[node name="PausePanel" type="PanelContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -150.0
|
||||
offset_top = -120.0
|
||||
offset_right = 150.0
|
||||
offset_bottom = 120.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="PausePanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title" type="Label" parent="PausePanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Paused"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
theme_override_font_sizes/font_size = 28
|
||||
|
||||
[node name="Ability1" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_active")
|
||||
[node name="Resume" type="Button" parent="PausePanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Resume"
|
||||
|
||||
[node name="CooldownOverlay" type="ColorRect" parent="AbilityBar/Ability1"]
|
||||
layout_mode = 1
|
||||
[node name="QuitToMenu" type="Button" parent="PausePanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Quit to Menu"
|
||||
|
||||
[node name="GameOverOverlay" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0, 0, 0, 0.6)
|
||||
visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/Ability1"]
|
||||
[node name="Background" type="ColorRect" parent="GameOverOverlay"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "1"
|
||||
color = Color(0.2, 0.0, 0.0, 0.8)
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="GameOverOverlay"]
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -200.0
|
||||
offset_top = -100.0
|
||||
offset_right = 200.0
|
||||
offset_bottom = 100.0
|
||||
|
||||
[node name="Title" type="Label" parent="GameOverOverlay/VBox"]
|
||||
layout_mode = 2
|
||||
text = "GAME OVER"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
theme_override_font_sizes/font_size = 48
|
||||
|
||||
[node name="Ability2" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_active")
|
||||
[node name="Restart" type="Button" parent="GameOverOverlay/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Back to Main Menu"
|
||||
|
||||
[node name="CooldownOverlay" type="ColorRect" parent="AbilityBar/Ability2"]
|
||||
layout_mode = 1
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0, 0, 0, 0.6)
|
||||
visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/Ability2"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "2"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Ability3" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_active")
|
||||
|
||||
[node name="CooldownOverlay" type="ColorRect" parent="AbilityBar/Ability3"]
|
||||
layout_mode = 1
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0, 0, 0, 0.6)
|
||||
visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/Ability3"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "3"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Ability4" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_active")
|
||||
|
||||
[node name="CooldownOverlay" type="ColorRect" parent="AbilityBar/Ability4"]
|
||||
layout_mode = 1
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0, 0, 0, 0.6)
|
||||
visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/Ability4"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "4"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Ability5" type="Panel" parent="AbilityBar"]
|
||||
custom_minimum_size = Vector2(45, 45)
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ability_round")
|
||||
|
||||
[node name="CooldownOverlay" type="ColorRect" parent="AbilityBar/Ability5"]
|
||||
layout_mode = 1
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
color = Color(0, 0, 0, 0.6)
|
||||
visible = false
|
||||
|
||||
[node name="Label" type="Label" parent="AbilityBar/Ability5"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "P"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
[connection signal="pressed" from="PausePanel/VBox/Resume" to="." method="_on_resume_pressed"]
|
||||
[connection signal="pressed" from="PausePanel/VBox/QuitToMenu" to="." method="_on_quit_pressed"]
|
||||
[connection signal="pressed" from="GameOverOverlay/VBox/Restart" to="." method="_on_game_over_restart"]
|
||||
|
||||
40
scenes/hud/minimap.gd
Normal file
40
scenes/hud/minimap.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
extends Control
|
||||
|
||||
@export var world_size: float = 200.0
|
||||
@export var label_text: String = ""
|
||||
@export var draw_labels: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
set_process(false)
|
||||
|
||||
func _draw() -> void:
|
||||
var view_size: Vector2 = get_size()
|
||||
draw_rect(Rect2(Vector2.ZERO, view_size), Color(0.05, 0.05, 0.08, 0.85))
|
||||
draw_rect(Rect2(Vector2.ZERO, view_size), Color(0.6, 0.6, 0.6, 0.5), false, 2.0)
|
||||
var local: Node = _local_player()
|
||||
var center_offset: Vector2 = Vector2.ZERO
|
||||
if local:
|
||||
center_offset = Vector2((local as Node3D).global_position.x, (local as Node3D).global_position.z)
|
||||
var map_sys: Node = get_tree().root.get_node_or_null("World/Systems/MapSystem")
|
||||
if map_sys == null:
|
||||
return
|
||||
for entry in map_sys.get_marker_data():
|
||||
var pos: Vector3 = entry.pos
|
||||
var px: Vector2 = _to_pixel(Vector2(pos.x, pos.z), view_size, center_offset)
|
||||
if px.x < 0 or px.x > view_size.x or px.y < 0 or px.y > view_size.y:
|
||||
continue
|
||||
draw_circle(px, 3.0, entry.color)
|
||||
if draw_labels and entry.label != "":
|
||||
var f: Font = ThemeDB.fallback_font
|
||||
draw_string(f, px + Vector2(5, -5), entry.label, HORIZONTAL_ALIGNMENT_LEFT, -1, 12, Color.WHITE)
|
||||
|
||||
func _to_pixel(world: Vector2, view_size: Vector2, center: Vector2) -> Vector2:
|
||||
var rel: Vector2 = world - center
|
||||
var s: float = view_size.x / world_size
|
||||
return view_size * 0.5 + rel * s
|
||||
|
||||
func _local_player() -> Node:
|
||||
for p in get_tree().get_nodes_in_group("player"):
|
||||
if p.is_multiplayer_authority():
|
||||
return p
|
||||
return null
|
||||
1
scenes/hud/minimap.gd.uid
Normal file
1
scenes/hud/minimap.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bt0i0umsod51f
|
||||
Reference in New Issue
Block a user