pulled out target selection to its own node
This commit is contained in:
parent
05914a3c64
commit
16951a9beb
@ -9,9 +9,9 @@ func _ready() -> void:
|
|||||||
func aim() -> void:
|
func aim() -> void:
|
||||||
super.aim()
|
super.aim()
|
||||||
var pos: Vector2 = Vector2(global_position.x, global_position.z)
|
var pos: Vector2 = Vector2(global_position.x, global_position.z)
|
||||||
var t_pos: Vector2 = Vector2(targeted_enemy.global_position.x, targeted_enemy.global_position.z)
|
var t_pos: Vector2 = Vector2(target_finder.get_target().global_position.x, target_finder.get_target().global_position.z)
|
||||||
var x: float = pos.distance_to(t_pos)
|
var x: float = pos.distance_to(t_pos)
|
||||||
var y: float = targeted_enemy.global_position.y - yaw_model.global_position.y
|
var y: float = target_finder.get_target().global_position.y - yaw_model.global_position.y
|
||||||
var v: float = force
|
var v: float = force
|
||||||
var g: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
var g: float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||||
var v2: float = pow(v, 2)
|
var v2: float = pow(v, 2)
|
||||||
|
@ -20,18 +20,14 @@ func _process(delta: float) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
if !targeted_enemy:
|
if !target_finder.get_target():
|
||||||
acquire_target()
|
time_since_firing_started = 0.0
|
||||||
|
current_time_between_shots = time_between_shots
|
||||||
else:
|
else:
|
||||||
if !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
aim()
|
||||||
targeted_enemy = null
|
time_since_firing_started += delta
|
||||||
time_since_firing_started = 0.0
|
var progress: float = clamp(time_since_firing_started / time_to_reach_max_speed, 0, 1.0)
|
||||||
current_time_between_shots = time_between_shots
|
current_time_between_shots = lerpf(time_between_shots, final_time_between_shots, progress)
|
||||||
if targeted_enemy:
|
if time_since_firing >= current_time_between_shots:
|
||||||
aim()
|
time_since_firing -= current_time_between_shots
|
||||||
time_since_firing_started += delta
|
shoot()
|
||||||
var progress: float = clamp(time_since_firing_started / time_to_reach_max_speed, 0, 1.0)
|
|
||||||
current_time_between_shots = lerpf(time_between_shots, final_time_between_shots, progress)
|
|
||||||
if time_since_firing >= current_time_between_shots:
|
|
||||||
time_since_firing -= current_time_between_shots
|
|
||||||
shoot()
|
|
||||||
|
@ -1,63 +1,27 @@
|
|||||||
class_name RocketLauncherTower extends ProjectileTower
|
class_name RocketLauncherTower extends ProjectileTower
|
||||||
|
|
||||||
var target_max: float = 3
|
|
||||||
var targets: Array[EnemyController] = []
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
super._ready()
|
super._ready()
|
||||||
target_max = floori(stats.get_attribute("Target Limit"))
|
target_finder.max_targets = floori(stats.get_attribute("Target Limit"))
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(_delta: float) -> void:
|
func _physics_process(_delta: float) -> void:
|
||||||
if !is_multiplayer_authority():
|
if !is_multiplayer_authority():
|
||||||
#only doing the graphical sort of stuff but not shoot logic
|
#only doing the graphical sort of stuff but not shoot logic
|
||||||
if targeted_enemy and is_instance_valid(targeted_enemy):
|
if target_finder.get_multiple_targets().size() >= 1:
|
||||||
if !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
|
||||||
targeted_enemy = null
|
|
||||||
else:
|
|
||||||
aim()
|
|
||||||
return
|
|
||||||
if targets.size() < target_max:
|
|
||||||
acquire_target()
|
|
||||||
if targets.size() > 0:
|
|
||||||
var valid_targets: Array[EnemyController] = []
|
|
||||||
for target: EnemyController in targets:
|
|
||||||
if is_instance_valid(target) and target.alive and global_position.distance_to(target.global_position) < target_range:
|
|
||||||
valid_targets.append(target)
|
|
||||||
targets = valid_targets
|
|
||||||
if targets.size() > 0:
|
|
||||||
targeted_enemy = targets[0]
|
|
||||||
networked_acquire_target.rpc(get_tree().root.get_path_to(targeted_enemy))
|
|
||||||
aim()
|
aim()
|
||||||
if time_since_firing >= time_between_shots:
|
return
|
||||||
time_since_firing -= time_between_shots
|
if target_finder.get_multiple_targets().size() >= 1:
|
||||||
shoot()
|
#networked_acquire_target.rpc(get_tree().root.get_path_to(targeted_enemy))
|
||||||
|
aim()
|
||||||
|
if time_since_firing >= time_between_shots:
|
||||||
func acquire_target() -> void:
|
time_since_firing -= time_between_shots
|
||||||
var possible_enemies: Array[EnemyController] = []
|
shoot()
|
||||||
for enemy: EnemyController in get_tree().get_nodes_in_group("Enemies"):
|
|
||||||
if !is_instance_valid(enemy):
|
|
||||||
continue
|
|
||||||
if global_position.distance_to(enemy.global_position) > target_range:
|
|
||||||
continue
|
|
||||||
if !(enemy.stats.target_type & stats.target_type):
|
|
||||||
continue
|
|
||||||
if targets.has(enemy):
|
|
||||||
continue
|
|
||||||
possible_enemies.append(enemy)
|
|
||||||
|
|
||||||
for x: int in target_max - targets.size():
|
|
||||||
if possible_enemies.size() == 0:
|
|
||||||
return
|
|
||||||
var chosen: EnemyController = possible_enemies.pick_random()
|
|
||||||
possible_enemies.erase(chosen)
|
|
||||||
targets.append(chosen)
|
|
||||||
|
|
||||||
|
|
||||||
func shoot() -> void:
|
func shoot() -> void:
|
||||||
for target: EnemyController in targets:
|
for target: EnemyController in target_finder.get_multiple_targets():
|
||||||
networked_spawn_rocket.rpc(get_tree().root.get_path_to(target), multiplayer.get_unique_id())
|
networked_spawn_rocket.rpc(get_tree().root.get_path_to(target), multiplayer.get_unique_id())
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,3 +4,4 @@ class_name Shredder extends StaticBody3D
|
|||||||
func _on_interact_button_button_interacted(_value: int, callback: Hero) -> void:
|
func _on_interact_button_button_interacted(_value: int, callback: Hero) -> void:
|
||||||
var card: Card = callback.inventory.remove_at(callback.inventory_selected_index) as Card
|
var card: Card = callback.inventory.remove_at(callback.inventory_selected_index) as Card
|
||||||
callback.currency += 5 * (card.rarity + 1)
|
callback.currency += 5 * (card.rarity + 1)
|
||||||
|
callback.decrement_selected()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=6 format=3 uid="uid://bvqu1heobgboe"]
|
[gd_scene load_steps=7 format=3 uid="uid://bvqu1heobgboe"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://Scripts/Towers/tower.gd" id="1_u8bfo"]
|
[ext_resource type="Script" path="res://Scripts/Towers/tower.gd" id="1_u8bfo"]
|
||||||
|
[ext_resource type="Script" path="res://Scripts/target_finder.gd" id="2_txlxp"]
|
||||||
|
|
||||||
[sub_resource type="Animation" id="Animation_vk4a8"]
|
[sub_resource type="Animation" id="Animation_vk4a8"]
|
||||||
resource_name = "shoot"
|
resource_name = "shoot"
|
||||||
@ -18,8 +19,9 @@ cull_mode = 1
|
|||||||
shading_mode = 0
|
shading_mode = 0
|
||||||
albedo_color = Color(1, 0, 0.415686, 0.223529)
|
albedo_color = Color(1, 0, 0.415686, 0.223529)
|
||||||
|
|
||||||
[node name="Tower" type="Node3D" node_paths=PackedStringArray("animator", "pitch_model", "yaw_model", "range_indicator", "audio_player")]
|
[node name="Tower" type="Node3D" node_paths=PackedStringArray("target_finder", "animator", "pitch_model", "yaw_model", "range_indicator", "audio_player")]
|
||||||
script = ExtResource("1_u8bfo")
|
script = ExtResource("1_u8bfo")
|
||||||
|
target_finder = NodePath("TargetFinder")
|
||||||
animator = NodePath("AnimationPlayer")
|
animator = NodePath("AnimationPlayer")
|
||||||
pitch_model = NodePath("Pitch")
|
pitch_model = NodePath("Pitch")
|
||||||
yaw_model = NodePath("Yaw")
|
yaw_model = NodePath("Yaw")
|
||||||
@ -51,3 +53,7 @@ radius = 10.0
|
|||||||
radial_segments = 16
|
radial_segments = 16
|
||||||
rings = 16
|
rings = 16
|
||||||
material = SubResource("StandardMaterial3D_1ucq4")
|
material = SubResource("StandardMaterial3D_1ucq4")
|
||||||
|
|
||||||
|
[node name="TargetFinder" type="Node" parent="." node_paths=PackedStringArray("tower")]
|
||||||
|
script = ExtResource("2_txlxp")
|
||||||
|
tower = NodePath("..")
|
||||||
|
@ -5,7 +5,7 @@ var direction: Vector3
|
|||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
distance_remaining = character.global_position.distance_squared_to(goal.global_position)
|
distance_remaining = character.global_position.distance_to(goal.global_position)
|
||||||
direction = character.global_position.direction_to(goal.global_position)
|
direction = character.global_position.direction_to(goal.global_position)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,10 +3,9 @@ class_name HitscanTower extends Tower
|
|||||||
|
|
||||||
func shoot() -> void:
|
func shoot() -> void:
|
||||||
super.shoot()
|
super.shoot()
|
||||||
if targeted_enemy and is_instance_valid(targeted_enemy) and targeted_enemy.alive:
|
target_finder.get_target().damage(damage)
|
||||||
targeted_enemy.damage(damage)
|
if Data.preferences.display_tower_damage_indicators:
|
||||||
if Data.preferences.display_tower_damage_indicators:
|
spawn_damage_indicator(target_finder.get_target().sprite.global_position)
|
||||||
spawn_damage_indicator(targeted_enemy.sprite.global_position)
|
|
||||||
|
|
||||||
|
|
||||||
@rpc("reliable")
|
@rpc("reliable")
|
||||||
|
@ -7,7 +7,7 @@ class_name ShapecastTower extends Tower
|
|||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
super._process(delta)
|
super._process(delta)
|
||||||
if targeted_enemy:
|
if target_finder.get_target():
|
||||||
particlesystem.emitting = true
|
particlesystem.emitting = true
|
||||||
else:
|
else:
|
||||||
particlesystem.emitting = false
|
particlesystem.emitting = false
|
||||||
@ -20,8 +20,8 @@ func shoot() -> void:
|
|||||||
|
|
||||||
|
|
||||||
func aim() -> void:
|
func aim() -> void:
|
||||||
yaw_model.look_at(targeted_enemy.global_position)
|
yaw_model.look_at(target_finder.get_target().global_position)
|
||||||
pitch_model.look_at(targeted_enemy.global_position)
|
pitch_model.look_at(target_finder.get_target().global_position)
|
||||||
pitch_model.rotation.x = 0.0
|
pitch_model.rotation.x = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@ class_name StatusApplyingTower extends HitscanTower
|
|||||||
|
|
||||||
func shoot() -> void:
|
func shoot() -> void:
|
||||||
super.shoot()
|
super.shoot()
|
||||||
if targeted_enemy and is_instance_valid(targeted_enemy) and targeted_enemy.alive:
|
if target_finder.get_target():
|
||||||
targeted_enemy.damage(damage)
|
target_finder.get_target().damage(damage)
|
||||||
targeted_enemy.status_manager.add_effect(build_status_object())
|
target_finder.get_target().status_manager.add_effect(build_status_object())
|
||||||
|
|
||||||
|
|
||||||
func build_status_object() -> StatusEffect:
|
func build_status_object() -> StatusEffect:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class_name Tower extends Node3D
|
class_name Tower extends Node3D
|
||||||
|
|
||||||
@export var stats: CardText
|
@export var stats: CardText
|
||||||
|
@export var target_finder: TargetFinder
|
||||||
@export var animator: AnimationPlayer
|
@export var animator: AnimationPlayer
|
||||||
@export var pitch_model: MeshInstance3D
|
@export var pitch_model: MeshInstance3D
|
||||||
@export var yaw_model: MeshInstance3D
|
@export var yaw_model: MeshInstance3D
|
||||||
@ -10,7 +11,7 @@ class_name Tower extends Node3D
|
|||||||
var owner_id: int
|
var owner_id: int
|
||||||
var damage_particle_scene: PackedScene = preload("res://Scenes/damage_particle.tscn")
|
var damage_particle_scene: PackedScene = preload("res://Scenes/damage_particle.tscn")
|
||||||
var base_name: String
|
var base_name: String
|
||||||
var targeted_enemy: EnemyController
|
#var targeted_enemy: EnemyController
|
||||||
var time_since_firing: float = 0.0
|
var time_since_firing: float = 0.0
|
||||||
var time_between_shots: float = 0.0
|
var time_between_shots: float = 0.0
|
||||||
var damage: float = 0.0
|
var damage: float = 0.0
|
||||||
@ -38,46 +39,22 @@ func _process(delta: float) -> void:
|
|||||||
func _physics_process(_delta: float) -> void:
|
func _physics_process(_delta: float) -> void:
|
||||||
if !is_multiplayer_authority():
|
if !is_multiplayer_authority():
|
||||||
#only doing the graphical sort of stuff but not shoot logic
|
#only doing the graphical sort of stuff but not shoot logic
|
||||||
if targeted_enemy:
|
if target_finder.get_target():
|
||||||
if !is_instance_valid(targeted_enemy) or !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
|
||||||
targeted_enemy = null
|
|
||||||
else:
|
|
||||||
aim()
|
|
||||||
return
|
|
||||||
if !targeted_enemy:
|
|
||||||
acquire_target()
|
|
||||||
else:
|
|
||||||
if !is_instance_valid(targeted_enemy) or !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
|
||||||
targeted_enemy = null
|
|
||||||
if targeted_enemy:
|
|
||||||
aim()
|
aim()
|
||||||
if time_since_firing >= time_between_shots:
|
return
|
||||||
time_since_firing -= time_between_shots
|
if target_finder.get_target():
|
||||||
shoot()
|
aim()
|
||||||
|
if time_since_firing >= time_between_shots:
|
||||||
|
time_since_firing -= time_between_shots
|
||||||
|
shoot()
|
||||||
|
|
||||||
|
|
||||||
func aim() -> void:
|
func aim() -> void:
|
||||||
yaw_model.look_at(targeted_enemy.global_position)
|
yaw_model.look_at(target_finder.get_target().global_position)
|
||||||
pitch_model.look_at(targeted_enemy.global_position)
|
pitch_model.look_at(target_finder.get_target().global_position)
|
||||||
pitch_model.rotation.x = 0.0
|
pitch_model.rotation.x = 0.0
|
||||||
|
|
||||||
|
|
||||||
func acquire_target() -> void:
|
|
||||||
var most_progressed_enemy: EnemyController = null
|
|
||||||
for enemy: EnemyController in get_tree().get_nodes_in_group("Enemies"):
|
|
||||||
if global_position.distance_to(enemy.global_position) > target_range:
|
|
||||||
continue
|
|
||||||
var em_1: EnemyMovement = enemy.movement_controller as EnemyMovement
|
|
||||||
var em_2: EnemyMovement
|
|
||||||
if most_progressed_enemy != null:
|
|
||||||
em_2 = most_progressed_enemy.movement_controller as EnemyMovement
|
|
||||||
if (most_progressed_enemy == null or em_1.distance_remaining < em_2.distance_remaining) and enemy.stats.target_type & stats.target_type:
|
|
||||||
most_progressed_enemy = enemy
|
|
||||||
if most_progressed_enemy != null:
|
|
||||||
targeted_enemy = most_progressed_enemy
|
|
||||||
networked_acquire_target.rpc(get_tree().root.get_path_to(most_progressed_enemy))
|
|
||||||
|
|
||||||
|
|
||||||
func shoot() -> void:
|
func shoot() -> void:
|
||||||
animator.play("shoot")
|
animator.play("shoot")
|
||||||
audio_player.play()
|
audio_player.play()
|
||||||
@ -98,6 +75,6 @@ func networked_shoot() -> void:
|
|||||||
shoot()
|
shoot()
|
||||||
|
|
||||||
|
|
||||||
@rpc("reliable")
|
#@rpc("reliable")
|
||||||
func networked_acquire_target(target_node_path: String) -> void:
|
#func networked_acquire_target(target_node_path: String) -> void:
|
||||||
targeted_enemy = get_tree().root.get_node(target_node_path)
|
#targeted_enemy = get_tree().root.get_node(target_node_path)
|
||||||
|
62
Scripts/target_finder.gd
Normal file
62
Scripts/target_finder.gd
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
class_name TargetFinder extends Node
|
||||||
|
|
||||||
|
@export var tower: Tower
|
||||||
|
@export var max_targets: int = 1
|
||||||
|
|
||||||
|
var target_cache: EnemyController
|
||||||
|
var multiple_targets_cache: Array[EnemyController]
|
||||||
|
|
||||||
|
|
||||||
|
func get_multiple_targets() -> Array[EnemyController]:
|
||||||
|
var new_cache: Array[EnemyController] = []
|
||||||
|
for enemy: EnemyController in multiple_targets_cache:
|
||||||
|
if is_instance_valid(enemy) and enemy.alive and enemy.global_position.distance_to(tower.global_position) <= tower.target_range:
|
||||||
|
new_cache.append(enemy)
|
||||||
|
if new_cache.size() < max_targets:
|
||||||
|
multiple_targets_cache = find_multiple_targets(new_cache)
|
||||||
|
return multiple_targets_cache
|
||||||
|
|
||||||
|
|
||||||
|
func get_target() -> EnemyController:
|
||||||
|
if !is_instance_valid(target_cache) or !target_cache.alive or tower.global_position.distance_to(target_cache.global_position) > tower.target_range:
|
||||||
|
target_cache = find_enemy()
|
||||||
|
return target_cache
|
||||||
|
|
||||||
|
|
||||||
|
func find_enemy() -> EnemyController:
|
||||||
|
var most_progressed_enemy: EnemyController = null
|
||||||
|
for enemy: EnemyController in get_tree().get_nodes_in_group("Enemies"):
|
||||||
|
if tower.global_position.distance_to(enemy.global_position) > tower.target_range:
|
||||||
|
continue
|
||||||
|
var em_1: EnemyMovement = enemy.movement_controller as EnemyMovement
|
||||||
|
var em_2: EnemyMovement
|
||||||
|
if most_progressed_enemy != null:
|
||||||
|
em_2 = most_progressed_enemy.movement_controller as EnemyMovement
|
||||||
|
if (most_progressed_enemy == null or em_1.distance_remaining < em_2.distance_remaining) and enemy.stats.target_type & tower.stats.target_type:
|
||||||
|
most_progressed_enemy = enemy
|
||||||
|
return most_progressed_enemy
|
||||||
|
#TODO: Figure out how to multiplayer-ize this
|
||||||
|
#networked_acquire_target.rpc(get_tree().root.get_path_to(most_progressed_enemy))
|
||||||
|
|
||||||
|
|
||||||
|
func find_multiple_targets(existing_cache: Array[EnemyController]) -> Array[EnemyController]:
|
||||||
|
var possible_enemies: Array[EnemyController] = []
|
||||||
|
for enemy: EnemyController in get_tree().get_nodes_in_group("Enemies"):
|
||||||
|
if !is_instance_valid(enemy):
|
||||||
|
continue
|
||||||
|
if tower.global_position.distance_to(enemy.global_position) > tower.target_range:
|
||||||
|
continue
|
||||||
|
if !(enemy.stats.target_type & tower.stats.target_type):
|
||||||
|
continue
|
||||||
|
if multiple_targets_cache.has(enemy):
|
||||||
|
continue
|
||||||
|
possible_enemies.append(enemy)
|
||||||
|
|
||||||
|
for x: int in max_targets - existing_cache.size():
|
||||||
|
if possible_enemies.size() == 0:
|
||||||
|
break
|
||||||
|
var chosen: EnemyController = possible_enemies.pick_random()
|
||||||
|
possible_enemies.erase(chosen)
|
||||||
|
existing_cache.append(chosen)
|
||||||
|
|
||||||
|
return existing_cache
|
Loading…
x
Reference in New Issue
Block a user