I need help with my mission system for my game

Hello, im working on an mmo and i tried making a simple cargo mission, basically you go to an npc to get the mission . if you accept the mission you get a tool in your backpack(this is the cargo) then you have to go the another npc to turn in the cargo and receive your reward. The problem is when you go turn in the cargo you get rewarded but if you click the button again after that it will continue to give you the reward(gold and xp). But if you never go to the first npc to get the cargo then go to the other npc to try and get the reward then it wont give you the reward so it seems like it works fine until you have the cargo in your backpack then thats when it gets messed up. Sorry if im not explaining it good but its just a weird situation. it should work but it doesn't. the code looks perfect to me so im just lost at this point.

Heres the entire script for turning in the cargo for reward. this is inside of a textbutton in a screenGui. Theres also a remote event and a server script with the function to give the reward ill also include that script below the first script

LocalScript

local player = game.Players.LocalPlayer
local giveGoldEvent = script.Parent.GiveGoldEvent
local cargo = player.Backpack:WaitForChild("Cargo1")

script.Parent.MouseButton1Click:Connect(function()
	if not cargo then end

	giveGoldEvent:FireServer()
	cargo:Destroy()
end)

Server script

local RemoteEvent = script.Parent.GiveGoldEvent


function GiveGold(player)
	player.leaderstats.Gold.Value = player.leaderstats.Gold.Value + 25
	player.leaderstats.Xp.Value = player.leaderstats.Xp.Value + 50
end

RemoteEvent.OnServerEvent:Connect(GiveGold)
3 Likes

Great work so far! However, you need to change what is done by the server and what is done by the Client.

Instead of just having a GiveGold event, you should have an event for turning in the cargo that the client sends. Then, on the server, you should check if the player can actually turn in the cargo and, if they can, destroy the cargo and give the player gold and xp.

It is my suspicion that the client is unable to actually delete the tool and that is why they can use it multiple times.

Also, if you are still having trouble, add a debugger or just some simple print statements to see which code is running and which code might be having issues!

1 Like

Add a variable or Datastore, like this:

local Data = game:GetService("DataStoreService"):GetDataStore("Test")

local RemoteEvent = script.Parent.GiveGoldEvent


function GiveGold(player)
local data = Data:GetAsync(player.userId.."-key"
if data then
else 
	player.leaderstats.Gold.Value = player.leaderstats.Gold.Value + 25
	player.leaderstats.Xp.Value = player.leaderstats.Xp.Value + 50
Data:SetAsync(plr.userId.."-key", "SAVE")
return 
end

end
RemoteEvent.OnServerEvent:Connect(GiveGold)

Also, check at the line,

if not cargo then return end

return end? That might fix it

Why not use an array? There’s no reason to store the information on datastore just to retrieve it seconds later; This causes unnecessary yielding and extra work on the server that simply doesn’t have to be done.

EDIT: If you are using a datastore to save info between servers, only load when a player joins and save when a player leaves, or backup periodically.

2 Likes

i tried that already it didn’t work

I made some print statements there but i still don’t understand why this happens. I mean it does seem like the client isn’t deleting the tool correctly but im not sure how to fix it still. If you click the button it just keeps giving the same output even when theres visibly no cargo in the players backpack

local player = game.Players.LocalPlayer
local giveGoldEvent = script.Parent.GiveGoldEvent
local cargo = player.Backpack:WaitForChild("Cargo1")

script.Parent.MouseButton1Click:Connect(function()
	if not cargo then return print("No cargo") end

	giveGoldEvent:FireServer()
	cargo:Destroy()
	print("cargo recieved")
end)

Server script

local RemoteEvent = script.Parent.GiveGoldEvent

function GiveGold(player)
print(“Rewarded”)
player.leaderstats.Gold.Value = player.leaderstats.Gold.Value + 25
player.leaderstats.Xp.Value = player.leaderstats.Xp.Value + 50
end

RemoteEvent.OnServerEvent:Connect(GiveGold)

Output...

cargo received
Rewarded

Have you tried using the FindFirstChild constructor to check if the cargo exists?

script.Parent.MouseButton1Click:Connect(function()
 if  player.Backpack:FindFirstChild("Cargo1") then -- will return true if Cargo1 exist, nil if not
	giveGoldEvent:FireServer()
	cargo:Destroy()
      end
end)

The reason why you script wasn’t working was because you are only checking if “Cargo1” exist once, its only being defined once and thus if cargo existed when you first did:

player.Backpack:WaitForChild("Cargo1")

cargo will never equal nil , if you trying to “use” it, it will give you an error because when the script tries to finally reference it , it wont be able to so as it doesn’t exist .

As you want it to equal nil if cargo doesn’t exist, so using this will never “end”

if not cargo then end

So to fix that checking to see if it exist again, as i mentioned above in this case using FindFirstChild should work for this and it should solve your problem.

3 Likes

Thanks ill give it a try but the first time i wrote the script i was using FindFirstChild instead of WaitForChild. If you clicked the button to turn in the cargo nothing happened no reward and the cargo wasnt getting destroyed. I will give it another try and get back to you

1 Like

i changed it to findfirstchild but it does the same thing. i also removed the line that say if not cargo then return end

oh sorry i read that wrong. i fixed it now it seems to work in studio

1 Like