I am making a tycoon game. When a player presses one of their buttons (and has enough money to buy it) the game builds the part and updates the player’s data. My buttons in this tycoon are separated into three categories: Structure, Security, and Laptop Upgrades. Naturally. My player data is structured in a table and one of the values is BuildButtons, which is the number of structure buttons the player has pressed. When a player successfully pushes a button and builds the part, it is supposed to add one to the BuildButtons data value. However, it seems to add one to each active player’s BuildButtons data instead.
I would test the game on a local server with two players. Both players would load in and they would be given the default data (which is basically 0 of everything) When Player1 would get a tycoon and build some parts, Player2 would get the other tycoon and all the parts that Player 1 had built would load in for him. The data is being updated for both player 1 and player 2 for some reason that I can’t figure out. My guess is it has something to do with the for loops I use to spread the code across all available tycoons.
What happens in the scripts is this:
It is a tycoon and there will be multiple tycoons so I do have my Structure Script wrapped in a for loop that loops through all the banks in the Banks folder. The Structure Script has a list of buttons. When a button is pressed it uses the BuildScript module script to see if the player has enough money to buy it and if he does the BuildScript builds the instance and returns true to the Structure Script. The structure script then gets the player’s data from the PlayerData module script and adds one to the build buttons value.
Originally I had my BuildScript update the player’s data but I switched it around a bunch of times to try out different ways of doing it and here we are.
Here is my first Structure Script that handles the buttons.
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local playerData = require(ServerScriptService.PlayerData)
local buildScript = require(ServerScriptService.BuildScripts.BuildScript)
local levelUpEvent = ReplicatedStorage.LevelUp
local cashTableBoughtEvent = ReplicatedStorage.CashTableBought
local banks = workspace.Banks:GetChildren()
for _, bank in banks do
local securityFolder = bank.Lvl1Security:GetChildren()
local structureFolder = bank.Structure
local vaultHousingFolder = bank.VaultHousing
local vaultFolder = bank.Vault
local deskFolder = bank.Desks
local loanOfficeFolder = bank.LoanOffices
local buttons = {structureFolder.Wall1.Button, structureFolder.Wall2.Button, structureFolder.Wall3.Button, structureFolder.Wall4.Button,
structureFolder.DoorLeft.Button, structureFolder.DoorRight.Button, vaultHousingFolder.Wall1.Button, vaultHousingFolder.Wall2.Button,
vaultHousingFolder.Wall3.Button, vaultHousingFolder.Door.Button, vaultFolder.Wall1.Button, vaultFolder.Wall2.Button, vaultFolder.Wall3.Button,
vaultFolder.Wall4.Button, vaultFolder.Floor.Button, vaultFolder.Ceiling.Button, vaultFolder.VaultDoor.Button, vaultFolder.Locker1.Button,
vaultFolder.Locker2.Button, vaultFolder.Locker3.Button, vaultFolder.Table.Button, deskFolder.Desk1.Button, deskFolder.Computer1.Button,
deskFolder.Desk2.Button, deskFolder.NpcComputer.Button, deskFolder.Desk3.Button, deskFolder.NpcComputer1.Button
}
--Add the touched function to all of the buttons in the laptop upgrades folder
for index, button in buttons do
button.Touched:Connect(function(hit)
local COST = button.Cost.Value
local bank = button.Parent.Parent.Parent
local owner = bank.Owner
playerData.returnPlayerData(Players:FindFirstChild(hit.Parent.Name).UserId).BuildButtons += 1
if not button:GetAttribute("Touched") then
button:SetAttribute("Touched", true)
if buildScript.instanceTouched(COST, hit, owner.Value, button.Parent, bank, "Structure") then
local character = Players:GetPlayerFromCharacter(hit.Parent)
buildScript.hideButton(button)
--Activate the next button if there is one
if #buttons > index then
buildScript.activateButton(buttons[index+1])
else
local addedMoney = math.floor(500 * character.Backpack.Multiplier.Value)
character.leaderstats.Money.Value += addedMoney
print("Bank Level 1 Completed. Awarded $" .. addedMoney)
levelUpEvent:Fire(bank, 1, 1, "Bank", addedMoney)
end
end
task.wait(0.1)
button:SetAttribute("Touched", false)
end
end)
end
end
Here is my BuildScript module script that checks to see if a player has enough money and then builds the instance.
local BuildScript = {}
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local playerData = require(ServerScriptService.PlayerData)
local prestigeEvent = ReplicatedStorage.PrestigeActivated
local resetBankEvent = ReplicatedStorage.ResetBank
local function CheckPrice(COST, partTouched, ownerName, instance)
local player = partTouched.Parent
if player:FindFirstChildWhichIsA("Humanoid") then
if player.Name == ownerName then
local character = Players:GetPlayerFromCharacter(player)
local money = character.leaderstats.Money
if money.Value < COST then
print("Need $" .. COST - money.Value .. " more")
else
money.Value -= COST
print("Bought " .. instance.Name .. " for $" .. COST)
return true
end
else
print(player.Name .. " is not the owner!")
end
end
return false
end
local function modifyPart(part, transparency, canCollide)
if transparency ~= "_" then
part.Transparency = transparency
end
if canCollide ~= "_" then
part.CanCollide = canCollide
end
end
local function BuildInstance(instance, bank)
if instance:HasTag("Default") then
if instance.ClassName == "Part" or instance.ClassName == "UnionOperation" or instance.ClassName == "MeshPart" then
modifyPart(instance, 0, true)
end
local parts = instance:GetDescendants()
local directParts = instance:GetChildren()
for _, part in directParts do
if part.Name == "EventFireScript" then
part.Enabled = true
end
end
for _, part in parts do
if part:HasTag("Ignore") then
elseif part.ClassName == "Script" or part.ClassName == "SurfaceGui" or part.ClassName == "SpotLight" or part.ClassName == "SurfaceLight" then
part.Enabled = true
elseif part.ClassName == "ClickDetector" then
part.MaxActivationDistance = 20
elseif part.ClassName == "Part" or part.ClassName == "UnionOperation" then
if part.Name ~= "Button" then
modifyPart(part, 0, true)
end
elseif part.ClassName == "Decal" then
part.Transparency = 0
elseif part.ClassName == "MeshPart" then
modifyPart(part, 0, true)
elseif part.ClassName == "Seat" then
part.CanTouch = true
part.CanCollide = true
elseif part.ClassName == "BoolValue" then
if part:HasTag("True") then
part.Value = true
end
elseif part.ClassName == "Sound" then
if part:HasTag("Start") then
part:Play()
end
elseif part.ClassName == "BindableEvent" then
part:Fire(bank)
end
if part:GetAttribute("Glass") then
modifyPart(part, part:GetAttribute("Glass"), "_")
end
if part:HasTag("CantCollide") then
modifyPart(part, "_", false)
end
end
elseif instance:HasTag("CantCollide") then
modifyPart(instance, 0, false)
end
end
function BuildScript.instanceTouched(COST, partTouched, ownerName, instance, bank, buttonType)
if not partTouched.Parent:FindFirstChild("MaxMoney") then
if CheckPrice(COST, partTouched, ownerName, instance) then
local successSound = instance.Button.Successful
successSound:Play()
BuildInstance(instance, bank)
return true
else
local failSound = instance.Button.Failure
failSound:Play()
end
end
return false
end
function BuildScript.hideButton(button)
if button:FindFirstChild("Highlight") then
button.Highlight:Destroy()
end
button.CanCollide = false
button.Transparency = 1
button.BillboardGui.Enabled = false
button.CanTouch = false
end
function BuildScript.activateButton(button)
local highLight = Instance.new("Highlight")
highLight.Parent = button
highLight.FillColor = button.Color
highLight.FillTransparency = 0.9
highLight.OutlineTransparency = 0.8
button.CanCollide = true
button.Transparency = 0
button.BillboardGui.AlwaysOnTop = true
button.BillboardGui.Enabled = true
button.CanTouch = true
end
function BuildScript.loadProgress(buttonFolder, bank, buttonsPressed, playerData, Datatype)
if buttonsPressed >= #buttonFolder then
buttonsPressed = #buttonFolder
else
if buttonFolder.Name ~= "StructureButtons" and buttonsPressed ~= 27 then
if buttonFolder.Name ~= "SecurityButtons" and buttonsPressed ~= 8 then
if buttonFolder.Name ~= "StructureButtons" and buttonsPressed ~= 57 then
if buttonFolder.Name ~= "SecurityButtons" and buttonsPressed ~= 26 then
if buttonFolder.Name ~= "StructureButtons" and buttonsPressed ~= 77 then
if buttonFolder.Name ~= "SecurityButtons" and buttonsPressed ~= 36 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
elseif playerData == 139 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
elseif playerData == 36 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
elseif playerData == 77 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
elseif playerData == 26 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
elseif playerData == 57 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
elseif playerData == 8 then
BuildScript.activateButton(buttonFolder[buttonsPressed + 1])
end
end
for i = 1, buttonsPressed do
BuildInstance(buttonFolder[i].Parent, bank)
BuildScript.hideButton(buttonFolder[i])
end
end
resetBankEvent.Event:Connect(resetBank)
return BuildScript
Here is my PlayerData module script
local Players = game:GetService("Players")
local playerData = {}
local default = {
["Money"] = 0,
["BuildButtons"] = 0, --Max 139 Level 1: 27 Level 2: 57 Level 3: 77 Level 4: 107,
["SecurityButtons"] = 0, --Max 45 Level 1: 8 Level 2: 26 Level 3: 36
["LaptopButtons"] = 0, --Max 5
["CustomerAccountSystem"] = {},
["Employees"] = {},
["Multiplier"] = 1.0,
["Ads"] = 0, -- Max 5
["PlayerLevel"] = 1 -- Max 5
}
local dataBase = {}
function playerDataModules.getPlayerData(playerId)
for key, data in dataBase do
if key == playerId then
print(playerId .. "'s data is loading...")
local player = Players:GetPlayerByUserId(playerId)
player.leaderstats.Money.Value = data.Money
print(playerId .. "'s data set!")
return
end
end
print("Could not find player data! Setting default data...")
dataBase[playerId] = default
print("Data set!")
end
function playerDataModules.savePlayerData(playerId, player)
for key, data in dataBase do
if key == playerId then
print("Found", playerId .. "'s data. Saving...")
print(data)
data.Money = player.leaderstats.Money.Value
return
end
end
warn("ERROR: Could not get player's data!")
playerDataModules.getPlayerData(playerId)
end
function playerDataModules.returnPlayerData(playerId)
local data = dataBase[playerId]
if data then
return data
end
warn("ERROR: Could not find player's data to return!\nAttempting to set default data...")
playerDataModules.getPlayerData(playerId)
end
The scripts are modified a little bit. I just cut out the fat that didn’t contribute to this part.