Assistance with Basic Weapon System

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By PyWhacket27

Hi all,

Newb here. I’m working on a 2D twin-stick shooter, similar to Metal Slug. I’m getting a little stuck on how to setup the weapon system I want, which is; the player has a base gun of a Pistol (Node2D0, but if they walk over a pickup (let’s say Assault Rifle (Area2D)), then the Pistol is removed for 30 seconds, and the Assault Rifle is added for 30 seconds. Once the 30 seconds are up, the Assault Rifle is then removed, and the Pistol is back in the player’s hand.

So far, I have a WeaponManager scene (Node2D) which will be Instanced on the Player scene with the following code:

var pistol := preload("res://pickups/weapons/pistol/Pistol.tscn") 
var assault_rifle := preload("res://pickups/weapons/assault_rifle/Assault_Rifle.tscn") 
var shotgun := preload("res://pickups/weapons/shotgun/Shotgun.tscn") 
var uzi := preload("res://pickups/weapons/uzi/Uzi.tscn")

func _ready() -> void: 	
current_weapon() 	    

func current_weapon(): 	
var current_weapon = pistol.instance() 	
add_child(current_weapon)

On the AssaultRifle (Area2D) scene, I have the following code:

var gun_name := "Assault_Rifle"
export (float, 0.0, 360.0, 1.0) var gun_accuracy := 9.0
export (float, 100.0, 2000.0, 1.0) var max_bullet_speed := 1400.0
export var damage := 25

onready var bullet := preload("res://pickups/weapons/Bullet.tscn")
var can_fire := true

func _physics_process(delta: float) -> void:
	look_at(get_global_mouse_position())
	if Input.is_action_pressed("shoot") and can_fire:
		_shoot()

func _shoot():
		var bullet_instance = bullet.instance()
		get_parent().add_child(bullet_instance)
		bullet_instance.rotation = rotation
		bullet_instance.speed = max_bullet_speed
		bullet_instance.randomize_rotation(deg2rad(gun_accuracy))
		bullet_instance.global_position = $Muzzle.global_position
		can_fire = false
		yield(get_tree().create_timer(0.2), "timeout")
		can_fire = true

func _on_Assault_Rifle_body_entered(body: Node) -> void:
	if body.is_in_group("players"):
		if body.has_method("current_weapon"):
			body.current_weapon()
		queue_free()

I know I need to remove the Pistol on the WeaponManager scene, but can’t seem to figure out how to accomplish what I mentioned above.

Any direction or tips would be greatly appreciated.

:bust_in_silhouette: Reply From: zhyrin

The pickup part:
You character is most likely a physics body, like a KinematicBody2D right? Well, the player needs to detect when they reached a new gun. If the pickup in the world doens’t need physics interactions (other than with the player), you could make a pickup that is an Area2D, it would store what kind of weapon this pickup can give, and Area2D can detect if a physics body enters it.

  • When the pickup detect the player, it would try to call something like pickup_weapon(<weapon_type>) on the player, if successful, the pickup deletes itself.

How you switch weapons could look like this:
How do you determine what is the active weapon? Just by what is a children of WeaponManager?
If that is the case, I would add a new variable to WeaponManager to store the pistol while it’s inactive (like var holstered_pistol: Pistol = null)

  • When you pick up a new gun, you remove the pistol child, and assign it to the variable to hold it while it’s not in use.
  • You add a new child, the type of weapon you picked up
  • You start a 30 second Timer
  • Once time runs out, you delete the currently used weapon, and put back the unused pistol as a child