Loot xp orbs script not adding Value to the stats when it should..?

  1. i’m trying to make it to where when player collects the xp orb it will add the amount of xp i want the player to be able to collect, the script works everything works except

  2. except that the xp i earned/collected is not changing the value of my “Exp” the xp variable…

  3. i’m tired of trying i’m done i’m fr giving up i don’t understand how it works on one game but doesn’t on the new game with the same everything added. only different was i changed the leaderstats name to “Data” but reverted back and it still has the issue…? i already have the required events same exact ones and it still does nothing different. i tried changing the way it finds the folder “leaderstats” folder but Nothing worked i did everything i can think of i’m done

-- local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Customize these variables as you need
local XP_PER_KILL = 10 -- The amount of XP gained on each enemy kill
local XP_ORBS_PER_KILL = 10 -- The number of XP orbs dropped per enemy kill
local CASH_DROP_MULTIPLIER = 0.5 -- The multiplier for cash drops (e.g., 2 would double the cash drop)
local CASH_DROP_DESTROY_DELAY = 4 -- The delay (in seconds) before destroying uncollected cash drop
local CASH_AMOUNT_PER_KILL = 1 -- The amount of cash dropped per enemy kill
local CASH_DROP_CHANCE = 1 -- The chance of dropping cash (percentage)

local cashDropped = {} -- A dictionary to keep track of dead humanoids

local function destroyCashDrop(drop)
	wait(CASH_DROP_DESTROY_DELAY)
	if drop and drop.Parent then
		drop:Destroy()
	end
end

local function onEnemyDied(humanoid)
	-- Check if the humanoid has already died and cash has been dropped
	if cashDropped[humanoid] then
		return
	end

	cashDropped[humanoid] = true

	local DropCashTemplate = ReplicatedStorage.DropCash

	local cashAmount = DropCashTemplate.AmountOfCash.Value * CASH_DROP_MULTIPLIER

	local player = game.Players.LocalPlayer
	if player then
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Gold")
			local XP = leaderstats:FindFirstChild("Exp")

			if Cash and XP and Cash.Value >= cashAmount then
				Cash.Value = Cash.Value - cashAmount
				XP.Value = XP.Value + (XP_PER_KILL * XP_ORBS_PER_KILL)
			end
		end
	end

	for i = 1, XP_ORBS_PER_KILL do
		local XPOrbs = ReplicatedStorage.XPOrbs:Clone()
		XPOrbs.Position = humanoid.Parent.HumanoidRootPart.Position
		XPOrbs.Parent = game.Workspace

		-- Start the cleanup coroutine for each XP orb
		coroutine.wrap(function()
			destroyCashDrop(XPOrbs)
		end)()
	end

	if math.random(100) <= CASH_DROP_CHANCE then -- Generate a random number between 1 and 100
		for i = 1, CASH_AMOUNT_PER_KILL do
			local DropCash = DropCashTemplate:Clone()
			DropCash.BillboardGui.amount.Text = cashAmount .. "$"
			DropCash.ProximityPrompt.ObjectText = humanoid.Parent.Name .. "'s Cash"
			local randomOffset = Vector3.new(math.random(-3, 3), 0, math.random(-3, 3)) -- Random position offset around the enemy
			DropCash.Position = humanoid.Parent.HumanoidRootPart.Position + randomOffset
			DropCash.Parent = game.Workspace

			-- Start the cleanup coroutine for each cash drop
			coroutine.wrap(function()
				destroyCashDrop(DropCash)
			end)()
		end
	end
end

local Humanoid = script.Parent:WaitForChild("Enemy")
Humanoid.Died:Connect(function()
	onEnemyDied(Humanoid)
end)

want any more info or the second script let me know, but the second script Does work the problem comes from this script…?

7 Likes

I have some ideas about solving that but firstly, can you tell me some infos like:
1- What type of script is this?
2- Can you send other script which you mentioned earlier?
3- Can you add some Print() for checking which parts are not working properly?

(Generally adding Print() is really effective for debugging, try using it much much more)

7 Likes

From the line local player = game.Players.LocalPlayer i can tell that this is a local script.
I think changing the value from local script doesn’t change the actual value it is just visual.
If you want truly change its value you need to change it on server script instead

4 Likes

that’s what i was thinking but server sided coding is new to me so it’s pretty difficult for me to deal with it. but thank you for letting me know that does help me realize

4 Likes

oh yea i did try messing with that before actually, and i couldn’t switch cause some reason that script actually only works in a “regular” script it’s not even a local script some reason it’s only functional within a regular “script” not local i don’t know why really cause like you said it’s local so? weird

2 Likes

I mean game.Players.LocalPlayer can only be called in local script so that is why im thinking it is local script.

3 Likes

yea i know now, but it’s not working regardless of changing that part of the script here’s the changed version that still doesn’t work same issue.

local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Customize these variables as you need
local XP_PER_KILL = 10 -- The amount of XP gained on each enemy kill
local XP_ORBS_PER_KILL = 10 -- The number of XP orbs dropped per enemy kill
local CASH_DROP_MULTIPLIER = 0.5 -- The multiplier for cash drops (e.g., 2 would double the cash drop)
local CASH_DROP_DESTROY_DELAY = 4 -- The delay (in seconds) before destroying uncollected cash drop
local CASH_AMOUNT_PER_KILL = 1 -- The amount of cash dropped per enemy kill
local CASH_DROP_CHANCE = 1 -- The chance of dropping cash (percentage)

local cashDropped = {} -- A dictionary to keep track of dead humanoids

local function destroyCashDrop(drop)
	wait(CASH_DROP_DESTROY_DELAY)
	if drop and drop.Parent then
		drop:Destroy()
	end
end

local function onEnemyDied(humanoid)
	-- Check if the humanoid has already died and cash has been dropped
	if cashDropped[humanoid] then
		return
	end

	cashDropped[humanoid] = true

	local DropCashTemplate = ReplicatedStorage.DropCash

	local cashAmount = DropCashTemplate.AmountOfCash.Value * CASH_DROP_MULTIPLIER

	-- Find the player by name
	local playerName = humanoid.Parent.Name
	local player = game.Players:FindFirstChild(playerName)
	if player then
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Gold")
			local XP = leaderstats:FindFirstChild("Exp")

			if Cash and XP and Cash.Value >= cashAmount then
				Cash.Value = Cash.Value - cashAmount
				XP.Value = XP.Value + (XP_PER_KILL * XP_ORBS_PER_KILL)
			end
		end
	end

	for i = 1, XP_ORBS_PER_KILL do
		local XPOrbs = ReplicatedStorage.XPOrbs:Clone()
		XPOrbs.Position = humanoid.Parent.HumanoidRootPart.Position
		XPOrbs.Parent = game.Workspace

		-- Start the cleanup coroutine for each XP orb
		coroutine.wrap(function()
			destroyCashDrop(XPOrbs)
		end)()
	end

	if math.random(100) <= CASH_DROP_CHANCE then -- Generate a random number between 1 and 100
		for i = 1, CASH_AMOUNT_PER_KILL do
			local DropCash = DropCashTemplate:Clone()
			DropCash.BillboardGui.amount.Text = cashAmount .. "$"
			DropCash.ProximityPrompt.ObjectText = playerName .. "'s Cash"
			local randomOffset = Vector3.new(math.random(-3, 3), 0, math.random(-3, 3)) -- Random position offset around the enemy
			DropCash.Position = humanoid.Parent.HumanoidRootPart.Position + randomOffset
			DropCash.Parent = game.Workspace

			-- Start the cleanup coroutine for each cash drop
			coroutine.wrap(function()
				destroyCashDrop(DropCash)
			end)()
		end
	end
end

local Humanoid = script.Parent:WaitForChild("Enemy")
Humanoid.Died:Connect(function()
	onEnemyDied(Humanoid)
end)
1 Like

Well yea like i said you’re using local script to changing value which server can’t see the updated value. Only you can see it
You have to create a remote event to fire to a script in ServerScriptService.

Let say you create a remote event in Replicated Storage (Where local script can reach to) named ChangeValue for example

then you call the remote event on top of the local script

local Event = game.ReplicatedStorage:WaitForChild("ChangeValue")

then instead of changing value in local script you replace it with Event:FireServer()

local playerName = humanoid.Parent.Name
	local player = game.Players:FindFirstChild(playerName)
	if player then
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Gold")
			local XP = leaderstats:FindFirstChild("Exp")

			if Cash and XP and Cash.Value >= cashAmount then
				Event:FireServer(cashAmount, (XP_PER_KILL * XP_ORBS_PER_KILL)) --The value you want to send to server script
			end
		end
	end

In server script (The one in ServerScriptService) you recall the event again and start the changes:

local Event = game.ReplicatedStorage:WaitForChild("ChangeValue")

Event.OnServerEvent:Connect(function(player, cashAmount, XP) --player is the one that sent the event, Cash and XP are the values in Event:FireServer()
	local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Gold")
			local XP = leaderstats:FindFirstChild("Exp")

			if Cash and XP then
				Cash.Value = Cash.Value - cashAmount
				XP.Value = XP.Value + XP
			end
		end
end)

If you don’t understand where you can tell me also let me know if it work

2 Likes

yea it still has same issue it works no errors but still is not adding to the “Exp” value stat when it should. here is the Server Script i add in the “Npc” i want to drop the orbs from and such…

local Event = game.ReplicatedStorage:WaitForChild("ChangeValue")

-- Customize these variables as you need
local XP_PER_KILL = 10 -- The amount of XP gained on each enemy kill
local XP_ORBS_PER_KILL = 10 -- The number of XP orbs dropped per enemy kill
local CASH_DROP_MULTIPLIER = 0.5 -- The multiplier for cash drops (e.g., 2 would double the cash drop)
local CASH_DROP_DESTROY_DELAY = 4 -- The delay (in seconds) before destroying uncollected cash drop
local CASH_AMOUNT_PER_KILL = 1 -- The amount of cash dropped per enemy kill
local CASH_DROP_CHANCE = 1 -- The chance of dropping cash (percentage)

local cashDropped = {} -- A dictionary to keep track of dead humanoids

local function destroyCashDrop(drop)
	wait(CASH_DROP_DESTROY_DELAY)
	if drop and drop.Parent then
		drop:Destroy()
	end
end

local function onEnemyDied(humanoid)
	-- Check if the humanoid has already died and cash has been dropped
	if cashDropped[humanoid] then
		return
	end

	cashDropped[humanoid] = true

	local DropCashTemplate = ReplicatedStorage.DropCash

	local cashAmount = DropCashTemplate.AmountOfCash.Value * CASH_DROP_MULTIPLIER

	local player = game.Players.LocalPlayer
	if player then
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Gold")
			local XP = leaderstats:FindFirstChild("Exp")

			if Cash and XP and Cash.Value >= cashAmount then
				Event:FireServer(cashAmount, (XP_PER_KILL * XP_ORBS_PER_KILL)) --The value you want to send to server script
				XP.Value = XP.Value + (XP_PER_KILL * XP_ORBS_PER_KILL)
			end
		end
	end

	for i = 1, XP_ORBS_PER_KILL do
		local XPOrbs = ReplicatedStorage.XPOrbs:Clone()
		XPOrbs.Position = humanoid.Parent.HumanoidRootPart.Position
		XPOrbs.Parent = game.Workspace

		-- Start the cleanup coroutine for each XP orb
		coroutine.wrap(function()
			destroyCashDrop(XPOrbs)
		end)()
	end

	if math.random(100) <= CASH_DROP_CHANCE then -- Generate a random number between 1 and 100
		for i = 1, CASH_AMOUNT_PER_KILL do
			local DropCash = DropCashTemplate:Clone()
			DropCash.BillboardGui.amount.Text = cashAmount .. "$"
			DropCash.ProximityPrompt.ObjectText = humanoid.Parent.Name .. "'s Cash"
			local randomOffset = Vector3.new(math.random(-3, 3), 0, math.random(-3, 3)) -- Random position offset around the enemy
			DropCash.Position = humanoid.Parent.HumanoidRootPart.Position + randomOffset
			DropCash.Parent = game.Workspace

			-- Start the cleanup coroutine for each cash drop
			coroutine.wrap(function()
				destroyCashDrop(DropCash)
			end)()
		end
	end
end

local Humanoid = script.Parent:WaitForChild("Enemy")
Humanoid.Died:Connect(function()
	onEnemyDied(Humanoid)
end)

now here is the Local Script placed in StarterPlayerScripts…

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Event = game.ReplicatedStorage:WaitForChild("ChangeValue")

-- Customize these variables as you need
local XPEvent = game.ReplicatedStorage.XPEvent
local XPAmount = 1 -- Set the amount of XP the player gains when close to an XP orb.
local XP_ORB_ATTRACTION_SPEED = 1 -- Customize the speed at which XP orbs are attracted to players.
local XP_ORB_ATTRACTION_DISTANCE = 50 -- Customize the distance at which XP orbs start being attracted to players.

-- Create a custom sound for collecting XP orbs
local CustomSound = Instance.new("Sound")
CustomSound.SoundId = "rbxassetid://6786936397" -- Replace "YOUR_SOUND_ID" with the ID of the sound you want to use
CustomSound.Volume = 1
CustomSound.Parent = game.ReplicatedStorage.XPOrbs

-- Table to keep track of collected orbs
local collectedOrbs = {}

-- Function called when a player touches an XP orb
local function onPlayerTouchedOrb(player, xpOrb)
	XPEvent:FireServer(XPAmount) -- Notify the server that the player gained XP.
	xpOrb:Destroy() -- Destroy the XP orb once collected.
	CustomSound:Play() -- Play the custom sound when the orb is collected.
	collectedOrbs[xpOrb] = nil -- Remove the collected orb from the table.
end

-- Function to attract XP orbs to players
local function attractXPOrbs()
	local player = game.Players.LocalPlayer
	local humanoidRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		return
	end

	local xpOrbs = game.Workspace:GetChildren()

	for _, xpOrb in ipairs(xpOrbs) do
		if xpOrb.Name == "XPOrbs" and xpOrb:IsA("Part") and not collectedOrbs[xpOrb] then
			local distance = (humanoidRootPart.Position - xpOrb.Position).Magnitude
			if distance <= XP_ORB_ATTRACTION_DISTANCE then
				local moveTween = TweenService:Create(xpOrb, TweenInfo.new(distance / XP_ORB_ATTRACTION_SPEED), {
					CFrame = CFrame.new(humanoidRootPart.Position)
				})
				moveTween:Play()
				moveTween.Completed:Connect(function()
					if xpOrb.Parent and xpOrb.Name == "XPOrbs" and xpOrb:IsA("Part") then
						onPlayerTouchedOrb(player, xpOrb)
					end
				end)
			end
		end
	end
end


Event.OnClientEvent:Connect(function(player, cashAmount, XP) --player is the one that sent the event, Cash and XP are the values in Event:FireServer()
	local leaderstats = player:FindFirstChild("leaderstats")
	if not leaderstats then
		print("leaderstats not being found?")
	end
	if leaderstats then
		local Cash = leaderstats:FindFirstChild("Gold")
		local XP = leaderstats:FindFirstChild("Exp")

		if Cash and XP then
			Cash.Value = Cash.Value - cashAmount
			XP.Value = XP.Value + XP
		end
	end
end)
-- Loop to continuously attract XP orbs and destroy them after being collected
while true do
	attractXPOrbs()
	wait(0.1) -- Adjust the delay as needed to control the frequency of orb attraction and collection.
	for xpOrb, _ in pairs(collectedOrbs) do
		if xpOrb.Parent and xpOrb.Name == "XPOrbs" and xpOrb:IsA("Part") then
			xpOrb:Destroy()
		end
	end
end
2 Likes

I see you misunderstood.
Local Script is the on fire the event (Event:FireServer() )
Server Script is the on receive the event (Event.OnServerEvent() )
It is Event.OnServerEvent() not Event.OnClientEvent() you are placing it in wrong script it should be in server script

2 Likes

OnServerEvent can only be used on the server . that’s why i changed it to use “OnClient” cause it’s not letting me

3 Likes

oh wait my bad. the exp orbs are actually local script though. so i should just change the script to a regular right?

3 Likes

Well if your regular script is the one that show only like a paper then yea (If it is the one with a computer it is a client one)

3 Likes

well i just did it 100% correctly this time and it still won’t work still same issue

2 Likes

Hm weird. Can you give me the source like the game file so i can look for the problem more easier?

2 Likes

i sent you the one i’m working with right now i made 2 new scripts to work with the code. i think i fixed it but i’m running into new issues so i’m fixing one step at a time atm to see what happens

2 Likes

From what i check these value seem changed now.
Also i see the “XPOrbs” Event have the same name with “XPOrbs” Part which caused some error when you cloning them.
And somehow in FireEvent() you deleted the value in Cash make the Event return nil.
Other than that i think that is. (And the bacon i kill again and again it only dropped once. this is your doing right?)

2 Likes

it should drop the orbs more than once, “all times” and yea i actually made the xp system, you can grab it in my models for free to fix it up if you want really… and the one in models should 100% work for sure it does in one of my other games that’s why it’s so weird how it’s not working. XpOrb System - Roblox

2 Likes

i honestly might just start over again cause i messed up the script couple times while messing with it and more. i did mess up few times and code is messy the game is messy lol i wanna fix it all up but idk it took so long and it was hard to deal with server side scripting i’m new with it lol

2 Likes

Yea it is ok scripting take time to understand.

I will try to fix the dropping issue in the meantime

2 Likes