Hello, Devs! I am using a modified Zed Tycoon kit, by @TwinPlayzDev, I fixed most of the Issues with the scripts. However, there Is an Infinite yield problem that Is very annoying for me, I know It’s not an error or does not cause any problem but I want the output code to be as clean as possible, whenever I play the game, It runs soo many Infinite yield warnings, the console Is almost full with this annoying messages, If anyone knows anything on how to solve this problem. The problem Is this Line
if script.Parent.PurchasedObjects:WaitForChild(v.Dependency.Value) then
please let me know what I should do, I tried changing “WaitForChild” with “FindFIrstChild” but It didn’t help, (It fixed the Infinite yield problem, but broke the code functionality). I tried to add wait but It didn’t work either (It might fix some issues but I am not sure.)
Full Code:
--[[
All configurations are located in the "Settings" Module script.
Please don't edit this script unless you know what you're doing.
--]]
local TweenS = game:GetService("TweenService")
local r = Random.new()
local PlayMusic = game.ReplicatedStorage:FindFirstChild("PlayMusic")
local BUILDING_ANIMATION_POSITION_OFFSET_AMOUNT = 200
local BUILDING_ANIMATION_PARTDELAY = 0.03
function hasProperty(instance, property)
assert(typeof(instance) == "Instance")
assert(typeof(property) == "string")
local hasProperty = false
pcall(function()
local v = instance[property]
hasProperty = true -- This line only runs if the previous line didn't error
end)
return hasProperty
end
function instanceListToPropertyDict(instances, propertyList)
assert(typeof(instances) == "table")
assert(typeof(propertyList) == "table")
--[[Given a list of instances and a list of properties, construct a dictionary like so:
dict = {
[instance1] = {property1 = instance1.property1, property2 = instance1.property2, ...},
[instance2] = {property1 = instance2.property1, property2 = instance2.property2, ...},
...
}]]
local dict = {}
for _, instance in ipairs(instances) do
local dictEntry = {}
for _, property in pairs(propertyList) do
assert(hasProperty(instance, property), string.format(
[[Instance '%s' (a %s) doesn't have property '%s'.]],
tostring(instance), instance.ClassName, property)
)
dictEntry[property] = instance[property]
end
dict[instance] = dictEntry
end
return dict
end
function getDescendantsWhichAre(ancestor, className)
assert(typeof(ancestor) == "Instance")
assert(typeof(className) == "string")
--[[Returns all descendants of ancestor which are of class className or a class that inherits from className]]
local descendants = {}
for _, descendant in pairs(ancestor:GetDescendants()) do
if descendant:IsA(className) then
table.insert(descendants, descendant)
end
end
return descendants
end
function animateBuildingIn(buildingModel, tweenInfo)
assert(typeof(buildingModel) == "Instance" and buildingModel.ClassName == "Model", string.format(
"Invalid argument #1 to 'animateBuildingIn' (Model expected, got %s)",
typeof(buildingModel) == "Instance" and buildingModel.ClassName or typeof(buildingModel)
))
assert(typeof(tweenInfo) == "TweenInfo", string.format(
"Invalid argument #1 to 'animateBuildingIn' (TweenInfo expected, got %s)",
typeof(tweenInfo)
))
--Collect BaseParts and original properties
local parts = getDescendantsWhichAre(buildingModel, "BasePart")
local originalProperties = instanceListToPropertyDict(parts, {"Transparency", "CFrame", "Color", "Size", "CanCollide"})
--local originalBasePartCFrame = buildingModel.PrimaryPart.CFrame
--Make parts invisible and randomly move them
for _, part in pairs(parts) do
part.Transparency = 1
part.CanCollide = false
part.Color = Color3.fromRGB(255, 255, 255)
-- part.CanCollide = false
part.Size = Vector3.new()
local positionOffset = Vector3.new(r:NextNumber(-1, 1), r:NextNumber(-0.25, 1.75), r:NextNumber(-1, 1)) * BUILDING_ANIMATION_POSITION_OFFSET_AMOUNT
local rotationOffset = CFrame.Angles(r:NextNumber(-math.pi, math.pi), r:NextNumber(-math.pi, math.pi), r:NextNumber(-math.pi, math.pi))
part.CFrame *= CFrame.new(positionOffset) * rotationOffset
end
--Tween them back to their original state, one at a time
local lastTween --Return this so the caller can do animateBuilding(...):Wait() to wait for the animation to complete
for _, part in pairs(parts) do
local tween = TweenS:Create(part, tweenInfo, originalProperties[part])
lastTween = tween
tween.Completed:Connect(function(playbackState)
part.CanCollide = false
--Sometimes Tweens stop before reaching their goal properly.
-- Make sure each Part is exactly how it was before.
part.Transparency = originalProperties[part].Transparency
part.CFrame = originalProperties[part].CFrame
end)
tween:Play()
-- tween.Completed:Wait()
wait(BUILDING_ANIMATION_PARTDELAY)
end
return lastTween.Completed
end
local MarketplaceService = game:GetService("MarketplaceService")
local Objects = {}
local TeamColor = script.Parent.TeamColor.Value
local Settings = require(script.Parent.Parent.Parent.Settings)
local Money = script.Parent.CurrencyToCollect
local Debris = game:GetService('Debris')
local Stealing = Settings.StealSettings
local CanSteal = true -- don't change or else you won't be able to steal currency
local BuildAnimation = Settings.BuildAnimation
script.Parent.Essentials.Spawn.TeamColor = TeamColor
script.Parent.Essentials.Spawn.BrickColor = TeamColor
--Parts that fall into the collector(s) get processed
for i,v in pairs(script.Parent.Essentials:GetChildren()) do
if v.Name == "PartCollector" then
v.Touched:connect(function(Part)
if Part:FindFirstChild('Cash') then
Money.Value = Money.Value + Part.Cash.Value
Debris:AddItem(Part,0.1)
end
end)
end
end
--Player Touched Collector processor
deb = false
script.Parent.Essentials.Giver.Touched:connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if player ~= nil then
if script.Parent.Owner.Value == player then
if hit.Parent:FindFirstChild("Humanoid") then
if hit.Parent.Humanoid.Health > 0 then
if deb == false then
deb = true
script.Parent.Essentials.Giver.BrickColor = BrickColor.new("Bright red")
local Stats = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if Stats ~= nil then
PlayMusic:FireClient(player, "Collect")
Stats.Value = Stats.Value + Money.Value
Money.Value = 0
wait(1)
script.Parent.Essentials.Giver.BrickColor = BrickColor.new("Sea green")
deb = false
end
end
end
end
elseif Stealing.Stealing then -- if player isn't owner and stealing is on
if CanSteal == true then
CanSteal = false
delay(Stealing.PlayerProtection, function()
CanSteal = true
end)
if hit.Parent:FindFirstChild("Humanoid") then
if hit.Parent.Humanoid.Health > 0 then
local Stats = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if Stats ~= nil then
local Difference = math.floor(Money.Value * Stealing.StealPrecent)
PlayMusic:FireClient(player, "Collect")
Stats.Value = Stats.Value + Difference
Money.Value = Money.Value - Difference
end
end
end
else
PlayMusic:FireClient(player, "ErrorBuy")
end
end
end
end)
local chosenGamePassButton = nil
script.Parent:WaitForChild("Buttons")
for i,v in pairs(script.Parent.Buttons:GetChildren()) do
spawn(function()
if v:FindFirstChild("Head") then
local ThingMade = script.Parent.Purchases:WaitForChild(v.Object.Value)
if ThingMade ~= nil then
--print("adding------------------> purchase ",ThingMade.Name)
Objects[ThingMade.Name] = ThingMade:Clone()
ThingMade:Destroy()
else
--//Button doesn't have object, remove it
error('Object missing for button: '..v.Name..', button has been removed')
v.Head.CanCollide = false
v.Head.Transparency = 1
end
if v:FindFirstChild("Dependency") then --// if button needs something unlocked before it pops up
v.Head.CanCollide = false
v.Head.Transparency = 1
coroutine.resume(coroutine.create(function()
if script.Parent.PurchasedObjects:WaitForChild(v.Dependency.Value) then
if Settings['ButtonsFadeIn'] then
for i=1,20 do
wait(Settings['FadeInTime']/20)
v.Head.Transparency = v.Head.Transparency - 0.05
end
end
v.Head.CanCollide = true
v.Head.Transparency = 0
end
end))
end
v.Head.Touched:connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if v.Head.CanCollide == true then
if player ~= nil then
if script.Parent.Owner.Value == player then
if hit.Parent:FindFirstChild("Humanoid") then
if hit.Parent.Humanoid.Health > 0 then
local PlayerStats = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if PlayerStats ~= nil then
if (v:FindFirstChild('Gamepass')) and (v.Gamepass.Value >= 1) then
if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId,v.Gamepass.Value) then
Purchase({[1] = v.Price.Value,[2] = v,[3] = PlayerStats})
else
chosenGamePassButton = v
game:GetService('MarketplaceService'):PromptGamePassPurchase(player,v.Gamepass.Value)
end
elseif (v:FindFirstChild('DevProduct')) and (v.DevProduct.Value >= 1) then
game:GetService('MarketplaceService'):PromptProductPurchase(player,v.DevProduct.Value)
elseif PlayerStats.Value >= v.Price.Value then
Purchase({[1] = v.Price.Value,[2] = v,[3] = PlayerStats})
PlayMusic:FireClient(player, "Purchased")
else
PlayMusic:FireClient(player, "ErrorBuy")
end
end
end
end
end
end
end
end)
end
end)
end
local function onPromptGamePassPurchaseFinished(player, purchasedPassID, purchaseSuccess)
local PlayerStats = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if purchaseSuccess == true and chosenGamePassButton and purchasedPassID == chosenGamePassButton.Gamepass.Value then
print(player.Name .. " purchased the game pass with ID " .. chosenGamePassButton.Gamepass.Value)
Purchase({[1] = chosenGamePassButton.Price.Value,[2] = chosenGamePassButton,[3] = PlayerStats})
end
end
MarketplaceService.PromptGamePassPurchaseFinished:Connect(onPromptGamePassPurchaseFinished)
function Purchase(tbl)
local cost = tbl[1]
local item = tbl[2]
local stats = tbl[3]
stats.Value = stats.Value - cost
Objects[item.Object.Value].Parent = script.Parent.PurchasedObjects
if Settings['ButtonsFadeOut'] then
item.Head.CanCollide = false
coroutine.resume(coroutine.create(function()
for i=1,20 do
wait(Settings['FadeOutTime']/20)
item.Head.Transparency = item.Head.Transparency + 0.05
end
end))
else
item.Head.CanCollide = false
item.Head.Transparency = 1
end
end
function Create(tab)
local x = Instance.new('Model')
Instance.new('NumberValue',x).Value = tab[1]
x.Value.Name = "Cost"
Instance.new('ObjectValue',x).Value = tab[2]
x.Value.Name = "Button"
local Obj = Instance.new('ObjectValue',x)
Obj.Name = "Stats"
Obj.Value = tab[3]
x.Parent = script.Parent.BuyObject
end
--// This was very rushed and is inefficent; if you plan on making something like this don't use a child added listener.
script.Parent:WaitForChild('BuyObject').ChildAdded:connect(function(child)
local tab = {}
tab[1] = child.Cost.Value
tab[2] = child.Button.Value
tab[3] = child.Stats.Value
Purchase(tab)
wait(10)
child:Destroy()
end)
script.Parent.PurchasedObjects.ChildAdded:Connect(function(add)
if Settings['BuildAnimation'] then
local buildwait = 2
for i,v in pairs(add:GetDescendants()) do
if v:IsA("BasePart") then
v.CanCollide = false
end
end
local result = animateBuildingIn(script.Parent.PurchasedObjects[add.Name], TweenInfo.new(buildwait, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out)):Wait()
wait(0.05)
for i,v in pairs(add:GetDescendants()) do
if v:IsA("BasePart") then
if v.Name == "Touch" or v.Name == "Upgrader" or v.Name == "Drop" or v.Name == "Pipe" or v.Name == "LeftFoot" or v.Name == "RightLowerArm" or v.Name == "RightLowerLeg" or v.Name == "RightHand" or v.Name == "RightFoot" or v.Name == "LowerTorso" or v.Name == "LeftUpperLeg" or v.Name == "LeftUpperArm" or v.Name == "LeftLowerLeg" or v.Name == "LeftLowerArm" or v.Name == "LeftHand" or v.Name == "RightUpperArm" or v.Name =="RightUpperLeg" or v.Name == "UpperTorso" or v.Name == "Head" or v.Name == "MyPhones" or v.Name == "Right Leg" or v.Name == "Right Arm" or v.Name == "Left Leg" or v.Name == "Left Arm" then
print(v.Name)
v.CanCollide = false
else
v.CanCollide = true
end
end
end
end
end)
return Objects