v4.2.2
Question
Why can’t I aim the “whip” attack? It’s supposed to detect aim while the whipTimer is running, and then attack in the last direction after the timer is up. It used to work, but after moving some code into new functions and whatnot, it just doesn’t work. I can’t aim. It just performs the attack facing forwards.
Code
extends CharacterBody2D
var direction: = Vector2.ZERO
var arm_aim = Vector2.ZERO
var whip_aim: float = 0
var redirect_aim = Vector2.ZERO
var last_direction: Vector2 = Vector2.RIGHT
var can_move = true
var can_flip = true
var flash_timer: Timer
var whip_timer: Timer
var nearest_bullet: Bullet = null
var bullet = preload("res://scenes/cowboyBullet.tscn")
var flash_scene = preload("res://scenes/cowboyFlash.tscn")
var roll_shot_scene = preload("res://scenes/cowboyRollShot.tscn")
var lasso = preload("res://scenes/cowboyLasso.tscn")
var lasso_projectile: Node2D = null
var rope: Line2D = null
@export var speed: int = 75
@onready var anim_player = $AnimationPlayer
@onready var sprite = $Sprite2D
@onready var pivot = $"Shoulder Pivot"
@onready var arm = $"Shoulder Pivot/Arm"
@onready var bullet_spawn = $"Shoulder Pivot/Arm/Bullet Spawn"
@onready var lasso_spawn = $"Shoulder Pivot/Arm/Lasso Spawn"
@onready var flash_spawn = $"Flash Spawn"
@onready var roll_shot_spawn = $"Roll Shot Spawn"
enum State { IDLE, RUNNING, ROLLING, ROLL_SHOOT, AIMING, SHOOTING, WHIPPING, LASSO_THROW }
var state: State = State.IDLE
func _ready():
anim_player.animation_finished.connect(_on_animation_finished)
func _process(delta):
if state == State.WHIPPING and whip_timer and whip_timer.time_left > 0:
arm_aim = Input.get_vector("p1aimLeft", "p1aimRight", "p1aimUp", "p1aimDown").normalized()
if arm_aim.length() > 0:
if sprite.flip_h:
arm_aim.x *= -1
arm_aim.y *= -1
whip_aim = arm_aim.angle()
print(arm_aim, " | ", whip_aim)
if whip_aim > PI / 2 or whip_aim < -PI / 2:
pivot.scale.y = -1
else:
pivot.scale.y = 1
else:
pivot.scale.y = 1
if rope and is_instance_valid(lasso_projectile):
rope.clear_points()
rope.add_point(lasso_spawn.global_position)
rope.add_point(lasso_projectile.global_position)
func _physics_process(delta):
if can_move == true:
movement()
rolling()
attackA()
attackB()
velocity = direction * speed
if state == State.SHOOTING:
velocity = Vector2.ZERO
move_and_slide()
func movement():
func rolling():
func flash():
func rollShoot():
func attackA():
func shoot():
func attackB():
if Input.is_action_just_pressed("p1attackB") and state not in [State.AIMING, State.SHOOTING, State.WHIPPING, State.ROLL_SHOOT, State.LASSO_THROW]:
if flash_timer and flash_timer.time_left > 0:
lassoThrow()
else:
print("whip")
state = State.WHIPPING
can_flip = false
anim_player.play("cowboyWhip")
speed = 0
whip_timer = Timer.new()
whip_timer.wait_time = 0.05
whip_timer.one_shot = true
whip_timer.connect("timeout", Callable(self, "_on_whip_timer_timeout"))
add_child(whip_timer)
whip_timer.start()
if whip_timer and whip_timer.time_left == 0:
print("TIMER UP")
pivot.rotation = arm_aim.angle()
whip_timer.queue_free()
whip_timer = null
state = State.WHIPPING
if anim_player.is_playing() == false and state == State.WHIPPING:
state = State.IDLE
speed = 75
func lassoThrow():
nearest_bullet = null
var nearest_distance = INF
for node in get_parent().get_children():
if node is Bullet:
var distance = global_position.distance_to(node.global_position)
if distance < nearest_distance:
nearest_distance = distance
nearest_bullet = node
if nearest_bullet:
state = State.LASSO_THROW
can_flip = false
speed = 0
anim_player.play("cowboyLassoWindup")
else:
print("no bullets found")
func bulletRedirect(body):
print("redirecting bullet")
redirect_aim = Input.get_vector("p1aimLeft", "p1aimRight", "p1aimUp", "p1aimDown").normalized()
print(redirect_aim, " | ", pivot.rotation)
var bullet = bullet.instantiate()
body.speed = 250
body.chargedBullet()
if redirect_aim.length() > 0:
body.rotation = redirect_aim.angle()
body.direction = redirect_aim.angle()
if rope:
rope.queue_free()
rope = null
func _on_animation_finished(animation_name: String):
if animation_name == "cowboyShoot":
state = State.IDLE
if state != State.SHOOTING:
print("not shooting")
elif animation_name == "cowboyWhip":
state = State.IDLE
speed = 75
if state != State.WHIPPING:
print("not whipping")
can_flip = true
elif animation_name == "cowboyLassoWindup":
if nearest_bullet and is_instance_valid(nearest_bullet):
print("nearest bullet at ", nearest_bullet.global_position)
anim_player.play("cowboyLassoThrow")
lasso_projectile = lasso.instantiate()
rope = Line2D.new()
rope.width = 1
rope.default_color = Color("#8e4d1e")
get_parent().add_child(rope)
lasso_projectile.cowboy_ref = self
lasso_projectile.target = nearest_bullet
lasso_projectile.l_position = lasso_spawn.global_position
if sprite.flip_h:
lasso_projectile.l_rotation = pivot.rotation + PI
lasso_projectile.direction = pivot.rotation + PI
else:
lasso_projectile.l_rotation = pivot.rotation
lasso_projectile.direction = pivot.rotation
get_parent().add_child(lasso_projectile)
else:
print("bullet despawned before lasso could finish")
print("no bullets found")
elif animation_name == "cowboyLassoThrow":
can_flip = true
speed = 75
state = State.IDLE