Godot Version
4.2.2.stable.mono
Question
` Hey everyone, I tried to create a buy system for my multiplayer game. I created a buy_screen and instantiate it to Player scene. buy_screen has this script ;
extends Control
var weapon_cost
var weapon_id
var player
func _enter_tree():
player = get_parent()
func _on_glock_button_pressed() -> void:
weapon_cost = 800
weapon_id = 1
rpc("purchase",weapon_id,weapon_cost)
@rpc("any_peer","call_local")
func purchase(weapon_id,weapon_cost):
player.request_purchase(weapon_id,weapon_cost)
and my Player scene has this script ;
extends CharacterBody3D
class_name Player
@onready var camera: Camera3D = $Camera3D
@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var ray_cast_3d: RayCast3D = $Camera3D/RayCast3D
@onready var weapon_handler: Node3D = $Camera3D/WeaponHandler
@onready var buy_screen: Control = $BuyScreen
@export var health = 100
@export var team = 1
@export var money = 80000
var is_alive = true
var is_buy_screen_open = false
var primary_weapon: PackedScene
const SPEED = 10.0
const JUMP_VELOCITY = 10.0
var gravity: float = 20.0
func _enter_tree():
set_multiplayer_authority(str(name).to_int())
func _ready() -> void:
if not is_multiplayer_authority(): return
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
camera.current = true
func _input(event: InputEvent) -> void:
pass
func _unhandled_input(event: InputEvent) -> void:
if not is_multiplayer_authority(): return
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * .005)
camera.rotate_x(-event.relative.y * .005)
camera.rotation.x = clamp(camera.rotation.x, -PI/2, PI/2)
if event.is_action_pressed("Buy"):
toggle_buy_screen()
func _physics_process(delta: float) -> void:
if not is_multiplayer_authority(): return
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
var input_dir := Input.get_vector("Left", "Right", "Forward", "Backward")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
@rpc("any_peer")
func request_purchase(weapon_id, weapon_cost):
if multiplayer.is_server():
server_purchase_weapon(weapon_id, weapon_cost)
else:
rpc_id(1, "server_purchase_weapon", weapon_id, weapon_cost)
@rpc("any_peer")
func take_damage(damage: int) -> void:
health -= damage
if health <= 0:
position = Vector3(-1.195,0,0)
@rpc("any_peer", "reliable")
func server_purchase_weapon(weapon_id, weapon_cost):
if money >= weapon_cost:
money -= weapon_cost
weapon_id = weapon_id
rpc("client_update_weapon", get_multiplayer_authority(),weapon_id)
@rpc("any_peer", "reliable")
func client_update_weapon(player_id,weapon_id):
if get_multiplayer_authority() == player_id:
update_weapon(weapon_id)
else:
pass
func update_weapon(weapon_id):
#if not is_multiplayer_authority(): return
var weapon_scene: PackedScene
match weapon_id:
1:
weapon_scene = preload("res://Weapons/glock.tscn")
if weapon_scene:
var weapon = weapon_scene.instantiate()
weapon_handler.add_child(weapon)
func toggle_buy_screen():
is_buy_screen_open = !is_buy_screen_open
buy_screen.visible = is_buy_screen_open
set_process_input(not is_buy_screen_open)
set_physics_process(not is_buy_screen_open)
if is_buy_screen_open:
buy_screen.set_focus_mode(Control.FOCUS_ALL)
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
get_viewport().set_input_as_handled()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
Problem is when host tries to buy weapon, visually there is no weapon. Client can buy weapon and its visible. But if host press shoot button both client and host shoots. Client can’t shoot. This is my weapon script ;
extends Node3D
@export var fire_rate := 14.0
@export var recoil := 0.05
@export var weapon_mesh : Node3D
@export var weapon_damage := 15
@export var muzzle_flash: GPUParticles3D
@export var sparks: PackedScene
@export var automatic: bool
@onready var cooldown_timer: Timer = $CooldownTimer
@onready var weapon_position: Vector3 = weapon_mesh.position
@onready var ray_cast_3d: RayCast3D = $RayCast3D
func _process(delta: float) -> void:
if not is_multiplayer_authority(): return
if automatic:
if Input.is_action_pressed("Shoot"):
if cooldown_timer.is_stopped():
shoot()
else:
if Input.is_action_just_pressed("Shoot"):
if cooldown_timer.is_stopped():
shoot()
weapon_mesh.position = weapon_mesh.position.lerp(weapon_position, delta * 10.0)
func shoot() -> void:
cooldown_timer.start(1.0 / fire_rate)
weapon_mesh.position.z += recoil
play_visual_effects(ray_cast_3d.get_collision_point())
if ray_cast_3d.is_colliding():
var collider = ray_cast_3d.get_collider()
if collider is Player and collider != null:
var authority = collider.get_multiplayer_authority()
collider.rpc_id(authority, "take_damage", weapon_damage)
else:
print("invalid")
rpc("play_visual_effects", ray_cast_3d.get_collision_point())
@rpc("call_remote")
func play_visual_effects(collison_point: Vector3) -> void:
muzzle_flash.restart()
var spark = sparks.instantiate()
add_child(spark)
spark.global_position = collison_point
Can anyone help?
`