65 lines
2.2 KiB
GDScript3
65 lines
2.2 KiB
GDScript3
|
|
class_name EnemyTargets
|
||
|
|
extends RefCounted
|
||
|
|
|
||
|
|
# #101 (#97c): who a wave enemy is coming for.
|
||
|
|
#
|
||
|
|
# Before this, every enemy component asked the same question - "which player
|
||
|
|
# SHIP is nearest?" - and a structure was scenery they flew straight past.
|
||
|
|
# #97 makes waves go after what the player has built, so the question
|
||
|
|
# becomes "which player thing is nearest", asked in one place so pursuit,
|
||
|
|
# standoff, the lancer's lunge and the ranged weapon cannot drift into
|
||
|
|
# disagreeing about it.
|
||
|
|
#
|
||
|
|
# There is one thumb on the scale. A ship inside SHIP_PRIORITY_RANGE always
|
||
|
|
# wins, even if a building is nearer: an enemy that ignored the vessels
|
||
|
|
# shooting it in order to reach a depot two hundred pixels closer would read
|
||
|
|
# as broken, and would make the fleet unable to defend anything by
|
||
|
|
# interposing itself.
|
||
|
|
|
||
|
|
const SHIP_PRIORITY_RANGE: float = 520.0
|
||
|
|
|
||
|
|
|
||
|
|
static func nearest_ship(node: Node, from: Vector2) -> Node2D:
|
||
|
|
var fleet: Node2D = node.get_tree().get_first_node_in_group("player_fleet")
|
||
|
|
if fleet == null:
|
||
|
|
return null
|
||
|
|
var nearest: Node2D = null
|
||
|
|
var best: float = INF
|
||
|
|
for ship in fleet.ships:
|
||
|
|
if not is_instance_valid(ship):
|
||
|
|
continue
|
||
|
|
var d: float = from.distance_to(ship.global_position)
|
||
|
|
if d < best:
|
||
|
|
best = d
|
||
|
|
nearest = ship
|
||
|
|
return nearest
|
||
|
|
|
||
|
|
|
||
|
|
static func nearest_building(node: Node, from: Vector2) -> Node2D:
|
||
|
|
var nearest: Node2D = null
|
||
|
|
var best: float = INF
|
||
|
|
for building in node.get_tree().get_nodes_in_group("buildings"):
|
||
|
|
if not is_instance_valid(building) or building.is_queued_for_deletion():
|
||
|
|
continue
|
||
|
|
var d: float = from.distance_to(building.global_position)
|
||
|
|
if d < best:
|
||
|
|
best = d
|
||
|
|
nearest = building
|
||
|
|
return nearest
|
||
|
|
|
||
|
|
|
||
|
|
static func nearest_target(node: Node, from: Vector2) -> Node2D:
|
||
|
|
var ship: Node2D = nearest_ship(node, from)
|
||
|
|
if ship != null and from.distance_to(ship.global_position) <= SHIP_PRIORITY_RANGE:
|
||
|
|
return ship
|
||
|
|
var building: Node2D = nearest_building(node, from)
|
||
|
|
if building == null:
|
||
|
|
return ship
|
||
|
|
if ship == null:
|
||
|
|
return building
|
||
|
|
return ship if from.distance_to(ship.global_position) \
|
||
|
|
<= from.distance_to(building.global_position) else building
|
||
|
|
|
||
|
|
|
||
|
|
static func is_building(target: Node) -> bool:
|
||
|
|
return target != null and target.is_in_group("buildings")
|