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.
- package/dist/api/room.d.ts +4 -2
- package/dist/api/socketTypes.d.ts +4 -0
- package/dist/core/actions.d.ts +2 -1
- package/dist/core/engine.d.ts +4 -1
- package/dist/core/engine.js +58 -5
- package/dist/core/events.d.ts +8 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/skins/cliches/clicheSkin.js +13 -10
- package/dist/skins/pokemon/pokemonSkin.js +9 -6
- package/package.json +1 -1
package/dist/api/room.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export interface PlayerLoadoutView {
|
|
2
|
-
|
|
3
|
-
|
|
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;
|
package/dist/core/actions.d.ts
CHANGED
package/dist/core/engine.d.ts
CHANGED
|
@@ -16,13 +16,16 @@ export interface BattleRuntime {
|
|
|
16
16
|
statusesById: Record<StatusId, StatusDefinition>;
|
|
17
17
|
typeEffectiveness: TypeEffectivenessMatrix;
|
|
18
18
|
}
|
|
19
|
-
export interface
|
|
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;
|
package/dist/core/engine.js
CHANGED
|
@@ -90,10 +90,10 @@ const recomputeEffectiveStatsForFighter = (state, fighter) => {
|
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
92
|
const createPlayerBattleState = (cfg) => {
|
|
93
|
-
const
|
|
93
|
+
const fighterTeam = cfg.team.map((f) => createBattleFighter(f));
|
|
94
94
|
return {
|
|
95
|
-
fighterTeam
|
|
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
|
-
|
|
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
|
-
//
|
|
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);
|
package/dist/core/events.d.ts
CHANGED
|
@@ -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
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// pokemon-io-core/src/skins/
|
|
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
|
|
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
|
-
|
|
75
|
-
const fighter = findPokemonById(loadout.fighterId);
|
|
74
|
+
const fighter = findTribeFighterById(loadout.fighterId);
|
|
76
75
|
if (!fighter) {
|
|
77
|
-
throw new Error(`Unknown fighterId for
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
}
|