Aplicación de escritorio para generar una tienda aleatoria de Pokémon por regiones y tiers. Permite compras con moneda ficticia, rerolls limitados y un historial de acciones. Toda la configuración (regiones, cuotas de tiers, tamaños, colores, recarga de rerolls, etc.) es externa y editable por el usuario. Los datos y el estado (dinero, tiendas por región, compras, rerolls, región activa…) persisten entre sesiones. Incluye soporte de sprites por defecto (1–1000) y sprites personalizados en una carpeta de configuración que sobrescriben los de serie.
- Características
- Stack
- Requisitos
- Instalación y arranque
- Build de producción
- Estructura relevante
- Configuración (config.json)
- Datos de Pokémon (pokemon.json)
- Sprites
- Distribución por porcentajes (tierWeights)
- Sistema de Fallback de Tiers
- Reglas de tienda y rerolls
- Gestión de perfiles
- Historial y Deshacer
- Consejos y resolución de problemas
- Licencia
- Gestión de perfiles: sistema completo de perfiles con archivos .sav independientes para cada perfil.
- Tienda por región con tamaño configurable (por defecto 10).
- Cuotas mínimas por tier (S, A, B, C…): garantizan unidades mínimas.
- Porcentajes por tier para rellenar el resto de la tienda (p. ej. C 40%, B 30%, A 20%, S 10%).
- Persistencia por región: al volver a una región, la misma tienda (con compras y estado) reaparece.
- Rerolls globales: contador único y configurable. Posibilidad de recarga cada N regiones distintas visitadas.
- Ciclos de tienda: la tienda de una región se mantiene igual durante N cambios de región (configurable); pasado el ciclo, puede regenerarse automáticamente al volver a entrar.
- Historial de compras, rerolls, cambios de región y ajustes de dinero.
- Deshacer la última acción.
- Sprites: imágenes por ID con fallback; el usuario puede poner sprites propios que sobrescriben los de serie.
- Sistema de Fallback de Tiers: sustitución automática de tiers no disponibles por tiers alternativos (configurable).
- Confirmación de degradación de tier: aviso al usuario cuando un reroll causaría una reducción de tier.
- Tema oscuro con estética simple y familiar de Pokémon (borde por color según tier, configurable).
- Gestión de Perfiles: Para poder crear nuevos perfiles, editarlos y tener varios simultáneamente
- Tauri (bundle nativo: .exe, .msi, .app, .deb, …)
- React + Vite
- Tailwind CSS v4
- Zustand (estado global con persistencia en archivos .sav)
- TypeScript
- Node.js 18+
- Rust (stable) + toolchain para Tauri
- En Windows: Microsoft C++ Build Tools
- Gestor de paquetes:
pnpm(recomendado) onpm
# Instalar dependencias
pnpm install # o npm install
# Desarrollo
pnpm tauri dev # abre la app con hot reloadLa app crea/usa la carpeta de configuración del sistema (Tauri
appConfigDir). Puedes abrirla desde Ajustes → Abrir carpeta de configuración.
# Build de producción (genera instalador / ejecutable)
pnpm tauri buildEl ejecutable/instalador se genera en src-tauri/target/release/bundle/… según tu plataforma.
src/
components/
TopBar.tsx
ProfileManager.tsx # gestión completa de perfiles
PokemonRow.tsx
HistoryPanel.tsx
PurchasesPanel.tsx
SettingsPanel.tsx
SpriteImg.tsx # carga sprites (custom o default)
lib/
config.ts # lectura/escritura config y datos, abrir carpetas
profileManager.ts # gestión de perfiles, detección y operaciones
saveManager.ts # manejo de archivos .sav por perfil
sprites.ts # utilidades sprites (override por carpeta)
storeLogic.ts # reglas de tienda/rerolls y utilidades
random.ts
store/
useShopStore.ts # estado global con persistencia en archivos .sav
types.ts # tipos compartidos
public/
sprites-default/ # sprites por defecto + fallbacksLa app crea y/o usa la carpeta de configuración del sistema (Tauri appConfigDir).
Desde la aplicación puedes abrirla en Ajustes → Abrir carpeta de configuración.
Campos soportados:
{
"shopSize": 10, // tamaño de la tienda
"quota": { "S": 1, "A": 1, "B": 1, "C": 2 }, // mínimos garantizados por tier
"tierWeights": { "C": 40, "B": 30, "A": 20, "S": 10 }, // porcentajes para rellenar el resto
"regionsOrder": ["Kanto", "Johto", "Hoenn", "Sinnoh"],
"rerollsPerRegion": 2,
// Rerolls: recarga cuando se hayan visitado N REGIONES DISTINTAS desde la última recarga.
// -1 = nunca recargar por cambiar de región
"rerollRechargeEveryRegions": 3,
// Tienda: cada región mantiene su tienda durante N CAMBIOS de región
// (se evalúa por región con un "contador" de movimientos). -1 = nunca auto-regenerar.
"shopRefreshEveryRegions": 2,
// Si haces "Actualizar" manual: ¿resetear rerolls?
"rerollResetOnRefresh": false,
// ¿Permitir duplicados visibles simultáneamente en tienda?
"allowDuplicates": false,
// Fichero de datos externos (lista de Pokémon). Se guarda junto al config.json.
"dataFile": "pokemon.json",
// Colores de borde por tier
"tierColors": {
"S": "#f59e0b",
"A": "#8b5cf6",
"B": "#3b82f6",
"C": "#22c55e"
},
"defaultTierColor": "#9ca3af",
// Si true, los comprados pueden volver a salir en un reroll
"includePurchasedInRerollPool": false,
// Si true, la tienda se autofillea al comprar un pokémon
"shopBuySlotAutofill": false,
// Si true, activa el sistema de fallback de tiers cuando no hay Pokémon disponibles
"tierFallback": false
}Notas
- Si la suma de quota excede shopSize, se ajusta empezando por tiers de menor prioridad.
- Si falta stock para un tier, se muestran huecos (“No hay pokémon de este tier disponibles”) sin consumir reroll al reintentar.
- Los colores por tier pueden cambiarse a tu gusto.
Se carga desde la carpeta de configuración (junto a config.json).
Estructura:
[
{
"id": 1,
"nombre": "Bulbasaur",
"tier": "C",
"precio": 200,
"regiones": ["Kanto"]
},
{
"id": 25,
"nombre": "Pikachu",
"tier": "B",
"precio": 500,
"regiones": ["Kanto, Johto, Hoenn"]
},
{
"id": 150,
"nombre": "Mewtwo",
"tier": "S",
"precio": 5000,
"regiones": ["Kanto"]
}
]id: número único (coincide con el nombre del sprite id.png)nombre: Nombre del pokémontier: “S” > “A” > … > “Z”precio: Precio del pokémon en la tiendaregiones: una o varias
Note
Por defecto hay una lista de pokémon con información aleatoria como ejemplo, no están todos los pokémon ni sus regiones correspondientes.
Coloca los sprites “de serie” (si los usas en tu repo) en:
public/sprites-default/{id}.png
public/sprites-default/missing.png # fallback si no existe el id
public/sprites-default/empty.png # para huecos (slots -1)En la carpeta de configuración, la app crea una subcarpeta sprites, donde puedes poner tus sprites personalizados:
<appConfigDir>/sprites/
1.png
2.png
25.png
...Si existe sprites/{id}.png, sobrescribe al de public/sprites-default/{id}.png.
Puedes abrir esta carpeta desde Ajustes → Abrir carpeta de sprites.
Tip
Para comprobar que se ha actualizado solamente tienes que hacer F5 en la aplicación
Además de los mínimos garantizados por quota, la tienda rellena el resto de huecos en base a porcentajes por tier:
quotafija los mínimos por tier (si un tier no tiene stock, se verá como hueco).tierWeightsreparte el resto de slots mediante muestreo ponderado.- Los porcentajes se normalizan (no es obligatorio que sumen 100).
- Por defecto:
C 40%,B 30%,A 20%,S 10%.
Ejemplo
"shopSize": 10,
"quota": { "S": 1, "A": 1, "B": 1, "C": 2 },
"tierWeights": { "C": 40, "B": 30, "A": 20, "S": 10 }- Se garantizan 1 Tier S, 1 Tier A, 1 Tier B, 2 Tier C, hay 5 slots cubiertos.
- Quedan 5 slots libres, a cada slot se asigna a un tier aleatorio ponderado por
tierWeights. Puede salir más o menos de un tier respecto a la cuota mínima.
La tienda se muestra ordenada de mejor a peor tier.
El sistema de fallback de tiers permite que la aplicación automáticamente sustituya Pokémon de tiers no disponibles por Pokémon de tiers alternativos, garantizando que la tienda siempre tenga contenido disponible.
Para activar el sistema de fallback, establece tierFallback: true en tu config.json:
{
"tierFallback": true
}Cuando el sistema no puede encontrar suficientes Pokémon de un tier específico, automáticamente busca Pokémon en otros tiers siguiendo esta prioridad:
- Tiers inferiores primero: Si necesita tier B, busca en C → D → E...
- Tiers superiores después: Si no encuentra en inferiores, busca en A → S
Tienes en tu región:
- Tier A: 5 Pokémon
- Tier B: 0 Pokémon (no existe)
- Tier C: 2 Pokémon
- Tier D: 0 Pokémon
Si la configuración requiere 3 Pokémon de tier B:
- Busca tier B → no encuentra ninguno
- Fallback a tier C → encuentra 2, usa 2
- Fallback a tier D → no encuentra ninguno
- Fallback a tier A → encuentra 5, usa 1
- Resultado: 3 slots de "tier B" rellenados con 2 tier C + 1 tier A
- Automático: La tienda se genera aplicando fallback cuando es necesario
- Ordenamiento: Los Pokémon se ordenan por tier independientemente del fallback aplicado
Cuando tierFallback está activo y un reroll causaría una degradación de tier, aparece una confirmación:
El tier se reducirá de A a B al rerollear. ¿Continuar?
- Aceptar: Procede con el reroll usando el tier inferior
- Cancelar: Mantiene el Pokémon actual sin gastar el reroll
El sistema de fallback respeta todas las configuraciones existentes:
- ✅ allowDuplicates: No genera duplicados si está desactivado
- ✅ includePurchasedInRerollPool: Excluye comprados si está desactivado
- ✅ quota y tierWeights: Mantiene la distribución configurada
- ✅ Filtros de región: Solo busca en la región actual
Recomendado para:
- Regiones con pocos Pokémon por tier
- Configuraciones con cuotas altas
- Garantizar tiendas siempre llenas
No recomendado para:
- Experiencias que requieren tiers específicos estrictos
- Cuando prefieres slots vacíos a mezclas de tiers
- Persistencia por región
- Cada región guarda su propia tienda (con compras, rerolls consumidos, etc.).
- Con
shopRefreshEveryRegions = N, una región permanece igual durante N cambios de región desde su última regeneración. Al superarse ese umbral y volver a entrar, puede regenerarse automáticamente.
- Rerolls (globales)
- Tienes
rerollsPerRegioncomo máximo global (visibles en la barra superior). - Con
rerollRechargeEveryRegions = R, al visitar R regiones distintas (dentro del ciclo actual) los rerolls se recargan (vuelven a 0 usados) y empieza un nuevo ciclo. Volver a una región ya contada no suma. - Si un reroll no encuentra candidato válido (por restricciones de duplicados, comprados excluidos, etc.), no se consume y se muestra un aviso breve.
- Tienes
- Compras
- Un Pokémon comprado queda marcado como Comprado en su slot. En el caso de que tengas la opción de
shopBuySlotAutofillse rellena automáticamente. - La lista de Compras muestra nombre, tier, precio, región y fecha.
- Un Pokémon comprado queda marcado como Comprado en su slot. En el caso de que tengas la opción de
La aplicación incluye un sistema completo de gestión de perfiles que permite mantener múltiples partidas independientes:
- Perfiles independientes: Cada perfíl tiene su propio archivo
.savcon estado completamente separado (dinero, compras, rerolls, regiones visitadas, historial). - Detección automática: La aplicación detecta perfiles añadidos manualmente en la carpeta al abrir el menú de perfiles.
- Identificación robusta: Los perfiles se identifican por ID único almacenado en el archivo
.sav, no solo por nombre de carpeta. - Actualización automática: Si cambias el nombre de una carpeta de perfíl, el perfíl se actualiza automáticamente al nombre de la carpeta.
Los perfiles se almacenan en la carpeta de configuración:
<appConfigDir>/profiles/
default/ # Perfíl predeterminado
save.sav
config.json
pokemon.json
sprites/
Mi_Perfil_Custom/ # Perfíl personalizado
save.sav
config.json
pokemon.json
sprites/- Crear perfíl: Nuevo perfíl vacío o copiando de otro perfíl existente.
- Duplicar perfíl: Copia completa incluyendo archivos
.sav, configuración, datos y sprites. - Renombrar perfíl: Cambiar el nombre directamente desde la interfaz.
- Eliminar perfíl: Borrar perfíl completo (no se puede eliminar el perfíl activo).
- Cambiar perfíl: Intercambiar entre perfiles con carga automática del estado.
Cada perfíl tiene su archivo save.sav que contiene:
{
"profileId": "unique-profile-id",
"regions": ["Kanto", "Johto", "Hoenn"],
"currentRegionIndex": 0,
"selectedRegionIndex": 0,
"selectedShopIndex": 0,
"lastShopIndex": 0,
"visitedRegions": ["Kanto"],
"shopByIndex": { "0": [...] },
"rerollsUsedGlobal": 0,
"money": 1000,
"history": [...],
"purchases": [...],
"undoStack": [...],
"savedAt": "2024-01-01T12:00:00.000Z"
}Cada perfíl puede tener su propia configuración personalizada:
- config.json: Configuración específica del perfíl (tamaños de tienda, cuotas, colores, etc.)
- pokemon.json: Lista de Pokémon personalizada para ese perfíl
- sprites/: Sprites personalizados que sobrescriben los por defecto
Para añadir un perfíl manualmente:
- Crea una carpeta en
<appConfigDir>/profiles/ - Añade al menos un archivo
save.savválido - Abre el menú de perfiles en la aplicación - se detectará automáticamente
Tip
Los perfiles se mantienen sincronizados incluso si cambias manualmente los nombres de las carpetas
- Historial: Registra compras, rerolls, cambios de región, modificaciones de saldo y acciones deshechas.
- Deshacer: Revierte el último cambio de estado (compra, reroll, actualizar, establecer región…).
- Barra superior: selección de región, aplicar/actualizar, deshacer, dinero, rerolls y gestión de perfiles.
- Perfiles: botón de perfil actual que abre el menú de gestión (crear, duplicar, renombrar, eliminar, cambiar).
- Ajustes: sumar/restar dinero, abrir carpetas (config/sprites), borrar datos (con confirmación).
- Historial (acciones) y Compras (registro con miniaturas).
- Tienda: cada fila muestra sprite, nombre, tier, precio, Comprar y Reroll.
- Si el slot está comprado, se muestra "Comprado".
- Si no hay Pokémon disponibles de ese tier, se muestra un mensaje y el slot queda deshabilitado (o aviso temporal al rerollear, según el caso).
- Si Tailwind da errores de PostCSS, asegúrate de usar la configuración recomendada para Tailwind v4 y Vite.
- Si no aparece nada al iniciar, revisa que existan
config.jsonypokemon.jsonen la carpeta de configuración (la app los genera por defecto). - Usa los botones de Ajustes para abrir rápidamente las carpetas o borrar datos.