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

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)