> 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/simplelures.md).

# SimpleLures

Configurable lure items for Cobblemon - boost species, types, spawn buckets, aspects or stats, then sell them through NPC-backed shops.

SimpleLures adds **configurable lure items** to Cobblemon. Activating a lure reweights the holder's wild spawns towards chosen species, elemental types, spawn buckets, spawn-pool aspects, or gives whatever spawns better stats - for a limited time, then the item is consumed. Lures can be handed out with a command or sold through NPC-backed shops, priced in an economy currency or in items.

Everything about a lure is config - what it boosts, how strongly, for how long, and what item it's rendered on.

***

## Features

* **Five lure kinds** - species, elemental type, spawn bucket, spawn-pool aspect (including shiny), and pure stat-boosting effects
* **Stat-boosting effect lures** - boost IVs, EVs, egg group, nature, friendship, gender chance, hidden-ability chance, alpha chance, mark chance and level, built directly on Cobblemon's own bait-effect system
* **Direct shiny-chance boosting** - a real multiplier on how often shiny Pokémon spawn
* **Stackable lures** - a targeted lure, a bucket lure and an effect lure can all be active on the same player at once
* **NPC-backed shops** - assign any entity as a shop NPC through an in-game GUI, no coding required
* **Flexible pricing** - sell lures for an economy currency (Impactor) or straight for items, no economy mod required
* **Instant lure hand-outs** - `/simplelures give` to yourself or another player
* **Automatic config migration** - upgrading from 1.x rewrites every file to the new format on first load, nothing to edit by hand
* **LuckPerms-ready permissions** - fine-grained nodes per command, unchanged from 1.x so existing grants keep working

***

## How it works

Right-clicking a lure item activates it. While active it registers a spawning influence for that player that reweights their wild spawns (or alters what spawns' stats look like) for `duration` seconds, then the item is consumed.

There are five kinds of lure:

* **`species`** - boosts specific species, optionally narrowed to specific forms. A species Cobblemon labels `legendary`, `mythical` or `ultra_beast` uses a separate multiplier instead of the normal one.
* **`type`** - boosts every species of one or more elemental types, optionally narrowed further by a species list.
* **`bucket`** - boosts entire Cobblemon spawn buckets (e.g. `ultra-rare`) before an individual species is even chosen, rather than reweighting species directly.
* **`aspect`** - boosts spawns carrying a chosen spawn-pool aspect, such as a costume or regional form, or `shiny` for a direct boost to shiny odds.
* **`effect`** - doesn't change *what* spawns at all, only *how good it is*: IVs, EVs, egg group, nature, friendship, gender chance, hidden-ability chance, alpha chance, mark chance and level.

`effect` lures are built directly on Cobblemon's own bait-effect system (the one fishing bait and PokeSnacks use), so none of that stat rolling is reimplemented - a lure just hands Cobblemon's own machinery the effect list.

### Stacking

A player can have **one** `species`/`type`/`aspect` lure and **one** `bucket` lure active at the same time - activating a second lure of the same kind replaces the first. `lures.allowBucketWithOtherLures` controls whether a bucket lure is allowed to run alongside a targeted lure at all; when it's `false`, activating either kind deactivates the other.

An `effect` lure is independent of both and can be active **alongside** a targeted lure and a bucket lure at the same time.

{% hint style="success" %}
Active-lure state is re-derived from the player's inventory once a second rather than tracked incrementally, so it can never drift from what's actually in their inventory - it survives relogging and changing dimension.
{% endhint %}

### NPC shops

`/simplelures npc` puts a player into NPC-assignment mode; the next entity they interact with is bound to a shop chosen from a GUI. Interacting with an assigned NPC afterwards opens that shop for purchase. Shops can be priced in an economy currency (needs an Impactor-compatible economy mod) or directly in items, which needs no economy mod at all.

***

## Commands

| Command                             | What it does                               | Default Permission       |
| ----------------------------------- | ------------------------------------------ | ------------------------ |
| `/simplelures give <lure>`          | Gives yourself a lure item.                | `simplelures.give`       |
| `/simplelures give <lure> <player>` | Gives another player a lure item.          | `simplelures.give`       |
| `/simplelures shop <shop>`          | Opens a shop for yourself.                 | `simplelures.shop.self`  |
| `/simplelures shop <shop> <player>` | Opens a shop for another player.           | `simplelures.shop.other` |
| `/simplelures npc`                  | Toggles NPC-assignment mode.               | `simplelures.npc`        |
| `/simplelures reload`               | Reloads config, lures, shops and NPC data. | `simplelures.reload`     |

***

## Permissions

SimpleLures uses [LuckPerms' Fabric permissions API](https://github.com/lucko/fabric-permissions-api).

| Node                     | Grants                                               | Default   |
| ------------------------ | ---------------------------------------------------- | --------- |
| `simplelures.reload`     | `/simplelures reload`                                | operators |
| `simplelures.give`       | `/simplelures give`                                  | operators |
| `simplelures.shop.self`  | `/simplelures shop <shop>` for yourself              | operators |
| `simplelures.shop.other` | `/simplelures shop <shop> <player>` for someone else | operators |
| `simplelures.npc`        | `/simplelures npc`                                   | operators |

{% hint style="info" %}
Operators (permission level 2) always pass regardless of node. Permission node names are unchanged from 1.x, so an existing LuckPerms setup keeps working after an upgrade.
{% endhint %}

***

## Configuration

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

| File          | Purpose                                            |
| ------------- | -------------------------------------------------- |
| `config.json` | Lure defaults, NPC behaviour, shop defaults.       |
| `lures/`      | One file per lure.                                 |
| `shops/`      | One file per shop.                                 |
| `npcs.json`   | Shop-to-entity assignments, written automatically. |
| `lang.json`   | Every player-facing message.                       |

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

### `config.json`

```json
{
  "lures": {
    "baseItem": "minecraft:popped_chorus_fruit",
    "defaultDuration": 600,
    "defaultWeightMultiplier": 100.0,
    "defaultLegendaryMultiplier": 0.5,
    "allowBucketWithOtherLures": true
  },
  "npcs": {
    "showShopName": true,
    "makeInvulnerable": true
  },
  "shops": {
    "defaultCurrency": "impactor:dollars"
  }
}
```

| Key                                | Default                         | Description                                                              |
| ---------------------------------- | ------------------------------- | ------------------------------------------------------------------------ |
| `lures.baseItem`                   | `minecraft:popped_chorus_fruit` | Fallback item id for a lure that doesn't set its own `item.id`.          |
| `lures.defaultDuration`            | `600`                           | Fallback active duration, in seconds.                                    |
| `lures.defaultWeightMultiplier`    | `100.0`                         | Fallback spawn-weight multiplier.                                        |
| `lures.defaultLegendaryMultiplier` | `0.5`                           | Fallback multiplier for legendary/mythical/ultra-beast species.          |
| `lures.allowBucketWithOtherLures`  | `true`                          | Whether a bucket lure can be active at the same time as a targeted lure. |
| `npcs.showShopName`                | `true`                          | Renames an assigned NPC entity to its shop's display name.               |
| `npcs.makeInvulnerable`            | `true`                          | Makes an assigned NPC entity immune to damage.                           |
| `shops.defaultCurrency`            | `impactor:dollars`              | Fallback currency key for a shop that doesn't set its own `payment.id`.  |

***

## Lures

Every file in `lures/` is one lure. The filename isn't significant - `id` is.

### `species` and `type` lures

```json
{
  "id": "example_pokemon_lure",
  "displayName": "<gold>Charmander Line Lure",
  "kind": "species",
  "duration": 600,
  "weightMultiplier": 100.0,
  "legendaryMultiplier": 0.5,
  "item": {
    "id": "minecraft:popped_chorus_fruit",
    "customModelData": 40009
  },
  "species": [
    { "name": "charmander", "forms": [] },
    { "name": "charmeleon", "forms": [] },
    { "name": "charizard", "forms": [] }
  ],
  "blacklist": false
}
```

| Field                                | Applies to        | Description                                                                                     |
| ------------------------------------ | ----------------- | ----------------------------------------------------------------------------------------------- |
| `id`                                 | all               | Identity. Written into the lure item's data. Not validated for uniqueness.                      |
| `displayName`                        | all               | MiniMessage. Becomes the item's custom name. Defaults to `id`.                                  |
| `kind`                               | all               | `species`, `type`, `bucket`, `aspect` or `effect`.                                              |
| `duration`                           | all               | Seconds. Falls back to `lures.defaultDuration`.                                                 |
| `weightMultiplier`                   | all               | Spawn-weight multiplier for a match. Falls back to `lures.defaultWeightMultiplier`.             |
| `legendaryMultiplier`                | `species`         | Used instead of `weightMultiplier` for a legendary/mythical/ultra-beast species.                |
| `item.id` / `item.customModelData`   | all               | The item the lure is rendered on. `id` falls back to `lures.baseItem`.                          |
| `species[].name` / `species[].forms` | `species`, `type` | Species name, optionally narrowed to specific forms. Empty `forms` matches every form.          |
| `blacklist`                          | `species`, `type` | Inverts the species list: boosts everything **except** the listed species instead of only them. |
| `types`                              | `type`            | Elemental type names, e.g. `["fire"]`.                                                          |

{% hint style="warning" %}
A `species` lure with no species, a `type` lure with no types, a `bucket` lure with no buckets, an `aspect` lure with no aspects, or an `effect` lure with no effects can never match anything - it's dropped on load and a warning is logged.
{% endhint %}

### `bucket` lures

```json
{
  "id": "example_bucket_lure",
  "displayName": "<light_purple>Ultra-Rare Lure",
  "kind": "bucket",
  "duration": 600,
  "weightMultiplier": 100.0,
  "item": { "id": "minecraft:popped_chorus_fruit", "customModelData": 40000 },
  "buckets": ["ultra-rare"]
}
```

`buckets` lists Cobblemon spawn bucket names. Bucket lures never see a species - the boost applies before one is picked - so they take no species filter.

### `aspect` lures

```json
{
  "id": "example_aspect_lure",
  "displayName": "<aqua>Shiny Charm Lure",
  "kind": "aspect",
  "duration": 600,
  "weightMultiplier": 8.0,
  "item": { "id": "minecraft:popped_chorus_fruit", "customModelData": 40010 },
  "aspects": ["shiny"]
}
```

`aspects` lists spawn-pool aspect names, e.g. `shiny` or a costume/regional form. `weightMultiplier` is how much more likely a matching spawn becomes - `8.0` means 8 times more likely.

### `effect` lures

```json
{
  "id": "example_effect_lure",
  "displayName": "<yellow>Well-Fed Lure",
  "kind": "effect",
  "duration": 600,
  "item": { "id": "minecraft:popped_chorus_fruit", "customModelData": 40011 },
  "effects": [
    { "type": "iv", "subcategory": "hp", "chance": 1.0, "value": 5.0 },
    { "type": "ev", "subcategory": "hp", "chance": 1.0, "value": 50.0 }
  ]
}
```

Each entry mirrors Cobblemon's own spawn bait effect shape and is handed straight to it, so refer to [Cobblemon's bait seasoning wiki page](https://wiki.cobblemon.com/index.php/Seasoning#Bait_Seasoning) for exactly what each `type`/`subcategory`/`value` combination does.

| Field         | Description                                                                                                                                                                    |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type`        | One of `alpha_chance`, `egg_group`, `ev`, `friendship`, `gender_chance`, `ha_chance`, `iv`, `level_raise`, `mark_chance`, `nature`.                                            |
| `subcategory` | Optional. Meaning depends on `type` - a stat name for `iv`/`ev`, an egg group id, a nature id, and so on. Read under the `cobblemon` namespace unless it already contains one. |
| `chance`      | `0.0`-`1.0`. Defaults to `1.0`.                                                                                                                                                |
| `value`       | Meaning depends on `type` - a stat amount for `iv`/`ev`, a percentage-point count for `friendship`, etc.                                                                       |

{% hint style="warning" %}
An entry with an unknown or disallowed `type` is dropped with a warning - the rest of the lure's effects still load.
{% endhint %}

***

## Shops

Every file in `shops/` is one shop.

```json
{
  "id": "example_lure_shop",
  "displayName": "<bold><red>Example Lure Shop</red></bold>",
  "payment": {
    "type": "currency",
    "id": "impactor:dollars"
  },
  "items": [
    { "id": "example_pokemon_lure", "price": 2000 },
    { "id": "example_typed_lure", "price": 2000 },
    { "id": "example_bucket_lure", "price": 5000 }
  ]
}
```

| Field                          | Description                                                                                                                           |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                           | Identity. Referenced by `npcs.json` and `/simplelures shop <id>`.                                                                     |
| `displayName`                  | MiniMessage. GUI title and, if `npcs.showShopName` is on, the assigned NPC's name.                                                    |
| `payment.type`                 | `currency` (needs an Impactor-compatible economy mod) or `item` (taken straight from the buyer's inventory, no economy mod required). |
| `payment.id`                   | A currency key (`namespace:value`) for `currency`, or an item id for `item`. Falls back to `shops.defaultCurrency`.                   |
| `items[].id` / `items[].price` | Lure id and its cost in `payment`.                                                                                                    |

{% hint style="info" %}
A shop entry naming a lure that no longer exists is hidden from the shop GUI but **kept in the file** - it comes back automatically if the lure is restored, rather than being erased the moment the lure file is temporarily missing.
{% endhint %}

### `npcs.json`

Written automatically the first time a player assigns an NPC - `shopId -> [entity UUID]`. An entry pointing at a shop that no longer exists is dropped on load, with a warning logging how many were removed.

***

## 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                                                                          |
| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `action.lure_activate` / `action.lure_deactivate`                                             | A lure is activated or deactivated.                                                      |
| `action.lure_expired`                                                                         | An active lure runs out.                                                                 |
| `action.npc_mode_enable` / `action.npc_mode_disable`                                          | NPC-assignment mode is toggled.                                                          |
| `action.npc_add_shop` / `action.npc_remove_shop`                                              | An NPC is assigned to or removed from a shop.                                            |
| `info.npc_shop`                                                                               | Looking at an NPC that belongs to a shop.                                                |
| `info.npc_mode_active`                                                                        | Action bar shown while in NPC mode.                                                      |
| `error.invalid_shop` / `error.invalid_player` / `error.invalid_lure` / `error.invalid_source` | Bad command input.                                                                       |
| `error.no_permission`                                                                         | A command was run without the required permission.                                       |
| `error.lure_already_active`                                                                   | Trying to activate a second lure in an occupied group.                                   |
| `error.unknown_lure_item`                                                                     | Activating a lure item whose id no longer exists in config.                              |
| `error.no_space_to_activate`                                                                  | No free inventory slot to split a stack for activation.                                  |
| `error.insufficient_funds` / `error.insufficient_space`                                       | A shop purchase fails.                                                                   |
| `error.shop_needs_economy`                                                                    | Opening a currency-priced shop with no economy mod installed.                            |
| `error.reload_issues`                                                                         | `/simplelures reload` finished with config problems.                                     |
| `success.reload_config`                                                                       | `/simplelures reload` succeeded.                                                         |
| `success.lure_received` / `success.lure_given`                                                | Receiving a lure via `/simplelures give`.                                                |
| `success.purchase_successful`                                                                 | A shop purchase succeeds.                                                                |
| `gui.*`                                                                                       | Shop GUI titles, buttons and price label.                                                |
| `lore.*`                                                                                      | Lure item lore lines - time remaining, active/inactive, boosted aspects, effect summary. |

***

## Requirements

* Minecraft 1.21.1 (Fabric)
* Cobblemon 1.8.0+
* Fabric API + Fabric Language Kotlin
* Optional: [LuckPerms](https://luckperms.net/), for permission node grants
* Optional: an Impactor-compatible economy mod, for currency-priced shops
