pokemon-io-core 0.0.62 → 0.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ import { ItemDefinition, MoveDefinition, PlayerBattleConfig } from "../../core";
2
+ import type { CombatSkin, FighterLoadout } from "../CombatSkin";
3
+ export declare class TribeSkin implements CombatSkin {
4
+ readonly id = "tribe";
5
+ getTypes(): import("../..").TypeDefinition[];
6
+ getTypeEffectiveness(): import("../..").TypeEffectivenessMatrix;
7
+ getMoves(): MoveDefinition[];
8
+ getItems(): ItemDefinition[];
9
+ getAmulets(): never[];
10
+ getStatuses(): import("../..").StatusDefinition[];
11
+ buildPlayerConfig(loadout: FighterLoadout): PlayerBattleConfig;
12
+ }
13
+ export declare const createTribeSkin: () => CombatSkin;
@@ -0,0 +1,92 @@
1
+ // pokemon-io-core/src/skins/pokemon/pokemonSkin.ts
2
+ import { POKEMON_ITEMS } from "../pokemon";
3
+ import { TRIBE_FIGHTERS, TRIBE_MOVES, TRIBE_STATUSES, TRIBE_TYPES, TRIBE_TYPE_MATRIX, } from "./index";
4
+ // --- helpers ---
5
+ const findPokemonById = (id) => {
6
+ const lower = id.toLowerCase();
7
+ return TRIBE_FIGHTERS.find((f) => f.id.toLowerCase() === lower) ?? null;
8
+ };
9
+ const findMoveById = (id) => {
10
+ return TRIBE_MOVES.find((m) => m.id === id) ?? null;
11
+ };
12
+ const findItemById = (id) => {
13
+ return POKEMON_ITEMS.find((i) => i.id === id) ?? null;
14
+ };
15
+ const FILLER_MOVE_ID = "tackle";
16
+ const buildMovesFromLoadout = (fighter, loadout) => {
17
+ const selectedMoveIds = loadout.moveIds ?? [];
18
+ const selectedMoves = selectedMoveIds
19
+ .map((id) => findMoveById(id))
20
+ .filter((m) => m !== null);
21
+ if (selectedMoves.length >= 4) {
22
+ return selectedMoves.slice(0, 4);
23
+ }
24
+ const result = [...selectedMoves];
25
+ const recommendedIds = fighter.recommendedMoves ?? [];
26
+ for (const recId of recommendedIds) {
27
+ if (result.length >= 4)
28
+ break;
29
+ const move = findMoveById(recId);
30
+ if (move && !result.some((m) => m.id === move.id)) {
31
+ result.push(move);
32
+ }
33
+ }
34
+ const filler = findMoveById(FILLER_MOVE_ID);
35
+ while (result.length < 4 && filler) {
36
+ result.push(filler);
37
+ }
38
+ if (result.length === 0 && filler) {
39
+ result.push(filler);
40
+ }
41
+ return result.slice(0, 4);
42
+ };
43
+ const buildItemsFromLoadout = (loadout) => {
44
+ const selectedItemIds = loadout.itemIds ?? [];
45
+ const selectedItems = selectedItemIds
46
+ .map((id) => findItemById(id))
47
+ .filter((i) => i !== null);
48
+ return selectedItems;
49
+ };
50
+ export class TribeSkin {
51
+ id = "tribe";
52
+ getTypes() {
53
+ return TRIBE_TYPES;
54
+ }
55
+ getTypeEffectiveness() {
56
+ return TRIBE_TYPE_MATRIX;
57
+ }
58
+ getMoves() {
59
+ return TRIBE_MOVES;
60
+ }
61
+ getItems() {
62
+ return POKEMON_ITEMS;
63
+ }
64
+ getAmulets() {
65
+ return []; // más adelante
66
+ }
67
+ getStatuses() {
68
+ return TRIBE_STATUSES; // más adelante
69
+ }
70
+ buildPlayerConfig(loadout) {
71
+ if (!loadout.fighterId) {
72
+ throw new Error("fighterId is required in FighterLoadout");
73
+ }
74
+ console.log("buildPlayerConfig", loadout.fighterId);
75
+ const fighter = findPokemonById(loadout.fighterId);
76
+ if (!fighter) {
77
+ throw new Error(`Unknown fighterId for Pokemon skin: ${loadout.fighterId}`);
78
+ }
79
+ const moves = buildMovesFromLoadout(fighter, loadout);
80
+ const items = buildItemsFromLoadout(loadout);
81
+ return {
82
+ fighter,
83
+ maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
84
+ moves,
85
+ items,
86
+ amulet: null,
87
+ };
88
+ }
89
+ }
90
+ export const createTribeSkin = () => {
91
+ return new TribeSkin();
92
+ };
@@ -0,0 +1,2 @@
1
+ import type { FighterDefinition } from "../../core";
2
+ export declare const TRIBE_FIGHTERS: FighterDefinition[];
@@ -0,0 +1,174 @@
1
+ import { TRIBE_TYPE_IDS } from "./types";
2
+ const makeStats = (offense, defense, speed, crit) => ({
3
+ offense,
4
+ defense,
5
+ speed,
6
+ crit,
7
+ });
8
+ export const TRIBE_FIGHTERS = [
9
+ // --- TIER 1: AZUL (Suma Atk + Def < 100) ---
10
+ {
11
+ id: "becario_nft", // (Era Pikachu)
12
+ name: "Becario NFT",
13
+ description: "Cree que se hará rico mañana. Rápido hablando, frágil si le preguntas qué hace.",
14
+ img: "becario_nft", // Asume que tienes esta imagen o mapeala
15
+ classId: TRIBE_TYPE_IDS.cryptobro,
16
+ baseStats: makeStats(55, 35, 90, 15),
17
+ recommendedMoves: ["venta_humo", "spam_whatsapp"],
18
+ },
19
+ {
20
+ id: "rrpp_discoteca", // (Era Cyndaquil)
21
+ name: "RRPP de Discoteca",
22
+ description: "Te promete entrada gratis hasta la 1:00. Ofensivo pero se quema rápido.",
23
+ img: "rrpp_discoteca",
24
+ classId: TRIBE_TYPE_IDS.canallita,
25
+ baseStats: makeStats(52, 38, 75, 10),
26
+ recommendedMoves: ["tortazo_cara", "colilla"],
27
+ },
28
+ {
29
+ id: "junior_esade", // (Era Squirtle)
30
+ name: "Junior de ESADE",
31
+ description: "Lleva chaleco incluso en verano. Resiste bien gracias al dinero de papá.",
32
+ img: "junior_esade",
33
+ classId: TRIBE_TYPE_IDS.cayetano,
34
+ baseStats: makeStats(40, 58, 45, 5),
35
+ recommendedMoves: ["golpe_remo", "cafe_hirviendo"],
36
+ },
37
+ {
38
+ id: "malabarista_semaforo", // (Era Chikorita)
39
+ name: "Malabarista de Semáforo",
40
+ description: "Aguanta mucho tiempo en el mismo sitio. Soporte natural del ecosistema urbano.",
41
+ img: "malabarista",
42
+ classId: TRIBE_TYPE_IDS.perroflauta,
43
+ baseStats: makeStats(35, 60, 40, 5),
44
+ recommendedMoves: ["malabares", "pedir_un_euro"],
45
+ },
46
+ {
47
+ id: "borracho_filosofo", // (Era Psyduck)
48
+ name: "Borracho Filósofo",
49
+ description: "Le duele la cabeza pero te suelta verdades incómodas a gritos.",
50
+ img: "borracho",
51
+ classId: TRIBE_TYPE_IDS.cunado,
52
+ baseStats: makeStats(50, 40, 60, 12),
53
+ recommendedMoves: ["yo_se_mas"],
54
+ },
55
+ {
56
+ id: "novato_gym", // (Era Geodude)
57
+ name: "Novato del Gym",
58
+ description: "Muy duro de cabeza, pero lento haciendo los ejercicios.",
59
+ img: "novato_gym",
60
+ classId: TRIBE_TYPE_IDS.gymbro,
61
+ baseStats: makeStats(40, 58, 20, 5),
62
+ recommendedMoves: ["flexion", "disco_movil"],
63
+ },
64
+ // --- TIER 2: AMBER (Suma Atk + Def >= 100 y < 120) ---
65
+ {
66
+ id: "trader_agresivo", // (Era Electabuzz)
67
+ name: "Trader Agresivo",
68
+ description: "Vende cursos online. Balanceado y con gran capacidad de estafa.",
69
+ img: "trader",
70
+ classId: TRIBE_TYPE_IDS.cryptobro,
71
+ baseStats: makeStats(65, 45, 95, 10),
72
+ recommendedMoves: ["venta_humo", "spam_whatsapp"],
73
+ },
74
+ {
75
+ id: "rey_del_reservado", // (Era Magmortar)
76
+ name: "Rey del Reservado",
77
+ description: "Pide botellas con bengalas. Daño masivo a la tarjeta de crédito.",
78
+ img: "reservado",
79
+ classId: TRIBE_TYPE_IDS.canallita,
80
+ baseStats: makeStats(70, 45, 60, 8),
81
+ recommendedMoves: ["tortazo_cara", "colilla"],
82
+ },
83
+ {
84
+ id: "heredero_empresa", // (Era Blastoise)
85
+ name: "Heredero de la Empresa",
86
+ description: "Tanque con náuticos blindados. Una muralla de abogados.",
87
+ img: "heredero",
88
+ classId: TRIBE_TYPE_IDS.cayetano,
89
+ baseStats: makeStats(50, 65, 55, 5),
90
+ recommendedMoves: ["golpe_remo", "cafe_hirviendo"],
91
+ },
92
+ {
93
+ id: "activista_twitter", // (Era Sceptile)
94
+ name: "Activista de Twitter",
95
+ description: "Depredador de las redes, ataca letalmente desde el anonimato.",
96
+ img: "activista",
97
+ classId: TRIBE_TYPE_IDS.perroflauta,
98
+ baseStats: makeStats(68, 40, 100, 12),
99
+ recommendedMoves: ["malabares", "pedir_un_euro"],
100
+ },
101
+ {
102
+ id: "todologo_de_bar", // (Era Alakazam)
103
+ name: "Todólogo de Bar",
104
+ description: "IQ de 5000 (según él). Poder mental puro, cero defensa ante hechos reales.",
105
+ img: "todologo",
106
+ classId: TRIBE_TYPE_IDS.cunado,
107
+ baseStats: makeStats(75, 30, 95, 8),
108
+ recommendedMoves: ["codazo", "yo_se_mas"],
109
+ },
110
+ {
111
+ id: "portero_discoteca", // (Era Onix)
112
+ name: "Portero de Discoteca",
113
+ description: "No pasas con esas zapatillas. Defensa física impenetrable.",
114
+ img: "portero",
115
+ classId: TRIBE_TYPE_IDS.gymbro,
116
+ baseStats: makeStats(35, 80, 30, 5),
117
+ recommendedMoves: ["flexion", "derrumbe"],
118
+ },
119
+ // --- TIER 3: RED (Suma Atk + Def >= 120) ---
120
+ {
121
+ id: "elon_musk_hacendado", // (Era Zapdos)
122
+ name: "Elon Musk de Hacendado",
123
+ description: "Leyenda del emprendimiento. Domina LinkedIn con poder bruto.",
124
+ img: "elon_hacendado",
125
+ classId: TRIBE_TYPE_IDS.cryptobro,
126
+ baseStats: makeStats(70, 55, 85, 10),
127
+ recommendedMoves: ["rug_pull", "tuit_elon"],
128
+ },
129
+ {
130
+ id: "dueño_del_garito", // (Era Charizard)
131
+ name: "Dueño del Garito",
132
+ description: "Leyenda de la noche madrileña. Arrasa con todo a su paso.",
133
+ img: "dueno_garito",
134
+ classId: TRIBE_TYPE_IDS.canallita,
135
+ baseStats: makeStats(75, 50, 85, 10),
136
+ recommendedMoves: ["tortazo_cara", "cubatazo"],
137
+ },
138
+ {
139
+ id: "amancio", // (Era Kyogre)
140
+ name: "Don Amancio",
141
+ description: "Leviatán del textil capaz de comprar el país entero.",
142
+ img: "amancio",
143
+ classId: TRIBE_TYPE_IDS.cayetano,
144
+ baseStats: makeStats(75, 65, 60, 8),
145
+ recommendedMoves: ["golpe_remo", "yate_papa"],
146
+ },
147
+ {
148
+ id: "lider_comuna", // (Era Venusaur)
149
+ name: "Líder de la Comuna",
150
+ description: "Coloso del huerto urbano. Combina toxicidad pasiva y fuerza bruta.",
151
+ img: "lider_comuna",
152
+ classId: TRIBE_TYPE_IDS.perroflauta,
153
+ baseStats: makeStats(62, 63, 60, 6),
154
+ recommendedMoves: ["malabares", "huelga_general"],
155
+ },
156
+ {
157
+ id: "teorico_conspiracion", // (Era Mew)
158
+ name: "Teórico de la Conspiración",
159
+ description: "El ancestro de todos los foros. Versátil y místico.",
160
+ img: "conspiranoico",
161
+ classId: TRIBE_TYPE_IDS.cunado,
162
+ baseStats: makeStats(65, 65, 80, 10),
163
+ recommendedMoves: ["codazo", "dato_inventado"],
164
+ },
165
+ {
166
+ id: "jefe_desokupa", // (Era Groudon)
167
+ name: "Jefe de Desokupa",
168
+ description: "Creador de polémicas, poder físico devastador.",
169
+ img: "desokupa",
170
+ classId: TRIBE_TYPE_IDS.gymbro,
171
+ baseStats: makeStats(80, 70, 50, 6),
172
+ recommendedMoves: ["flexion", "derrumbe"],
173
+ },
174
+ ];
@@ -0,0 +1,5 @@
1
+ export * from "./fighters.js";
2
+ export * from "./moves.js";
3
+ export * from "./clicheSkin.js";
4
+ export * from "./statuses.js";
5
+ export * from "./types.js";
@@ -0,0 +1,5 @@
1
+ export * from "./fighters.js";
2
+ export * from "./moves.js";
3
+ export * from "./clicheSkin.js";
4
+ export * from "./statuses.js";
5
+ export * from "./types.js";
@@ -0,0 +1,2 @@
1
+ import { ItemDefinition } from "../../core";
2
+ export declare const POKEMON_ITEMS: ItemDefinition[];
@@ -0,0 +1,143 @@
1
+ export const POKEMON_ITEMS = [
2
+ {
3
+ id: "super_potion",
4
+ name: "Super Poción",
5
+ category: "heal_shield",
6
+ target: "self",
7
+ maxUses: 1,
8
+ effects: [{ kind: "heal", amount: 50 }],
9
+ image: "hiper-potion",
10
+ },
11
+ {
12
+ id: "potion",
13
+ name: "Poción",
14
+ category: "heal_shield",
15
+ target: "self",
16
+ maxUses: 2,
17
+ effects: [{ kind: "heal", amount: 25 }],
18
+ image: "potion",
19
+ },
20
+ {
21
+ id: "apple",
22
+ name: "Manzana",
23
+ category: "heal_shield",
24
+ target: "self",
25
+ maxUses: 3,
26
+ effects: [{ kind: "heal", amount: 17 }],
27
+ image: "fancy-apple",
28
+ },
29
+ {
30
+ id: "mushroom",
31
+ name: "Seta",
32
+ category: "heal_shield",
33
+ target: "self",
34
+ maxUses: 4,
35
+ effects: [{ kind: "heal", amount: 14 }],
36
+ image: "mushroom",
37
+ },
38
+ {
39
+ id: "shotgun",
40
+ name: "Escopeta",
41
+ target: "enemy",
42
+ category: "damage",
43
+ maxUses: 2,
44
+ effects: [
45
+ { kind: "damage", flatAmount: 15 },
46
+ { kind: "apply_status", statusId: "burn" },
47
+ ],
48
+ image: "shotgun",
49
+ },
50
+ {
51
+ id: "pistol",
52
+ name: "Pistola",
53
+ category: "damage",
54
+ target: "enemy",
55
+ maxUses: 4,
56
+ effects: [
57
+ { kind: "damage", flatAmount: 8 },
58
+ { kind: "apply_status", statusId: "burn" },
59
+ ],
60
+ image: "pistol",
61
+ },
62
+ {
63
+ id: "riffle",
64
+ name: "Rifle",
65
+ target: "enemy",
66
+ category: "damage",
67
+ maxUses: 3,
68
+ effects: [
69
+ { kind: "damage", flatAmount: 10 },
70
+ { kind: "apply_status", statusId: "burn" },
71
+ ],
72
+ image: "riffle",
73
+ },
74
+ {
75
+ id: "sniper",
76
+ name: "Sniper",
77
+ target: "enemy",
78
+ category: "damage",
79
+ maxUses: 1,
80
+ effects: [
81
+ { kind: "damage", flatAmount: 30 },
82
+ { kind: "apply_status", statusId: "burn" },
83
+ ],
84
+ image: "sniper",
85
+ },
86
+ {
87
+ id: "blue-berry",
88
+ name: "Baya azul",
89
+ category: "status_buff",
90
+ maxUses: 1,
91
+ target: "self",
92
+ effects: [
93
+ {
94
+ kind: "clear_status",
95
+ statusIds: ["burn"], // cura QUEMADURA
96
+ },
97
+ ],
98
+ image: "blue-berry",
99
+ },
100
+ {
101
+ id: "pink-berry",
102
+ name: "Baya rosa",
103
+ category: "status_buff",
104
+ maxUses: 1,
105
+ target: "self",
106
+ effects: [
107
+ {
108
+ kind: "clear_status",
109
+ statusIds: ["poison"], // cura VENENO
110
+ },
111
+ ],
112
+ image: "pink-berry",
113
+ },
114
+ {
115
+ id: "yellow-berry",
116
+ name: "Baya amarilla",
117
+ category: "status_buff",
118
+ maxUses: 1,
119
+ target: "self",
120
+ effects: [
121
+ {
122
+ kind: "clear_status",
123
+ statusIds: ["paralysis"], // cura PARÁLISIS
124
+ },
125
+ ],
126
+ image: "yellow-berry",
127
+ },
128
+ {
129
+ id: "green-berry",
130
+ name: "Baya verde",
131
+ category: "status_buff",
132
+ maxUses: 1,
133
+ target: "self",
134
+ effects: [
135
+ {
136
+ kind: "clear_status",
137
+ statusIds: ["burn", "poison"], // por ejemplo: limpia quemadura o veneno
138
+ kinds: ["soft"], // redundante pero semántico
139
+ },
140
+ ],
141
+ image: "green-berry",
142
+ },
143
+ ];
@@ -0,0 +1,2 @@
1
+ import type { MoveDefinition } from "../../core";
2
+ export declare const TRIBE_MOVES: MoveDefinition[];
@@ -0,0 +1,422 @@
1
+ export const TRIBE_MOVES = [
2
+ // --- CANALLITA (Fuego) ---
3
+ {
4
+ id: "chupito_fuego", // overheat
5
+ name: "Ronda de Jäger",
6
+ typeId: "canallita",
7
+ accuracy: 66,
8
+ maxPP: 3,
9
+ priority: 0,
10
+ effects: [
11
+ { kind: "damage", basePower: 40 },
12
+ { kind: "damage", flatAmount: 10, target: "self" } // Te hace daño al hígado
13
+ ]
14
+ },
15
+ {
16
+ id: "cubatazo", // flamethrower
17
+ name: "Cubatazo",
18
+ typeId: "canallita",
19
+ accuracy: 65,
20
+ maxPP: 8,
21
+ priority: 0,
22
+ effects: [
23
+ { kind: "damage", basePower: 30 }
24
+ ]
25
+ },
26
+ {
27
+ id: "colilla", // ember
28
+ name: "Colilla Mal Apagada",
29
+ typeId: "canallita",
30
+ accuracy: 65,
31
+ maxPP: 15,
32
+ priority: 0,
33
+ effects: [
34
+ { kind: "damage", basePower: 20 },
35
+ { kind: "apply_status", statusId: "resaca" }
36
+ ]
37
+ },
38
+ {
39
+ id: "kebab_salvador", // purifying_flame (Heal)
40
+ name: "Kebab de Madrugada",
41
+ typeId: "canallita",
42
+ accuracy: 100,
43
+ maxPP: 5,
44
+ priority: 0,
45
+ effects: [
46
+ { kind: "heal", target: "self", amount: 22 },
47
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
48
+ ]
49
+ },
50
+ {
51
+ id: "tortazo_cara", // fire_claw (Basic attack 15)
52
+ name: "Tortazo de Realidad",
53
+ typeId: "canallita",
54
+ accuracy: 100,
55
+ maxPP: 10,
56
+ priority: 0,
57
+ effects: [
58
+ { kind: "damage", basePower: 15 }
59
+ ]
60
+ },
61
+ {
62
+ id: "ego_boost", // healing_warmth
63
+ name: "Subidón de Ego",
64
+ typeId: "canallita",
65
+ accuracy: 100,
66
+ maxPP: 8,
67
+ priority: 0,
68
+ effects: [
69
+ { kind: "heal", target: "self", amount: 18 }
70
+ ]
71
+ },
72
+ // --- CAYETANO (Agua) ---
73
+ {
74
+ id: "demanda_judicial", // hydro_cannon
75
+ name: "Demanda Judicial",
76
+ typeId: "cayetano",
77
+ accuracy: 85,
78
+ maxPP: 3,
79
+ priority: 0,
80
+ effects: [
81
+ { kind: "damage", basePower: 40 },
82
+ { kind: "modify_stats", offenseDelta: -15 } // Pierdes tiempo en juzgados
83
+ ]
84
+ },
85
+ {
86
+ id: "yate_papa", // surf
87
+ name: "Yate de Papá",
88
+ typeId: "cayetano",
89
+ accuracy: 100,
90
+ maxPP: 8,
91
+ priority: 0,
92
+ effects: [
93
+ { kind: "damage", basePower: 30 }
94
+ ]
95
+ },
96
+ {
97
+ id: "cafe_hirviendo", // scald
98
+ name: "Café de Especialidad",
99
+ typeId: "cayetano",
100
+ accuracy: 100,
101
+ maxPP: 10,
102
+ priority: 0,
103
+ effects: [
104
+ { kind: "damage", basePower: 20 },
105
+ { kind: "apply_status", statusId: "cancelado" }
106
+ ]
107
+ },
108
+ {
109
+ id: "contacto_influente", // aqua_purify
110
+ name: "Llamada a Contactos",
111
+ typeId: "cayetano",
112
+ accuracy: 100,
113
+ maxPP: 5,
114
+ priority: 0,
115
+ effects: [
116
+ { kind: "heal", target: "self", amount: 22 },
117
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
118
+ ]
119
+ },
120
+ {
121
+ id: "golpe_remo", // wave_crash (Basic 15)
122
+ name: "Golpe de Remo",
123
+ typeId: "cayetano",
124
+ accuracy: 100,
125
+ maxPP: 10,
126
+ priority: 0,
127
+ effects: [
128
+ { kind: "damage", basePower: 15 }
129
+ ]
130
+ },
131
+ {
132
+ id: "herencia", // healing_rain
133
+ name: "Cobrar Herencia",
134
+ typeId: "cayetano",
135
+ accuracy: 100,
136
+ maxPP: 8,
137
+ priority: 0,
138
+ effects: [
139
+ { kind: "heal", target: "self", amount: 18 }
140
+ ]
141
+ },
142
+ // --- PERROFLAUTA (Planta) ---
143
+ {
144
+ id: "huelga_general", // leaf_storm
145
+ name: "Huelga General",
146
+ typeId: "perroflauta",
147
+ accuracy: 90,
148
+ maxPP: 3,
149
+ priority: 0,
150
+ effects: [
151
+ { kind: "damage", basePower: 40 },
152
+ { kind: "modify_stats", offenseDelta: -20 } // Te cansas de gritar
153
+ ]
154
+ },
155
+ {
156
+ id: "energia_reiki", // energy_ball
157
+ name: "Bola de Reiki",
158
+ typeId: "perroflauta",
159
+ accuracy: 100,
160
+ maxPP: 8,
161
+ priority: 0,
162
+ effects: [
163
+ { kind: "damage", basePower: 30 }
164
+ ]
165
+ },
166
+ {
167
+ id: "pedir_un_euro", // leech_seed
168
+ name: "Pedir un Euro",
169
+ typeId: "perroflauta",
170
+ accuracy: 100,
171
+ maxPP: 10,
172
+ priority: 0,
173
+ effects: [
174
+ { kind: "damage", basePower: 20 },
175
+ { kind: "apply_status", statusId: "sin_cobertura" }
176
+ ]
177
+ },
178
+ {
179
+ id: "limpieza_chakras", // nature_purify
180
+ name: "Limpieza de Chakras",
181
+ typeId: "perroflauta",
182
+ accuracy: 100,
183
+ maxPP: 5,
184
+ priority: 0,
185
+ effects: [
186
+ { kind: "heal", target: "self", amount: 22 },
187
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
188
+ ]
189
+ },
190
+ {
191
+ id: "malabares", // power_whip (Basic 15)
192
+ name: "Golpe de Diábolo",
193
+ typeId: "perroflauta",
194
+ accuracy: 100,
195
+ maxPP: 10,
196
+ priority: 0,
197
+ effects: [
198
+ { kind: "damage", basePower: 15 }
199
+ ]
200
+ },
201
+ {
202
+ id: "abrazar_arbol", // regrowth
203
+ name: "Abrazar un Árbol",
204
+ typeId: "perroflauta",
205
+ accuracy: 100,
206
+ maxPP: 8,
207
+ priority: 0,
208
+ effects: [
209
+ { kind: "heal", target: "self", amount: 18 }
210
+ ]
211
+ },
212
+ // --- CUÑADO (Psíquico) ---
213
+ {
214
+ id: "dato_inventado", // psycho_boost
215
+ name: "Dato Inventado",
216
+ typeId: "cunado",
217
+ accuracy: 90,
218
+ maxPP: 3,
219
+ priority: 0,
220
+ effects: [
221
+ { kind: "damage", basePower: 40 },
222
+ { kind: "modify_stats", offenseDelta: -20 } // Pierdes credibilidad
223
+ ]
224
+ },
225
+ {
226
+ id: "chapa_politica", // psychic
227
+ name: "Chapa Política",
228
+ typeId: "cunado",
229
+ accuracy: 100,
230
+ maxPP: 8,
231
+ priority: 0,
232
+ effects: [
233
+ { kind: "damage", basePower: 30 }
234
+ ]
235
+ },
236
+ {
237
+ id: "yo_se_mas", // mind_spike
238
+ name: "Yo Sé Más Que Tú",
239
+ typeId: "cunado",
240
+ accuracy: 100,
241
+ maxPP: 8,
242
+ priority: 0,
243
+ effects: [
244
+ { kind: "damage", basePower: 20 },
245
+ { kind: "apply_status", statusId: "turra_maxima" }
246
+ ]
247
+ },
248
+ {
249
+ id: "borrar_historial", // aura_cleanse
250
+ name: "Borrar Historial",
251
+ typeId: "cunado",
252
+ accuracy: 100,
253
+ maxPP: 5,
254
+ priority: 0,
255
+ effects: [
256
+ { kind: "heal", target: "self", amount: 22 },
257
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
258
+ ]
259
+ },
260
+ {
261
+ id: "codazo", // psyshock (Basic 15)
262
+ name: "Codazo de Barra",
263
+ typeId: "cunado",
264
+ accuracy: 100,
265
+ maxPP: 10,
266
+ priority: 0,
267
+ effects: [
268
+ { kind: "damage", basePower: 15 }
269
+ ]
270
+ },
271
+ {
272
+ id: "tener_razon", // healing_mind
273
+ name: "Tener la Razón",
274
+ typeId: "cunado",
275
+ accuracy: 100,
276
+ maxPP: 8,
277
+ priority: 0,
278
+ effects: [
279
+ { kind: "heal", target: "self", amount: 18 }
280
+ ]
281
+ },
282
+ // --- GYMBRO (Roca) ---
283
+ {
284
+ id: "mancuernazo", // rock_wrecker
285
+ name: "Mancuernazo",
286
+ typeId: "gymbro",
287
+ accuracy: 85,
288
+ maxPP: 3,
289
+ priority: 0,
290
+ effects: [
291
+ { kind: "damage", basePower: 40 },
292
+ { kind: "modify_stats", offenseDelta: -20 } // Catabolizas
293
+ ]
294
+ },
295
+ {
296
+ id: "disco_movil", // stone_edge
297
+ name: "Disco de 20kg",
298
+ typeId: "gymbro",
299
+ accuracy: 90,
300
+ maxPP: 5,
301
+ priority: 0,
302
+ effects: [
303
+ { kind: "damage", basePower: 30 }
304
+ ]
305
+ },
306
+ {
307
+ id: "derrumbe", // rock_slide
308
+ name: "Derrumbe Inmobiliario",
309
+ typeId: "gymbro",
310
+ accuracy: 100,
311
+ maxPP: 8,
312
+ priority: 0,
313
+ effects: [
314
+ { kind: "damage", basePower: 15 },
315
+ { kind: "apply_status", statusId: "agujetas" }
316
+ ]
317
+ },
318
+ {
319
+ id: "ducha_fria", // sand_cleanse
320
+ name: "Ducha Fría",
321
+ typeId: "gymbro",
322
+ accuracy: 100,
323
+ maxPP: 5,
324
+ priority: 0,
325
+ effects: [
326
+ { kind: "heal", target: "self", amount: 22 },
327
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
328
+ ]
329
+ },
330
+ {
331
+ id: "flexion", // power_gem (Basic 15)
332
+ name: "Flexión Agresiva",
333
+ typeId: "gymbro",
334
+ accuracy: 100,
335
+ maxPP: 10,
336
+ priority: 0,
337
+ effects: [
338
+ { kind: "damage", basePower: 15 }
339
+ ]
340
+ },
341
+ {
342
+ id: "batido_prote", // healing_mineral
343
+ name: "Batido de Proteína",
344
+ typeId: "gymbro",
345
+ accuracy: 100,
346
+ maxPP: 8,
347
+ priority: 0,
348
+ effects: [
349
+ { kind: "heal", target: "self", amount: 18 }
350
+ ]
351
+ },
352
+ // --- CRYPTOBRO (Eléctrico) ---
353
+ {
354
+ id: "rug_pull", // bolt_strike
355
+ name: "Rug Pull",
356
+ typeId: "cryptobro",
357
+ accuracy: 85,
358
+ maxPP: 3,
359
+ priority: 0,
360
+ effects: [
361
+ { kind: "damage", basePower: 40 },
362
+ { kind: "modify_stats", offenseDelta: -15 } // Pierdes dinero
363
+ ]
364
+ },
365
+ {
366
+ id: "tuit_elon", // thunderbolt
367
+ name: "Tuit de Elon",
368
+ typeId: "cryptobro",
369
+ accuracy: 100,
370
+ maxPP: 8,
371
+ priority: 0,
372
+ effects: [
373
+ { kind: "damage", basePower: 30 }
374
+ ]
375
+ },
376
+ {
377
+ id: "spam_whatsapp", // thunder_wave
378
+ name: "Spam de WhatsApp",
379
+ typeId: "cryptobro",
380
+ accuracy: 100,
381
+ maxPP: 10,
382
+ priority: 0,
383
+ effects: [
384
+ { kind: "damage", basePower: 20 },
385
+ { kind: "apply_status", statusId: "ansiedad_financiera" }
386
+ ]
387
+ },
388
+ {
389
+ id: "vpn_activada", // static_field
390
+ name: "Activar VPN",
391
+ typeId: "cryptobro",
392
+ accuracy: 100,
393
+ maxPP: 5,
394
+ priority: 0,
395
+ effects: [
396
+ { kind: "heal", target: "self", amount: 22 },
397
+ { kind: "clear_status", target: "self", kinds: ["soft"] }
398
+ ]
399
+ },
400
+ {
401
+ id: "venta_humo", // wild_charge (Basic 15)
402
+ name: "Venta de Humo",
403
+ typeId: "cryptobro",
404
+ accuracy: 100,
405
+ maxPP: 10,
406
+ priority: 0,
407
+ effects: [
408
+ { kind: "damage", basePower: 15 }
409
+ ]
410
+ },
411
+ {
412
+ id: "to_the_moon", // healing_spark
413
+ name: "To The Moon 🚀",
414
+ typeId: "cryptobro",
415
+ accuracy: 100,
416
+ maxPP: 8,
417
+ priority: 0,
418
+ effects: [
419
+ { kind: "heal", target: "self", amount: 18 }
420
+ ]
421
+ }
422
+ ];
@@ -0,0 +1,2 @@
1
+ import type { StatusDefinition } from "../../core";
2
+ export declare const TRIBE_STATUSES: StatusDefinition[];
@@ -0,0 +1,81 @@
1
+ export const TRIBE_STATUSES = [
2
+ // CANALLITA (Fuego) – Quemadura -> "Resaca"
3
+ {
4
+ id: "resaca",
5
+ name: "Resaca",
6
+ kind: "soft",
7
+ minDurationTurns: 3,
8
+ maxDurationTurns: 5,
9
+ effectsPerStack: [
10
+ {
11
+ kind: "damage",
12
+ flatAmount: 6, // El hígado duele
13
+ },
14
+ ],
15
+ },
16
+ // CAYETANO (Agua) – Escaldado -> "Cancelado" (en Twitter)
17
+ {
18
+ id: "cancelado",
19
+ name: "Cancelado",
20
+ kind: "soft",
21
+ minDurationTurns: 3,
22
+ maxDurationTurns: 5,
23
+ effectsPerStack: [
24
+ {
25
+ kind: "damage",
26
+ flatAmount: 5, // Daño a la reputación
27
+ },
28
+ ],
29
+ },
30
+ // PERROFLAUTA (Planta) – Enredado -> "Sin Cobertura"
31
+ {
32
+ id: "sin_cobertura",
33
+ name: "Sin Cobertura",
34
+ kind: "soft",
35
+ minDurationTurns: 3,
36
+ maxDurationTurns: 5,
37
+ effectsPerStack: [
38
+ {
39
+ kind: "damage",
40
+ flatAmount: 4, // La ansiedad de no conectarse
41
+ },
42
+ ],
43
+ },
44
+ // CUÑADO (Psíquico) – Bloqueo mental -> "Turra" (Te aburren)
45
+ {
46
+ id: "turra_maxima",
47
+ name: "Turra Máxima",
48
+ kind: "hard_cc", // Hard CC, te duermes del aburrimiento
49
+ minDurationTurns: 1,
50
+ maxDurationTurns: 2,
51
+ effectsPerStack: [],
52
+ },
53
+ // GYMBRO (Roca) – Petrificado -> "Agujetas"
54
+ {
55
+ id: "agujetas",
56
+ name: "Agujetas",
57
+ kind: "soft",
58
+ minDurationTurns: 2,
59
+ maxDurationTurns: 4,
60
+ effectsPerStack: [
61
+ {
62
+ kind: "damage",
63
+ flatAmount: 5, // No puedes moverte del dolor
64
+ },
65
+ ],
66
+ },
67
+ // CRYPTOBRO (Eléctrico) – Electrocutado -> "Ansiedad"
68
+ {
69
+ id: "ansiedad_financiera",
70
+ name: "Ansiedad",
71
+ kind: "soft",
72
+ minDurationTurns: 2,
73
+ maxDurationTurns: 4,
74
+ effectsPerStack: [
75
+ {
76
+ kind: "damage",
77
+ flatAmount: 5, // El mercado baja, tu salud también
78
+ },
79
+ ],
80
+ },
81
+ ];
@@ -0,0 +1,13 @@
1
+ import type { TypeDefinition, TypeEffectivenessMatrix, TypeId } from "../../core";
2
+ export declare const TRIBE_TYPE_IDS: {
3
+ readonly canallita: "canallita";
4
+ readonly cayetano: "cayetano";
5
+ readonly perroflauta: "perroflauta";
6
+ readonly cryptobro: "cryptobro";
7
+ readonly cunado: "cunado";
8
+ readonly gymbro: "gymbro";
9
+ };
10
+ export type TribeTypeId = (typeof TRIBE_TYPE_IDS)[keyof typeof TRIBE_TYPE_IDS];
11
+ export declare const TRIBE_TYPES: TypeDefinition[];
12
+ export declare const TRIBE_TYPE_MATRIX: TypeEffectivenessMatrix;
13
+ export declare const getTribeTypeEffectiveness: (attackerTypeId: TypeId, defenderTypeId: TypeId) => number;
@@ -0,0 +1,98 @@
1
+ // Nuevos IDs semánticos
2
+ export const TRIBE_TYPE_IDS = {
3
+ canallita: "canallita", // Fuego (Daño/Frágil)
4
+ cayetano: "cayetano", // Agua (Tanque/Dinero)
5
+ perroflauta: "perroflauta", // Planta (Soporte/Hierbas)
6
+ cryptobro: "cryptobro", // Eléctrico (Rápido/Volátil)
7
+ cunado: "cunado", // Psíquico (Mental/Turra)
8
+ gymbro: "gymbro", // Roca (Duro/Físico)
9
+ };
10
+ export const TRIBE_TYPES = [
11
+ {
12
+ id: TRIBE_TYPE_IDS.canallita,
13
+ displayName: "Canallita", // El rey de la noche
14
+ color: "#EE8130", // Naranja cubata
15
+ },
16
+ {
17
+ id: TRIBE_TYPE_IDS.cayetano,
18
+ displayName: "Cayetano", // El rey del club de campo
19
+ color: "#25a8fa", // Azul camisa Oxford
20
+ },
21
+ {
22
+ id: TRIBE_TYPE_IDS.perroflauta,
23
+ displayName: "Perroflauta", // El rey del parque
24
+ color: "#7AC74C", // Verde sospechoso
25
+ },
26
+ {
27
+ id: TRIBE_TYPE_IDS.cryptobro,
28
+ displayName: "CryptoBro", // To the moon
29
+ color: "#F7D02C", // Dorado Bitcoin
30
+ },
31
+ {
32
+ id: TRIBE_TYPE_IDS.cunado,
33
+ displayName: "Cuñado", // Sabelotodo
34
+ color: "#e54fff", // Púrpura místico
35
+ },
36
+ {
37
+ id: TRIBE_TYPE_IDS.gymbro,
38
+ displayName: "GymBro", // Pura fibra
39
+ color: "#787878", // Gris mancuerna
40
+ },
41
+ ];
42
+ // Matriz de efectividad (Mismo balance que Pokémon)
43
+ export const TRIBE_TYPE_MATRIX = {
44
+ [TRIBE_TYPE_IDS.cryptobro]: {
45
+ [TRIBE_TYPE_IDS.cryptobro]: 1,
46
+ [TRIBE_TYPE_IDS.canallita]: 1,
47
+ [TRIBE_TYPE_IDS.cayetano]: 1,
48
+ [TRIBE_TYPE_IDS.perroflauta]: 1,
49
+ [TRIBE_TYPE_IDS.cunado]: 1,
50
+ [TRIBE_TYPE_IDS.gymbro]: 1,
51
+ },
52
+ [TRIBE_TYPE_IDS.canallita]: {
53
+ [TRIBE_TYPE_IDS.canallita]: 0.9,
54
+ [TRIBE_TYPE_IDS.cayetano]: 0.9,
55
+ [TRIBE_TYPE_IDS.perroflauta]: 1.1,
56
+ [TRIBE_TYPE_IDS.cryptobro]: 1,
57
+ [TRIBE_TYPE_IDS.cunado]: 1,
58
+ [TRIBE_TYPE_IDS.gymbro]: 1,
59
+ },
60
+ [TRIBE_TYPE_IDS.cayetano]: {
61
+ [TRIBE_TYPE_IDS.canallita]: 1.1,
62
+ [TRIBE_TYPE_IDS.cayetano]: 0.9,
63
+ [TRIBE_TYPE_IDS.perroflauta]: 0.9,
64
+ [TRIBE_TYPE_IDS.cryptobro]: 1,
65
+ [TRIBE_TYPE_IDS.cunado]: 1,
66
+ [TRIBE_TYPE_IDS.gymbro]: 1,
67
+ },
68
+ [TRIBE_TYPE_IDS.perroflauta]: {
69
+ [TRIBE_TYPE_IDS.canallita]: 0.9,
70
+ [TRIBE_TYPE_IDS.cayetano]: 1.1,
71
+ [TRIBE_TYPE_IDS.perroflauta]: 0.9,
72
+ [TRIBE_TYPE_IDS.cryptobro]: 1,
73
+ [TRIBE_TYPE_IDS.cunado]: 1,
74
+ [TRIBE_TYPE_IDS.gymbro]: 1,
75
+ },
76
+ [TRIBE_TYPE_IDS.cunado]: {
77
+ [TRIBE_TYPE_IDS.canallita]: 1,
78
+ [TRIBE_TYPE_IDS.cayetano]: 1.1,
79
+ [TRIBE_TYPE_IDS.perroflauta]: 0.9,
80
+ [TRIBE_TYPE_IDS.cryptobro]: 0.9,
81
+ [TRIBE_TYPE_IDS.cunado]: 1,
82
+ [TRIBE_TYPE_IDS.gymbro]: 1,
83
+ },
84
+ [TRIBE_TYPE_IDS.gymbro]: {
85
+ [TRIBE_TYPE_IDS.canallita]: 1,
86
+ [TRIBE_TYPE_IDS.cayetano]: 1.1,
87
+ [TRIBE_TYPE_IDS.perroflauta]: 0.9,
88
+ [TRIBE_TYPE_IDS.cryptobro]: 0.9,
89
+ [TRIBE_TYPE_IDS.cunado]: 1,
90
+ [TRIBE_TYPE_IDS.gymbro]: 1,
91
+ },
92
+ };
93
+ export const getTribeTypeEffectiveness = (attackerTypeId, defenderTypeId) => {
94
+ const row = TRIBE_TYPE_MATRIX[attackerTypeId];
95
+ if (!row)
96
+ return 1;
97
+ return row[defenderTypeId] ?? 1;
98
+ };
@@ -1,2 +1,3 @@
1
1
  export * from "./pokemon/index.js";
2
+ export * from "./cliches/index.js";
2
3
  export * from "./CombatSkin.js";
@@ -1,2 +1,3 @@
1
1
  export * from "./pokemon/index.js";
2
+ export * from "./cliches/index.js";
2
3
  export * from "./CombatSkin.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pokemon-io-core",
3
- "version": "0.0.62",
3
+ "version": "0.0.63",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",