extends Node2D static var _soft: GradientTexture2D var _sparks: Array[Dictionary] = [] var _smoke: Array[Dictionary] = [] var _timer := 0.0 var _last_hit := -1.0 var _age := 0.0 func _ready() -> void: z_index = 3 if _soft == null: _soft = GradientTexture2D.new() _soft.width = 48 _soft.height = 48 _soft.fill = GradientTexture2D.FILL_RADIAL _soft.fill_from = Vector2(0.5,0.5) _soft.fill_to = Vector2(1,0.5) var gradient := Gradient.new() gradient.set_color(0,Color.WHITE) gradient.set_color(1,Color(1,1,1,0)) _soft.gradient = gradient func hit(at: Vector2, direction: Vector2, kind: int) -> void: if _age-_last_hit<0.08: return _last_hit = _age var owner := get_parent() as Node2D var radius := float(owner.get_visual_size())*0.4 if owner.has_method("get_visual_size") else 24.0 var local := owner.to_local(at).limit_length(radius) var point := owner.to_global(local) for i in 7: if _sparks.size()>=36: _sparks.pop_front() _sparks.append({"point":point,"velocity":(-direction).rotated(randf_range(-1.4,1.4))*randf_range(20,75),"age":0.0,"life":randf_range(0.12,0.3),"kind":kind}) func _process(delta: float) -> void: _age += delta var owner := get_parent() if owner.has_method("is_mini_boosting") and (bool(owner.get("_is_destroyed")) or bool(owner.get("is_docked"))): _sparks.clear() _smoke.clear() queue_redraw() return _timer -= delta var ratio := float(owner.get("hull"))/maxf(1.0,float(owner.get("max_hull"))) if ratio<0.35 and ratio>0 and _timer<=0: _timer = 0.15+ratio*0.6 var local := Vector2(-8 if int(_age*3)%2 else 8,7) _smoke.append({"point":owner.to_global(local),"velocity":owner.velocity*0.15+Vector2(randf_range(-4,4),-6),"age":0.0,"life":0.65,"radius":randf_range(3,6)}) if _smoke.size()>10: _smoke.pop_front() for pool in [_sparks,_smoke]: for i in range(pool.size()-1,-1,-1): pool[i].age += delta pool[i].point += pool[i].velocity*delta if pool[i].age >= pool[i].life: pool.remove_at(i) queue_redraw() func _draw() -> void: for puff in _smoke: var t := float(puff.age)/float(puff.life) var radius := float(puff.radius)*(1+t*1.8) draw_texture_rect(_soft,Rect2(to_local(puff.point)-Vector2.ONE*radius,Vector2.ONE*radius*2),false,Color(0.35,0.26,0.22,(1-t)*0.3)) if t<0.2: draw_circle(to_local(puff.point),1.2,Color(1,0.48,0.12,(1-t*5)*0.8)) for spark in _sparks: var fade := 1.0-float(spark.age)/float(spark.life) var point := to_local(spark.point) var color: Color = [Color("ffc176"),Color("8de4ff"),Color("a4ff70")][int(spark.kind)] draw_line(point,point-to_local(global_position+spark.velocity.normalized()*4),Color(color,fade),1.0,true)