Coin Collecting Issue

This is really hard for me to explain, so just tell me if it makes sense or not. Say in a game there is a coin, and just as a player is about to get that coin another player gets it before he does. How would I make it so that both players can get that coin. Lets go back to the example early. The player who has just collected the coin cannot collect it again until it respawns. For the other player though ,who was about to collect it, can still collect it until he touches it. (sorry if this doesn’t really make sense, I am bad at explaining this). The reason why I need to know this is because in my game people get mad when there are no coins to collect when someone just collect the coin he/she was about to take. Thank you!

4 Likes

When a player picks up the coin, only delete it on their client via a local script. Using a remote event, have the server award them the coin. After the desired amount of time, replace the coin on the same client (it may be easiest to simply reparent the coin to the replicatedstorage or something and then reparent back to workspace after the cooldown).

You will probably want to keep track of how often they pick up each coin on the server to prevent users from hacking the remote event to get infinite coins.

3 Likes

For this, the coin must be localized. When the player (seemingly) touches the coin, they send a signal through a remote event to the server to give them the reward for the coin.
Here, the server checks it’s list of cooldowns for this coin (container of your choosing). If it finds no cooldowns that relate to said player and coin, then it will award the points and add the cooldown (for example, a StringValue whose name is the player’s name and whose value is the coin’s identifier) and then use the Debris service to make the new cooldown expire after a set amount of time.
Once the amount of time passes, the cooldown is automatically removed and the coin appears to the player locally (better to have a separate script use a remote event to signal the client that the coin should respawn on their end), making it possible to collect once more on their end. This method makes sure that everyone stays happy and absolutely no tampering can occur from the client.

3 Likes

you can use the while wait command. Set it to while wait(1) do and detect if another humanoid is touching it. And then destroy it with :Destroy. That is if you want the coin to be deleted from the entire server. But if the coins are just local, then, you just need a local script that destroys the coin when touched, and then have to local script fire a remote event. Make sure :Destroy is in the local script.

you dont want :Destroy() unless you’re planning for the coins to not regenerate again and only be collected once, Destroy() is actually a pretty TERRIBLE idea, you might want to do this,

put this in the coin …
getting the coin at the same time is impossible, try it

waittime = 6 -- Time Between each hit
amnt = 20 --how much you get for it
function onTouched(part)
	local h = part.Parent:findFirstChild("Humanoid")
	if (h~=nil) then
		local thisplr = game.Players:findFirstChild(h.Parent.Name)
		if (thisplr~=nil) then
			local stats = thisplr:findFirstChild("leaderstats")
			if (stats~=nil) then
				local score = stats:findFirstChild("PUT YOUR CURRENCY NAME HERE IF IT IS IN LEADERSTATS")
				if (score~=nil) then
					score.Value = score.Value + amnt
				end
			end
		end
		
		script.Parent.Transparency = 1
		script.Disabled = true
		wait(waittime)
		script.Parent.Transparency = 0
		script.Disabled = false		


	end
end

script.Parent.Touched:connect(onTouched)

this will automatically regenerate after

waittime
although what @Kironte said before, you can localize it to prevent to players getting it at the same time.

You can always clone it back, considering you using collection service

But then again isn’t it better to set an infinite loop (or for a specified duration)
for regenerating the coin rather then cloning every one of them whenever you need to call one to be generated?

You will probably want to keep track of how often they pick up each coin on the server to prevent users from hacking the remote event to get infinite coins.

I am sorry, but I am like a beginner-intermediate scripter. How would I keep track of how often they pick up a coin? Also great idea!

1 Like

BUt then there is the max part count, and destroy command would be s a very good thing to use. In addition to that, there would be less lag

On the server, when a player is awarded a coin, log that coin under the users name in an array and set the value to the current tick. If the user tries to pick up that same coin again, check the array with saved tick value and compare to the current tick value. Make sure that the difference of the ticks is greater than or equal to the amount of time it takes for the coin to regenerate. If it hasn’t been long enough, I would simply not award them the coin. If you want to be proactive about hackers, you can have them kicked with a warning if they are managing to spam the coin remote event.

Does this make sense? I can show an example of the array you would need to create.

I think you misunderstood his question. He doesn’t care about two players getting the coin at the same time, in fact he wants every player to be able to pick up the same coin that was just picked up, except the player who already picked it up.

He wants the coins to not disappear for other users when a user picks one up, but to only disappear for the user that grabbed it. Then of course, it should regenerate after the allotted time passes (but only for the user that picked it up), thus the necessity for a localized coin, with remote events for the stat of the coin to be able to be adjusted.

Edit: It also does not really matter if the coin is destroyed and re-cloned, or made transparent, or re-parented for the duration of the regeneration. The difference is going to be negligible since the code is ran on the client and will not be effecting the server whatsoever.

ofcourse a localized script is what he requires, in that case.

1 Like

This makes sense to me, I am just confused on how to do it. I would love it if you showed me an example!
And how do you make a 3D block belong to the client? Do you just put a local script in it? Sorry if you already answered this.

You don’t make it “belong” so to speak. You must parent the local script to somewhere it can be executed, like StarterPlayerScripts, etc. Inside of the local script just reference the coin object and now whatever you do will be client side only (on the coin itself).

It is exactly as @Antradz said. If you delete the coin via a local script, it will only be deleted for that user. Simply place a local script into the starter character and set up the touched events there.

I can give you a more detailed explanation if you need, let me know!

Edit: Happy Thanksgiving! I will be a little less active today as I have family plans.

If you could make a script on it and post it here, that would be awesome! Although this is kinda late, Happy Thanksgiving!

Thanks! I will be on tomorrow morning to answer this.

Essentially, you will create an array outside of the function’s scope called something like coinsTimers. You will then save the coin, and the current tick() every time a coin is picked up. This should be saved under the player’s name. You may want to erase a player’s data once they leave the game to avoid having an unnecessary amount of data retained in this array. If a player does not yet have any data, we will add their name into the array, with the value set to an empty table. We will then insert a table with the coin and tick() inside it. This is what we will refer to for our checks if the player has data. If the player has data, we will need to loop through their data to find if the coin they are trying to pick up has been picked up yet. If it has, we will need to check how long it has been since they did so. If they haven’t yet, then we will award the coin and add the coin and tick into the players data.

Note you may need to change certain directories for your code to work. I just made example code.

local coinsTimers = {} -- our new array that will track coin pick up times!
local regenTime = 10 -- set this to your regeneration timer in seconds
game:GetService’ReplicatedStorage’.RemoteEvents.AwardCoin.OnServerEvent:Connect(function(player, coin) -- your awardCoin remote event (or whatever you refer to it as ;p).
    local awardCoin = false -- if this is not met as true by the end of the checks, coin is not awarded.
    if coinsTimers[player.Name] ~= nil  then -- has the player recieved a coin? If not they won't have a value in the array yet.
        local coinFound = false -- if this is not found in the array and set to true, the coin has not been picked up yet and thus will be added with a timer and awardCoin will be set to true.
        local i = 0 -- track how many times the loop has ran in case we need to remove the old tick() value if the coin is eligible to be picked up.
        for savedCoin, lastTime in pairs(coinsTimers[player.Name]) do -- loop through all the current saved data in the array. Unfortunately, we cannot directly refer to the coin since we also have to save the tick as well.
            i = i + 1
            if coin == savedCoin then -- if this is the coin we are looking for..
                coinFound = true -- we found the coin!
                if tick() - lastTime > regenTime then -- check if it has been long enough!
                    awardCoin = true -- this coin should be awarded!
                    table.remove(coinsTimers, i) -- delete the old time assigned to the coin.
                    table.insert(coinsTimers, {coin, tick()}) -- add the new time assigned to the coin.
                end
                break
            end
        end
        if not coinFound then -- if coin wasn't found in the saves, award the coin!
            table.insert(coinsTimers[player.Name], {coin, tick()})
            awardCoin = true
        end
    else -- the player does not have data yet, lets add it!
        awardCoin = true
        coinsTimers[player.Name] = {}
        table.insert(coinsTimers[player.Name], {coin, tick()})
    end
    if awardCoin then -- the checks proved the coin should be awarded, lets give them a coin!
        player.Stats.Coins.Value = player.Stats.Coins.Value + 1
    end
end)

All edits were notes being added, please let me know if you need anymore assistance implementing this change!

Note: In order for this to work, you will need to be retaining the same coin on the client side. AKA don’t delete the coin. On your local script, have the coin re-parented during the duration of the regeneration, or simply make it transparent. That way the server script can always reference the same coin when checking the timer.

6 Likes

This is great! thanks! Just in a little while I am just gonna clarify on what to do so I got it down. Thanks again!

1 Like