Error in hitscan_weapon script with ammo_handler

So when I follow this lecture and get to use the functions of the ammo_handler in the shoot() function of hitscan_weapon I get this error:

“Cannot call non-static function “has_ammo()” on the class “AmmoHandler” directly. Make an instance instead.”

I fixed it by replacing this:
@export var ammo_handler = AmmoHandler

with this:
@export var ammo_handler = AmmoHandler.new()

And it seems to be working fine also when I test the game. I am wondering what I am missing. I am in the same Godot Version (4.1.1.stable) as in the lecture and there seems to be no error like this.

Here is my code for the AmmoHandler:

extends Node3D
class_name AmmoHandler

enum ammo_type {
	BULLET,
	SMALL_BULLET
}

var ammo_storage := {
	ammo_type.BULLET: 20,
	ammo_type.SMALL_BULLET: 60
	}

func has_ammo(type: ammo_type) -> bool:
	return ammo_storage[type] > 0

func use_ammo (type: ammo_type) -> void:
	if has_ammo(type):
		ammo_storage[type] -= 1
	print(ammo_storage[type])

And here the hitscan_weapon script:

extends Node3D

@export var fire_rate := 3.0
@export var recoil := 0.08
@export var weapon_damage := 10
@export var automatic: bool
@export var ammo_type: AmmoHandler.ammo_type

@export var weapon_mesh: Node3D
@export var muzzle_flash: GPUParticles3D
@export var sparks: PackedScene
@export var ammo_handler = AmmoHandler.new()

@onready var cooldown_timer: Timer = $CooldownTimer
@onready var ray_cast_3d: RayCast3D = $RayCast3D
@onready var weapon_position: Vector3 = weapon_mesh.position

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	if automatic:
		if Input.is_action_pressed("fire"):
			if cooldown_timer.is_stopped():
				shoot()
	else:
		if Input.is_action_just_pressed("fire"):
			if cooldown_timer.is_stopped():
				shoot()
	#reset recoil smoothly with lerp
	weapon_mesh.position = weapon_mesh.position.lerp(weapon_position, delta * 10.0)

func shoot () -> void:
	#check if player has ammo
	if ammo_handler.has_ammo(ammo_type):
		ammo_handler.use_ammo(ammo_type)
		#start weapon cooldown
		cooldown_timer.start(1.0 / fire_rate)
		#emit muzzle flash
		muzzle_flash.restart() #restart to be sure that the particles are emitted everytime
		
		#check what was shot
		var collider = ray_cast_3d.get_collider()
		printt("weapon fired",collider)
		if collider is Enemy:
			collider.hitpoints -= weapon_damage
		
		#recoil
		weapon_mesh.position.z += recoil
		
		#particles at hit point
		if ray_cast_3d.is_colliding():
			var spark = sparks.instantiate()
			add_child(spark)
			spark.global_position = ray_cast_3d.get_collision_point()

Hi Hugison,

I think one of the problems may be that you are using a Node3D for the AmmoHandler so you would need to right click the node in the scene tree and click change type and change it to a normal Node.
Once you have done this change the AmmoHandler.gd script to extend from the Node not Node3D.

You should find if you revert back to the @export var ammo_handler = AmmoHandler then it should work as intended.

Hope this helps

Thanks for the Reply Marc.

I changed it and got the same error. But I found what was really causing it.
I typed

@export var ammo_handler = AmmoHandler

instead of

@export var ammo_handler: AmmoHandler

Thia caused the error and everything makes sense now.

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

Privacy & Terms