I just realized now that the original Cost
and wholeNub
were only referenced by the section of code that set the initial values. However, I think it could be reused to store the most updated upgrade cost value after Multiplier1
changes so that you wouldn’t have two separate sets of variables.
Before doing that, though, it can be consolidated into a single variable by calling math.floor()
on it before calculateUpgradeCost
returns the value:
-- Before
local function calculateUpgradeCost(currentNumber)
return baseCost * (costMultiplier ^ currentNumber)
end
local Cost = calculateUpgradeCost(currentNumber)
local wholeNub = math.floor(Cost)
-- After
local function calculateUpgradeCost(currentNumber)
return math.floor( baseCost * (costMultiplier ^ currentNumber) )
end
local Cost = calculateUpgradeCost(currentNumber)
Then, instead of creating the Costnew
variable for it whenever Multiplier1.Changed
activates the function, update the original Cost
variable to the value returned from calling the function:
-- Before
Multiplier1.Changed:Connect(function(nextval)
local Costnew = calculateUpgradeCost(nextval)
local wholeNubnew = math.floor(Costnew)
-- After
Multiplier1.Changed:Connect(function(nextval)
Cost = calculateUpgradeCost(nextval)
-- And then the rest of the function will need to be updated to reference "Cost", instead
Lastly, the function that is supposed to fire the RemoteEvent
can reference the Cost
variable since we know it’s being updated with the newest value:
UpgradeButton.Activated:Connect(function()
if Multiplier1.Value == 2 then return end
local valToTake = EventSend:FireServer(Cost)
end)
However, if this RemoteEvent
is being used to verify if the player has enough of a certain leaderstat in order to update their data, you could start by checking if they have enough on the client, and if they do, fire the RemoteEvent
to the server for it to re-verify that and then update the data there.
Something to keep in mind is that exploiters would be able to send in whatever value they wanted as the Cost
, which means that on the server-side, you should be verifying that the calculated Cost
value is correct so that they aren’t able to upgrade unless they actually have met the requirements to do so.
In the same vein, don’t send Multiplier1.Value
through the RemoteEvent
because exploiters may be able to modify that locally, too, and then send through a spoofed value that could result in their stats being increased way more than what was intended.
This means that when you receive the event on the server, you’d need to re-reference Multiplier1
and then update it accordingly:
-- Example
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventSend = Remotes:WaitForChild('UpgradeFinal')
EventSend.OnServerEvent:Connect(function(player)
local MultiplierFolder = player:WaitForChild("MultiplierFolder")
local Multiplier1 = MultiplierFolder:WaitForChild("Multiplier1")
-- Sanity checks here to make sure the player has met the requirements for the changes they are requesting to make
end)
In order to calculate the cost on the server, you would probably need the same calculateUpgradeCost
function, but that also means you would need to reference the baseCost
and currentMultiplier
values, too. Since those values were set directly within the LocalScript
and the server should not rely on the client to send the intended values through, it may need to be revised a bit to ensure that the server knows the
One example of this could be to create Attributes that store the baseCost
and currentMultiplier
values on the Player
object from the server when the game first starts. Both the LocalScript
and the server would be able to reference that with certainty that it’s correct (since it’s being managed by the server).
And lastly, here’s the full version of the LocalScript
again after making those revisions (and I’m pretty sure I made all the necessary revisions; but if not, it should be a quick fix):
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
local MultiplierFolder = player:WaitForChild("MultiplierFolder")
local Multiplier1 = MultiplierFolder:WaitForChild("Multiplier1")
local ScreenGui = script.Parent
local MainFrame = ScreenGui:WaitForChild("MainFrame")
local NextPrice = MainFrame:WaitForChild("NextPrice")
local CurrentMulti = MainFrame:WaitForChild("CurrentMulti")
local NextMulti = MainFrame:WaitForChild("NextMulti")
local CloseButton = MainFrame:WaitForChild("CloseButton")
local UpgradeButton = MainFrame:WaitForChild("UpgradeButton")
local Remotes = ReplicatedStorage.Remotes
local Event = Remotes:WaitForChild('UpgraderClient')
local EventSend = Remotes:WaitForChild('UpgradeFinal')
---
local currentNumber = Multiplier1.Value
local baseCost = 50000
local costMultiplier = 1.25
---
local formatNumber = (function (n)
n = tostring(n)
return n:reverse():gsub("%d%d%d", "%1,"):reverse():gsub("^,", "")
end)
local function calculateUpgradeCost(currentNumber)
return math.floor( baseCost * (costMultiplier ^ currentNumber) )
end
---
local Cost = calculateUpgradeCost(currentNumber)
local function setInitialValues()
NextPrice.Text = '$'.. formatNumber(Cost)
CurrentMulti.Text = 'X '.. Multiplier1.Value
if Multiplier1.Value == 2 then
NextMulti.Text = 'MAX'
elseif Multiplier1.Value <= 1.95 then
NextMulti.Text = 'X ' .. Multiplier1.Value + 0.05
end
end
setInitialValues()
---
Multiplier1.Changed:Connect(function(nextval)
Cost = calculateUpgradeCost(nextval)
NextPrice.Text = '$'.. formatNumber(Cost)
CurrentMulti.Text = 'X '.. Multiplier1.Value
if Multiplier1.Value == 2 then
NextMulti.Text = 'MAX'
elseif Multiplier1.Value <= 1.95 then
NextMulti.Text = 'X ' .. Multiplier1.Value + 0.05
end
end)
UpgradeButton.Activated:Connect(function()
if Multiplier1.Value == 2 then return end
local valToTake = EventSend:FireServer(Cost)
end)
MainFrame.CloseButton.Activated:Connect(function()
ScreenGui.Enabled = false
end)
Event.OnClientEvent:Connect(function()
ScreenGui.Enabled = true
end)