script.lol
Executors Arceus X (Mobile) Delta Executor Synapse X (PC) KRNL Exploit Xeno Scripts Keyless Scripts
Search Roblox Scripts
Popular Searches
Payload copied to clipboard
100% Free & Keyless 🐾 Pet Sim 99 Aug 10, 2026 Author: ins

VibeCoded Sloppy Pet sim 99 pet spawner and farmer OPENSOURCE (Pet Sim 99) Script Pastebin 2026 - Auto Farm, ESP & Keyless (Arceus X)

Verified and keyless Lua script payload for VibeCoded Sloppy Pet sim 99 pet spawner and farmer OPENSOURCE. Compatible with Android/iOS mobile executors and Windows PC exploits.

script.lua (Raw Payload)
local Players     = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer

local ClientLib = game:GetService("ReplicatedStorage"):WaitForChild("Library"):WaitForChild("Client")

local function need(name)
	local child = ClientLib:FindFirstChild(name)
	if not child then return nil end
	local ok, mod = pcall(require, child)
	return ok and mod or nil
end

local Network        = need("Network")
local FFlags         = need("FFlags")
local PlayerPet      = need("PlayerPet")
local MapCmds        = need("MapCmds")
local InstancingCmds = need("InstancingCmds")
local EventUpgrades  = need("EventUpgradeCmds")
local RaidCmds       = need("RaidCmds")
local FiestaMazeCmds = need("FiestaMazeCmds")

local ClientRaid = (function()
	local rc = ClientLib:FindFirstChild("RaidCmds")
	local child = rc and rc:FindFirstChild("ClientRaidInstance")
	if not child then return nil end
	local ok, mod = pcall(require, child)
	return ok and mod or nil
end)()

local Orb = (function()
	local oc = ClientLib:FindFirstChild("OrbCmds")
	local child = oc and oc:FindFirstChild("Orb")
	if not child then return nil end
	local ok, mod = pcall(require, child)
	return ok and mod or nil
end)()

local Lib = game:GetService("ReplicatedStorage"):WaitForChild("Library")

local function needAt(parent, name)
	local child = parent and parent:FindFirstChild(name)
	if not child then return nil end
	local ok, mod = pcall(require, child)
	return ok and mod or nil
end

local FiestaUpgrades  = needAt(Lib:FindFirstChild("Util"), "FiestaUpgrades")
local UpgradeDir      = needAt(Lib:FindFirstChild("Directory"), "EventUpgrades")
local CurrencyItem    = needAt(Lib:FindFirstChild("Items"), "CurrencyItem")
local RaidTypes       = needAt(Lib:FindFirstChild("Types"), "Raids")
local BreakableTypes  = needAt(Lib:FindFirstChild("Types"), "Breakables")
local TeleportTo      = needAt(Lib:FindFirstChild("Functions"), "TeleportCharacterTo")

-- Breakables.ParentType = { Zone = 1, Instance = 2, Plaza = 3 }
local ParentType = (BreakableTypes and BreakableTypes.ParentType) or { Zone = 1, Instance = 2, Plaza = 3 }
local P_ZONE, P_INSTANCE, P_PLAZA = ParentType.Zone, ParentType.Instance, ParentType.Plaza

if not Network then
	error("[Fiesta] could not require Network -- game not loaded yet?")
end

-- taps/sec and target count are intentionally not exposed: the script always
-- runs flat out at every breakable it can legally damage.
local TAP_RATE   = 30
local PET_SPEED_MULT = 100

local CFG = {
	autoTap    = false,
	sendPets   = true,

	petSpeed   = false,

	autoOrbs   = false,

	autoJoin   = false,
	instanceId = "FiestaLobby",

	autoMaze   = false,

	autoUpgrade = false,
	wanted      = {},   -- [upgradeId] = true
}

local running = {}

local Weave   -- loaded in the UI section below; used by the upgrade loop

--=============================================================================
-- breakable discovery
--=============================================================================

local breakFolder

local function breakableModels()
	if not (breakFolder and breakFolder.Parent) then
		local things = workspace:FindFirstChild("__THINGS")
		breakFolder = things and things:FindFirstChild("Breakables")
	end
	return breakFolder and breakFolder:GetChildren() or {}
end

-- Zone the server thinks we are in. Breakables carry BOTH a ParentType and a
-- ParentID, and the two are validated differently (see canMine below), so a
-- plain "zone id" is not enough on its own.
local function currentZoneId()
	if MapCmds then
		local ok, res = pcall(MapCmds.GetCurrentZone)
		if ok and res then return res end
	end
	return nil
end

local function currentInstanceId()
	if InstancingCmds then
		local ok, res = pcall(InstancingCmds.GetInstanceID)
		if ok and res then return res end
	end
	return nil
end

-- what the status line shows
local function currentParentId()
	return currentInstanceId() or currentZoneId()
end

local function inInstance()
	if not InstancingCmds then return false end
	local ok, res = pcall(InstancingCmds.IsInInstance)
	return ok and res and true or false
end

local function myPosition()
	local char = LocalPlayer.Character
	local root = char and char:FindFirstChild("HumanoidRootPart")
	return root and root.Position or nil
end

-- defined up here so the auto-join guard can ask "are we mid-raid?"
local function currentRaid()
	if not (ClientRaid and ClientRaid.GetCurrent) then return nil end
	local ok, raid = pcall(ClientRaid.GetCurrent)
	return ok and raid or nil
end

-- BreakableFrontend.canMine, mirrored. The server applies the same rule, so
-- anything this rejects would be a wasted remote call:
--   Instance -> InstancingCmds.IsInInstance(parentID)   (raids/maze live here)
--   Zone     -> ZoneCmds.Owns(parentID)
--   Plaza    -> on the trading plaza
-- The maze is an INSTANCE, not a zone. Comparing its ParentID against
-- GetCurrentZone() never matches, which is why nothing got tapped in there.
local function canDamage(model, zoneId, instanceId)
	local pType = model:GetAttribute("ParentType")
	local pId   = model:GetAttribute("ParentID")

	if pType == P_INSTANCE then
		return instanceId ~= nil and pId == instanceId
	end

	if pType == P_ZONE then
		if model:GetAttribute("VIPBreakable") then return false end
		-- while inside an instance, outside-world zone breakables are not ours
		if instanceId then return false end
		return zoneId == nil or pId == zoneId
	end

	if pType == P_PLAZA then
		return false
	end

	-- unknown/absent ParentType: fall back to a loose id match
	return pId == nil or zoneId == nil or pId == zoneId or pId == instanceId
end

-- returns { {uid=, model=, dist=}, ... } nearest first.
-- every breakable we are actually allowed to damage, no cap.
local function collectTargets()
	local zoneId = currentZoneId()
	local instanceId = currentInstanceId()
	local pos = myPosition()
	local out = {}

	for _, model in ipairs(breakableModels()) do
		local uid = model:GetAttribute("BreakableUID")
		if uid and model:IsA("Model") and canDamage(model, zoneId, instanceId) then
			local dist = 0
			if pos then
				local ok, pivot = pcall(model.GetPivot, model)
				if ok then dist = (pivot.Position - pos).Magnitude end
			end
			table.insert(out, { uid = uid, model = model, dist = dist })
		end
	end

	table.sort(out, function(a, b) return a.dist < b.dist end)
	return out
end

--=============================================================================
-- damage
--=============================================================================

local function tap(uid)
	-- BreakableFrontend rate-limits this to 8/s client-side; we call it directly
	if Network.UnreliableFire then
		pcall(Network.UnreliableFire, "Breakables_PlayerDealDamage", uid)
	else
		pcall(Network.Fire, "Breakables_PlayerDealDamage", uid)
	end
end

-- pets deal the bulk of the damage, tapping alone is chip damage
local function assignPets(model)
	if not (PlayerPet and CFG.sendPets and model) then return end
	local ok, pets = pcall(PlayerPet.GetByPlayer, LocalPlayer)
	if not ok or type(pets) ~= "table" then return end
	for _, pet in pairs(pets) do
		pcall(function() pet:SetTarget(model) end)
	end
end

--=============================================================================
-- pet speed
--
-- PlayerPet.CalculateSpeedMultiplier is the single funnel for pet movement
-- speed. updatePetSpeedTask() re-reads it once a second and broadcasts the
-- result to the parallel pet actors, so hooking it is enough -- no per-pet
-- writes and nothing to re-apply when pets respawn.
--=============================================================================

local originalCalcSpeed
local hookFailed = false

-- push the current multiplier onto every live pet right now
local function pushPetSpeed()
	pcall(function()
		for _, pet in pairs(PlayerPet.GetByPlayer(LocalPlayer)) do
			local mult
			if hookFailed and CFG.petSpeed then
				local ok, base = pcall(pet.CalculateSpeedMultiplier, pet)
				mult = ((ok and type(base) == "number") and base or 1) * PET_SPEED_MULT
			else
				mult = pet:CalculateSpeedMultiplier()
			end
			pet.speedMult = mult
			pet.cpet:Broadcast("petSpeedMult", mult)
		end
	end)
end

local function setPetSpeed(enabled)
	if not PlayerPet or not PlayerPet.CalculateSpeedMultiplier then return false end

	if enabled then
		if not originalCalcSpeed and not hookFailed then
			local orig = PlayerPet.CalculateSpeedMultiplier
			-- the module table may be frozen; fall back to per-pet writes if so
			local ok = pcall(function()
				PlayerPet.CalculateSpeedMultiplier = function(self, ...)
					local good, base = pcall(orig, self, ...)
					if not good or type(base) ~= "number" then base = 1 end
					return base * PET_SPEED_MULT
				end
			end)
			if ok then
				originalCalcSpeed = orig
			else
				hookFailed = true
			end
		end

		-- frozen-table path: the game's 1s task resets speedMult, so out-pace it
		if hookFailed and not running.speed then
			running.speed = true
			task.spawn(function()
				while running.speed and CFG.petSpeed do
					pushPetSpeed()
					task.wait(0.4)
				end
				running.speed = false
			end)
		end
	else
		running.speed = false
		if originalCalcSpeed then
			pcall(function() PlayerPet.CalculateSpeedMultiplier = originalCalcSpeed end)
			originalCalcSpeed = nil
		end
	end

	pushPetSpeed()
	return true
end

--=============================================================================
-- loops
--=============================================================================

local function startAutoTap()
	if running.tap then return end
	running.tap = true

	task.spawn(function()
		local petTick = 0
		while running.tap do
			local ok = pcall(function()
				local targets = collectTargets()

				-- hit everything in the zone, no cap
				for i = 1, #targets do
					tap(targets[i].uid)
				end

				-- retargeting pets every tick thrashes them; ~2x a second is plenty
				petTick = petTick + 1
				if petTick >= 15 and #targets > 0 then
					petTick = 0
					assignPets(targets[1].model)
				end
			end)
			if not ok then task.wait(0.5) end
			task.wait(1 / TAP_RATE)
		end
	end)
end

local function stopAutoTap()
	running.tap = false
end

local function startAutoJoin()
	if running.join then return end
	running.join = true

	task.spawn(function()
		while running.join do
			pcall(function()
				if not (InstancingCmds and InstancingCmds.Enter) then return end

				-- Never yank the player out of a maze run. A raid is itself an
				-- instance, so entering the lobby mid-run would abandon it.
				if running.maze or currentRaid() then return end

				-- Already somewhere else instanced? Leave that alone too.
				if InstancingCmds.IsInInstance(CFG.instanceId) then return end
				if inInstance() then return end

				if not InstancingCmds.IsBusy() then
					InstancingCmds.Enter(CFG.instanceId)
				end
			end)
			task.wait(5)
		end
	end)
end

local function stopAutoJoin()
	running.join = false
end

--=============================================================================
-- auto collect orbs
--
-- OrbCmds' RenderStep recomputes the magnet reach every frame as
--   local v8 = Orb.DefaultPickupDistance + UpgradeCmds.GetPower("Magnet") + ...
--   local v9 = EnchantCmds.GetPower("Super Magnet") > 0
-- and hands both to Orb.RenderStepped. In there, if super magnet is on, any orb
-- past 150 studs is claimed outright (`Collect(nil, nil, true)`) and anything
-- closer gets unanchored with a 999999999 reach so it flies straight in.
-- So the whole feature is one boolean: make GetPower("Super Magnet") positive.
-- Widening DefaultPickupDistance is an independent fallback that still pulls
-- orbs in if the enchant hook somehow doesn't take. Collection itself still
-- goes out over the game's own Network.Fire("Orbs: Collect", ids) batch.
--=============================================================================

local EnchantCmds = need("EnchantCmds")

local origPickupDistance
local origEnchantPower

local function setAutoOrbs(enabled)
	local hooked = false

	if enabled then
		if Orb and origPickupDistance == nil and type(Orb.DefaultPickupDistance) == "number" then
			local saved = Orb.DefaultPickupDistance
			local ok = pcall(function() Orb.DefaultPickupDistance = 100000 end)
			if ok and Orb.DefaultPickupDistance ~= saved then
				origPickupDistance = saved
				hooked = true
			end
		end

		if EnchantCmds and type(EnchantCmds.GetPower) == "function" and origEnchantPower == nil then
			local orig = EnchantCmds.GetPower
			local patched
			patched = function(name, ...)
				if name == "Super Magnet" then
					local good, base = pcall(orig, name, ...)
					local n = (good and type(base) == "number") and base or 0
					return math.max(n, 1)
				end
				return orig(name, ...)
			end
			local ok = pcall(function() EnchantCmds.GetPower = patched end)
			if ok and EnchantCmds.GetPower == patched then
				origEnchantPower = orig
				hooked = true
			end
		end

		return hooked or origPickupDistance ~= nil or origEnchantPower ~= nil
	end

	if origPickupDistance ~= nil then
		pcall(function() Orb.DefaultPickupDistance = origPickupDistance end)
		origPickupDistance = nil
	end
	if origEnchantPower ~= nil then
		pcall(function() EnchantCmds.GetPower = origEnchantPower end)
		origEnchantPower = nil
	end
	return true
end

--=============================================================================
-- autofarm maze
--
-- Drives the same primitives the game's own (FFlag-gated) Auto Raid uses:
--   RaidCmds.Create{Portal=n, Difficulty=d, PartyMode=Solo}    -- start a run
--   ClientRaidInstance.GetCurrent() :GetRoomNumber() :IsComplete() ._ct
--   FiestaMazeCmds.PathCellModel(room) + TeleportCharacterTo   -- walk a room
--   Network.Invoke("Raids_CollectReward", chestKey, raid._ct)  -- open the eggs
-- Damage itself is the normal auto-tap path: maze breakables are
-- ParentType.Instance, so canMine() only asks whether we are in the raid.
--=============================================================================

local mazeStatus = "idle"

local function freePortal()
	if not (ClientRaid and ClientRaid.GetByPortal) then return 1 end
	for i = 1, 10 do
		local ok, taken = pcall(ClientRaid.GetByPortal, i)
		if ok and not taken then return i end
	end
	return nil
end

-- Create the raid AND join it. Create() only reserves the portal -- the game's
-- own Auto Raid follows it with raid:Join(), and leaves any instance it is
-- currently sitting in first (you cannot start a raid from inside the lobby).
local function startRun()
	if not (RaidCmds and RaidCmds.Create) then return false, "RaidCmds missing" end

	-- step out of the Fiesta lobby (or any instance) before creating
	if inInstance() and InstancingCmds and InstancingCmds.Leave then
		pcall(InstancingCmds.Leave, false, true)
		local deadline = os.clock() + 5
		while inInstance() and os.clock() < deadline do
			task.wait(0.25)
		end
	end

	local portal = freePortal()
	if not portal then return false, "no free portal" end

	local difficulty = 1
	if RaidCmds.GetDifficultyLevel then
		local ok, d = pcall(RaidCmds.GetDifficultyLevel)
		if ok and type(d) == "number" then difficulty = d end
	end

	local solo = RaidTypes and RaidTypes.PartyMode and RaidTypes.PartyMode.Solo

	local ok, res, err, raid = pcall(RaidCmds.Create, {
		Portal = portal,
		Difficulty = difficulty,
		PartyMode = solo,
	})
	if not ok then return false, tostring(res) end
	if not res then return false, tostring(err or "rejected") end
	if not raid then return false, "created but no raid returned" end

	-- this is what actually puts the character inside the maze
	local jok, jres, jerr = pcall(raid.Join, raid)
	if not jok then return false, tostring(jres) end
	if not jres then return false, tostring(jerr or "join refused") end

	return true
end

-- Open every non-retired chest -- the "open all the eggs at the end" step.
-- Deliberately does NOT teleport: the claim is a pure remote call and works
-- from wherever you are standing, so there is no reason to move the character.
-- The server can answer "isn't ready yet" for a few seconds after a run ends,
-- so retry on that specific refusal (same 15s window the game's own Auto Raid
-- uses) instead of quietly banking nothing.
local function openAllChests(raid)
	raid = raid or currentRaid()
	local ct = raid and raid._ct
	if not (ct and RaidTypes and RaidTypes.ChestDirectory) then return 0, 0 end

	local deadline = os.clock() + 15

	while true do
		local opened, attempted, notReady = 0, 0, false

		for key, chest in pairs(RaidTypes.ChestDirectory) do
			if not chest.Retired then
				attempted = attempted + 1
				local ok, res, why = pcall(Network.Invoke, "Raids_CollectReward", key, ct)
				if ok and res then
					opened = opened + 1
				elseif why and string.find(tostring(why), "isn't ready yet", 1, true) then
					notReady = true
				end
				task.wait(0.1)
			end
		end

		-- done once something landed, nothing is pending, or we ran out of time
		if opened > 0 or not notReady or os.clock() >= deadline then
			return opened, attempted
		end

		task.wait(1)
	end
end

--=============================================================================
-- moving through the maze
--
-- Maze breakables are ParentType.Instance, so canMine() only asks whether we
-- are inside the raid instance -- distance is irrelevant and we could damage
-- them from the spawn. But the maze only *spawns* the next room's breakables
-- once the client has opened that cell, so standing still stalls the run.
-- Hence: walk the character to the current room, exactly like the game's own
-- teleportToRoom() does (PathCellModel(room) -> TeleportCharacterTo).
--=============================================================================

local lastTeleport = 0

local function teleportTo(position)
	if not position then return false end
	if os.clock() - lastTeleport < 1.5 then return false end   -- don't spam it
	lastTeleport = os.clock()

	if TeleportTo then
		local ok = pcall(TeleportTo, position)
		if ok then return true end
	end

	local char = LocalPlayer.Character
	if char then
		return (pcall(char.PivotTo, char, CFrame.new(position + Vector3.new(0, 4, 0))))
	end
	return false
end

-- walk to the room the raid says we are on
local function moveToRoom(roomNumber)
	if not (FiestaMazeCmds and FiestaMazeCmds.PathCellModel and roomNumber) then return false end
	local ok, cell = pcall(FiestaMazeCmds.PathCellModel, roomNumber)
	if not (ok and cell) then return false end
	local good, pivot = pcall(cell.GetPivot, cell)
	if not (good and pivot) then return false end
	return teleportTo(pivot.Position)
end

local function startAutoMaze()
	if running.maze then return end
	running.maze = true

	task.spawn(function()
		local lastRaidId, cleared, lastRoom = nil, false, nil

		while running.maze do
			local ok = pcall(function()
				local raid = currentRaid()

				if not raid then
					-- between runs: start a fresh maze
					mazeStatus = "starting run"
					cleared = false
					lastRaidId, lastRoom = nil, nil
					local started, why = startRun()
					if not started then
						mazeStatus = "start failed: " .. tostring(why)
						task.wait(4)
					else
						task.wait(2)
					end
					return
				end

				local id = nil
				if raid.GetId then
					local good, res = pcall(raid.GetId, raid)
					if good then id = res end
				end
				if id ~= lastRaidId then
					lastRaidId = id
					cleared = false
					lastRoom = nil
				end

				local done = false
				if raid.IsComplete then
					local good, res = pcall(raid.IsComplete, raid)
					done = good and res == true
				end

				if done and not cleared then
					cleared = true
					mazeStatus = "run complete -- claiming"

					local n = openAllChests(raid)
					mazeStatus = string.format("opened %d chest(s)", n)
					if Weave then
						Weave:Notify({
							Title = "Fiesta Farm",
							Content = string.format("Maze done -- opened %d chest(s).", n),
							Duration = 4,
						})
					end
					task.wait(3)   -- let the server tear the raid down
				elseif done then
					-- already claimed this one. If the finished raid is still
					-- hanging around, kick off the next run anyway rather than
					-- waiting forever for it to disappear.
					mazeStatus = "starting next run"
					local started = startRun()
					task.wait(started and 3 or 5)
				else
					local room = nil
					if raid.GetRoomNumber then
						local good, r = pcall(raid.GetRoomNumber, raid)
						if good and type(r) == "number" then room = r end
					end
					mazeStatus = "farming room " .. (room and tostring(room) or "?")

					-- walk to this room so its breakables actually spawn; the
					-- server only materializes a cell once the client is there
					if room and room ~= lastRoom then
						if moveToRoom(room) then lastRoom = room end
					end

					-- then walk to the pinatas themselves. The room cell pivot is
					-- its centre, which can be a long way from where the breakables
					-- actually sit -- and pets have to physically reach a target to
					-- damage it, so standing in the middle of an empty cell farms
					-- nothing. Taps ignore distance; pets do not.
					local targets = collectTargets()
					local nearest = targets[1]
					if nearest and nearest.dist > 60 then
						local good, pivot = pcall(nearest.model.GetPivot, nearest.model)
						if good and pivot then
							if teleportTo(pivot.Position) then
								mazeStatus = string.format(
									"farming room %s (%d pinata(s))",
									room and tostring(room) or "?", #targets)
							end
						end
					end
				end
			end)

			if not ok then
				mazeStatus = "error -- retrying"
				task.wait(2)
			end
			task.wait(1)
		end

		mazeStatus = "idle"
	end)
end

local function stopAutoMaze()
	running.maze = false
end

--=============================================================================
-- fiesta maze upgrades
--
-- Mirrors "Fiesta Upgrade Machine": isMaxxed / getCost / canAfford, then
-- EventUpgradeCmds.Purchase(id). Purchase() invokes the server, which is the
-- authority -- if it says no we just try again next pass.
--=============================================================================

-- the 4 the machine actually sells; everything else is a passive track
local UPGRADE_IDS = (FiestaUpgrades and FiestaUpgrades.PurchasableOrder)
	or { "FiestaDamage", "FiestaSmashSpeed", "FiestaPets", "FiestaKeyDrops" }

local function upgradeDef(id)
	return UpgradeDir and UpgradeDir[id] or nil
end

local function upgradeName(id)
	local def = upgradeDef(id)
	return (def and def.Name) or id
end

local function upgradeTier(id)
	if not (EventUpgrades and EventUpgrades.GetTier) then return 0 end
	local ok, tier = pcall(EventUpgrades.GetTier, id)
	return (ok and type(tier) == "number") and tier or 0
end

local function isMaxxed(id)
	local def = upgradeDef(id)
	if not def then return false end
	return upgradeTier(id) >= #def.TierPowers
end

-- cost of the NEXT tier, with the live cost-multiplier FFlag applied
local function nextCost(id)
	local def = upgradeDef(id)
	if not def then return nil end

	local tier = upgradeTier(id)
	local entry = def.TierCosts[tier + 1]
	if not entry then return nil end

	local mult = 1
	if FFlags then
		local ok, v = pcall(function() return FFlags.Get(FFlags.Keys.PinataFiesta_UpgradeCostMult) end)
		if ok and type(v) == "number" then mult = math.max(1, v) end
	end

	local ok, item = pcall(function()
		local clone = entry:Clone()
		return clone:SetAmount(math.max(1, math.ceil(clone:GetAmount() * mult)))
	end)
	return ok and item or nil
end

local function canAfford(id)
	local item = nextCost(id)
	if not item then return false end
	local ok, have = pcall(item.CountAny, item)
	if not ok then return false end
	return have >= item:GetAmount()
end

local function orbCount()
	if not CurrencyItem then return nil end
	local ok, n = pcall(function() return CurrencyItem("FiestaOrbs"):CountAny() end)
	return ok and n or nil
end

-- one pass over the wanted list; returns how many purchases went through
local function buyWanted(notify)
	if not EventUpgrades then return 0 end
	local bought = 0

	for _, id in ipairs(UPGRADE_IDS) do
		if CFG.wanted[id] and not isMaxxed(id) then
			-- keep buying this one while it is affordable; tier moves each time
			for _ = 1, 25 do
				if isMaxxed(id) or not canAfford(id) then break end

				local ok, res = pcall(EventUpgrades.Purchase, id)
				if not (ok and res) then break end

				bought = bought + 1
				if notify then
					Weave:Notify({
						Title = "Fiesta Farm",
						Content = string.format("%s -> tier %d", upgradeName(id), upgradeTier(id)),
						Duration = 3,
					})
				end
				task.wait(0.25)   -- let the save replicate before re-reading tier
			end
		end
	end

	return bought
end

local function startAutoUpgrade()
	if running.upgrade then return end
	running.upgrade = true

	task.spawn(function()
		while running.upgrade do
			pcall(buyWanted, true)
			task.wait(3)
		end
	end)
end

local function stopAutoUpgrade()
	running.upgrade = false
end

--=============================================================================
-- pet spawner -- client-side visuals only
--
-- Pet art lives at __DIRECTORY.Pets.<Class>.<Name>: a ModuleScript holding a
-- "Pet" BasePart plus a "Golden" variant. Newer gargantuans nest both under a
-- "Holder" model instead. Cloning that part IS the whole visual -- the real
-- pets are driven by Library.Client.CustomPet, which we never touch.
--
-- Clones are parented to workspace.CurrentCamera, which is where the game puts
-- its own local-only preview models (see "Egg Opening Frontend"). Nothing here
-- replicates: no stats, no damage, no inventory, and nobody else can see them.
--=============================================================================

local RunService = game:GetService("RunService")

local PET_CLASSES = { "Titanic", "Gargantuan" }

-- classes we strip out of a clone: audio would loop forever and any script
-- would try to run the real pet logic against a model that has no owner
local function isJunk(inst)
	return inst:IsA("Sound")
		or inst:IsA("Script")
		or inst:IsA("LocalScript")
		or inst:IsA("ModuleScript")
end

local function petDirFolder()
	local dir = game:GetService("ReplicatedStorage"):FindFirstChild("__DIRECTORY")
	return dir and dir:FindFirstChild("Pets") or nil
end

-- { {name=, class=, source=ModuleScript}, ... } sorted, Titanic then Gargantuan
local PET_LIST, PET_BY_NAME = {}, {}

local function rebuildPetList()
	PET_LIST, PET_BY_NAME = {}, {}
	local root = petDirFolder()
	for _, class in ipairs(PET_CLASSES) do
		local folder = root and root:FindFirstChild(class)
		if folder then
			local kids = folder:GetChildren()
			table.sort(kids, function(a, b) return a.Name < b.Name end)
			for _, child in ipairs(kids) do
				local entry = { name = child.Name, class = class, source = child }
				table.insert(PET_LIST, entry)
				PET_BY_NAME[child.Name] = entry
				PET_BY_NAME[string.lower(child.Name)] = entry
			end
		end
	end
	return #PET_LIST
end

rebuildPetList()

-- the art is either a direct child or one level down inside "Holder"
local function findPetArt(source, golden)
	if not source then return nil end
	local wanted = golden and "Golden" or "Pet"

	local function pick(parent)
		local hit = parent:FindFirstChild(wanted)
		if hit and (hit:IsA("BasePart") or hit:IsA("Model")) then return hit end
		-- no golden variant for this pet: fall back to the normal one
		local base = parent:FindFirstChild("Pet")
		if base and (base:IsA("BasePart") or base:IsA("Model")) then return base end
		return nil
	end

	local direct = pick(source)
	if direct then return direct end

	local holder = source:FindFirstChild("Holder")
	return holder and pick(holder) or nil
end

-- FileMesh parts render at Mesh.Scale, ignoring Part.Size, so both have to be
-- scaled -- same thing the game's own AdminShows resize helper does. Multi-part
-- Holder models get Model:ScaleTo instead, which also fixes up the joint
-- offsets; scaling their parts individually would just blow the model apart.
local function scaleArt(inst, mult)
	if mult == 1 then return end

	if inst:IsA("Model") then
		local ok = pcall(inst.ScaleTo, inst, mult)
		if ok then return end
	end

	if inst:IsA("BasePart") then
		inst.Size = inst.Size * mult
	end
	for _, child in ipairs(inst:GetDescendants()) do
		if child:IsA("SpecialMesh") then
			child.Scale = child.Scale * mult
		elseif child:IsA("BasePart") then
			child.Size = child.Size * mult
		end
	end
end

local function buildVisual(entry, golden, mult)
	local art = findPetArt(entry.source, golden)
	if not art then return nil end

	local ok, clone = pcall(art.Clone, art)
	if not (ok and clone) then return nil end

	for _, child in ipairs(clone:GetDescendants()) do
		if isJunk(child) then
			pcall(child.Destroy, child)
		end
	end
	if isJunk(clone) then pcall(clone.Destroy, clone); return nil end

	for _, part in ipairs(clone:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Anchored = true
			part.CanCollide = false
			part.CanQuery = false
			part.CanTouch = false
			part.Massless = true
		end
	end
	if clone:IsA("BasePart") then
		clone.Anchored = true
		clone.CanCollide = false
		clone.CanQuery = false
		clone.CanTouch = false
		clone.Massless = true
	end

	pcall(scaleArt, clone, mult)
	clone.Name = "__SPAWNED_" .. entry.name
	return clone
end

local spawnedPets = {}   -- { {inst=, height=}, ... }
local orbitConn

local function artSize(inst)
	if inst:IsA("BasePart") then return inst.Size end
	local ok, size = pcall(inst.GetExtentsSize, inst)
	return (ok and size) or Vector3.new(6, 6, 6)
end

local function setArtCFrame(inst, cf)
	if inst:IsA("BasePart") then
		inst.CFrame = cf
	else
		pcall(inst.PivotTo, inst, cf)
	end
end

--=============================================================================
-- fake inventory entries
--
-- The client inventory is a Container wrapping a SimpleStore over
-- Save.Get(player).Inventory (Library.Client.InventoryCmds -> ClientPlayerState).
-- store:SetReference(uid, item) is pure local table work -- it fills _byUID,
-- _byType, _byStack and the backing data table -- so writing to it puts a pet
-- in the inventory GUI without a single remote call. Firing container.Updated
-- is what makes the GUI redraw: GUIs.Inventory hooks Container:UpdatedCallback,
-- which compares the type store's iteration counter, and SetReference bumps it.
--
-- The server never sees these. Anything that asks the server about one (equip,
-- trade, sell, delete) is simply refused, and a save update from the server can
-- wipe them. They are there to look at.
--=============================================================================

local InventoryCmds = need("InventoryCmds")
local ItemsLib      = needAt(Lib, "Items")
local PetsDir       = needAt(Lib:FindFirstChild("Directory"), "Pets")
local Constants     = needAt(Lib:FindFirstChild("Balancing"), "Constants")

local function inventoryContainer()
	if not (InventoryCmds and InventoryCmds.Container) then return nil end
	local ok, container = pcall(InventoryCmds.Container)
	return ok and container or nil
end

-- Directory.Pets has an __index that *errors* on unknown keys, so never index
-- it directly to test for a pet -- rawget reads the real entry or nil.
local function petDirEntry(name)
	if not PetsDir then return nil end
	local ok, entry = pcall(rawget, PetsDir, name)
	return ok and entry or nil
end

local function makePetItem(name, golden)
	if not (ItemsLib and ItemsLib.Pet) then return nil, "Items library unavailable" end

	local ok, item = pcall(ItemsLib.Pet, name)
	if not (ok and item) then return nil, "no directory entry for " .. tostring(name) end

	-- golden is a pet *type*, and some pets explicitly forbid it
	local dir = petDirEntry(name)
	if golden and Constants and Constants.PetTypes and not (dir and dir.preventGolden) then
		pcall(item.SetType, item, Constants.PetTypes.Golden)
	end

	if not pcall(item.PopulateUID, item) then return nil, "could not generate a UID" end

	local gotUid, uid = pcall(item.GetUID, item)
	if not (gotUid and uid) then return nil, "could not read the UID" end

	-- items sitting in a store are tracked; harmless if the build disagrees
	pcall(item.SetTracked, item, true)
	return item, uid
end

-- redraw the inventory GUI. Updated carries the store, matching what a real
-- transaction commit fires.
local function refreshInventoryGUI(container)
	container = container or inventoryContainer()
	if not (container and container.Updated) then return end
	pcall(function()
		container.Updated:FireAsync(container._store)
	end)
end

local fakeUids = {}   -- uids we put there, so we can take them back out

-- returns uid, err
local function addToInventory(name, golden)
	local container = inventoryContainer()
	if not container then return nil, "inventory not ready" end

	local store = container._store
	if not (store and store.SetReference) then return nil, "inventory store unavailable" end

	local item, uidOrErr = makePetItem(name, golden)
	if not item then return nil, uidOrErr end

	local ok, err = pcall(store.SetReference, store, uidOrErr, item)
	if not ok then return nil, tostring(err) end

	table.insert(fakeUids, uidOrErr)
	refreshInventoryGUI(container)
	return uidOrErr
end

local function removeFromInventory(uid)
	if not uid then return false end

	local container = inventoryContainer()
	local store = container and container._store
	if not (store and store.SetReference) then return false end

	local ok = pcall(store.SetReference, store, uid, nil)

	for i = #fakeUids, 1, -1 do
		if fakeUids[i] == uid then table.remove(fakeUids, i) end
	end

	if ok then refreshInventoryGUI(container) end
	return ok
end

local function clearInventoryAdds()
	local container = inventoryContainer()
	local store = container and container._store
	local n = 0

	if store and store.SetReference then
		for _, uid in ipairs(fakeUids) do
			if pcall(store.SetReference, store, uid, nil) then n = n + 1 end
		end
		if n > 0 then refreshInventoryGUI(container) end
	end

	fakeUids = {}
	return n
end

local function clearPets()
	if orbitConn then orbitConn:Disconnect(); orbitConn = nil end
	for _, e in ipairs(spawnedPets) do
		if e.inst then pcall(e.inst.Destroy, e.inst) end
		if e.uid then removeFromInventory(e.uid) end
	end
	spawnedPets = {}
end

local ORBIT_SPEED = 0.6

local function startOrbit()
	if orbitConn then return end
	orbitConn = RunService.RenderStepped:Connect(function()
		local n = #spawnedPets
		if n == 0 then return end

		local char = LocalPlayer.Character
		local root = char and char:FindFirstChild("HumanoidRootPart")
		if not root then return end

		-- ring wide enough that the models do not intersect each other; these
		-- things are enormous natively, so space off the biggest one. Sizes are
		-- measured once at spawn -- GetExtentsSize on 70 models every frame is
		-- not something to do in RenderStepped.
		local widest = 0
		for _, e in ipairs(spawnedPets) do
			if e.inst and e.inst.Parent then
				widest = math.max(widest, e.width)
			end
		end
		local radius = math.max(10, widest * 0.7 + n * 1.5)

		local now = os.clock()
		local look = root.CFrame.LookVector
		local step = math.pi * 2 / n

		for i, e in ipairs(spawnedPets) do
			local inst = e.inst
			if inst and inst.Parent then
				local a = (i - 1) * step + now * ORBIT_SPEED
				local bob = math.sin(now * 2 + i) * 1.5
				local pos = root.Position + Vector3.new(
					math.cos(a) * radius,
					e.height + bob,
					math.sin(a) * radius
				)
				setArtCFrame(inst, CFrame.lookAt(pos, pos + look))
			end
		end
	end)
end

-- returns spawned, reason
local function spawnPet(name, golden, mult, count, toInventory)
	local entry = PET_BY_NAME[name] or PET_BY_NAME[string.lower(tostring(name))]
	if not entry then return 0, "unknown pet '" .. tostring(name) .. "'" end

	local made = 0
	for _ = 1, math.max(1, count or 1) do
		local visual = buildVisual(entry, golden, mult or 1)
		if not visual then break end
		visual.Parent = workspace.CurrentCamera
		local size = artSize(visual)

		-- each visual gets its own inventory row, so removing one visual takes
		-- exactly one row with it
		local uid = nil
		if toInventory then
			uid = addToInventory(entry.name, golden)
		end

		table.insert(spawnedPets, {
			inst   = visual,
			uid    = uid,
			height = size.Y * 0.5,
			width  = math.max(size.X, size.Z),
		})
		made = made + 1
	end

	if made == 0 then return 0, "no art found for " .. entry.name end
	startOrbit()
	return made
end

local function removeLastPet()
	local e = table.remove(spawnedPets)
	if not e then return false end
	if e.inst then pcall(e.inst.Destroy, e.inst) end
	if e.uid then removeFromInventory(e.uid) end
	if #spawnedPets == 0 and orbitConn then
		orbitConn:Disconnect(); orbitConn = nil
	end
	return true
end

--=============================================================================
-- UI
--=============================================================================

Weave = loadstring(game:HttpGet("https://raw.githubusercontent.com/SvenaEE/Testlibary-/refs/heads/main/Weave-Release"))()

local Window = Weave:CreateWindow({
	Name = "Fiesta Farm",
	LoadingSubtitle = "Pet Sim 99",
	ConfigurationSaving = { Enabled = true, FileName = "FiestaFarm" },
	KeySystem = false,
	ToggleKey = Enum.KeyCode.RightShift,
})

local MainTab = Window:CreateTab("Farm", "skull", { "Tapping", "Pets", "Event" })

--------------------------------------------------------------------- Tapping
local TapSec = MainTab:CreateSection({ Name = "Auto Tap", Side = "left", Subtab = "Tapping" })

TapSec:CreateToggle({
	Name = "Auto Tap",
	CurrentValue = false,
	Flag = "auto_tap",
	Callback = function(v)
		CFG.autoTap = v
		if v then startAutoTap() else stopAutoTap() end
	end,
})

TapSec:CreateToggle({
	Name = "Send pets to targets",
	CurrentValue = true,
	Flag = "pet_send",
	Callback = function(v) CFG.sendPets = v end,
})

TapSec:CreateToggle({
	Name = "Auto Collect Orbs",
	CurrentValue = false,
	Flag = "auto_orbs",
	Callback = function(v)
		CFG.autoOrbs = v
		if not setAutoOrbs(v) then
			Weave:Notify({ Title = "Fiesta Farm", Content = "OrbCmds unavailable.", Duration = 5 })
		end
	end,
})

TapSec:CreateButton({
	Name = "Count breakables",
	Callback = function()
		local n = #collectTargets()
		Weave:Notify({ Title = "Fiesta Farm", Content = n .. " target(s) here.", Duration = 4 })
	end,
})

local TapInfo = MainTab:CreateSection({ Name = "Info", Side = "right", Subtab = "Tapping" })
local TapStatus = TapInfo:CreateParagraph({
	Title = "Status",
	Content = "Idle.",
})

TapInfo:CreateParagraph({
	Title = "How it works",
	Content = "Fires Breakables_PlayerDealDamage at EVERY breakable you are "
		.. "allowed to damage, at max rate, skipping the 8/s client cap. Works "
		.. "in the overworld and inside the maze. Pets do most of the real "
		.. "damage, so leave 'Send pets' on. Orbs are pulled in by forcing the "
		.. "game's own super-magnet path.",
})

--------------------------------------------------------------------- Pets
local PetSec = MainTab:CreateSection({ Name = "Pets", Side = "left", Subtab = "Pets" })

PetSec:CreateToggle({
	Name = "Infinite Pet Speed",
	CurrentValue = false,
	Flag = "pet_speed",
	Callback = function(v)
		CFG.petSpeed = v
		if not setPetSpeed(v) then
			Weave:Notify({ Title = "Fiesta Farm", Content = "PlayerPet unavailable.", Duration = 5 })
		end
	end,
})

local PetInfo = MainTab:CreateSection({ Name = "Note", Side = "right", Subtab = "Pets" })
PetInfo:CreateParagraph({
	Title = "Speed is visual-ish",
	Content = "Runs at max (" .. PET_SPEED_MULT .. "x). Pet movement speed is "
		.. "client-side: pets reach targets instantly, but damage per hit does "
		.. "not change. Nothing to tune, it is already flat out.",
})

--------------------------------------------------------------------- Event
local EventSec = MainTab:CreateSection({ Name = "Pinata Event", Side = "left", Subtab = "Event" })

EventSec:CreateToggle({
	Name = "Auto join Fiesta Lobby",
	CurrentValue = false,
	Flag = "auto_join",
	Callback = function(v)
		CFG.autoJoin = v
		if v then startAutoJoin() else stopAutoJoin() end
	end,
})

EventSec:CreateButton({
	Name = "Join now",
	Callback = function()
		local ok = pcall(function() InstancingCmds.Enter(CFG.instanceId) end)
		Weave:Notify({
			Title = "Fiesta Farm",
			Content = ok and "Entering Fiesta Lobby..." or "Could not enter.",
			Duration = 4,
		})
	end,
})

EventSec:CreateParagraph({
	Title = "Note",
	Content = "Auto join stands down while you are in a maze run, so it will "
		.. "never pull you out of one.",
})

--------------------------------------------------------------------- Maze
local MazeSec = MainTab:CreateSection({ Name = "Maze", Side = "left", Subtab = "Event" })

MazeSec:CreateToggle({
	Name = "AutoFarm Maze",
	CurrentValue = false,
	Flag = "auto_maze",
	Callback = function(v)
		CFG.autoMaze = v
		if v then startAutoMaze() else stopAutoMaze() end
	end,
})

MazeSec:CreateButton({
	Name = "Start a run now",
	Callback = function()
		task.spawn(function()
			local ok, why = startRun()
			Weave:Notify({
				Title = "Fiesta Farm",
				Content = ok and "Maze run started." or ("Could not start: " .. tostring(why)),
				Duration = 4,
			})
		end)
	end,
})

MazeSec:CreateButton({
	Name = "Open all chests now",
	Callback = function()
		task.spawn(function()
			-- no teleport: claiming is a plain remote call, it works in place
			local n = openAllChests()
			Weave:Notify({
				Title = "Fiesta Farm",
				Content = n > 0 and (n .. " chest(s) opened.") or "No chests claimed -- not in a finished run?",
				Duration = 4,
			})
		end)
	end,
})

local MazeInfo = MainTab:CreateSection({ Name = "Maze Info", Side = "right", Subtab = "Event" })
local MazeStatus = MazeInfo:CreateParagraph({ Title = "Status", Content = "Idle." })

MazeInfo:CreateParagraph({
	Title = "How it works",
	Content = "Starts a solo run on the first free portal, walks you to each "
		.. "room so its breakables spawn, then claims every chest in place and "
		.. "starts the next run. Chests are claimed without teleporting. Turn "
		.. "Auto Tap on too -- that is what does the breaking.",
})

--------------------------------------------------------------- auto upgrade
local UpgSec = MainTab:CreateSection({ Name = "Maze Upgrades", Side = "right", Subtab = "Event" })

UpgSec:CreateToggle({
	Name = "Auto buy selected",
	CurrentValue = false,
	Flag = "auto_upgrade",
	Callback = function(v)
		CFG.autoUpgrade = v
		if v then startAutoUpgrade() else stopAutoUpgrade() end
	end,
})

UpgSec:CreateDivider()

for _, id in ipairs(UPGRADE_IDS) do
	UpgSec:CreateToggle({
		Name = upgradeName(id),
		CurrentValue = false,
		Flag = "upg_" .. id,
		Callback = function(v) CFG.wanted[id] = v or nil end,
	})
end

UpgSec:CreateDivider()

UpgSec:CreateButton({
	Name = "Buy once now",
	Callback = function()
		-- buyWanted yields between purchases; keep it off the UI thread
		task.spawn(function()
			local n = buyWanted(false)
			Weave:Notify({
				Title = "Fiesta Farm",
				Content = n > 0 and (n .. " upgrade(s) bought.") or "Nothing bought -- not enough orbs, maxed, or none selected.",
				Duration = 4,
			})
		end)
	end,
})

local UpgStatus = UpgSec:CreateParagraph({ Title = "Tiers", Content = "Nothing selected." })

--------------------------------------------------------------- PetSpawner tab
local SpawnTab = Window:CreateTab("PetSpawner", "cat", { "Spawn", "Info" })

local pickedClass = PET_CLASSES[1]
local pickedPet   = nil
local pickedGold  = false
local pickedScale = 1
local pickedCount = 1
local pickedInv   = false

-- names of one class only -- the Pet dropdown is refilled from this whenever
-- the class changes, so you pick Titanic or Gargantuan first and then only see
-- that class's pets instead of scrolling one ~400-entry list.
local function namesOfClass(class)
	local out = {}
	for _, e in ipairs(PET_LIST) do
		if e.class == class then table.insert(out, e.name) end
	end
	return out
end

local function firstOfClass(class)
	for _, e in ipairs(PET_LIST) do
		if e.class == class then return e.name end
	end
	return nil
end

pickedPet = firstOfClass(pickedClass)

local SpawnSec = SpawnTab:CreateSection({ Name = "Spawn a pet", Side = "left", Subtab = "Spawn" })

local SpawnDrop   -- forward declaration: the class callback refreshes it

SpawnSec:CreateDropdown({
	Name = "Class",
	Options = PET_CLASSES,
	CurrentOption = pickedClass,
	Flag = "spawn_class",
	Callback = function(opt)
		pickedClass = type(opt) == "table" and opt[1] or opt
		pickedPet = firstOfClass(pickedClass)
		if SpawnDrop and SpawnDrop.Refresh then
			pcall(SpawnDrop.Refresh, SpawnDrop, namesOfClass(pickedClass))
		end
	end,
})

SpawnDrop = SpawnSec:CreateDropdown({
	Name = "Pet",
	Options = namesOfClass(pickedClass),
	CurrentOption = pickedPet,
	Flag = "spawn_pet",
	Callback = function(opt)
		-- Weave hands back the string; tolerate a table in case the build
		-- returns multi-select style
		pickedPet = type(opt) == "table" and opt[1] or opt
	end,
})

SpawnSec:CreateToggle({
	Name = "Golden variant",
	CurrentValue = false,
	Flag = "spawn_golden",
	Callback = function(v) pickedGold = v end,
})

SpawnSec:CreateToggle({
	Name = "Add to inventory",
	CurrentValue = false,
	Flag = "spawn_inventory",
	Callback = function(v) pickedInv = v end,
})

SpawnSec:CreateSlider({
	Name = "Size",
	Range = { 0.5, 10 },
	Increment = 0.5,
	CurrentValue = 1,
	Flag = "spawn_scale",
	Callback = function(v) pickedScale = v end,
})

SpawnSec:CreateSlider({
	Name = "How many",
	Range = { 1, 25 },
	Increment = 1,
	CurrentValue = 1,
	Flag = "spawn_count",
	Callback = function(v) pickedCount = v end,
})

SpawnSec:CreateButton({
	Name = "Spawn",
	Callback = function()
		if not pickedPet then
			Weave:Notify({ Title = "PetSpawner", Content = "Pick a pet first.", Duration = 4 })
			return
		end
		local made, why = spawnPet(pickedPet, pickedGold, pickedScale, pickedCount, pickedInv)
		Weave:Notify({
			Title = "PetSpawner",
			Content = made > 0
				and string.format("Spawned %dx %s.%s", made, pickedPet,
					pickedInv and " Added to inventory." or "")
				or ("Failed: " .. tostring(why)),
			Duration = 4,
		})
	end,
})

SpawnSec:CreateButton({
	Name = "Remove last",
	Callback = function()
		local ok = removeLastPet()
		Weave:Notify({
			Title = "PetSpawner",
			Content = ok and ("Removed. " .. #spawnedPets .. " left.") or "Nothing spawned.",
			Duration = 3,
		})
	end,
})

SpawnSec:CreateButton({
	Name = "Clear all",
	Callback = function()
		local n = #spawnedPets
		clearPets()
		Weave:Notify({ Title = "PetSpawner", Content = "Cleared " .. n .. " pet(s).", Duration = 3 })
	end,
})

local RandomSec = SpawnTab:CreateSection({ Name = "Shortcuts", Side = "right", Subtab = "Spawn" })

local function spawnRandomOf(class)
	local pool = namesOfClass(class)
	if #pool == 0 then
		Weave:Notify({ Title = "PetSpawner", Content = "No " .. class .. " art found.", Duration = 4 })
		return
	end
	local name = pool[math.random(1, #pool)]
	local made, why = spawnPet(name, pickedGold, pickedScale, pickedCount, pickedInv)
	Weave:Notify({
		Title = "PetSpawner",
		Content = made > 0 and string.format("Spawned %dx %s.", made, name) or ("Failed: " .. tostring(why)),
		Duration = 4,
	})
end

RandomSec:CreateButton({ Name = "Random Titanic",    Callback = function() spawnRandomOf("Titanic") end })
RandomSec:CreateButton({ Name = "Random Gargantuan", Callback = function() spawnRandomOf("Gargantuan") end })

RandomSec:CreateDivider()

RandomSec:CreateButton({
	Name = "Reload pet list",
	Callback = function()
		local n = rebuildPetList()
		if SpawnDrop and SpawnDrop.Refresh then
			pcall(SpawnDrop.Refresh, SpawnDrop, namesOfClass(pickedClass))
		end
		pickedPet = firstOfClass(pickedClass)
		Weave:Notify({ Title = "PetSpawner", Content = n .. " pet(s) found.", Duration = 4 })
	end,
})

RandomSec:CreateButton({
	Name = "One of every (selected class)",
	Callback = function()
		task.spawn(function()
			local class = pickedClass
			local made = 0
			for _, e in ipairs(PET_LIST) do
				if e.class == class then
					made = made + (spawnPet(e.name, pickedGold, pickedScale, 1, pickedInv))
					task.wait()   -- hundreds of big models: yield so the frame does not hitch
				end
			end
			Weave:Notify({
				Title = "PetSpawner",
				Content = string.format("Spawned %d %s pet(s).", made, class),
				Duration = 5,
			})
		end)
	end,
})

RandomSec:CreateDivider()

RandomSec:CreateButton({
	Name = "Clear inventory adds",
	Callback = function()
		local n = clearInventoryAdds()
		-- the visuals stay; only the inventory rows go, so forget the uids we
		-- just removed or removing a visual later would clear a live row
		for _, e in ipairs(spawnedPets) do e.uid = nil end
		Weave:Notify({
			Title = "PetSpawner",
			Content = "Removed " .. n .. " inventory entr" .. (n == 1 and "y." or "ies."),
			Duration = 4,
		})
	end,
})

local SpawnInfo = SpawnTab:CreateSection({ Name = "Spawned", Side = "left", Subtab = "Info" })
local SpawnStatus = SpawnInfo:CreateParagraph({ Title = "Status", Content = "Nothing spawned." })

SpawnInfo:CreateParagraph({
	Title = "Read this",
	Content = "These are visuals ONLY, and only you can see them. Each one is a "
		.. "clone of the pet's art from ReplicatedStorage parented to your camera "
		.. "-- it deals no damage, gives no stats, and does not replicate to the "
		.. "server or to other players. Nothing here touches the real pet system. "
		.. "Sounds and scripts are stripped from the clones, so they are silent "
		.. "and inert.",
})

SpawnInfo:CreateParagraph({
	Title = "About 'Add to inventory'",
	Content = "This writes the pet straight into your local inventory table, so "
		.. "it shows up in the Inventory GUI like a real one. It is still local "
		.. "only: the server has no idea it exists. Equipping, trading, selling "
		.. "or deleting it will be refused by the server, and it disappears the "
		.. "moment the server pushes a save update or you rejoin. Use 'Clear "
		.. "inventory adds' to take the rows back out yourself.",
})

local function upgradeSummary()
	local lines = {}
	for _, id in ipairs(UPGRADE_IDS) do
		if CFG.wanted[id] then
			local def = upgradeDef(id)
			local cap = def and #def.TierPowers or "?"
			local cost = nextCost(id)
			local price = "max"
			if cost then
				local ok, amt = pcall(cost.GetAmount, cost)
				price = ok and tostring(amt) or "?"
			end
			table.insert(lines, string.format("%s  %d/%s  (next: %s)",
				upgradeName(id), upgradeTier(id), tostring(cap), price))
		end
	end

	local orbs = orbCount()
	local head = "Fiesta Orbs: " .. (orbs and tostring(orbs) or "?")
	if #lines == 0 then return head .. "\nNothing selected." end
	return head .. "\n" .. table.concat(lines, "\n")
end

--------------------------------------------------------------------- status
task.spawn(function()
	while task.wait(1) do
		local ok = pcall(function()
			local n = #collectTargets()
			local zone = tostring(currentParentId() or "?")
			TapStatus:Set("Status", string.format(
				"%s | zone: %s | targets: %d | pets: %s",
				running.tap and "Farming" or "Idle", zone, n,
				CFG.petSpeed and (PET_SPEED_MULT .. "x") or "normal"
			))
			UpgStatus:Set("Tiers", upgradeSummary())

			local room = "-"
			local raid = currentRaid()
			if raid and raid.GetRoomNumber then
				local good, r = pcall(raid.GetRoomNumber, raid)
				if good and r then room = tostring(r) end
			end
			MazeStatus:Set("Status", string.format("%s | room: %s | orbs: %s",
				mazeStatus, room, CFG.autoOrbs and "auto" or "off"))

			-- drop any clone that lost its parent (camera reset, respawn, etc.)
			for i = #spawnedPets, 1, -1 do
				local e = spawnedPets[i]
				if not (e.inst and e.inst.Parent) then table.remove(spawnedPets, i) end
			end
			SpawnStatus:Set("Status", string.format(
				"%d spawned | %s: %d of %d pet(s) | inventory: %d",
				#spawnedPets, pickedClass, #namesOfClass(pickedClass), #PET_LIST, #fakeUids))
		end)
		if not ok then break end
	end
end)

Weave:Notify({
	Title = "Fiesta Farm",
	Content = "Loaded. Enable Auto Tap under Farm > Tapping.",
	Duration = 6,
})
Verified Executor Compatibility

Features of VibeCoded Sloppy Pet sim 99 pet spawner and farmer OPENSOURCE Script

The VibeCoded Sloppy Pet sim 99 pet spawner and farmer OPENSOURCE script is an optimized Lua execution payload designed for Roblox players. Built to minimize FPS drops and prevent crashes, it provides essential automated functions:

  • Auto Farm & Level Grinding: Automatically cycles quests and mobs with efficient positioning algorithms.
  • Aimbot & ESP: Accurate enemy targeting and wall visibility for items, chests and players.
  • Teleportation: Seamless movement across game checkpoints, safe zones and dungeons.
  • Direct Keyless Loadstring: Executes directly without third-party key verification links.

How to Execute This Script on Mobile & PC

Follow these steps depending on your platform:

Mobile (Android / iOS)

  1. Install Arceus X NEO or Delta Mobile.
  2. Launch the game inside the executor environment.
  3. Open the floating executor console.
  4. Paste the Lua script copied from above.
  5. Click Execute.

PC (Windows)

  1. Launch your PC exploit (such as Synapse X, KRNL, or Xeno).
  2. Join the Roblox game server.
  3. Click Inject / Attach.
  4. Paste the copied script into the script tab.
  5. Press Execute to run the menu.

Frequently Asked Questions (FAQ)

Is the VibeCoded Sloppy Pet sim 99 pet spawner and farmer OPENSOURCE script free and keyless?

Yes, this script payload is verified to be 100% free and keyless without linkvertise checkpoints.

Which executors support this script?

Compatible with Arceus X, Delta, Arceus X, Synapse X, KRNL, Fluxus and Xeno.

How do I execute this script safely?

Copy the script payload using the Copy button above, launch your Roblox executor on PC or Mobile, attach to the game client, paste the payload into the editor, and press Execute.

Related & Recommended Scripts