So I have a script where if the Player touches a Part with this script inside they will get Exp, But i’m trying to get it so when the player kills a NPC not another player they will get exp, Where should I put the script? And if I have a combat script should I do something with that?
I tried multiple different methods of doing this before but none of them worked, maybe because I don’t understand what I should do to make them work. I did try looking at other forms but I either didn’t understand them or the information in that form didn’t work for me.
Give Player Experience When they Touch Part:
local serverModules = game.ServerStorage:WaitForChild("ModuleScripts")
local PlayerStats = require(serverModules:WaitForChild("PlayerStats"))
local part = script.Parent
local db = {}
local dbTime = 0.6
part.Touched:Connect(function(touch)
local player = game.Players:GetPlayerFromCharacter(touch.Parent)
if player and not db[player] then
db[player] = true
local randomExpToGive = math.random(10, 60)
PlayerStats.AddExp(player, randomExpToGive)
task.wait(dbTime)
db[player] = nil
end
end)
You need to set up a system that tracks the player who last damaged the NPC, and awards that player XP when that NPC dies. A primitive implementation would insert an ObjectValue within each NPC so that the game’s weapons can assign their wielders to that value. When the NPC dies, it will read the current state of the value. The player stored at this time would be the player who last attacked the NPC. There are more advanced solutions that work entirely through middleware. You can have a look at my system for handling FPS kill-tracking
I looked though the kill tracking script but I don’t understand how much of it actually is detecting when someone, or a NPC dies and who killed them, can you give a short example on how to use the Objective Value, I’ll keep looking at the script though to see if I’ll find anything.
You should keep track of which player damaged each NPC last through a table (your combat system should write to this table), and simply index the NPC when it dies to reward exp to that player
can you give an example on how to do this, I’m not good with tables, also is there any way to detect if what the player killed actually is a npc or just another player?
I don’t exactly know how your combat system works, but lets say you have a function that you run each time the player does damage to an NPC
local function attackCharacter(attacker: Player, character: Model)
all you have to do with this is make a table that lists out every NPC paired with a player, which gets updated whenever a player attacks an NPC
local npcAttackerMap: {[Model]: Player} = {}
and update the table whenever the function to attack one of your NPCs or characters is ran
local function attackCharacter(attacker: Player, character: Model)
npcAttackerMap[character] = attacker
-- if you'd like, you can also make this value expire after, for example, 2 minutes
task.delay(120, function()
npcAttackerMap[character] = nil
end)
end
From this table, you can now decide which player to grant experience whenever an NPC dies
local function onCharacterDied(character: Model)
local murderer = npcAttackerMap[character]
-- It's important to check that the character was even murdered by anyone in the first place, as they might have died from things that weren't caused by an attack
if murderer ~= nil then
grantExperienceTo(murderer)
-- Get rid of the value to not leak memory
npcAttackerMap[character] = nil
end
end
Also, you can tell if a character is a player or an NPC by using Players:GetPlayerFromCharacter(character) ~= nil, if it outputs true, it means it is a player, false otherwise
do I put it in like this or do I have to do it a different way?
hit.Parent.Humanoid:TakeDamage(5)
local npcAttackerMap: {[Model]: Player} = {}
local function attackCharacter(attacker: Player, character: Model)
npcAttackerMap[character] = attacker
task.delay(120, function()
npcAttackerMap[character] = nil
end)
end
local function onCharacterDied(character: Model)
local murderer = npcAttackerMap[character]
if murderer ~= nil then
local randomExpToGive = math.random(10, 60)
PlayerStats.AddExp(murderer, randomExpToGive)
npcAttackerMap[character] = nil
end
end
So it turns out I’m dumb, the exp scrip needed a player to give it to, I forgot that the damage script already gave the player who damaged the npc or player, I used that and it worked, thanks though. Although is it possible to do a if statement for if the humanoid that was killed was a humanoid or npc so it only gives exp when the kill was a npc.
It starts with KillsService.trackDamage. This function takes in a Player instance and initializes a damage history for that player. A damage history is a chronological collection of damage tokens, where each token contains the following information:
type DamageToken = {
Dealer : Player?,
Damage : number,
Cause : string,
}
Here, you can see the damage token contains a “dealer”. This is a reference to the Player instance of the client who dealt the damage. KillsService.dealDamage is the middle-man that handles the creation of these tokens, dealing of the damage, and recording of said damage. Further within KillsService.trackDamage, events are set up for detecting the changing health of a player and their ultimate death. As the player gains health, we look at the oldest damage record and reduce its value by the health gain, ultimately erasing the damage record when the gain exceeds its recorded damage. This ensures players who’ve dealt damage to another aren’t considered if that damage is healed away. This also provides an opportunity to record any damage from outside forces.
When the player dies, buildDeathSummary is called, which is a function that evaluates the damage history of the tracked player. The same principle with the ObjectValue is applied here, in that the latest damage record will reveal the player who killed the other. The remaining tokens are processed for rewarding those who helped in slaying the tracked player along the way. This system provides a very powerful summary of how a tracked player died, yielding the following information:
export type DeathSummary = {
Assists : {Player},
AssistCountAsKiller : Player?,
Killer : Player?,
Time : number,
Cause : string,
Location : Vector3?
}