saumwacht-godot/scripts/luneraria/ui/lune_minimap.gd
Martin Stickelbroeck f53859a298 M2: Helden, Items, Talente, Angriffschampions und Bossgrotte
Drei Helden mit Nähe-/Teilnahme-XP, Talenten und drei Itemplätzen,
drei Angriffschampions mit Buchung n -> n+1, Bossgrotte mit Streitfall,
ruhendem Boss, idempotenter Eroberung, einmaliger Entsendung für das
Siegerteam, hohem Kopfgeld und Sperre bis Sieg+4. HUD-Reiter, Porträt
aus echtem Modell, Grotten-Asset, Bots für alle Systeme. Regeln M2 73/73,
M1 91/91, App M2 15/15 und M1 38/38, Bossszenarien dokumentiert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 22:33:11 +02:00

70 lines
3.5 KiB
GDScript

extends Control
## Minimap drawn from the authoritative match state. Click or drag to move the camera.
signal focus_requested(point: Vector3)
const TEAM_COLORS: Array[Color] = [Color("5aa8ff"), Color("ff6a55"), Color("b37cff")]
var match_state: LuneMatch
var camera_focus := Vector3.ZERO
var camera_span: float = 34.0
func _ready() -> void:
custom_minimum_size = Vector2(236, 236)
mouse_filter = Control.MOUSE_FILTER_STOP
focus_mode = Control.FOCUS_NONE
tooltip_text = "Minimap · Klicken oder ziehen, um die Kamera zu bewegen"
func to_map(v: Vector2) -> Vector2:
var extent: float = LuneMap.HALF_EXTENT + 4.0
return (v + Vector2(extent, extent)) / (extent * 2.0) * size
func to_world(p: Vector2) -> Vector3:
var extent: float = LuneMap.HALF_EXTENT + 4.0
var v: Vector2 = p / size * extent * 2.0 - Vector2(extent, extent)
return Vector3(v.x, 0, v.y)
func _gui_input(event: InputEvent) -> void:
if (event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT) or (event is InputEventMouseMotion and event.button_mask & MOUSE_BUTTON_MASK_LEFT):
focus_requested.emit(to_world(event.position))
accept_event()
func _draw() -> void:
draw_rect(Rect2(Vector2.ZERO, size), Color(.04, .06, .06, .92))
draw_rect(Rect2(Vector2.ZERO, size), Color("5c4a33"), false, 1.5)
if match_state == null:
return
var a: Vector2 = to_map(Vector2(-40, -40))
var b: Vector2 = to_map(Vector2(40, 40))
draw_line(a, b, Color(.12, .38, .42, .8), 7.0)
for lane: String in LuneMap.LANES:
var path: LuneMap.LanePath = match_state.map.lanes[lane]
var points := PackedVector2Array()
for p: Vector2 in path.points:
points.append(to_map(p))
draw_polyline(points, Color(.62, .56, .42), 4.0, true)
var grotto: Vector2 = to_map(LuneMap.GROTTO)
var claim: Dictionary = match_state.boss.claim
var grotto_color: Color = TEAM_COLORS[int(claim.team)] if not claim.is_empty() else (Color(.62, .42, .95) if match_state.grotto_available() else Color(.35, .32, .4))
draw_circle(grotto, 6.0, grotto_color)
draw_arc(grotto, 6.0, 0, TAU, 16, Color(1, 1, 1, .6), 1.0)
var hp: Dictionary = {}
if match_state.phase == LuneMatch.Phase.COMBAT and match_state.combat != null:
for unit: LuneUnit in match_state.combat.units:
if unit.is_mobile() and unit.alive:
var radius: float = 4.0 if unit.kind == "boss" else (3.2 if unit.kind == "hero" else (1.8 if unit.kind == "monster" else 2.4))
draw_circle(to_map(unit.position), radius, Color("f2c96b") if unit.kind == "hero" else TEAM_COLORS[unit.team].lightened(.2 if unit.kind == "monster" else 0.0))
for definition: Dictionary in match_state.map.buildings:
var alive: bool = match_state.building_alive(definition.id)
if match_state.phase == LuneMatch.Phase.COMBAT and match_state.combat != null and match_state.combat.buildings.has(definition.id):
alive = (match_state.combat.buildings[definition.id] as LuneUnit).alive
var at: Vector2 = to_map(definition.position)
var radius: float = 6.5 if definition.tier == "core" else 4.0
var color: Color = TEAM_COLORS[int(definition.team)]
if alive:
draw_circle(at, radius, color)
draw_arc(at, radius, 0, TAU, 16, Color(1, 1, 1, .6), 1.0)
else:
draw_arc(at, radius, 0, TAU, 16, color.darkened(.3), 1.5)
draw_line(at - Vector2(radius, radius) * .6, at + Vector2(radius, radius) * .6, color.darkened(.3), 1.5)
var center: Vector2 = to_map(Vector2(camera_focus.x, camera_focus.z))
var span: float = camera_span / ((LuneMap.HALF_EXTENT + 4.0) * 2.0) * size.x
draw_rect(Rect2(center - Vector2(span * .9, span * .55), Vector2(span * 1.8, span * 1.1)), Color(1, 1, 1, .55), false, 1.2)