Godot Version
v.4.3.stable
Question
I’m working on a multiplayer battle royale-style game, where Player A can deal damage to Player B. When this happens, Player B should get killed and then respawn at a random location after 10 seconds. However, my code isn’t behaving as expected.
The issue is that when Player A inflicts damage on Player B, Player A (the attacker) gets killed and respawns instead. Additionally, the 10-second respawn timer only works the first time. After that, players don’t respawn at all.
I’ve been stuck on this problem for a while, and no matter what changes I make, the result is always the same. I need help identifying what’s going wrong and how to fix it. Here’s my current player code:
extends CharacterBody2D
@export var speed: int
@onready var camera = $Camera2D as Camera2D
var mafia: bool = false
var respawning: bool
var dead: boolTexture identifier mapping
var texture_map = {
“green”: “res://characters/green_character.png”,
“purple”: “res://characters/purple_character.png”,
“red”: “res://characters/red_character.png”,
“yellow”: “res://characters/yellow_character.png”
}var item = [“axe”, “arrow”, “dagger”, “pole”]
Synchronization variables
var syncPos: Vector2
var syncRot = 0
var syncWeaponRot = 0
var syncTextureID: String # Texture identifier (instead of full texture path)
var syncWeaponID: String # Weapon Identifier
var syncVisibility: bool
var syncDisableCollision: bool
var syncName: String
var syncArrowPos: Vector2
var syncArrowState: bool
var syncDaggerRot = 0
var arrow_scene: PackedScene
var arrow_projectile@onready var arrow = $Arrow
@onready var axe = $Axe
@onready var pole = $Pole
@onready var sword = $Sword
@onready var dagger = $DaggerRandomly select skin and weapon
var skin = [“green”, “purple”, “red”, “yellow”][randi_range(0, 3)]
var weapon = ‘dagger’ #item[randi_range(0, item.size() - 1)]var loaded_bow
var empty_bow
var loaded: bool
var can_shoot: boolfunc _ready():
Initializes the player with a randomly selected texture and weapon.
arrow.visible = false axe.visible = false pole.visible = false sword.visible = false dagger.visible = false respawning = false GlobalScript.dead = false $CanvasLayer.visible = false
Assign the multiplayer authority
$MultiplayerSynchronizer.set_multiplayer_authority(str(name).to_int()) for i in GameManager.Players: if i == multiplayer.get_unique_id(): syncName = GameManager.Players[i].name if weapon in item: syncWeaponID = weapon
Assign texture and syncTextureID
if skin in texture_map: syncTextureID = skin # Store texture identifier (e.g., "green") $Body.texture = load(texture_map[skin]) # Load texture using the identifier
Initialize weapon visibility and textures
if weapon == "arrow": arrow.visible = true loaded = true can_shoot = true arrow_scene = load("res://arrow.tscn") loaded_bow = load("res://items/weapon_bow_arrow.png") empty_bow = load("res://items/weapon_bow.png") $Arrow/Weapon.texture = loaded_bow $"Arrow/Left Hand".texture = load("res://characters/"+skin+"_hand.png") $"Arrow/Right Hand".texture = load("res://characters/"+skin+"_hand.png") elif weapon == "pole": pole.visible = true $"Pole/Left Hand".texture = load("res://characters/"+skin+"_hand.png") $"Pole/Right Hand".texture = load("res://characters/"+skin+"_hand.png") elif weapon == "dagger": dagger.visible = true $"Dagger/Left Hand".texture = load("res://characters/"+skin+"_hand.png") $"Dagger/Right Hand".texture = load("res://characters/"+skin+"_hand.png") elif weapon == "axe": axe.visible = true $"Axe/Left Hand".texture = load("res://characters/"+skin+"_hand.png") $"Axe/Right Hand".texture = load("res://characters/"+skin+"_hand.png")
func launch_arrow():
if !loaded:
$Arrow/Weapon.texture = empty_bow
can_shoot = false
arrow_projectile = arrow_scene.instantiate()
$Arrow.add_child(arrow_projectile)
arrow_projectile.global_position = $Arrow/Marker2D.global_position
syncArrowPos = arrow_projectile.global_position
$WeaponTimer.start(0.25)func is_dead():
GlobalScript.Player_target = ‘’
GlobalScript.respawn_counter = 10
GlobalScript.dead = truefunc respawn():
respawning = trueif GlobalScript.dead and GlobalScript.respawn_counter > 0: $RespawnTimer.start() else: $RespawnTimer.stop() var spawn_nodes_count = get_tree().get_node_count_in_group("PlayerSpawn") for pos in get_tree().get_nodes_in_group("PlayerSpawn"): var picker = randi_range(0, (spawn_nodes_count - 1)) if pos.name == str(picker): global_position = pos.global_position GlobalScript.dead = false break
func _physics_process(delta):
print(GlobalScript.dead)Handles movement, rotation, and synchronization.
if $MultiplayerSynchronizer.get_multiplayer_authority() == multiplayer.get_unique_id(): camera.make_current() $MarginContainer/Name.text = 'You' if GlobalScript.dead: syncVisibility = false $CollisionShape2D.disabled = true syncDisableCollision = true $CanvasLayer.visible = true if !respawning: respawn() elif !GlobalScript.dead: $CanvasLayer.visible = false syncVisibility = true $CollisionShape2D.disabled = false syncDisableCollision = false syncArrowState = loaded if loaded: $Arrow/Weapon.texture = loaded_bow var direction = Input.get_vector("left", "right", "up", "down") velocity = direction * speed if velocity.length() > 0: velocity = velocity.normalized() * speed position += velocity * delta self.look_at(Vector2(get_global_mouse_position())) syncRot = rotation_degrees move_and_slide() if Input.is_action_just_pressed("attack"): if weapon == "arrow": if can_shoot: loaded = false launch_arrow() else: self.visible = syncVisibility $CollisionShape2D.disabled = syncDisableCollision if syncName != '' and syncName != ' ': $MarginContainer/Name.text = syncName else: $MarginContainer/Name.text = "Dick Head" rotation_degrees = lerpf(rotation_degrees, syncRot, 1) arrow.visible = false axe.visible = false pole.visible = false sword.visible = false dagger.visible = false if syncTextureID in texture_map: $Body.texture = load(texture_map[syncTextureID]) if syncWeaponID in item: weapon = syncWeaponID if weapon == "arrow": arrow.visible = true loaded_bow = load("res://items/weapon_bow_arrow.png") empty_bow = load("res://items/weapon_bow.png") loaded = syncArrowState if loaded: $Arrow/Weapon.texture = loaded_bow else: $Arrow/Weapon.texture = empty_bow $"Arrow/Left Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") $"Arrow/Right Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") elif weapon == "pole": pole.visible = true $"Pole/Left Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") $"Pole/Right Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") elif weapon == "dagger": dagger.visible = true $"Dagger/Left Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") $"Dagger/Right Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") $Dagger/dagger.rotation_degrees = lerpf(rotation_degrees, syncDaggerRot, .8) elif weapon == "axe": axe.visible = true $"Axe/Left Hand".texture = load("res://characters/"+syncTextureID+"_hand.png") $"Axe/Right Hand".texture = load("res://characters/"+syncTextureID+"_hand.png")
func _on_weapon_timer_timeout() → void:
if !dead and weapon == “arrow”:
can_shoot = true
loaded = truefunc _on_respawn_timer_timeout():
if GlobalScript.respawn_counter != 0:
$CanvasLayer/RespawnTimerNotification.text = 'Time to respawn: ’ + str(GlobalScript.respawn_counter) + ‘s’
GlobalScript.respawn_counter -= 1
else:
respawn()