0 votes

Hey there. So I’ve been searching and haven’t found a great answer for this questions.
Let’s say that in my game my character has 200 of total ammo which are divided in 10 rounds of 20 bullets, so if you shoot 20 times, you need to reload, and now you would have 9 rounds left.
How could I implement something like reloading having in mind the previous values?
Also, if I change the maximum limit of bullets in a round, let’s suppose that now it’s 9, then we could have an error, because the total amount of bullets is pair, while the limit of bullets in a round isn’t . How would you fix this?

in Engine by (97 points)

Hi,
You've used the word rounds, when I think you mean magazines. As a round usually refers to a bullet.
For example, an AK-47, the standard magazine capacity is 30 rounds.

If I'm correct with that, could you re-write this line: Also, if I change the maximum limit of bullets in a round, let’s suppose that now it’s 9, then we could have an error, because the total amount of bullets is pair, while the limit of bullets in a round isn’t .
I don't quite understand it.

1 Answer

0 votes
Best answer

Hi,
I know you haven't answered my question yet, but a simple ammo script could work like this:

extends Node2D

export var _magazines: int = 10 # how many magazines does the player have
export var _magazine_capacity: int = 20 # how many bullets in a magazine
var _current_magazine: int = 0 # track the bullets in the loaded magazine
var _have_ammo: bool = false # does the player have ammo?

func _ready() -> void:
    _reload() # load the gun for the first time


func _unhandled_input(event):
    # check for mouse down and shoot
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT:
            if event.pressed:
                _shoot()


func _shoot() -> void:
    if _have_ammo: # only shoot if we have ammo
        _current_magazine -= 1 # take a bullet out of the magazine
        print("Bang!  Ammo left: ", _current_magazine)
        if _current_magazine < 1: # if we've used the last bullet, reload.
            _reload()
    else:
        print("out of ammo")


func _reload() -> void:
    if _magazines > 0: # if there are any magazines left, reload
        _have_ammo = true # we still have ammo
        _magazines -= 1 # but we have 1 less magazine
        _current_magazine = _magazine_capacity # reload the current magazine
        print("Reload - Magazines left ",  _magazines)
    else:
        _have_ammo = false # no more ammo
by (2,015 points)
selected by

Hi! Im trying to add a timer to have like a cooldown to shoot before reloading. I dont find any place to use it whitout making reload impossible. I know that your post is ol, I will still apreciate help! Ty

Hi,
I haven't done any Godot for a while. I'm back now though on Godot 4.
Looking at the code I did, I went a bit overboard on underscores before variable names, as I thought that was best, as it makes them private. Now I'm not so sure.

Anyway, you need a bool to say if you can shoot or not. That needs to go in the shoot function. Set the bool so the player can't shoot, and start the timer. When the timer runs out, set the bool so the player can shoot.

Like this (the timer is called shoot_delay:

extends Node2D

export var magazines: int = 4 # how many magazines does the player have
export var magazine_capacity: int = 4 # how many bullets in a magazine
var current_magazine: int = 0 # track the bullets in the loaded magazine
var have_ammo: bool = false # does the player have ammo?
var can_shoot: bool = true # can the player shoot

func _ready() -> void:
    reload() # load the gun for the first time


func _unhandled_input(event):
    # check for mouse down and shoot
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT:
            if event.pressed:
                shoot()


func shoot() -> void:
    if have_ammo and can_shoot: # only shoot if we have ammo
        current_magazine -= 1 # take a bullet out of the magazine
        print("Bang!  Ammo left: ", current_magazine)
        can_shoot = false # don't let the player shoot until the timer runs out
        $"shoot_delay".start() # start the timer
        if current_magazine < 1: # if we've used the last bullet, reload.
            reload()
    else:
        if !have_ammo:
            print("out of ammo")
        elif !can_shoot:
            print("Waiting to shoot")


func reload() -> void:
    if magazines > 0: # if there are any magazines left, reload
        have_ammo = true # we still have ammo
        can_shoot = true # must be able to shoot after reloading
        magazines -= 1 # but we have 1 less magazine
        current_magazine = magazine_capacity # reload the current magazine
        print("Reload - Magazines left ",  magazines)
    else:
        have_ammo = false # no more ammo


func _on_shoot_delay_timeout() -> void:
    can_shoot = true

thanks mate, ill first try to make my code cleaner

extends KinematicBody

var damage = 10
const MAX_CAM_SHAKE = 0.3

export var _magazines: int = 3 # how many magazines does the player have
export var _magazine_capacity: int = 25 # how many bullets in a magazine
var _current_magazine: int = 15 # track the bullets in the loaded magazine
var _have_ammo: bool = true # does the player have ammo?

var speed = 10
var h_acceleration = 6
var air_acceleration = 1
var normal_acceleration = 6
var gravity = 20
var jump = 10
var full_contact = false
var reloadxd = false

var mouse_sensitivity = 0.06

var direction = Vector3()
var h_velocity = Vector3()
var movement = Vector3()
var gravity_vec = Vector3()

onready var head = $Head
onready var ground_check = $GroundCheck
onready var anim_player = $AnimationPlayer
onready var camera = $Head/Camera
onready var raycast = $Head/Camera/RayCast
onready var timer = $Timer
onready var timer2 = $Timer2

func _process(delta):
    $Control/RichTextLabel.text = str(_current_magazine)
    $Control/RichTextLabel2.text = str(_magazines)

func _ready() -> void:
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
    _reload()

func _reload() -> void:
    if _magazines > 0: # if there are any magazines left, reload
        _have_ammo = true # we still have ammo
        _magazines -= 1 # but we have 1 less magazine
        _current_magazine = _magazine_capacity # reload the current magazine
        print("Reload - Magazines left ",  _magazines)
    else:
        _have_ammo = false # no more ammo

func _input(event):
    if event is InputEventMouseMotion:
        rotate_y(deg2rad(-event.relative.x * mouse_sensitivity))
        head.rotate_x(deg2rad(-event.relative.y * mouse_sensitivity))
        head.rotation.x = clamp(head.rotation.x, deg2rad(-89), deg2rad(89))

func fire():
    if Input.is_action_pressed("fire") and timer.is_stopped() and _have_ammo:
        if not anim_player.is_playing():
            camera.translation = lerp(camera.translation, 
                    Vector3(rand_range(MAX_CAM_SHAKE, -MAX_CAM_SHAKE), 
                    rand_range(MAX_CAM_SHAKE, -MAX_CAM_SHAKE), 0), 0.5)
            if raycast.is_colliding():
                var target = raycast.get_collider()
                if target.is_in_group("Enemy"):
                    target.health -= damage
                    anim_player.play("Assault Fire")
            if _have_ammo: # only shoot if we have ammo
                _current_magazine -= 1 # take a bullet out of the magazine
                print("Bang!  Ammo left: ", _current_magazine)
        if _current_magazine < 1: # if we've used the last bullet, reload.
            _reload()

            camera.translation = lerp(camera.translation, 
                    Vector3(rand_range(MAX_CAM_SHAKE, -MAX_CAM_SHAKE), 
                    rand_range(MAX_CAM_SHAKE, -MAX_CAM_SHAKE), 0), 0.5)
            if raycast.is_colliding():
                var target = raycast.get_collider()
                if target.is_in_group("Enemy"):
                    target.health -= damage
        anim_player.play("Assault Fire")

    else:
        camera.translation = Vector3()
        anim_player.stop()

func _physics_process(delta):

    fire()

    direction = Vector3()

    full_contact = ground_check.is_colliding()

    if not is_on_floor():
        gravity_vec += Vector3.DOWN * gravity * delta
        h_acceleration = air_acceleration
    elif is_on_floor() and full_contact:
        gravity_vec = -get_floor_normal() * gravity
        h_acceleration = normal_acceleration
    else:
        gravity_vec = -get_floor_normal()
        h_acceleration = normal_acceleration

    if Input.is_action_just_pressed("jump") and (is_on_floor() or ground_check.is_colliding()):
        gravity_vec = Vector3.UP * jump

    if Input.is_action_pressed("move_forward"):
        direction -= transform.basis.z
    elif Input.is_action_pressed("move_backward"):
        direction += transform.basis.z
    if Input.is_action_pressed("move_left"):
        direction -= transform.basis.x
    elif Input.is_action_pressed("move_right"):
        direction += transform.basis.x

    direction = direction.normalized()
    h_velocity = h_velocity.linear_interpolate(direction * speed, h_acceleration * delta)
    movement.z = h_velocity.z + gravity_vec.z
    movement.x = h_velocity.x + gravity_vec.x
    movement.y = gravity_vec.y

    move_and_slide(movement, Vector3.UP)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.