Hello, I’m looking for some ways to hopefully improve my code for my match managing system i think it’s pretty good, but I feel like there’s room for improvements.
local Remotes = RepStorage:WaitForChild("Remotes")
local MatchState = Remotes.MatchState --used for updating the clients when the match state changes
local timer = RepStorage.GameValues.Timer
local died = nil
local timePaused = false
local instance = {}
local startingTime = 99 -- -1 for infinite time
local onDeath = ServStorage.Events.OnDeath
local onRespawn = ServStorage.Events.OnRespawn
--this might be completely useless
local function OnDeath(character)
died = character
end
onDeath.Event:Connect(OnDeath)
local function OnRespawn(newInstance)
if newInstance.Name == instance.player1.Name then
instance.player1 = newInstance
else
instance.player2 = newInstance
end
instance.state.reset()
end
onRespawn.Event:Connect(OnRespawn)
function MatchManager.NewMatch()
--kind of yoinked UE naming with the pawn thing
--makes a new class for the player or npc if there is no player
local player1 = Pawn.new(Players:GetPlayers()[1],false,500,9) or Pawn.new(nil,true,500,9)
local player2 = Pawn.new(Players:GetPlayers()[2],false,500,9) or Pawn.new(nil,true,500,9)
player1:Setup(player2)
player2:Setup(player1)
--for smoother ai (this shouldnt go here but for some reason it works here)
if (not Players:GetPlayerFromCharacter(player2.Character)) and (Players:GetPlayerFromCharacter(player1.Character)) then
player2.HRP:SetNetworkOwner(Players:GetPlayers()[1])
end
instance.stage = StageManager:SpawnStage("Grid 3")
instance.rounds = 3 --total rounds
instance.round = 1 --current round
instance.time = startingTime
instance.roundWinner = nil
instance.roundOver = false --useless
instance.test = "" --the text to display when the match ends (ex: K.O. or DRAW)
instance.firstHit = nil
instance.player1 = player1
instance.player2 = player2
instance.state = FSM.create({ --finite-state machine for managing match states
initial = "begin",
events = {
{name = "begin", from = "reset", to = "begin"},
{name = "reset", from = "begin", to = "reset"},
--{name = "end", from = "crouch", to = "idle"},
},
callbacks = {
on_enter_begin = function(self,event,from,to,msg)
--stuff for begin state
timePaused = false
StageManager:TeleportToStage(instance.player1,instance.player2)
MatchState:FireAllClients(self.current,instance)
end,
on_enter_reset = function(self,event,from,to,msg)
--stuff for reset state
timePaused = true
instance.time = startingTime
ServerCombat.firstHit = nil
instance.round += 1
instance.roundWinner = instance:CheckWinner()
MatchState:FireAllClients(self.current,instance)
task.wait(3)
if self.can("begin") then
self.begin()
else
warn("[SERVER]: Unable to switch to begin state")
end
end,
}
})
--Timer
local currentFrame = 0
RunService.Heartbeat:Connect(function()
currentFrame += 1
if (currentFrame % 60) == 1 then --can be any number from 1 to 59
timer.Value = instance.time
if (instance.state.current == "begin") and (not timePaused) then
if timer.Value == 0 then
if instance.state.can("reset") then --checks if we're able to go into the reset state
instance.state.reset()
else
warn("[SERVER]: Unable to switch to reset state")
end
else
instance.time -= 1
end
end
end
end)
return setmetatable(instance,MatchManager)
end
A scuffed explanation of how the code works
Basically, I decided to use OOP although it ended up being kind of useless with the way I ended up coding things it could still be useful in the future though if I do need to add on to it, but I use OOP to make a new match which just has info about the match like the rounds, players in it the state etc and whenever the match goes into a new state I just send it all to the client so it can update with the new info. I also learned about finite state machines which I used for managing the state of the match and changing it when needed which is what that instance.state
is for.