Co-op Rules
In short
One shared score and one shared outs pool per inning. Players bat in lobby order; a turn lasts until the batter makes an out (each turn costs the pool exactly one out). The pool is max(solo outs per inning, players still in), so 3 on Normal and Medium, 2 on Hard, but never fewer than the number of players. Reach the goal and the inning is cleared at once; empty the pool first and the run is over.
How it works
CoopRules is the referee. It lives only on the host, has no Unity objects and is tested headless.
- Order. Player ids in lobby order, fixed when the run starts (
StartRun). - Opener rotation. Inning
r(0-based) opens with seatr mod players. If that player has left, the next seat still in opens. So the first batter moves one seat on each inning. - Pool. At the start of each inning:
OutsPool = max(soloOuts, ActiveCount), wheresoloOutsisRunManager.OutsPerInning(config, difficulty)andActiveCountis the players still in. - A turn. The batter’s own machine plays a mini-round starting from the team score (see Co-op Run Flow).
When it ends, the host gets the score the turn added (
CompleteTurn(player, scoreGained)):- Team score +=
max(0, scoreGained). - If team score ≥ goal: the inning is Cleared (the turn ended on the clearing hit, not an out). No out is charged.
- Otherwise one out comes off the pool. If the pool is now empty: Failed (run over). Else the turn passes to
the next seat still in, and
TurnIndexgoes up by one.
- Team score +=
- Second life.
CoopRules.OutsForTurn(extraOuts): a batter whose stats give Extra Outs > 0 gets 2 outs on their own turn, otherwise 1. Their first out neither ends the turn nor costs the pool. Never more than one extra life, however many Extra Outs they own. The HUD shows SECOND LIFE. - Drops.
RemovePlayer(player): the player never bats again this run. If it was their turn, the turn passes without costing an out. If nobody is left, the inning is Failed. In the shop, a leaver is removed from the READY wait. - Wrong batter.
CompleteTurnthrows if the player is not the current batter;CoopRunignores staleTurnEnds from a player who already left.
stateDiagram-v2 [*] --> NotStarted NotStarted --> Playing: StartRound(index, goal) Playing --> Playing: CompleteTurn below goal, pool left → next batter Playing --> Playing: batter leaves → next batter, no out Playing --> Cleared: team score ≥ goal Playing --> Failed: pool empty, or nobody left Cleared --> Playing: next StartRound
Coins (per player, computed on each machine)
When an inning ends, every machine pays its own player with RunManager.InningCoins:
coins = myHomeRuns × (coinsPerHomeRun + CoinBonus stat) + my $$$ bonus coins
if cleared: coins += coinsPerInning + teamOutsLeft × coinsPerLeftoverOut + (boss inning ? bossBonusCoins : 0)
- Own: home runs you hit this inning (over all your turns), and $$$ special-ball coins you hit out.
- Shared: the clear pay, the leftover-out pay (from the team pool) and the boss bonus go to every player equally.
- A failed inning pays only your own home runs (and then the run ends).
Score
- The team score starts at 0 each inning.
node.scoreandRunState.TotalScoreon every machine get the team score, so the run total is the team’s total. - Your machine also counts your own
HomeRunsandLongestFtfor the run summary and XP.
Numbers
| What | Value | Where to tune |
|---|---|---|
| Solo outs per inning | 3 | RunConfig.outsPerInning |
| Hard difficulty | −1 out (so 2) | Difficulties.OutsDelta |
| Outs per inning (never below) | 1 | RunManager.OutsPerInning |
| Pool | max(soloOuts, players still in) | CoopRules.PoolFor |
| Pool, 2-3 players, Normal / Medium | 3 | |
| Pool, 4 players, any difficulty | 4 | |
| Pool, 2 players, Hard | 2 | |
| Outs on your turn | 1, or 2 with Extra Outs > 0 | CoopRules.OutsForTurn |
| Outs a turn costs the pool | 1 (0 if the turn clears the goal or the batter leaves) | CoopRules.CompleteTurn |
| Coins per home run | 1 + CoinBonus | RunConfig.coinsPerHomeRun |
| Inning clear pay (everyone) | 4 | RunConfig.coinsPerInning |
| Per leftover team out (everyone) | 1 | RunConfig.coinsPerLeftoverOut |
| Boss inning bonus (everyone) | 5 | RunConfig.bossBonusCoins |
| Starting coins | 5 | RunConfig.startingCoins |
In the code
| File | What it does |
|---|---|
Assets/_Project/Scripts/Run/CoopRules.cs | StartRound, CompleteTurn, RemovePlayer, PoolFor, OutsForTurn, CurrentBatter, TurnIndex, RoundPhase |
Assets/_Project/Scripts/Run/CoopRun.cs | Host: PlayCurrentRound, HostAnnounceTurn, HostTurnEnded, HostEndRound, OnPlayerLeft. Everyone: OnRoundEnd (coins), BeginMyTurn (outs for the turn) |
Assets/_Project/Scripts/Run/RunManager.cs | OutsPerInning, InningCoins (shared with solo) |
Assets/_Project/Editor/CoopRulesTest.cs | Tools > Home Run Derby > Net > Run Co-op Rules Test: pool size, opener rotation, turns on outs, clearing mid-turn, empty pool, drops on and off turn, everyone leaving, second life, wrong batter |
Gotchas
The plan's "7 outs" is stale
docs/MULTIPLAYER-PLAN.md(6a) says a solo round has 7 outs, so the pool is max(7, players). Since the 9-inning runs,RunConfig.outsPerInningis 3, andCoopRulestakes it fromRunManager.OutsPerInning. The code wins: the pool is max(3, players), or max(2, players) on Hard.CoopRulesTeststill builds its rules withSoloOuts = 7; that only tests the formula, not the live value.
- The second life is handled by the batter’s own at-bat (it plays a mini-round with 2 outs).
CoopRulesonly ever sees one finished turn = one out. - No boss bonus to the pool (solo has none either).
- The leftover-out bonus uses the team pool’s outs left, so a big pool with 4 players can pay more than solo.
- The pool size uses players still in at the start of the inning; it does not shrink if someone leaves mid-inning.
- In inning 1 the host holds the first
TurnStartuntil everyone is through the match intro (or a deadline passes). The rules above are unchanged by it. See Cutscenes.
Related
- Co-op Run Flow: when these rules run
- Count and Outs: outs in a solo inning
- Shop and Economy: the solo coin rules these reuse
- Upgrades: where Extra Outs comes from
- Difficulty: Hard takes an out away
- Run Structure: innings, goals, bosses