Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --MainGameLoop.lua
- game.Workspace.Remote:WaitForChild("ServerLocal"):WaitForChild("VarsSanCheck"):Fire() --Oh geez I better run this at game start O_O
- local Const = require(script.Parent.Parent.Constants.Const)
- local LibCommon = require(script.Parent.Parent.Lib.LibCommon)
- local LibInit = require(script.Parent.Parent.Lib.LibInit)
- local LibModel = require(game.Workspace.Lib.LibModel)
- local LibString = require(script.Parent.Parent.Lib.LibString)
- local Remote = require(script.Parent.Parent.Remote.Remote)
- local TrackGeneratorFactory = require(script.Parent.Parent.TrackGenerator.TrackGeneratorFactory)
- local Vars = game.Workspace:WaitForChild("Vars")
- --Important pointers
- local announcementText = game.StarterGui.AnnouncerBillboard.BillboardGui.GameStatus
- LibInit.gameStateInit()
- local gameState = script.Parent.Parent.GameState
- local playerLocScript = Const.LocalScripts.PlayerLocator:Clone()
- local loadingScreenScript = Const.LocalScripts.LoadingScreen:Clone()
- local cameraConfigScript = Const.LocalScripts.RaceCameraConfig:Clone()
- local listeners = {}
- local themeList = { "Theme_RoArena", "Theme_Desert", "Theme_Jungle", "Theme_Tundra", "Theme_Trollplanet" }
- --One-time inits
- if game.Workspace:FindFirstChild("ArenaStands") == nil then LibModel.regenStands(Vars.FieldSize.Value.x, Vars.FieldSize.Value.z) end
- --Race running
- function raceLogic()
- local finishLine = game.Workspace.CourseModels.FinishLinePointer.Value.trigger_finishline
- local numPlayersFinished = 0
- finishLine.Touched:connect(function(part)
- if part.Name ~= "HumanoidRootPart" then return end
- local player = game.Players:FindFirstChild(part.Parent.Name)
- if player == nil then return end
- local playerData = Const.getRaceDataForPlayer(player)
- if playerData == nil then return end
- if not playerData.IsRacing.Value then return end
- if playerData.CurrentLap.Value < 1 then playerData.CurrentLap.Value = 1 end
- if playerData.CurrentLap.Value > Const.getTrackData().NumLaps.Value then playerData.CurrentLap.Value = Const.getTrackData().NumLaps.Value end
- local nodeCount = #(playerData.VisitedNodes:GetChildren())
- if nodeCount > #(Const.getTrackNodes():GetChildren()) * 0.75 then
- if playerData.CurrentLap.Value == Const.getTrackData().NumLaps.Value then
- playerData.IsRacing.Value = false
- playerData.CurrentLap.Value = playerData.CurrentLap.Value + 1 --Needs to go to 4 to trigger the final lap-recording
- game.Workspace.GameState.PlayersStillRacing:FindFirstChild(player.Name):Remove()
- numPlayersFinished = numPlayersFinished + 1
- playerData.FinishPosition.Value = numPlayersFinished
- playerData.PlayerRaceState.Value = "Finish"
- updateAnnouncementTextRacerCount()
- delay(0, function()
- local kart = player.Character:FindFirstChild(player.Name.."'s Kart")
- if kart then while kart.VehicleSeat.MaxSpeed > 0 do kart.VehicleSeat.MaxSpeed = kart.VehicleSeat.MaxSpeed - 1 wait() end end
- end)
- else
- playerData.CurrentLap.Value = playerData.CurrentLap.Value + 1
- playerData.VisitedNodes:ClearAllChildren()
- end
- --HUD stuff, this is AFTER lap incrementing.
- if playerData.CurrentLap.Value == Const.getTrackData().NumLaps.Value and playerData.PlayerRaceState.Value ~= "Finish" then
- playerData.PlayerRaceState.Value = "FinalLap"
- elseif playerData.PlayerRaceState.Value ~= "Finish" then
- playerData.PlayerRaceState.Value = "Lap"..playerData.CurrentLap.Value
- end
- end
- end)
- local continueRace = true
- --Race-place tracker
- delay(0, function()
- while continueRace do
- local playerTable = game.Workspace.PlayerData:GetChildren()
- local count = #playerTable
- for i = 1, count do
- local most = playerTable[1].RaceDistance.Value
- local mostPlayer = playerTable[1].Name
- local index = 1
- for j = 1, #playerTable do
- if playerTable[j].RaceDistance.Value > most then
- most = playerTable[j].RaceDistance.Value
- mostPlayer = playerTable[j].Name
- index = j
- end
- end
- game.Workspace.PlayerData:FindFirstChild(mostPlayer).Position.Value = i
- table.remove(playerTable, index)
- end
- wait()
- end
- end)
- --Check for players finishing
- game.Workspace.GameState.PlayersStillRacing.ChildRemoved:connect(function()
- pcall(function() if #(game.Workspace.GameState.PlayersStillRacing:GetChildren()) == 0 then continueRace = false end end)
- end)
- while continueRace do wait() end
- --Verify that no players left after crossing finish line, and adjust if necessary
- local playerTable = game.Workspace.PlayerData:GetChildren()
- if #playerTable ~= numPlayersFinished then
- local numPlayers = #playerTable
- for i = 1, numPlayers do
- local leastPlayer = playerTable[1]
- local leastIndex, iterations = 1, 1
- --Get the lowest-numbered-finish player, since the /order/ of finishing is still valid
- for _, player in pairs(playerTable) do
- if player.FinishPosition.Value < leastPlayer.FinishPosition.Value then leastPlayer = player leastIndex = iterations end
- iterations = iterations + 1
- end
- leastPlayer.FinishPosition.Value = i
- table.remove(playerTable, leastIndex) --This is valid because playerTable is merely a list of object pointers, not PlayerData directly
- end
- --In theory, the table should now be "compacted"
- end
- end
- function deregisterRacer(player, playerList, playerData)
- --Find the player index, to remove them
- local playerWasRacer = false
- for i = 1, #playerList do if playerList[i] == player then playerWasRacer = true table.remove(playerList, i) break end end
- if playerWasRacer then
- pcall(function() playerData:FindFirstChild(player.Name):Remove() end)
- pcall(function() game.Workspace.GameState.PlayersStillRacing:FindFirstChild(player.Name):Remove() end)
- end
- gameState.RacingPlayerCount.Value = #playerList
- updateAnnouncementTextRacerCount()
- end
- function updateAnnouncementTextRacerCount()
- local playersRacing = #(game.Workspace.GameState.PlayersStillRacing:GetChildren())
- local playersFinished = #(game.Workspace.PlayerData:GetChildren()) - #(game.Workspace.GameState.PlayersStillRacing:GetChildren())
- local racingText, finishText
- if playersRacing == 0 then racingText = "" elseif playersRacing == 1 then racingText = "1 Player is Racing!" else
- racingText = playersRacing.." Players are Racing!" end
- if playersFinished == 0 then finishText = "" elseif playersFinished == 1 then finishText = "\n1 Player has Finished!" else
- finishText = "\n"..playersFinished.." Players have Finished!" end
- announcementText.Text = racingText..finishText
- end
- --Aaaand let's-a-go!
- while true do
- --Once-per-race inits
- game.Workspace.Remote:WaitForChild("ServerLocal"):WaitForChild("VarsSanCheck"):Fire()
- LibInit.gameStateInit()
- fieldSize = Vars.FieldSize.Value
- gameState = script.Parent.Parent.GameState
- Remote.setGameState("NotRacing")
- gameState.RacingPlayerCount.Value = 0
- gameState.RacingPlayersPreloaded.Value = 0
- gameState.RacingPlayersSeated.Value = 0
- LibInit.timerStartReset()
- LibInit.trackDataInit(fieldSize.x, fieldSize.z)
- LibInit.regenBaseTiles(fieldSize.x, fieldSize.z)
- listeners = {}
- --Wait for playercount to be nonzero
- announcementText.Text = "Waiting for Players..."
- while game.Players.NumPlayers < 1 do wait(1) end
- for i = Vars.TimeBetweenRounds.Value or 15, 0, -1 do
- announcementText.Text = "Intermission ("..i..")"
- wait(1)
- end
- announcementText.Text = "Generating Track..."
- Remote.setGameState("Loading")
- wait(1)
- local success = false
- while not success do
- local didItFailed = false
- success, caught = pcall(function()
- local genseed = math.random(0, 2147483647)
- Vars.WorldSeed.Value = genseed
- Vars.RandomCalls.Value = 0
- Vars.CurrentTheme.Value = themeList[(Vars.NumRaces.Value % #themeList) + 1]
- local generator = TrackGeneratorFactory.getGenerator(Vars.GeneratorName.Value)
- if generator.GeneratorVersion == "Version2" then LibInit.trackgenGuiInit(fieldSize.x, fieldSize.z) end
- announcementText.Text = "Generating Track...\n[ID: "..LibString.encodeNumberAsTrackCode(genseed).."]"
- local oops = generator:generate(genseed)
- generator:model()
- if oops ~= "OK" then
- return "Generator exploded!"
- end
- end)
- if (not success) or didItFailed then
- print(caught)
- wait(10)
- for k, v in pairs(game.Workspace.BaseTiles:GetChildren()) do v.BrickColor = BrickColor.new("Medium stone grey") end
- pcall(function() game.Workspace.TrackData:Remove() end)
- LibInit.trackDataInit(fieldSize.x, fieldSize.z)
- end
- end
- announcementText.Text = "Track Generated. Starting..."
- Vars.RandomCalls.Value = 0
- wait(1)
- --Game start stuff
- --Note: This is the point of no return. Any further players joining after this point, will NOT be in the active race.
- --Also I'm pretty sure Past Me was smart enough to do this already, but: don't do any playercount checks on game.Players directly.
- local playerList = game.Players:GetChildren()
- for _, v in pairs(playerList) do loadingScreenScript:Clone().Parent = v.PlayerGui end
- wait()
- Remote.setGameState("PrepareToStart")
- local _, playerData = LibInit.playerRaceDataInit(playerList)
- require(game.Workspace.CourseModels.FinishLinePointer.Value.KartSpawner).spawnKarts(#playerList)
- --Player race cleanup if exit mid-race
- table.insert(listeners, game.Players.ChildRemoved:connect(function(player) deregisterRacer(player, playerList, playerData) end))
- for _, player in pairs(playerList) do table.insert(listeners, player.CharacterAdded:connect(function() deregisterRacer(player, playerList, playerData) end)) end
- wait(1)
- updateAnnouncementTextRacerCount()
- gameState.RacingPlayerCount.Value = #playerList
- local id = 0
- for k, v in pairs(playerList) do
- pcall(function()
- id = id + 1
- local kart = game.Workspace:FindFirstChild("KartyThing"..id)
- v.Character.HumanoidRootPart.CFrame = kart.VehicleSeat.CFrame
- kart.VehicleSeat.Anchored = true
- delay(0, function()
- --wait()
- cameraConfigScript:Clone().Parent = v.Character
- while not v.Character.Humanoid.Sit do v.Character.Humanoid.Jump = true wait() end
- gameState.RacingPlayersSeated.Value = gameState.RacingPlayersSeated.Value + 1
- kart.VehicleSeat.Anchored = false
- end)
- v.Character.Humanoid.WalkSpeed = 0
- v.PlayerGui.AnnouncerBillboard.BillboardGui.GameStatus.Visible = false
- kart.Name = v.Name.."'s Kart"
- kart.Parent = v.Character
- kart.VehicleSeat.MaxSpeed = 0
- Const.LocalScripts.ScoreHud:Clone().Parent = v.PlayerGui.RaceHud.HudFrame
- playerLocScript:Clone().Parent = v.Character
- end)
- end
- --Respawn stands formatted to currently active theme
- game.Workspace.ArenaStands:Destroy()
- LibModel.regenStands(fieldSize.x, fieldSize.z)
- --Player race cleanup if respawned after placed in kart
- for _, player in pairs(playerData:GetChildren()) do player.IsRacing.Value = true end
- local tooLongWaiting = 0
- local loadedPlayers = {}
- local preloaderCon
- preloaderCon = game.Workspace.Remote.ToServer.ClientLoaded.OnServerEvent:connect(function(player) table.insert(loadedPlayers, player) end)
- while gameState.RacingPlayersPreloaded.Value < gameState.RacingPlayerCount.Value
- or gameState.RacingPlayersSeated.Value < gameState.RacingPlayerCount.Value do
- wait(0.1) gameState.RacingPlayersPreloaded.Value = #loadedPlayers
- tooLongWaiting = tooLongWaiting + 1
- if tooLongWaiting >= 100 then game.Workspace.Remote.ToClient.LoadingTimeout:FireAllClients() break end --Ten seconds of loading, 8r8k it already!
- end
- preloaderCon:disconnect()
- for k, v in pairs(game.Workspace:GetChildren()) do if string.sub(v.Name, 1, 10) == "KartyThing" then v:Remove() end end
- gameState.RacingPlayersPreloaded:ClearAllChildren()
- --Fix a thing
- for _, fixDis in pairs(game.Workspace.CourseModels:GetChildren()) do
- if string.sub(fixDis.Name, string.len(fixDis.Name) - 4) == "[1,5]" then
- fixDis.Parent = nil
- wait()
- fixDis.Parent = game.Workspace.CourseModels
- end
- end
- Remote.setGameState("LoadComplete")
- wait(1)
- wait(3)
- Remote.setGameState("GetReady")
- for _, player in pairs(playerData:GetChildren()) do player.PlayerRaceState.Value = "GetReady" end
- wait(2)
- for k, v in pairs(playerList) do
- pcall(function()
- local kart = v.Character:FindFirstChild(v.Name.."'s Kart")
- if kart then kart.VehicleSeat.MaxSpeed = kart.VehicleSeat.NormalMaxSpeed.Value end
- end)
- end
- game.Workspace.GameState.RaceInProgress.Value = true
- Remote.setGameState("Go")
- for _, player in pairs(playerData:GetChildren()) do player.PlayerRaceState.Value = "Go" end
- --Go Speed Racer!
- raceLogic()
- --End race results
- game.Workspace.GameState.RaceInProgress.Value = false
- announcementText.Text = "Race Over"
- Remote.setGameState("ShowResults")
- for _, v in pairs(playerList) do Const.LocalScripts.RaceResults:Clone().Parent = v.PlayerGui.ResultsScreen end
- wait(1)
- local scoreboardData = LibInit.endRaceResults(playerData)
- wait(8)
- --Exploderate players!
- Remote.setGameState("BoomBaby")
- for _, player in pairs(playerList) do
- player.Character:BreakJoints()
- player.Character.PlayerLocator:Remove()
- if player.Character:FindFirstChild(player.Name.."'s Kart"):FindFirstChild("BoundingBox") then
- player.Character:FindFirstChild(player.Name.."'s Kart").BoundingBox:Remove()
- end
- player.PlayerGui.ResultsScreen.BGFrame.Visible = false
- player.PlayerGui.ResultsScreen.ResultsFrame.Visible = false
- end
- game.Players.CharacterAutoLoads = false --<haaaaaaaax>
- delay(3, function() for _, player in pairs(playerList) do player:LoadCharacter() end --Force-respawn all after 3 sec
- wait() game.Players.CharacterAutoLoads = true --</haaaaaaaax>
- end)
- --Data cleanup
- wait()
- pcall(function() game.Workspace.TrackData:Remove() playerData:Remove() scoreboardData:Remove() gameState:Remove() end)
- --print("Disconnecting "..#listeners.." listeners")
- for _, v in pairs(listeners) do pcall(function() v:disconnect() end) end listeners = {} --Disconnect all those now-useless listeners
- --Model cleanup
- wait(2)
- announcementText.Text = "Cleaning Track..."
- Remote.setGameState("Cleanup")
- wait(2)
- local trackModels = game.Workspace.CourseModels:GetChildren()
- for k, v in pairs(trackModels) do v:Remove() wait() end game.Workspace.CourseModels:Remove()
- for k, v in pairs(game.Workspace.BaseTiles:GetChildren()) do v.BrickColor = BrickColor.new("Medium stone grey") end
- if game.Workspace:FindFirstChild("TrackgenGuiData") ~= nil then game.Workspace.TrackgenGuiData:Remove() end
- Vars.NumRaces.Value = Vars.NumRaces.Value + 1
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement