How to check if an NPC killed a Player?

Hello,
Simply put, I want to do a check if a NPC killed a player, I’ve managed to log a:

killerName [killerID] killed playerName [playerNameID] [Weapon_Type]

But I want a check to see if an NPC killed a player, cause if it’s not a player that kills the victim, the killerID turns into ‘nil’ but if an NPC kills a player it also is ‘nil’ and I do not want that, I want to detect if a NPC killed the player so I can show that instead.

I’ve tried some natives but none seem to work so here I am, on the forums, asking for help :confused:

Anyone? :3

Oh I also have a simple question, is it worth it to replace every GetPlayerPed(-1) with PlayerPedId()? Since it seems to be always a faster alternative.

GetPedSourceOfDeath and IsEntityAPed and maybe a for loop in active players-peds to exclude them

You don’t need to do that, there is a native for this :slight_smile:

Apart from that, I’d stick with @rbsace 's suggestion.

1 Like

Still doesn’t tell me if a NPC killed the player or not, that would just return false and it wouldn’t prove a NPC was the cause of his death, NPCs don’t have an ID

                 if killer == GetPlayerPed(id) and IsPedAPlayer(killer) == true then
                     killerName = GetPlayerName(id)
                     killerID = id
                 elseif IsEntityAPed(killer) == true and IsPedAPlayer(killer) == false then
                     killerName = 'NPC'
                     killerID = 'NPC'
                 else
                     killerName = playerName
                     killerID = playerNameID
                 end
             end

Don’t mind the extra code and silly things but I’ve attempted to put it as “NPC” when it’s not a player but it just doesn’t prove that it is a NPC… just that it wasn’t a player.
I’ve tried checking like the code above, I’ve tried with only the “IsPedAPlayer” but still…

I use: death = GetPedCauseOfDeath(playerPed) and it always returns a hash for a weapon, vehicle and so on, it works out for those, but it does not verify that a NPC was the killer, it just says the type of weapon/vehicle etc…

Hi again!

I didn’t notice - try using this native instead :smile:.

I did include on my reply that I’ve tried that, it returns everything but not a NPC. Just what thing killed the player, doesn’t include the NPC but the weapon/method that killed the player with.

You mentioned native GetPedCauseOfDeath, not GetPedSourceOfDeath.

Oh, so sorry, I think the source is the same thing though, saying it’s a ped, object, etc but not saying it’s an actual NPC, I will try printing that out and see what the result is.

It just seems to return 0 when it’s the NPC killing the player.

Are you sure you are calling the native when the psd is actually dead?

Yes, I have a if IsEntityDead(playerPed) and not DeadAlready then
and right after it logs the death reason and by who I print out the Source and it returns 0 when it’s an NPC. But it prints correctly what weapon the played died by, but it assumes that the Killer Name and ID is his own tho. Like he killed himself and that isn’t true.

Isn’t that what you wanted? Just tell me again what you’re trying to achieve.

Whatever I’ve tried, I cannot get something that proves that an NPC killed the player, like I said, if a player gets shot by a NPC, it counts as killing himself, which isn’t right.

Killing himself should be burning himself, exploding himself or drowning on purpose, something like that, but it counts as killing himself when a NPC shoots him too, sadly. It assumes KillerID = player id, KillerName = players name. For some reason

Oh and if I capture the Player ID through: GetPlayerPed(-1) it will return (nil) when a NPC kills him, but if I use PlayerPedId() it’s fast enough to capture an ID but it’s the Players ID.

Please provide the code you’re using. PlayerPedId() and GetPlayerPed(-1) returns the same value and shouldn’t (and most probably doesn’t) make difference.

Citizen.CreateThread(function()
    local DeadAlready = false
    local playerPed = PlayerPedId()
    local playerName
    local playerNameID
    local killerID
    local death

while true do
        Citizen.Wait(100)

        if IsEntityDead(playerPed) and not DeadAlready then
            playerName = GetPlayerName(PlayerId())
            playerNameID = GetPlayerServerId()
            killer = GetPedKiller(playerPed)
            killerName = false

            for id = 0, 100 do -- Amount of players
                if killer == GetPlayerPed(id) and IsPedAPlayer(killer) == true then
                    killerName = GetPlayerName(id)
                    killerID = id
                elseif GetPedSourceOfDeath(playerPed) == 0 and IsEntityAPed(killer) == true and IsPedAPlayer(killer) == false then -----Need to check if NPC is why player died, need better way
                    killerName = 'NPC'
                    killerID = 'NPC'
                else
                    killerName = playerName
                    killerID = playerNameID
                end
            end

              death = GetPedCauseOfDeath(playerPed)

            if checkArray (BulletPistol, death) then
                TriggerServerEvent('playerDied', "**" .. killerName .. ' [' .. tostring(killerID) .. ']** killed **' .. playerName .. ' [' .. playerNameID .. ']** → [Pistol]')
                print(GetPedSourceOfDeath(playerPed))
                print(GetPedCauseOfDeath(playerPed))
            end
            DeadAlready = true
        end
        if not IsEntityDead(playerPed) then
            DeadAlready = false
        end
    end
end)

function checkArray (array, val)
    for name, value in ipairs(array) do
        if value == val then
            return true
        end
    end
    return false
end

I am putting tostring(killerID) cause it will error out if it’s NIL so at least I wanted to see its value

Here is a working snippet:

Citizen.CreateThread(function()
    local DeadAlready = false
    local playerPed = PlayerPedId()

    while true do
        Citizen.Wait(10) — You can play around with this depending on how quick a player can respawn 

        if IsEntityDead(playerPed) and not DeadAlready then
            local playerName = GetPlayerName(playerPed)
            local killedBy = nil

            local sourceOfDeath = GetPedSourceOfDeath(playerPed)

            if sourceOfDeath ~= 0 and IsEntityAPed(sourceOfDeath) then
                if not IsPedAPlayer(sourceOfDeath) then
                    print("Killed by an NPC.")
                else
                    print("Killed by a player.")
                    killedBy = GetPlayerName(sourceOfDeath)
                end
            else
                print("Killed yourself.") -- Fall damage, etc.
            end

            DeadAlready = true
        elseif not IsEntityDead(playerPed) and DeadAlready then
            DeadAlready = false
        end
    end
end)
Citizen.CreateThread(function()
    local DeadAlready = false
    local playerPed = PlayerPedId()
    local victimID, victimName
    local killerID, killerName
    local SourceOfDeath, CauseOfDeath
    local WeaponName

    while true do
        Citizen.Wait(100)
        if IsEntityDead(playerPed) and not DeadAlready then
            victimName = GetPlayerName(PlayerId())
            victimID = GetPlayerServerId(PlayerId())
            killerName = false

            SourceOfDeath = GetPedSourceOfDeath(playerPed)
            CauseOfDeath = GetPedCauseOfDeath(playerPed)
            WeaponName = tostring(CauseOfDeath) -- Don't mind this

                if SourceOfDeath ~= 0 and IsEntityAPed(SourceOfDeath) then
                        if not IsPedAPlayer(SourceOfDeath) then
                            killerName = 'NPC'
                            killerID = 'NPC'
                            print("Killed by an NPC.")
                        else
                            killerName = GetPlayerName(SourceOfDeath)
                            killerID = GetPlayerServerId(SourceOfDeath)
                            print("Killed by a Player.")
                        end

                else
                    killerID = 0
                    killerName = victimName
                    print("Killed yourself.")
                end

            if killerName == 'NPC' and killerID == 'NPC' then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** died due to a NPC → ' .. WeaponName)
            elseif checkArray (Animal, CauseOfDeath) then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** died due to an animal 🐆')
            elseif checkArray (Drown, CauseOfDeath) then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** drowned 💧')
            elseif checkArray (Explosion, CauseOfDeath) then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** died due to an explosion 💥')
            elseif checkArray (FallDamage, CauseOfDeath) then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** died from fall damage')
            elseif killerID == 0 and killerName == victimName then
                TriggerServerEvent('playerDied', '**' .. victimName .. ' [' .. victimID .. ']** killed himself.')
            elseif Config.BannedWeaponLog == false then
                TriggerServerEvent('playerDied', "**" .. killerName .. ' [' .. killerID .. ']** killed **' .. victimName .. ' [' .. victimID .. ']** → ' .. WeaponName)
            elseif Config.BannedWeaponLog == true and checkArray (Config.BannedWeapon, CauseOfDeath) then
                TriggerServerEvent('playerDied', "**" .. killerName .. ' [' .. killerID .. ']** killed **' .. victimName .. ' [' .. victimID .. ']** → __[BANNED WEAPON]__🚫 ' .. WeaponName)
            end

            DeadAlready = true
        elseif not IsEntityDead(playerPed) and DeadAlready then
            DeadAlready = false
        end
    end
end)

I have done this, but when I kill myself for example with a Grenade or RPG it counts as “Killed by Player” same with drowning at times, returning killerName as ‘Invalid’ and ID as 0 + victimName as the right playerped name but victimID as the right player ID

Oh and dying from falling doesn’t even print anything :confused:
I want this to log every time a death happens but after the first death it seems to break, before it wasn’t the case with my older code.

There was a little mistake in my code - you must get the player’s ped id every time he respawns. But - apart from that, have you even tried my code? It works flawlessly on my server.

Citizen.CreateThread(function()
    local DeadAlready = false
    local playerPed = nil

    while true do
        playerPed = PlayerPedId()
        Citizen.Wait(10) -- You can play around with this depending on how quick a player can respawn 

        if IsEntityDead(playerPed) and not DeadAlready then
            local playerName = GetPlayerName(playerPed)
            local killedBy = nil

            local sourceOfDeath = GetPedSourceOfDeath(playerPed)

            if sourceOfDeath ~= 0 and IsEntityAPed(sourceOfDeath) then
                if not IsPedAPlayer(sourceOfDeath) then
                    print("Killed by an NPC.")
                else
                    print("Killed by a player.")
                    killedBy = GetPlayerName(sourceOfDeath)
                end
            else
                print("Killed yourself.") -- Fall damage, etc.
            end

            DeadAlready = true
        elseif not IsEntityDead(playerPed) and DeadAlready then
            DeadAlready = false
        end
    end
end)

Yes your Code does seem to work I adapted it to mine, but my issue now seems to be that when I attempt to print the Killers ID, it prints as nil, for example I kill a player and the killer id turns into NIL for some reason, not my actual ID

But maybe I’m even getting the killer ID wrongly, how do I do it? :thinking: