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
except that the xp i earned/collected is not changing the value of my “Exp” the xp variable…
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…?
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)
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
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
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
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)
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
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
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
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
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?)
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
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