extends Node2D
@onready var timer = $Timer
@onready var animated_sprite_2d = $AnimatedSprite2D
@onready var los_raycast = $"LOS Raycast"
@export var in_range_targets: Array[CharacterBody2D] = []
@export var los_targets: Array[CharacterBody2D] = []
@export var tethered: bool = false:
get:
return tethered
set(value):
if value == true:
tethered = value
var current_frame = animated_sprite_2d.get_frame()
var current_progress = animated_sprite_2d.get_frame_progress()
animated_sprite_2d.play("Tethered")
animated_sprite_2d.set_frame_and_progress(current_frame, current_progress)
else:
tethered = value
var current_frame = animated_sprite_2d.get_frame()
var current_progress = animated_sprite_2d.get_frame_progress()
animated_sprite_2d.play("Untethered")
animated_sprite_2d.set_frame_and_progress(current_frame, current_progress)
@export var tethered_player: CharacterBody2D
var on_player_vertex = preload("res://Scenes/Objects/player_tether_node.tscn")
var created_vertices = [self]
signal tether_created(player, previous_target)
signal tether_broken(vertex)
func _physics_process(delta):
var space_state = get_world_2d().direct_space_state
if tethered == true && tethered_player != null:
var query = PhysicsRayQueryParameters2D.create(los_raycast.global_position, tethered_player.global_position,
0b00000000_00000000_00000000_00000011, [self])
query.collide_with_areas = true
var result = space_state.intersect_ray(query)
if !result.is_empty():
print("Tether Broken", ", Sent from: ", self, "\n")
untether()
for target in in_range_targets:
var query = PhysicsRayQueryParameters2D.create(los_raycast.global_position, target.global_position,
0b00000000_00000000_00000000_00000011, [self])
query.collide_with_areas = true
var result = space_state.intersect_ray(query)
if result.is_empty() && !los_targets.has(target) && timer.is_stopped():
timer.start()
elif !result.is_empty() && los_targets.has(target):
los_targets.erase(target)
func _on_area_2d_body_entered(body):
in_range_targets.append(body)
if !in_range_targets.is_empty():
timer.start()
func _on_area_2d_body_exited(body):
in_range_targets.erase(body)
los_targets.erase(body)
if body == tethered_player:
untether()
func _on_timer_timeout():
los_check()
func tether(target: CharacterBody2D):
tethered = true
tethered_player = target
tether_created.emit(tethered_player, self)
print("Is tethered: ", tethered, " Sent from: ", self, "\n")
print("Tethered to: ", tethered_player, " Sent from: ", self, "\n")
func untether():
print("Untethered, Sent from: ", self, "\n")
tethered = false
los_targets.erase(tethered_player)
tethered_player = null
tether_broken.emit(self)
if !los_targets.is_empty():
timer.start()
func los_check():
los_raycast.enabled = true
for target in in_range_targets:
los_raycast.target_position = -(los_raycast.global_position - target.global_position)
los_raycast.force_raycast_update()
if (los_raycast.get_collider() == null) && (los_targets.find(target) == -1):
los_targets.append(target)
los_raycast.enabled = false
print("Targets in line of sight: ", los_targets, " Sent from: ", self, "\n")
if !tethered && !los_targets.is_empty():
tether(los_targets[0])
func instantiate_on_player_vertex(player, previous_target):
var instance = on_player_vertex.instantiate()
add_child(instance)
instance.anchor = player
instance.previous_target = previous_target
created_vertices.append(instance)
instance.connect("tether_created", instantiate_on_player_vertex)
instance.connect("tether_broken", break_subsequent_vertices)
func break_subsequent_vertices(vertex):
pass
Hopefully this is formatted correctly, otherwise I’ll edit it.
The add_child is within the instantiate_on_player_vertex function, which is hooked up to the tether_created signal, which I connected through the editor.
Also please feel free to give me any other pointers, this is my first time writing in gdscript and I’d love some pointers or if anything I’m doing here is particularly egregious or incorrect.