sinrashed

My Restaurant! Auto Farm *VERY OP!!*

Oct 22nd, 2022
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 54.00 KB | None | 0 0
  1. -- Open raw and click Ctrl + A to select the whole script --
  2. local fpsBoost = fpsBoost or false
  3.  
  4.  
  5. if not getconnections then return end
  6. for i,v in next, getconnections(game.Players.LocalPlayer.Idled) do
  7. v:Disable()
  8. end
  9.  
  10. local c = workspace:WaitForChild("__DEBRIS",10)
  11. c.ChildAdded:Connect(function(ch)
  12. task.wait()
  13. if fpsBoost then
  14. ch:Destroy()
  15. end
  16. end)
  17.  
  18. local petNet = loadstring(game:HttpGet("https://rawscripts.net/raw/Pet-Simulator-X!-PSX-Safe-Networking-3732"))()
  19.  
  20. local Food = petNet:getPath("Food")
  21. local Entity = petNet:getPath("Entity")
  22. local Customer = petNet:getPath("Customer")
  23. local Waiter = petNet:getPath("Waiter")
  24. local Appliance = petNet:getPath("Appliance")
  25. local Bakery = petNet:getPath("Bakery")
  26. local player = game:GetService("Players").LocalPlayer
  27.  
  28. local _L = require(game:GetService("ReplicatedStorage"):WaitForChild("Framework",10):WaitForChild("Library",10));
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. Food.RandomFoodChoice = function(customerOwnerUID, customerOwnerID, isRichCustomer, isPirateCustomer, isNearTree)
  37. local spoof = Food.new("45", customerOwnerUID, customerOwnerID, true, true)
  38. spoof.IsGold = true
  39. return spoof
  40. end
  41.  
  42. function Entity:FadeTransparency(targetTransparency, finishedCallback)
  43.  
  44. local processedCallback = false
  45.  
  46. for _, child in ipairs(self.model:GetDescendants()) do
  47. if child.Name == "HumanoidRootPart" or child.Name == "CenterPart" or not child:IsA("BasePart") then
  48. continue
  49. end
  50. if child.Name == "Head" and self.ID == "25" then
  51. continue
  52. end
  53. _L.Functions.FastTween(
  54. child,
  55. {Transparency = targetTransparency},
  56. {0.0000002, "Quad", "Out"}
  57. ).Completed:Connect(function()
  58. -- race condition? god I hope not
  59. if finishedCallback and not processedCallback then
  60. processedCallback = true
  61. finishedCallback()
  62. end
  63. end)
  64. end
  65.  
  66. end
  67.  
  68.  
  69. function Entity:WalkThroughWaypoints(voxelpoints, waypoints, startX, startZ)
  70. self:PlayLoadedAnimation("walking")
  71.  
  72. if #voxelpoints == 0 then
  73. return
  74. end
  75.  
  76. if not self:BelongsToMyBakery() and self.stateData.walkingThroughWaypoints then
  77. repeat wait() until self.isDeleted or not self.stateData.walkingThroughWaypoints
  78. if self.isDeleted then
  79. return
  80. end
  81. end
  82. if not self:BelongsToMyBakery() then
  83. self.stateData.walkingThroughWaypoints = true
  84. end
  85.  
  86. -- replication fix?
  87. if not self:BelongsToMyBakery() then
  88. self.model.HumanoidRootPart.Anchored = false
  89. end
  90.  
  91. for i, v in ipairs(waypoints) do
  92.  
  93. self.model.HumanoidRootPart.CFrame = CFrame.new(v)
  94. --self.humanoid.MoveToFinished:Wait()
  95. local oldX, oldZ = self.xVoxel, self.zVoxel
  96. self.xVoxel = voxelpoints[i].x
  97. self.zVoxel = voxelpoints[i].y
  98.  
  99. -- no need for position table updates if it's not my client.
  100. -- only the owner of the bakery does pathfinding calculations.
  101. -- if replication occurs, the host client sends the pathfinding
  102. -- data.... it is not recalculated
  103. if self:BelongsToMyBakery() then
  104. self:GetMyFloor():BroadcastNPCPositionChange(self, oldX, oldZ)
  105. end
  106. end
  107.  
  108. if not self:BelongsToMyBakery() then
  109. self.stateData.walkingThroughWaypoints = false
  110. end
  111.  
  112. self:StopLoadedAnimation("walking")
  113. self:PlayLoadedAnimation("idle")
  114. end
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121. function Customer:ChangeToWaitForOrderState()
  122.  
  123. if self.state ~= "WalkingToSeat" then
  124. return
  125. end
  126.  
  127. local seatLeaf = self:EntityTable()[self.stateData.seatUID]
  128. local tableLeaf = self:EntityTable()[self.stateData.tableUID]
  129.  
  130. if seatLeaf.isDeleted or tableLeaf.isDeleted then
  131. self:ForcedToLeave()
  132. return
  133. end
  134.  
  135. self:SetCustomerState("ThinkingAboutOrder")
  136.  
  137. -- make the humanoid sit
  138. self:SitInSeat(seatLeaf).Completed:Connect(function()
  139. self.humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, true)
  140.  
  141. -- change voxel position to match the seat
  142. self.xVoxel = seatLeaf.xVoxel
  143. self.zVoxel = seatLeaf.zVoxel
  144.  
  145. coroutine.wrap(function()
  146.  
  147. -- start reading the menu
  148. self:ReadMenu()
  149. if self.isDeleted or self.state ~= "ThinkingAboutOrder" then
  150. return
  151. end
  152.  
  153. -- stop reading the menu
  154. self:StopReadingMenu()
  155.  
  156. -- advance to next state
  157. self:SetCustomerState("DecidedOnOrder")
  158.  
  159. -- only set my entire group to ready to order when everybody has decided on the order
  160. local myGroup = {self}
  161. for _, partner in ipairs(self.stateData.queueGroup) do
  162. if not partner.isDeleted then
  163. table.insert(myGroup, partner)
  164. end
  165. end
  166. local foundUndecidedMember = false
  167. for _, groupMember in ipairs(myGroup) do
  168. if groupMember.state ~= "DecidedOnOrder" then
  169. foundUndecidedMember = true
  170. break
  171. end
  172. end
  173.  
  174. -- if the entire group is ready, then have them say it in sync
  175. if not foundUndecidedMember then
  176. for _, groupMember in ipairs(myGroup) do
  177. groupMember:ReadyToOrder()
  178. end
  179. end
  180.  
  181. end)()
  182. end)
  183.  
  184. end
  185.  
  186.  
  187. function Customer:ChangeToEatingState()
  188.  
  189. coroutine.wrap(function()
  190. if self.state == "EatingFood" then
  191. return
  192. end
  193.  
  194. -- first, check for silverware
  195. local myFloor = self:GetMyFloor()
  196. table.sort(myFloor.silverwareTrays, function(a, b)
  197. local aDist = math.abs(self.xVoxel - a.xVoxel) + math.abs(self.zVoxel - a.zVoxel)
  198. local bDist = math.abs(self.xVoxel - b.xVoxel) + math.abs(self.zVoxel - b.zVoxel)
  199. return aDist < bDist
  200. end)
  201. table.sort(myFloor.goldSilverwareTrays, function(a, b)
  202. local aDist = math.abs(self.xVoxel - a.xVoxel) + math.abs(self.zVoxel - a.zVoxel)
  203. local bDist = math.abs(self.xVoxel - b.xVoxel) + math.abs(self.zVoxel - b.zVoxel)
  204. return aDist < bDist
  205. end)
  206.  
  207. self:SetCustomerState("EatingFood")
  208.  
  209. -- if there's a path to me, delete it
  210. if self.stateData.pathToMe then
  211. _L.Variables.MyBakery:CleanupAnimatedPath()
  212. self.stateData.pathToMe = nil
  213. end
  214.  
  215. local didSaladCheck = false
  216. local function checkForSaladBars(isWalkingFromSilverware, doWalkBackToSeat)
  217. didSaladCheck = true
  218. local didWalkToSalad = false
  219. -- walk to salad bar sometimes
  220. local isWalkingToSaladBar = false
  221. for _, saladBar in ipairs(myFloor.saladBars) do
  222. if math.random() < 0.20 then
  223.  
  224. if not isWalkingFromSilverware then
  225. self:StandUp()
  226. end
  227.  
  228. isWalkingToSaladBar = true
  229. didWalkToSalad = true
  230. local sx, sy, sz = self.xVoxel, self.yVoxel, self.zVoxel
  231. self:WalkToPoint(saladBar.xVoxel, saladBar.yVoxel, saladBar.zVoxel, function()
  232. if saladBar.isDeleted then
  233. isWalkingToSaladBar = false
  234. self:ForcedToLeave()
  235. return
  236. end
  237.  
  238. self:FaceEntity(saladBar)
  239. _L.SFX.Play(5708685167, saladBar.model.PrimaryPart)
  240. _L.Network.Fire("AwardTipWithVerification", self.UID, saladBar.UID, self.stateData.foodOrder.ID, isWalkingFromSilverware)
  241.  
  242. if doWalkBackToSeat then
  243. self:WalkToPoint(sx, sy, sz, function()
  244. isWalkingToSaladBar = false
  245. if self.stateData.mySeat.isDeleted then
  246. self:ForcedToLeave()
  247. return
  248. end
  249. self:SitInSeat(self.stateData.mySeat)
  250. end)
  251. else
  252. isWalkingToSaladBar = false
  253. end
  254. end)
  255. break
  256. end
  257. end
  258. if isWalkingToSaladBar then
  259. repeat wait() until not isWalkingToSaladBar
  260. end
  261. return didWalkToSalad
  262. end
  263.  
  264. local didDessertCheck = false
  265. local function checkForDessertBars(isWalkingFromSilverware, doWalkBackToSeat)
  266. didDessertCheck = true
  267. local didWalkToDessert = false
  268. -- walk to salad bar sometimes
  269. local isWalkingToDessertBar = false
  270. for _, dessertBar in ipairs(myFloor.dessertBars) do
  271. if math.random() < 0.20 then
  272.  
  273. if not isWalkingFromSilverware then
  274. self:StandUp()
  275. end
  276.  
  277. isWalkingToDessertBar = true
  278. didWalkToDessert = true
  279. local sx, sy, sz = self.xVoxel, self.yVoxel, self.zVoxel
  280. self:WalkToPoint(dessertBar.xVoxel, dessertBar.yVoxel, dessertBar.zVoxel, function()
  281. if dessertBar.isDeleted then
  282. isWalkingToDessertBar = false
  283. self:ForcedToLeave()
  284. return
  285. end
  286.  
  287. self:FaceEntity(dessertBar)
  288. _L.SFX.Play(5708685167, dessertBar.model.PrimaryPart)
  289. _L.Network.Fire("AwardTipWithVerification", self.UID, dessertBar.UID, self.stateData.foodOrder.ID, isWalkingFromSilverware)
  290.  
  291. if doWalkBackToSeat then
  292. self:WalkToPoint(sx, sy, sz, function()
  293. isWalkingToDessertBar = false
  294. if self.stateData.mySeat.isDeleted then
  295. self:ForcedToLeave()
  296. return
  297. end
  298. self:SitInSeat(self.stateData.mySeat)
  299. end)
  300. else
  301. isWalkingToDessertBar = false
  302. end
  303. end)
  304. break
  305. end
  306. end
  307. if isWalkingToDessertBar then
  308. repeat wait() until not isWalkingToDessertBar
  309. end
  310. return didWalkToDessert
  311. end
  312.  
  313. -- create food model for the customer
  314. if not self.stateData.foodOrder then
  315. self:ForcedToLeave()
  316. return
  317. end
  318. local myTable = self:EntityTable()[self.stateData.tableUID]
  319. local mySeat = self:EntityTable()[self.stateData.seatUID]
  320. if not myTable or not mySeat then
  321. _L.Print("CRITICAL: COULDN'T FIND CUSTOMERS TABLE WHEN EATING", true)
  322. return
  323. end
  324. local myFloor = myTable:GetMyFloor()
  325. local worldPos = myFloor:WorldPositionFromVoxel(mySeat:GetFacePosition())
  326. local tableRoot = myTable.model.PrimaryPart
  327. local tableTop = Vector3.new(worldPos.X, tableRoot.Position.Y + tableRoot.Size.Y/2, worldPos.Z)
  328. local foodOffset = (-1.1)*mySeat:GetFaceDirection() + Vector3.new(0, self.stateData.foodOrder.data.model.PrimaryPart.Size.Y/2, 0)
  329. local foodCF = CFrame.new(tableTop + foodOffset)
  330. self:CreateMyFoodModel(foodCF)
  331.  
  332. local isWalkingToTray = false
  333. local wasWalkingToTray = false
  334. local trayUID = false
  335. local forkModel = nil
  336. local spoonModel = nil
  337. local welds = {}
  338. local function walkToTray(tray)
  339. isWalkingToTray = true
  340. wasWalkingToTray = true
  341. trayUID = tray.UID
  342. self:StandUp()
  343. local sx, sy, sz = self.xVoxel, self.yVoxel, self.zVoxel
  344. self:WalkToPoint(tray.xVoxel, tray.yVoxel, tray.zVoxel, function()
  345. if tray.isDeleted then
  346. isWalkingToTray = false
  347. self:ForcedToLeave()
  348. return
  349. end
  350. local sounds = {5601560377, 5601560515, 5601560641}
  351. _L.SFX.Play(sounds[math.random(#sounds)], tray.model.PrimaryPart)
  352. self:FaceEntity(tray)
  353.  
  354. if not checkForSaladBars(true, false) then
  355. checkForDessertBars(true, false)
  356. end
  357.  
  358. self:WalkToPoint(sx, sy, sz, function()
  359. isWalkingToTray = false
  360. if self.stateData.mySeat.isDeleted then
  361. self:ForcedToLeave()
  362. return
  363. end
  364. self:SitInSeat(self.stateData.mySeat)
  365.  
  366. -- hold silverware
  367. local isGold = tray.ID == "25"
  368. local function weldToHand(part, hand)
  369. local weld = Instance.new("Weld", part)
  370. weld.Part0 = part
  371. weld.Part1 = hand
  372. weld.C0 = CFrame.Angles(-math.pi/2, 0, 0)
  373. table.insert(welds, weld)
  374. end
  375. if isGold then
  376. forkModel = game.ReplicatedStorage.Assets.Models["Luxury Fork"]:Clone()
  377. spoonModel = game.ReplicatedStorage.Assets.Models["Luxury Spoon"]:Clone()
  378. forkModel.Parent = self.model
  379. spoonModel.Parent = self.model
  380. weldToHand(forkModel, self.model.RightHand)
  381. weldToHand(spoonModel, self.model.LeftHand)
  382. else
  383. forkModel = game.ReplicatedStorage.Assets.Models["Default Fork"]:Clone()
  384. spoonModel = game.ReplicatedStorage.Assets.Models["Default Spoon"]:Clone()
  385. forkModel.Parent = self.model
  386. spoonModel.Parent = self.model
  387. weldToHand(forkModel, self.model.RightHand)
  388. weldToHand(spoonModel, self.model.LeftHand)
  389. end
  390. end)
  391. end)
  392. end
  393.  
  394. if #myFloor.goldSilverwareTrays > 0 then
  395. walkToTray(myFloor.goldSilverwareTrays[1])
  396. elseif #myFloor.silverwareTrays > 0 then
  397. local goodRoll = false
  398. for i = 1, #myFloor.silverwareTrays do
  399. if true then
  400. goodRoll = true
  401. end
  402. end
  403. if goodRoll then
  404. walkToTray(myFloor.silverwareTrays[1])
  405. end
  406. end
  407.  
  408. if isWalkingToTray then
  409. repeat wait() until not isWalkingToTray
  410. end
  411.  
  412. if not didSaladCheck then
  413. if not checkForSaladBars(false, true) then
  414. checkForDessertBars(false, true)
  415. end
  416. end
  417.  
  418. -- play eating animation
  419. self:PlayLoadedAnimation("eating")
  420.  
  421. -- play served sound
  422. _L.SFX.Play(5205174537, self.model.PrimaryPart, nil, 0.60)
  423.  
  424. -- play eating looped sound
  425. local pitch = 1 + (math.random() - 0.50)*0.10
  426. local eatSound = math.random() < 0.50 and 5029600710 or 5029600543
  427. self.stateData.loopedEatingSound = _L.SFX.Play(eatSound, self.model.PrimaryPart, pitch, 0.85, 35, nil, true)
  428.  
  429. coroutine.wrap(function()
  430.  
  431. -- eat timing is determined by the server. //no, it's not, -bluwud
  432. local forceLeaveTip = true
  433. if not self.isDeleted and self.state == "EatingFood" then
  434. if self.stateData.loopedEatingSound then
  435. self.stateData.loopedEatingSound = self.stateData.loopedEatingSound:Destroy()
  436. end
  437. self.stateData.foodOrder:ChangeToDirtyDish()
  438. self:StopLoadedAnimation("eating")
  439. self:ChangeToReadyToExitState(forceLeaveTip)
  440.  
  441. if forkModel then
  442. forkModel:Destroy()
  443. spoonModel:Destroy()
  444. for _, weld in ipairs(welds) do
  445. weld:Destroy()
  446. end
  447. welds = {}
  448. end
  449. end
  450. end)()
  451. end)()
  452.  
  453. end
  454.  
  455.  
  456.  
  457. function Customer:ChangeToExitingState(wasForcedToLeave, forcedToLeaveTip)
  458.  
  459. if self.isDeleted then
  460. return
  461. end
  462.  
  463. self.leaving = true
  464. self:SetCustomerState("WalkingToExit")
  465.  
  466. -- remove customer from table
  467. local myTable = self:EntityTable()[self.stateData.tableUID]
  468. if myTable and not myTable.isDeleted then
  469. myTable:RemoveCustomerFromTable(self)
  470. end
  471.  
  472. local myFloor = self:GetMyFloor()
  473.  
  474. coroutine.wrap(function()
  475. if wasForcedToLeave then
  476. self:TimedEmoji("MadEmoji", 2)
  477. else
  478. if math.random() < 0.30 or _L.Variables.MyBakery.isTutorial then
  479. self:TimedEmoji("HappyEmoji", 2.5)
  480. end
  481. end
  482.  
  483. -- make humanoid stand
  484. self:StandUp()
  485.  
  486. local function goToExitAndLeave()
  487. self:WalkToNewFloor(_L.Variables.MyBakery.floors[1], function()
  488. local vx, vy, vz = _L.Variables.MyBakery:GetCustomerStartVoxel(1)
  489. self:WalkToPoint(vx, vy, vz, function()
  490. self:FadeTransparency(1, function()
  491. self:LeaveBakery()
  492. end)
  493. end, nil, true)
  494. end)
  495. end
  496.  
  497. local isLeavingTip = false
  498. local isGoingForGumball = false
  499. local isGoingForCandy = false
  500. local isGoingForArcade = false
  501. local isGoingForPopcorn = false
  502. local isGoingForSoda = false
  503. local isGoingForBowl = false
  504.  
  505. -- is there a tip jar on this floor? if so, roll to leave tip
  506. if not wasForcedToLeave then
  507. local tipJars = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "Tip Jar")
  508. if #tipJars > 0 then
  509. for _, tipJar in ipairs(tipJars) do
  510. local tipChance = tipJar.ID == "14" and 0.05 or tipJar.ID == "19" and 0.50 or tipJar.ID == "26" and 0.40 or 0
  511. if true or forcedToLeaveTip or self:IsVIPCustomer() then
  512. isLeavingTip = true
  513. self:WalkToPoint(tipJar.xVoxel, tipJar.yVoxel, tipJar.zVoxel, function()
  514. if tipJar.isDeleted or self.isDeleted or not self.stateData or not self.stateData.foodOrder then
  515. goToExitAndLeave()
  516. return
  517. end
  518.  
  519. -- happy emoji at tip jar
  520. self:TimedEmoji("VeryHappyEmoji", 2.5)
  521.  
  522. _L.Network.Fire("AwardTipWithVerification", self.UID, tipJar.UID, self.stateData.foodOrder.ID)
  523. _L.SFX.Play(5839737230, tipJar.model.PrimaryPart)
  524.  
  525. self:FaceEntity(tipJar)
  526. goToExitAndLeave()
  527. end)
  528. break
  529. end
  530. end
  531. end
  532. end
  533.  
  534. if not isLeavingTip then
  535. local candyBowls = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "CandyBowl")
  536. if #candyBowls > 0 then
  537. for _, bowl in ipairs(candyBowls) do
  538. if true and bowl.level and bowl.level > 0 then
  539. isGoingForBowl = true
  540. self:WalkToPoint(bowl.xVoxel, bowl.yVoxel, bowl.zVoxel, function()
  541. if bowl.isDeleted or not self.stateData or not self.stateData.foodOrder or bowl.level <= 0 then
  542. goToExitAndLeave()
  543. return
  544. end
  545.  
  546. -- happy emoji at tip jar
  547. self:TimedEmoji("VeryHappyEmoji", 2.5)
  548.  
  549. _L.Network.Fire("AwardTipWithVerification", self.UID, bowl.UID, self.stateData.foodOrder.ID)
  550. _L.SFX.Play(5057746151, bowl.model.PrimaryPart)
  551.  
  552. self:FaceEntity(bowl)
  553. goToExitAndLeave()
  554. end)
  555. break
  556. end
  557. end
  558. end
  559. end
  560.  
  561. -- only go for gumball if we're not leaving a tip
  562. if not isLeavingTip and not isGoingForBowl then
  563.  
  564. local gumballMachines = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "GumballMachine")
  565. if #gumballMachines > 0 then
  566. for _, gumballMachine in ipairs(gumballMachines) do
  567. if true then
  568. isGoingForGumball = true
  569.  
  570. local fx, fy, fz = gumballMachine:GetFacePosition()
  571. if not myFloor:IsValidVoxel(fx, fy, fz) then
  572. fx, fy, fz = gumballMachine.xVoxel, gumballMachine.yVoxel, gumballMachine.zVoxel
  573. end
  574. self:WalkToPoint(fx, fy, fz, function()
  575. if gumballMachine.isDeleted or self.isDeleted then
  576. goToExitAndLeave()
  577. return
  578. end
  579.  
  580. -- gumball tip
  581. if self.stateData.foodOrder then
  582. _L.Network.Fire("AwardTipWithVerification", self.UID, gumballMachine.UID, self.stateData.foodOrder.ID)
  583. end
  584.  
  585. -- gumball sound
  586. _L.SFX.Play(5205171179, gumballMachine.model.PrimaryPart.Position)
  587.  
  588. -- gumball emoji
  589. self:TimedEmoji("VeryHappyEmoji", 2.5)
  590. self:FaceEntity(gumballMachine)
  591. goToExitAndLeave()
  592. end)
  593. break
  594. end
  595. end
  596. end
  597.  
  598. end
  599.  
  600. if not isLeavingTip and not isGoingForGumball and not isGoingForBowl then
  601. local candyMachines = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "CandyMachine")
  602. if #candyMachines > 0 then
  603. for _, candyMachine in ipairs(candyMachines) do
  604. if true then
  605. isGoingForCandy = true
  606.  
  607. local fx, fy, fz = candyMachine:GetFacePosition()
  608. if not myFloor:IsValidVoxel(fx, fy, fz) then
  609. fx, fy, fz = candyMachine.xVoxel, candyMachine.yVoxel, candyMachine.zVoxel
  610. end
  611. self:WalkToPoint(fx, fy, fz, function()
  612. if candyMachine.isDeleted or self.isDeleted then
  613. goToExitAndLeave()
  614. return
  615. end
  616.  
  617. _L.SFX.Play(5601560734, candyMachine.model.PrimaryPart)
  618.  
  619. -- gumball tip
  620. if self.stateData.foodOrder then
  621. _L.Network.Fire("AwardTipWithVerification", self.UID, candyMachine.UID, self.stateData.foodOrder.ID)
  622. end
  623.  
  624. -- gumball emoji
  625. self:TimedEmoji("VeryHappyEmoji", 2.5)
  626. self:FaceEntity(candyMachine)
  627. goToExitAndLeave()
  628. end)
  629. break
  630. end
  631. end
  632. end
  633. end
  634.  
  635. -- check for popcorn machine
  636. if not isLeavingTip and not isGoingForGumball and not isGoingForCandy and not isGoingForBowl then
  637.  
  638. local popcornMachines = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "PopcornMachine")
  639. if #popcornMachines > 0 then
  640. for _, popcornMachine in ipairs(popcornMachines) do
  641. if true then
  642. isGoingForPopcorn = true
  643.  
  644. local fx, fy, fz = popcornMachine:GetFacePosition()
  645. if not myFloor:IsValidVoxel(fx, fy, fz) then
  646. fx, fy, fz = popcornMachine.xVoxel, popcornMachine.yVoxel, popcornMachine.zVoxel
  647. end
  648. self:WalkToPoint(fx, fy, fz, function()
  649. if popcornMachine.isDeleted or self.isDeleted then
  650. goToExitAndLeave()
  651. return
  652. end
  653.  
  654. _L.SFX.Play(5625433552, popcornMachine.model.PrimaryPart)
  655.  
  656. -- popcorn tip
  657. if self.stateData.foodOrder then
  658. _L.Network.Fire("AwardTipWithVerification", self.UID, popcornMachine.UID, self.stateData.foodOrder.ID)
  659. end
  660.  
  661. -- gumball emoji
  662. self:TimedEmoji("VeryHappyEmoji", 2.5)
  663. self:FaceEntity(popcornMachine)
  664. goToExitAndLeave()
  665. end)
  666. break
  667. end
  668. end
  669. end
  670.  
  671. end
  672.  
  673. -- check for soda machine
  674. if not isLeavingTip and not isGoingForGumball and not isGoingForCandy and not isGoingForPopcorn and not wasForcedToLeave and not isGoingForBowl then
  675. local sodaMachines = myFloor:GetEntitiesFromClassAndSubClass("Appliance", "SodaMachine")
  676. if #sodaMachines > 0 then
  677. for _, sodaMachine in ipairs(sodaMachines) do
  678. if true then
  679. isGoingForSoda = true
  680.  
  681. local fx, fy, fz = sodaMachine:GetFacePosition()
  682. if not myFloor:IsValidVoxel(fx, fy, fz) then
  683. fx, fy, fz = sodaMachine.xVoxel, sodaMachine.yVoxel, sodaMachine.zVoxel
  684. end
  685. self:WalkToPoint(fx, fy, fz, function()
  686. if sodaMachine.isDeleted or self.isDeleted then
  687. goToExitAndLeave()
  688. return
  689. end
  690.  
  691. _L.SFX.Play(5708685354, sodaMachine.model.PrimaryPart)
  692.  
  693. -- soda tip
  694. if self.stateData.foodOrder then
  695. _L.Network.Fire("AwardTipWithVerification", self.UID, sodaMachine.UID, self.stateData.foodOrder.ID)
  696. end
  697.  
  698. -- gumball emoji
  699. self:TimedEmoji("VeryHappyEmoji", 2.5)
  700. self:FaceEntity(sodaMachine)
  701. goToExitAndLeave()
  702. end)
  703. break
  704. end
  705. end
  706. end
  707. end
  708.  
  709. -- check for arcade machine
  710. if not isLeavingTip and not isGoingForGumball and not isGoingForCandy and not isGoingForPopcorn and not isGoingForSoda and not wasForcedToLeave and not isGoingForBowl then
  711. local arcadeMachines = myFloor:GetEntitiesFromClassAndSubClass("Furniture", "ArcadeMachine")
  712. if #arcadeMachines > 0 then
  713. local indices = _L.Functions.RandomIndices(arcadeMachines)
  714. for _, index in ipairs(indices) do
  715. local arcadeMachine = arcadeMachines[index]
  716. if arcadeMachine.arcadeState ~= "Highscore" then
  717. continue
  718. end
  719. if arcadeMachine.busy then
  720. continue
  721. end
  722. arcadeMachine.busy = true
  723. isGoingForArcade = true
  724. local fx, fy, fz = arcadeMachine:GetFacePosition()
  725. if not myFloor:IsValidVoxel(fx, fy, fz) then
  726. fx, fy, fz = arcadeMachine.xVoxel, arcadeMachine.yVoxel, arcadeMachine.zVoxel
  727. end
  728. self:WalkToPoint(fx, fy, fz, function()
  729.  
  730. if arcadeMachine.isDeleted or self.isDeleted then
  731. goToExitAndLeave()
  732. return
  733. end
  734.  
  735. self:FaceEntity(arcadeMachine)
  736.  
  737. -- play game (halts thread until done)
  738. arcadeMachine:PlayGameWithCustomer(self)
  739.  
  740. arcadeMachine.busy = false
  741.  
  742. goToExitAndLeave()
  743.  
  744. end)
  745. break
  746. end
  747. end
  748. end
  749.  
  750. -- check for celebrity customer
  751. local isGoingForCelebrity = false
  752. (function()
  753. if isLeavingTip or isGoingForGumball or isGoingForCandy or isGoingForPopcorn or isGoingForArcade or isGoingForSoda or isGoingForBowl then
  754. return
  755. end
  756. if _L.Variables.MyBakery.nameCounters["Celebrity Customer"] == 0 then
  757. return
  758. end
  759.  
  760. local celebrity = _L.Variables.MyBakery:SearchForCelebrity()
  761. if not celebrity or celebrity.isDeleted or celebrity.stateData.celebrityApproachCount >= 3 then
  762. return
  763. end
  764.  
  765. local function isValidCelebState()
  766. local validCelebStates = {
  767. ThinkingAboutOrder = true,
  768. DecidedOnOrder = true,
  769. WaitingToOrder = true,
  770. WaitingForFood = true,
  771. EatingFood = true
  772. }
  773. return not celebrity.isDeleted and validCelebStates[celebrity.state]
  774. end
  775.  
  776. if not isValidCelebState() then
  777. return
  778. end
  779.  
  780. isGoingForCelebrity = true
  781. celebrity.stateData.celebrityApproachCount += 1
  782.  
  783. self:WalkToNewFloor(celebrity:GetMyFloor(), function()
  784. if not isValidCelebState() then
  785. if not celebrity.isDeleted then
  786. celebrity.stateData.celebrityApproachCount -= 1
  787. end
  788. goToExitAndLeave()
  789. return
  790. end
  791.  
  792. self:WalkToPoint(celebrity.xVoxel, celebrity.yVoxel, celebrity.zVoxel, function()
  793. if not isValidCelebState() then
  794. if not celebrity.isDeleted then
  795. celebrity.stateData.celebrityApproachCount -= 1
  796. end
  797. goToExitAndLeave()
  798. return
  799. end
  800.  
  801. celebrity.stateData.celebrityApproachCount -= 1
  802.  
  803. _L.SFX.Play(5278932469, celebrity.model.PrimaryPart.Position)
  804. self:FaceEntity(celebrity)
  805. self:TimedEmoji("Starstruck", 2.5)
  806. self:PlayLoadedAnimation("wave")
  807. goToExitAndLeave()
  808. end)
  809. end)
  810. end)()
  811. if not isLeavingTip and not isGoingForGumball and not isGoingForCelebrity and not isGoingForCandy and not isGoingForArcade and not isGoingForPopcorn and not isGoingForBowl then
  812. goToExitAndLeave()
  813. end
  814. end)()
  815. end
  816.  
  817.  
  818. function Waiter:StartActionLoop()
  819. coroutine.wrap(function()
  820. while not self.isDeleted do
  821. self:PerformAction()
  822. wait()
  823. end
  824. end)()
  825. end
  826.  
  827.  
  828. function Waiter:CheckForDishPickup()
  829.  
  830. local myFloor = self:GetMyFloor()
  831. local selectedDishChair, selectedDishChairFloor = nil
  832.  
  833. -- check other floors for dishes
  834. local indices = _L.Functions.RandomIndices(_L.Variables.MyBakery.floors)
  835.  
  836. --check my floor first
  837. if true then
  838. for i, index in ipairs(indices) do
  839. if index == myFloor.floorLevel then
  840. table.remove(indices, i)
  841. table.insert(indices, 1, myFloor.floorLevel)
  842. break
  843. end
  844. end
  845. end
  846.  
  847. for _, index in ipairs(indices) do
  848. local thisFloor = _L.Variables.MyBakery.floors[index]
  849. local dishIndices = _L.Functions.RandomIndices(thisFloor.dishChairs)
  850. for _, dishIndex in ipairs(dishIndices) do
  851. local dishChair = thisFloor.dishChairs[dishIndex]
  852. if dishChair.isDeleted or dishChair.stateData.flaggedByWaiterForDishPickup or not dishChair.stateData.dish or dishChair.stateData.dish.isDeleted then
  853. continue
  854. end
  855. selectedDishChair = dishChair
  856. selectedDishChairFloor = dishChair:GetMyFloor()
  857. break
  858. end
  859. if selectedDishChair then
  860. break
  861. end
  862. end
  863.  
  864. if not selectedDishChair then
  865. return false
  866. end
  867.  
  868. local dishwashers = myFloor:GatherDishwashersOnAnyFloor()
  869. if #dishwashers == 0 then
  870. return false
  871. end
  872.  
  873. -- chair that has an attached dish to go to
  874. local dishChair = selectedDishChair
  875. dishChair.stateData.flaggedByWaiterForDishPickup = true
  876.  
  877. local dishwasher = dishwashers[math.random(#dishwashers)]
  878. dishwasher.stateData.dishWasherTargetCount += 1
  879.  
  880. -- flag the dish with the targeted dishwasher
  881. dishChair.stateData.dish.flaggedDishwasherUID = dishwasher.UID
  882.  
  883. self.state = "WalkingToPickupDish"
  884.  
  885. self:WalkToNewFloor(dishChair:GetMyFloor(), function()
  886.  
  887. if dishChair.isDeleted or not dishChair.stateData.dish then
  888. dishwasher.stateData.dishWasherTargetCount -= 1
  889. self.state = "Idle"
  890. return
  891. end
  892.  
  893. self:WalkToPoint(dishChair.xVoxel, dishChair.yVoxel, dishChair.zVoxel, function()
  894.  
  895. if dishChair.isDeleted or not dishChair.stateData.dish then
  896. dishwasher.stateData.dishWasherTargetCount -= 1
  897. self.state = "Idle"
  898. return
  899. end
  900.  
  901. dishChair.stateData.flaggedByWaiterForDishPickup = false
  902.  
  903. if not dishChair.stateData.dish or dishChair.stateData.dish.isDeleted then
  904. dishwasher.stateData.dishWasherTargetCount -= 1
  905. self.state = "Idle"
  906. return
  907. end
  908.  
  909. -- dish is good. delete it and remove
  910. if dishChair.stateData.dish and dishChair.stateData.dish.model then
  911.  
  912. -- remove dishChair from available
  913. for i, dishChairEntry in ipairs(selectedDishChairFloor.dishChairs) do
  914. if dishChairEntry == selectedDishChair then
  915. table.remove(selectedDishChairFloor.dishChairs, i)
  916. break
  917. end
  918. end
  919.  
  920. -- stop the interact
  921. dishChair.stateData.dish:CleanupInteract()
  922.  
  923. -- play dish sound
  924. if dishChair.stateData.dish.model and dishChair.stateData.dish.model.PrimaryPart then
  925. local dishSounds = {5205173686, 5205173942}
  926. _L.SFX.Play(dishSounds[math.random(#dishSounds)], dishChair.stateData.dish.model:GetPrimaryPartCFrame().p)
  927. end
  928.  
  929. -- pick up the money and dish (if necessary)
  930. dishChair.stateData.dish:MoneyPickedUp()
  931. dishChair.stateData.dish:DestroyModel()
  932. dishChair.stateData.dish = nil
  933.  
  934. -- hold the dish I'm delivering
  935. self:HoldDirtyDish()
  936.  
  937. end
  938.  
  939. self:FaceEntity(dishChair)
  940.  
  941. if dishwasher.isDeleted then
  942. self:StopLoadedAnimation("hold")
  943. if self.stateData.heldDish then
  944. self.stateData.heldDish = self.stateData.heldDish:Destroy()
  945. end
  946. self.state = "Idle"
  947. return
  948. end
  949.  
  950. -- walk to the dishwasher to deposit
  951. -- TODO face direction
  952. self:WalkToNewFloor(dishwasher:GetMyFloor(), function()
  953.  
  954. if dishwasher.isDeleted then
  955. self:StopLoadedAnimation("hold")
  956. if self.stateData.heldDish then
  957. self.stateData.heldDish = self.stateData.heldDish:Destroy()
  958. end
  959. self.state = "Idle"
  960. return
  961. end
  962.  
  963. self:WalkToPoint(dishwasher.xVoxel, dishwasher.yVoxel, dishwasher.zVoxel, function()
  964.  
  965. -- put down the dish
  966. self:DropFood()
  967.  
  968. if dishwasher.isDeleted then
  969. self.state = "Idle"
  970. return
  971. end
  972. dishwasher:AddDish()
  973.  
  974. self:FaceEntity(dishwasher)
  975.  
  976. self:ResetAllStates()
  977.  
  978. end)
  979. end)
  980. end)
  981. end)
  982.  
  983. return true
  984.  
  985. end
  986.  
  987.  
  988. function Waiter:WalkToNewFloor(targetFloor, finishedCallback)
  989.  
  990. local currentFloor = self:GetMyFloor()
  991.  
  992. if not targetFloor or currentFloor.floorLevel == targetFloor.floorLevel then
  993. if finishedCallback then finishedCallback() end
  994. return
  995. end
  996.  
  997.  
  998. self:TransitionToDifferentFloor(targetFloor)
  999. if finishedCallback then
  1000. finishedCallback()
  1001. end
  1002.  
  1003. end
  1004.  
  1005. function Waiter:CheckForFoodDelivery()
  1006.  
  1007. -- gather all order stands
  1008. local myFloor = self:GetMyFloor()
  1009. local orderStands = myFloor:GatherOrderStandsWithDeliveryReady()
  1010.  
  1011. if #orderStands == 0 then
  1012.  
  1013. -- if there are no order stands on my floor, search for floors that might need help
  1014. local indices = _L.Functions.RandomIndices(_L.Variables.MyBakery.floors)
  1015. for _, index in ipairs(indices) do
  1016. local floor = _L.Variables.MyBakery.floors[index]
  1017. if floor ~= myFloor then
  1018. if not floor:HasAtLeastOneIdleStateOfClass("Waiter") then
  1019. -- gather order stands on this floor
  1020. orderStands = floor:GatherOrderStandsWithDeliveryReady()
  1021. if #orderStands > 0 then
  1022. break
  1023. end
  1024. end
  1025. end
  1026. end
  1027.  
  1028. -- STILL nothing? abort
  1029. if #orderStands == 0 then
  1030. return false
  1031. end
  1032. end
  1033.  
  1034. -- select a random order stand to deliver from
  1035. local orderStand = orderStands[math.random(#orderStands)]
  1036. if not orderStand then
  1037. return false
  1038. end
  1039.  
  1040. orderStand.stateData.foodReadyTargetCount = orderStand.stateData.foodReadyTargetCount + 1
  1041.  
  1042. self.state = "WalkingToPickupFood"
  1043.  
  1044. -- walk to the order stand
  1045. self:WalkToNewFloor(orderStand:GetMyFloor(), function()
  1046.  
  1047. -- no need to kick out the customer, they've already been removed.
  1048. -- just reset the waiter back to idle
  1049. if orderStand.isDeleted then
  1050. self.state = "Idle"
  1051. return
  1052. end
  1053.  
  1054. self:WalkToPoint(orderStand.xVoxel, orderStand.yVoxel, orderStand.zVoxel, function()
  1055.  
  1056. if orderStand.isDeleted then
  1057. self.state = "Idle"
  1058. return
  1059. end
  1060.  
  1061. orderStand.stateData.foodReadyTargetCount = orderStand.stateData.foodReadyTargetCount - 1
  1062.  
  1063. -- it's possible that the user already cleared the queue...
  1064. if #orderStand.stateData.foodReadyList == 0 then
  1065. self.state = "Idle"
  1066. return
  1067. end
  1068.  
  1069. -- grab some food off of the top of the queue
  1070. local selectedFoodOrder = orderStand.stateData.foodReadyList[1]
  1071. selectedFoodOrder.isGold = true
  1072. table.remove(orderStand.stateData.foodReadyList, 1)
  1073. if selectedFoodOrder.isGold then
  1074. _L.SFX.Play(5370840758, orderStand.model.PrimaryPart)
  1075. end
  1076.  
  1077. -- delete this list item
  1078. selectedFoodOrder:DestroyPopupListItemUI()
  1079.  
  1080. -- the customer that I should deliver to...
  1081. local customerOfOrder = self:EntityTable()[selectedFoodOrder.customerOwnerUID]
  1082. if not customerOfOrder then
  1083. _L.Print("CRITICAL: customer owner of food not found", true)
  1084. self.state = "Idle"
  1085. return false
  1086. end
  1087.  
  1088.  
  1089. -- pause to face the order stand for a little bit
  1090. self:FaceEntity(orderStand)
  1091. -- hold the dish I'm delivering
  1092. self:HoldFood(selectedFoodOrder.ID, selectedFoodOrder.isGold)
  1093.  
  1094. self.state = "WalkingToDeliverFood"
  1095.  
  1096. if customerOfOrder.isDeleted then
  1097. self.state = "Idle"
  1098. self.stateData.heldDish = self.stateData.heldDish:Destroy()
  1099. return
  1100. end
  1101.  
  1102. -- walk to the customer to deliver...
  1103. self:WalkToNewFloor(customerOfOrder:GetMyFloor(), function()
  1104. self:WalkToPoint(customerOfOrder.xVoxel, customerOfOrder.yVoxel, customerOfOrder.zVoxel, function()
  1105.  
  1106. self:DropFood()
  1107.  
  1108. if customerOfOrder.isDeleted then
  1109. _L.Print("CRITICAL: walked to customer, but they were forced to leave. aborting", true)
  1110. self.state = "Idle"
  1111. return
  1112. end
  1113.  
  1114. customerOfOrder:ChangeToEatingState()
  1115.  
  1116. -- face the customer
  1117. self:FaceEntity(customerOfOrder)
  1118.  
  1119. -- award XP for delivering food
  1120. _L.Network.Fire("AwardWaiterExperienceForDeliveringOrderWithVerification", self.UID)
  1121. -- free the waiter back up
  1122. self.state = "Idle"
  1123. end)
  1124. end)
  1125. end)
  1126. end)
  1127.  
  1128. return true
  1129. end
  1130.  
  1131.  
  1132. function Waiter:CheckForCustomerOrder()
  1133.  
  1134. local myFloor = self:GetMyFloor()
  1135.  
  1136. -- find a customer that is waiting to order
  1137. local waitingCustomer = myFloor:GetCustomerWaitingToOrder()
  1138.  
  1139. if not waitingCustomer then
  1140.  
  1141. -- if there's no customer on my current floor, check if other floors need help
  1142. local indices = _L.Functions.RandomIndices(_L.Variables.MyBakery.floors)
  1143. for _, index in ipairs(indices) do
  1144. local floor = _L.Variables.MyBakery.floors[index]
  1145. if floor ~= myFloor then
  1146. if not floor:HasAtLeastOneIdleStateOfClass("Waiter") then
  1147. waitingCustomer = floor:GetCustomerWaitingToOrder()
  1148. if waitingCustomer then
  1149. break
  1150. end
  1151. end
  1152. end
  1153. end
  1154.  
  1155. -- still nothing? abort
  1156. if not waitingCustomer then
  1157. return false
  1158. end
  1159. end
  1160.  
  1161. self.state = "WalkingToTakeOrder"
  1162.  
  1163. -- find the entire customer group
  1164. local customerGroup = {waitingCustomer}
  1165. for _, customerPartner in ipairs(waitingCustomer.stateData.queueGroup) do
  1166. if customerPartner.state == "WaitingToOrder" and not customerPartner.waiterIsAttendingToFoodOrder then
  1167. table.insert(customerGroup, customerPartner)
  1168. end
  1169. end
  1170.  
  1171. -- tag debounce, not allowing other waiters to interfere
  1172. for _, seatedCustomer in ipairs(customerGroup) do
  1173. seatedCustomer.waiterIsAttendingToFoodOrder = true
  1174. end
  1175.  
  1176. local function untagGroup()
  1177. for _, seatedCustomer in ipairs(customerGroup) do
  1178. seatedCustomer.waiterIsAttendingToFoodOrder = false
  1179. end
  1180. end
  1181.  
  1182. -- walk to the seated group
  1183. local firstCustomer = customerGroup[1]
  1184. local groupTable = self:EntityTable()[firstCustomer.stateData.tableUID]
  1185. if not groupTable or groupTable.isDeleted then
  1186. self.state = "Idle"
  1187. return
  1188. end
  1189. local tx, ty, tz = groupTable.xVoxel, groupTable.yVoxel, groupTable.zVoxel
  1190.  
  1191. local customerFloor = firstCustomer:GetMyFloor()
  1192. self:WalkToNewFloor(customerFloor, function()
  1193. if firstCustomer.leaving or firstCustomer.isDeleted then
  1194. self.state = "Idle"
  1195. return
  1196. end
  1197. self:WalkToPoint(tx, ty, tz, function()
  1198.  
  1199. if firstCustomer.isDeleted or firstCustomer.leaving then
  1200. self.state = "Idle"
  1201. return
  1202. end
  1203.  
  1204. -- order stand to deposit the orders in
  1205. local orderStand = customerFloor:FindOrderStandOnAnyFloor()
  1206. if not orderStand then
  1207. _L.Print("CRITICAL: NO ORDER STAND FOUND!", true)
  1208. untagGroup()
  1209. self.state = "Idle"
  1210. self:TimedEmoji("ConcernedEmoji", 2)
  1211. return
  1212. end
  1213.  
  1214. -- stop interacting
  1215. local firstCustomer = customerGroup[1]
  1216. if firstCustomer then
  1217. firstCustomer:StopGroupEmoji()
  1218. firstCustomer:CleanupGroupInteract()
  1219. end
  1220.  
  1221. -- check for customers in the group still waiting to have their
  1222. -- order taken. it's possible that the user took one or
  1223. -- more of their orders
  1224. local groupOrder = {}
  1225. local tookOrdersFrom = {}
  1226. for _, seatedCustomer in ipairs(customerGroup) do
  1227. if seatedCustomer.state == "WaitingToOrder" then
  1228. table.insert(tookOrdersFrom, seatedCustomer)
  1229. groupOrder[seatedCustomer.UID] = _L.Food.RandomFoodChoice(seatedCustomer.UID, seatedCustomer.ID, seatedCustomer:IsRichCustomer(), seatedCustomer:IsPirateCustomer(), seatedCustomer.isNearTree)
  1230. seatedCustomer.state = "WaitingForFood"
  1231. seatedCustomer:StopChat()
  1232. end
  1233. end
  1234.  
  1235. -- if no orders are taken, abort
  1236. if #tookOrdersFrom == 0 then
  1237. self.state = "Idle"
  1238. return
  1239. end
  1240.  
  1241. -- take order animation
  1242. self:PlayLoadedAnimation("write")
  1243. for _, customer in ipairs(customerGroup) do
  1244. self:FaceEntity(customer)
  1245. end
  1246. self:StopLoadedAnimation("write")
  1247.  
  1248. self.state = "WalkingToDropoffOrder"
  1249.  
  1250. self:WalkToNewFloor(orderStand:GetMyFloor(), function()
  1251.  
  1252. if orderStand.isDeleted then
  1253. for _, customer in ipairs(customerGroup) do
  1254. customer:ForcedToLeave()
  1255. end
  1256. self.state = "Idle"
  1257. return
  1258. end
  1259.  
  1260. self:WalkToPoint(orderStand.xVoxel, orderStand.yVoxel, orderStand.zVoxel, function()
  1261.  
  1262. if orderStand.isDeleted then
  1263. for _, customer in ipairs(customerGroup) do
  1264. customer:ForcedToLeave()
  1265. end
  1266. self.state = "Idle"
  1267. return
  1268. end
  1269.  
  1270. -- deposit each of the orders
  1271. for _, orderedCustomer in ipairs(tookOrdersFrom) do
  1272. if orderedCustomer.isDeleted then
  1273. continue
  1274. end
  1275. orderedCustomer:ChangeToWaitingForFoodState(groupOrder[orderedCustomer.UID])
  1276. orderStand:AddFoodToQueue(groupOrder[orderedCustomer.UID])
  1277. end
  1278.  
  1279. -- award XP for taking an order
  1280. _L.Network.Fire("AwardWaiterExperienceForTakingOrderWithVerification", self.UID)
  1281.  
  1282. -- face deposit location
  1283. self:FaceEntity(orderStand)
  1284.  
  1285. -- free up the waiter for more actions
  1286. self.state = "Idle"
  1287.  
  1288. end)
  1289. end)
  1290.  
  1291. end)
  1292. end)
  1293.  
  1294. return true
  1295.  
  1296. end
  1297.  
  1298. function Waiter:CheckForQueuedCustomers()
  1299.  
  1300. if not _L.Variables.MyBakery.isOpen then
  1301. return false
  1302. end
  1303.  
  1304.  
  1305. local myFloor = self:GetMyFloor()
  1306.  
  1307. -- if I'm not on the first floor, only go to help if there is nobody
  1308. -- idle on the first floor
  1309. if myFloor.floorLevel ~= 1 then
  1310. if _L.Variables.MyBakery.floors[1]:HasAtLeastOneIdleStateOfClass("Waiter") then
  1311. return false
  1312. end
  1313.  
  1314. -- only allow myself to go de-queue a customer if there are 5 or less waiters
  1315. -- on the first floor. no need to overdo it.
  1316. if #_L.Variables.MyBakery.floors[1].waiters > 5 then
  1317. return false
  1318. end
  1319. end
  1320.  
  1321. -- search for the top of the queue customer group that is ready
  1322. -- to be seated
  1323. local readyCustomerGroup = nil
  1324. for _, customerGroup in ipairs(_L.Variables.MyBakery.customerQueue) do
  1325. if customerGroup[1].state == "WaitingForSeat" and not customerGroup[1].waiterIsAttendingToInQueue then
  1326. readyCustomerGroup = customerGroup
  1327. break
  1328. end
  1329. end
  1330.  
  1331. if not readyCustomerGroup then
  1332. return false
  1333. end
  1334.  
  1335. -- tag each customer as attended to
  1336. for _, customer in ipairs(readyCustomerGroup) do
  1337. customer.waiterIsAttendingToInQueue = true
  1338. end
  1339. local firstCustomer = readyCustomerGroup[1]
  1340.  
  1341. -- waiter is attending to me but I still haven't been seated? timeout
  1342. coroutine.wrap(function()
  1343. wait()
  1344. if #readyCustomerGroup == 0 then
  1345. return
  1346. end
  1347. if readyCustomerGroup[1].waiterIsAttendingToInQueue and readyCustomerGroup[1].state == "WaitingForSeat" then
  1348. --_L.Print("timeout successful")
  1349. for _, customer in ipairs(readyCustomerGroup) do
  1350. customer.waiterIsAttendingToInQueue = false
  1351. end
  1352. end
  1353. end)()
  1354.  
  1355. self.state = "WalkingToQueuedCustomerGroup"
  1356.  
  1357. -- walk to one of the customers in the queue group
  1358.  
  1359.  
  1360.  
  1361. -- it's possible that the user sends the customers to their
  1362. -- seat before we get there. if so, abort
  1363. if firstCustomer.state ~= "WaitingForSeat" or firstCustomer.stateData.busyWalking then
  1364. -- untag attending
  1365. for _, customer in ipairs(readyCustomerGroup) do
  1366. customer.waiterIsAttendingToInQueue = false
  1367. end
  1368. self:ResetAllStates()
  1369. return
  1370. end
  1371.  
  1372. -- stop user pings
  1373. firstCustomer:CleanupGroupInteract()
  1374. firstCustomer:StopGroupEmoji()
  1375.  
  1376. -- seat the customer group
  1377. _L.Variables.MyBakery:SeatQueuedCustomerGroup(firstCustomer)
  1378.  
  1379. -- update positioning
  1380. _L.Variables.MyBakery:UpdateCustomerQueuePositioning()
  1381.  
  1382. -- face the group
  1383. self:FaceEntity(firstCustomer)
  1384.  
  1385. -- free the waiter up
  1386. self.state = "Idle"
  1387.  
  1388. return true
  1389.  
  1390. end
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399. local rng = Random.new()
  1400.  
  1401.  
  1402. function Bakery:AddCustomersToQueueIfNecessary(kickCustomerIfNecessary, UIDBatch)
  1403.  
  1404. -- helper function
  1405. local function goToSeat(customer, doNotPlaySound)
  1406. if customer.state ~= "WaitingForSeat" then
  1407. -- error sound
  1408. if not doNotPlaySound then
  1409. _L.Audio.Play(5074110087, player.PlayerGui)
  1410. end
  1411. return
  1412. end
  1413. customer:StopGroupEmoji()
  1414. customer:CleanupGroupInteract()
  1415.  
  1416. self:SeatQueuedCustomerGroup(customer)
  1417. self:UpdateCustomerQueuePositioning()
  1418.  
  1419. -- click sound
  1420. if not doNotPlaySound then
  1421. _L.Audio.Play(5074101610, player.PlayerGui)
  1422. end
  1423. end
  1424.  
  1425. -- max queue size of 4
  1426. if #self.customerQueue >= 4 then
  1427. return 0
  1428. end
  1429.  
  1430. -- every customer is initially on the first floor
  1431. local firstFloor = self.floors[1]
  1432.  
  1433. -- grab all available seats. search floors at random until a seat group is found
  1434. local selectedTable, selectedSeatGroup
  1435. local indices = _L.Functions.RandomIndices(_L.Variables.MyBakery.floors)
  1436. for _, index in ipairs(indices) do
  1437. local floor = self.floors[index]
  1438. selectedTable, selectedSeatGroup = floor:GetAvailableSeatGroupings()
  1439. if selectedTable and selectedSeatGroup then
  1440. break
  1441. end
  1442. end
  1443.  
  1444. if not (selectedTable and selectedSeatGroup) then
  1445.  
  1446. -- if we didn't find a seat and kickCustomerIfNecessary (for VIP customers), then
  1447. -- kick a random customer for the VIP customer
  1448. if kickCustomerIfNecessary then
  1449. local didKickCustomer = false
  1450. for _, floor in ipairs(self.floors) do
  1451. for _, customer in ipairs(floor.customers) do
  1452. if customer.state ~= "ReadyToExit" then
  1453. customer:ForcedToLeave()
  1454. didKickCustomer = true
  1455. break
  1456. end
  1457. end
  1458. if didKickCustomer then
  1459. break
  1460. end
  1461. end
  1462.  
  1463. end
  1464.  
  1465. return 0
  1466. end
  1467. local queueEntry = {}
  1468.  
  1469. local didPlayVIPCustomerSound = false
  1470.  
  1471. -- if a vip is forced (royal set), let the server know
  1472. local vipOverride = {}
  1473. local johnDoeOverride = {}
  1474. local pirateOverride = {}
  1475. local youtuberOverride = {}
  1476. local shadowOverride = {}
  1477. local corruptedVIPOverride = {}
  1478. local santaOverride = {}
  1479. local elfOverride = {}
  1480. local treeTable = {}
  1481.  
  1482. -- create customers to fill this seat grouping
  1483. local containsGhostOrSpecial = false
  1484. for i, seatGroup in pairs(selectedSeatGroup) do
  1485. local seat = seatGroup
  1486. local tabl = selectedTable
  1487.  
  1488. local forceVIPCustomer = false
  1489. local forceShadowCustomer = false
  1490. local forceJohnDoeCustomer = false
  1491. local forcePirateCustomer = false
  1492. local forceYoutuberCustomer = false
  1493. local forceSantaCustomer = false
  1494. local forceElfCustomer = false
  1495.  
  1496. -- look for a nearby christmas tree
  1497. local floor = self.floors[seat.floorLevel]
  1498. for _, entity in ipairs(floor:GetEntitiesFromClassAndSubClass("Furniture", "ChristmasTree")) do
  1499. local dist = math.sqrt(math.pow(entity.xVoxel - seat.xVoxel, 2) + math.pow(entity.zVoxel - seat.zVoxel, 2))
  1500. if dist < 4*math.sqrt(2)+0.1 then
  1501. treeTable[i] = true
  1502. break
  1503. end
  1504. end
  1505.  
  1506. -- royal table logic
  1507. local overrideUID = nil
  1508. if seat.ID == "43" and tabl.ID == "44" then
  1509. forceVIPCustomer = true
  1510. overrideUID = seat.UID
  1511. elseif seat.ID == "43" then
  1512. forceVIPCustomer = true
  1513. overrideUID = seat.UID
  1514. elseif tabl.ID == "44" then
  1515. forceVIPCustomer = true
  1516. overrideUID = tabl.UID
  1517. end
  1518.  
  1519. if forceVIPCustomer then
  1520. UIDBatch[i].ID = "13"
  1521. vipOverride[i] = overrideUID
  1522. end
  1523.  
  1524. -- royal halloween table logic
  1525. if not forceVIPCustomer then
  1526. if seat.ID == "98" and tabl.ID == "99" then
  1527. forceShadowCustomer = true
  1528. overrideUID = seat.UID
  1529. elseif seat.ID == "98" then
  1530. forceShadowCustomer = true
  1531. overrideUID = seat.UID
  1532. elseif tabl.ID == "99" then
  1533. forceShadowCustomer = true
  1534. overrideUID = tabl.UID
  1535. end
  1536. -- 1% chance for haunted customer, otherwise corrupted VIP
  1537. if forceShadowCustomer then
  1538. UIDBatch[i].ID = "26"
  1539. corruptedVIPOverride[i] = overrideUID
  1540. end
  1541. end
  1542.  
  1543. -- John Doe Table Logic
  1544. if not forceVIPCustomer then
  1545. if seat.ID == "216" and tabl.ID == "217" then
  1546. forceJohnDoeCustomer = true
  1547. overrideUID = seat.UID
  1548. elseif seat.ID == "216" then
  1549. forceJohnDoeCustomer = true
  1550. overrideUID = seat.UID
  1551. elseif tabl.ID == "217" then
  1552. forceJohnDoeCustomer = true
  1553. overrideUID = tabl.UID
  1554. end
  1555. --Force John Doe
  1556. if forceJohnDoeCustomer then
  1557. -- if math.random() < 0.005 then
  1558. UIDBatch[i].ID = "29"
  1559. johnDoeOverride[i] = overrideUID
  1560. -- else
  1561. --UIDBatch[i].ID = "26"
  1562. --corruptedVIPOverride[i] = overrideUID
  1563. end
  1564. end
  1565. -- end
  1566.  
  1567. -- pirate table logic
  1568. if not forceVIPCustomer and not forceShadowCustomer then
  1569. if seat.ID == "74" and tabl.ID == "75" then
  1570. forcePirateCustomer = true
  1571. overrideUID = seat.UID
  1572. elseif seat.ID == "74" then
  1573. forcePirateCustomer = true
  1574. overrideUID = seat.UID
  1575. elseif tabl.ID == "75" then
  1576. forcePirateCustomer = true
  1577. overrideUID = tabl.UID
  1578. end
  1579.  
  1580. if forcePirateCustomer then
  1581. UIDBatch[i].ID = "21"
  1582. pirateOverride[i] = overrideUID
  1583. end
  1584. end
  1585.  
  1586. -- gamer table logic
  1587. if not forceVIPCustomer and not forcePirateCustomer and not forceShadowCustomer then
  1588. if seat.ID == "84" and tabl.ID == "85" then
  1589. forceYoutuberCustomer = true
  1590. overrideUID = seat.UID
  1591. elseif seat.ID == "84" then
  1592. forceYoutuberCustomer = true
  1593. overrideUID = seat.UID
  1594. elseif tabl.ID == "85" then
  1595. forceYoutuberCustomer = true
  1596. overrideUID = tabl.UID
  1597. end
  1598.  
  1599. if forceYoutuberCustomer then
  1600. UIDBatch[i].ID = "22"
  1601. youtuberOverride[i] = overrideUID
  1602. end
  1603. end
  1604.  
  1605. -- santa table logic
  1606. if not forceVIPCustomer and not forcePirateCustomer and not forceShadowCustomer and not forceYoutuberCustomer then
  1607. if seat.ID == "108" and true then
  1608. forceSantaCustomer = true
  1609. overrideUID = seat.UID
  1610. UIDBatch[i].ID = "27"
  1611. santaOverride[i] = overrideUID
  1612. end
  1613. end
  1614.  
  1615. -- elf table logic
  1616. if not forceVIPCustomer and not forcePirateCustomer and not forceShadowCustomer and not forceYoutuberCustomer and not forceSantaCustomer then
  1617. if seat.ID == "110" and tabl.ID == "111" then
  1618. forceElfCustomer = true
  1619. overrideUID = seat.UID
  1620. elseif seat.ID == "110" then
  1621. forceElfCustomer = true
  1622. overrideUID = seat.UID
  1623. elseif tabl.ID == "111" then
  1624. forceElfCustomer = true
  1625. overrideUID = tabl.UID
  1626. end
  1627.  
  1628. if forceElfCustomer then
  1629. UIDBatch[i].ID = "28"
  1630. elfOverride[i] = overrideUID
  1631. end
  1632. end
  1633.  
  1634. local sx, sy, sz = self:GetCustomerStartVoxel(i, #selectedSeatGroup)
  1635. local fx, fy, fz = self:GetCustomerQueueVoxel(i, -5, #selectedSeatGroup)
  1636. local createdCustomer = _L.Customer.CreateRandomCustomer(UIDBatch[i], sx, sy, sz)
  1637. local worldStart = firstFloor:WorldPositionFromVoxel(sx, sy, sz)
  1638. local queueFront = firstFloor:WorldPositionFromVoxel(fx, fy, fz)
  1639. createdCustomer.stateData.seatUID = seat.UID
  1640. createdCustomer.stateData.tableUID = tabl.UID
  1641. createdCustomer.stateData.queuePosition = #self.customerQueue + 1
  1642. createdCustomer.isNearTree = treeTable[i] ~= nil
  1643. createdCustomer:SetVoxelPosition(self:GetCustomerStartVoxel(i, #selectedSeatGroup))
  1644.  
  1645. -- center the customer group...... remember that max group size is 4
  1646. if createdCustomer:BelongsToMyBakery() then
  1647. if #selectedSeatGroup % 2 == 0 then
  1648. createdCustomer.model:SetPrimaryPartCFrame(CFrame.new(worldStart + Vector3.new(0, 2, 0), queueFront))
  1649. elseif #selectedSeatGroup == 1 then
  1650. local startCFrame = CFrame.new(worldStart + Vector3.new(0, 2, 0)) * CFrame.Angles(0, self.baseAngle, 0) * CFrame.new(2, 0, 0)
  1651. local faceCFrame = CFrame.new(queueFront) * CFrame.Angles(0, self.baseAngle, 0) * CFrame.new(2, 0, 0)
  1652. createdCustomer.model:SetPrimaryPartCFrame(CFrame.new(startCFrame.p, faceCFrame.p))
  1653. elseif #selectedSeatGroup == 3 then
  1654. local startCFrame = CFrame.new(worldStart + Vector3.new(0, 2, 0)) * CFrame.Angles(0, self.baseAngle, 0) * CFrame.new(-2, 0, 0)
  1655. local faceCFrame = CFrame.new(queueFront) * CFrame.Angles(0, self.baseAngle, 0) * CFrame.new(-2, 0, 0)
  1656. createdCustomer.model:SetPrimaryPartCFrame(CFrame.new(startCFrame.p, faceCFrame.p))
  1657. end
  1658. end
  1659.  
  1660. -- special customer notifications
  1661. if _L.PlayerSettings.GetSetting("Notifications") == "Enabled" then
  1662. -- Haunted Horseman
  1663. if createdCustomer.ID == "25" and not didPlayVIPCustomerSound then
  1664. didPlayVIPCustomerSound = true
  1665. _L.SFX.Play(5839736886, player.PlayerGui, nil, 1)
  1666. _L.Alert.Message("The Headless Horseman has entered your Restaurant!")
  1667. end
  1668.  
  1669. -- Santa
  1670. if createdCustomer.ID == "27" and not didPlayVIPCustomerSound then
  1671. didPlayVIPCustomerSound = true
  1672. _L.SFX.Play("6106142958", player.PlayerGui)
  1673. _L.Alert.Message("Santa has entered your Restaurant!")
  1674. end
  1675.  
  1676. -- VIP customer? play sound for at least one
  1677. if createdCustomer.ID == "13" and not didPlayVIPCustomerSound then
  1678. didPlayVIPCustomerSound = true
  1679. _L.SFX.Play(5174014731, player.PlayerGui)
  1680. _L.Alert.Message("A VIP Customer has entered your Restaurant!")
  1681. end
  1682.  
  1683. -- celebrity customer?
  1684. if createdCustomer.ID == "20" and not didPlayVIPCustomerSound then
  1685. didPlayVIPCustomerSound = true
  1686. _L.SFX.Play(5278932246, player.PlayerGui)
  1687. _L.Alert.Message("A Celebrity Customer has entered your Restaurant!")
  1688. end
  1689.  
  1690. -- pirate customer
  1691. if createdCustomer.ID == "21" and not didPlayVIPCustomerSound then
  1692. didPlayVIPCustomerSound = true
  1693. _L.SFX.Play(5601560215, player.PlayerGui, nil, 0.25)
  1694. _L.Alert.Message("A Pirate Customer has entered your Restaurant!")
  1695. end
  1696.  
  1697. -- youtuber customer
  1698. if createdCustomer.ID == "22" and not didPlayVIPCustomerSound then
  1699. didPlayVIPCustomerSound = true
  1700. _L.SFX.Play(5625433365, player.PlayerGui, nil, 0.25)
  1701. _L.Alert.Message("A Youtuber Customer has entered your Restaurant!")
  1702. end
  1703.  
  1704. -- corrupted VIP
  1705. if createdCustomer.ID == "26" and not didPlayVIPCustomerSound then
  1706. didPlayVIPCustomerSound = true
  1707. _L.SFX.Play(5839737683, player.PlayerGui, nil, 0.25)
  1708. _L.Alert.Message("A Haunted VIP Customer has entered your Restaurant!")
  1709. end
  1710.  
  1711. --John Doe
  1712. if createdCustomer.ID == "29" and not didPlayVIPCustomerSound then
  1713. didPlayVIPCustomerSound = true
  1714. _L.SFX.Play(5839737683, player.PlayerGui, nil, 0.25)
  1715. _L.Alert.Message("John Doe has entered your Restaurant!")
  1716. end
  1717. end
  1718.  
  1719. if createdCustomer.ID == "14" or createdCustomer.ID == "15" then
  1720. containsGhostOrSpecial = true
  1721. end
  1722.  
  1723. -- finally give the customer a parent (prevents weird teleporting from corner thing)
  1724. createdCustomer.model.Parent = createdCustomer.cachedParent
  1725. createdCustomer:FadeTransparency(createdCustomer:GetMyTransparency())
  1726.  
  1727. -- replication event.. customer created
  1728. _L.Replication.SendEvent("CustomerCreated", createdCustomer:ToUIDData())
  1729.  
  1730. -- tutorial table + flag
  1731. if self.isTutorial then
  1732. table.insert(self.tutorial.firstCustomerWave, createdCustomer)
  1733. self.tutorial.hasAllowedFirstWaveOfCustomers = true
  1734. end
  1735.  
  1736. seat:SetIsOccupied(createdCustomer)
  1737. tabl:AddCustomerAtTable(createdCustomer)
  1738.  
  1739. createdCustomer:Emoji("WaitingForSeat", true)
  1740.  
  1741. createdCustomer:Interact(function()
  1742. goToSeat(createdCustomer)
  1743. end)
  1744.  
  1745. -- celebrity customer flag
  1746. if createdCustomer.ID == "20" then
  1747. _L.Variables.MyBakery.activeCelebrity = true
  1748. end
  1749.  
  1750. table.insert(queueEntry, createdCustomer)
  1751.  
  1752. end
  1753.  
  1754. -- initialize each customer's queue group. the customer can NOT be
  1755. -- inside of their own queue group, since cyclic tables are not permitted
  1756. for _, customer0 in ipairs(queueEntry) do
  1757. customer0.stateData.queueGroup = {}
  1758. for _, customer1 in ipairs(queueEntry) do
  1759. if customer0 ~= customer1 then
  1760. table.insert(customer0.stateData.queueGroup, customer1)
  1761. end
  1762. end
  1763. end
  1764.  
  1765. table.insert(self.customerQueue, queueEntry)
  1766.  
  1767. if not containsGhostOrSpecial then
  1768. self:UpdateCustomerQueuePositioning()
  1769. else
  1770. goToSeat(queueEntry[1], true)
  1771. end
  1772.  
  1773. return #selectedSeatGroup, vipOverride, pirateOverride, youtuberOverride, shadowOverride, corruptedVIPOverride, santaOverride, elfOverride, johnDoeOverride, treeTable
  1774.  
  1775. end
  1776.  
  1777.  
  1778. local bakeryData = _L.Variables.UIDData
  1779. if not bakeryData then
  1780. repeat wait() bakeryData = _L.Variables.UIDData until bakeryData
  1781. end
  1782.  
  1783. --"🐈"-bluwu
  1784. local Wells = {"101","49","50"}
  1785. local Slots = {"57"}
  1786. local UNIT_SECOND = 1
  1787. local UNIT_MINUTE = UNIT_SECOND * 60
  1788. local SLOT_REFRESH = UNIT_MINUTE * 10
  1789.  
  1790. local function useWell(wellUID, wellId)
  1791. local event = "RequestWishingWellUsage"
  1792. if wellId == "101" then
  1793. event = "RequestHauntedWishingWellUsage"
  1794. end
  1795. _L.Network.Fire(event,wellUID)
  1796. end
  1797. coroutine.wrap(function()
  1798. while true do
  1799. for i,v in next, bakeryData["Furniture"] do
  1800. local ID = v.ID
  1801. if ID and table.find(Wells,ID) and v.ClassName == "Furniture" then
  1802. task.spawn(function()
  1803. local event = "GetWishingWellRefreshTime"
  1804. if ID == "101" then
  1805. event = "GetHauntedWishingWellRefreshTime"
  1806. end
  1807. local cooldown = _L.Network.Invoke(event,v.UID)
  1808. if not isOnCooldown then
  1809. useWell(v.UID, ID)
  1810. end
  1811. end)
  1812. end
  1813. if ID and table.find(Slots,ID) then
  1814. task.spawn(function()
  1815. local cooldown = _L.Network.Invoke("GetSlotRefreshTime")
  1816. if cooldown == 0 then
  1817. _L.Network.Fire("RequestSlotUsage", v.UID)
  1818. end
  1819. end)
  1820. end
  1821. end
  1822. task.wait(3)
  1823. end
  1824. end)()
  1825. -- script wasnt made by me lol --
Add Comment
Please, Sign In to add comment