Cash upon damaging NPC

So I guess you would set the health before it was changed, and when it is changed (Using HealthChanged Humanoid.HealthChanged) get the value of that change (so that you can preform and operation on this value, such as adding it to the leaderboard), and then send that value to the leaderboard.

This is sudo code, and not actual code.

2 Likes

You can add a multiplier based on the dmg to your cash. I’ll assume you know how to add money. Here’s an example to the equation.

local dmg = 50 --how much dmg the player did I believe you can check the amount of dmg via HealthChanged on the humanoid of the npc you're attacking.
local multiplier = 1.5 --The multiplier. You would do dmg * multiplier to get the amount of cash you get.
cash += dmg * multiplier --adding to the current cash leaderstat

You would put this probably as a local scripts in player starter scripts or something- don’t really know much about leaderstats.

1 Like

Yeah he/her could do it that way most likely

1 Like

Next time, try to provide some code of what you’ve already done to make it easier for others to add or fix upon what you’ve made (it makes for a better learning experience too!).

For example, in this code, I have no idea HOW you want a certain player to be rewarded. I don’t know if you’ve tagged the player instance or set up object values pointing to the player who did the last hit.

Anyways, I’ll just set up the basics of what this thread has come up with for you so you can build upon it or ask about it later…

local players = game:GetService("Players")

-- your values here. these won't work until you hook them up appropriately for your game.
local humanoid
local humanoidRootPart
local cashPerHit = 10


local cash


local function findNearestPlayer()
	
	-- put characters in a table array so we can sort through it later...
	local characters = {}
	
	-- loop through each player in the server and check if their characters exist...
	for i, playerInstance in ipairs(players:GetChildren()) do
		
		local thisPlayerCharacter = playerInstance.Character
		if thisPlayerCharacter then
			-- put this character in the table
			table.insert(characters, thisPlayerCharacter)
		end
	end
	
	
	-- check to see if the table has at least one character inside the array..
	-- if there is one, sort the list
	if #characters > 0 then
		
		if #characters > 1 then
			-- only sort if there is more than one target otherwise you're sorting for no reason...
			table.sort(characters, function(a, b)

				local function distance(givenChar)
					-- in this case, Magnitude is the distance in units between two points
					return (humanoidRootPart.Position - givenChar.Position).Magnitude
				end

				-- sort from smallest to greatest
				return distance(a) < distance(b)
			end)
		end
		
		-- closest char should be at the first
		return characters[1]
	else
		-- return nothing since table is empty
		return nil
	end
end





-- HealthChanged event suggested by ProgrammersRightHand
humanoid.HealthChanged:Connect(function()
	local closestChar = findNearestPlayer()
	
	-- if player character was found...
	if closestChar ~= nil then
		--convert the character back into a player instance to change cash value prolly
		local targetPlayer = players:GetPlayerFromCharacter(closestChar)
		
		-- change the cash value
		targetPlayer.Cash += cashPerHit
	end
end)

But for real, please put any code that you have done that you think can help us help you.

2 Likes

sorry for not providing any code

heres the script for the cash when killing an npc:

function PwntX_X() 
local tag = Humanoid:findFirstChild("creator") 
if tag ~= nil then 
if tag.Value ~= nil then 
local Leaderstats = tag.Value:findFirstChild("leaderstats") 
if Leaderstats ~= nil then 
Leaderstats.Cash.Value = Leaderstats.Cash.Value + script.Parent.addedMoney.Value
wait(0.1) 
script:remove() 
end 
end 
end 
end 
Humanoid.Died:connect(PwntX_X)

and heres the cash:

	local folder = Instance.new("Folder", plr)
	folder.Name = "leaderstats"
	local cash = Instance.new("IntValue", folder)
	cash.Name = "Cash"
	cash.Value = 0
end)

game:GetService('Players').PlayerAdded:Connect(function(player)

	player.CharacterAdded:Connect(function(character)

		character:WaitForChild("Humanoid").Died:Connect(function()

			if player.leaderstats.Cash.Value  > 0 then

				wait(1)

				player.leaderstats.Cash.Value = 0

				player.PlayerGui.Death.Message.Visible = false

				player.PlayerGui.Death.Message.Text = ''

				wait(1)

				player.PlayerGui.Death.Message.Visible = false

			end

		end)

	end)

end)

im new to scripting, please try to provide clear instructions on how to set it up if you have a solution

1 Like

Thank you for sharing your code. :slightly_smiling_face:

Since you’ve tagged them with an object value (I think), we just have to copy your PwntX_X() function and change it up a bit so it doesn’t destroy the script as soon as it gets damaged.

I made it so you can slap this code into the script that has PwntX_X() in it

local function onDamage()
	local tag = Humanoid:findFirstChild("creator") 
	if tag ~= nil and tag.Value ~= nil then 
		local Leaderstats = tag.Value:findFirstChild("leaderstats") 
		if Leaderstats ~= nil then 
			Leaderstats.Cash.Value = Leaderstats.Cash.Value + script.Parent.addedMoney.Value
		end 
	end
end

-- add HealthChanged event
Humanoid.HealthChanged:Connect(onDamage)

Note that these events might overlap each other because the Died and HealthChanged event will both fire at the same time when the humanoid dies, so you’ll probably want to add a check to make sure the humanoid is alive before running the code in onDamage().

1 Like

is there any way to make it so that the amount of money given to the player be the amount of the damage the player deals to the npc?

1 Like

Yes there is.

https://developer.roblox.com/en-us/api-reference/event/Humanoid/HealthChanged

What you should do is to create a dictionary and add any new NPCs to it along with their current health.

Then when the healthchanged event fires, you get the previous current health stored in the table, as well as the value that the event returns (the new health). Subtract the difference and you have the change in health which you can convert to cash amount.

Then update the dictionary for the NPC with the new health.

1 Like

can you show me an example of how to do this with my current code? thanks

1 Like

Would be difficult to do as youve not provided the code around how your NPCs are created. But broadly:

Create a blank array in the server script which creates your npcs:

Local npcHealth = {}

At the point your server script creates an Npc, get the NPC humanoid and:

npcHealth[humanoid] = humanoid.Health

Then in your event:

humanoid.HealthChanged:Connect(function(newhealth)
        local currentHealth = npcHealth[humanoid]
	local change = math.abs(currentHealth - newhealth)
	-- Insert your code to calculate money based on the change in health
	npcHealth[humanoid] = newhealth
end)

Bear in mind im writing this on a mobile so the syntax and formatting might not accurate. Nut this should be enough for you to adaprt for your code.

2 Likes

Going off of what @ArcherThesu suggested, I would recommend adding money inside the server code of your guns. As it deals damage, add money to the player based on how much damage has been dealt. I can’t provide an exact solution since no code was provided, but here is an example:

local MoneyMultiplier = 2 -- (this can obviously be changed)
--Damage
NPC_humanoid:TakeDamage(damageToDeal) -- lets say damageToDeal is 50 in this case
Player.Money.Value += (damageToDeal * MoneyMultiplier) -- 50x2=100 cash would be added

This example assumes you use an IntValue inside the player, but adjust it accordingly.

Hope this helps a bit :slight_smile:

2 Likes

the npc is actually an AI free model, i changed mine a little but that shouldnt affect anything
Marine AI IV - Roblox (ignore the vehicle i dont use it)

1 Like

as stated in the original post im using ACS 2.0.1 which is a free model gun engine
unfortunately the entire system is complex and the guns themselves only have the values for how much damage a gun does but the code which makes it so that these values are how much damage the gun does is in a separate script which is not in the gun itself

1 Like

If the gun’s damage is controlled by a separate script, edit that one, otherwise if the actual damage is controlled by each gun individually, you’ll have to add it to every gun, which would be tedious (but possible). It may be worth switching gun systems or learning how to make one yourself, which could take time but would eventually pay off.

Unfortunately, free models have their limitations and can be harder to edit than if you made it yourself.

1 Like

In the same script as the PwntX_X(), add a variable that stores the past health of the humanoid.
We’re gonna use it to calculate the damage percentage that the last player hit just did, though it may not be performant or accurate if you’re using a bunch of guns with high firerates.

-- I'm assuming this is the total amount of gold you want reward...
local totalCashReward = script.Parent.addedMoney.Value


-- this is to calculate the damage percentage in onDamage()
local pastHp = Humanoid.Health


local function onDamage()
	
	local currentHp = Humanoid.Health
	local damagePercentage = currentHp / pastHp
	
	-- if the damagePercentage is over 100%, that means the humanoid has healed instead of taking damage
	-- we return because we're only rewarding players for damaging npcs, not healing them
	if damagePercentage > 1 then return end
	
	-- update the pastHp for the next onDamage() call
	pastHp = currentHp
	
	local tag = Humanoid:findFirstChild("creator") 
	if tag ~= nil and tag.Value ~= nil then 
		
		local Leaderstats = tag.Value:findFirstChild("leaderstats") 
		if Leaderstats ~= nil then 
			
			-- scale reward amount with the damage percentage...
			local thisReward = totalCashReward * damagePercentage
			Leaderstats.Cash.Value = Leaderstats.Cash.Value + thisReward
		end 
	end
end

-- add HealthChanged event
Humanoid.HealthChanged:Connect(onDamage)

I haven’t stressed tested this to see how well it would do against multiple machine guns but this should be a good starting point.

You can also do what @fireustuk and @pjhinthehouse said. Their methods take a lot more work, but it is better in the long run when making a big game.

1 Like

how am i supposed to put this into my current script?
ive pasted this under the original script and sometimes the money rewarded becomes a negative value

Off the top of my head, the only way the value would become negative is if the Humanoid’s health is below zero, since that would create a negative percentage.

You’ll probably want to add a guard clause to make sure the Humanoid is alive, so add a

local currentHp = Humanoid.Health
if currentHp < 0 then return end

If that doesn’t work then try printing out each of the values to see where it is going wrong.

1 Like

it seems to be working now, but it seems like when killing the npc its rewarding you for the amount of damage you dealt to the enemy and not the amount of health the npc had left

it also seems to be giving me negative values when using high firerate weapons

I have an idea for your game development, i came accross a problem with this issue and i haven’t found a solution for it. After thinking for a while, i manage to do it by myself without anyone’s help.

Here’s an example code with info and details in it:

local EnemyTarget = game.Workspace.Dummy -- Example Enemy
local GunDamage = 5 -- This is your gun damage

-- Let's say the health is 100 or the max health is 100
-- And then get the Gun Damage value, example is 5. (Per Hit)

-- The first method is if the enemy health is lower than the damage.
if EnemyTarget.Humanoid.Health < GunDamage then -- if 100 is less than 5 then do stuff.
	-- We subtract the enemy's health and the gun damage : 5 - 4 (Example Enemy's Health is down to 4)
	local Recalculate = GunDamage - EnemyTarget.Humanoid.Health -- 5 - 4 = 1
	-- Now the enemy should be take damage upon hit with the exact damage which is 5.
	EnemyTarget.Humanoid:TakeDamage(GunDamage)

	-- Now we should earn the right money, because 5 damage per hit depends on the enemy's health.
	game.Players.Pul129PG.leaderstats.Cash.Value += GunDamage - Recalculate -- We earn 5 - 1 = 4 cash upon killing it fully!

	-- Now for the 2nd method. Different way of damaging the enemy with same cash, it means Damage = Cash. (Sorry for bad English)
elseif EnemyTarget.Humanoid.Health >= GunDamage then -- if 100 > 5 then do stuff.
	-- Now the enemy should be take damage upon hit with the exact damage which is 5.
	EnemyTarget.Humanoid:TakeDamage(GunDamage)

	-- Now we earn exact cash with same damage which is 5.
	game.Players.Pul129PG.leaderstats.Cash.Value += GunDamage
end

And now if you need help converting this to your script, just ask me and i’m here to help right away!

If you need more info about this example, here’s how…

Method 1:

-- The first method is used to check whether the enemies health is either lower than the damage value, for example: The enemy's health is 4 and the current gun's damage is 5. We cannot let it earn 5 cash, but instead give him the cash by 4 (Subtracting).
if EnemyTarget.Humanoid.Health < GunDamage then
	
end

Method 2:

-- The 2nd method is used if the enemy's health is more than or equal to the Gun's Damage value, it means the damage is 5 and the enemy's health is more than that (100 example), and also if the enemy's health is 5 but the damage is also 5, we earn the exact damage. That means overall the 2nd method is the exact damage.
--[[else]]if EnemyTarget.Humanoid.Health >= GunDamage then

end

What’s the difference between the two methods?

  • The first method is only used to earn exact enemy’s health cash.
    (Example: Enemy’s Health is 4, but the damage is 5. We earn 4 cash after hit.)

  • The 2nd method is only used to earn the exact cash with same damage.
    (Example: Enemy’s Health is 35, but the damage is 5. We earn 5 cash after hit.)

Overall both of them are used for Tower Defense Game in my opinion.
Notice, this can be used anywhere. Not only in TDG

Let me know if i miss anything.