> For the complete documentation index, see [llms.txt](https://xpressdev.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xpressdev.gitbook.io/docs/mods/catchcombo.md).

# CatchCombo

CatchCombo brings Pokémon Let's Go-style **catch combos** to Cobblemon. Catching the same species over and over builds a chain, and the longer that chain gets, the better the rewards: higher shiny odds, guaranteed perfect IVs, hidden abilities, bonus spawns, and a boosted spawn rate for the species you're chaining.

***

## Features

* **Per-species catch combo chains**, optionally split per form
* **Configurable tiers** with escalating rewards: shiny rate multiplier, guaranteed perfect IVs, hidden ability chance, double spawn chance, spawn rate boost, and custom aspects
* **Visual glow** on wild spawns matching your chain, visible only to you
* **Bad luck mitigation** that builds the longer a chain runs without a shiny
* **Configurable chain-breaking rules** for legendaries, mythicals, ultra beasts and blacklisted species
* **Optional grace period** for a few wrong catches before a chain actually ends
* **Admin pause/resume** for any player's chain, including a server-wide resume
* **Live sidebar** showing chain length, shiny rate, spawn rate, hidden ability chance and guaranteed perfect IVs
* **Placeholder API support** for chain stats in scoreboards, chat and holograms
* **MongoDB or per-player JSON storage**

***

## How catch combos work

Catch a Pikachu. Then another. Then another. Each catch of the **same species** increases your chain by one, and the game tells you where you're at:

```
Pikachu Catch Combo: 12
```

Your chain length decides your **tier**, and the tier decides your rewards. Keep chaining and you climb into better tiers. Catch something else and your chain restarts on that new species.

{% hint style="info" %}
Rewards apply to **wild Pokémon of your chained species** - the ones that spawn around you while the chain is active. The chain doesn't buff unrelated Pokémon.
{% endhint %}

### Rewards

Each tier can grant:

| Reward             | What it does                                                  |
| ------------------ | ------------------------------------------------------------- |
| **Shiny rate**     | Multiplies your odds of a shiny spawn of the chained species. |
| **Perfect IVs**    | Guarantees a minimum number of 31-IV stats.                   |
| **Hidden ability** | A chance for the spawn to roll its hidden ability.            |
| **Double spawn**   | A chance to spawn a second copy alongside the first.          |
| **Spawn rate**     | Boosts how often the chained species itself spawns for you.   |
| **Aspects**        | A chance to apply any Cobblemon aspect (special forms, etc.). |

Comboed Pokémon also **glow** so you can spot them at a glance. The glow is visible only to you - other players nearby won't see it, because it reflects *your* chain.

### Boosted spawn rate

The longer your chain, the more often the chained species itself spawns for you - on top of every other tier reward. This boost is personal to you; it doesn't change what spawns for anyone else on the server.

{% hint style="info" %}
This stacks with lures, bait, and any other mod that affects spawn rates - it adds on top of them rather than overriding them, so an active lure and a long chain both boost your odds at once.
{% endhint %}

### Bad luck mitigation

If you're deep into a long chain and still haven't found a shiny, bad luck mitigation slowly tilts the odds in your favour. It starts after a configurable chain length and builds up the longer you go without a shiny, resetting once you finally find one.

### Ending your chain

Your chain ends when you:

* catch a **different species** (a new chain starts on it)
* catch a **blacklisted** Pokémon, or a legendary/mythical/Ultra Beast, depending on config
* hit the **chain cap**, if the server sets one - the chain restarts at 1 on the same species

{% hint style="success" %}
**Grace period.** If enabled, players get a few "free" wrong catches before the chain actually ends. During the grace period the chain doesn't grow, but it doesn't break either - players just get a warning telling them how many wrong catches they have left.
{% endhint %}

### Pausing

`/combo pause <player>` lets an **admin pause another player's chain** - useful for moderation, events, or freezing a player's progress without wiping it. While paused, nothing that player catches changes their chain and no combo bonuses apply to them; running the command again resumes them exactly where they left off. Use `server` as the player name to resume everyone at once.

Players can also pause their *own* chain with `/combo pause` (no argument), but this is disabled for regular players by default - both the self and other forms of the command default to operators only.

{% hint style="info" %}
Server owners can independently configure who can use each form of the command via the `combo.pause.self` and `combo.pause.other` permission nodes - for example, granting `combo.pause.self` to everyone to let players pause their own chain, while keeping `combo.pause.other` restricted to staff.
{% endhint %}

***

## Commands

All commands live under `/combo` (alias: `/catchcombo`).

| Command                                         | What it does                                                                                    | Default Permission |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------ |
| `/combo info`                                   | Shows your current chain and its length.                                                        | everyone           |
| `/combo info toggle`                            | Toggles the on-screen combo sidebar.                                                            | everyone           |
| `/combo top`                                    | Lists the top 10 chains on the server.                                                          | everyone           |
| `/combo pause`                                  | Pauses or resumes your own chain.                                                               | operators          |
| `/combo pause <player>`                         | An admin pauses or resumes another player's chain. Use `server` as the name to resume everyone. | operators          |
| `/combo set <player> <species> <form> <amount>` | Sets a player's chain directly.                                                                 | operators          |
| `/combo setBlm <player> <amount>`               | Sets a player's bad-luck-mitigation streak.                                                     | operators          |
| `/combo reload`                                 | Reloads all config files and refreshes online players.                                          | operators          |

### The sidebar

`/combo info toggle` opens a live sidebar showing your species, chain length, shiny rate, double spawn chance, spawn rate multiplier, hidden ability chance, and minimum perfect IVs. It updates on every catch and closes when you log out.

***

## Permissions

CatchCombo uses [LuckPerms' Fabric permissions API](https://github.com/lucko/fabric-permissions-api). Every command has its own node:

| Node                 | Grants                  | Default   |
| -------------------- | ----------------------- | --------- |
| `combo.info`         | `/combo info`           | everyone  |
| `combo.info.toggle`  | `/combo info toggle`    | everyone  |
| `combo.top`          | `/combo top`            | everyone  |
| `combo.pause.self`   | `/combo pause`          | operators |
| `combo.pause.other`  | `/combo pause <player>` | operators |
| `combo.admin.set`    | `/combo set`            | operators |
| `combo.admin.blm`    | `/combo setBlm`         | operators |
| `combo.admin.reload` | `/combo reload`         | operators |

{% hint style="info" %}
Granting one of the operator-default nodes to a group lets non-ops use that command - you don't need to op anyone. Operators (permission level 2) always pass regardless of node.
{% endhint %}

Without a permissions plugin installed, the **Default** column applies.

***

## Placeholders

For use with [Placeholder API](https://github.com/Patbox/PlaceholderAPI) - in scoreboards, chat formats, holograms, and anywhere else placeholders are supported.

| Placeholder                           | Value                                                       |
| ------------------------------------- | ----------------------------------------------------------- |
| `%catchcombos:amount%`                | Chain length, or `0`.                                       |
| `%catchcombos:species%`               | Chained species, or `None`.                                 |
| `%catchcombos:form%`                  | Chained form, or `Normal`.                                  |
| `%catchcombos:shiny_rate%`            | Shiny odds as `x/y`.                                        |
| `%catchcombos:hidden_ability_chance%` | Hidden ability chance, as a percentage.                     |
| `%catchcombos:extra_spawn_chance%`    | Double spawn chance, as a percentage.                       |
| `%catchcombos:spawn_rate_multiplier%` | Spawn rate multiplier for the chained species, e.g. `2.0x`. |
| `%catchcombos:min_perfect_ivs%`       | Guaranteed perfect IV count.                                |

***

## Configuration

Config files live in `config/catchcombo/` and are created on first run:

| File                | Purpose                                                            |
| ------------------- | ------------------------------------------------------------------ |
| `config.json`       | Combo rules, spawn behaviour, and tiers.                           |
| `lang.json`         | Every player-facing message.                                       |
| `mongo_config.json` | Database connection - only read when `storage.useMongo` is `true`. |

Edit a file and run `/combo reload`, or restart the server, to apply changes.

{% hint style="success" %}
Configs from older versions load fine and are rewritten in the current format automatically - nothing needs migrating by hand.
{% endhint %}

### `combo` - chain rules

| Key                       | Default | Description                                                                      |
| ------------------------- | ------- | -------------------------------------------------------------------------------- |
| `differentComboPerForm`   | `false` | Treat each form as its own chain, not just each species.                         |
| `chainReset`              | `false` | Cap how long a chain can run.                                                    |
| `chainResetAt`            | `300`   | The cap. On the next catch past it, the chain restarts at 1 on the same species. |
| `shinyBreaksCombo`        | `true`  | Whether catching a shiny of a *new* species starts a chain as normal.            |
| `shinySpawnBreaksCombo`   | `false` | A shiny *spawn* matching your chain restarts it at 1.                            |
| `speciesShinyBreaksCombo` | `false` | A shiny *catch* of your own chained species restarts it at 1.                    |
| `gracePeriod`             | `0`     | Wrong catches a chain survives before ending. `0` disables it.                   |

#### Grace period

With `gracePeriod: 3`, catching something that doesn't match your chain three times in a row won't break it - each one warns you instead. The fourth ends the chain and starts a new one. Any catch that continues your chain resets the counter back to full.

While in the grace period the offending catch earns **no combo bonuses** - it isn't part of your chain. If `differentComboPerForm` is on, catching the wrong *form* consumes grace too.

### `breaking` - what ends a chain

| Key                     | Default | Description                                                            |
| ----------------------- | ------- | ---------------------------------------------------------------------- |
| `canComboLegendary`     | `true`  | Whether legendaries interact with combos at all.                       |
| `canComboMythical`      | `true`  | Same, for mythicals.                                                   |
| `canComboUltraBeast`    | `true`  | Same, for Ultra Beasts.                                                |
| `legendaryBreaksCombo`  | `true`  | Whether catching a legendary clears your chain.                        |
| `mythicalBreaksCombo`   | `true`  | Same, for mythicals.                                                   |
| `ultraBeastBreaksCombo` | `true`  | Same, for Ultra Beasts.                                                |
| `blacklistBreaksCombo`  | `true`  | `true` clears the chain; `false` ignores blacklisted Pokémon entirely. |
| `blacklist`             | `[]`    | Species names, case-insensitive.                                       |

{% hint style="warning" %}
**`canCombo*` vs `*BreaksCombo`.** `canComboLegendary: false` makes legendaries invisible to the system - they never affect a chain in any way. `legendaryBreaksCombo: false` (with `canComboLegendary: true`) means a legendary will never *end* a chain you already have, but can still start one when you have none.
{% endhint %}

### `spawns` - spawn-time behaviour

| Key                            | Default | Description                                         |
| ------------------------------ | ------- | --------------------------------------------------- |
| `spawnExtraPokemon`            | `true`  | Enables bonus double spawns.                        |
| `broadcastShinyToPlayer`       | `true`  | Announce a combo-granted shiny to the player.       |
| `generateHiddenAbilityOnSpawn` | `true`  | Roll hidden ability at spawn instead of at capture. |
| `applyIVsOnSpawn`              | `false` | Roll perfect IVs at spawn instead of at capture.    |
| `differentDittoIVs`            | `true`  | Cap Ditto's perfect IVs separately.                 |
| `maxDittoIVs`                  | `3`     | The Ditto cap.                                      |
| `extraSpawnExcludedAspects`    | `[]`    | Aspects that never receive a double spawn.          |

#### Excluding aspects from double spawns

`extraSpawnExcludedAspects` takes a list of Cobblemon aspects. If a spawning Pokémon has any of them, it won't be doubled - useful for keeping rare forms from being duplicated:

```json
"extraSpawnExcludedAspects": ["alolan", "galarian"]
```

{% hint style="info" %}
Double spawns respect the `doPokemonSpawning` gamerule. In a world where Pokémon spawning is turned off, CatchCombo will not create bonus spawns there.
{% endhint %}

### `mitigation` - bad luck mitigation

| Key                           | Default | Description                             |
| ----------------------------- | ------- | --------------------------------------- |
| `badLuckMitigation`           | `true`  | Enables mitigation.                     |
| `badLuckMitigationAfter`      | `200`   | Chain length before it starts building. |
| `badLuckMitigationIncrements` | `0.1`   | How much it adds per catch.             |
| `badLuckMitigationCap`        | `0`     | Maximum bonus. `0` means uncapped.      |

### `display`

| Key                  | Default | Description                                                     |
| -------------------- | ------- | --------------------------------------------------------------- |
| `glowComboedPokemon` | `true`  | Glow effect on spawns matching your chain, visible only to you. |

### `storage`

| Key        | Default | Description                                               |
| ---------- | ------- | --------------------------------------------------------- |
| `useMongo` | `false` | `false` stores each player in `config/catchcombo/saves/`. |

***

## Tiers

Tiers are the heart of the mod: they map chain lengths to rewards.

```json
"tiers": [
  {
    "startValue": 0,
    "endValue": 10,
    "perfectIVs": 0,
    "shinyRateMultiplier": 0,
    "extraSpawnChance": 0,
    "hiddenAbilityChance": 0,
    "spawnWeightMultiplier": 1,
    "otherAspects": {}
  },
  {
    "startValue": 11,
    "endValue": 30,
    "perfectIVs": 2,
    "shinyRateMultiplier": 2,
    "extraSpawnChance": 0.25,
    "hiddenAbilityChance": 0.005,
    "spawnWeightMultiplier": 2,
    "otherAspects": {}
  },
  {
    "startValue": 31,
    "endValue": -1,
    "perfectIVs": 4,
    "shinyRateMultiplier": 6,
    "extraSpawnChance": 0.85,
    "hiddenAbilityChance": 0.01,
    "spawnWeightMultiplier": 4,
    "otherAspects": {}
  }
]
```

| Field                     | Description                                                                    |
| ------------------------- | ------------------------------------------------------------------------------ |
| `startValue` / `endValue` | Chain range, inclusive. Use `-1` as the last tier's `endValue` for "no limit". |
| `perfectIVs`              | Guaranteed 31-IV stats.                                                        |
| `shinyRateMultiplier`     | Shiny odds multiplier - see below.                                             |
| `extraSpawnChance`        | Double spawn chance, `0.0`-`1.0`.                                              |
| `hiddenAbilityChance`     | Hidden ability chance, `0.0`-`1.0`.                                            |
| `spawnWeightMultiplier`   | Spawn rate multiplier for the chained species - see below.                     |
| `otherAspects`            | Aspects to roll, as `{"aspect": chance}`.                                      |

{% hint style="danger" %}
**`shinyRateMultiplier` is not a percentage.** It's a multiplier over the server's base shiny rate. With Cobblemon's default rate of 1/8192, `shinyRateMultiplier: 6` gives roughly 6× the normal odds - about 1/1365 - **not** a 6% chance.
{% endhint %}

{% hint style="warning" %}
**`spawnWeightMultiplier` defaults to `1`, not `0`.** Every other tier field defaults to "no bonus" at `0`, but `0` here would mean the chained species can *never* spawn. `1` means unchanged spawn odds; `2` roughly doubles them; and so on. It stacks multiplicatively with lures and other spawn-rate mods rather than replacing their effect.
{% endhint %}

Tiers can be listed in any order. Gaps and overlaps are repaired automatically when the config loads, and every repair is written to the server log - worth a look after editing tiers.

***

## Storage

By default each player is stored as a JSON file in `config/catchcombo/saves/`. To use MongoDB instead, set `storage.useMongo` to `true` and fill in `mongo_config.json`:

```json
{
  "mongoUri": "mongodb://localhost:27017",
  "dbName": "catchcombos",
  "collectionName": "catchcombos",
  "portToMongo": false
}
```

Setting `portToMongo` to `true` copies your existing JSON saves into MongoDB on the next startup, then turns itself back off so it only ever runs once.

***

## Messages

Every message players see is in `lang.json` and uses [MiniMessage](https://docs.advntr.dev/minimessage/format.html) formatting. Legacy `&` and `§` colour codes work too.

| Key                                                    | When it's shown                        |
| ------------------------------------------------------ | -------------------------------------- |
| `info.catch_combo_update`                              | A catch grows your chain.              |
| `info.player_join_combo_info`                          | On login, if you have a chain.         |
| `info.current_chain`                                   | `/combo info`.                         |
| `info.no_chain`                                        | `/combo info` with no chain.           |
| `info.combo_reset`                                     | Your chain was cleared.                |
| `info.chain_capped`                                    | Your chain hit the cap and restarted.  |
| `info.upcoming_combo_reset`                            | Your chain is one catch from the cap.  |
| `info.chain_restarted_by_shiny`                        | A shiny catch restarted your chain.    |
| `info.grace_warning`                                   | A wrong catch consumed a grace charge. |
| `info.shiny_found`                                     | You found a combo-granted shiny.       |
| `info.combo_paused` / `info.combo_resumed`             | You paused or resumed.                 |
| `info.combo_pause_other` / `info.combo_resume_other`   | You paused or resumed someone else.    |
| `info.scoreboard_enabled` / `info.scoreboard_disabled` | You toggled the sidebar.               |

Available tokens, depending on the message: `{pokemon}`, `{combo}`, `{player}`, `{remaining}`.

***

## Requirements

* Minecraft 1.21.1 (Fabric)
* Cobblemon
* Fabric API + Fabric Language Kotlin
