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 pulse := 0.88+0.12*sin(_time*1.8) var intensity := (0.35+ratio*0.65)*pulse var tint := Color("61d8ff").lerp(Color("a4edff"),ratio*0.35) # A soft Fresnel-like rim: transparent centre, luminous outer shell. draw_circle(Vector2.ZERO,shield_radius,Color(tint,0.012*intensity)) for layer in range(5,0,-1): draw_arc(Vector2.ZERO,shield_radius,0,TAU,96,Color(tint,0.012*intensity),float(layer)*2.6,true) for band in 4: draw_arc(Vector2.ZERO,shield_radius-1.5-band*1.6,0,TAU,96,Color(tint,0.018*intensity*(1.0-band/4.0)),2.0,true) draw_arc(Vector2.ZERO,shield_radius,0,TAU,96,Color(tint,0.34*intensity),1.1,true) # Slow highlights travel along the field without shifting its collision edge. for index in 3: var angle := _time*0.16+TAU*index/3.0 for segment in 8: var start := angle+segment*0.065 var alpha := sin((segment+0.5)/8.0*PI)*0.22*intensity draw_arc(Vector2.ZERO,shield_radius-0.6,start,start+0.07,5,Color("d0f6ff",alpha),1.6,true) _draw_impacts() func _draw_impacts() -> void: 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 draw_circle(contact,8.0*(1.0-t),Color(color,fade*0.12)) 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))