Add boss team match playstyle rule
When enabled, the sticky boss banner shows the next boss's team size as a hint for players who voluntarily match the boss's party count. Handles variant boss teams by using the auto-detected starter variant. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,33 +1,29 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-fv7w
|
# nuzlocke-tracker-fv7w
|
||||||
title: Add team size limit rule
|
title: Add boss team match rule
|
||||||
status: todo
|
status: in-progress
|
||||||
type: feature
|
type: feature
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-20T19:56:22Z
|
created_at: 2026-02-20T19:56:22Z
|
||||||
updated_at: 2026-02-20T20:01:53Z
|
updated_at: 2026-02-20T21:01:36Z
|
||||||
parent: nuzlocke-tracker-49xj
|
parent: nuzlocke-tracker-49xj
|
||||||
---
|
---
|
||||||
|
|
||||||
Cap the active party size with warnings when the limit is exceeded.
|
When enabled, hint to the player that they should limit their active party to the same number of Pokemon as the next boss fight. This is a self-imposed difficulty rule — the tracker cannot enforce it since it doesn't track the active party, but it can surface the information.
|
||||||
|
|
||||||
## Design Decisions
|
## Design
|
||||||
|
|
||||||
**Configurable limit:** Add `teamSizeLimit: number | null` to `NuzlockeRules`. `null` means no limit (disabled). Default Pokemon party size is 6, but variants like "trio-locke" use 3.
|
**Rule:** Add `bossTeamMatch: boolean` to `NuzlockeRules` (default: `false`, category: `playstyle`).
|
||||||
|
|
||||||
**What counts:** "Active team" = encounters with status `caught` and not fainted. The tracker already tracks this — alive Pokemon are shown in the team section on RunEncounters.
|
**Display:** When enabled and the sticky boss banner is shown, add a hint next to the boss name showing their team size, e.g. "Next: Brock (2 Pokemon — match their team)". This reuses the existing `nextBoss` and its `pokemon` array.
|
||||||
|
|
||||||
**No PC box tracking:** The tracker doesn't model a PC box. Excess catches beyond the team limit are still logged normally. The tracker just warns that the team is over capacity.
|
**Variant bosses:** Some bosses have conditional teams (e.g. rival starter choice). Use the same logic as `BossTeamPreview`: count pokemon without a `conditionLabel` plus those matching the auto-detected variant (via `matchVariant`). Falls back to first variant if no match is detected.
|
||||||
|
|
||||||
**Enforcement:** Soft enforcement. Show a warning banner on the encounters page when alive count exceeds the limit. Highlight the count in the team section header. Don't block new catches.
|
**Scope:** Frontend-only. No backend or data model changes needed.
|
||||||
|
|
||||||
**UI:** Add a numeric input to `RulesConfiguration` (shown when team size toggle is on, min 1, max 6). Display the limit in the sticky bar alongside level caps if enabled.
|
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
|
|
||||||
- [ ] Add `teamSizeLimit: number | null` to `NuzlockeRules` interface (default: `null`)
|
- [x] Add `bossTeamMatch: boolean` to `NuzlockeRules` interface and `DEFAULT_RULES` (default: false)
|
||||||
- [ ] Add `RuleDefinition` entry under `'difficulty'` category
|
- [x] Add `RuleDefinition` entry (category: `playstyle`)
|
||||||
- [ ] Add numeric input to `RulesConfiguration` (shown when enabled, min 1, max 6)
|
- [x] Show boss team size hint in the sticky level cap banner when the rule is enabled
|
||||||
- [ ] Show warning banner on RunEncounters when alive team count exceeds limit
|
- [x] Handle variant boss teams (use auto-matched variant count when available)
|
||||||
- [ ] Display team size limit in sticky bar alongside level caps
|
|
||||||
- [ ] Show count in team section header (e.g., "Team (4/3)" in red when over)
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
# nuzlocke-tracker-sij8
|
# nuzlocke-tracker-sij8
|
||||||
title: Add gift clause rule
|
title: Add gift clause rule
|
||||||
status: in-progress
|
status: completed
|
||||||
type: feature
|
type: feature
|
||||||
priority: normal
|
priority: normal
|
||||||
created_at: 2026-02-20T19:56:10Z
|
created_at: 2026-02-20T19:56:10Z
|
||||||
updated_at: 2026-02-20T20:53:15Z
|
updated_at: 2026-02-20T20:55:23Z
|
||||||
parent: nuzlocke-tracker-49xj
|
parent: nuzlocke-tracker-49xj
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ DEFAULT_RULES = {
|
|||||||
"levelCaps": False,
|
"levelCaps": False,
|
||||||
"hardcoreMode": False,
|
"hardcoreMode": False,
|
||||||
"setModeOnly": False,
|
"setModeOnly": False,
|
||||||
|
"bossTeamMatch": False,
|
||||||
"egglocke": False,
|
"egglocke": False,
|
||||||
"wonderlocke": False,
|
"wonderlocke": False,
|
||||||
"randomizer": False,
|
"randomizer": False,
|
||||||
|
|||||||
@@ -178,6 +178,17 @@ function matchVariant(labels: string[], starterName?: string | null): string | n
|
|||||||
return matches.length === 1 ? (matches[0] ?? null) : null
|
return matches.length === 1 ? (matches[0] ?? null) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Count boss pokemon for the effective variant (or all if no variants). */
|
||||||
|
function getBossTeamSize(pokemon: BossPokemon[], starterName?: string | null): number {
|
||||||
|
const labels = [
|
||||||
|
...new Set(pokemon.filter((bp) => bp.conditionLabel).map((bp) => bp.conditionLabel!)),
|
||||||
|
]
|
||||||
|
if (labels.length === 0) return pokemon.length
|
||||||
|
const matched = matchVariant(labels, starterName)
|
||||||
|
const variant = matched ?? labels[0] ?? null
|
||||||
|
return pokemon.filter((bp) => bp.conditionLabel === variant || bp.conditionLabel === null).length
|
||||||
|
}
|
||||||
|
|
||||||
function BossTeamPreview({
|
function BossTeamPreview({
|
||||||
pokemon,
|
pokemon,
|
||||||
starterName,
|
starterName,
|
||||||
@@ -1060,7 +1071,15 @@ export function RunEncounters() {
|
|||||||
Level Cap: {currentLevelCap ?? '—'}
|
Level Cap: {currentLevelCap ?? '—'}
|
||||||
</span>
|
</span>
|
||||||
{nextBoss && (
|
{nextBoss && (
|
||||||
<span className="text-sm text-text-tertiary">Next: {nextBoss.name}</span>
|
<span className="text-sm text-text-tertiary">
|
||||||
|
Next: {nextBoss.name}
|
||||||
|
{run.rules?.bossTeamMatch && (
|
||||||
|
<span className="text-text-muted">
|
||||||
|
{' '}
|
||||||
|
({getBossTeamSize(nextBoss.pokemon, starterName)} Pokémon — match their team)
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
{!nextBoss && (
|
{!nextBoss && (
|
||||||
<span className="text-sm text-status-active">All bosses defeated!</span>
|
<span className="text-sm text-status-active">All bosses defeated!</span>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface NuzlockeRules {
|
|||||||
// Playstyle (informational, for stats/categorization)
|
// Playstyle (informational, for stats/categorization)
|
||||||
hardcoreMode: boolean
|
hardcoreMode: boolean
|
||||||
setModeOnly: boolean
|
setModeOnly: boolean
|
||||||
|
bossTeamMatch: boolean
|
||||||
|
|
||||||
// Variant (changes which Pokemon can appear)
|
// Variant (changes which Pokemon can appear)
|
||||||
egglocke: boolean
|
egglocke: boolean
|
||||||
@@ -27,6 +28,7 @@ export const DEFAULT_RULES: NuzlockeRules = {
|
|||||||
// Playstyle - off by default
|
// Playstyle - off by default
|
||||||
hardcoreMode: false,
|
hardcoreMode: false,
|
||||||
setModeOnly: false,
|
setModeOnly: false,
|
||||||
|
bossTeamMatch: false,
|
||||||
|
|
||||||
// Variant - off by default
|
// Variant - off by default
|
||||||
egglocke: false,
|
egglocke: false,
|
||||||
@@ -93,6 +95,13 @@ export const RULE_DEFINITIONS: RuleDefinition[] = [
|
|||||||
'The game must be played in "Set" battle style, meaning you cannot switch Pokémon after knocking out an opponent.',
|
'The game must be played in "Set" battle style, meaning you cannot switch Pokémon after knocking out an opponent.',
|
||||||
category: 'playstyle',
|
category: 'playstyle',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'bossTeamMatch',
|
||||||
|
name: 'Boss Team Match',
|
||||||
|
description:
|
||||||
|
'Limit your active party to the same number of Pokémon as the boss you are challenging.',
|
||||||
|
category: 'playstyle',
|
||||||
|
},
|
||||||
|
|
||||||
// Variant
|
// Variant
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user