Replacement for Roblox's TagHumanoid function (Rewards based on damage contributed OR last hit)

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:

  1. Create a new ModuleScript and place it somewhere accessible by other scripts
  2. Copy and paste the code below into it
  3. Use local DamageModule = require(Path_To_Module) and DamageModule:Damage(Args)
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)

Support

Sirs and madams this thing is (Not) simple feel free to use it for free
1 Like

image

image

1 Like