pokemon-io-core 0.0.68 → 0.0.70

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.
@@ -1,8 +1,10 @@
1
1
  export interface PlayerLoadoutView {
2
- fighterId: string | null;
3
- moveIds: string[];
2
+ fighterIds: string[];
3
+ movesByFighterId: Record<string, string[]>;
4
4
  itemIds: string[];
5
5
  amuletId: string | null;
6
+ fighterId: string | null;
7
+ moveIds: string[];
6
8
  }
7
9
  export interface PlayerView {
8
10
  id: string;
@@ -14,6 +14,10 @@ export interface ClientToServerEvents {
14
14
  "room:leave": (payload: {
15
15
  roomId: string;
16
16
  }) => void;
17
+ "room:reconnect": (payload: {
18
+ roomId: string;
19
+ oldPlayerId: string;
20
+ }) => void;
17
21
  "room:setLoadout": (payload: {
18
22
  roomId: string;
19
23
  fighterId: string;
@@ -9,7 +9,8 @@ export interface UseItemAction {
9
9
  }
10
10
  export interface SwitchFighterAction {
11
11
  kind: "switch_fighter";
12
- targetIndex: number;
12
+ newIndex: number;
13
+ forced?: boolean;
13
14
  }
14
15
  export interface NoAction {
15
16
  kind: "no_action";
@@ -16,13 +16,16 @@ export interface BattleRuntime {
16
16
  statusesById: Record<StatusId, StatusDefinition>;
17
17
  typeEffectiveness: TypeEffectivenessMatrix;
18
18
  }
19
- export interface PlayerBattleConfig {
19
+ export interface PlayerFighterConfig {
20
20
  fighter: FighterDefinition;
21
21
  maxHp: number;
22
22
  moves: MoveDefinition[];
23
23
  items: ItemDefinition[];
24
24
  amulet: AmuletDefinition | null;
25
25
  }
26
+ export interface PlayerBattleConfig {
27
+ team: PlayerFighterConfig[];
28
+ }
26
29
  export interface BattleConfig {
27
30
  types: TypeDefinition[];
28
31
  typeEffectiveness: TypeEffectivenessMatrix;
@@ -90,10 +90,10 @@ const recomputeEffectiveStatsForFighter = (state, fighter) => {
90
90
  };
91
91
  };
92
92
  const createPlayerBattleState = (cfg) => {
93
- const fighter = createBattleFighter(cfg);
93
+ const fighterTeam = cfg.team.map((f) => createBattleFighter(f));
94
94
  return {
95
- fighterTeam: [fighter],
96
- activeIndex: 0,
95
+ fighterTeam,
96
+ activeIndex: 0, // siempre el primero al empezar
97
97
  };
98
98
  };
99
99
  export const createInitialBattleState = (config) => {
@@ -762,6 +762,35 @@ const applyEndOfTurnStatuses = (state) => {
762
762
  };
763
763
  return { state: newState, events };
764
764
  };
765
+ const applySwitchAction = (state, playerKey, newIndex, events) => {
766
+ const playerState = state[playerKey];
767
+ const team = playerState.fighterTeam;
768
+ // Validaciones básicas
769
+ if (newIndex < 0 || newIndex >= team.length)
770
+ return state;
771
+ if (!team[newIndex]?.isAlive)
772
+ return state;
773
+ if (newIndex === playerState.activeIndex)
774
+ return state;
775
+ const oldIndex = playerState.activeIndex;
776
+ const oldFighter = team[oldIndex];
777
+ const newFighter = team[newIndex];
778
+ const newPlayerState = {
779
+ ...playerState,
780
+ activeIndex: newIndex,
781
+ };
782
+ const newState = {
783
+ ...state,
784
+ [playerKey]: newPlayerState,
785
+ };
786
+ events.push({
787
+ ...createBaseEvent(state.turnNumber, "fighter_switched", `${oldFighter.fighterId} se retira. ¡Adelante ${newFighter.fighterId}!`),
788
+ player: playerKey,
789
+ oldFighterId: oldFighter.fighterId,
790
+ newFighterId: newFighter.fighterId,
791
+ });
792
+ return newState;
793
+ };
765
794
  // ------------------------------------------------------
766
795
  // Bucle principal de turno
767
796
  // ------------------------------------------------------
@@ -797,6 +826,7 @@ export const resolveTurn = (state, actions) => {
797
826
  ...getMovePriorityAndSpeed(runtimeState, "player2", actions.player2),
798
827
  },
799
828
  ];
829
+ // Orden clásico por prioridad + velocidad
800
830
  entries.sort((a, b) => {
801
831
  if (b.priority !== a.priority) {
802
832
  return b.priority - a.priority;
@@ -813,7 +843,29 @@ export const resolveTurn = (state, actions) => {
813
843
  priority: e.priority,
814
844
  speed: e.speed,
815
845
  })));
816
- for (const entry of entries) {
846
+ // 🔁 1) FASE DE CAMBIOS (switch_fighter) – prioridad absoluta
847
+ const switchEntries = entries.filter((e) => e.action.kind === "switch_fighter");
848
+ for (const entry of switchEntries) {
849
+ const { playerKey, action } = entry;
850
+ if (action.kind !== "switch_fighter")
851
+ continue;
852
+ const { self } = getOpponentAndSelf(currentState, playerKey);
853
+ // Si el activo ya está muerto, no tiene sentido cambiar (o el combate ya está decidido).
854
+ if (!self.isAlive || self.currentHp <= 0)
855
+ continue;
856
+ if (hasHardCc(currentState, self)) {
857
+ // No puede cambiar tampoco si está bajo hard CC
858
+ events.push({
859
+ ...createBaseEvent(currentState.turnNumber, "action_skipped_hard_cc", `${self.fighterId} no puede actuar por control total`),
860
+ actorId: self.fighterId,
861
+ });
862
+ continue;
863
+ }
864
+ currentState = applySwitchAction(currentState, playerKey, action.newIndex, events);
865
+ }
866
+ // 🔁 2) FASE DE ACCIONES (movimientos / objetos)
867
+ const actionEntries = entries.filter((e) => e.action.kind !== "switch_fighter");
868
+ for (const entry of actionEntries) {
817
869
  const { playerKey, action } = entry;
818
870
  if (action.kind === "no_action")
819
871
  continue;
@@ -838,7 +890,7 @@ export const resolveTurn = (state, actions) => {
838
890
  events.push(...result.events);
839
891
  }
840
892
  else {
841
- // switch_fighter u otros no implementados aún
893
+ // Cualquier otro tipo de acción futura se ignora de momento
842
894
  continue;
843
895
  }
844
896
  const winnerAfterAction = checkWinner(currentState);
@@ -857,6 +909,7 @@ export const resolveTurn = (state, actions) => {
857
909
  };
858
910
  }
859
911
  }
912
+ // 🔁 3) Estados de final de turno
860
913
  const statusResult = applyEndOfTurnStatuses(currentState);
861
914
  currentState = statusResult.state;
862
915
  events.push(...statusResult.events);
@@ -1,5 +1,5 @@
1
1
  import type { FighterId, MoveId, ItemId, StatusId } from "./ids.js";
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";
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" | "fighter_switched" | "turn_end" | "battle_end";
3
3
  export interface BaseBattleEvent {
4
4
  id: string;
5
5
  turnNumber: number;
@@ -60,8 +60,14 @@ export interface FighterFaintedEvent extends BaseBattleEvent {
60
60
  kind: "fighter_fainted";
61
61
  fighterId: FighterId;
62
62
  }
63
+ export interface FighterSwitchedEvent extends BaseBattleEvent {
64
+ kind: "fighter_switched";
65
+ player: "player1" | "player2";
66
+ oldFighterId: FighterId;
67
+ newFighterId: FighterId;
68
+ }
63
69
  export interface BattleEndEvent extends BaseBattleEvent {
64
70
  kind: "battle_end";
65
71
  winner: "player1" | "player2" | "draw";
66
72
  }
67
- export type BattleEvent = ActionDeclaredEvent | MoveMissEvent | MoveHitEvent | ItemUsedEvent | DamageEvent | HealEvent | StatusAppliedEvent | StatusExpiredEvent | FighterFaintedEvent | BattleEndEvent | BaseBattleEvent;
73
+ export type BattleEvent = ActionDeclaredEvent | MoveMissEvent | MoveHitEvent | ItemUsedEvent | DamageEvent | HealEvent | StatusAppliedEvent | StatusExpiredEvent | FighterFaintedEvent | FighterSwitchedEvent | BattleEndEvent | BaseBattleEvent;
package/dist/index.d.ts CHANGED
@@ -3,4 +3,3 @@ export * from "./api/battle.js";
3
3
  export * from "./api/room.js";
4
4
  export * from "./api/socketTypes.js";
5
5
  export * from "./skins/CombatSkin.js";
6
- export * from "./engine/pokemonBattleService.js";
package/dist/index.js CHANGED
@@ -3,4 +3,3 @@ export * from "./api/battle.js";
3
3
  export * from "./api/room.js";
4
4
  export * from "./api/socketTypes.js";
5
5
  export * from "./skins/CombatSkin.js";
6
- export * from "./engine/pokemonBattleService.js";
@@ -1,8 +1,8 @@
1
- // pokemon-io-core/src/skins/pokemon/pokemonSkin.ts
1
+ // pokemon-io-core/src/skins/tribes/clicheSkin.ts
2
2
  import { POKEMON_ITEMS } from "../pokemon/index.js";
3
3
  import { TRIBE_FIGHTERS, TRIBE_MOVES, TRIBE_STATUSES, TRIBE_TYPES, TRIBE_TYPE_MATRIX, } from "./index.js";
4
4
  // --- helpers ---
5
- const findPokemonById = (id) => {
5
+ const findTribeFighterById = (id) => {
6
6
  const lower = id.toLowerCase();
7
7
  return TRIBE_FIGHTERS.find((f) => f.id.toLowerCase() === lower) ?? null;
8
8
  };
@@ -71,19 +71,22 @@ export class TribeSkin {
71
71
  if (!loadout.fighterId) {
72
72
  throw new Error("fighterId is required in FighterLoadout");
73
73
  }
74
- console.log("buildPlayerConfig", loadout.fighterId);
75
- const fighter = findPokemonById(loadout.fighterId);
74
+ const fighter = findTribeFighterById(loadout.fighterId);
76
75
  if (!fighter) {
77
- throw new Error(`Unknown fighterId for Pokemon skin: ${loadout.fighterId}`);
76
+ throw new Error(`Unknown fighterId for tribe skin: ${loadout.fighterId}`);
78
77
  }
79
78
  const moves = buildMovesFromLoadout(fighter, loadout);
80
79
  const items = buildItemsFromLoadout(loadout);
81
80
  return {
82
- fighter,
83
- maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
84
- moves,
85
- items,
86
- amulet: null,
81
+ team: [
82
+ {
83
+ fighter,
84
+ maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
85
+ moves,
86
+ items,
87
+ amulet: null,
88
+ },
89
+ ],
87
90
  };
88
91
  }
89
92
  }
@@ -70,7 +70,6 @@ export class PokemonSkin {
70
70
  if (!loadout.fighterId) {
71
71
  throw new Error("fighterId is required in FighterLoadout");
72
72
  }
73
- console.log("buildPlayerConfig", loadout.fighterId);
74
73
  const fighter = findPokemonById(loadout.fighterId);
75
74
  if (!fighter) {
76
75
  throw new Error(`Unknown fighterId for Pokemon skin: ${loadout.fighterId}`);
@@ -78,11 +77,15 @@ export class PokemonSkin {
78
77
  const moves = buildMovesFromLoadout(fighter, loadout);
79
78
  const items = buildItemsFromLoadout(loadout);
80
79
  return {
81
- fighter,
82
- maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
83
- moves,
84
- items,
85
- amulet: null,
80
+ team: [
81
+ {
82
+ fighter,
83
+ maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
84
+ moves,
85
+ items,
86
+ amulet: null,
87
+ },
88
+ ],
86
89
  };
87
90
  }
88
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pokemon-io-core",
3
- "version": "0.0.68",
3
+ "version": "0.0.70",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",