Compare commits
5 Commits
renovate/c
...
22d72e8a34
| Author | SHA1 | Date | |
|---|---|---|---|
| 22d72e8a34 | |||
| 2675491216 | |||
| e9100fa826 | |||
| acfe767214 | |||
| 5240236759 |
@@ -1,11 +1,11 @@
|
||||
---
|
||||
# nuzlocke-tracker-4ni4
|
||||
title: Fix seed data with encounter conditions
|
||||
status: todo
|
||||
status: completed
|
||||
type: task
|
||||
priority: high
|
||||
created_at: 2026-02-17T07:37:25Z
|
||||
updated_at: 2026-02-17T07:37:28Z
|
||||
updated_at: 2026-02-17T17:52:29Z
|
||||
parent: oqfo
|
||||
---
|
||||
|
||||
@@ -15,94 +15,30 @@ Some Pokémon games have different encounter tables depending on time of day, we
|
||||
|
||||
The existing seed data has curated route ordering and normalized route names (from beans r48e, qvww, j28y) that must be preserved — only encounter condition data should be added/changed.
|
||||
|
||||
## Reference branch
|
||||
|
||||
**Branch:** \`feature/encounter-conditions\` (PoC)
|
||||
|
||||
Key changes on the PoC branch:
|
||||
- **Backend model:** \`RouteEncounter\` gains a \`condition\` field (String(30), default \`""\`)
|
||||
- **Migration:** \`c0d1e2f3a4_add_condition_to_route_encounters.py\` — adds condition column + updated unique constraint
|
||||
- **Seed loader:** handles \`conditions\` dict format: \`{"morning": 50, "day": 20, "night": 0}\` per encounter
|
||||
- **API/schema:** \`condition\` field exposed in route encounter responses
|
||||
- **Frontend types:** \`RouteEncounter\` type gains \`condition: string\`
|
||||
- **Frontend UI:** condition selector tabs and badges in \`RunEncounters\` and \`EncounterModal\`
|
||||
|
||||
## Seed data format
|
||||
|
||||
When an encounter has per-condition rates, the JSON uses a \`conditions\` dict instead of a flat \`encounter_rate\`:
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"pokeapi_id": 163,
|
||||
"pokemon_name": "Hoothoot",
|
||||
"method": "walk",
|
||||
"encounter_rate": null,
|
||||
"conditions": {
|
||||
"night": 50,
|
||||
"morning": 10,
|
||||
"day": 0
|
||||
},
|
||||
"min_level": 2,
|
||||
"max_level": 5
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
For encounters without variant rates, the existing flat \`encounter_rate\` field remains unchanged.
|
||||
|
||||
## Approach
|
||||
|
||||
### Phase 1: HeartGold (reference game)
|
||||
|
||||
Create complete encounter condition data for HeartGold first. This serves as the reference implementation and validates the full pipeline (seed → DB → API → UI).
|
||||
|
||||
HeartGold uses **morning/day/night** conditions for walking encounters. Source: PokeDB data (the import tool at \`tools/import-pokedb\` already has the raw per-condition rates, but \`extract_encounter_rate()\` currently flattens them to \`max()\`).
|
||||
|
||||
### Phase 2: All other games with conditions
|
||||
|
||||
Update the remaining games' seed data with encounter conditions, without changing route order or route names. Match encounters by route name + Pokémon + method and add the \`conditions\` dict.
|
||||
|
||||
## Condition types by game group
|
||||
|
||||
- **morning/day/night**: Gold, Silver, Crystal, HeartGold, SoulSilver, Diamond, Pearl, Platinum, Brilliant Diamond, Shining Pearl
|
||||
- **spring/summer/autumn/winter**: Black, White, Black 2, White 2
|
||||
- **weather (clear, overcast, rain, thunderstorm, snow, snowstorm, sandstorm, intense-sun, heavy-rain, fog)**: Sword, Shield
|
||||
- **SOS calls**: Sun, Moon, Ultra Sun, Ultra Moon
|
||||
- **No conditions (flat rates)**: Red, Blue, Yellow, Ruby, Sapphire, Emerald, FireRed, LeafGreen, X, Y, Omega Ruby, Alpha Sapphire, Let's Go Pikachu, Let's Go Eevee, Legends: Arceus, Scarlet, Violet, Legends: Z-A
|
||||
|
||||
## Checklist
|
||||
|
||||
### Infrastructure (merge from PoC)
|
||||
- [ ] Merge backend model + migration for \`condition\` field on \`RouteEncounter\`
|
||||
- [ ] Merge seed loader changes to handle \`conditions\` dict format
|
||||
- [ ] Merge API/schema changes to expose \`condition\` field
|
||||
- [ ] Merge frontend type updates (\`RouteEncounter.condition\`)
|
||||
- [ ] Merge frontend UI (condition selector tabs/badges in RunEncounters & EncounterModal)
|
||||
- [x] Merge backend model + migration for `condition` field on `RouteEncounter`
|
||||
- [x] Merge seed loader changes to handle `conditions` dict format
|
||||
- [x] Merge API/schema changes to expose `condition` field
|
||||
- [x] Merge frontend type updates (`RouteEncounter.condition`)
|
||||
- [x] Merge frontend UI (condition selector tabs/badges in EncounterModal)
|
||||
- [x] Add horde/SOS method badges to EncounterMethodBadge
|
||||
- [x] Add condition column to AdminRouteDetail
|
||||
|
||||
### Phase 1: HeartGold
|
||||
- [ ] Update \`tools/import-pokedb\` to extract per-condition rates instead of flattening to \`max()\`
|
||||
- [ ] Write a merge script that adds condition data to existing seed files without touching route names/order
|
||||
- [ ] Generate and merge condition data for HeartGold
|
||||
- [ ] Verify HeartGold seed data loads correctly and conditions display in the frontend
|
||||
### Import tool updates
|
||||
- [x] Update `tools/import-pokedb` to extract per-condition rates instead of flattening to `max()`
|
||||
- [x] Fix encounter method mappings (horde, SOS as distinct methods)
|
||||
- [x] Write merge script (`tools/merge-conditions.py`)
|
||||
|
||||
### Phase 2: Remaining games
|
||||
- [ ] Gen 2: Gold, Silver, Crystal (morning/day/night)
|
||||
- [ ] Gen 4: SoulSilver, Diamond, Pearl, Platinum, Brilliant Diamond, Shining Pearl (morning/day/night)
|
||||
- [ ] Gen 5: Black, White, Black 2, White 2 (spring/summer/autumn/winter)
|
||||
- [ ] Gen 7: Sun, Moon, Ultra Sun, Ultra Moon (SOS calls)
|
||||
- [ ] Gen 8: Sword, Shield (weather conditions)
|
||||
- [ ] Verify all updated games load correctly and show conditions in the UI
|
||||
### Seed data updates
|
||||
- [x] Gen 2: Gold, Silver, Crystal (morning/day/night)
|
||||
- [x] Gen 4: HeartGold, SoulSilver, Diamond, Pearl, Platinum, Brilliant Diamond, Shining Pearl (morning/day/night)
|
||||
- [x] Gen 5: Black, White, Black 2, White 2 (spring/summer/autumn/winter)
|
||||
- [x] Gen 7: Sun, Moon, Ultra Sun, Ultra Moon (day/night)
|
||||
- [x] Gen 8: Sword, Shield (weather conditions)
|
||||
- [x] Verify all hooks pass (`prek run --all-files`)
|
||||
|
||||
## Success criteria
|
||||
|
||||
All games that have condition-dependent encounters show those conditions in the UI, so players can see what they can actually catch given their current game state (time of day, season, weather, etc.).
|
||||
|
||||
## Key files
|
||||
|
||||
- \`backend/src/app/models/route_encounter.py\` — RouteEncounter model
|
||||
- \`backend/src/app/seeds/loader.py\` — seed loading logic
|
||||
- \`backend/src/app/seeds/data/*.json\` — game encounter seed files
|
||||
- \`tools/import-pokedb/import_pokedb/processing.py\` — \`extract_encounter_rate()\` flattens conditions
|
||||
- \`tools/import-pokedb/import_pokedb/models.py\` — Encounter dataclass
|
||||
- \`frontend/src/types/game.ts\` — RouteEncounter type
|
||||
- \`frontend/src/pages/RunEncounters.tsx\` — encounter display with conditions
|
||||
- \`frontend/src/components/EncounterModal.tsx\` — encounter registration with condition context
|
||||
## Notes
|
||||
- X/Y had no condition data in PokeDB (horde encounters already tracked as separate method)
|
||||
- 5,684 encounters updated across 22 games
|
||||
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -18,6 +18,9 @@ on:
|
||||
- ".gitignore"
|
||||
- ".github/workflows/deploy.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
backend-lint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -45,14 +48,12 @@ jobs:
|
||||
persist-credentials: false
|
||||
- name: Install actionlint
|
||||
run: |
|
||||
curl -sL https://github.com/rhysd/actionlint/releases/latest/download/actionlint_linux_amd64.tar.gz | tar xz
|
||||
bash <(curl -sL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
|
||||
sudo mv actionlint /usr/local/bin/
|
||||
- name: Lint GitHub Actions
|
||||
run: actionlint
|
||||
- name: Install zizmor
|
||||
run: pip install zizmor
|
||||
- name: Audit GitHub Actions security
|
||||
run: zizmor .github/workflows/
|
||||
run: pipx run zizmor .github/workflows/
|
||||
|
||||
frontend-lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/deploy.yml
vendored
3
.github/workflows/deploy.yml
vendored
@@ -3,6 +3,9 @@ name: Deploy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""add condition to route encounters
|
||||
|
||||
Revision ID: h9c0d1e2f3a4
|
||||
Revises: g8b9c0d1e2f3
|
||||
Create Date: 2026-02-17 12:00:00.000000
|
||||
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "h9c0d1e2f3a4"
|
||||
down_revision: str | Sequence[str] | None = "g8b9c0d1e2f3"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"route_encounters",
|
||||
sa.Column(
|
||||
"condition",
|
||||
sa.String(30),
|
||||
nullable=False,
|
||||
server_default="",
|
||||
),
|
||||
)
|
||||
op.drop_constraint(
|
||||
"uq_route_pokemon_method_game",
|
||||
"route_encounters",
|
||||
type_="unique",
|
||||
)
|
||||
op.create_unique_constraint(
|
||||
"uq_route_pokemon_method_game_condition",
|
||||
"route_encounters",
|
||||
["route_id", "pokemon_id", "encounter_method", "game_id", "condition"],
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint(
|
||||
"uq_route_pokemon_method_game_condition",
|
||||
"route_encounters",
|
||||
type_="unique",
|
||||
)
|
||||
op.create_unique_constraint(
|
||||
"uq_route_pokemon_method_game",
|
||||
"route_encounters",
|
||||
["route_id", "pokemon_id", "encounter_method", "game_id"],
|
||||
)
|
||||
op.drop_column("route_encounters", "condition")
|
||||
@@ -69,8 +69,9 @@ async def export_game_routes(
|
||||
game_encounters = [
|
||||
enc for enc in route.route_encounters if enc.game_id == game_id
|
||||
]
|
||||
return [
|
||||
{
|
||||
result = []
|
||||
for enc in sorted(game_encounters, key=lambda e: -e.encounter_rate):
|
||||
entry: dict = {
|
||||
"pokeapi_id": enc.pokemon.pokeapi_id,
|
||||
"pokemon_name": enc.pokemon.name,
|
||||
"method": enc.encounter_method,
|
||||
@@ -78,8 +79,10 @@ async def export_game_routes(
|
||||
"min_level": enc.min_level,
|
||||
"max_level": enc.max_level,
|
||||
}
|
||||
for enc in sorted(game_encounters, key=lambda e: -e.encounter_rate)
|
||||
]
|
||||
if enc.condition:
|
||||
entry["condition"] = enc.condition
|
||||
result.append(entry)
|
||||
return result
|
||||
|
||||
def format_route(route: Route) -> dict:
|
||||
data: dict = {
|
||||
|
||||
@@ -213,6 +213,7 @@ async def get_pokemon_encounter_locations(
|
||||
route_name=enc.route.name,
|
||||
encounter_method=enc.encounter_method,
|
||||
encounter_rate=enc.encounter_rate,
|
||||
condition=enc.condition,
|
||||
min_level=enc.min_level,
|
||||
max_level=enc.max_level,
|
||||
)
|
||||
|
||||
@@ -12,7 +12,8 @@ class RouteEncounter(Base):
|
||||
"pokemon_id",
|
||||
"encounter_method",
|
||||
"game_id",
|
||||
name="uq_route_pokemon_method_game",
|
||||
"condition",
|
||||
name="uq_route_pokemon_method_game_condition",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -22,6 +23,7 @@ class RouteEncounter(Base):
|
||||
game_id: Mapped[int] = mapped_column(ForeignKey("games.id"), index=True)
|
||||
encounter_method: Mapped[str] = mapped_column(String(30))
|
||||
encounter_rate: Mapped[int] = mapped_column(SmallInteger)
|
||||
condition: Mapped[str] = mapped_column(String(30), default="", server_default="")
|
||||
min_level: Mapped[int] = mapped_column(SmallInteger)
|
||||
max_level: Mapped[int] = mapped_column(SmallInteger)
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ class RouteEncounterResponse(CamelModel):
|
||||
game_id: int
|
||||
encounter_method: str
|
||||
encounter_rate: int
|
||||
condition: str = ""
|
||||
min_level: int
|
||||
max_level: int
|
||||
|
||||
@@ -55,6 +56,7 @@ class PokemonEncounterLocationItem(CamelModel):
|
||||
route_name: str
|
||||
encounter_method: str
|
||||
encounter_rate: int
|
||||
condition: str = ""
|
||||
min_level: int
|
||||
max_level: int
|
||||
|
||||
@@ -89,6 +91,7 @@ class RouteEncounterCreate(CamelModel):
|
||||
game_id: int
|
||||
encounter_method: str
|
||||
encounter_rate: int
|
||||
condition: str = ""
|
||||
min_level: int
|
||||
max_level: int
|
||||
|
||||
@@ -96,6 +99,7 @@ class RouteEncounterCreate(CamelModel):
|
||||
class RouteEncounterUpdate(CamelModel):
|
||||
encounter_method: str | None = None
|
||||
encounter_rate: int | None = None
|
||||
condition: str | None = None
|
||||
min_level: int | None = None
|
||||
max_level: int | None = None
|
||||
|
||||
@@ -178,6 +182,7 @@ class BulkRouteEncounterItem(BaseModel):
|
||||
pokeapi_id: int
|
||||
method: str
|
||||
encounter_rate: int
|
||||
condition: str = ""
|
||||
min_level: int
|
||||
max_level: int
|
||||
|
||||
|
||||
@@ -844,17 +844,25 @@
|
||||
"pokeapi_id": 88,
|
||||
"pokemon_name": "Grimer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 5,
|
||||
"max_level": 20
|
||||
"max_level": 20,
|
||||
"conditions": {
|
||||
"spring": 100,
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 88,
|
||||
"pokemon_name": "Grimer",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"spring": 100,
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 19,
|
||||
@@ -884,17 +892,25 @@
|
||||
"pokeapi_id": 89,
|
||||
"pokemon_name": "Muk",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 50,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"spring": 10,
|
||||
"summer": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 89,
|
||||
"pokemon_name": "Muk",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 5,
|
||||
"max_level": 20
|
||||
"max_level": 20,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3294,41 +3310,63 @@
|
||||
"pokeapi_id": 593,
|
||||
"pokemon_name": "Jellicent",
|
||||
"method": "surf",
|
||||
"encounter_rate": 60,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 60,
|
||||
"summer": 60,
|
||||
"autumn": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 320,
|
||||
"pokemon_name": "Wailmer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 60,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30,
|
||||
"winter": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 458,
|
||||
"pokemon_name": "Mantyke",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 364,
|
||||
"pokemon_name": "Sealeo",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 363,
|
||||
"pokemon_name": "Spheal",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 171,
|
||||
@@ -3342,9 +3380,14 @@
|
||||
"pokeapi_id": 226,
|
||||
"pokemon_name": "Mantine",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 224,
|
||||
@@ -3374,9 +3417,12 @@
|
||||
"pokeapi_id": 365,
|
||||
"pokemon_name": "Walrein",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -7642,33 +7688,53 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 54
|
||||
"max_level": 54,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 453,
|
||||
"pokemon_name": "Croagunk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 15,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 15,
|
||||
"summer": 15,
|
||||
"autumn": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -7682,9 +7748,14 @@
|
||||
"pokeapi_id": 588,
|
||||
"pokemon_name": "Karrablast",
|
||||
"method": "walk",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 57,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 537,
|
||||
@@ -7728,33 +7799,53 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 54
|
||||
"max_level": 54,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 453,
|
||||
"pokemon_name": "Croagunk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 15,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 15,
|
||||
"summer": 15,
|
||||
"autumn": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -7768,9 +7859,14 @@
|
||||
"pokeapi_id": 588,
|
||||
"pokemon_name": "Karrablast",
|
||||
"method": "walk",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 57,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 537,
|
||||
|
||||
@@ -1486,7 +1486,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Relic Castle (Volcarona\u2019s Room and Room Outside)",
|
||||
"name": "Relic Castle (Volcarona’s Room and Room Outside)",
|
||||
"order": 30,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -2971,25 +2971,40 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -3439,25 +3454,40 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -5630,9 +5660,12 @@
|
||||
"pokeapi_id": 446,
|
||||
"pokemon_name": "Munchlax",
|
||||
"method": "trade",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 60,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 90,
|
||||
@@ -5740,9 +5773,15 @@
|
||||
"pokeapi_id": 320,
|
||||
"pokemon_name": "Wailmer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 90,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"spring": 90,
|
||||
"summer": 90,
|
||||
"autumn": 90,
|
||||
"winter": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 223,
|
||||
@@ -5772,25 +5811,36 @@
|
||||
"pokeapi_id": 458,
|
||||
"pokemon_name": "Mantyke",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 364,
|
||||
"pokemon_name": "Sealeo",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 363,
|
||||
"pokemon_name": "Spheal",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -5812,9 +5862,14 @@
|
||||
"pokeapi_id": 226,
|
||||
"pokemon_name": "Mantine",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 224,
|
||||
@@ -5836,9 +5891,12 @@
|
||||
"pokeapi_id": 365,
|
||||
"pokemon_name": "Walrein",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"winter": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@
|
||||
"encounters": [],
|
||||
"children": [
|
||||
{
|
||||
"name": "Alola Route 1 (First two fields east of the player\u2019s house)",
|
||||
"name": "Alola Route 1 (First two fields east of the player’s house)",
|
||||
"order": 3,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -368,7 +368,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Trainer\u2019s School (Alola)",
|
||||
"name": "Trainer’s School (Alola)",
|
||||
"order": 8,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -709,17 +709,23 @@
|
||||
"pokeapi_id": 425,
|
||||
"pokemon_name": "Drifloon",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 7,
|
||||
"max_level": 10
|
||||
"max_level": 10,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 200,
|
||||
"pokemon_name": "Misdreavus",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 7,
|
||||
"max_level": 10
|
||||
"max_level": 10,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 41,
|
||||
@@ -1089,17 +1095,23 @@
|
||||
"pokeapi_id": 10091,
|
||||
"pokemon_name": "Rattata (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 734,
|
||||
"pokemon_name": "Yungoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 79,
|
||||
@@ -1686,9 +1698,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1702,9 +1717,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 54,
|
||||
@@ -1740,25 +1758,34 @@
|
||||
"pokeapi_id": 755,
|
||||
"pokemon_name": "Morelull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 46,
|
||||
"pokemon_name": "Paras",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1772,9 +1799,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 278,
|
||||
@@ -1810,9 +1840,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1826,9 +1859,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2742,17 +2778,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 20,
|
||||
"max_level": 23
|
||||
"max_level": 23,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 20,
|
||||
"max_level": 23
|
||||
"max_level": 23,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 299,
|
||||
@@ -2920,33 +2962,45 @@
|
||||
"pokeapi_id": 752,
|
||||
"pokemon_name": "Araquanid",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 284,
|
||||
"pokemon_name": "Masquerain",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10107,
|
||||
@@ -3076,9 +3130,13 @@
|
||||
"pokeapi_id": 22,
|
||||
"pokemon_name": "Fearow",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 40,
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10136,
|
||||
@@ -3100,9 +3158,12 @@
|
||||
"pokeapi_id": 173,
|
||||
"pokemon_name": "Cleffa",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 132,
|
||||
@@ -3531,9 +3592,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 28,
|
||||
"max_level": 31
|
||||
"max_level": 31,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -3547,9 +3611,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 28,
|
||||
"max_level": 31
|
||||
"max_level": 31,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 361,
|
||||
@@ -3871,17 +3938,23 @@
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 34
|
||||
"max_level": 34,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 34
|
||||
"max_level": 34,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 741,
|
||||
@@ -4103,9 +4176,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4119,9 +4195,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 73,
|
||||
@@ -4213,9 +4292,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4229,9 +4311,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 210,
|
||||
@@ -4706,17 +4791,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -4792,9 +4883,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 548,
|
||||
@@ -4808,9 +4902,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 297,
|
||||
@@ -4854,17 +4951,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -4908,17 +5011,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 97,
|
||||
@@ -4994,9 +5103,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 241,
|
||||
@@ -5010,9 +5122,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 128,
|
||||
@@ -5040,17 +5155,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -5220,9 +5341,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 56,
|
||||
"max_level": 59
|
||||
"max_level": 59,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -5236,9 +5360,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 56,
|
||||
"max_level": 59
|
||||
"max_level": 59,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 210,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@
|
||||
"encounters": [],
|
||||
"children": [
|
||||
{
|
||||
"name": "Alola Route 1 (First two fields east of the player\u2019s house)",
|
||||
"name": "Alola Route 1 (First two fields east of the player’s house)",
|
||||
"order": 3,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -368,7 +368,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Trainer\u2019s School (Alola)",
|
||||
"name": "Trainer’s School (Alola)",
|
||||
"order": 8,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -709,17 +709,23 @@
|
||||
"pokeapi_id": 425,
|
||||
"pokemon_name": "Drifloon",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 7,
|
||||
"max_level": 10
|
||||
"max_level": 10,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 200,
|
||||
"pokemon_name": "Misdreavus",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 7,
|
||||
"max_level": 10
|
||||
"max_level": 10,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 41,
|
||||
@@ -1105,17 +1111,23 @@
|
||||
"pokeapi_id": 10091,
|
||||
"pokemon_name": "Rattata (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 734,
|
||||
"pokemon_name": "Yungoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 79,
|
||||
@@ -1702,9 +1714,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1718,9 +1733,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 54,
|
||||
@@ -1756,25 +1774,34 @@
|
||||
"pokeapi_id": 755,
|
||||
"pokemon_name": "Morelull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 46,
|
||||
"pokemon_name": "Paras",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1788,9 +1815,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 278,
|
||||
@@ -1826,9 +1856,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -1842,9 +1875,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2758,17 +2794,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 20,
|
||||
"max_level": 23
|
||||
"max_level": 23,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 20,
|
||||
"max_level": 23
|
||||
"max_level": 23,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 299,
|
||||
@@ -2944,33 +2986,45 @@
|
||||
"pokeapi_id": 752,
|
||||
"pokemon_name": "Araquanid",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 284,
|
||||
"pokemon_name": "Masquerain",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 24,
|
||||
"max_level": 27
|
||||
"max_level": 27,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10107,
|
||||
@@ -3100,9 +3154,13 @@
|
||||
"pokeapi_id": 22,
|
||||
"pokemon_name": "Fearow",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 40,
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10136,
|
||||
@@ -3124,9 +3182,12 @@
|
||||
"pokeapi_id": 173,
|
||||
"pokemon_name": "Cleffa",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 132,
|
||||
@@ -3571,9 +3632,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 28,
|
||||
"max_level": 31
|
||||
"max_level": 31,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -3587,9 +3651,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 28,
|
||||
"max_level": 31
|
||||
"max_level": 31,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 361,
|
||||
@@ -3911,17 +3978,23 @@
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 34
|
||||
"max_level": 34,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 34
|
||||
"max_level": 34,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 741,
|
||||
@@ -4143,9 +4216,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4159,9 +4235,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 73,
|
||||
@@ -4253,9 +4332,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4269,9 +4351,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 43
|
||||
"max_level": 43,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 210,
|
||||
@@ -4729,17 +4814,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -4823,17 +4914,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 628,
|
||||
@@ -4877,17 +4974,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -4931,17 +5034,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 546,
|
||||
@@ -5017,9 +5126,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 241,
|
||||
@@ -5033,9 +5145,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 128,
|
||||
@@ -5063,17 +5178,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 546,
|
||||
@@ -5243,9 +5364,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 56,
|
||||
"max_level": 59
|
||||
"max_level": 59,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -5259,9 +5383,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 56,
|
||||
"max_level": 59
|
||||
"max_level": 59,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 210,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"name": "Alola Route 1 (First two fields east of the player\u2019s house)",
|
||||
"name": "Alola Route 1 (First two fields east of the player’s house)",
|
||||
"order": 3,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -377,7 +377,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Trainer\u2019s School (Alola)",
|
||||
"name": "Trainer’s School (Alola)",
|
||||
"order": 8,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -773,7 +773,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Alola Route 2 (Two patches of grass southwest of the Pok\u00e9mon Center)",
|
||||
"name": "Alola Route 2 (Two patches of grass southwest of the Pokémon Center)",
|
||||
"order": 15,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -922,9 +922,12 @@
|
||||
"pokeapi_id": 425,
|
||||
"pokemon_name": "Drifloon",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 6,
|
||||
"max_level": 9
|
||||
"max_level": 9,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 92,
|
||||
@@ -938,9 +941,12 @@
|
||||
"pokeapi_id": 198,
|
||||
"pokemon_name": "Murkrow",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 6,
|
||||
"max_level": 9
|
||||
"max_level": 9,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 41,
|
||||
@@ -1342,17 +1348,23 @@
|
||||
"pokeapi_id": 10091,
|
||||
"pokemon_name": "Rattata (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 734,
|
||||
"pokemon_name": "Yungoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 456,
|
||||
@@ -1591,9 +1603,13 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 222,
|
||||
@@ -1613,17 +1629,25 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 55,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 35,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 222,
|
||||
"pokemon_name": "Corsola",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 370,
|
||||
@@ -1707,9 +1731,13 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2096,9 +2124,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -2112,33 +2143,45 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 755,
|
||||
"pokemon_name": "Morelull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 46,
|
||||
"pokemon_name": "Paras",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -2168,9 +2211,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 278,
|
||||
@@ -3263,9 +3309,13 @@
|
||||
"pokeapi_id": 278,
|
||||
"pokemon_name": "Wingull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 50,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 50
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 170,
|
||||
@@ -3287,17 +3337,23 @@
|
||||
"pokeapi_id": 177,
|
||||
"pokemon_name": "Natu",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 299,
|
||||
@@ -3341,9 +3397,13 @@
|
||||
"pokeapi_id": 771,
|
||||
"pokemon_name": "Pyukumuku",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 22,
|
||||
"max_level": 25
|
||||
"max_level": 25,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 456,
|
||||
@@ -3457,33 +3517,45 @@
|
||||
"pokeapi_id": 752,
|
||||
"pokemon_name": "Araquanid",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 284,
|
||||
"pokemon_name": "Masquerain",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10107,
|
||||
@@ -3861,9 +3933,13 @@
|
||||
"pokeapi_id": 737,
|
||||
"pokemon_name": "Charjabug",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 29,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"day": 10,
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10110,
|
||||
@@ -4013,9 +4089,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4029,9 +4108,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 361,
|
||||
@@ -4415,9 +4497,12 @@
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 33,
|
||||
"max_level": 36
|
||||
"max_level": 36,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 670,
|
||||
@@ -4431,9 +4516,12 @@
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 33,
|
||||
"max_level": 36
|
||||
"max_level": 36,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 741,
|
||||
@@ -5418,9 +5506,12 @@
|
||||
"pokeapi_id": 427,
|
||||
"pokemon_name": "Buneary",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -5458,9 +5549,12 @@
|
||||
"pokeapi_id": 447,
|
||||
"pokemon_name": "Riolu",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5559,9 +5653,13 @@
|
||||
"pokeapi_id": 743,
|
||||
"pokemon_name": "Ribombee",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 670,
|
||||
@@ -5583,9 +5681,12 @@
|
||||
"pokeapi_id": 200,
|
||||
"pokemon_name": "Misdreavus",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5621,17 +5722,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 57,
|
||||
@@ -5707,17 +5814,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -5761,33 +5874,47 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 297,
|
||||
"pokemon_name": "Hariyama",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 20,
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 97,
|
||||
"pokemon_name": "Hypno",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 241,
|
||||
@@ -5855,9 +5982,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 241,
|
||||
@@ -5871,9 +6001,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 128,
|
||||
@@ -5901,17 +6034,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -6696,7 +6835,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Team Rocket\u2019s Castle",
|
||||
"name": "Team Rocket’s Castle",
|
||||
"order": 124,
|
||||
"encounters": [
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"name": "Alola Route 1 (First two fields east of the player\u2019s house)",
|
||||
"name": "Alola Route 1 (First two fields east of the player’s house)",
|
||||
"order": 3,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -377,7 +377,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Trainer\u2019s School (Alola)",
|
||||
"name": "Trainer’s School (Alola)",
|
||||
"order": 8,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -773,7 +773,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Alola Route 2 (Two patches of grass southwest of the Pok\u00e9mon Center)",
|
||||
"name": "Alola Route 2 (Two patches of grass southwest of the Pokémon Center)",
|
||||
"order": 15,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -922,9 +922,12 @@
|
||||
"pokeapi_id": 425,
|
||||
"pokemon_name": "Drifloon",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 6,
|
||||
"max_level": 9
|
||||
"max_level": 9,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 92,
|
||||
@@ -938,9 +941,12 @@
|
||||
"pokeapi_id": 198,
|
||||
"pokemon_name": "Murkrow",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 6,
|
||||
"max_level": 9
|
||||
"max_level": 9,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 41,
|
||||
@@ -1342,17 +1348,23 @@
|
||||
"pokeapi_id": 10091,
|
||||
"pokemon_name": "Rattata (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 734,
|
||||
"pokemon_name": "Yungoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 15,
|
||||
"max_level": 18
|
||||
"max_level": 18,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 456,
|
||||
@@ -1591,9 +1603,13 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 222,
|
||||
@@ -1613,17 +1629,25 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 55,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 35,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 222,
|
||||
"pokemon_name": "Corsola",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 370,
|
||||
@@ -1707,9 +1731,13 @@
|
||||
"pokeapi_id": 366,
|
||||
"pokemon_name": "Clamperl",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 10,
|
||||
"max_level": 22
|
||||
"max_level": 22,
|
||||
"conditions": {
|
||||
"day": 5,
|
||||
"night": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2096,9 +2124,12 @@
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -2112,33 +2143,45 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 751,
|
||||
"pokemon_name": "Dewpider",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 755,
|
||||
"pokemon_name": "Morelull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 46,
|
||||
"pokemon_name": "Paras",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 60,
|
||||
@@ -2168,9 +2211,12 @@
|
||||
"pokeapi_id": 283,
|
||||
"pokemon_name": "Surskit",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 14,
|
||||
"max_level": 17
|
||||
"max_level": 17,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 278,
|
||||
@@ -3263,9 +3309,13 @@
|
||||
"pokeapi_id": 278,
|
||||
"pokemon_name": "Wingull",
|
||||
"method": "walk",
|
||||
"encounter_rate": 50,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 50
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 170,
|
||||
@@ -3287,17 +3337,23 @@
|
||||
"pokeapi_id": 177,
|
||||
"pokemon_name": "Natu",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 21,
|
||||
"max_level": 24
|
||||
"max_level": 24,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 299,
|
||||
@@ -3341,9 +3397,13 @@
|
||||
"pokeapi_id": 771,
|
||||
"pokemon_name": "Pyukumuku",
|
||||
"method": "surf",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 22,
|
||||
"max_level": 25
|
||||
"max_level": 25,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 456,
|
||||
@@ -3457,33 +3517,45 @@
|
||||
"pokeapi_id": 752,
|
||||
"pokemon_name": "Araquanid",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"day": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 284,
|
||||
"pokemon_name": "Masquerain",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 28
|
||||
"max_level": 28,
|
||||
"conditions": {
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10107,
|
||||
@@ -3861,9 +3933,13 @@
|
||||
"pokeapi_id": 737,
|
||||
"pokemon_name": "Charjabug",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 29,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"day": 10,
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10110,
|
||||
@@ -4021,9 +4097,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -4037,9 +4116,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 361,
|
||||
@@ -4423,9 +4505,12 @@
|
||||
"pokeapi_id": 168,
|
||||
"pokemon_name": "Ariados",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 33,
|
||||
"max_level": 36
|
||||
"max_level": 36,
|
||||
"conditions": {
|
||||
"night": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 546,
|
||||
@@ -4447,9 +4532,12 @@
|
||||
"pokeapi_id": 166,
|
||||
"pokemon_name": "Ledian",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 33,
|
||||
"max_level": 36
|
||||
"max_level": 36,
|
||||
"conditions": {
|
||||
"day": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 741,
|
||||
@@ -5427,9 +5515,12 @@
|
||||
"pokeapi_id": 427,
|
||||
"pokemon_name": "Buneary",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -5467,9 +5558,12 @@
|
||||
"pokeapi_id": 447,
|
||||
"pokemon_name": "Riolu",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 52,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5568,9 +5662,13 @@
|
||||
"pokeapi_id": 743,
|
||||
"pokemon_name": "Ribombee",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 670,
|
||||
@@ -5592,9 +5690,12 @@
|
||||
"pokeapi_id": 200,
|
||||
"pokemon_name": "Misdreavus",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5630,17 +5731,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 70,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 70
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 57,
|
||||
@@ -5716,17 +5823,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 732,
|
||||
@@ -5770,33 +5883,47 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 297,
|
||||
"pokemon_name": "Hariyama",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 20,
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 97,
|
||||
"pokemon_name": "Hypno",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10,
|
||||
"night": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 546,
|
||||
@@ -5864,9 +5991,12 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 241,
|
||||
@@ -5880,9 +6010,12 @@
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 128,
|
||||
@@ -5910,17 +6043,23 @@
|
||||
"pokeapi_id": 735,
|
||||
"pokemon_name": "Gumshoos",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"day": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 10092,
|
||||
"pokemon_name": "Raticate (Alola)",
|
||||
"method": "walk",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"night": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 546,
|
||||
@@ -6705,7 +6844,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Team Rocket\u2019s Castle",
|
||||
"name": "Team Rocket’s Castle",
|
||||
"order": 124,
|
||||
"encounters": [
|
||||
{
|
||||
|
||||
@@ -844,17 +844,25 @@
|
||||
"pokeapi_id": 88,
|
||||
"pokemon_name": "Grimer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 5,
|
||||
"max_level": 20
|
||||
"max_level": 20,
|
||||
"conditions": {
|
||||
"spring": 100,
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 88,
|
||||
"pokemon_name": "Grimer",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 40,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"spring": 100,
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 19,
|
||||
@@ -884,17 +892,25 @@
|
||||
"pokeapi_id": 89,
|
||||
"pokemon_name": "Muk",
|
||||
"method": "fishing",
|
||||
"encounter_rate": 10,
|
||||
"encounter_rate": null,
|
||||
"min_level": 50,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"spring": 10,
|
||||
"summer": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 89,
|
||||
"pokemon_name": "Muk",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 5,
|
||||
"max_level": 20
|
||||
"max_level": 20,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3294,41 +3310,63 @@
|
||||
"pokeapi_id": 593,
|
||||
"pokemon_name": "Jellicent",
|
||||
"method": "surf",
|
||||
"encounter_rate": 60,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 60,
|
||||
"summer": 60,
|
||||
"autumn": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 320,
|
||||
"pokemon_name": "Wailmer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 60,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30,
|
||||
"winter": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 458,
|
||||
"pokemon_name": "Mantyke",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 364,
|
||||
"pokemon_name": "Sealeo",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 363,
|
||||
"pokemon_name": "Spheal",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 171,
|
||||
@@ -3342,9 +3380,14 @@
|
||||
"pokeapi_id": 226,
|
||||
"pokemon_name": "Mantine",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 224,
|
||||
@@ -3374,9 +3417,12 @@
|
||||
"pokeapi_id": 365,
|
||||
"pokemon_name": "Walrein",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 40
|
||||
"max_level": 40,
|
||||
"conditions": {
|
||||
"winter": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -7642,33 +7688,53 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 588,
|
||||
"pokemon_name": "Karrablast",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 57,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 453,
|
||||
"pokemon_name": "Croagunk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 15,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 15,
|
||||
"summer": 15,
|
||||
"autumn": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -7690,9 +7756,14 @@
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 54
|
||||
"max_level": 54,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -7728,33 +7799,53 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 588,
|
||||
"pokemon_name": "Karrablast",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 54,
|
||||
"max_level": 54
|
||||
"max_level": 54,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 453,
|
||||
"pokemon_name": "Croagunk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 15,
|
||||
"encounter_rate": null,
|
||||
"min_level": 55,
|
||||
"max_level": 56
|
||||
"max_level": 56,
|
||||
"conditions": {
|
||||
"spring": 15,
|
||||
"summer": 15,
|
||||
"autumn": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -7776,9 +7867,14 @@
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 57,
|
||||
"max_level": 57
|
||||
"max_level": 57,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1486,7 +1486,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Relic Castle (Volcarona\u2019s Room and Room Outside)",
|
||||
"name": "Relic Castle (Volcarona’s Room and Room Outside)",
|
||||
"order": 30,
|
||||
"encounters": [
|
||||
{
|
||||
@@ -2971,25 +2971,40 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -3439,25 +3454,40 @@
|
||||
"pokeapi_id": 536,
|
||||
"pokemon_name": "Palpitoad",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 616,
|
||||
"pokemon_name": "Shelmet",
|
||||
"method": "walk",
|
||||
"encounter_rate": 40,
|
||||
"encounter_rate": null,
|
||||
"min_level": 30,
|
||||
"max_level": 33
|
||||
"max_level": 33,
|
||||
"conditions": {
|
||||
"spring": 40,
|
||||
"summer": 40,
|
||||
"autumn": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 618,
|
||||
"pokemon_name": "Stunfisk",
|
||||
"method": "walk",
|
||||
"encounter_rate": 20,
|
||||
"encounter_rate": null,
|
||||
"min_level": 31,
|
||||
"max_level": 32
|
||||
"max_level": 32,
|
||||
"conditions": {
|
||||
"spring": 20,
|
||||
"summer": 20,
|
||||
"autumn": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 340,
|
||||
@@ -5630,9 +5660,12 @@
|
||||
"pokeapi_id": 446,
|
||||
"pokemon_name": "Munchlax",
|
||||
"method": "trade",
|
||||
"encounter_rate": 100,
|
||||
"encounter_rate": null,
|
||||
"min_level": 60,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"summer": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 90,
|
||||
@@ -5740,9 +5773,15 @@
|
||||
"pokeapi_id": 320,
|
||||
"pokemon_name": "Wailmer",
|
||||
"method": "surf",
|
||||
"encounter_rate": 90,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"spring": 90,
|
||||
"summer": 90,
|
||||
"autumn": 90,
|
||||
"winter": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 223,
|
||||
@@ -5772,25 +5811,36 @@
|
||||
"pokeapi_id": 458,
|
||||
"pokemon_name": "Mantyke",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"spring": 30,
|
||||
"summer": 30,
|
||||
"autumn": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 364,
|
||||
"pokemon_name": "Sealeo",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 363,
|
||||
"pokemon_name": "Spheal",
|
||||
"method": "surf",
|
||||
"encounter_rate": 30,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 55
|
||||
"max_level": 55,
|
||||
"conditions": {
|
||||
"winter": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 279,
|
||||
@@ -5812,9 +5862,14 @@
|
||||
"pokeapi_id": 226,
|
||||
"pokemon_name": "Mantine",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 60
|
||||
"max_level": 60,
|
||||
"conditions": {
|
||||
"spring": 5,
|
||||
"summer": 5,
|
||||
"autumn": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pokeapi_id": 224,
|
||||
@@ -5836,9 +5891,12 @@
|
||||
"pokeapi_id": 365,
|
||||
"pokemon_name": "Walrein",
|
||||
"method": "surf",
|
||||
"encounter_rate": 5,
|
||||
"encounter_rate": null,
|
||||
"min_level": 25,
|
||||
"max_level": 70
|
||||
"max_level": 70,
|
||||
"conditions": {
|
||||
"winter": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -192,6 +192,41 @@ async def upsert_routes(
|
||||
return {row.name: row.id for row in result}
|
||||
|
||||
|
||||
async def _upsert_single_encounter(
|
||||
session: AsyncSession,
|
||||
route_id: int,
|
||||
pokemon_id: int,
|
||||
game_id: int,
|
||||
method: str,
|
||||
encounter_rate: int,
|
||||
min_level: int,
|
||||
max_level: int,
|
||||
condition: str = "",
|
||||
) -> None:
|
||||
stmt = (
|
||||
insert(RouteEncounter)
|
||||
.values(
|
||||
route_id=route_id,
|
||||
pokemon_id=pokemon_id,
|
||||
game_id=game_id,
|
||||
encounter_method=method,
|
||||
encounter_rate=encounter_rate,
|
||||
condition=condition,
|
||||
min_level=min_level,
|
||||
max_level=max_level,
|
||||
)
|
||||
.on_conflict_do_update(
|
||||
constraint="uq_route_pokemon_method_game_condition",
|
||||
set_={
|
||||
"encounter_rate": encounter_rate,
|
||||
"min_level": min_level,
|
||||
"max_level": max_level,
|
||||
},
|
||||
)
|
||||
)
|
||||
await session.execute(stmt)
|
||||
|
||||
|
||||
async def upsert_route_encounters(
|
||||
session: AsyncSession,
|
||||
route_id: int,
|
||||
@@ -207,28 +242,33 @@ async def upsert_route_encounters(
|
||||
print(f" Warning: no pokemon_id for pokeapi_id {enc['pokeapi_id']}")
|
||||
continue
|
||||
|
||||
stmt = (
|
||||
insert(RouteEncounter)
|
||||
.values(
|
||||
route_id=route_id,
|
||||
pokemon_id=pokemon_id,
|
||||
game_id=game_id,
|
||||
encounter_method=enc["method"],
|
||||
encounter_rate=enc["encounter_rate"],
|
||||
min_level=enc["min_level"],
|
||||
max_level=enc["max_level"],
|
||||
conditions = enc.get("conditions")
|
||||
if conditions:
|
||||
for condition_name, rate in conditions.items():
|
||||
await _upsert_single_encounter(
|
||||
session,
|
||||
route_id,
|
||||
pokemon_id,
|
||||
game_id,
|
||||
enc["method"],
|
||||
rate,
|
||||
enc["min_level"],
|
||||
enc["max_level"],
|
||||
condition=condition_name,
|
||||
)
|
||||
count += 1
|
||||
else:
|
||||
await _upsert_single_encounter(
|
||||
session,
|
||||
route_id,
|
||||
pokemon_id,
|
||||
game_id,
|
||||
enc["method"],
|
||||
enc["encounter_rate"],
|
||||
enc["min_level"],
|
||||
enc["max_level"],
|
||||
)
|
||||
.on_conflict_do_update(
|
||||
constraint="uq_route_pokemon_method_game",
|
||||
set_={
|
||||
"encounter_rate": enc["encounter_rate"],
|
||||
"min_level": enc["min_level"],
|
||||
"max_level": enc["max_level"],
|
||||
},
|
||||
)
|
||||
)
|
||||
await session.execute(stmt)
|
||||
count += 1
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
|
||||
@@ -43,6 +43,14 @@ export const METHOD_CONFIG: Record<string, { label: string; color: string }> = {
|
||||
label: 'Super Rod',
|
||||
color: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900/40 dark:text-indigo-300',
|
||||
},
|
||||
horde: {
|
||||
label: 'Horde',
|
||||
color: 'bg-rose-100 text-rose-800 dark:bg-rose-900/40 dark:text-rose-300',
|
||||
},
|
||||
sos: {
|
||||
label: 'SOS',
|
||||
color: 'bg-violet-100 text-violet-800 dark:bg-violet-900/40 dark:text-violet-300',
|
||||
},
|
||||
}
|
||||
|
||||
/** Display order for encounter method groups */
|
||||
@@ -58,6 +66,8 @@ export const METHOD_ORDER = [
|
||||
'old-rod',
|
||||
'good-rod',
|
||||
'super-rod',
|
||||
'horde',
|
||||
'sos',
|
||||
]
|
||||
|
||||
export function getMethodLabel(method: string): string {
|
||||
|
||||
@@ -62,14 +62,90 @@ const statusOptions: {
|
||||
|
||||
const SPECIAL_METHODS = ['starter', 'gift', 'fossil', 'trade']
|
||||
|
||||
function groupByMethod(
|
||||
pokemon: RouteEncounterDetail[]
|
||||
): { method: string; pokemon: RouteEncounterDetail[] }[] {
|
||||
const groups = new Map<string, RouteEncounterDetail[]>()
|
||||
interface GroupedEncounter {
|
||||
encounter: RouteEncounterDetail
|
||||
conditions: string[]
|
||||
displayRate: number | null
|
||||
}
|
||||
|
||||
function getUniqueConditions(pokemon: RouteEncounterDetail[]): string[] {
|
||||
const conditions = new Set<string>()
|
||||
for (const rp of pokemon) {
|
||||
const list = groups.get(rp.encounterMethod) ?? []
|
||||
list.push(rp)
|
||||
groups.set(rp.encounterMethod, list)
|
||||
if (rp.condition) conditions.add(rp.condition)
|
||||
}
|
||||
return [...conditions].sort()
|
||||
}
|
||||
|
||||
function groupByMethod(
|
||||
pokemon: RouteEncounterDetail[],
|
||||
selectedCondition: string | null
|
||||
): { method: string; pokemon: GroupedEncounter[] }[] {
|
||||
const groups = new Map<string, Map<number, GroupedEncounter>>()
|
||||
|
||||
// Build a lookup: pokemonId+method -> condition -> rate
|
||||
const rateByCondition = new Map<string, Map<string, number>>()
|
||||
for (const rp of pokemon) {
|
||||
if (rp.condition) {
|
||||
const key = `${rp.pokemonId}:${rp.encounterMethod}`
|
||||
let condMap = rateByCondition.get(key)
|
||||
if (!condMap) {
|
||||
condMap = new Map()
|
||||
rateByCondition.set(key, condMap)
|
||||
}
|
||||
condMap.set(rp.condition, rp.encounterRate)
|
||||
}
|
||||
}
|
||||
|
||||
for (const rp of pokemon) {
|
||||
// When a specific condition is selected, skip pokemon with 0% under that condition
|
||||
if (selectedCondition) {
|
||||
const key = `${rp.pokemonId}:${rp.encounterMethod}`
|
||||
const condMap = rateByCondition.get(key)
|
||||
if (condMap) {
|
||||
const rate = condMap.get(selectedCondition)
|
||||
if (rate === 0) continue
|
||||
// Skip entries for other conditions (we only want one entry per pokemon)
|
||||
if (rp.condition && rp.condition !== selectedCondition) continue
|
||||
}
|
||||
} else {
|
||||
// "All" mode: skip 0% entries
|
||||
if (rp.encounterRate === 0 && rp.condition) continue
|
||||
}
|
||||
|
||||
let methodGroup = groups.get(rp.encounterMethod)
|
||||
if (!methodGroup) {
|
||||
methodGroup = new Map()
|
||||
groups.set(rp.encounterMethod, methodGroup)
|
||||
}
|
||||
|
||||
const existing = methodGroup.get(rp.pokemonId)
|
||||
if (existing) {
|
||||
if (rp.condition) existing.conditions.push(rp.condition)
|
||||
} else {
|
||||
// Determine the display rate
|
||||
let displayRate: number | null = null
|
||||
const isSpecial = SPECIAL_METHODS.includes(rp.encounterMethod)
|
||||
if (!isSpecial) {
|
||||
if (selectedCondition) {
|
||||
const key = `${rp.pokemonId}:${rp.encounterMethod}`
|
||||
const condMap = rateByCondition.get(key)
|
||||
if (condMap) {
|
||||
displayRate = condMap.get(selectedCondition) ?? null
|
||||
} else {
|
||||
displayRate = rp.encounterRate
|
||||
}
|
||||
} else if (!rp.condition) {
|
||||
// "All" mode: show the base rate for non-condition entries
|
||||
displayRate = rp.encounterRate
|
||||
}
|
||||
}
|
||||
|
||||
methodGroup.set(rp.pokemonId, {
|
||||
encounter: rp,
|
||||
conditions: rp.condition ? [rp.condition] : [],
|
||||
displayRate,
|
||||
})
|
||||
}
|
||||
}
|
||||
return [...groups.entries()]
|
||||
.sort(([a], [b]) => {
|
||||
@@ -77,14 +153,25 @@ function groupByMethod(
|
||||
const bi = METHOD_ORDER.indexOf(b)
|
||||
return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi)
|
||||
})
|
||||
.map(([method, pokemon]) => ({ method, pokemon }))
|
||||
.map(([method, pokemonMap]) => ({
|
||||
method,
|
||||
pokemon: [...pokemonMap.values()].sort((a, b) => (b.displayRate ?? 0) - (a.displayRate ?? 0)),
|
||||
}))
|
||||
}
|
||||
|
||||
function pickRandomPokemon(
|
||||
pokemon: RouteEncounterDetail[],
|
||||
dupedIds?: Set<number>
|
||||
): RouteEncounterDetail | null {
|
||||
const eligible = dupedIds ? pokemon.filter((rp) => !dupedIds.has(rp.pokemonId)) : pokemon
|
||||
// Deduplicate by pokemonId (conditions may create multiple entries)
|
||||
const seen = new Set<number>()
|
||||
const unique = pokemon.filter((rp) => {
|
||||
if (rp.encounterRate === 0) return false
|
||||
if (seen.has(rp.pokemonId)) return false
|
||||
seen.add(rp.pokemonId)
|
||||
return true
|
||||
})
|
||||
const eligible = dupedIds ? unique.filter((rp) => !dupedIds.has(rp.pokemonId)) : unique
|
||||
if (eligible.length === 0) return null
|
||||
return eligible[Math.floor(Math.random() * eligible.length)] ?? null
|
||||
}
|
||||
@@ -112,6 +199,7 @@ export function EncounterModal({
|
||||
const [faintLevel, setFaintLevel] = useState<string>('')
|
||||
const [deathCause, setDeathCause] = useState('')
|
||||
const [search, setSearch] = useState('')
|
||||
const [selectedCondition, setSelectedCondition] = useState<string | null>(null)
|
||||
|
||||
const isEditing = !!existing
|
||||
|
||||
@@ -131,13 +219,18 @@ export function EncounterModal({
|
||||
}
|
||||
}, [existing, routePokemon])
|
||||
|
||||
const availableConditions = useMemo(
|
||||
() => (routePokemon ? getUniqueConditions(routePokemon) : []),
|
||||
[routePokemon]
|
||||
)
|
||||
|
||||
const filteredPokemon = routePokemon?.filter((rp) =>
|
||||
rp.pokemon.name.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
|
||||
const groupedPokemon = useMemo(
|
||||
() => (filteredPokemon ? groupByMethod(filteredPokemon) : []),
|
||||
[filteredPokemon]
|
||||
() => (filteredPokemon ? groupByMethod(filteredPokemon, selectedCondition) : []),
|
||||
[filteredPokemon, selectedCondition]
|
||||
)
|
||||
const hasMultipleGroups = groupedPokemon.length > 1
|
||||
|
||||
@@ -235,6 +328,35 @@ export function EncounterModal({
|
||||
className="w-full px-3 py-1.5 mb-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
)}
|
||||
{availableConditions.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1 mb-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelectedCondition(null)}
|
||||
className={`px-2.5 py-1 text-xs font-medium rounded-full border transition-colors ${
|
||||
selectedCondition === null
|
||||
? 'bg-purple-100 border-purple-300 text-purple-800 dark:bg-purple-900/40 dark:border-purple-600 dark:text-purple-300'
|
||||
: 'border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400 hover:border-purple-300 dark:hover:border-purple-600'
|
||||
}`}
|
||||
>
|
||||
All
|
||||
</button>
|
||||
{availableConditions.map((cond) => (
|
||||
<button
|
||||
key={cond}
|
||||
type="button"
|
||||
onClick={() => setSelectedCondition(cond)}
|
||||
className={`px-2.5 py-1 text-xs font-medium rounded-full border transition-colors capitalize ${
|
||||
selectedCondition === cond
|
||||
? 'bg-purple-100 border-purple-300 text-purple-800 dark:bg-purple-900/40 dark:border-purple-600 dark:text-purple-300'
|
||||
: 'border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400 hover:border-purple-300 dark:hover:border-purple-600'
|
||||
}`}
|
||||
>
|
||||
{cond}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="max-h-64 overflow-y-auto space-y-3">
|
||||
{groupedPokemon.map(({ method, pokemon }, groupIdx) => (
|
||||
<div key={method}>
|
||||
@@ -247,18 +369,21 @@ export function EncounterModal({
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{pokemon.map((rp) => {
|
||||
{pokemon.map(({ encounter: rp, conditions, displayRate }) => {
|
||||
const isDuped = dupedPokemonIds?.has(rp.pokemonId) ?? false
|
||||
const isSelected =
|
||||
selectedPokemon?.pokemonId === rp.pokemonId &&
|
||||
selectedPokemon?.encounterMethod === rp.encounterMethod
|
||||
return (
|
||||
<button
|
||||
key={rp.id}
|
||||
key={`${rp.encounterMethod}-${rp.pokemonId}`}
|
||||
type="button"
|
||||
onClick={() => !isDuped && setSelectedPokemon(rp)}
|
||||
disabled={isDuped}
|
||||
className={`flex flex-col items-center p-2 rounded-lg border text-center transition-colors ${
|
||||
isDuped
|
||||
? 'opacity-40 cursor-not-allowed border-gray-200 dark:border-gray-700'
|
||||
: selectedPokemon?.id === rp.id
|
||||
: isSelected
|
||||
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/30'
|
||||
: 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
|
||||
}`}
|
||||
@@ -287,6 +412,18 @@ export function EncounterModal({
|
||||
{!isDuped && SPECIAL_METHODS.includes(rp.encounterMethod) && (
|
||||
<EncounterMethodBadge method={rp.encounterMethod} />
|
||||
)}
|
||||
{!isDuped && displayRate !== null && displayRate !== undefined && (
|
||||
<span className="text-[10px] text-purple-500 dark:text-purple-400 font-medium">
|
||||
{displayRate}%
|
||||
</span>
|
||||
)}
|
||||
{!isDuped &&
|
||||
selectedCondition === null &&
|
||||
conditions.length > 0 && (
|
||||
<span className="text-[10px] text-purple-500 dark:text-purple-400">
|
||||
{conditions.join(', ')}
|
||||
</span>
|
||||
)}
|
||||
{!isDuped && (
|
||||
<span className="text-[10px] text-gray-400">
|
||||
Lv. {rp.minLevel}
|
||||
|
||||
@@ -63,6 +63,8 @@ export function AdminRouteDetail() {
|
||||
? Math.max(...childRoutes.map((r) => r.order)) + 1
|
||||
: (route?.order ?? 0) * 10 + 1
|
||||
|
||||
const hasConditions = encounters.some((e) => e.condition !== '')
|
||||
|
||||
const columns: Column<RouteEncounterDetail>[] = [
|
||||
{
|
||||
header: 'Pokemon',
|
||||
@@ -79,6 +81,14 @@ export function AdminRouteDetail() {
|
||||
},
|
||||
{ header: 'Method', accessor: (e) => e.encounterMethod },
|
||||
{ header: 'Rate', accessor: (e) => `${e.encounterRate}%` },
|
||||
...(hasConditions
|
||||
? [
|
||||
{
|
||||
header: 'Condition',
|
||||
accessor: (e: RouteEncounterDetail) => e.condition || '\u2014',
|
||||
} as Column<RouteEncounterDetail>,
|
||||
]
|
||||
: []),
|
||||
{
|
||||
header: 'Levels',
|
||||
accessor: (e) =>
|
||||
|
||||
@@ -68,6 +68,7 @@ export interface CreateRouteEncounterInput {
|
||||
gameId: number
|
||||
encounterMethod: string
|
||||
encounterRate: number
|
||||
condition?: string
|
||||
minLevel: number
|
||||
maxLevel: number
|
||||
}
|
||||
@@ -75,6 +76,7 @@ export interface CreateRouteEncounterInput {
|
||||
export interface UpdateRouteEncounterInput {
|
||||
encounterMethod?: string
|
||||
encounterRate?: number
|
||||
condition?: string
|
||||
minLevel?: number
|
||||
maxLevel?: number
|
||||
}
|
||||
@@ -128,6 +130,7 @@ export interface PokemonEncounterLocationItem {
|
||||
routeName: string
|
||||
encounterMethod: string
|
||||
encounterRate: number
|
||||
condition: string
|
||||
minLevel: number
|
||||
maxLevel: number
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ export interface RouteEncounter {
|
||||
gameId: number
|
||||
encounterMethod: string
|
||||
encounterRate: number
|
||||
condition: string
|
||||
minLevel: number
|
||||
maxLevel: number
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ ENCOUNTER_METHOD_MAP: dict[str, str] = {
|
||||
"cave-spot": "walk",
|
||||
"bubble-spot": "surf",
|
||||
"sand-spot": "walk",
|
||||
"horde": "walk",
|
||||
"sos-encounter": "walk",
|
||||
"horde": "horde",
|
||||
"sos-encounter": "sos",
|
||||
"ambush": "walk",
|
||||
# Seaweed / diving
|
||||
"diving": "surf",
|
||||
@@ -105,7 +105,7 @@ ENCOUNTER_METHOD_MAP: dict[str, str] = {
|
||||
"dust-cloud": "walk",
|
||||
"hidden-grotto": "static",
|
||||
"hidden-encounter": "walk",
|
||||
"horde-encounter": "walk",
|
||||
"horde-encounter": "horde",
|
||||
"shaking-trees": "walk",
|
||||
"shaking-ore-deposits": "walk",
|
||||
"island-scan": "static",
|
||||
|
||||
@@ -13,16 +13,22 @@ class Encounter:
|
||||
encounter_rate: int
|
||||
min_level: int
|
||||
max_level: int
|
||||
conditions: dict[str, int] | None = None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
d: dict = {
|
||||
"pokeapi_id": self.pokeapi_id,
|
||||
"pokemon_name": self.pokemon_name,
|
||||
"method": self.method,
|
||||
"encounter_rate": self.encounter_rate,
|
||||
"min_level": self.min_level,
|
||||
"max_level": self.max_level,
|
||||
}
|
||||
if self.conditions:
|
||||
d["encounter_rate"] = None
|
||||
d["conditions"] = self.conditions
|
||||
else:
|
||||
d["encounter_rate"] = self.encounter_rate
|
||||
return d
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -65,61 +65,75 @@ def parse_rate(value: str | None) -> int | None:
|
||||
return None
|
||||
|
||||
|
||||
def extract_encounter_rate(record: dict[str, Any], generation: int) -> int:
|
||||
"""Extract a single encounter_rate from a PokeDB encounter record.
|
||||
def extract_encounter_data(
|
||||
record: dict[str, Any],
|
||||
generation: int,
|
||||
) -> tuple[int, dict[str, int] | None]:
|
||||
"""Extract encounter rate and per-condition rates from a PokeDB record.
|
||||
|
||||
Flattens generation-specific rate variants into a single value.
|
||||
Returns (rate, conditions) where:
|
||||
- rate is the max/overall rate (used for sorting and backward compat)
|
||||
- conditions is a dict of {condition_name: rate} or None for flat rates
|
||||
"""
|
||||
# Gen 1/3/6: rate_overall
|
||||
# Gen 1/3/6: rate_overall — flat rate, no conditions
|
||||
rate_overall = parse_rate(record.get("rate_overall"))
|
||||
if rate_overall is not None:
|
||||
return rate_overall
|
||||
return rate_overall, None
|
||||
|
||||
# Gen 2/4: time-of-day rates — take the max
|
||||
time_rates = [
|
||||
parse_rate(record.get("rate_morning")),
|
||||
parse_rate(record.get("rate_day")),
|
||||
parse_rate(record.get("rate_night")),
|
||||
]
|
||||
time_rates = [r for r in time_rates if r is not None]
|
||||
if time_rates:
|
||||
return max(time_rates)
|
||||
# Gen 2/4/7: time-of-day rates
|
||||
time_fields = {
|
||||
"morning": parse_rate(record.get("rate_morning")),
|
||||
"day": parse_rate(record.get("rate_day")),
|
||||
"night": parse_rate(record.get("rate_night")),
|
||||
}
|
||||
time_conditions = {k: v for k, v in time_fields.items() if v is not None}
|
||||
if time_conditions:
|
||||
rate = max(time_conditions.values())
|
||||
return rate, time_conditions
|
||||
|
||||
# Gen 5: seasonal rates — take the max
|
||||
season_rates = [
|
||||
parse_rate(record.get("rate_spring")),
|
||||
parse_rate(record.get("rate_summer")),
|
||||
parse_rate(record.get("rate_autumn")),
|
||||
parse_rate(record.get("rate_winter")),
|
||||
]
|
||||
season_rates = [r for r in season_rates if r is not None]
|
||||
if season_rates:
|
||||
return max(season_rates)
|
||||
# Gen 5: seasonal rates
|
||||
season_fields = {
|
||||
"spring": parse_rate(record.get("rate_spring")),
|
||||
"summer": parse_rate(record.get("rate_summer")),
|
||||
"autumn": parse_rate(record.get("rate_autumn")),
|
||||
"winter": parse_rate(record.get("rate_winter")),
|
||||
}
|
||||
season_conditions = {
|
||||
k: v for k, v in season_fields.items() if v is not None
|
||||
}
|
||||
if season_conditions:
|
||||
rate = max(season_conditions.values())
|
||||
return rate, season_conditions
|
||||
|
||||
# Gen 8 Sw/Sh: weather rates — take the max
|
||||
weather_rates = []
|
||||
# Gen 8 Sw/Sh: weather rates
|
||||
weather_conditions: dict[str, int] = {}
|
||||
for key, val in record.items():
|
||||
if key.startswith("weather_") and key.endswith("_rate") and val:
|
||||
parsed = parse_rate(val)
|
||||
if parsed is not None:
|
||||
weather_rates.append(parsed)
|
||||
if weather_rates:
|
||||
return max(weather_rates)
|
||||
# "weather_clear_rate" -> "clear"
|
||||
condition_name = key[len("weather_"):-len("_rate")]
|
||||
weather_conditions[condition_name] = parsed
|
||||
if weather_conditions:
|
||||
rate = max(weather_conditions.values())
|
||||
return rate, weather_conditions
|
||||
|
||||
# Gen 8 Legends Arceus: boolean conditions → presence-based
|
||||
if record.get("during_any_time") or record.get("during_morning") or \
|
||||
record.get("during_day") or record.get("during_evening") or record.get("during_night"):
|
||||
return 100 # Present under conditions
|
||||
# Gen 8 Legends Arceus: boolean conditions — presence-based
|
||||
if (
|
||||
record.get("during_any_time")
|
||||
or record.get("during_morning")
|
||||
or record.get("during_day")
|
||||
or record.get("during_evening")
|
||||
or record.get("during_night")
|
||||
):
|
||||
return 100, None
|
||||
|
||||
# Gen 9 Sc/Vi: probability weights → normalize
|
||||
# Gen 9 Sc/Vi: probability weights — normalize
|
||||
prob_overall = record.get("probability_overall")
|
||||
if prob_overall:
|
||||
parsed = parse_rate(prob_overall)
|
||||
if parsed is not None:
|
||||
# These are spawn weights (e.g. "20", "300"), not percentages.
|
||||
# We'll normalize them later during aggregation when we have
|
||||
# all encounters for a location. For now, store the raw weight.
|
||||
return parsed
|
||||
return parsed, None
|
||||
|
||||
# Check time-based probability variants
|
||||
prob_rates = [
|
||||
@@ -130,10 +144,10 @@ def extract_encounter_rate(record: dict[str, Any], generation: int) -> int:
|
||||
]
|
||||
prob_rates = [r for r in prob_rates if r is not None]
|
||||
if prob_rates:
|
||||
return max(prob_rates)
|
||||
return max(prob_rates), None
|
||||
|
||||
# Fallback: gift/trade/static encounters with no rate
|
||||
return 100
|
||||
return 100, None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -212,8 +226,8 @@ def process_encounters(
|
||||
# Parse levels
|
||||
min_level, max_level = parse_levels(record.get("levels"))
|
||||
|
||||
# Extract rate
|
||||
encounter_rate = extract_encounter_rate(record, generation)
|
||||
# Extract rate and conditions
|
||||
encounter_rate, conditions = extract_encounter_data(record, generation)
|
||||
|
||||
# Location area
|
||||
area_id = record.get("location_area_identifier", "")
|
||||
@@ -227,6 +241,7 @@ def process_encounters(
|
||||
encounter_rate=encounter_rate,
|
||||
min_level=min_level,
|
||||
max_level=max_level,
|
||||
conditions=conditions,
|
||||
)
|
||||
|
||||
by_area.setdefault(area_id, []).append(enc)
|
||||
@@ -234,10 +249,28 @@ def process_encounters(
|
||||
return by_area
|
||||
|
||||
|
||||
def _merge_conditions(
|
||||
a: dict[str, int] | None,
|
||||
b: dict[str, int] | None,
|
||||
) -> dict[str, int] | None:
|
||||
"""Merge two condition dicts by summing rates per key."""
|
||||
if a is None and b is None:
|
||||
return None
|
||||
merged = dict(a or {})
|
||||
for k, v in (b or {}).items():
|
||||
merged[k] = merged.get(k, 0) + v
|
||||
return merged
|
||||
|
||||
|
||||
def _cap_conditions(conditions: dict[str, int]) -> dict[str, int]:
|
||||
"""Cap each condition rate at 100."""
|
||||
return {k: min(v, 100) for k, v in conditions.items()}
|
||||
|
||||
|
||||
def aggregate_encounters(encounters: list[Encounter]) -> list[Encounter]:
|
||||
"""Aggregate encounters by (pokeapi_id, method), merging level ranges and summing rates.
|
||||
|
||||
Replicates the Go tool's aggregation logic.
|
||||
Preserves per-condition rates through aggregation.
|
||||
"""
|
||||
key_type = tuple[int, str]
|
||||
agg: dict[key_type, Encounter] = {}
|
||||
@@ -250,8 +283,10 @@ def aggregate_encounters(encounters: list[Encounter]) -> list[Encounter]:
|
||||
existing.encounter_rate += enc.encounter_rate
|
||||
existing.min_level = min(existing.min_level, enc.min_level)
|
||||
existing.max_level = max(existing.max_level, enc.max_level)
|
||||
existing.conditions = _merge_conditions(
|
||||
existing.conditions, enc.conditions
|
||||
)
|
||||
else:
|
||||
# Copy so we don't mutate the original
|
||||
agg[k] = Encounter(
|
||||
pokeapi_id=enc.pokeapi_id,
|
||||
pokemon_name=enc.pokemon_name,
|
||||
@@ -259,6 +294,7 @@ def aggregate_encounters(encounters: list[Encounter]) -> list[Encounter]:
|
||||
encounter_rate=enc.encounter_rate,
|
||||
min_level=enc.min_level,
|
||||
max_level=enc.max_level,
|
||||
conditions=dict(enc.conditions) if enc.conditions else None,
|
||||
)
|
||||
order.append(k)
|
||||
|
||||
@@ -266,6 +302,9 @@ def aggregate_encounters(encounters: list[Encounter]) -> list[Encounter]:
|
||||
for k in order:
|
||||
e = agg[k]
|
||||
e.encounter_rate = min(e.encounter_rate, 100)
|
||||
if e.conditions:
|
||||
e.conditions = _cap_conditions(e.conditions)
|
||||
e.encounter_rate = max(e.conditions.values())
|
||||
result.append(e)
|
||||
|
||||
# Sort by rate descending, then name ascending
|
||||
|
||||
322
tools/merge-conditions.py
Normal file
322
tools/merge-conditions.py
Normal file
@@ -0,0 +1,322 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Merge per-condition encounter rates from a fresh import into curated seed files.
|
||||
|
||||
Usage:
|
||||
# From repo root (requires PokeDB cache):
|
||||
python tools/merge-conditions.py --game heartgold
|
||||
|
||||
# Process all games that have conditions:
|
||||
python tools/merge-conditions.py --all
|
||||
|
||||
# Dry run (print what would change, don't write):
|
||||
python tools/merge-conditions.py --game heartgold --dry-run
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add tools/import-pokedb to sys.path so we can import the library
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(REPO_ROOT / "tools" / "import-pokedb"))
|
||||
|
||||
from import_pokedb.loader import load_pokedb_data, load_seed_config # noqa: E402
|
||||
from import_pokedb.mappings import ( # noqa: E402
|
||||
LocationMapper,
|
||||
PokemonMapper,
|
||||
build_version_map,
|
||||
)
|
||||
from import_pokedb.processing import ( # noqa: E402
|
||||
build_routes,
|
||||
filter_den_routes,
|
||||
filter_encounters_for_game,
|
||||
process_encounters,
|
||||
)
|
||||
from import_pokedb.output import merge_special_encounters, sort_routes # noqa: E402
|
||||
|
||||
SEEDS_DIR = REPO_ROOT / "backend" / "src" / "app" / "seeds"
|
||||
DATA_DIR = SEEDS_DIR / "data"
|
||||
|
||||
# Games that have per-condition encounter rates
|
||||
CONDITION_GAMES: dict[str, str] = {
|
||||
# Gen 2: morning/day/night
|
||||
"gold": "gold-silver",
|
||||
"silver": "gold-silver",
|
||||
"crystal": "crystal",
|
||||
# Gen 4: morning/day/night
|
||||
"heartgold": "heartgold-soulsilver",
|
||||
"soulsilver": "heartgold-soulsilver",
|
||||
"diamond": "diamond-pearl",
|
||||
"pearl": "diamond-pearl",
|
||||
"platinum": "platinum",
|
||||
"brilliant-diamond": "brilliant-diamond-shining-pearl",
|
||||
"shining-pearl": "brilliant-diamond-shining-pearl",
|
||||
# Gen 5: spring/summer/autumn/winter
|
||||
"black": "black-white",
|
||||
"white": "black-white",
|
||||
"black-2": "black-2-white-2",
|
||||
"white-2": "black-2-white-2",
|
||||
# Gen 6: horde encounters
|
||||
"x": "x-y",
|
||||
"y": "x-y",
|
||||
# Gen 7: day/night + SOS
|
||||
"sun": "sun-moon",
|
||||
"moon": "sun-moon",
|
||||
"ultra-sun": "ultra-sun-ultra-moon",
|
||||
"ultra-moon": "ultra-sun-ultra-moon",
|
||||
# Gen 8: weather
|
||||
"sword": "sword-shield",
|
||||
"shield": "sword-shield",
|
||||
}
|
||||
|
||||
|
||||
def normalize_route_name(name: str) -> str:
|
||||
"""Normalize a route name for fuzzy matching."""
|
||||
return name.lower().strip()
|
||||
|
||||
|
||||
def build_fresh_lookup(
|
||||
game_slug: str,
|
||||
vg_key: str,
|
||||
generation: int,
|
||||
pokedb: object,
|
||||
config: object,
|
||||
pokemon_mapper: PokemonMapper,
|
||||
location_mapper: LocationMapper,
|
||||
) -> dict[str, dict[tuple[int, str], dict[str, int]]]:
|
||||
"""Run the import pipeline and build a conditions lookup.
|
||||
|
||||
Returns: {normalized_route_name: {(pokeapi_id, method): conditions_dict}}
|
||||
"""
|
||||
game_encounters = filter_encounters_for_game(
|
||||
pokedb.encounters, game_slug
|
||||
)
|
||||
if not game_encounters:
|
||||
return {}
|
||||
|
||||
encounters_by_area = process_encounters(
|
||||
game_encounters, generation, pokemon_mapper, location_mapper
|
||||
)
|
||||
|
||||
routes = build_routes(encounters_by_area, location_mapper)
|
||||
|
||||
if vg_key == "sword-shield":
|
||||
routes = filter_den_routes(routes)
|
||||
|
||||
routes = merge_special_encounters(
|
||||
routes, config, vg_key, pokemon_mapper
|
||||
)
|
||||
routes = sort_routes(routes, config, vg_key)
|
||||
|
||||
lookup: dict[str, dict[tuple[int, str], dict[str, int]]] = {}
|
||||
|
||||
def index_route(route):
|
||||
key = normalize_route_name(route.name)
|
||||
enc_map: dict[tuple[int, str], dict[str, int]] = {}
|
||||
for enc in route.encounters:
|
||||
if enc.conditions:
|
||||
enc_map[(enc.pokeapi_id, enc.method)] = enc.conditions
|
||||
if enc_map:
|
||||
lookup[key] = enc_map
|
||||
|
||||
for route in routes:
|
||||
index_route(route)
|
||||
for child in route.children:
|
||||
index_route(child)
|
||||
|
||||
return lookup
|
||||
|
||||
|
||||
def merge_conditions_into_seed(
|
||||
seed_data: list[dict],
|
||||
lookup: dict[str, dict[tuple[int, str], dict[str, int]]],
|
||||
game_slug: str,
|
||||
dry_run: bool = False,
|
||||
) -> tuple[list[dict], int]:
|
||||
"""Merge conditions from lookup into seed data, return (updated_data, count)."""
|
||||
merged_count = 0
|
||||
|
||||
def process_route(route: dict) -> None:
|
||||
nonlocal merged_count
|
||||
route_key = normalize_route_name(route["name"])
|
||||
route_lookup = lookup.get(route_key)
|
||||
|
||||
if route_lookup is None:
|
||||
return
|
||||
|
||||
for enc in route.get("encounters", []):
|
||||
key = (enc["pokeapi_id"], enc["method"])
|
||||
conditions = route_lookup.get(key)
|
||||
if conditions:
|
||||
if dry_run:
|
||||
print(
|
||||
f" {route['name']}: "
|
||||
f"{enc.get('pokemon_name', '?')} ({enc['method']}) "
|
||||
f"-> {conditions}"
|
||||
)
|
||||
enc["conditions"] = conditions
|
||||
enc["encounter_rate"] = None
|
||||
merged_count += 1
|
||||
|
||||
for child in route.get("children", []):
|
||||
process_route(child)
|
||||
|
||||
for route in seed_data:
|
||||
process_route(route)
|
||||
|
||||
return seed_data, merged_count
|
||||
|
||||
|
||||
def process_game(
|
||||
game_slug: str,
|
||||
pokedb,
|
||||
config,
|
||||
pokemon_mapper: PokemonMapper,
|
||||
location_mapper: LocationMapper,
|
||||
version_map: dict[str, str],
|
||||
dry_run: bool = False,
|
||||
) -> int:
|
||||
"""Process a single game. Returns number of encounters merged."""
|
||||
vg_key = CONDITION_GAMES.get(game_slug)
|
||||
if vg_key is None:
|
||||
print(f" Skipping {game_slug}: not a condition game")
|
||||
return 0
|
||||
|
||||
# Find generation
|
||||
vg_info = config.version_groups.get(vg_key)
|
||||
if vg_info is None:
|
||||
print(f" Warning: version group '{vg_key}' not found")
|
||||
return 0
|
||||
|
||||
generation = vg_info.get("generation", 0)
|
||||
|
||||
# Build fresh import lookup
|
||||
lookup = build_fresh_lookup(
|
||||
game_slug,
|
||||
vg_key,
|
||||
generation,
|
||||
pokedb,
|
||||
config,
|
||||
pokemon_mapper,
|
||||
location_mapper,
|
||||
)
|
||||
|
||||
if not lookup:
|
||||
print(" No conditions found in fresh import")
|
||||
return 0
|
||||
|
||||
total_conditions = sum(len(v) for v in lookup.values())
|
||||
print(
|
||||
f" Fresh import: {len(lookup)} routes with conditions, "
|
||||
f"{total_conditions} encounter+condition pairs"
|
||||
)
|
||||
|
||||
# Load existing seed file
|
||||
seed_path = DATA_DIR / f"{game_slug}.json"
|
||||
if not seed_path.exists():
|
||||
print(f" Warning: seed file not found: {seed_path}")
|
||||
return 0
|
||||
|
||||
with open(seed_path) as f:
|
||||
seed_data = json.load(f)
|
||||
|
||||
# Merge
|
||||
updated_data, merged_count = merge_conditions_into_seed(
|
||||
seed_data, lookup, game_slug, dry_run=dry_run
|
||||
)
|
||||
|
||||
if merged_count == 0:
|
||||
print(" No encounters matched for merging")
|
||||
return 0
|
||||
|
||||
print(f" Merged conditions into {merged_count} encounters")
|
||||
|
||||
if not dry_run:
|
||||
with open(seed_path, "w") as f:
|
||||
json.dump(updated_data, f, indent=2, ensure_ascii=False)
|
||||
f.write("\n")
|
||||
print(f" Wrote {seed_path}")
|
||||
|
||||
return merged_count
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Merge per-condition encounter rates into seed files."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--game", type=str, help="Process a specific game slug"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--all",
|
||||
action="store_true",
|
||||
help="Process all games with conditions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Print what would change without writing files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pokedb-dir",
|
||||
type=Path,
|
||||
default=None,
|
||||
help="Path to PokeDB data directory",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.game and not args.all:
|
||||
parser.error("Specify --game SLUG or --all")
|
||||
|
||||
pokedb_dir = args.pokedb_dir or (SEEDS_DIR / ".pokedb_cache")
|
||||
|
||||
print(f"PokeDB data: {pokedb_dir}")
|
||||
print(f"Seed data: {DATA_DIR}")
|
||||
print()
|
||||
|
||||
# Load PokeDB data
|
||||
pokedb = load_pokedb_data(pokedb_dir)
|
||||
print(pokedb.summary())
|
||||
print()
|
||||
|
||||
# Load seed config
|
||||
config = load_seed_config(SEEDS_DIR)
|
||||
print(f"Loaded {len(config.version_groups)} version groups")
|
||||
print()
|
||||
|
||||
# Build mappings
|
||||
pokemon_json = DATA_DIR / "pokemon.json"
|
||||
pokemon_mapper = PokemonMapper(pokemon_json, pokedb)
|
||||
location_mapper = LocationMapper(pokedb)
|
||||
version_map = build_version_map(pokedb, config.version_groups)
|
||||
|
||||
# Determine games to process
|
||||
if args.game:
|
||||
games = [args.game]
|
||||
else:
|
||||
games = list(CONDITION_GAMES.keys())
|
||||
|
||||
total_merged = 0
|
||||
for game_slug in games:
|
||||
print(f"\n--- {game_slug} ---")
|
||||
count = process_game(
|
||||
game_slug,
|
||||
pokedb,
|
||||
config,
|
||||
pokemon_mapper,
|
||||
location_mapper,
|
||||
version_map,
|
||||
dry_run=args.dry_run,
|
||||
)
|
||||
total_merged += count
|
||||
|
||||
print(f"\nTotal: {total_merged} encounters updated across {len(games)} games")
|
||||
if args.dry_run:
|
||||
print("(dry run — no files written)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user