develop #24
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# nuzlocke-tracker-yfi8
|
||||
title: Fetch boss battle sprites from Bulbapedia
|
||||
status: in-progress
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-02-14T09:14:32Z
|
||||
updated_at: 2026-02-14T09:24:28Z
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Write and run a one-time script to download boss battle trainer sprites from Bulbapedia's archives. For totem pokemon, link to existing pokemon sprites instead.
|
||||
|
||||
## Current State
|
||||
- 10 game directories have sprites (122 files total): red, yellow, gold, crystal, ruby, emerald, firered, diamond, heartgold, omega-ruby
|
||||
- 11 game directories are completely missing: black, black-2, platinum, x, sun, ultra-sun, lets-go-pikachu, sword, brilliant-diamond, legends-arceus, scarlet
|
||||
- 11 boss entries have null sprite_url (firered Elite Four + heartgold Elite Four/Red)
|
||||
|
||||
## Checklist
|
||||
- [x] Write download script with Bulbapedia image URL patterns
|
||||
- [x] Download sprites for all missing games
|
||||
- [x] Fill in null sprite_url entries for firered/heartgold
|
||||
- [x] Handle totem pokemon by linking to existing pokemon sprites
|
||||
- [x] Handle special cases (multi-boss entries, Legends Arceus nobles)
|
||||
- [x] Update seed JSON files with correct local paths
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# nuzlocke-tracker-zmvy
|
||||
title: Add game_id field to BossBattle for version-exclusive bosses
|
||||
status: completed
|
||||
type: feature
|
||||
priority: normal
|
||||
created_at: 2026-02-14T09:47:40Z
|
||||
updated_at: 2026-02-14T09:52:59Z
|
||||
---
|
||||
|
||||
Add a proper game_id FK to BossBattle so version-exclusive bosses can be filtered per game instead of overloading the section field.
|
||||
@@ -0,0 +1,76 @@
|
||||
"""add game_id to boss battles
|
||||
|
||||
Revision ID: f7a8b9c0d1e2
|
||||
Revises: e5f70a1ca323
|
||||
Create Date: 2026-02-14 12:00:00.000000
|
||||
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "f7a8b9c0d1e2"
|
||||
down_revision: str | Sequence[str] | None = "e5f70a1ca323"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"boss_battles",
|
||||
sa.Column("game_id", sa.Integer(), nullable=True),
|
||||
)
|
||||
op.create_foreign_key(
|
||||
"fk_boss_battles_game_id",
|
||||
"boss_battles",
|
||||
"games",
|
||||
["game_id"],
|
||||
["id"],
|
||||
)
|
||||
op.create_index("ix_boss_battles_game_id", "boss_battles", ["game_id"])
|
||||
|
||||
# Data migration: for bosses where section is a game name,
|
||||
# look up the game ID, set game_id, and reset section to null.
|
||||
conn = op.get_bind()
|
||||
rows = conn.execute(
|
||||
sa.text(
|
||||
"SELECT bb.id, g.id AS gid "
|
||||
"FROM boss_battles bb "
|
||||
"JOIN games g ON LOWER(bb.section) = LOWER(g.name) "
|
||||
"WHERE bb.section IS NOT NULL"
|
||||
)
|
||||
).fetchall()
|
||||
for row in rows:
|
||||
conn.execute(
|
||||
sa.text(
|
||||
"UPDATE boss_battles SET game_id = :gid, section = NULL WHERE id = :bid"
|
||||
),
|
||||
{"gid": row.gid, "bid": row.id},
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Reverse data migration: restore section from game name
|
||||
conn = op.get_bind()
|
||||
rows = conn.execute(
|
||||
sa.text(
|
||||
"SELECT bb.id, g.name "
|
||||
"FROM boss_battles bb "
|
||||
"JOIN games g ON bb.game_id = g.id "
|
||||
"WHERE bb.game_id IS NOT NULL"
|
||||
)
|
||||
).fetchall()
|
||||
for row in rows:
|
||||
conn.execute(
|
||||
sa.text(
|
||||
"UPDATE boss_battles SET section = :name, game_id = NULL WHERE id = :bid"
|
||||
),
|
||||
{"name": row.name, "bid": row.id},
|
||||
)
|
||||
|
||||
op.drop_index("ix_boss_battles_game_id", table_name="boss_battles")
|
||||
op.drop_constraint("fk_boss_battles_game_id", "boss_battles", type_="foreignkey")
|
||||
op.drop_column("boss_battles", "game_id")
|
||||
@@ -1,7 +1,7 @@
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Response
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
@@ -43,15 +43,26 @@ async def _get_version_group_id(session: AsyncSession, game_id: int) -> int:
|
||||
|
||||
|
||||
@router.get("/games/{game_id}/bosses", response_model=list[BossBattleResponse])
|
||||
async def list_bosses(game_id: int, session: AsyncSession = Depends(get_session)):
|
||||
async def list_bosses(
|
||||
game_id: int,
|
||||
all: bool = False,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
vg_id = await _get_version_group_id(session, game_id)
|
||||
|
||||
result = await session.execute(
|
||||
query = (
|
||||
select(BossBattle)
|
||||
.where(BossBattle.version_group_id == vg_id)
|
||||
.options(selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon))
|
||||
.order_by(BossBattle.order)
|
||||
)
|
||||
|
||||
if not all:
|
||||
query = query.where(
|
||||
or_(BossBattle.game_id.is_(None), BossBattle.game_id == game_id)
|
||||
)
|
||||
|
||||
result = await session.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
|
||||
@@ -106,6 +117,14 @@ async def create_boss(
|
||||
):
|
||||
vg_id = await _get_version_group_id(session, game_id)
|
||||
|
||||
if data.game_id is not None:
|
||||
game = await session.get(Game, data.game_id)
|
||||
if game is None or game.version_group_id != vg_id:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="game_id does not belong to this version group",
|
||||
)
|
||||
|
||||
boss = BossBattle(version_group_id=vg_id, **data.model_dump())
|
||||
session.add(boss)
|
||||
await session.commit()
|
||||
@@ -128,6 +147,14 @@ async def update_boss(
|
||||
):
|
||||
vg_id = await _get_version_group_id(session, game_id)
|
||||
|
||||
if data.game_id is not None:
|
||||
game = await session.get(Game, data.game_id)
|
||||
if game is None or game.version_group_id != vg_id:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="game_id does not belong to this version group",
|
||||
)
|
||||
|
||||
result = await session.execute(
|
||||
select(BossBattle)
|
||||
.where(BossBattle.id == boss_id, BossBattle.version_group_id == vg_id)
|
||||
@@ -192,10 +219,16 @@ async def bulk_import_bosses(
|
||||
)
|
||||
route_name_to_id = {row.name: row.id for row in result}
|
||||
|
||||
# Build game slug -> id mapping for game_slug resolution
|
||||
result = await session.execute(
|
||||
select(Game.slug, Game.id).where(Game.version_group_id == vg_id)
|
||||
)
|
||||
slug_to_game_id = {row.slug: row.id for row in result}
|
||||
|
||||
bosses_data = [item.model_dump() for item in items]
|
||||
try:
|
||||
count = await upsert_bosses(
|
||||
session, vg_id, bosses_data, dex_to_id, route_name_to_id
|
||||
session, vg_id, bosses_data, dex_to_id, route_name_to_id, slug_to_game_id
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -126,6 +126,7 @@ async def export_game_bosses(
|
||||
.options(
|
||||
selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon),
|
||||
selectinload(BossBattle.after_route),
|
||||
selectinload(BossBattle.game),
|
||||
)
|
||||
.order_by(BossBattle.order)
|
||||
)
|
||||
@@ -146,6 +147,7 @@ async def export_game_bosses(
|
||||
"location": b.location,
|
||||
"section": b.section,
|
||||
"sprite_url": b.sprite_url,
|
||||
**({"game_slug": b.game.slug} if b.game_id else {}),
|
||||
"pokemon": [
|
||||
{
|
||||
"pokeapi_id": bp.pokemon.pokeapi_id,
|
||||
|
||||
@@ -33,9 +33,13 @@ class BossBattle(Base):
|
||||
location: Mapped[str] = mapped_column(String(200))
|
||||
section: Mapped[str | None] = mapped_column(String(100), default=None)
|
||||
sprite_url: Mapped[str | None] = mapped_column(String(500))
|
||||
game_id: Mapped[int | None] = mapped_column(
|
||||
ForeignKey("games.id"), index=True, default=None
|
||||
)
|
||||
|
||||
version_group: Mapped["VersionGroup"] = relationship(back_populates="boss_battles")
|
||||
after_route: Mapped["Route | None"] = relationship()
|
||||
game: Mapped["Game | None"] = relationship()
|
||||
pokemon: Mapped[list["BossPokemon"]] = relationship(
|
||||
back_populates="boss_battle", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@ class BossBattleResponse(CamelModel):
|
||||
location: str
|
||||
section: str | None
|
||||
sprite_url: str | None
|
||||
game_id: int | None
|
||||
pokemon: list[BossPokemonResponse] = []
|
||||
|
||||
|
||||
@@ -54,6 +55,7 @@ class BossBattleCreate(CamelModel):
|
||||
location: str
|
||||
section: str | None = None
|
||||
sprite_url: str | None = None
|
||||
game_id: int | None = None
|
||||
|
||||
|
||||
class BossBattleUpdate(CamelModel):
|
||||
@@ -68,6 +70,7 @@ class BossBattleUpdate(CamelModel):
|
||||
location: str | None = None
|
||||
section: str | None = None
|
||||
sprite_url: str | None = None
|
||||
game_id: int | None = None
|
||||
|
||||
|
||||
class BossPokemonInput(CamelModel):
|
||||
|
||||
@@ -215,4 +215,5 @@ class BulkBossItem(BaseModel):
|
||||
location: str
|
||||
section: str | None = None
|
||||
sprite_url: str | None = None
|
||||
game_slug: str | None = None
|
||||
pokemon: list[BulkBossPokemonItem] = []
|
||||
|
||||
@@ -107,8 +107,9 @@
|
||||
"order": 8,
|
||||
"after_route_name": null,
|
||||
"location": "Opelucid Gym",
|
||||
"section": "Black",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/black/drayden.png",
|
||||
"game_slug": "black",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -121,8 +122,9 @@
|
||||
"order": 9,
|
||||
"after_route_name": null,
|
||||
"location": "Opelucid Gym",
|
||||
"section": "White",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/black/iris.png",
|
||||
"game_slug": "white",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"after_route_name": "Violet City",
|
||||
"location": "Violet Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/falkner.png",
|
||||
"sprite_url": "/boss-sprites/crystal/falkner.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -24,7 +24,7 @@
|
||||
"after_route_name": "Slowpoke Well",
|
||||
"location": "Azalea Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/bugsy.png",
|
||||
"sprite_url": "/boss-sprites/crystal/bugsy.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"after_route_name": "Goldenrod City",
|
||||
"location": "Goldenrod Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/whitney.png",
|
||||
"sprite_url": "/boss-sprites/crystal/whitney.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -52,7 +52,7 @@
|
||||
"after_route_name": "Ecruteak City",
|
||||
"location": "Ecruteak Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/morty.png",
|
||||
"sprite_url": "/boss-sprites/crystal/morty.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -66,7 +66,7 @@
|
||||
"after_route_name": "Cianwood City",
|
||||
"location": "Cianwood Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/chuck.png",
|
||||
"sprite_url": "/boss-sprites/crystal/chuck.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -80,7 +80,7 @@
|
||||
"after_route_name": "Cianwood City",
|
||||
"location": "Olivine Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/jasmine.png",
|
||||
"sprite_url": "/boss-sprites/crystal/jasmine.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -94,7 +94,7 @@
|
||||
"after_route_name": "Lake of Rage",
|
||||
"location": "Mahogany Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/pryce.png",
|
||||
"sprite_url": "/boss-sprites/crystal/pryce.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -108,7 +108,7 @@
|
||||
"after_route_name": "Blackthorn City",
|
||||
"location": "Blackthorn Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/clair.png",
|
||||
"sprite_url": "/boss-sprites/crystal/clair.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -122,7 +122,7 @@
|
||||
"after_route_name": "Victory Road (Kanto)",
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/will.png",
|
||||
"sprite_url": "/boss-sprites/crystal/will.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@
|
||||
"after_route_name": "Victory Road (Kanto)",
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/koga.png",
|
||||
"sprite_url": "/boss-sprites/crystal/koga.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -150,7 +150,7 @@
|
||||
"after_route_name": "Victory Road (Kanto)",
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/bruno.png",
|
||||
"sprite_url": "/boss-sprites/crystal/bruno.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -164,7 +164,7 @@
|
||||
"after_route_name": "Victory Road (Kanto)",
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/karen.png",
|
||||
"sprite_url": "/boss-sprites/crystal/karen.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -178,7 +178,7 @@
|
||||
"after_route_name": "Victory Road (Kanto)",
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/gold/lance.png",
|
||||
"sprite_url": "/boss-sprites/crystal/lance.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -192,7 +192,7 @@
|
||||
"after_route_name": "Vermilion City",
|
||||
"location": "Vermilion Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/lt-surge.png",
|
||||
"sprite_url": "/boss-sprites/crystal/lt-surge.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -206,7 +206,7 @@
|
||||
"after_route_name": "Route 05 (Kanto)",
|
||||
"location": "Saffron Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/sabrina.png",
|
||||
"sprite_url": "/boss-sprites/crystal/sabrina.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -220,7 +220,7 @@
|
||||
"after_route_name": "Cerulean Cave (B1F)",
|
||||
"location": "Cerulean Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/misty.png",
|
||||
"sprite_url": "/boss-sprites/crystal/misty.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -234,7 +234,7 @@
|
||||
"after_route_name": "Celadon City",
|
||||
"location": "Celadon Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/erika.png",
|
||||
"sprite_url": "/boss-sprites/crystal/erika.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -248,7 +248,7 @@
|
||||
"after_route_name": "Fuchsia City",
|
||||
"location": "Fuchsia Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/janine.png",
|
||||
"sprite_url": "/boss-sprites/crystal/janine.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -262,7 +262,7 @@
|
||||
"after_route_name": "Pewter City",
|
||||
"location": "Pewter Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/brock.png",
|
||||
"sprite_url": "/boss-sprites/crystal/brock.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -276,7 +276,7 @@
|
||||
"after_route_name": "Cinnabar Island",
|
||||
"location": "Cinnabar Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/blaine.png",
|
||||
"sprite_url": "/boss-sprites/crystal/blaine.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -290,7 +290,7 @@
|
||||
"after_route_name": "Viridian City",
|
||||
"location": "Viridian Gym",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/blue.png",
|
||||
"sprite_url": "/boss-sprites/crystal/blue.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -304,7 +304,7 @@
|
||||
"after_route_name": "Mt. Silver (Cave Full Restore Chamber)",
|
||||
"location": "Silver Cave",
|
||||
"section": "Endgame",
|
||||
"sprite_url": "/boss-sprites/gold/red.png",
|
||||
"sprite_url": "/boss-sprites/crystal/red.png",
|
||||
"pokemon": []
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"after_route_name": "Rustboro City",
|
||||
"location": "Rustboro Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/roxanne.png",
|
||||
"sprite_url": "/boss-sprites/emerald/roxanne.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -24,7 +24,7 @@
|
||||
"after_route_name": "Dewford Town",
|
||||
"location": "Dewford Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/brawly.png",
|
||||
"sprite_url": "/boss-sprites/emerald/brawly.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"after_route_name": "Hoenn Route 110",
|
||||
"location": "Mauville Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/wattson.png",
|
||||
"sprite_url": "/boss-sprites/emerald/wattson.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -52,7 +52,7 @@
|
||||
"after_route_name": "Lavaridge Town",
|
||||
"location": "Lavaridge Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/flannery.png",
|
||||
"sprite_url": "/boss-sprites/emerald/flannery.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -66,7 +66,7 @@
|
||||
"after_route_name": "Desert Ruins",
|
||||
"location": "Petalburg Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/norman.png",
|
||||
"sprite_url": "/boss-sprites/emerald/norman.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -80,7 +80,7 @@
|
||||
"after_route_name": "Fortree City",
|
||||
"location": "Foretree Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/winona.png",
|
||||
"sprite_url": "/boss-sprites/emerald/winona.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -94,7 +94,7 @@
|
||||
"after_route_name": "Mossdeep City",
|
||||
"location": "Mossdeep Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/tate--lisa.png",
|
||||
"sprite_url": "/boss-sprites/emerald/tate--lisa.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -108,7 +108,7 @@
|
||||
"after_route_name": "Sootopolis City",
|
||||
"location": "Sootopolis Gym",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/juan.png",
|
||||
"sprite_url": "/boss-sprites/emerald/juan.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -122,7 +122,7 @@
|
||||
"after_route_name": "Victory Road (Hoenn)",
|
||||
"location": "Ever Grande City",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/sydney.png",
|
||||
"sprite_url": "/boss-sprites/emerald/sydney.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@
|
||||
"after_route_name": "Victory Road (Hoenn)",
|
||||
"location": "Ever Grande City",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/phoebe.png",
|
||||
"sprite_url": "/boss-sprites/emerald/phoebe.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -150,7 +150,7 @@
|
||||
"after_route_name": "Victory Road (Hoenn)",
|
||||
"location": "Ever Grande City",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/glacia.png",
|
||||
"sprite_url": "/boss-sprites/emerald/glacia.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -164,7 +164,7 @@
|
||||
"after_route_name": "Victory Road (Hoenn)",
|
||||
"location": "Ever Grande City",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/ruby/drake.png",
|
||||
"sprite_url": "/boss-sprites/emerald/drake.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -145,9 +145,9 @@
|
||||
{
|
||||
"name": "Giovanni",
|
||||
"boss_type": "gym_leader",
|
||||
"specialty_type": null,
|
||||
"badge_name": "50",
|
||||
"badge_image_url": "/badges/50.png",
|
||||
"specialty_type": "ground",
|
||||
"badge_name": "Earth Badge",
|
||||
"badge_image_url": "/badges/earth-badge.png",
|
||||
"level_cap": 50,
|
||||
"order": 8,
|
||||
"after_route_name": null,
|
||||
@@ -167,7 +167,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": null,
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/firered/lorelei.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -181,7 +181,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": null,
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/firered/bruno.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -195,7 +195,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": null,
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/firered/agatha.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -209,7 +209,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": null,
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/firered/lance.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -223,7 +223,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": null,
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/firered/blue.png",
|
||||
"pokemon": [
|
||||
{
|
||||
"pokeapi_id": 18,
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/will.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/koga.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -150,7 +150,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/bruno.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -164,7 +164,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/karen.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -178,7 +178,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Indigo Plateau",
|
||||
"section": "Main Story",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/lance.png",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -304,7 +304,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Silver Cave",
|
||||
"section": "Endgame",
|
||||
"sprite_url": null,
|
||||
"sprite_url": "/boss-sprites/heartgold/red.png",
|
||||
"pokemon": []
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Grandtree Arena",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/lord-kleavor.png",
|
||||
"sprite_url": "/sprites/900.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -24,7 +24,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Brava Arena",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/lady-lilligant.png",
|
||||
"sprite_url": "/sprites/10237.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Molten Arena",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/lord-arcanine.png",
|
||||
"sprite_url": "/sprites/10230.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -52,7 +52,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Moonview Arena",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/lord-electrode.png",
|
||||
"sprite_url": "/sprites/10232.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -66,7 +66,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Icepeak Arena",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/lord-avalugg.png",
|
||||
"sprite_url": "/sprites/10243.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -80,7 +80,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Temple of Sinnoh",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/origin-dialga--palkia.png",
|
||||
"sprite_url": "/sprites/10245.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -94,7 +94,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Temple of Sinnoh",
|
||||
"section": "Main Story",
|
||||
"sprite_url": "/boss-sprites/legends-arceus/arceus.png",
|
||||
"sprite_url": "/sprites/493.webp",
|
||||
"pokemon": []
|
||||
}
|
||||
]
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "South Province (Area Three)",
|
||||
"section": "Path of Legends",
|
||||
"sprite_url": "/boss-sprites/scarlet/stony-cliff-titan.png",
|
||||
"sprite_url": "/sprites/950.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -290,7 +290,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "West Province (Area One)",
|
||||
"section": "Path of Legends",
|
||||
"sprite_url": "/boss-sprites/scarlet/open-sky-titan.png",
|
||||
"sprite_url": "/sprites/962.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -304,7 +304,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "East Province (Area Three)",
|
||||
"section": "Path of Legends",
|
||||
"sprite_url": "/boss-sprites/scarlet/lurking-steel-titan.png",
|
||||
"sprite_url": "/sprites/968.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -318,7 +318,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Asado Desert",
|
||||
"section": "Path of Legends",
|
||||
"sprite_url": "/boss-sprites/scarlet/quaking-earth-titan.png",
|
||||
"sprite_url": "/sprites/984.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -332,7 +332,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Casseroya Lake",
|
||||
"section": "Path of Legends",
|
||||
"sprite_url": "/boss-sprites/scarlet/false-dragon-titan.png",
|
||||
"sprite_url": "/sprites/977.webp",
|
||||
"pokemon": []
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Verdant Cavern",
|
||||
"section": "Melemele Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-gumshoos.png",
|
||||
"sprite_url": "/sprites/735.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Brooklet Hill",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-wishiwashi.png",
|
||||
"sprite_url": "/sprites/746.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -52,7 +52,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Wela Volcano Park",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-salazzle.png",
|
||||
"sprite_url": "/sprites/758.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -66,7 +66,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Lush Jungle",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-lurantis.png",
|
||||
"sprite_url": "/sprites/754.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -94,7 +94,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Hokulani Observatory",
|
||||
"section": "Ula'ula Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-vikavolt.png",
|
||||
"sprite_url": "/sprites/738.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -108,7 +108,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Thrifty Megamart",
|
||||
"section": "Ula'ula Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-mimikyu.png",
|
||||
"sprite_url": "/sprites/778.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Vast Poni Canyon",
|
||||
"section": "Poni Island",
|
||||
"sprite_url": "/boss-sprites/sun/totem-kommo-o.png",
|
||||
"sprite_url": "/sprites/784.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -51,8 +51,9 @@
|
||||
"order": 4,
|
||||
"after_route_name": null,
|
||||
"location": "Stow-on-Side Stadium",
|
||||
"section": "Sword",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/sword/bea.png",
|
||||
"game_slug": "sword",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -65,8 +66,9 @@
|
||||
"order": 5,
|
||||
"after_route_name": null,
|
||||
"location": "Stow-on-Side Stadium",
|
||||
"section": "Shield",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/sword/allister.png",
|
||||
"game_slug": "shield",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -93,8 +95,9 @@
|
||||
"order": 7,
|
||||
"after_route_name": null,
|
||||
"location": "Circhester Stadium",
|
||||
"section": "Sword",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/sword/gordie.png",
|
||||
"game_slug": "sword",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -107,8 +110,9 @@
|
||||
"order": 8,
|
||||
"after_route_name": null,
|
||||
"location": "Circhester Stadium",
|
||||
"section": "Shield",
|
||||
"section": null,
|
||||
"sprite_url": "/boss-sprites/sword/melony.png",
|
||||
"game_slug": "shield",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Verdant Cavern",
|
||||
"section": "Melemele Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-gumshoos.png",
|
||||
"sprite_url": "/sprites/735.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Brooklet Hill",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-araquanid.png",
|
||||
"sprite_url": "/sprites/752.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -52,7 +52,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Wela Volcano Park",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-salazzle.png",
|
||||
"sprite_url": "/sprites/758.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -66,7 +66,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Lush Jungle",
|
||||
"section": "Akala Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-lurantis.png",
|
||||
"sprite_url": "/sprites/754.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -94,7 +94,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Hokulani Observatory",
|
||||
"section": "Ula'ula Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-vikavolt.png",
|
||||
"sprite_url": "/sprites/738.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -108,7 +108,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Thrifty Megamart",
|
||||
"section": "Ula'ula Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-mimikyu.png",
|
||||
"sprite_url": "/sprites/778.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -122,7 +122,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Hokulani Observatory",
|
||||
"section": "Ula'ula Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-togedemaru.png",
|
||||
"sprite_url": "/sprites/777.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -150,7 +150,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Vast Poni Canyon",
|
||||
"section": "Poni Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-kommo-o.png",
|
||||
"sprite_url": "/sprites/784.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
@@ -164,7 +164,7 @@
|
||||
"after_route_name": null,
|
||||
"location": "Seafolk Village",
|
||||
"section": "Poni Island",
|
||||
"sprite_url": "/boss-sprites/ultra-sun/totem-ribombee.png",
|
||||
"sprite_url": "/sprites/743.webp",
|
||||
"pokemon": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -239,6 +239,7 @@ async def upsert_bosses(
|
||||
bosses: list[dict],
|
||||
dex_to_id: dict[int, int],
|
||||
route_name_to_id: dict[str, int] | None = None,
|
||||
slug_to_game_id: dict[str, int] | None = None,
|
||||
) -> int:
|
||||
"""Upsert boss battles for a version group, return count of bosses upserted."""
|
||||
count = 0
|
||||
@@ -253,6 +254,16 @@ async def upsert_bosses(
|
||||
f" Warning: route '{after_route_name}' not found for boss '{boss['name']}'"
|
||||
)
|
||||
|
||||
# Resolve game_slug to game_id
|
||||
game_id = None
|
||||
game_slug = boss.get("game_slug")
|
||||
if game_slug and slug_to_game_id:
|
||||
game_id = slug_to_game_id.get(game_slug)
|
||||
if game_id is None:
|
||||
print(
|
||||
f" Warning: game '{game_slug}' not found for boss '{boss['name']}'"
|
||||
)
|
||||
|
||||
# Upsert the boss battle on (version_group_id, order) conflict
|
||||
stmt = (
|
||||
insert(BossBattle)
|
||||
@@ -269,6 +280,7 @@ async def upsert_bosses(
|
||||
location=boss["location"],
|
||||
section=boss.get("section"),
|
||||
sprite_url=boss.get("sprite_url"),
|
||||
game_id=game_id,
|
||||
)
|
||||
.on_conflict_do_update(
|
||||
constraint="uq_boss_battles_version_group_order",
|
||||
@@ -283,6 +295,7 @@ async def upsert_bosses(
|
||||
"location": boss["location"],
|
||||
"section": boss.get("section"),
|
||||
"sprite_url": boss.get("sprite_url"),
|
||||
"game_id": game_id,
|
||||
},
|
||||
)
|
||||
.returning(BossBattle.id)
|
||||
|
||||
@@ -160,7 +160,7 @@ async def seed():
|
||||
|
||||
route_name_to_id = route_maps_by_vg.get(vg_id, {})
|
||||
boss_count = await upsert_bosses(
|
||||
session, vg_id, bosses_data, dex_to_id, route_name_to_id
|
||||
session, vg_id, bosses_data, dex_to_id, route_name_to_id, slug_to_id
|
||||
)
|
||||
total_bosses += boss_count
|
||||
print(f" {vg_slug}: {boss_count} bosses")
|
||||
@@ -491,6 +491,7 @@ async def _export_bosses(session: AsyncSession, vg_data: dict):
|
||||
.options(
|
||||
selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon),
|
||||
selectinload(BossBattle.after_route),
|
||||
selectinload(BossBattle.game),
|
||||
)
|
||||
.order_by(BossBattle.order)
|
||||
)
|
||||
@@ -525,8 +526,7 @@ async def _export_bosses(session: AsyncSession, vg_data: dict):
|
||||
downloaded_sprites,
|
||||
)
|
||||
|
||||
data.append(
|
||||
{
|
||||
boss_dict: dict = {
|
||||
"name": b.name,
|
||||
"boss_type": b.boss_type,
|
||||
"specialty_type": b.specialty_type,
|
||||
@@ -548,7 +548,9 @@ async def _export_bosses(session: AsyncSession, vg_data: dict):
|
||||
for bp in sorted(b.pokemon, key=lambda p: p.order)
|
||||
],
|
||||
}
|
||||
)
|
||||
if b.game_id:
|
||||
boss_dict["game_slug"] = b.game.slug
|
||||
data.append(boss_dict)
|
||||
|
||||
_write_json(f"{first_game_slug}-bosses.json", data)
|
||||
exported += 1
|
||||
|
||||
BIN
frontend/public/badges/basic-badge.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
frontend/public/badges/beacon-badge.png
Normal file
|
After Width: | Height: | Size: 561 KiB |
BIN
frontend/public/badges/bolt-badge.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
frontend/public/badges/bug-badge.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/public/badges/cliff-badge.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
frontend/public/badges/cobble-badge.png
Normal file
|
After Width: | Height: | Size: 493 KiB |
BIN
frontend/public/badges/dark-badge.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
frontend/public/badges/dragon-badge.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
frontend/public/badges/electric-badge.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
frontend/public/badges/fairy-badge.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/public/badges/fen-badge.png
Normal file
|
After Width: | Height: | Size: 585 KiB |
BIN
frontend/public/badges/fighting-badge.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
frontend/public/badges/fire-badge.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
frontend/public/badges/forest-badge.png
Normal file
|
After Width: | Height: | Size: 566 KiB |
BIN
frontend/public/badges/freeze-badge.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
frontend/public/badges/ghost-badge.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
frontend/public/badges/grass-badge.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
frontend/public/badges/ice-badge.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
frontend/public/badges/iceberg-badge.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
frontend/public/badges/icicle-badge.png
Normal file
|
After Width: | Height: | Size: 604 KiB |
BIN
frontend/public/badges/insect-badge.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
frontend/public/badges/jet-badge.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
frontend/public/badges/legend-badge.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
frontend/public/badges/mine-badge.png
Normal file
|
After Width: | Height: | Size: 683 KiB |
BIN
frontend/public/badges/normal-badge.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
frontend/public/badges/plant-badge.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
frontend/public/badges/psychic-badge.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
frontend/public/badges/quake-badge.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
frontend/public/badges/relic-badge.png
Normal file
|
After Width: | Height: | Size: 524 KiB |
BIN
frontend/public/badges/rock-badge.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
frontend/public/badges/rumble-badge.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
frontend/public/badges/toxic-badge.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
frontend/public/badges/trio-badge.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
frontend/public/badges/voltage-badge.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
frontend/public/badges/water-badge.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
frontend/public/badges/wave-badge.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
frontend/public/boss-sprites/black-2/burgh.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
frontend/public/boss-sprites/black-2/caitlin.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
frontend/public/boss-sprites/black-2/cheren.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/public/boss-sprites/black-2/clay.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
frontend/public/boss-sprites/black-2/drayden.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
frontend/public/boss-sprites/black-2/elesa.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
frontend/public/boss-sprites/black-2/grimsley.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
frontend/public/boss-sprites/black-2/iris.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
frontend/public/boss-sprites/black-2/marlon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
frontend/public/boss-sprites/black-2/marshal.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
frontend/public/boss-sprites/black-2/roxie.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
frontend/public/boss-sprites/black-2/shauntal.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
frontend/public/boss-sprites/black-2/skyla.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
frontend/public/boss-sprites/black/brycen.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
frontend/public/boss-sprites/black/burgh.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
frontend/public/boss-sprites/black/caitlin.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
frontend/public/boss-sprites/black/cilan--chili--cress.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
frontend/public/boss-sprites/black/clay.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
frontend/public/boss-sprites/black/drayden.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
frontend/public/boss-sprites/black/elesa.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
frontend/public/boss-sprites/black/ghetsis.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
frontend/public/boss-sprites/black/grimsley.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
frontend/public/boss-sprites/black/iris.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
frontend/public/boss-sprites/black/lenora.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
frontend/public/boss-sprites/black/marshal.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
frontend/public/boss-sprites/black/n.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
frontend/public/boss-sprites/black/shauntal.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
frontend/public/boss-sprites/black/skyla.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/aaron.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/bertha.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/byron.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/candice.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/crasher-wake.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/cynthia.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/fantina.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/flint.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/gardenia.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/lucian.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/maylene.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/roark.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
frontend/public/boss-sprites/brilliant-diamond/volkner.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
frontend/public/boss-sprites/diamond/aaron.png
Normal file
|
After Width: | Height: | Size: 821 B |
BIN
frontend/public/boss-sprites/diamond/bertha.png
Normal file
|
After Width: | Height: | Size: 745 B |
BIN
frontend/public/boss-sprites/diamond/byron.png
Normal file
|
After Width: | Height: | Size: 973 B |