TowerDefense/Towers/Projectiles/Projectile.gd

98 lines
2.6 KiB
GDScript3
Raw Normal View History

extends CharacterBody3D
class_name Projectile
const TARGET_ENEMY : int = 1 ## Flag to target enemy
const TARGET_ALLY : int = 2 ## Flag to target ally
const MINIMUN_AREA : float = .1
enum TYPE { ## Types of projectiles
AOE, ## One target
BASIC, ## Multiple targets[br]work with [member ProjectileResource.damageArea]
PIERCING ## Piercing through many enemy[br]work with [member ProjectileResource.maxTarets]
}
var type : TYPE = TYPE.BASIC
var speed : int = 20
var allowedTargets : int = TARGET_ENEMY
var target : PhysicsBody3D
var vectorTarget : Vector3
var maxTargets : int = 1
var damage : int = 1
var enemiesInRange : Array[Enemy]
var affectedTarget : Array[Enemy]
var allyInRange : Array[Tower]
func _physics_process(delta: float) -> void:
prints(vectorTarget, is_instance_valid(target), vectorTarget == Vector3.ZERO)
if !is_instance_valid(target) && vectorTarget == Vector3.ZERO:
queue_free()
return
var globalPos : Vector3 = vectorTarget if vectorTarget else target.global_position
velocity = global_position.direction_to(globalPos) * speed
look_at(globalPos)
move_and_slide()
func onBodyEnteredDamageArea(body: Node3D) -> void:
if type == TYPE.AOE && targetable(body):
addTarget(body)
func onBodyCollideWithProjectile(body: Node3D) -> void:
if not affectedTarget.has(body) && (body == target || type == TYPE.PIERCING && targetable(body)):
addTarget(body)
resolveDamages()
func targetable(body: Node3D) -> bool:
if body is Enemy:
return TARGET_ENEMY & allowedTargets
if body is Tower:
return TARGET_ALLY & allowedTargets
return false
func resolveDamages() -> void:
for enemy in enemiesInRange:
if is_instance_valid(enemy):
maxTargets -= 1
enemy.take_damage(damage)
affectedTarget.append(enemy)
if maxTargets < 1:
queue_free()
func loadProjectile(resource: ProjectileResource, startPosition: Vector3, _target: PhysicsBody3D) -> void:
target = _target
global_position = startPosition
type = resource.type
if type == TYPE.PIERCING:
vectorTarget = target.global_position
# NOTE removing colision layer for pierce effect
$HitBox.collision_layer = 0
speed = resource.speed
maxTargets = resource.maxTargets
damage = resource.damage
allowedTargets = resource.allowedTargets
$Sprite3D.texture = resource.sprite
if type == TYPE.AOE && resource.damageArea:
$DamageArea/ProjectileArea.shape = resource.damageArea
func addTarget(body: Node3D) -> void:
if body is Enemy:
enemiesInRange.append(body)
if body is Tower:
allyInRange.append(body)
func removeTarget(body: Node3D) -> void:
if body is Enemy:
enemiesInRange.erase(body)
if body is Tower:
allyInRange.erase(body)