Win Conditions
A win condition is a reusable rule that inspects the round's Context and determines whether the round has been won. Phases decide when to evaluate a win condition. The win condition decides whether a winner exists.
Defining a win condition
Register a win condition with WinCondition.new(name, evaluator):
RoundKit.WinCondition.new("LastAlive", function(context)
local players = context:GetPlayers()
local alive = {}
for _, player in ipairs(players) do
-- This metric should ideally be set by having an player.Character.Humanoid.Died event inside a phase.
if context:GetMetric(player, "Alive") ~= false then
table.insert(alive, player)
end
end
if #alive == 1 then
return {
Type = "Player",
Winners = alive,
}
end
return nil
end)
The evaluator receives the current Context and returns either:
nilif the round should continue.- A
WinOutcomeif a winner has been determined.
export type WinOutcome = {
Type: "Player" | "Team" | "Draw" | "None",
Winners: { Player | Team },
}
Register each win condition once, typically when your game starts. Registering the same name more than once raises an error.
Using a win condition
Reference a registered win condition by name, or pass a WinCondition instance directly.
RoundKit.new({
Phases = Phases,
InitialPhase = "Lobby",
WinCondition = "LastAlive",
})
Win conditions are evaluated only while the active phase has EvaluateWinCondition = true (see Defining Phases).
When the evaluator returns a WinOutcome, RoundKit fires the OnWinConditionMet event.
Active = {
Name = "Active",
EvaluateWinCondition = true,
OnEnter = function(context)
context:Connect("OnWinConditionMet", function(outcome)
context:SetGlobalMetric("LastOutcome", outcome)
context:TransitionTo("Results")
end)
end,
}
A win condition never transitions phases directly. The phase decides how to respond to the outcome.
Combining win conditions
Multiple win conditions can be combined with AnyOf and AllOf.
RoundKit.WinCondition.new("TimeLimit", function(context)
if context:GetElapsedTime() >= 120 then
return {
Type = "Draw",
Winners = {},
}
end
return nil
end)
RoundKit.new({
Phases = Phases,
InitialPhase = "Lobby",
WinCondition = RoundKit.WinCondition.AnyOf({
"LastAlive",
"TimeLimit",
}),
})
AnyOf
Evaluates each child condition in order and returns the first non nil WinOutcome.
Use it when any condition should end the round.
AllOf
Evaluates every child condition and returns a WinOutcome only after all of them succeed.
AllOf assumes every child agrees on the outcome. It returns the first successful WinOutcome; it does not merge multiple outcomes.
Both combinators accept registered condition names or WinCondition instances, and can be nested to build more complex logic.
The next section covers Player & Global State, which stores the data accessed through Context.