How to check who killed people using ROBLOX's Endorsed Weapons?

I think the sword has an object value which you could use, other than that you’d have to implement it yourself.

It is for ROBLOX’s endorsed guns like the pistol

An easy way to do this is to add a tag to the player when a weapon hits them and then to read the tag when they die and award points. Obviously if a player is hit by multiple other players the last tag found will be applied.

To do this, in ServerScriptService add a script with the following:

local Players = game:GetService("Players")
Players.PlayerAdded:connect(function(player)
-- SETUP PLAYER STATS
	local folder = Instance.new("Folder", player)
	folder.Name = "leaderstats"
	local PlayerKills = Instance.new("IntValue", folder)
	PlayerKills.Name = "Kills"
-- ADD KILL :Connect function
	player.CharacterAdded:connect(function(Character) -- When they respawn (Get a new Character)
		local Humanoid = Character:WaitForChild("Humanoid") -- Find Humanoid
		Humanoid.Died:connect(function() -- Detects for when the Humanoid dies
			if Humanoid:FindFirstChild("creator") ~= nil then -- Checks for a Killed
				local player = Humanoid.creator.Value
				print(player, " killed", Humanoid)
-- Update Leaderstats				
				player.leaderstats.Kills.Value = player.leaderstats.Kills.Value + 1
			end
			-- For the Dead guy, you can do stuff to him here.
		end)
	end)
end)

Then you need to update the modulescript in ReplicatedStorage > WeaponsSystem > WeaponsSystem to add the required tags when the player gets hit.
First add a couple of new functions in this script:

--       ADD CREATOR TAGS FOR WEAPON HITS      --
--            NEEDED FOR LEADERSTATS             --

function TagHumanoid(humanoid, player)
--	print("Rscript: ", player, " tagged ", humanoid)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	Creator_Tag.Parent = humanoid
end

function UntagHumanoid(humanoid)
	for i, v in pairs(humanoid:GetChildren()) do
		if v:IsA("ObjectValue") and v.Name == "creator" then
			v:Destroy()
		end
	end
end

Then in the same modulescript find the WeaponsSystem.doDamage function and before the final 2 end statements in that function add:

		UntagHumanoid(target)
		TagHumanoid(target, dealer)

This will remove any previous tags from player hits so that the last shot awards the points.

The endorsed Roblox Weapons Kit is a great resource which my son has used extensively in his game [Insert Game Name Here] - Roblox and I have modified a little.

Let us know how you get on.

4 Likes

Can it work when theres an already existing leaderstats?

where you do the damage dealing do this

for ex:

if humanoid.Health - damage <= 0 then
  print(attacker.Name, 'Killed', target.Name)
end

if it doesn’t work try adding tonumber(humanoid.Health - damage)

where do you put this line of script?

read the thing that i said again

Is this correct?

	if not target or CollectionService:HasTag(target, "WeaponsSystemIgnore") then
		return
	end
	--if IsServer then
		if target:IsA("Humanoid") and dealer:IsA("Player") and dealer.Character then
			local dealerHumanoid = dealer.Character:FindFirstChildOfClass("Humanoid")
			local targetPlayer = Players:GetPlayerFromCharacter(target.Parent)
			if dealerHumanoid and target ~= dealerHumanoid and targetPlayer then
				-- Trigger the damage indicator
			WeaponData:FireClient(targetPlayer, "HitByOtherPlayer", dealer.Character.HumanoidRootPart.CFrame.Position)
			UntagHumanoid(target)
			TagHumanoid(target, dealer)
			if humanoid.Health - damage <= 0 then
				print(attacker.Name, 'Killed', target.Name)
			end
		end
		end

		-- NOTE:  damageData is a more or less free-form parameter that can be used for passing information from the code that is dealing damage about the cause.
		-- .The most obvious usage is extracting icons from the various weapon types (in which case a weapon instance would likely be passed in)
		-- ..The default weapons pass in that data
		local handler = _damageCallback or _defaultDamageCallback
		handler(WeaponsSystem, target, amount, damageType, dealer, hitInfo, damageData)
	--end
end

Use the soloution as help Detect Kill and Reward is not working

Your existing leaderstats will be created on a PlayerAdded:Connect event. Just add the KILL : Connect function inside that event handler and change the leaderstats objects to use yours.

Is this correct?

game.Players.PlayerAdded:connect(function(player)
	local folder = Instance.new("Folder", player)
	folder.Name = "leaderstats"
	
	local Cash = Instance.new("IntValue", folder)
	Cash.Name = "Cash"
	
	local Hunger = Instance.new("IntValue", folder)
	Hunger.Name = "Hunger"
	Hunger.Value = 100
	
	local Thirst = Instance.new("IntValue", folder)
	Thirst.Name = "Thirst"
	Thirst.Value = 100

	local PlayerKills = Instance.new("IntValue", folder)
	PlayerKills.Name = "Kills"
		-- ADD KILL :Connect function
		player.CharacterAdded:connect(function(Character) -- When they respawn (Get a new Character)
			local Humanoid = Character:WaitForChild("Humanoid") -- Find Humanoid
			Humanoid.Died:connect(function() -- Detects for when the Humanoid dies
				if Humanoid:FindFirstChild("creator") ~= nil then -- Checks for a Killed
					local player = Humanoid.creator.Value
					print(player, " killed", Humanoid)
					-- Update Leaderstats				
					player.leaderstats.Kills.Value = player.leaderstats.Kills.Value + 1
				end
				-- For the Dead guy, you can do stuff to him here.
			end)
	end)
end)

Yup. So now you can track Kills.

SO, how are you going to approach the next part “wanted level system for my upcoming game”?

Before I answer that question, may I ask do I put the “function TagHumanoid” on the very top? and may I know regarding the WeaponsSystem.doDamage function to see if this is correct?

	if not target or CollectionService:HasTag(target, "WeaponsSystemIgnore") then
		return
	end
	--if IsServer then
		if target:IsA("Humanoid") and dealer:IsA("Player") and dealer.Character then
			local dealerHumanoid = dealer.Character:FindFirstChildOfClass("Humanoid")
			local targetPlayer = Players:GetPlayerFromCharacter(target.Parent)
			if dealerHumanoid and target ~= dealerHumanoid and targetPlayer then
				-- Trigger the damage indicator
			WeaponData:FireClient(targetPlayer, "HitByOtherPlayer", dealer.Character.HumanoidRootPart.CFrame.Position)
		end
		UntagHumanoid(target)
		TagHumanoid(target, dealer)
		end

		-- NOTE:  damageData is a more or less free-form parameter that can be used for passing information from the code that is dealing damage about the cause.
		-- .The most obvious usage is extracting icons from the various weapon types (in which case a weapon instance would likely be passed in)
		-- ..The default weapons pass in that data
		local handler = _damageCallback or _defaultDamageCallback
		handler(WeaponsSystem, target, amount, damageType, dealer, hitInfo, damageData)
	--end
end```

I added the new TagHumanoid & UntagHumanoid functions after the variables are defined as I wasn’t sure where else I might be using it:

local _damageCallback = nil
local _getTeamCallback = nil
-- functions added below here...

My full equivalent WeaponsSystem.doDamage function is this currently:

function WeaponsSystem.doDamage(target, amount, damageType, dealer, hitInfo, damageData)
	if not target or ancestorHasTag(target, "WeaponsSystemIgnore") then
		return
	end
	if IsServer then
		if target:IsA("Humanoid") and dealer:IsA("Player") and dealer.Character then
			local dealerHumanoid = dealer.Character:FindFirstChildOfClass("Humanoid")
			local targetPlayer = Players:GetPlayerFromCharacter(target.Parent)
			if dealerHumanoid and target ~= dealerHumanoid and targetPlayer then
				-- Trigger the damage indicator
				WeaponData:FireClient(targetPlayer, "HitByOtherPlayer", dealer.Character.HumanoidRootPart.CFrame.Position)
			end
		end

		-- NOTE:  damageData is a more or less free-form parameter that can be used for passing information from the code that is dealing damage about the cause.
		-- .The most obvious usage is extracting icons from the various weapon types (in which case a weapon instance would likely be passed in)
		-- ..The default weapons pass in that data
		local handler = _damageCallback or _defaultDamageCallback
		handler(WeaponsSystem, target, amount, damageType, dealer, hitInfo, damageData)
		UntagHumanoid(target)
		TagHumanoid(target, dealer)
	end
end
1 Like

Also from what I have noticed in the script, there is another function with a similar name to the “TagHumanoid” you provided, does that have to do with anything? Or do I remove it

There is the getHumanoid function which checks to see what the weapon has hit and whether it has an associated HumanoidRootPart, which detects if you have hit a player or an NPC

Okay, sorry for the really late reply but I have one final question, how do I get the Humanoid’s player when they died, I’m thinking so that if a player kills that person with a bounty, they get their bounty.

I have a standard function I run to get Player from the Humanoid:

local function getPlayerFromName(name)
-- loop over all players:
	for _, player in pairs(game:GetService("Players"):GetPlayers()) do
-- if their name matches (case insensitive), return with that player:
		if player.Name:lower() == name:lower() then
			return player
		end
	end
	-- if we reach the end of the for-loop, no player with that name was found
end

-- if you have the Humanoid then you can call the function above using:
local player = getPlayerFromName(Humanoid.Parent.Name)


Alternatively, if you have the Character then we can use the following, which is a Roblox built-in API call:

local player = game.Players:GetPlayerFromCharacter(character)

I hope this helps. Which one you decide to use will be determined by how much information you have at the point at which you call it.

Hello everyone, this comes late and tbh is my first topic, let me start to say i’m not a expert neither a professional programmer but i like to play with code and this issue cross my mind when i started using weapon kit, for my bad luck i din’t saw this topic early so i changed the weponScript by my needs.

My goal on this is to show you all what i did so far and to know if i’m using the best approach/best practices!

Keep in mind i’m really new at roblox and still learning :sweat_smile:

So to start, the 1º thing i did was to add a new remote event in REMOTE_EVENT_NAMES and created list to keep track of players

local REMOTE_EVENT_NAMES = {
	"WeaponFired",
	"WeaponHit",
	"WeaponReloadRequest",
	"WeaponReloaded",
	"WeaponReloadCanceled",
	"WeaponActivated",
	"PlayerReborn" --<<<  
}

local current_players = {}

i added a function to lookup tables, cuz i don’t really know if there is a built-in on roblox or a best approach

local function in_table(tbl, item, field)
	--print(table)
	for i = 1, #tbl do
		if field and (tbl[i] and tbl[i][field] and tbl[i][field] == item) then
			return i
		elseif not field then
			if (tbl[i] == item) then
				return i
			end
		end
	end
	return -1
end

after on WeaponsSystem.setup() right after if IsServer then , i added a listener each time a player enters the game and assign some properties

...
if IsServer then
		-- build player record
		Players.PlayerAdded:Connect(function()
			for _, player in ipairs(Players:GetPlayers()) do
				local player_i = in_table(current_players, player.name, "name")
				if player_i < 0 then
					current_players[#current_players + 1] = {
						name = player.name,
						dead = false,
						total_dead = 0,
						total_kill = 0,
						last_dealer = nil,
					}
				end

			end
		end)
        ...

then on WeaponsSystem.onCharacterAdded() (i petty sure this runs at client side, correct me if i’m wrong) i call event “PlayerReborn” on server side like this

function WeaponsSystem.onCharacterAdded(character)
   	WeaponsSystem.getRemoteEvent("PlayerReborn"):FireServer(character)

now i added more 2 function to be acceded trough weapon system module, just after _defaultDamageCallback(), i think both function are self explanatory :slightly_smiling_face:

-- set player dead status
function WeaponsSystem.setPlayerDead(player_name, dead)
	local player_i = in_table(current_players, player_name, "name")
	if player_i > 0 then
		current_players[player_i].dead = dead
	end
	return player_i
end
-- get player dead
function WeaponsSystem.playerIsDead(player_name)
	local player_i = in_table(current_players, player_name, "name")
	if player_i > 0 then
		return current_players[player_i].dead
	end
	return false
end

The main function to handle player dead, added after WeaponsSystem.playerIsDead()

local function updateOnPlayerDie(target, dealer, hitInfo)
	-- only server side
	if IsServer then
		-- only humanoid hit's, exclude parts, etc 
		if target:IsA("Humanoid") then
			local humanoid = target.parent:FindFirstChildOfClass("Humanoid")
			local player_name = target.parent.name
			
			-- only if player is alive and health is depleted.
			if humanoid.Health <= 0 and not WeaponsSystem.playerIsDead(player_name) then
				
				-- change dead value
				WeaponsSystem.setPlayerDead(player_name, true)
				
				-- get table indx for target and dealer player in current_players
				local player_i = in_table(current_players, player_name, "name")
				local dealer_i = in_table(current_players, dealer.name, "name")
				
				-- assign headshot
				local head_shot = false
				if hitInfo and hitInfo.part and hitInfo.part.Name == "Head" then
					head_shot = true
				end
				
				-- optional
				--local KillEvent = GUIEvents:WaitForChild("KillEvent")

				-- set counters for both target player and dealer player
				current_players[player_i].total_dead = current_players[player_i].total_dead + 1
				current_players[dealer_i].total_kill = current_players[dealer_i].total_kill + 1

				-- optional
				--KillEvent:FireAllClients(dealer.name, player_name, head_shot)
			end
		end
	end
end

now to finish WeaponsSystem i added this line at the very end of WeaponsSystem.doDamage()

function WeaponsSystem.doDamage(target, amount, damageType, dealer, hitInfo, damageData)
    ...
	updateOnPlayerDie(target, dealer, hitInfo)
end

I set a new NetworkingCallback for PlayerReborn at NetworkingCallbacks file, to follow weaponSystem script logic

at the very end right before return NetworkingCallbacks

function NetworkingCallbacks.PlayerReborn(player)
	local WeaponsSystem = NetworkingCallbacks.WeaponsSystem
	if not WeaponsSystem then
		return
	end
	-- player is no longe dead
	WeaponsSystem.setPlayerDead(player.name,false)
end
return NetworkingCallbacks

for last but not less important, to get the head shot part working properly , i changed BulletWeapon:applyDamage() at WeaponsSystem->WeaponTypes->BulletWeapon

function BulletWeapon:applyDamage(hitInfo)
	local damage = self:calculateDamage(hitInfo.d)

	if damage <= 0 then
		return
	end
	-- self.weaponsSystem.doDamage(hitInfo.h, damage, nil, self.player) 
	self.weaponsSystem.doDamage(hitInfo.h, damage, nil, self.player,hitInfo) --<<<
end

How this all work? so in my deep mind :grinning_face_with_smiling_eyes: this do the following
New Player → fires server event PlayerReborn → assign dead status to false and others values → player death → get player dead, killer and last hit part → update player and killer values → player reborn → fires server event PlayerReborn

i have also added some event to be fired on client side, for GUI only , who kills who , headshot or not, how many kills, etc etc.

Just let me know your feedback
Thank you for reading this :smiley:

2 Likes

the tag name for the linked sword is “creator” so the script should look like this

local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")

humanoid.Died:Connect(function()
	if (humanoid:FindFirstChild("creator")) then 
		local player = humanoid.creator.Value
		
	end
end)