It’s key codes. SO like the q key, e key, etc.
You can try this way, although not the most efficient way, you can build on it:
When a player damages the NPC, store the player in a table, then once it dies, retrieve it from the table and you can see which players did damage.
The thing is, what would I do to detect who damages the npc?
I’m not to experienced with damage system’s but I would recommend using remote events with the player name as a variable. :FireServer() from when the keycode is pressed.
Well yes, the attacks work like that and all, but what I’m trying to do is have the boss script detect who damages it.
Add another variable to the RemoteEvent with the players name.
This would require some framework:
- There will be a module somewhere in a script service that manages the NPCs and player damage
- The module will also create a new table to each NPC
- The player will require the module when they do damage
- The module will deal damage to the NPC and insert the player into that NPCs table
- When the NPC dies, retrieve the corresponding table
This might seem hard to do, and yes, it is if you just started using frameworks, but, once you get the hang of it, this is probably one of the most efficient ways to do these kinds of tasks.
I’d have to put each power’s event inside of that one script and there’s like 50 of em.
Trying to do this without editing the power scripts as much as possible.
A simple way to do this that I have used:
Make a folder inside the boss. Then check when the player does damage to the boss. Get that player name and store it in a boolvalue. Put this inside the folder and maybe call it “PlayersWhoDamagedBoss”. After that, loop through the values in the folder, and give the rewards to the players.
I don’t know what you mean as I don’t know how your system works. All I can say is use a RemoteEvent. You can just set up another one to make it more simple if needed.
I’m trying to do it without having to put values inside of the boss when the player attacks, as I’d have to do that for each attack - and there’s quite a lot of attacks.
Don’t do it for each attack. Just check when the player has damaged the boss, and then check if they are in the folder or not. If they are not, then add them. It will have a table of all the players who damaged the boss.
Still, I’d have to put something in each attack to detect when the player has damaged a boss.
add a string value to the player upon playeradded. Then each time something damages the player have it also edit the string value with the name of the attacker
i.e. Last = nil
player takes 10 dmg from Nogalo
Last = Nogalo
Again, that would require having to add something to each attack/power.
simply make a module for it instead of injecting it into every script
Hm but still wouldn’t I have to completely change how the powers work (so they use one single module)?
make a dmg calculator module. This is also useful if you have abilites that increase and reduce damage. When an ability finds a target instead of doing dmg right away fire the module, which would then change the value of the boolvalue inside the victim
Make a function (on the server side) that’s like TakeDamage, but stores the damage a player has dealt to a humanoid. We are going to make a drop-in replacement for TakeDamage that will keep track of how much damage a boss has been dealt by which players.
Make a ModuleScript that the function is in, so you don’t have to put the function in every script that deals damage to bosses.
The function, which is now better named something like PlayerDamagesHumanoid
not TakeDamage
, should be something like this—
-- ModuleScript
local module = {}
local prefix = "damage-"
function module.PlayerDamagesHumanoid(player, humanoid, damage)
-- Store the damage dealt
-- I've chosen to store the damage in IntValues in the Humanoid itself
-- The benefits are that they automatically get cleared when the
-- boss is removed from the map, and the boss's death event
-- can find the data easily
-- However, all clients can see the IntValues appear and change
-- This may not be a bad thing e.g. if you do want to make a live
-- boss damage leaderboard
-- Find or create the IntValue, which is named after the player with
-- a prefix before it (this prevents conflicts with other unrelated things
-- inside the hunanoid)
local name = prefix .. player.Name
local record = humanoid:FindFirstChild(name)
if record == nil then
record = Instance.new("IntValue")
record.Name = name
record.Parent = humanoid
end
-- Increase the value
record.Value = record.Value + damage
-- Damage the humanoid
return humanoid:TakeDamage(damage)
-- We assume that this is always successful and the Humanoid is
-- not protected by a ForceField - you'll have to deal with it
-- yourself if so
end
return module
Name the script DamageRecorder for example, put it in ServerScriptService and require it in your scripts like this:
local DamageRecorder = require(game:GetService("ServerScriptService").DamageRecorder)
Now search every single script for a :TakeDamage() against a boss.
In these scripts, require the above module. Replace all humanoid:TakeDamage(damage)
with DamageRecorder.PlayerDamagesHumanoid(player, humanoid, damage)
. Note that you need to know which player did the attack!
Eventually, the boss will die.
It should then loop through all of the children of its Humanoid (or where-ever the damage records are stored) and recover all the damage records of the players. Something like this—
-- Place in the same module as the above function
local Players = game:GetService("Players")
function module.RetrieveDamageRecords(humanoid)
local playersAndDamage = {}
for _,v in ipairs(humanoid:GetChildren()) do
-- Is this a damage record? Does its name start with the prefix?
if string.sub(v.Name, 1, #prefix) == prefix then
-- This is a damage record.
local playerName = string.sub(v.Name, #prefix + 1) -- Get player name
local playerDamage = v.Value
-- But first, is the player actually still in the game?
-- Otherwise, you might end up giving awards to players who
-- are long gone, and other annoying missteps related to various
-- player stuff being gone (no character, no leaderstats etc.)
local player = Players:FindFirstChild(playerName)
if not player then continue end
-- We need to put this info in playersAndDamage somehow
-- I opted to make it an array of record objects/tables, each
-- object containing the player and their damage.
table.insert(playersAndDamage, {
player = player,
damage = playerDamage
})
end
end
return playersAndDamage
end
The script that handles boss death has to require the module and use DamageRecorder.RetrieveDamageRecords(humanoid)
to get all the players that damaged it (if they used PlayerDamagesHumanoid
to do so!!!)
To get the best player, either iterate over all of the records and find the highest one (similarly to the ‘get nearest player’ function that’s in every zombie and such), or sort the table if you want the n
best players.
local function sortfunc(a, b) return a.damage < b.damage end
-- Your creature's humanoid
local hum
local records = DamageRecorder.RetrieveDamageRecords(hum)
-- Sort the records from most to least damage dealt
table.sort(records, sortfunc)
-- Kill the player who dealt the most damage
-- You might want to reward them instead
records[1].player.Character:BreakJoints()
Edit:
there’s a bunch of powers/things that can hit the boss, and I don’t want to have it insert a value into the boss for each attack
There isn’t much of a way around it. There needs to be some kind of evidence that it was this or that particular player who damaged something. If you leave a lego on the ground and someone steps on it, then there’s no way to know it was you who dropped it, unless your name is on the lego (i.e. putting a value on an attack that refers to who attacked – you have to do this yourself), or someone saw you drop the lego (i.e. storing who made which attack in some table like whoAttacked[brick] = player – again, nothing does this by default)
The method in my post needs only a creator
value on each projectile, and a value for each player who has hit a humanoid - it’s not hard to manage if you make it easy to manage by creating functions that hide all the pain from you.