Reloading for shotguns

Godot Version

4.4

Question

Hello!
I am completely new to making video games and trying to make a top down survival shooter. My problem is that I can’t seem to figure out logic for shotgun reloading and hoping someone can give me a hint.

The way how I’m trying to do this now:

  • check how many bullets missing from current mag
  • create a timer that will not allow to shoot while animation for reloading is playing

That works fine if I let full reload to complete, but I want to have an ability to interrupt reload in between each shell and allow to resume shooting with proper timer + animation and amount of shell in the magazine.

Thanks in advanced!

@onready var body: AnimatedSprite2D = $body

@onready var _ammo: int = 32 # total ammo available
@onready var _magazine_capacity: int = 8 # total ammo in a magazine
var _current_magazine: int = 0 # ammo in current mag
var _have_ammo: bool = false # does the player have ammo?
var _not_reloading: bool = true # waiting for reloading timer?
@onready var reload_delay: Timer = $reload_delay # timer that tracks reload of 1 bullet

func _ready():
	body.play("idle")
	_have_ammo = true
	_current_magazine = _magazine_capacity

func _process(_delta):

	if Input.is_action_just_pressed("shoot"):
		print("somehow interrupt animation")

func shoot():
	if is_ready_to_fire:
		if _not_reloading:
			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 local_raycast.is_colliding() and local_raycast.get_collider().has_method("kill"):
					local_raycast.get_collider().kill()

				if _current_magazine < 1: # if we've used the last bullet, reload.
					reload()
			else:
				print("out of ammo")
		else:
			print("reloading")

func reload() -> void:
	var missing_ammo = 8 - _current_magazine
	for bullet in missing_ammo:
		if _ammo > 0:
			reload_delay.set_wait_time(missing_ammo * 1.1)
			reload_delay.start()
			print("Ammo in clip:", _current_magazine)
			_have_ammo = true # we still have ammo
			_ammo -= 1 # but we have 1 less magazine
			_current_magazine += 1
			print("Reload - Ammo total left ",  _ammo)
			print("Reload - Current mag ",  _current_magazine)
			body.play("reload")
			_not_reloading = false
		else:
			_have_ammo = false # no more ammo

func _on_reload_delay_timeout() -> void:
	_not_reloading = true
	body.play("idle")

Hi!

Hope I understand the question correctly, let me know if not.
A way you can do that is by detecting that you need to stop reloading, stop the timer, and check how many shells you should have reloaded based on the timer progress.

For instance, let’s say you want to reload 8 shells in total, and the total reload time is 2 seconds:

  • You let the reloading run for 0.6 seconds.
  • You press the input to cancel the reloading.
  • Since the timer ran for 0.6s, and the total is 2s, by doing 0.6 / 2, you get 0.3, which means you interrupted the reload at 30% of its progress (30 = 0.3 * 100).
  • You can then multiply this percentage by the maximum number of reloaded shells, here 8, so 8 * 0.3, which will give you 2.4. Since it’s not a round number, you’ll have to round, as reloading 2.4 shells does not make sense. Let say you round to the nearest round number, here 2, that would mean you have to reload 2 shells.

By doing so, you can re-use the same code as when the reload ends naturally, so that any animation/sound/etc. will work the same way, you just trigger the reload end manually and changes the reloaded value.

Feel free to ask if you need more info/explanations!

1 Like

Hi!
Thanks a lot for your answer.
I didn’t think of it this way and this helps a lot!

Still figuring out the specifics but I know where to go from here
Thanks!

1 Like

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