Throw and recall not working as expected 4.3, help T-T

Godot Version

Godot 4.3

Question

So super newbie her but i have made some basic stuff for a first person project, the character controller is done and even added a melee weapon, the only problem is i want to add a throw and recall function for the weapon which i have somewhat succeeded in but there a catch, in my code when i throw the weapon, it is influenced by the camera motion and makes it unbearable to see, easy solution - top level. it works but now the dagger just isn’t going the way i want it to in different directions(It tilts whenever thrown in a new direction except for the one it starts in T_T) and i have no clue how to deal with this now

the weapon in the player scene is a child of the camera and sorry if the code is just bad and messy

extends CharacterBody3D

@onready var anim_player = $AnimationPlayer
@onready var hitbox = $Dagger/WeaponHit  

var is_attacking = false
var is_thrown = false
var is_recalling = false
var throw_speed = 20.0
var recall_speed = 30.0
var throw_direction: Vector3
var player_position: Vector3  

func _ready():
	hitbox.monitoring = false  
	hitbox.connect("body_entered", Callable(self, "_on_weapon_hit_body_entered"))

func _physics_process(delta):
	player_position = get_parent().global_transform.origin  

	if Input.is_action_just_pressed("Attack_1") and not is_thrown:
		attack()
	
	if Input.is_action_just_pressed("Dagger_throw") and not is_thrown:
		throw_dagger()
		
	if Input.is_action_just_pressed("Dagger_recall") and is_thrown:
		recall_dagger()

	if is_thrown:
		global_transform.origin += throw_direction * throw_speed * delta

	if is_recalling:
		recall_to_player(delta)

func attack():
	if not is_attacking and not is_thrown:
		is_attacking = true
		anim_player.play("Attack")
		hitbox.monitoring = true  

func throw_dagger():
	is_thrown = true
	is_attacking = false
	hitbox.monitoring = true
	var player_transform = get_parent().global_transform
	throw_direction = -player_transform.basis.z.normalized()
	global_transform.origin = player_transform.origin
	global_transform.basis = player_transform.basis
	anim_player.play("thrown")
	


func recall_dagger():
	is_recalling = true
	top_level = false
	is_thrown = false
	hitbox.monitoring = true  

func recall_to_player(delta):
	var to_player = player_position - global_transform.origin  
	if to_player.length() > 0.5:
		# Move dagger back to player
		global_transform.origin += to_player.normalized() * recall_speed * delta
	else:
		
		anim_player.play("Idle")
		is_recalling = false
		reset_to_player()

func reset_to_player():
	global_transform.origin = player_position
	global_transform.basis = get_parent().global_transform.basis  
	anim_player.play("Idle")  #
	hitbox.monitoring = false
	is_attacking = false

func _on_weapon_hit_body_entered(body: Node3D) -> void:
	if body.is_in_group("Enemies"):
		if is_thrown or is_attacking:
			print("Enemy hit with dagger")
			body._take_damage(25)  #damage

func _on_animation_player_animation_finished(anim_name: StringName) -> void:
	if anim_name == "Attack":
		anim_player.play("Idle")  
		hitbox.monitoring = false  
		is_attacking = false

Doesn’t seem like you are setting top_level anywhere, maybe it’s part of the animation? I believe you will have to use a Tween instead of an animation to effectively use top_level with this knife, since you do not know the knife’s end point until the player hits “throw”.

1 Like

I tried to use tween but didn’t really get it, for some reason the dagger never even moved or left it’s position but then i did a big brain move, which was if the animation plays correctly to the end and then apply top_level after 0.1 seconds, it just somehow magically works but thank will look more into tween

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.