Randoloot/scripts/game/shield_visual.gd
2026-10-25 22:38:13 +01:00

62 lines
2.5 KiB
GDScript

extends Node2D
@export var shield_radius := 50.0
var current_shields := 100.0
var max_shields := 100.0
var _hit_flash_timer := 0.0
var _hits: Array[Dictionary] = []
var _time := 0.0
func _ready() -> void:
var owner := get_parent()
if owner is CharacterBody2D and owner.has_method("take_damage"):
owner.add_to_group("shielded_combatants")
func _process(delta: float) -> void:
_time += delta
_hit_flash_timer = maxf(0.0,_hit_flash_timer-delta)
for i in range(_hits.size()-1,-1,-1):
_hits[i].age += delta
if _hits[i].age >= 0.42: _hits.remove_at(i)
visible = current_shields > 0.0 or not _hits.is_empty()
var owner := get_parent()
if owner.has_method("is_mini_boosting") and bool(owner.get("_is_destroyed")): visible = false
if visible: queue_redraw()
func set_shield_values(current: float, maximum: float) -> void:
current_shields = current
max_shields = maxf(1.0,maximum)
visible = current_shields > 0.0 or not _hits.is_empty()
queue_redraw()
func flash_hit(world_point := Vector2.INF, damage_type := DamageTypes.Type.ENERGY, strength := 1.0) -> void:
_hit_flash_timer = 0.22
var direction := Vector2.UP if not world_point.is_finite() else to_local(world_point).normalized()
if direction.length_squared()<0.01: direction = Vector2.UP
if _hits.size()>=6: _hits.pop_front()
_hits.append({"angle":direction.angle(),"age":0.0,"kind":damage_type,"strength":clampf(strength,0.4,1.4)})
visible = true
queue_redraw()
func _draw() -> void:
var ratio := clampf(current_shields/max_shields,0.0,1.0)
if current_shields>0:
var ambient := 0.025+sin(_time*1.6)*0.008
draw_arc(Vector2.ZERO,shield_radius,0,TAU,80,Color(0.25,0.7,1,0.10+ratio*0.13),0.8,true)
draw_arc(Vector2.ZERO,shield_radius-1.0,0,TAU,80,Color(0.12,0.6,1,ambient),4.0,true)
for hit in _hits:
var t := float(hit.age)/0.42
var fade := (1.0-t)*(1.0-t)*float(hit.strength)
var color: Color = [Color("ffd18b"),Color("75dfff"),Color("a1f475")][int(hit.kind)]
var angle: float = hit.angle
var spread := 0.12+t*1.2
var radius := shield_radius+t*2.0
for layer in 3:
draw_arc(Vector2.ZERO,radius-float(layer)*1.5,angle-spread,angle+spread,28,Color(color,fade*(0.6 if layer==0 else 0.13)),1.4 if layer==0 else 3.0,true)
var contact := Vector2.RIGHT.rotated(angle)*shield_radius
for ring in 2:
draw_arc(contact,3.0+t*(17.0+ring*8.0),angle+PI*0.5,angle+PI*1.5,22,Color(color,fade*(0.5 if ring==0 else 0.17)),1.1,true)
if t<0.35:
var core := (1.0-t/0.35)*float(hit.strength)
draw_circle(contact,5*core,Color(color,core*0.22))
draw_circle(contact,1.8*core,Color(color.lightened(0.7),core))