84 lines
2.6 KiB
GDScript
84 lines
2.6 KiB
GDScript
extends Node2D
|
|
|
|
@export var speed = 100 # How fast the virus will move (pixels/sec).
|
|
@export var attack_range = 1000 # virus vision radius (pixels)
|
|
@export var max_health = 10
|
|
|
|
var health = max_health
|
|
|
|
# a virus is instantiated as Spawning and transitions (matures) into Spawned
|
|
# after a timer timeout, after which it is activated and ready to do its thing.
|
|
enum SpawningState {Spawning, Spawned}
|
|
# when idle, a virus Waits. if it has already performed some action, it may
|
|
# become Blocked for a while. otherwise it might be Running. like a process.
|
|
enum ActionState {Blocked, Waiting, Running}
|
|
|
|
var spawning_state
|
|
var action_state
|
|
|
|
var knockback_timer: Timer = Timer.new()
|
|
var knockback = Vector2.ZERO
|
|
|
|
# temp 0 because of if len == 0 in process
|
|
var targets = [0] # who the virus will attack
|
|
|
|
func _ready():
|
|
self.spawning_state = SpawningState.Spawning
|
|
self.action_state = ActionState.Waiting
|
|
self.add_to_group("Virus")
|
|
$AnimationTree.set("parameters/transition/transition_request", "processing")
|
|
knockback_timer.one_shot = true
|
|
add_child(knockback_timer);
|
|
|
|
func _process(delta):
|
|
if self.spawning_state != SpawningState.Spawned:
|
|
return # do nothing if not yet spawned
|
|
if self.targets.size() == 0:
|
|
return # do nothing if no set targets
|
|
|
|
# --- determine nearest target
|
|
var nearest_target = get_node("../../Player").position
|
|
var shortest_distance = nearest_target.distance_to(self.position)
|
|
|
|
# --- attack the nearest target, if within range
|
|
if self.action_state != ActionState.Blocked:
|
|
if shortest_distance < self.attack_range:
|
|
self.attack(nearest_target)
|
|
|
|
if knockback_timer.time_left > 0:
|
|
print_debug("knockback timer left: %f %s" % [knockback_timer.time_left, knockback])
|
|
self.position += knockback * delta
|
|
else:
|
|
# --- move towards nearest target
|
|
self.position += \
|
|
self.position.direction_to(nearest_target) * self.speed * delta
|
|
|
|
func attack(target):
|
|
# do attack, block until timer
|
|
self.action_state = ActionState.Blocked
|
|
|
|
func set_spawning():
|
|
self.spawning_state = SpawningState.Spawning
|
|
|
|
func set_spawned():
|
|
self.spawning_state = SpawningState.Spawned
|
|
|
|
func take_hit(damage, knockback_vector, knockback_strength = 1):
|
|
$HitSFX.play();
|
|
if self.spawning_state == SpawningState.Spawning:
|
|
health -= damage * 2
|
|
else:
|
|
health -= damage
|
|
if health <= 0:
|
|
get_node("../../Player").add_to_score(1);
|
|
queue_free()
|
|
elif knockback_strength > 0:
|
|
knockback = -knockback_vector;
|
|
knockback_timer.start(0.2 * knockback_strength);
|
|
# Flash white?
|
|
|
|
func _on_body_entered(body: Node2D) -> void:
|
|
if self.spawning_state == SpawningState.Spawning:
|
|
return
|
|
body.take_hit(1, self.position.direction_to(body.position) * 500, 2)
|