Just track the score in the level script, or a separate script, rather than the player script.
For instance, make a dictionary in the scorekeeper script.
something like var PlayerScores:Dictionary
And it’s structure will be an identifier for the player as the key (player name would work, a reference to the player’s node would also work, you have your pick of it really) followed by their score as the key.
The score doesn’t just have to be an int either, it can be an array (so for example if you want to have something like kills/deaths/assists, you could just make it an array of 3 numbers, and fetch those values from these numbers whenever you wish to display them)
There are many ways you could keep the score, but the most correct way would be to use a signal, but here is a lazy way:
in your scorekeeper node you must have this:
var PlayerScores:Dictionary
Then in your player, you have this:
func _ready() -> void:
$"../ScoreKeeper".PlayerScores[name] = 0 #Create or reset a dictionary entry for this player on spawn
func damage_receieved(Source: String) -> void:
player_death(Source) # Source in this case is the name of the player that harmed this player. Ideally received from a signal.
func player_death(Killer: String) -> void:
$"../ScoreKeeper".PlayerScores[name] += 1 # Add score to the player that killed this player before destroying this player
queue_free() # Destroy player
$“…/ScoreKeeper” is a reference to the scorekeeper node containing the scorekeeping script. It could also potentially be get_parent()
if all players are child to the node that keeps the score.
Direct referencing like this is not recommended (it can weigh down your code in the long run) which is why I recommend you learn how to create and use custom signals instead.