123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- extends CharacterBody2D
- class_name Plant
- signal shoot(ufo: UFO)
- @export var y_offset: float = 0.0
- @export var height: float = 100.0
- @export_range(1.0, 30.0) var grow_time: float = 1.0
- var growing: bool = true
- var grow_value: float = 0.0
- @export_range(0.0, 1.0) var base_scale: float = 0.5
- @onready var target_scale: float = get_scale().x
- @export_range(0.0, 1000.0) var max_hp = 100.0
- @onready var hp: float = max_hp
- var planted_position: Vector2 = Vector2(0, 0)
- var dead: bool = false
- var attackers: Array[UFO] = []
- var target_attacker: UFO = null # Used when the plant is dying
- @export var cost: int = 10
- @export var bullet_color: Color = Color(1, 1, 1, 1)
- @export var bullet_base_speed_u: int = 2000
- @export var bullet_base_speed_l: int = 1000
- @export var constant_sound: bool = false
- @onready var body = $Body
- enum TargetMode {
- NEAREST, HIGHEST, LOWEST
- }
- var ufo_search_timer: Timer = Timer.new()
- var attack_timer: Timer = Timer.new()
- @onready var ufos: Node2D = get_tree().get_root().find_child("UFOs", true, false)
- var victim: UFO = null
- @export var target_mode: TargetMode = TargetMode.NEAREST
- @export var attack_rate: float = 0.1
- @export var attack_range: float = 300.0
- @export var attack_damage: float = 10.0
- func _ready():
- move_local_y(y_offset)
- planted_position = get_position()
- ufo_search_timer.set_wait_time(0.1)
- ufo_search_timer.set_autostart(false)
- ufo_search_timer.set_one_shot(true)
- ufo_search_timer.connect("timeout", _on_attack)
- attack_timer.set_wait_time(attack_rate)
- attack_timer.set_autostart(false)
- attack_timer.set_one_shot(true)
- attack_timer.connect("timeout", _on_attack)
- add_child(ufo_search_timer)
- add_child(attack_timer)
- attack_timer.start()
- # Workaround crash run out of packets
- if constant_sound:
- $Coin.set_volume_db(-100)
- $Coin.play()
- func get_class():
- return "Plant"
- func _on_attack():
- find_ufo()
- if victim == null or victim.dead:
- ufo_search_timer.start()
- else:
- emit_signal("shoot", victim)
- attack_timer.start()
- if !constant_sound:
- $Coin.play()
- func find_ufo():
- victim = null
- var all_ufos = ufos.get_children()
- var plant_pos = get_global_position()
- if all_ufos.size() > 0:
- var best_ufo = all_ufos[0]
- var best_value = 0.0
- if target_mode == TargetMode.NEAREST:
- best_value = 10000000.0
- for ufo in ufos.get_children():
- if ufo.dead:
- continue
- var tested_value: float
- if target_mode == TargetMode.NEAREST:
- tested_value = ufo.get_global_position().distance_to(plant_pos)
- if tested_value <= attack_range:
- if tested_value < best_value:
- best_value = tested_value
- best_ufo = ufo
- victim = best_ufo
- else:
- tested_value = ufo.hp
- if tested_value > best_value:
- best_value = tested_value
- best_ufo = ufo
- victim = best_ufo
-
- func _process(delta):
- if growing:
- grow_value += delta / grow_time
- if grow_value > 1.0:
- grow_value = 1.0
- growing = false
- set_scale(Vector2(target_scale, target_scale))
- else:
- var new_scale = target_scale * (base_scale + grow_value * (1.0 - base_scale))
- set_scale(Vector2(new_scale, new_scale))
- elif dead:
- if target_attacker == null or target_attacker.dead:
- select_attacker()
- if target_attacker != null:
- velocity = target_attacker.get_global_position() - get_global_position()
- move_and_slide()
- var scale = get_scale().x
- scale *= (1.0 - delta)
- set_scale(Vector2(scale, scale))
- set_z_index(-30)
- rotate(delta * PI)
- if scale < 0.1:
- get_parent().remove_child(self)
- queue_free()
- else:
- if target_attacker == null or target_attacker.dead:
- alter_hp(delta * max_hp / 10.0)
- if constant_sound:
- $Coin.set_volume_db(-100)
- if victim != null and not victim.dead and constant_sound:
- $Coin.set_volume_db(-12)
- func select_attacker():
- for attacker in attackers:
- #if !attacker.dead:
- target_attacker = attacker
- func alter_hp(delta: float):
- hp += delta
- hp = min(hp, max_hp)
- set_position(Vector2(planted_position.x, planted_position.y - height * (1.0 - hp / max_hp)))
- func deal_damage(damage: float, attacker: UFO):
- if dead:
- return
- alter_hp(-damage)
- if attacker != null:
- attackers.push_back(attacker)
- if hp < 0:
- dead = true
- func is_ready():
- return !growing
|