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.
- package/dist/api/room.d.ts +2 -4
- package/dist/api/socketTypes.d.ts +4 -0
- package/dist/api/socketTypes.js +1 -0
- package/dist/core/engine.d.ts +1 -4
- package/dist/core/engine.js +45 -59
- package/dist/core/events.d.ts +6 -7
- package/dist/skins/cliches/clicheSkin.js +10 -13
- package/dist/skins/pokemon/pokemonSkin.js +6 -9
- package/package.json +1 -1
package/dist/api/room.d.ts
CHANGED
|
@@ -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;
|
package/dist/api/socketTypes.js
CHANGED
package/dist/core/engine.d.ts
CHANGED
|
@@ -16,16 +16,13 @@ export interface BattleRuntime {
|
|
|
16
16
|
statusesById: Record<StatusId, StatusDefinition>;
|
|
17
17
|
typeEffectiveness: TypeEffectivenessMatrix;
|
|
18
18
|
}
|
|
19
|
-
export interface
|
|
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;
|
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 fighter = createBattleFighter(cfg);
|
|
94
94
|
return {
|
|
95
|
-
fighterTeam,
|
|
96
|
-
activeIndex: 0,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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);
|
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" | "
|
|
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/
|
|
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
|
|
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
|
-
|
|
74
|
+
console.log("buildPlayerConfig", loadout.fighterId);
|
|
75
|
+
const fighter = findPokemonById(loadout.fighterId);
|
|
75
76
|
if (!fighter) {
|
|
76
|
-
throw new Error(`Unknown fighterId for
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
}
|