base_plant.gd 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. extends CharacterBody2D
  2. class_name Plant
  3. signal shoot(ufo: UFO)
  4. @export var y_offset: float = 0.0
  5. @export var height: float = 100.0
  6. @export_range(1.0, 30.0) var grow_time: float = 1.0
  7. var growing: bool = true
  8. var grow_value: float = 0.0
  9. @export_range(0.0, 1.0) var base_scale: float = 0.5
  10. @onready var target_scale: float = get_scale().x
  11. @export_range(0.0, 1000.0) var max_hp = 100.0
  12. @onready var hp: float = max_hp
  13. var planted_position: Vector2 = Vector2(0, 0)
  14. var dead: bool = false
  15. var attackers: Array[UFO] = []
  16. var target_attacker: UFO = null # Used when the plant is dying
  17. @export var cost: int = 10
  18. @export var bullet_color: Color = Color(1, 1, 1, 1)
  19. @export var bullet_base_speed_u: int = 2000
  20. @export var bullet_base_speed_l: int = 1000
  21. enum TargetMode {
  22. NEAREST, HIGHEST, LOWEST
  23. }
  24. var ufo_search_timer: Timer = Timer.new()
  25. var attack_timer: Timer = Timer.new()
  26. @onready var ufos: Node2D = get_tree().get_root().find_child("UFOs", true, false)
  27. var victim: UFO = null
  28. @export var target_mode: TargetMode = TargetMode.NEAREST
  29. @export var attack_rate: float = 0.1
  30. @export var attack_range: float = 300.0
  31. @export var attack_damage: float = 10.0
  32. func _ready():
  33. move_local_y(y_offset)
  34. planted_position = get_position()
  35. ufo_search_timer.set_wait_time(0.1)
  36. ufo_search_timer.set_autostart(false)
  37. ufo_search_timer.set_one_shot(true)
  38. ufo_search_timer.connect("timeout", _on_attack)
  39. attack_timer.set_wait_time(attack_rate)
  40. attack_timer.set_autostart(false)
  41. attack_timer.set_one_shot(true)
  42. attack_timer.connect("timeout", _on_attack)
  43. add_child(ufo_search_timer)
  44. add_child(attack_timer)
  45. attack_timer.start()
  46. func get_class():
  47. return "Plant"
  48. func _on_attack():
  49. find_ufo()
  50. if victim == null or victim.dead:
  51. ufo_search_timer.start()
  52. else:
  53. emit_signal("shoot", victim)
  54. attack_timer.start()
  55. $Coin.play()
  56. func find_ufo():
  57. victim = null
  58. var all_ufos = ufos.get_children()
  59. var plant_pos = get_global_position()
  60. if all_ufos.size() > 0:
  61. var best_ufo = all_ufos[0]
  62. var best_value = 0.0
  63. if target_mode == TargetMode.NEAREST:
  64. best_value = 10000000.0
  65. for ufo in ufos.get_children():
  66. if ufo.dead:
  67. continue
  68. var tested_value: float
  69. if target_mode == TargetMode.NEAREST:
  70. tested_value = ufo.get_global_position().distance_to(plant_pos)
  71. if tested_value <= attack_range:
  72. if tested_value < best_value:
  73. best_value = tested_value
  74. best_ufo = ufo
  75. victim = best_ufo
  76. else:
  77. tested_value = ufo.hp
  78. if tested_value > best_value:
  79. best_value = tested_value
  80. best_ufo = ufo
  81. victim = best_ufo
  82. func _process(delta):
  83. if growing:
  84. grow_value += delta / grow_time
  85. if grow_value > 1.0:
  86. grow_value = 1.0
  87. growing = false
  88. set_scale(Vector2(target_scale, target_scale))
  89. else:
  90. var new_scale = target_scale * (base_scale + grow_value * (1.0 - base_scale))
  91. set_scale(Vector2(new_scale, new_scale))
  92. elif dead:
  93. if target_attacker == null or target_attacker.dead:
  94. select_attacker()
  95. if target_attacker != null:
  96. velocity = target_attacker.get_global_position() - get_global_position()
  97. move_and_slide()
  98. var scale = get_scale().x
  99. scale *= (1.0 - delta)
  100. set_scale(Vector2(scale, scale))
  101. set_z_index(-30)
  102. rotate(delta * PI)
  103. if scale < 0.1:
  104. get_parent().remove_child(self)
  105. queue_free()
  106. else:
  107. if target_attacker == null or target_attacker.dead:
  108. alter_hp(delta * max_hp / 10.0)
  109. func select_attacker():
  110. for attacker in attackers:
  111. #if !attacker.dead:
  112. target_attacker = attacker
  113. func alter_hp(delta: float):
  114. hp += delta
  115. hp = min(hp, max_hp)
  116. set_position(Vector2(planted_position.x, planted_position.y - height * (1.0 - hp / max_hp)))
  117. func deal_damage(damage: float, attacker: UFO):
  118. if dead:
  119. return
  120. alter_hp(-damage)
  121. if attacker != null:
  122. attackers.push_back(attacker)
  123. if hp < 0:
  124. dead = true
  125. func is_ready():
  126. return !growing