I have a tycoon kit that I made myself that is having some issues recently, specifically when players attempt to buy buttons or collect cash.
It is not a consistent glitch. Some people, like one of my developers, experience it frequently, and many others, like myself have never experienced it, period. This makes it something that is pretty difficult to replicate.
There is no information or errors given to me by output/the developer console when this issue occurs.
First and foremost, I have tycoons structure in an OOP-style structure, where a server script places the tycoon model/setup around the base, and then executes a tycoon.new() constructor to actually get them working.
I also use Janitor to cleanup connections in the tycoon when it is destroyed by either the player leaving or rebirthing (and then a new tycoon.new() constructor is called). Before I didn’t use a Janitor, which wasn’t good practice given the connections I am running, but it seems that using Janitor may have caused more issues with the button buying/cash collecting.
Second, I have a bit of a weird setup for the cash collectors. There is one main cash collector model, and in it are two collectors. I have the following code for handling that
for _,child in next,self.collection:GetChildren() do
if child:FindFirstChild("main") ~= nil then
self._janitor:Add(
child.main.Touched:Connect(function(hit)
local tP = game.Players:GetPlayerFromCharacter(hit.Parent)
if tP ~= nil then
if tP == self.values.owner.Value then
if self.autoCollect ~= true and self.values.debounce.Value == false and self.values.cashToCollect.Value > 0 then
child.main.BrickColor = BrickColor.new("Bright red")
self.values.debounce.Value = true
local currAmount = self.values.cashToCollect.Value
if tP.multiplier.Value >= 2 then
local newCurrAmount = currAmount*2
tP.leaderstats.Cash.Value = tP.leaderstats.Cash.Value + newCurrAmount
--self.values.cashToCollect.Value = self.values.cashToCollect.Value - currAmount
self.values.cashToCollect.Value = 0
notificationRemote:FireClient(tP,
"Income Notification",
"Since you own the Double Income game pass, you've collected an increased $"..newCurrAmount.."!")
else
tP.leaderstats.Cash.Value = tP.leaderstats.Cash.Value + currAmount
--self.values.cashToCollect.Value = self.values.cashToCollect.Value - currAmount
self.values.cashToCollect.Value = 0
notificationRemote:FireClient(tP,"Income Notification","You've collected $"..currAmount.."!")
end
task.wait(2)
child.main.BrickColor = BrickColor.new("Bright blue")
self.values.debounce.Value = false
end
end
end
end), "Disconnect")
end
end
Here is a snippet of the code that handles buttons. In this code, when a new child is added to the buttons to buy folder, which is detected by a .ChildAdded connection, it establishes a connection for that button for when that button is stepped on:
self._janitor:Add(
self.objects.buttons.ChildAdded:Connect(function(Button)
task.wait(.1)
if Button == nil then error("button error!") end
local ButtonHead = Button:WaitForChild("Head",3)
local PriceText = ""
local stats = Button:WaitForChild("stats",3)
if stats ~= nil then
local itemName = stats.buys.Value.Name
if Button:GetAttribute("buyType") == "Cash" then ---- if the button is bought using cash...
if Button:GetAttribute("tier") ~= nil and Button:GetAttribute("tierMulti") ~= nil then
local rebirthMulti = 0
if self.values.owner.Value ~= nil then
--rebirthMulti = rebirthMulti + self.values.owner.Value.leaderstats.Rebirths.Value
end
local tier = Button:GetAttribute("tier")
local tierMulti = Button:GetAttribute("tierMulti")
local price = math.ceil((costFinder.getTierAmount(tier)*math.max(tierMulti,1))*(1+(.01*rebirthMulti)))
Button:SetAttribute("cost",price)
task.wait(.01)
end
PriceText = "$"..Button:GetAttribute("cost")
elseif Button:GetAttribute("buyType") == "gamePass" then ---- bought with robux
local assetInfo = mkt:GetProductInfo(Button:GetAttribute("cost"),2)
PriceText = "R$"..assetInfo.PriceInRobux
elseif Button:GetAttribute("buyType") == "Rebirths" then ---- bought with rebirth
PriceText = Button:GetAttribute("cost").." Rebirth(s)"
else
PriceText = "Premium Members Only"
end;
Button.display.item.Text = "Buy "..itemName
Button.display.price.Text = PriceText;
task.wait()
ButtonHead.Touched:Connect(function(hit)
if self.values.debounce.Value == false then
self.values.debounce.Value = true
local player = Players:GetPlayerFromCharacter(hit.Parent);
if player ~= nil then
if player == self.values.owner.Value then
self:buy(self.values.owner.Value, Button, Button:GetAttribute("cost"), false)
elseif Button:GetAttribute("teamBuy") == true then
if player.Team == self.values.owner.Value.Team then
self:buy(self.values.owner.Value, Button, Button:GetAttribute("cost"), false)
else
notificationRemote:FireClient(player,
"Purchase Failure",
"You are not a member of the owner's team!");
end
else
notificationRemote:FireClient(player,
"Purchase Failure",
"You are not the Commander of this Base!")
end
end
task.wait(1.5)
self.values.debounce.Value = false
end
end)
end
end), "Disconnect")
The weird thing about the buy buttons is, if the owner tries stepping on the button with this glitch, nothing happens, but if I am to step on their button, it gives me the notification that I am not the owner and therefore cannot buy this button.
And finally, here is the constructor:
function tycoons.new(model)
local self = setmetatable({
_janitor = Janitor.new(), --- the janitor
actualModel = model,
events = model:WaitForChild("events",3), --- folder that contains RemoteEvent
objects = model:WaitForChild("objects",3), --- folder that contains bought objects + buttons
values = model:WaitForChild("values",3), --- this contains the values like owner of the tycoon etc
collection = model:WaitForChild("collectorMoney",3), --- this is the collector cash model
},tycoons)