Files
aetherbound-guild/runtime/entry/party_line_track.gd
T

122 lines
5.0 KiB
GDScript

class_name ABGPartyLineTrack
extends Control
const INK := Color("#17252c")
const GOLD := Color("#d6ad5d")
const GOLD_LIGHT := Color("#f3d991")
const TEAL := Color("#4b8790")
const CORAL := Color("#d97964")
var actor_nodes: Array[Control] = []
var selected_recruit_id := ""
var locale := "zh_CN"
var draw_static_cord := true
enum RenderLayer { CORD, EFFECTS }
var render_layer := RenderLayer.CORD
func bind(nodes: Array[Control], selected_id: String, next_locale: String) -> void:
actor_nodes = nodes
selected_recruit_id = selected_id
locale = next_locale
queue_redraw()
func _process(_delta: float) -> void:
if not is_inside_tree():
return
queue_redraw()
func _exit_tree() -> void:
set_process(false)
actor_nodes.clear()
func _draw() -> void:
if actor_nodes.is_empty() or size.x <= 2.0 or size.y <= 2.0:
return
var centers: Array[Vector2] = []
for node in actor_nodes:
if not is_instance_valid(node):
continue
var rect := node.get_global_rect()
var track_rect := get_global_rect()
centers.append(Vector2(rect.get_center().x - track_rect.position.x, rect.position.y + rect.size.y * 0.68 - track_rect.position.y))
if centers.size() < 2:
return
var cord_y := centers[0].y
var left_x := maxf(18.0, centers[0].x - 92.0)
var right_x := minf(size.x - 18.0, centers[centers.size() - 1].x + 92.0)
if render_layer == RenderLayer.CORD:
if not draw_static_cord:
return
draw_line(Vector2(left_x, cord_y), Vector2(right_x, cord_y), Color(INK, 0.82), 8.0, true)
draw_line(Vector2(left_x, cord_y - 2.0), Vector2(right_x, cord_y - 2.0), GOLD, 2.0, true)
draw_line(Vector2(left_x, cord_y + 3.0), Vector2(right_x, cord_y + 3.0), Color(TEAL, 0.72), 1.0, true)
draw_circle(Vector2(left_x, cord_y), 9.0, Color(INK, 0.88))
draw_circle(Vector2(left_x, cord_y), 5.0, GOLD)
draw_circle(Vector2(right_x, cord_y), 9.0, Color(INK, 0.88))
draw_circle(Vector2(right_x, cord_y), 5.0, GOLD)
for index in range(centers.size() - 1):
var midpoint := centers[index].lerp(centers[index + 1], 0.5)
var diamond := PackedVector2Array([
midpoint + Vector2(0, -7), midpoint + Vector2(7, 0),
midpoint + Vector2(0, 7), midpoint + Vector2(-7, 0)
])
draw_colored_polygon(diamond, Color(INK, 0.90))
draw_polyline(diamond + PackedVector2Array([diamond[0]]), GOLD_LIGHT, 1.5, true)
return
var threat_target := Vector2(size.x * 0.94, size.y * 0.65)
draw_circle(threat_target, 8.0, Color(INK, 0.86))
draw_circle(threat_target, 5.0, Color(CORAL, 0.92))
draw_arc(threat_target, 12.0, 0.0, TAU, 28, Color(GOLD_LIGHT, 0.92), 2.0, true)
for index in range(centers.size()):
var point := centers[index]
var position := int(actor_nodes[index].get_meta("position", centers.size() - index - 1))
_draw_marker(point, position, position == 0)
var selected_index := -1
for index in range(actor_nodes.size()):
if is_instance_valid(actor_nodes[index]) and String(actor_nodes[index].get_meta("recruit_id", "")) == selected_recruit_id:
selected_index = index
break
if selected_index >= 0 and selected_index < centers.size():
var source := centers[selected_index]
draw_arc(source, 29.0, 0.0, TAU, 40, Color(GOLD_LIGHT, 0.92), 3.0, true)
draw_arc(source, 36.0, 0.2, 2.5, 40, Color(CORAL, 0.68), 2.0, true)
if threat_target.distance_to(source) > 20.0:
_draw_dashed_curve(source, threat_target)
for index in range(centers.size()):
if index == selected_index:
continue
var destination := centers[index] + Vector2(0, 18)
draw_arc(destination, 18.0, 0.0, TAU, 28, Color(GOLD_LIGHT, 0.75), 2.0, true)
draw_circle(destination, 4.0, Color(TEAL, 0.78))
func _draw_marker(point: Vector2, index: int, exposed: bool) -> void:
var center := point + Vector2(0, 18)
var fill := CORAL if exposed else TEAL
var shield := PackedVector2Array([
center + Vector2(-17, -11), center + Vector2(17, -11),
center + Vector2(13, 14), center + Vector2(0, 25),
center + Vector2(-13, 14)
])
draw_colored_polygon(shield, Color(INK, 0.92))
draw_polyline(shield + PackedVector2Array([shield[0]]), GOLD, 2.0, true)
draw_colored_polygon(PackedVector2Array([
center + Vector2(-12, -7), center + Vector2(12, -7),
center + Vector2(9, 10), center + Vector2(0, 18), center + Vector2(-9, 10)
]), Color(fill, 0.88))
draw_string(ThemeDB.fallback_font, center + Vector2(-4, 6), str(index), HORIZONTAL_ALIGNMENT_LEFT, -1, 14, GOLD_LIGHT)
func _draw_dashed_curve(start: Vector2, finish: Vector2) -> void:
var control := Vector2((start.x + finish.x) * 0.5, minf(size.y - 8.0, maxf(start.y, finish.y) + size.y * 0.26))
const SEGMENTS := 24
for index in range(SEGMENTS):
if index % 2 != 0:
continue
var t0 := float(index) / float(SEGMENTS)
var t1 := float(index + 1) / float(SEGMENTS)
draw_line(_quadratic_point(start, control, finish, t0), _quadratic_point(start, control, finish, t1), Color(GOLD_LIGHT, 0.92), 2.0, true)
func _quadratic_point(start: Vector2, control: Vector2, finish: Vector2, t: float) -> Vector2:
var inverse := 1.0 - t
return inverse * inverse * start + 2.0 * inverse * t * control + t * t * finish