Damage Module & Improved TagHumanoid function
Introduction
Hi! I’m about to release an open-sourced system for applying Status Effects which utilizes this function so I’m making this post first
You might have seen something called TagHumanoid in Roblox Gear scripts, which is used to indicate the last player who killed an enemy or another player. It does not let you know how much damage each player contributed if many people team up to fight.
This function allows you to replace the outdated method by Roblox. You can check not only the last hit, but also total damage contributed by each individual player.
On top of that, I have a function for dealing damage here, it automatically does the sanity checks as well as tagging the target upon dealing damage. You can even send info like ignoring defense or immunity or attack type (If the target has Defense or AttackType . . Immunity Attributes)
Usage:
- Create a new ModuleScript and place it somewhere accessible by other scripts
- Copy and paste the code below into it
- Use local DamageModule = require(Path_To_Module) and DamageModule:Damage(Args)
- Roblox Model: Damage Module & Updated TagHumanoid
Source code:
local Module = {}
local Players = game:GetService("Players")
function Module:TagForDamage(Player: Player, Target, Damage: number)
local Humanoid = Target:FindFirstChildOfClass("Humanoid")
if not Humanoid or Humanoid.Health <= 0 then return end
local PlayerTags = Target:FindFirstChild("PlayerTags")
if not PlayerTags then
PlayerTags = Instance.new("Configuration")
PlayerTags.Name = "PlayerTags"
PlayerTags.Parent = Target
end
-- Why not Username? Because players can change theirs while playing, rare but not impossible
local ExistingTag = PlayerTags:GetAttribute(Player.UserId)
if ExistingTag then
PlayerTags:SetAttribute(Player.UserId, ExistingTag + Damage)
else
PlayerTags:SetAttribute(Player.UserId, Damage)
end
-- In case you want to reward the one who did the final blow
if Damage >= Humanoid.Health then
PlayerTags:SetAttribute("LastHit", Player.UserId)
end
end
function Module:Damage(Player: Player, Target, Damage, IgnoreDefense, IgnoreImmunity, AttackType, Cooldown)
if Player and Target and Target:FindFirstChildOfClass("Humanoid") and tonumber(Damage) ~= nil then
local TargetHum = Target:FindFirstChildOfClass("Humanoid")
if TargetHum.Health <= 0 then return end
local Character = Player
if Player:IsA("Player") then
Character = Player.Character
else
Player = Players:GetPlayerFromCharacter(Player)
Character = Player.Character
end
if Cooldown then
if Target:GetAttribute(Player.UserId) then return end
Target:SetAttribute(Player.UserId, true)
task.delay(Cooldown, function()
Target:SetAttribute(Player.UserId, nil)
end)
end
if Character:GetAttribute("Voided") then
Damage = Damage / 2
end
if not IgnoreDefense and Target:GetAttribute("Defense") then
Damage = Damage - (Damage * Target:GetAttribute("Defense") / 100)
end
if not IgnoreImmunity and AttackType and Character:GetAttribute(AttackType .. "Immunity") then
Damage = Damage - Damage * (Character:GetAttribute(AttackType .. "Immunity") / 100)
end
if Damage > TargetHum.Health then
Damage = TargetHum.Health
end
Module:TagForDamage(Player, Target, Damage)
TargetHum:TakeDamage(math.clamp(Damage, 0, TargetHum.MaxHealth))
return Damage
end
end
return Module
- The function used in gears (Quite outdated)
-- Don't use this, the DamageModule is above if you somehow missed it
Module.TagHumanoid = function(Humanoid, Player)
for i, v in pairs(Humanoid:GetChildren()) do
if v:IsA("ObjectValue") and string.lower(v.Name) == "creator" then
v:Destroy()
end
end
local Creator_Tag = Instance.new("ObjectValue")
Creator_Tag.Name = "creator"
Creator_Tag.Value = Player
Creator_Tag.Parent = Humanoid
end
Examples (These are also in the model I provided above)
Here are some examples to get you understand what this can be used for.
- 1: Reward all players who dealt damage equal to at least 15% of the target’s MaxHealth
local MinimumDamagePercentageForReward = 0.15
local Rewards = {
Coins = 100, BadgeID = 0
}
local Character = script.Parent
local Humanoid = Character:FindFirstChild("Humanoid")
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local PlayerData = require(ServerScriptService.PlayerData.Manager) -- ProfileService datastore
local FunctionBank = require(Your_Badge_Rewarding_Function)
if Character:FindFirstChild("PlayerTags") then
local PlayerTags = Character:FindFirstChild("PlayerTags")
for UserId, Damage: number in PlayerTags:GetAttributes() do
UserId = tonumber(UserId)
if UserId then
local Player = Players:GetPlayerByUserId(UserId)
if not Player then continue end
local Percent = Damage / Humanoid.MaxHealth
if Percent >= MinimumDamagePercentageForReward then
local RewardMulti = Percent / 2
if RewardMulti > 0.5 then
RewardMulti = 0.5
end
local profile = PlayerData.Profiles[Player]
if profile then
PlayerData.AdjustStat(Player, profile, "Kills", 1)
PlayerData.AdjustStat(Player, profile, "Coins", math.round(Rewards.Coins * RewardMulti))
end
if Rewards.BadgeID then
FunctionBank.AwardBadge(Player, Rewards.BadgeID)
end
end
end
end
end
- 2: Touched damage in a Roblox sword
local DamageModule = require(game:GetService("ReplicatedStorage"):FindFirstChild("DamageModule"))
function Blow(Part)
Part.Touched:connect(function(Hit)
if not Hit or not Hit.Parent or not Equipped or not Character or not Character.Parent then
return
end
local character = Hit.Parent
local humanoid = character:FindFirstChild("Humanoid")
if character ~= Character and humanoid and humanoid.Health > 0 then
if not humanoid then return end
if humanoid.Parent == Tool then return end
if game:GetService("Players"):GetPlayerFromCharacter(Hit.Parent) then return end
DamageModule:Damage(Player, Hit.Parent, (Active and Damage.Slash) or Damage.Touch)
end
end)
end
- 3: Dealing damage from a script in a projectile or a minion created by a player
local DamageModule = require(game:GetService("ReplicatedStorage"):FindFirstChild("DamageModule"))
DamageModule:Damage(script:FindFirstChild("creator").Value, TempChar, Damage)
Features
- LastHit (The player who deals the final hit)
- Damage contribution (You can reward players based on the damage dealt percentage)
- Defense/Immunity (Set Attributes to use this)
- Cooldown (Time to wait before the same player can attack again)