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 ## Ground outline of the game camera's view (perspective trapezoid); empty = rectangle. var camera_footprint := PackedVector2Array() 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 # The Kluft: from the grotto spring along the symmetry axis into the south-eastern delta. var spring: Vector2 = LuneMap.GROTTO + LuneMap.AXIS * LuneTerrain.ARENA_RADIUS draw_line(to_map(spring), to_map(Vector2(40, 40)), Color(.12, .38, .42, .8), 7.0) draw_circle(to_map(Vector2(33, 33)), 11.0, Color(.12, .38, .42, .8)) 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) if camera_footprint.size() == 4: var outline := PackedVector2Array() for corner: Vector2 in camera_footprint: outline.append(to_map(corner).clamp(Vector2.ZERO, size)) outline.append(outline[0]) draw_polyline(outline, Color(1, 1, 1, .6), 1.2, true) else: 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)