pokemon-io-core 0.0.54 → 0.0.55
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.
- package/dist/api/battle.d.ts +26 -0
- package/dist/api/battle.js +2 -0
- package/dist/api/room.d.ts +21 -0
- package/dist/api/room.js +2 -0
- package/dist/api/socketTypes.d.ts +46 -0
- package/dist/api/socketTypes.js +1 -0
- package/dist/core/actions.d.ts +21 -0
- package/dist/core/actions.js +1 -0
- package/dist/core/amulets.d.ts +18 -0
- package/dist/core/amulets.js +1 -0
- package/dist/core/battleState.d.ts +39 -0
- package/dist/core/battleState.js +1 -0
- package/dist/core/engine.d.ts +45 -0
- package/dist/core/engine.js +869 -0
- package/dist/core/events.d.ts +67 -0
- package/dist/core/events.js +1 -0
- package/dist/core/fighters.d.ts +13 -0
- package/dist/core/fighters.js +1 -0
- package/dist/core/ids.d.ts +6 -0
- package/dist/core/ids.js +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.js +11 -0
- package/dist/core/items.d.ts +12 -0
- package/dist/core/items.js +1 -0
- package/dist/core/moves.d.ts +73 -0
- package/dist/core/moves.js +2 -0
- package/dist/core/status.d.ts +11 -0
- package/dist/core/status.js +1 -0
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.js +1 -0
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.js +1 -0
- package/dist/engine/pokemonBattleService.d.ts +6 -0
- package/dist/engine/pokemonBattleService.js +32 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/skins/CombatSkin.d.ts +18 -0
- package/dist/skins/CombatSkin.js +1 -0
- package/dist/skins/index.d.ts +2 -0
- package/dist/skins/index.js +2 -0
- package/dist/skins/pokemon/fighters.d.ts +2 -0
- package/dist/skins/pokemon/fighters.js +174 -0
- package/dist/skins/pokemon/index.d.ts +6 -0
- package/dist/skins/pokemon/index.js +6 -0
- package/dist/skins/pokemon/items.d.ts +2 -0
- package/dist/skins/pokemon/items.js +143 -0
- package/dist/skins/pokemon/moves.d.ts +2 -0
- package/dist/skins/pokemon/moves.js +459 -0
- package/dist/skins/pokemon/pokemonSkin.d.ts +13 -0
- package/dist/skins/pokemon/pokemonSkin.js +91 -0
- package/dist/skins/pokemon/statuses.d.ts +2 -0
- package/dist/skins/pokemon/statuses.js +85 -0
- package/dist/skins/pokemon/types.d.ts +13 -0
- package/dist/skins/pokemon/types.js +97 -0
- package/package.json +7 -7
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { FighterId, MoveId, ItemId, StatusId } from "./ids";
|
|
2
|
+
export type BattleEventKind = "turn_start" | "action_declared" | "action_skipped_hard_cc" | "move_miss" | "move_hit" | "item_used" | "status_cleared" | "damage" | "heal" | "shield_applied" | "status_applied" | "status_refreshed" | "status_expired" | "fighter_fainted" | "turn_end" | "battle_end";
|
|
3
|
+
export interface BaseBattleEvent {
|
|
4
|
+
id: string;
|
|
5
|
+
turnNumber: number;
|
|
6
|
+
kind: BattleEventKind;
|
|
7
|
+
message: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ActionDeclaredEvent extends BaseBattleEvent {
|
|
11
|
+
kind: "action_declared";
|
|
12
|
+
actorId: FighterId;
|
|
13
|
+
}
|
|
14
|
+
export interface MoveMissEvent extends BaseBattleEvent {
|
|
15
|
+
kind: "move_miss";
|
|
16
|
+
actorId: FighterId;
|
|
17
|
+
moveId: MoveId;
|
|
18
|
+
targetId: FighterId;
|
|
19
|
+
}
|
|
20
|
+
export interface MoveHitEvent extends BaseBattleEvent {
|
|
21
|
+
kind: "move_hit";
|
|
22
|
+
actorId: FighterId;
|
|
23
|
+
moveId: MoveId;
|
|
24
|
+
targetId: FighterId;
|
|
25
|
+
isCritical: boolean;
|
|
26
|
+
effectiveness: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ItemUsedEvent extends BaseBattleEvent {
|
|
29
|
+
kind: "item_used";
|
|
30
|
+
actorId: FighterId;
|
|
31
|
+
itemId: ItemId;
|
|
32
|
+
targetId: FighterId;
|
|
33
|
+
}
|
|
34
|
+
export interface DamageEvent extends BaseBattleEvent {
|
|
35
|
+
kind: "damage";
|
|
36
|
+
actorId: FighterId;
|
|
37
|
+
targetId: FighterId;
|
|
38
|
+
amount: number;
|
|
39
|
+
isCritical: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface HealEvent extends BaseBattleEvent {
|
|
42
|
+
kind: "heal";
|
|
43
|
+
actorId: FighterId;
|
|
44
|
+
targetId: FighterId;
|
|
45
|
+
amount: number;
|
|
46
|
+
}
|
|
47
|
+
export interface StatusAppliedEvent extends BaseBattleEvent {
|
|
48
|
+
kind: "status_applied";
|
|
49
|
+
targetId: FighterId;
|
|
50
|
+
statusId: StatusId;
|
|
51
|
+
stacks: 1 | 2;
|
|
52
|
+
durationTurns: number;
|
|
53
|
+
}
|
|
54
|
+
export interface StatusExpiredEvent extends BaseBattleEvent {
|
|
55
|
+
kind: "status_expired";
|
|
56
|
+
targetId: FighterId;
|
|
57
|
+
statusId: StatusId;
|
|
58
|
+
}
|
|
59
|
+
export interface FighterFaintedEvent extends BaseBattleEvent {
|
|
60
|
+
kind: "fighter_fainted";
|
|
61
|
+
fighterId: FighterId;
|
|
62
|
+
}
|
|
63
|
+
export interface BattleEndEvent extends BaseBattleEvent {
|
|
64
|
+
kind: "battle_end";
|
|
65
|
+
winner: "player1" | "player2" | "draw";
|
|
66
|
+
}
|
|
67
|
+
export type BattleEvent = ActionDeclaredEvent | MoveMissEvent | MoveHitEvent | ItemUsedEvent | DamageEvent | HealEvent | StatusAppliedEvent | StatusExpiredEvent | FighterFaintedEvent | BattleEndEvent | BaseBattleEvent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FighterId, TypeId, MoveId, ItemId, AmuletId } from "./ids";
|
|
2
|
+
import type { FighterStats } from "./types";
|
|
3
|
+
export interface FighterDefinition {
|
|
4
|
+
id: FighterId;
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
img?: string;
|
|
8
|
+
classId: TypeId;
|
|
9
|
+
baseStats: FighterStats;
|
|
10
|
+
recommendedMoves?: MoveId[];
|
|
11
|
+
recommendedItems?: ItemId[];
|
|
12
|
+
recommendedAmuletId?: AmuletId;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/core/ids.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./actions.js";
|
|
2
|
+
export * from "./amulets.js";
|
|
3
|
+
export * from "./battleState.js";
|
|
4
|
+
export * from "./engine.js";
|
|
5
|
+
export * from "./events.js";
|
|
6
|
+
export * from "./fighters.js";
|
|
7
|
+
export * from "./ids.js";
|
|
8
|
+
export * from "./items.js";
|
|
9
|
+
export * from "./moves.js";
|
|
10
|
+
export * from "./status.js";
|
|
11
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./actions.js";
|
|
2
|
+
export * from "./amulets.js";
|
|
3
|
+
export * from "./battleState.js";
|
|
4
|
+
export * from "./engine.js";
|
|
5
|
+
export * from "./events.js";
|
|
6
|
+
export * from "./fighters.js";
|
|
7
|
+
export * from "./ids.js";
|
|
8
|
+
export * from "./items.js";
|
|
9
|
+
export * from "./moves.js";
|
|
10
|
+
export * from "./status.js";
|
|
11
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ItemId } from "./ids";
|
|
2
|
+
import type { EffectDefinition, TargetKind } from "./moves";
|
|
3
|
+
export type ItemCategory = "damage" | "heal_shield" | "status_buff";
|
|
4
|
+
export interface ItemDefinition {
|
|
5
|
+
id: ItemId;
|
|
6
|
+
name: string;
|
|
7
|
+
category: ItemCategory;
|
|
8
|
+
target: TargetKind;
|
|
9
|
+
maxUses: number;
|
|
10
|
+
image: string;
|
|
11
|
+
effects: EffectDefinition[];
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { MoveId, StatusId, TypeId } from "./ids";
|
|
2
|
+
export type EffectTarget = "self" | "enemy";
|
|
3
|
+
export type EffectKind = "damage" | "heal" | "shield" | "modify_stats" | "apply_status" | "clear_status" | "modify_hit_chance" | "modify_crit_chance" | "modify_priority" | "modify_effective_speed";
|
|
4
|
+
export type TargetKind = EffectTarget;
|
|
5
|
+
interface BaseEffect {
|
|
6
|
+
target?: EffectTarget;
|
|
7
|
+
}
|
|
8
|
+
export interface DamageEffect extends BaseEffect {
|
|
9
|
+
kind: "damage";
|
|
10
|
+
/**
|
|
11
|
+
* Daño “de fórmula” (stats + tipo + crit…).
|
|
12
|
+
* Si no se define, NO se llama a computeDamage.
|
|
13
|
+
*/
|
|
14
|
+
basePower?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Daño plano adicional.
|
|
17
|
+
* Se suma al daño de fórmula o se usa solo si no hay basePower.
|
|
18
|
+
*/
|
|
19
|
+
flatAmount?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface HealEffect extends BaseEffect {
|
|
22
|
+
kind: "heal";
|
|
23
|
+
amount: number;
|
|
24
|
+
}
|
|
25
|
+
export interface ShieldEffect extends BaseEffect {
|
|
26
|
+
kind: "shield";
|
|
27
|
+
amount: number;
|
|
28
|
+
durationTurns: number;
|
|
29
|
+
}
|
|
30
|
+
export interface ModifyStatsEffect extends BaseEffect {
|
|
31
|
+
kind: "modify_stats";
|
|
32
|
+
offenseDelta?: number;
|
|
33
|
+
defenseDelta?: number;
|
|
34
|
+
speedDelta?: number;
|
|
35
|
+
critDelta?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ApplyStatusEffect extends BaseEffect {
|
|
38
|
+
kind: "apply_status";
|
|
39
|
+
statusId: StatusId;
|
|
40
|
+
}
|
|
41
|
+
export interface ClearStatusEffect extends BaseEffect {
|
|
42
|
+
kind: "clear_status";
|
|
43
|
+
statusIds?: StatusId[];
|
|
44
|
+
kinds?: ("hard_cc" | "soft")[];
|
|
45
|
+
clearAll?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface ModifyHitChanceEffect extends BaseEffect {
|
|
48
|
+
kind: "modify_hit_chance";
|
|
49
|
+
delta: number;
|
|
50
|
+
}
|
|
51
|
+
export interface ModifyCritChanceEffect extends BaseEffect {
|
|
52
|
+
kind: "modify_crit_chance";
|
|
53
|
+
delta: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ModifyPriorityEffect extends BaseEffect {
|
|
56
|
+
kind: "modify_priority";
|
|
57
|
+
delta: number;
|
|
58
|
+
}
|
|
59
|
+
export interface ModifyEffectiveSpeedEffect extends BaseEffect {
|
|
60
|
+
kind: "modify_effective_speed";
|
|
61
|
+
multiplier: number;
|
|
62
|
+
}
|
|
63
|
+
export type EffectDefinition = DamageEffect | HealEffect | ShieldEffect | ModifyStatsEffect | ApplyStatusEffect | ClearStatusEffect | ModifyHitChanceEffect | ModifyCritChanceEffect | ModifyPriorityEffect | ModifyEffectiveSpeedEffect;
|
|
64
|
+
export interface MoveDefinition {
|
|
65
|
+
id: MoveId;
|
|
66
|
+
name: string;
|
|
67
|
+
typeId: TypeId;
|
|
68
|
+
accuracy?: number;
|
|
69
|
+
maxPP: number;
|
|
70
|
+
priority?: number;
|
|
71
|
+
effects: EffectDefinition[];
|
|
72
|
+
}
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { StatusId } from "./ids";
|
|
2
|
+
import type { EffectDefinition } from "./moves";
|
|
3
|
+
export type StatusKind = "hard_cc" | "soft";
|
|
4
|
+
export interface StatusDefinition {
|
|
5
|
+
id: StatusId;
|
|
6
|
+
name: string;
|
|
7
|
+
kind: StatusKind;
|
|
8
|
+
minDurationTurns: number;
|
|
9
|
+
maxDurationTurns: number;
|
|
10
|
+
effectsPerStack: EffectDefinition[];
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TypeId } from "./ids";
|
|
2
|
+
export type Effectiveness = 0 | 0.75 | 1 | 1.25;
|
|
3
|
+
export interface TypeDefinition {
|
|
4
|
+
id: TypeId;
|
|
5
|
+
displayName: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
export type TypeEffectivenessMatrix = Record<TypeId, Record<TypeId, Effectiveness>>;
|
|
9
|
+
export interface FighterStats {
|
|
10
|
+
offense: number;
|
|
11
|
+
defense: number;
|
|
12
|
+
speed: number;
|
|
13
|
+
crit: number;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './pokemonBattleService.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './pokemonBattleService.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BattleActions, BattleState } from "../core";
|
|
2
|
+
export declare const createPokemonBattle: (fighter1Id: string, fighter2Id: string) => BattleState;
|
|
3
|
+
export declare const runPokemonTurn: (state: BattleState, actions: BattleActions) => {
|
|
4
|
+
newState: BattleState;
|
|
5
|
+
events: import("..").BattleEvent[];
|
|
6
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { POKEMON_FIGHTERS, POKEMON_MOVES, POKEMON_TYPE_MATRIX, POKEMON_TYPES } from "../skins/pokemon";
|
|
2
|
+
import { createInitialBattleState, resolveTurn } from "../core/engine";
|
|
3
|
+
const findPokemon = (id) => POKEMON_FIGHTERS.find((p) => p.id === id);
|
|
4
|
+
const findMove = (id) => POKEMON_MOVES.find((m) => m.id === id);
|
|
5
|
+
export const createPokemonBattle = (fighter1Id, fighter2Id) => {
|
|
6
|
+
const f1 = findPokemon(fighter1Id);
|
|
7
|
+
const f2 = findPokemon(fighter2Id);
|
|
8
|
+
const config = {
|
|
9
|
+
types: POKEMON_TYPES,
|
|
10
|
+
typeEffectiveness: POKEMON_TYPE_MATRIX,
|
|
11
|
+
moves: POKEMON_MOVES,
|
|
12
|
+
items: [], // MVP: sin items
|
|
13
|
+
amulets: [],
|
|
14
|
+
statuses: [],
|
|
15
|
+
player1: {
|
|
16
|
+
fighter: f1,
|
|
17
|
+
maxHp: 100,
|
|
18
|
+
moves: POKEMON_MOVES.filter((m) => (f1.recommendedMoves ?? []).includes(m.id)),
|
|
19
|
+
items: [],
|
|
20
|
+
amulet: null
|
|
21
|
+
},
|
|
22
|
+
player2: {
|
|
23
|
+
fighter: f2,
|
|
24
|
+
maxHp: 100,
|
|
25
|
+
moves: POKEMON_MOVES.filter((m) => (f2.recommendedMoves ?? []).includes(m.id)),
|
|
26
|
+
items: [],
|
|
27
|
+
amulet: null
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return createInitialBattleState(config);
|
|
31
|
+
};
|
|
32
|
+
export const runPokemonTurn = (state, actions) => resolveTurn(state, actions);
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TypeDefinition, TypeEffectivenessMatrix, MoveDefinition, ItemDefinition, AmuletDefinition, StatusDefinition } from "../core";
|
|
2
|
+
import type { PlayerBattleConfig } from "../core/engine";
|
|
3
|
+
export interface FighterLoadout {
|
|
4
|
+
fighterId: string | null;
|
|
5
|
+
itemIds: string[];
|
|
6
|
+
amuletId: string | null;
|
|
7
|
+
moveIds: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface CombatSkin {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
getTypes(): TypeDefinition[];
|
|
12
|
+
getTypeEffectiveness(): TypeEffectivenessMatrix;
|
|
13
|
+
getMoves(): MoveDefinition[];
|
|
14
|
+
getItems(): ItemDefinition[];
|
|
15
|
+
getAmulets(): AmuletDefinition[];
|
|
16
|
+
getStatuses(): StatusDefinition[];
|
|
17
|
+
buildPlayerConfig(loadout: FighterLoadout): PlayerBattleConfig;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { POKEMON_TYPE_IDS } from "./types";
|
|
2
|
+
const makeStats = (offense, defense, speed, crit) => ({
|
|
3
|
+
offense,
|
|
4
|
+
defense,
|
|
5
|
+
speed,
|
|
6
|
+
crit,
|
|
7
|
+
});
|
|
8
|
+
export const POKEMON_FIGHTERS = [
|
|
9
|
+
// --- TIER 1: AZUL (Suma Atk + Def < 100) ---
|
|
10
|
+
{
|
|
11
|
+
id: "pikachu",
|
|
12
|
+
name: "Pikachu",
|
|
13
|
+
description: "Rápido y ágil, confía en su velocidad y golpes críticos.",
|
|
14
|
+
img: "pikachu",
|
|
15
|
+
classId: POKEMON_TYPE_IDS.electric,
|
|
16
|
+
baseStats: makeStats(55, 35, 90, 15), // Suma: 90
|
|
17
|
+
recommendedMoves: ["tackle", "thunder_shock"],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "cyndaquil",
|
|
21
|
+
name: "Cyndaquil",
|
|
22
|
+
description: "Pequeño volcán en erupción, ofensivo pero frágil.",
|
|
23
|
+
img: "cyndaquil",
|
|
24
|
+
classId: POKEMON_TYPE_IDS.fire,
|
|
25
|
+
baseStats: makeStats(52, 38, 75, 10), // Suma: 90
|
|
26
|
+
recommendedMoves: ["tackle", "ember"],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "squirtle",
|
|
30
|
+
name: "Squirtle",
|
|
31
|
+
description: "Caparazón resistente, ideal para resistir el daño inicial.",
|
|
32
|
+
img: "squirtle",
|
|
33
|
+
classId: POKEMON_TYPE_IDS.water,
|
|
34
|
+
baseStats: makeStats(40, 58, 45, 5), // Suma: 98
|
|
35
|
+
recommendedMoves: ["tackle", "water_gun"],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "chikorita",
|
|
39
|
+
name: "Chikorita",
|
|
40
|
+
description: "Soporte natural, destaca por su defensa y persistencia.",
|
|
41
|
+
img: "chikorita",
|
|
42
|
+
classId: POKEMON_TYPE_IDS.grass,
|
|
43
|
+
baseStats: makeStats(35, 60, 40, 5), // Suma: 95
|
|
44
|
+
recommendedMoves: ["tackle", "vine_whip"],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "psyduck",
|
|
48
|
+
name: "Psyduck",
|
|
49
|
+
description: "Dolor de cabeza constante que desata ráfagas psíquicas.",
|
|
50
|
+
img: "psyduck",
|
|
51
|
+
classId: POKEMON_TYPE_IDS.psychic,
|
|
52
|
+
baseStats: makeStats(50, 40, 60, 12), // Suma: 90
|
|
53
|
+
recommendedMoves: ["confusion"],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "geodude",
|
|
57
|
+
name: "Geodude",
|
|
58
|
+
description: "Roca sólida, muy duro de derribar pero extremadamente lento.",
|
|
59
|
+
img: "geodude",
|
|
60
|
+
classId: POKEMON_TYPE_IDS.rock,
|
|
61
|
+
baseStats: makeStats(40, 58, 20, 5), // Suma: 98
|
|
62
|
+
recommendedMoves: ["tackle", "rock_throw"],
|
|
63
|
+
},
|
|
64
|
+
// --- TIER 2: AMBER (Suma Atk + Def >= 100 y < 120) ---
|
|
65
|
+
{
|
|
66
|
+
id: "electabuzz",
|
|
67
|
+
name: "Electabuzz",
|
|
68
|
+
description: "Duelista eléctrico balanceado con gran capacidad ofensiva.",
|
|
69
|
+
img: "electabuzz",
|
|
70
|
+
classId: POKEMON_TYPE_IDS.electric,
|
|
71
|
+
baseStats: makeStats(65, 45, 95, 10), // Suma: 110
|
|
72
|
+
recommendedMoves: ["tackle", "thunder_shock"],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "magmortar",
|
|
76
|
+
name: "Magmortar",
|
|
77
|
+
description: "Artillería pesada de fuego, daño masivo a media distancia.",
|
|
78
|
+
img: "magmortar",
|
|
79
|
+
classId: POKEMON_TYPE_IDS.fire,
|
|
80
|
+
baseStats: makeStats(70, 45, 60, 8), // Suma: 115
|
|
81
|
+
recommendedMoves: ["tackle", "ember"],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "blastoise",
|
|
85
|
+
name: "Blastoise",
|
|
86
|
+
description: "Tanque con cañones hidráulicos, una muralla ofensiva.",
|
|
87
|
+
img: "blastoise",
|
|
88
|
+
classId: POKEMON_TYPE_IDS.water,
|
|
89
|
+
baseStats: makeStats(50, 65, 55, 5), // Suma: 115
|
|
90
|
+
recommendedMoves: ["tackle", "water_gun"],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "sceptile",
|
|
94
|
+
name: "Sceptile",
|
|
95
|
+
description: "Depredador de la selva, golpea letalmente desde las sombras.",
|
|
96
|
+
img: "sceptile",
|
|
97
|
+
classId: POKEMON_TYPE_IDS.grass,
|
|
98
|
+
baseStats: makeStats(68, 40, 100, 12), // Suma: 108
|
|
99
|
+
recommendedMoves: ["tackle", "vine_whip"],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "alakazam",
|
|
103
|
+
name: "Alakazam",
|
|
104
|
+
description: "Coeficiente intelectual de 5000, poder mental puro sin defensa física.",
|
|
105
|
+
img: "alakazam",
|
|
106
|
+
classId: POKEMON_TYPE_IDS.psychic,
|
|
107
|
+
baseStats: makeStats(75, 30, 95, 8), // Suma: 105
|
|
108
|
+
recommendedMoves: ["tackle", "confusion"],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "onix",
|
|
112
|
+
name: "Onix",
|
|
113
|
+
description: "Serpiente de roca gigante, defensa física casi impenetrable.",
|
|
114
|
+
img: "onix",
|
|
115
|
+
classId: POKEMON_TYPE_IDS.rock,
|
|
116
|
+
baseStats: makeStats(35, 80, 30, 5), // Suma: 115
|
|
117
|
+
recommendedMoves: ["tackle", "rock_slide"],
|
|
118
|
+
},
|
|
119
|
+
// --- TIER 3: RED (Suma Atk + Def >= 120) ---
|
|
120
|
+
{
|
|
121
|
+
id: "zapdos",
|
|
122
|
+
name: "Zapdos",
|
|
123
|
+
description: "Ave legendaria del trueno, domina los cielos con poder bruto.",
|
|
124
|
+
img: "zapdos",
|
|
125
|
+
classId: POKEMON_TYPE_IDS.electric,
|
|
126
|
+
baseStats: makeStats(70, 55, 85, 10), // Suma: 125
|
|
127
|
+
recommendedMoves: ["peck", "thunderbolt"],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "charizard",
|
|
131
|
+
name: "Charizard",
|
|
132
|
+
description: "Dragón de fuego icónico, arrasa con todo a su paso.",
|
|
133
|
+
img: "charizard",
|
|
134
|
+
classId: POKEMON_TYPE_IDS.fire,
|
|
135
|
+
baseStats: makeStats(75, 50, 85, 10), // Suma: 125
|
|
136
|
+
recommendedMoves: ["tackle", "ember"],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "kyogre",
|
|
140
|
+
name: "Kyogre",
|
|
141
|
+
description: "Leviatán mítico capaz de inundar el mundo entero.",
|
|
142
|
+
img: "kyogre",
|
|
143
|
+
classId: POKEMON_TYPE_IDS.water,
|
|
144
|
+
baseStats: makeStats(75, 65, 60, 8), // Suma: 140
|
|
145
|
+
recommendedMoves: ["tackle", "water_gun"],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "venusaur",
|
|
149
|
+
name: "Venusaur",
|
|
150
|
+
description: "Coloso de la jungla, combina toxicidad y fuerza bruta.",
|
|
151
|
+
img: "venusaur",
|
|
152
|
+
classId: POKEMON_TYPE_IDS.grass,
|
|
153
|
+
baseStats: makeStats(62, 63, 60, 6), // Suma: 125
|
|
154
|
+
recommendedMoves: ["tackle", "vine_whip"],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "mew",
|
|
158
|
+
name: "Mew",
|
|
159
|
+
description: "El ancestro de todos los Pokémon, versátil y místico.",
|
|
160
|
+
img: "mew",
|
|
161
|
+
classId: POKEMON_TYPE_IDS.psychic,
|
|
162
|
+
baseStats: makeStats(65, 65, 80, 10), // Suma: 130
|
|
163
|
+
recommendedMoves: ["tackle", "confusion"], // Corregido vine_whip
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "groudon",
|
|
167
|
+
name: "Groudon",
|
|
168
|
+
description: "Creador de continentes, poder terrestre devastador.",
|
|
169
|
+
img: "groudon",
|
|
170
|
+
classId: POKEMON_TYPE_IDS.rock,
|
|
171
|
+
baseStats: makeStats(80, 70, 50, 6), // Suma: 150
|
|
172
|
+
recommendedMoves: ["tackle", "rock_slide"], // Corregido vine_whip
|
|
173
|
+
},
|
|
174
|
+
];
|