pokemon-io-core 0.0.70 → 0.0.72

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,10 +1,8 @@
1
1
  export interface PlayerLoadoutView {
2
- fighterIds: string[];
3
- movesByFighterId: Record<string, string[]>;
4
- itemIds: string[];
5
- amuletId: string | null;
6
2
  fighterId: string | null;
7
3
  moveIds: string[];
4
+ itemIds: string[];
5
+ amuletId: string | null;
8
6
  }
9
7
  export interface PlayerView {
10
8
  id: string;
@@ -42,6 +42,10 @@ export interface ClientToServerEvents {
42
42
  roomId: string;
43
43
  itemIndex: number;
44
44
  }) => void;
45
+ "battle:switchFighter": (payload: {
46
+ roomId: string;
47
+ newIndex: number;
48
+ }) => void;
45
49
  "battle:rematchSameLoadout": (payload: {
46
50
  roomId: string;
47
51
  }) => void;
@@ -1 +1,2 @@
1
+ // @pokemon-io/combat-core/src/api/socketTypests
1
2
  export {};
@@ -16,16 +16,13 @@ export interface BattleRuntime {
16
16
  statusesById: Record<StatusId, StatusDefinition>;
17
17
  typeEffectiveness: TypeEffectivenessMatrix;
18
18
  }
19
- export interface PlayerFighterConfig {
19
+ export interface PlayerBattleConfig {
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
- }
29
26
  export interface BattleConfig {
30
27
  types: TypeDefinition[];
31
28
  typeEffectiveness: TypeEffectivenessMatrix;
@@ -90,10 +90,10 @@ const recomputeEffectiveStatsForFighter = (state, fighter) => {
90
90
  };
91
91
  };
92
92
  const createPlayerBattleState = (cfg) => {
93
- const fighterTeam = cfg.team.map((f) => createBattleFighter(f));
93
+ const fighter = createBattleFighter(cfg);
94
94
  return {
95
- fighterTeam,
96
- activeIndex: 0, // siempre el primero al empezar
95
+ fighterTeam: [fighter],
96
+ activeIndex: 0,
97
97
  };
98
98
  };
99
99
  export const createInitialBattleState = (config) => {
@@ -480,6 +480,34 @@ const applyEffectsOnTarget = (state, actor, target, moveTypeId, isCritical, effe
480
480
  }
481
481
  return { actor: currentActor, target: currentTarget, events };
482
482
  };
483
+ const resolveSwitchFighter = (state, playerKey, action) => {
484
+ if (action.kind !== "switch_fighter") {
485
+ return { state, events: [] };
486
+ }
487
+ const events = [];
488
+ const player = playerKey === "player1" ? state.player1 : state.player2;
489
+ const from = getActiveFighter(player);
490
+ const to = player.fighterTeam[action.newIndex];
491
+ if (!to)
492
+ return { state, events };
493
+ if (!to.isAlive || to.currentHp <= 0)
494
+ return { state, events };
495
+ if (action.newIndex === player.activeIndex)
496
+ return { state, events };
497
+ const updatedPlayer = {
498
+ ...player,
499
+ activeIndex: action.newIndex,
500
+ };
501
+ const newState = playerKey === "player1"
502
+ ? { ...state, player1: updatedPlayer }
503
+ : { ...state, player2: updatedPlayer };
504
+ events.push({
505
+ ...createBaseEvent(state.turnNumber, "fighter_switched", `${from.fighterId} cambia a ${to.fighterId}`),
506
+ fromFighterId: from.fighterId,
507
+ toFighterId: to.fighterId,
508
+ });
509
+ return { state: newState, events };
510
+ };
483
511
  const getMovePriorityAndSpeed = (state, playerKey, action) => {
484
512
  const { self } = getOpponentAndSelf(state, playerKey);
485
513
  if (action.kind === "no_action") {
@@ -497,6 +525,12 @@ const getMovePriorityAndSpeed = (state, playerKey, action) => {
497
525
  speed: self.effectiveStats.speed,
498
526
  };
499
527
  }
528
+ if (action.kind === "switch_fighter") {
529
+ return {
530
+ priority: 10, // prioridad especial (ajústalo si quieres)
531
+ speed: self.effectiveStats.speed,
532
+ };
533
+ }
500
534
  // Items y switch: prioridad base 0 por ahora
501
535
  return {
502
536
  priority: 0,
@@ -762,35 +796,6 @@ const applyEndOfTurnStatuses = (state) => {
762
796
  };
763
797
  return { state: newState, events };
764
798
  };
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
- };
794
799
  // ------------------------------------------------------
795
800
  // Bucle principal de turno
796
801
  // ------------------------------------------------------
@@ -826,7 +831,6 @@ export const resolveTurn = (state, actions) => {
826
831
  ...getMovePriorityAndSpeed(runtimeState, "player2", actions.player2),
827
832
  },
828
833
  ];
829
- // Orden clásico por prioridad + velocidad
830
834
  entries.sort((a, b) => {
831
835
  if (b.priority !== a.priority) {
832
836
  return b.priority - a.priority;
@@ -843,29 +847,7 @@ export const resolveTurn = (state, actions) => {
843
847
  priority: e.priority,
844
848
  speed: e.speed,
845
849
  })));
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) {
850
+ for (const entry of entries) {
869
851
  const { playerKey, action } = entry;
870
852
  if (action.kind === "no_action")
871
853
  continue;
@@ -884,13 +866,18 @@ export const resolveTurn = (state, actions) => {
884
866
  currentState = result.state;
885
867
  events.push(...result.events);
886
868
  }
887
- else if (action.kind === "use_item") {
869
+ if (action.kind === "use_item") {
888
870
  const result = resolveItemUse(currentState, playerKey, action);
889
871
  currentState = result.state;
890
872
  events.push(...result.events);
891
873
  }
874
+ if (action.kind === "switch_fighter") {
875
+ const result = resolveSwitchFighter(currentState, playerKey, action);
876
+ currentState = result.state;
877
+ events.push(...result.events);
878
+ }
892
879
  else {
893
- // Cualquier otro tipo de acción futura se ignora de momento
880
+ // switch_fighter u otros no implementados aún
894
881
  continue;
895
882
  }
896
883
  const winnerAfterAction = checkWinner(currentState);
@@ -909,7 +896,6 @@ export const resolveTurn = (state, actions) => {
909
896
  };
910
897
  }
911
898
  }
912
- // 🔁 3) Estados de final de turno
913
899
  const statusResult = applyEndOfTurnStatuses(currentState);
914
900
  currentState = statusResult.state;
915
901
  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" | "fighter_switched" | "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" | "fighter_switched" | "shield_applied" | "status_applied" | "status_refreshed" | "status_expired" | "fighter_fainted" | "turn_end" | "battle_end";
3
3
  export interface BaseBattleEvent {
4
4
  id: string;
5
5
  turnNumber: number;
@@ -51,6 +51,11 @@ export interface StatusAppliedEvent extends BaseBattleEvent {
51
51
  stacks: 1 | 2;
52
52
  durationTurns: number;
53
53
  }
54
+ export interface FighterSwitchedEvent extends BaseBattleEvent {
55
+ kind: "fighter_switched";
56
+ fromFighterId: FighterId;
57
+ toFighterId: FighterId;
58
+ }
54
59
  export interface StatusExpiredEvent extends BaseBattleEvent {
55
60
  kind: "status_expired";
56
61
  targetId: FighterId;
@@ -60,12 +65,6 @@ export interface FighterFaintedEvent extends BaseBattleEvent {
60
65
  kind: "fighter_fainted";
61
66
  fighterId: FighterId;
62
67
  }
63
- export interface FighterSwitchedEvent extends BaseBattleEvent {
64
- kind: "fighter_switched";
65
- player: "player1" | "player2";
66
- oldFighterId: FighterId;
67
- newFighterId: FighterId;
68
- }
69
68
  export interface BattleEndEvent extends BaseBattleEvent {
70
69
  kind: "battle_end";
71
70
  winner: "player1" | "player2" | "draw";
@@ -1,8 +1,8 @@
1
- // pokemon-io-core/src/skins/tribes/clicheSkin.ts
1
+ // pokemon-io-core/src/skins/pokemon/pokemonSkin.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 findTribeFighterById = (id) => {
5
+ const findPokemonById = (id) => {
6
6
  const lower = id.toLowerCase();
7
7
  return TRIBE_FIGHTERS.find((f) => f.id.toLowerCase() === lower) ?? null;
8
8
  };
@@ -71,22 +71,19 @@ export class TribeSkin {
71
71
  if (!loadout.fighterId) {
72
72
  throw new Error("fighterId is required in FighterLoadout");
73
73
  }
74
- const fighter = findTribeFighterById(loadout.fighterId);
74
+ console.log("buildPlayerConfig", loadout.fighterId);
75
+ const fighter = findPokemonById(loadout.fighterId);
75
76
  if (!fighter) {
76
- throw new Error(`Unknown fighterId for tribe skin: ${loadout.fighterId}`);
77
+ throw new Error(`Unknown fighterId for Pokemon skin: ${loadout.fighterId}`);
77
78
  }
78
79
  const moves = buildMovesFromLoadout(fighter, loadout);
79
80
  const items = buildItemsFromLoadout(loadout);
80
81
  return {
81
- team: [
82
- {
83
- fighter,
84
- maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
85
- moves,
86
- items,
87
- amulet: null,
88
- },
89
- ],
82
+ fighter,
83
+ maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
84
+ moves,
85
+ items,
86
+ amulet: null,
90
87
  };
91
88
  }
92
89
  }
@@ -70,6 +70,7 @@ 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);
73
74
  const fighter = findPokemonById(loadout.fighterId);
74
75
  if (!fighter) {
75
76
  throw new Error(`Unknown fighterId for Pokemon skin: ${loadout.fighterId}`);
@@ -77,15 +78,11 @@ export class PokemonSkin {
77
78
  const moves = buildMovesFromLoadout(fighter, loadout);
78
79
  const items = buildItemsFromLoadout(loadout);
79
80
  return {
80
- team: [
81
- {
82
- fighter,
83
- maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
84
- moves,
85
- items,
86
- amulet: null,
87
- },
88
- ],
81
+ fighter,
82
+ maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
83
+ moves,
84
+ items,
85
+ amulet: null,
89
86
  };
90
87
  }
91
88
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pokemon-io-core",
3
- "version": "0.0.70",
3
+ "version": "0.0.72",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",