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>
70 lines
3.5 KiB
GDScript
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)
|