Randoloot/scripts/game/weapon_projectile.gd

83 lines
2.4 KiB
GDScript

extends Area2D
var direction := Vector2.UP
var projectile_speed := 600.0
var damage := 1.0
var max_range := 800.0
var weapon_kind := ItemDefinition.WeaponKind.PLASMA
var _distance_travelled := 0.0
var _already_hit: Dictionary = {}
func _ready() -> void:
body_entered.connect(_on_body_entered)
area_entered.connect(_on_area_entered)
rotation = direction.angle()
func configure(
start_position: Vector2,
travel_direction: Vector2,
kind: int,
speed: float,
projectile_damage: float,
projectile_range: float
) -> void:
global_position = start_position
direction = travel_direction.normalized()
weapon_kind = kind
projectile_speed = speed
damage = projectile_damage
max_range = projectile_range
func _physics_process(delta: float) -> void:
var step := projectile_speed * delta
global_position += direction * step
_distance_travelled += step
if _distance_travelled >= max_range:
queue_free()
func _draw() -> void:
match weapon_kind:
ItemDefinition.WeaponKind.PLASMA:
draw_circle(Vector2.ZERO, 6.0, Color(0.3, 0.85, 1.0, 0.95))
draw_circle(Vector2.ZERO, 3.0, Color(0.85, 0.98, 1.0, 1.0))
ItemDefinition.WeaponKind.MACHINE_GUN:
draw_rect(Rect2(-7.0, -2.0, 14.0, 4.0), Color(1.0, 0.82, 0.38, 1.0))
ItemDefinition.WeaponKind.MISSILE:
draw_colored_polygon(PackedVector2Array([
Vector2(10, 0), Vector2(-7, -4), Vector2(-4, 0), Vector2(-7, 4),
]), Color(1.0, 0.42, 0.2, 1.0))
func _on_body_entered(body: Node2D) -> void:
_hit_target(body)
func _on_area_entered(area: Area2D) -> void:
_hit_target(area)
func _hit_target(target: Node) -> void:
if weapon_kind == ItemDefinition.WeaponKind.MISSILE:
_explode_at_target(target)
else:
_apply_damage_once(target)
queue_free()
func _explode_at_target(impact_target: Node) -> void:
_apply_damage_once(impact_target)
var explosion_shape := CircleShape2D.new()
explosion_shape.radius = 120.0
var query := PhysicsShapeQueryParameters2D.new()
query.shape = explosion_shape
query.transform = Transform2D(0.0, global_position)
query.collision_mask = 4 # Enemy physics layer 3.
for result in get_world_2d().direct_space_state.intersect_shape(query, 32):
_apply_damage_once(result.get("collider"))
func _apply_damage_once(target: Variant) -> void:
if not (target is Node):
return
var instance_id: int = target.get_instance_id()
if _already_hit.has(instance_id):
return
_already_hit[instance_id] = true
if target.has_method("take_damage"):
target.call("take_damage", damage)