166 lines
5.1 KiB
GDScript
166 lines
5.1 KiB
GDScript
# base player ability class
|
|
class_name AbilityPlayer
|
|
extends AbilityBase
|
|
|
|
|
|
var middleX
|
|
var playerPos
|
|
|
|
enum TargetType {
|
|
SINGLE,
|
|
CLEAVE,
|
|
CONE,
|
|
CHAIN,
|
|
SWIPE,
|
|
WAVE,
|
|
AREA,
|
|
RAY,
|
|
}
|
|
|
|
|
|
@export var target_type := TargetType.SINGLE
|
|
@export var target_angle := PI # mobs can't get behind
|
|
@export var base_cooldown := 0.3
|
|
@export var attack_damage := 100
|
|
@export var ability_cost := 1
|
|
@export var ability_binding := "use_A1"
|
|
|
|
var ability_ready:bool
|
|
|
|
func _ready() -> void:
|
|
middleX = get_viewport_rect().size.x / 2
|
|
SignalBus.player_leveled_up.connect(_on_player_leveled_up)
|
|
if PlayerState.level >= 2:
|
|
$AutoCooldown.start(auto_speed)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
playerPos = Vector2(middleX, get_viewport_rect().size.y * (0.75))
|
|
$AutoCooldown.wait_time = auto_speed
|
|
$CooldownIndicator.value = $AttackCooldown.time_left
|
|
|
|
|
|
func _get_enemies() -> Array:
|
|
var enemies := get_tree().get_nodes_in_group("enemies")
|
|
return enemies
|
|
|
|
|
|
func _get_num_enemies() -> int:
|
|
var enemies := get_tree().get_nodes_in_group("enemies")
|
|
return enemies.size()
|
|
|
|
|
|
func _get_distsq_to_player(enemy: Node) -> float:
|
|
return enemy.position.distance_squared_to(playerPos)
|
|
|
|
|
|
func _get_angle_to_player(enemy: Node) -> float:
|
|
return enemy.position.angle_to_point(playerPos)
|
|
|
|
|
|
func _get_target_in_range(enemies) -> Node:
|
|
# var numEnemies := _get_num_enemies()
|
|
var enemyDists
|
|
var closestEnemy
|
|
# get list of distances by mapping distance to each node in enemies
|
|
enemyDists = enemies.map(_get_distsq_to_player)
|
|
# get closest enemy by finding first index with min dist
|
|
if enemyDists.min() <= self.attack_range ** 2:
|
|
closestEnemy = enemies[enemyDists.find(enemyDists.min())]
|
|
|
|
return closestEnemy
|
|
|
|
|
|
func _get_targets_in_range(enemies) -> Array:
|
|
var enemyDists
|
|
var enemiesInRange := []
|
|
# get list of distances by mapping distance to each node in enemies
|
|
enemyDists = enemies.map(_get_distsq_to_player)
|
|
# append enemies in range to enemiesInRange
|
|
for i in range(enemies.size()):
|
|
if enemyDists[i] <= self.attack_range ** 2:
|
|
enemiesInRange.append(enemies[i])
|
|
|
|
return enemiesInRange
|
|
|
|
|
|
# func _get_targets_in_angle(enemies) -> Array:
|
|
# var enemyAngles
|
|
# var enemiesInAngle := []
|
|
# # get list of angles by mapping distance to each node in enemies
|
|
# enemyAngles = enemies.map(_get_angle_to_player)
|
|
# # append enemies in range to enemiesInAngle
|
|
# for i in range(enemies.size()):
|
|
# if enemyAngles[i] <= self.attack_range ** 2:
|
|
# enemiesInAngle.append(enemies[i])
|
|
|
|
# return enemiesInAngle
|
|
|
|
|
|
# func _get_targets(enemies) -> Array:
|
|
# if self.attack_range > 0:
|
|
# var enemiesInRange = _get_targets_in_range(enemies)
|
|
|
|
|
|
|
|
func _apply_status() -> void:
|
|
# TODO: Try passing damage and status type to target for mods, e.g. burning or stunned, and use with singleton stats to add thread to target for damage or do other things depending on the case
|
|
# unnecessary... can just loop await get_tree().create_timer(time).timeout
|
|
# just make sure target still exists each loop
|
|
pass
|
|
|
|
|
|
func _deal_idle_damage(enemiesList) -> void:
|
|
var total_damage = auto_damage
|
|
match target_type:
|
|
TargetType.SINGLE:
|
|
var target = _get_target_in_range(enemiesList)
|
|
if target:
|
|
target.damageTaken += total_damage
|
|
_:
|
|
var targets = _get_targets_in_range(enemiesList)
|
|
if targets:
|
|
for target in targets:
|
|
target.damageTaken += total_damage
|
|
|
|
|
|
func _deal_damage(enemiesList, damage) -> void:
|
|
match target_type:
|
|
TargetType.SINGLE:
|
|
var target = _get_target_in_range(enemiesList)
|
|
if target:
|
|
target.damageTaken += damage
|
|
_:
|
|
var targets = _get_targets_in_range(enemiesList)
|
|
if targets:
|
|
for target in targets:
|
|
target.damageTaken += damage
|
|
|
|
|
|
func _on_auto_cooldown_timeout() -> void:
|
|
var total_damage = auto_damage
|
|
var enemiesList = _get_enemies()
|
|
if not enemiesList.is_empty() and self.visible:
|
|
_deal_damage(enemiesList, total_damage)
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
# BUG: need to add ability queue, as you can't spam ability unless you hit the key at multiples of the cooldown length (e.g. 2 or 10 times exactly per cooldown).
|
|
if event.is_action_pressed(ability_binding):
|
|
var total_damage = attack_damage
|
|
var current_cooldown = base_cooldown
|
|
var enemiesList = _get_enemies()
|
|
if not enemiesList.is_empty() and self.visible and $AttackCooldown.is_stopped() and PlayerState.current_resource >= ability_cost:
|
|
_deal_damage(enemiesList, total_damage)
|
|
$CooldownIndicator.max_value = current_cooldown
|
|
$AttackCooldown.start(current_cooldown)
|
|
SignalBus.player_used_ability.emit(ability_cost)
|
|
|
|
|
|
# func _on_attack_cooldown_timeout() -> void:
|
|
# print("%s off cooldown!" % self.name)
|
|
|
|
|
|
func _on_player_leveled_up() -> void:
|
|
if PlayerState.level >= 2:
|
|
$AutoCooldown.start()
|