pokemon-io-core 0.0.73 → 0.0.74
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 +4 -0
- package/dist/api/room.d.ts +5 -2
- package/dist/api/socketTypes.d.ts +4 -2
- package/dist/core/battleState.d.ts +1 -1
- package/dist/core/engine.d.ts +5 -1
- package/dist/core/engine.js +41 -14
- package/dist/skins/CombatSkin.d.ts +6 -3
- package/dist/skins/cliches/clicheSkin.d.ts +2 -2
- package/dist/skins/cliches/clicheSkin.js +21 -14
- package/dist/skins/pokemon/pokemonSkin.d.ts +2 -2
- package/dist/skins/pokemon/pokemonSkin.js +21 -14
- package/package.json +1 -1
package/dist/api/battle.d.ts
CHANGED
package/dist/api/room.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export interface
|
|
2
|
-
fighterId: string
|
|
1
|
+
export interface PlayerLoadoutFighterView {
|
|
2
|
+
fighterId: string;
|
|
3
3
|
moveIds: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface PlayerLoadoutView {
|
|
6
|
+
fighters: PlayerLoadoutFighterView[];
|
|
4
7
|
itemIds: string[];
|
|
5
8
|
amuletId: string | null;
|
|
6
9
|
}
|
|
@@ -20,8 +20,10 @@ export interface ClientToServerEvents {
|
|
|
20
20
|
}) => void;
|
|
21
21
|
"room:setLoadout": (payload: {
|
|
22
22
|
roomId: string;
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
fighters: {
|
|
24
|
+
fighterId: string;
|
|
25
|
+
moveIds: string[];
|
|
26
|
+
}[];
|
|
25
27
|
itemIds: string[];
|
|
26
28
|
amuletId?: string | null;
|
|
27
29
|
}) => void;
|
|
@@ -22,7 +22,6 @@ export interface BattleFighter {
|
|
|
22
22
|
baseStats: FighterStats;
|
|
23
23
|
effectiveStats: FighterStats;
|
|
24
24
|
moves: EquippedMove[];
|
|
25
|
-
items: EquippedItem[];
|
|
26
25
|
amuletId: AmuletId | null;
|
|
27
26
|
statuses: ActiveStatus[];
|
|
28
27
|
isAlive: boolean;
|
|
@@ -30,6 +29,7 @@ export interface BattleFighter {
|
|
|
30
29
|
export interface PlayerBattleState {
|
|
31
30
|
fighterTeam: BattleFighter[];
|
|
32
31
|
activeIndex: number;
|
|
32
|
+
inventory: EquippedItem[];
|
|
33
33
|
}
|
|
34
34
|
export interface BattleState {
|
|
35
35
|
turnNumber: number;
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -16,10 +16,14 @@ export interface BattleRuntime {
|
|
|
16
16
|
statusesById: Record<StatusId, StatusDefinition>;
|
|
17
17
|
typeEffectiveness: TypeEffectivenessMatrix;
|
|
18
18
|
}
|
|
19
|
-
export interface
|
|
19
|
+
export interface PlayerFighterBattleConfig {
|
|
20
20
|
fighter: FighterDefinition;
|
|
21
21
|
maxHp: number;
|
|
22
22
|
moves: MoveDefinition[];
|
|
23
|
+
amulet: AmuletDefinition | null;
|
|
24
|
+
}
|
|
25
|
+
export interface PlayerBattleConfig {
|
|
26
|
+
fighters: PlayerFighterBattleConfig[];
|
|
23
27
|
items: ItemDefinition[];
|
|
24
28
|
amulet: AmuletDefinition | null;
|
|
25
29
|
}
|
package/dist/core/engine.js
CHANGED
|
@@ -34,9 +34,6 @@ const createBattleFighter = (cfg) => {
|
|
|
34
34
|
if (cfg.moves.length !== 4) {
|
|
35
35
|
throw new Error("Each fighter must have exactly 4 moves in MVP");
|
|
36
36
|
}
|
|
37
|
-
if (cfg.items.length > 4) {
|
|
38
|
-
throw new Error("A fighter cannot have more than 4 items");
|
|
39
|
-
}
|
|
40
37
|
return {
|
|
41
38
|
fighterId: cfg.fighter.id,
|
|
42
39
|
classId: cfg.fighter.classId,
|
|
@@ -48,10 +45,6 @@ const createBattleFighter = (cfg) => {
|
|
|
48
45
|
moveId: move.id,
|
|
49
46
|
currentPP: move.maxPP,
|
|
50
47
|
})),
|
|
51
|
-
items: cfg.items.map((item) => ({
|
|
52
|
-
itemId: item.id,
|
|
53
|
-
usesRemaining: item.maxUses,
|
|
54
|
-
})),
|
|
55
48
|
amuletId: cfg.amulet ? cfg.amulet.id : null,
|
|
56
49
|
statuses: [],
|
|
57
50
|
isAlive: true,
|
|
@@ -90,10 +83,15 @@ const recomputeEffectiveStatsForFighter = (state, fighter) => {
|
|
|
90
83
|
};
|
|
91
84
|
};
|
|
92
85
|
const createPlayerBattleState = (cfg) => {
|
|
93
|
-
const
|
|
86
|
+
const team = cfg.fighters.map((fCfg) => createBattleFighter(fCfg));
|
|
87
|
+
const inventory = cfg.items.map((item) => ({
|
|
88
|
+
itemId: item.id,
|
|
89
|
+
usesRemaining: item.maxUses,
|
|
90
|
+
}));
|
|
94
91
|
return {
|
|
95
|
-
fighterTeam:
|
|
92
|
+
fighterTeam: team,
|
|
96
93
|
activeIndex: 0,
|
|
94
|
+
inventory,
|
|
97
95
|
};
|
|
98
96
|
};
|
|
99
97
|
export const createInitialBattleState = (config) => {
|
|
@@ -132,6 +130,16 @@ const getOpponentAndSelf = (state, playerKey) => {
|
|
|
132
130
|
opponent: getActiveFighter(oppPlayer),
|
|
133
131
|
};
|
|
134
132
|
};
|
|
133
|
+
const getPlayersAndActives = (state, playerKey) => {
|
|
134
|
+
const selfPlayer = playerKey === "player1" ? state.player1 : state.player2;
|
|
135
|
+
const oppPlayer = playerKey === "player1" ? state.player2 : state.player1;
|
|
136
|
+
return {
|
|
137
|
+
selfPlayer,
|
|
138
|
+
oppPlayer,
|
|
139
|
+
self: getActiveFighter(selfPlayer),
|
|
140
|
+
opponent: getActiveFighter(oppPlayer),
|
|
141
|
+
};
|
|
142
|
+
};
|
|
135
143
|
const getTypeEffectiveness = (state, attackerTypeId, defenderTypeId) => {
|
|
136
144
|
const matrix = state.runtime.typeEffectiveness;
|
|
137
145
|
const row = matrix[attackerTypeId];
|
|
@@ -634,9 +642,9 @@ const resolveItemUse = (state, playerKey, action) => {
|
|
|
634
642
|
if (action.kind !== "use_item") {
|
|
635
643
|
return { state, events: [] };
|
|
636
644
|
}
|
|
637
|
-
const { self, opponent } =
|
|
645
|
+
const { selfPlayer, oppPlayer, self, opponent } = getPlayersAndActives(state, playerKey);
|
|
638
646
|
const events = [];
|
|
639
|
-
const itemSlot =
|
|
647
|
+
const itemSlot = selfPlayer.inventory[action.itemIndex];
|
|
640
648
|
if (!itemSlot || itemSlot.usesRemaining <= 0) {
|
|
641
649
|
dbg("use_item: no charges", {
|
|
642
650
|
playerKey,
|
|
@@ -652,10 +660,10 @@ const resolveItemUse = (state, playerKey, action) => {
|
|
|
652
660
|
});
|
|
653
661
|
return { state, events };
|
|
654
662
|
}
|
|
655
|
-
const
|
|
663
|
+
const updatedInventory = selfPlayer.inventory.map((it, idx) => idx === action.itemIndex
|
|
656
664
|
? { ...it, usesRemaining: Math.max(0, it.usesRemaining - 1) }
|
|
657
665
|
: it);
|
|
658
|
-
let updatedSelf = { ...self
|
|
666
|
+
let updatedSelf = { ...self };
|
|
659
667
|
let updatedOpponent = { ...opponent };
|
|
660
668
|
events.push({
|
|
661
669
|
...createBaseEvent(state.turnNumber, "action_declared", `${self.fighterId} usó ${itemDef.name}`),
|
|
@@ -664,7 +672,26 @@ const resolveItemUse = (state, playerKey, action) => {
|
|
|
664
672
|
const { actor: finalSelf, target: finalOpp, events: extraEvents, } = applyEffectsOnTarget(state, updatedSelf, updatedOpponent, null, // los items no usan fórmula de tipo por ahora
|
|
665
673
|
false, itemDef.effects);
|
|
666
674
|
events.push(...extraEvents);
|
|
667
|
-
|
|
675
|
+
let newState = updateFightersInState(state, playerKey, finalSelf, finalOpp);
|
|
676
|
+
// persistimos el inventario gastado en el jugador que actuó
|
|
677
|
+
if (playerKey === "player1") {
|
|
678
|
+
newState = {
|
|
679
|
+
...newState,
|
|
680
|
+
player1: {
|
|
681
|
+
...newState.player1,
|
|
682
|
+
inventory: updatedInventory,
|
|
683
|
+
},
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
newState = {
|
|
688
|
+
...newState,
|
|
689
|
+
player2: {
|
|
690
|
+
...newState.player2,
|
|
691
|
+
inventory: updatedInventory,
|
|
692
|
+
},
|
|
693
|
+
};
|
|
694
|
+
}
|
|
668
695
|
return { state: newState, events };
|
|
669
696
|
};
|
|
670
697
|
// ------------------------------------------------------
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { TypeDefinition, TypeEffectivenessMatrix, MoveDefinition, ItemDefinition, AmuletDefinition, StatusDefinition } from "../core/index.js";
|
|
2
2
|
import type { PlayerBattleConfig } from "../core/engine.js";
|
|
3
|
-
export interface
|
|
3
|
+
export interface TeamFighterLoadout {
|
|
4
4
|
fighterId: string | null;
|
|
5
|
+
moveIds: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface PlayerTeamLoadout {
|
|
8
|
+
fighters: TeamFighterLoadout[];
|
|
5
9
|
itemIds: string[];
|
|
6
10
|
amuletId: string | null;
|
|
7
|
-
moveIds: string[];
|
|
8
11
|
}
|
|
9
12
|
export interface CombatSkin {
|
|
10
13
|
readonly id: string;
|
|
@@ -14,5 +17,5 @@ export interface CombatSkin {
|
|
|
14
17
|
getItems(): ItemDefinition[];
|
|
15
18
|
getAmulets(): AmuletDefinition[];
|
|
16
19
|
getStatuses(): StatusDefinition[];
|
|
17
|
-
buildPlayerConfig(loadout:
|
|
20
|
+
buildPlayerConfig(loadout: PlayerTeamLoadout): PlayerBattleConfig;
|
|
18
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ItemDefinition, MoveDefinition, PlayerBattleConfig } from "../../core/index.js";
|
|
2
|
-
import type { CombatSkin,
|
|
2
|
+
import type { CombatSkin, PlayerTeamLoadout } from "../CombatSkin.js";
|
|
3
3
|
export declare class TribeSkin implements CombatSkin {
|
|
4
4
|
readonly id = "tribe";
|
|
5
5
|
getTypes(): import("../../index.js").TypeDefinition[];
|
|
@@ -8,6 +8,6 @@ export declare class TribeSkin implements CombatSkin {
|
|
|
8
8
|
getItems(): ItemDefinition[];
|
|
9
9
|
getAmulets(): never[];
|
|
10
10
|
getStatuses(): import("../../index.js").StatusDefinition[];
|
|
11
|
-
buildPlayerConfig(loadout:
|
|
11
|
+
buildPlayerConfig(loadout: PlayerTeamLoadout): PlayerBattleConfig;
|
|
12
12
|
}
|
|
13
13
|
export declare const createTribeSkin: () => CombatSkin;
|
|
@@ -13,8 +13,7 @@ const findItemById = (id) => {
|
|
|
13
13
|
return POKEMON_ITEMS.find((i) => i.id === id) ?? null;
|
|
14
14
|
};
|
|
15
15
|
const FILLER_MOVE_ID = "tackle";
|
|
16
|
-
const buildMovesFromLoadout = (fighter,
|
|
17
|
-
const selectedMoveIds = loadout.moveIds ?? [];
|
|
16
|
+
const buildMovesFromLoadout = (fighter, selectedMoveIds) => {
|
|
18
17
|
const selectedMoves = selectedMoveIds
|
|
19
18
|
.map((id) => findMoveById(id))
|
|
20
19
|
.filter((m) => m !== null);
|
|
@@ -68,22 +67,30 @@ export class TribeSkin {
|
|
|
68
67
|
return TRIBE_STATUSES; // más adelante
|
|
69
68
|
}
|
|
70
69
|
buildPlayerConfig(loadout) {
|
|
71
|
-
if (!loadout.
|
|
72
|
-
throw new Error("
|
|
70
|
+
if (!loadout.fighters || loadout.fighters.length === 0) {
|
|
71
|
+
throw new Error("fighters[] is required in PlayerTeamLoadout");
|
|
73
72
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
const fighters = loadout.fighters.map((slot, idx) => {
|
|
74
|
+
if (!slot.fighterId) {
|
|
75
|
+
throw new Error(`fighterId is required in slot ${idx}`);
|
|
76
|
+
}
|
|
77
|
+
const fighter = findPokemonById(slot.fighterId);
|
|
78
|
+
if (!fighter) {
|
|
79
|
+
throw new Error(`Unknown fighterId for Pokemon skin: ${slot.fighterId}`);
|
|
80
|
+
}
|
|
81
|
+
const moves = buildMovesFromLoadout(fighter, slot.moveIds ?? []);
|
|
82
|
+
return {
|
|
83
|
+
fighter,
|
|
84
|
+
maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
|
|
85
|
+
moves,
|
|
86
|
+
amulet: null
|
|
87
|
+
};
|
|
88
|
+
});
|
|
80
89
|
const items = buildItemsFromLoadout(loadout);
|
|
81
90
|
return {
|
|
82
|
-
|
|
83
|
-
maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
|
|
84
|
-
moves,
|
|
91
|
+
fighters,
|
|
85
92
|
items,
|
|
86
|
-
amulet: null
|
|
93
|
+
amulet: null
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
96
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ItemDefinition, MoveDefinition, PlayerBattleConfig } from "../../core/index.js";
|
|
2
|
-
import type { CombatSkin,
|
|
2
|
+
import type { CombatSkin, PlayerTeamLoadout } from "../CombatSkin.js";
|
|
3
3
|
export declare class PokemonSkin implements CombatSkin {
|
|
4
4
|
readonly id = "pokemon";
|
|
5
5
|
getTypes(): import("../../index.js").TypeDefinition[];
|
|
@@ -8,6 +8,6 @@ export declare class PokemonSkin implements CombatSkin {
|
|
|
8
8
|
getItems(): ItemDefinition[];
|
|
9
9
|
getAmulets(): never[];
|
|
10
10
|
getStatuses(): import("../../index.js").StatusDefinition[];
|
|
11
|
-
buildPlayerConfig(loadout:
|
|
11
|
+
buildPlayerConfig(loadout: PlayerTeamLoadout): PlayerBattleConfig;
|
|
12
12
|
}
|
|
13
13
|
export declare const createPokemonSkin: () => CombatSkin;
|
|
@@ -12,8 +12,7 @@ const findItemById = (id) => {
|
|
|
12
12
|
return POKEMON_ITEMS.find((i) => i.id === id) ?? null;
|
|
13
13
|
};
|
|
14
14
|
const FILLER_MOVE_ID = "tackle";
|
|
15
|
-
const buildMovesFromLoadout = (fighter,
|
|
16
|
-
const selectedMoveIds = loadout.moveIds ?? [];
|
|
15
|
+
const buildMovesFromLoadout = (fighter, selectedMoveIds) => {
|
|
17
16
|
const selectedMoves = selectedMoveIds
|
|
18
17
|
.map((id) => findMoveById(id))
|
|
19
18
|
.filter((m) => m !== null);
|
|
@@ -67,22 +66,30 @@ export class PokemonSkin {
|
|
|
67
66
|
return POKEMON_STATUSES; // más adelante
|
|
68
67
|
}
|
|
69
68
|
buildPlayerConfig(loadout) {
|
|
70
|
-
if (!loadout.
|
|
71
|
-
throw new Error("
|
|
69
|
+
if (!loadout.fighters || loadout.fighters.length === 0) {
|
|
70
|
+
throw new Error("fighters[] is required in PlayerTeamLoadout");
|
|
72
71
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
const fighters = loadout.fighters.map((slot, idx) => {
|
|
73
|
+
if (!slot.fighterId) {
|
|
74
|
+
throw new Error(`fighterId is required in slot ${idx}`);
|
|
75
|
+
}
|
|
76
|
+
const fighter = findPokemonById(slot.fighterId);
|
|
77
|
+
if (!fighter) {
|
|
78
|
+
throw new Error(`Unknown fighterId for Pokemon skin: ${slot.fighterId}`);
|
|
79
|
+
}
|
|
80
|
+
const moves = buildMovesFromLoadout(fighter, slot.moveIds ?? []);
|
|
81
|
+
return {
|
|
82
|
+
fighter,
|
|
83
|
+
maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
|
|
84
|
+
moves,
|
|
85
|
+
amulet: null
|
|
86
|
+
};
|
|
87
|
+
});
|
|
79
88
|
const items = buildItemsFromLoadout(loadout);
|
|
80
89
|
return {
|
|
81
|
-
|
|
82
|
-
maxHp: fighter.baseStats.defense + fighter.baseStats.offense,
|
|
83
|
-
moves,
|
|
90
|
+
fighters,
|
|
84
91
|
items,
|
|
85
|
-
amulet: null
|
|
92
|
+
amulet: null
|
|
86
93
|
};
|
|
87
94
|
}
|
|
88
95
|
}
|