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()