pokemon-io-core 0.0.23 → 0.0.24

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,14 +1,22 @@
1
+ import { StatusId } from "../core";
2
+ export interface BattlePlayerStatusView {
3
+ statusId: StatusId;
4
+ stacks: 1 | 2;
5
+ remainingTurns: number;
6
+ }
1
7
  export interface BattlePlayerView {
2
8
  playerId: string;
3
9
  nickname: string;
4
10
  hp: number;
11
+ statuses: BattlePlayerStatusView[];
5
12
  }
6
- export type BattleStatusView = "ongoing" | "finished";
13
+ export type BattleStatus = "ongoing" | "finished";
7
14
  export interface BattleView {
8
15
  roomId: string;
9
- status: BattleStatusView;
10
- currentTurnPlayerId: string | null;
16
+ status: BattleStatus;
11
17
  winnerId: string | null;
18
+ currentTurnPlayerId: string | null;
19
+ startedAt: string;
12
20
  endsAt: string;
13
21
  players: BattlePlayerView[];
14
22
  }
@@ -1,4 +1,14 @@
1
1
  // src/domain/combat/engine/battleEngine.ts
2
+ // ------------------------------------------------------
3
+ // Debug helper
4
+ // ------------------------------------------------------
5
+ const DEBUG_BATTLE = true;
6
+ const dbg = (...args) => {
7
+ if (!DEBUG_BATTLE)
8
+ return;
9
+ // eslint-disable-next-line no-console
10
+ console.log("[BATTLE]", ...args);
11
+ };
2
12
  const DEFAULT_RULES = {
3
13
  baseCritChance: 0.05,
4
14
  critPerStat: 0.002,
@@ -7,18 +17,19 @@ const DEFAULT_RULES = {
7
17
  randomMinDamageFactor: 0.85,
8
18
  randomMaxDamageFactor: 1.0,
9
19
  };
10
- const buildMap = (list) => {
11
- return list.reduce((acc, item) => {
12
- acc[item.id] = item;
13
- return acc;
14
- }, {});
15
- };
20
+ const buildMap = (list) => list.reduce((acc, item) => {
21
+ acc[item.id] = item;
22
+ return acc;
23
+ }, {});
16
24
  const cloneStats = (stats) => ({
17
25
  offense: stats.offense,
18
26
  defense: stats.defense,
19
27
  speed: stats.speed,
20
28
  crit: stats.crit,
21
29
  });
30
+ // ------------------------------------------------------
31
+ // Creación de estado inicial
32
+ // ------------------------------------------------------
22
33
  const createBattleFighter = (cfg) => {
23
34
  if (cfg.moves.length !== 4) {
24
35
  throw new Error("Each fighter must have exactly 4 moves in MVP");
@@ -77,10 +88,10 @@ export const createInitialBattleState = (config) => {
77
88
  };
78
89
  return state;
79
90
  };
80
- // HELPERS
81
- const getActiveFighter = (player) => {
82
- return player.fighterTeam[player.activeIndex];
83
- };
91
+ // ------------------------------------------------------
92
+ // Helpers
93
+ // ------------------------------------------------------
94
+ const getActiveFighter = (player) => player.fighterTeam[player.activeIndex];
84
95
  const getOpponentAndSelf = (state, playerKey) => {
85
96
  const selfPlayer = playerKey === "player1" ? state.player1 : state.player2;
86
97
  const oppPlayer = playerKey === "player1" ? state.player2 : state.player1;
@@ -96,9 +107,7 @@ const getTypeEffectiveness = (state, attackerTypeId, defenderTypeId) => {
96
107
  return 1;
97
108
  return row[defenderTypeId] ?? 1;
98
109
  };
99
- const randomInRange = (min, max) => {
100
- return Math.random() * (max - min) + min;
101
- };
110
+ const randomInRange = (min, max) => Math.random() * (max - min) + min;
102
111
  const chance = (probability) => {
103
112
  if (probability <= 0)
104
113
  return false;
@@ -106,8 +115,9 @@ const chance = (probability) => {
106
115
  return true;
107
116
  return Math.random() < probability;
108
117
  };
109
- // FIN HELPERS
110
- // CALCULO DE CRITICOS Y DAÑO
118
+ // ------------------------------------------------------
119
+ // Cálculo de críticos y daño
120
+ // ------------------------------------------------------
111
121
  const computeCritChance = (rules, critStat) => {
112
122
  const raw = rules.baseCritChance + critStat * rules.critPerStat;
113
123
  return Math.max(0, Math.min(1, raw));
@@ -175,14 +185,16 @@ const applyDamageToFighter = (state, defender, amount, actorId, isCritical) => {
175
185
  }
176
186
  return { updatedDefender, events };
177
187
  };
188
+ // ------------------------------------------------------
189
+ // apply_status
190
+ // ------------------------------------------------------
178
191
  const applyStatusToFighter = (state, target, statusId) => {
179
192
  const def = state.runtime.statusesById[statusId];
180
193
  if (!def)
181
194
  return { updated: target, events: [] };
182
195
  const events = [];
183
196
  const existing = target.statuses.find((s) => s.statusId === statusId);
184
- const duration = Math.floor(randomInRange(def.minDurationTurns, def.maxDurationTurns + 1)) ||
185
- def.minDurationTurns;
197
+ const duration = Math.floor(randomInRange(def.minDurationTurns, def.maxDurationTurns + 1)) || def.minDurationTurns;
186
198
  let newStatuses = [...target.statuses];
187
199
  if (!existing) {
188
200
  newStatuses.push({
@@ -199,6 +211,12 @@ const applyStatusToFighter = (state, target, statusId) => {
199
211
  else {
200
212
  newStatuses = newStatuses.map((s) => s.statusId === statusId ? { ...s, remainingTurns: duration } : s);
201
213
  }
214
+ dbg("STATUS_APPLY", {
215
+ fighterId: target.fighterId,
216
+ statusId,
217
+ duration,
218
+ prevStacks: existing?.stacks ?? 0,
219
+ });
202
220
  events.push({
203
221
  ...createBaseEvent(state.turnNumber, "status_applied", `Se aplica ${statusId} a ${target.fighterId}`),
204
222
  targetId: target.fighterId,
@@ -209,6 +227,54 @@ const applyStatusToFighter = (state, target, statusId) => {
209
227
  events,
210
228
  };
211
229
  };
230
+ const applyClearStatusToFighter = (state, target, effect) => {
231
+ const { statusIds, kinds, clearAll } = effect;
232
+ const events = [];
233
+ const before = target.statuses;
234
+ let after = before;
235
+ if (clearAll) {
236
+ after = [];
237
+ }
238
+ else {
239
+ after = before.filter((st) => {
240
+ const def = state.runtime.statusesById[st.statusId];
241
+ if (statusIds && statusIds.includes(st.statusId)) {
242
+ return false;
243
+ }
244
+ if (kinds && def && kinds.includes(def.kind)) {
245
+ return false;
246
+ }
247
+ return true;
248
+ });
249
+ }
250
+ if (after.length === before.length) {
251
+ // nada que limpiar
252
+ return { updated: target, events };
253
+ }
254
+ const removed = before
255
+ .filter((old) => !after.some((st) => st.statusId === old.statusId))
256
+ .map((st) => st.statusId);
257
+ dbg("STATUS_CLEAR", {
258
+ fighterId: target.fighterId,
259
+ cleared: removed,
260
+ clearAll: !!clearAll,
261
+ });
262
+ events.push({
263
+ ...createBaseEvent(state.turnNumber, "status_cleared", `Se limpian estados (${removed.join(", ")}) de ${target.fighterId}`),
264
+ targetId: target.fighterId,
265
+ statusIds: removed,
266
+ });
267
+ return {
268
+ updated: {
269
+ ...target,
270
+ statuses: after,
271
+ },
272
+ events,
273
+ };
274
+ };
275
+ // ------------------------------------------------------
276
+ // heal
277
+ // ------------------------------------------------------
212
278
  const applyHealToFighter = (state, target, amount, sourceId) => {
213
279
  const newHp = Math.min(target.maxHp, target.currentHp + amount);
214
280
  const healed = newHp - target.currentHp;
@@ -218,6 +284,12 @@ const applyHealToFighter = (state, target, amount, sourceId) => {
218
284
  isAlive: newHp > 0,
219
285
  };
220
286
  const events = [];
287
+ dbg("HEAL", {
288
+ sourceId,
289
+ targetId: target.fighterId,
290
+ healed,
291
+ newHp,
292
+ });
221
293
  events.push({
222
294
  ...createBaseEvent(state.turnNumber, "heal", `${sourceId} cura ${healed} a ${target.fighterId}`),
223
295
  actorId: sourceId,
@@ -226,6 +298,9 @@ const applyHealToFighter = (state, target, amount, sourceId) => {
226
298
  });
227
299
  return { updated, events };
228
300
  };
301
+ // ------------------------------------------------------
302
+ // Motor de efectos genérico (move + item)
303
+ // ------------------------------------------------------
229
304
  const applyEffectsOnTarget = (state, actor, target, effects) => {
230
305
  let currentActor = actor;
231
306
  let currentTarget = target;
@@ -244,6 +319,12 @@ const applyEffectsOnTarget = (state, actor, target, effects) => {
244
319
  events.push(...res.events);
245
320
  break;
246
321
  }
322
+ case "clear_status": {
323
+ const res = applyClearStatusToFighter(state, currentTarget, eff);
324
+ currentTarget = res.updated;
325
+ events.push(...res.events);
326
+ break;
327
+ }
247
328
  case "damage": {
248
329
  if (typeof eff.amount === "number") {
249
330
  const res = applyDamageToFighter(state, currentTarget, eff.amount, actor.fighterId, false);
@@ -253,6 +334,7 @@ const applyEffectsOnTarget = (state, actor, target, effects) => {
253
334
  break;
254
335
  }
255
336
  default:
337
+ // otros efectos (modify_stats, etc.) se pueden añadir aquí
256
338
  break;
257
339
  }
258
340
  }
@@ -281,6 +363,9 @@ const getMovePriorityAndSpeed = (state, playerKey, action) => {
281
363
  speed: self.effectiveStats.speed,
282
364
  };
283
365
  };
366
+ // ------------------------------------------------------
367
+ // use_move
368
+ // ------------------------------------------------------
284
369
  const resolveDamageMove = (state, playerKey, action) => {
285
370
  if (action.kind !== "use_move") {
286
371
  return { state, events: [] };
@@ -289,14 +374,23 @@ const resolveDamageMove = (state, playerKey, action) => {
289
374
  const events = [];
290
375
  const moveSlot = self.moves[action.moveIndex];
291
376
  if (!moveSlot) {
377
+ dbg("use_move: empty slot", { playerKey, moveIndex: action.moveIndex });
292
378
  return { state, events };
293
379
  }
294
380
  const move = state.runtime.movesById[moveSlot.moveId];
295
381
  if (!move) {
382
+ dbg("use_move: move definition not found", {
383
+ playerKey,
384
+ moveId: moveSlot.moveId,
385
+ });
296
386
  return { state, events };
297
387
  }
298
- // Sin PP → no hace nada
299
388
  if (moveSlot.currentPP <= 0) {
389
+ dbg("use_move: no PP", {
390
+ playerKey,
391
+ fighterId: self.fighterId,
392
+ moveId: move.id,
393
+ });
300
394
  return { state, events };
301
395
  }
302
396
  // Movimiento solo de curación → no calculamos daño base
@@ -315,7 +409,14 @@ const resolveDamageMove = (state, playerKey, action) => {
315
409
  const newState = updateFightersInState(state, playerKey, finalSelf, finalOpp);
316
410
  return { state: newState, events };
317
411
  }
318
- // Movimiento de daño/hybrid
412
+ dbg("ACTION", {
413
+ playerKey,
414
+ fighterId: self.fighterId,
415
+ moveId: move.id,
416
+ moveName: move.name,
417
+ targetId: opponent.fighterId,
418
+ currentPP: moveSlot.currentPP,
419
+ });
319
420
  events.push({
320
421
  ...createBaseEvent(state.turnNumber, "action_declared", `${self.fighterId} usa ${move.name}`),
321
422
  actorId: self.fighterId,
@@ -329,6 +430,13 @@ const resolveDamageMove = (state, playerKey, action) => {
329
430
  let updatedSelf = { ...self, moves: updatedMoves };
330
431
  let updatedOpponent = { ...opponent };
331
432
  if (!hit) {
433
+ dbg("MISS", {
434
+ fighterId: self.fighterId,
435
+ moveId: move.id,
436
+ moveName: move.name,
437
+ hitRoll,
438
+ accuracy,
439
+ });
332
440
  events.push({
333
441
  ...createBaseEvent(state.turnNumber, "move_miss", `${self.fighterId} falla ${move.name}`),
334
442
  actorId: self.fighterId,
@@ -338,7 +446,6 @@ const resolveDamageMove = (state, playerKey, action) => {
338
446
  const newState = updateFightersInState(state, playerKey, updatedSelf, updatedOpponent);
339
447
  return { state: newState, events };
340
448
  }
341
- // Crítico y daño base
342
449
  const critChance = computeCritChance(state.runtime.rules, updatedSelf.effectiveStats.crit);
343
450
  const isCritical = chance(critChance);
344
451
  const { damage, effectiveness } = computeDamage({
@@ -348,6 +455,15 @@ const resolveDamageMove = (state, playerKey, action) => {
348
455
  move,
349
456
  isCritical,
350
457
  });
458
+ dbg("HIT", {
459
+ fighterId: self.fighterId,
460
+ moveId: move.id,
461
+ moveName: move.name,
462
+ isCritical,
463
+ damage,
464
+ effectiveness,
465
+ defenderBeforeHp: opponent.currentHp,
466
+ });
351
467
  events.push({
352
468
  ...createBaseEvent(state.turnNumber, "move_hit", `${self.fighterId} acierta ${move.name}`),
353
469
  actorId: self.fighterId,
@@ -357,14 +473,21 @@ const resolveDamageMove = (state, playerKey, action) => {
357
473
  effectiveness,
358
474
  });
359
475
  const damageRes = applyDamageToFighter(state, updatedOpponent, damage, updatedSelf.fighterId, isCritical);
476
+ dbg("AFTER_DAMAGE", {
477
+ targetId: opponent.fighterId,
478
+ newHp: damageRes.updatedDefender.currentHp,
479
+ });
360
480
  updatedOpponent = damageRes.updatedDefender;
361
481
  events.push(...damageRes.events);
362
- // Efectos secundarios del movimiento (quemado, buffs, daño extra fijo, etc.)
482
+ // Efectos secundarios del movimiento (quemado, buffs, daño fijo, etc.)
363
483
  const { actor: finalSelf, target: finalOpp, events: extraEvents, } = applyEffectsOnTarget(state, updatedSelf, updatedOpponent, move.effects);
364
484
  events.push(...extraEvents);
365
485
  const newState = updateFightersInState(state, playerKey, finalSelf, finalOpp);
366
486
  return { state: newState, events };
367
487
  };
488
+ // ------------------------------------------------------
489
+ // use_item (respeta item.target: "self" | "enemy")
490
+ // ------------------------------------------------------
368
491
  const resolveItemUse = (state, playerKey, action) => {
369
492
  if (action.kind !== "use_item") {
370
493
  return { state, events: [] };
@@ -373,13 +496,20 @@ const resolveItemUse = (state, playerKey, action) => {
373
496
  const events = [];
374
497
  const itemSlot = self.items[action.itemIndex];
375
498
  if (!itemSlot || itemSlot.usesRemaining <= 0) {
499
+ dbg("use_item: no charges", {
500
+ playerKey,
501
+ itemIndex: action.itemIndex,
502
+ });
376
503
  return { state, events };
377
504
  }
378
505
  const itemDef = state.runtime.itemsById[itemSlot.itemId];
379
506
  if (!itemDef) {
507
+ dbg("use_item: item definition not found", {
508
+ playerKey,
509
+ itemId: itemSlot.itemId,
510
+ });
380
511
  return { state, events };
381
512
  }
382
- // Reducir usos
383
513
  const updatedItems = self.items.map((it, idx) => idx === action.itemIndex
384
514
  ? { ...it, usesRemaining: Math.max(0, it.usesRemaining - 1) }
385
515
  : it);
@@ -389,11 +519,29 @@ const resolveItemUse = (state, playerKey, action) => {
389
519
  ...createBaseEvent(state.turnNumber, "action_declared", `${self.fighterId} usa objeto ${itemDef.name}`),
390
520
  actorId: self.fighterId,
391
521
  });
392
- const { actor: finalSelf, target: finalOpp, events: extraEvents, } = applyEffectsOnTarget(state, updatedSelf, updatedOpponent, itemDef.effects);
393
- events.push(...extraEvents);
522
+ let finalSelf = updatedSelf;
523
+ let finalOpp = updatedOpponent;
524
+ // interpretamos itemDef.target:
525
+ // - "self" → efectos aplican sobre el propio usuario
526
+ // - "enemy" → efectos sobre el rival
527
+ if (itemDef.target === "self") {
528
+ const res = applyEffectsOnTarget(state, updatedSelf, updatedSelf, itemDef.effects);
529
+ finalSelf = res.actor; // o res.target, son el mismo
530
+ // el oponente no cambia
531
+ events.push(...res.events);
532
+ }
533
+ else {
534
+ const res = applyEffectsOnTarget(state, updatedSelf, updatedOpponent, itemDef.effects);
535
+ finalSelf = res.actor;
536
+ finalOpp = res.target;
537
+ events.push(...res.events);
538
+ }
394
539
  const newState = updateFightersInState(state, playerKey, finalSelf, finalOpp);
395
540
  return { state: newState, events };
396
541
  };
542
+ // ------------------------------------------------------
543
+ // Actualizar fighters en el estado
544
+ // ------------------------------------------------------
397
545
  const updateFightersInState = (state, actingPlayerKey, updatedSelf, updatedOpponent) => {
398
546
  const player1 = { ...state.player1 };
399
547
  const player2 = { ...state.player2 };
@@ -421,14 +569,13 @@ const updateFightersInState = (state, actingPlayerKey, updatedSelf, updatedOppon
421
569
  player2: selfPlayer,
422
570
  };
423
571
  };
424
- // FIN RESOLUCION DE ACCION DE use_move
425
- // ORDEN DE ACCIONES HARD CC Y FIN DE TURNO
426
- const hasHardCc = (state, fighter) => {
427
- return fighter.statuses.some((st) => {
428
- const def = state.runtime.statusesById[st.statusId];
429
- return def?.kind === "hard_cc";
430
- });
431
- };
572
+ // ------------------------------------------------------
573
+ // CC duro + check winner
574
+ // ------------------------------------------------------
575
+ const hasHardCc = (state, fighter) => fighter.statuses.some((st) => {
576
+ const def = state.runtime.statusesById[st.statusId];
577
+ return def?.kind === "hard_cc";
578
+ });
432
579
  const checkWinner = (state) => {
433
580
  const f1 = getActiveFighter(state.player1);
434
581
  const f2 = getActiveFighter(state.player2);
@@ -442,7 +589,9 @@ const checkWinner = (state) => {
442
589
  return "draw";
443
590
  return "none";
444
591
  };
445
- // Estados al final del turno: MVP = aplicar DoT básico
592
+ // ------------------------------------------------------
593
+ // Fin de turno: aplicar DoT de estados
594
+ // ------------------------------------------------------
446
595
  const applyEndOfTurnStatuses = (state) => {
447
596
  const events = [];
448
597
  const applyForPlayer = (player) => {
@@ -452,18 +601,27 @@ const applyEndOfTurnStatuses = (state) => {
452
601
  for (const st of active.statuses) {
453
602
  const def = state.runtime.statusesById[st.statusId];
454
603
  if (!def) {
604
+ dbg("STATUS_MISSING_DEF", {
605
+ fighterId: active.fighterId,
606
+ statusId: st.statusId,
607
+ });
455
608
  continue;
456
609
  }
457
- // MVP: interpretamos cualquier efecto kind: "damage" como DoT
458
610
  let damageFromStatus = 0;
459
611
  def.effectsPerStack.forEach((eff) => {
460
612
  if (eff.kind === "damage") {
461
613
  const stacksMultiplier = st.stacks === 2 ? 2 : 1;
462
- const basePower = 10; // DoT base “genérico” (podrás parametrizar)
614
+ const basePower = typeof eff.amount === "number" ? eff.amount : 10;
463
615
  damageFromStatus += basePower * stacksMultiplier;
464
616
  }
465
617
  });
466
618
  if (damageFromStatus > 0 && updated.isAlive) {
619
+ dbg("STATUS_DOT", {
620
+ fighterId: updated.fighterId,
621
+ statusId: st.statusId,
622
+ damageFromStatus,
623
+ stacks: st.stacks,
624
+ });
467
625
  const damageRes = applyDamageToFighter(state, updated, damageFromStatus, updated.fighterId, false);
468
626
  updated = damageRes.updatedDefender;
469
627
  events.push(...damageRes.events);
@@ -476,6 +634,10 @@ const applyEndOfTurnStatuses = (state) => {
476
634
  });
477
635
  }
478
636
  else {
637
+ dbg("STATUS_EXPIRE", {
638
+ fighterId: updated.fighterId,
639
+ statusId: st.statusId,
640
+ });
479
641
  events.push({
480
642
  ...createBaseEvent(state.turnNumber, "status_expired", `El estado ${st.statusId} expira en ${updated.fighterId}`),
481
643
  targetId: updated.fighterId,
@@ -502,15 +664,19 @@ const applyEndOfTurnStatuses = (state) => {
502
664
  };
503
665
  return { state: newState, events };
504
666
  };
505
- // FIN ORDEN DE ACCIONES HARD CC Y FIN DE TURNO
667
+ // ------------------------------------------------------
668
+ // Bucle principal de turno
669
+ // ------------------------------------------------------
506
670
  export const resolveTurn = (state, actions) => {
507
671
  const runtimeState = state;
508
672
  const events = [];
509
- // Evento de inicio de turno
673
+ dbg(`TURN ${runtimeState.turnNumber} start`, {
674
+ p1Action: actions.player1.kind,
675
+ p2Action: actions.player2.kind,
676
+ });
510
677
  events.push({
511
678
  ...createBaseEvent(runtimeState.turnNumber, "turn_start", `Comienza el turno ${runtimeState.turnNumber}`),
512
679
  });
513
- // Construir orden con prioridad+speed
514
680
  const entries = [
515
681
  {
516
682
  playerKey: "player1",
@@ -533,18 +699,20 @@ export const resolveTurn = (state, actions) => {
533
699
  // empate total → coin flip
534
700
  return Math.random() < 0.5 ? -1 : 1;
535
701
  });
702
+ dbg(`TURN ${runtimeState.turnNumber} order`, entries.map((e) => ({
703
+ player: e.playerKey,
704
+ action: e.action.kind,
705
+ priority: e.priority,
706
+ speed: e.speed,
707
+ })));
536
708
  let currentState = runtimeState;
537
709
  for (const entry of entries) {
538
710
  const { playerKey, action } = entry;
539
- if (action.kind === "no_action") {
711
+ if (action.kind === "no_action")
540
712
  continue;
541
- }
542
713
  const { self } = getOpponentAndSelf(currentState, playerKey);
543
- // Si ya está muerto, no hace nada
544
- if (!self.isAlive || self.currentHp <= 0) {
714
+ if (!self.isAlive || self.currentHp <= 0)
545
715
  continue;
546
- }
547
- // Hard CC → se salta acción
548
716
  if (hasHardCc(currentState, self)) {
549
717
  events.push({
550
718
  ...createBaseEvent(currentState.turnNumber, "action_skipped_hard_cc", `${self.fighterId} no puede actuar por control total`),
@@ -563,10 +731,9 @@ export const resolveTurn = (state, actions) => {
563
731
  events.push(...result.events);
564
732
  }
565
733
  else {
566
- // switch_fighter y otros aún no implementados
734
+ // switch_fighter u otros no implementados aún
567
735
  continue;
568
736
  }
569
- // Comprobar victoria inmediata tras cada acción
570
737
  const winnerAfterAction = checkWinner(currentState);
571
738
  if (winnerAfterAction !== "none") {
572
739
  events.push({
@@ -583,7 +750,6 @@ export const resolveTurn = (state, actions) => {
583
750
  };
584
751
  }
585
752
  }
586
- // Fin de turno: aplicar estados
587
753
  const statusResult = applyEndOfTurnStatuses(currentState);
588
754
  currentState = statusResult.state;
589
755
  events.push(...statusResult.events);
@@ -1,5 +1,5 @@
1
1
  import type { FighterId, MoveId, ItemId, StatusId } from "./ids";
2
- export type BattleEventKind = "turn_start" | "action_declared" | "action_skipped_hard_cc" | "move_miss" | "move_hit" | "item_used" | "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" | "turn_end" | "battle_end";
3
3
  export interface BaseBattleEvent {
4
4
  id: string;
5
5
  turnNumber: number;
@@ -37,12 +37,16 @@ export const POKEMON_MOVES = [
37
37
  name: "Ascuas",
38
38
  typeId: POKEMON_TYPE_IDS.fire,
39
39
  kind: "damage",
40
- basePower: 40,
40
+ basePower: 20,
41
41
  accuracy: 100,
42
42
  maxPP: 25,
43
43
  priority: 0,
44
44
  target: "enemy",
45
45
  effects: [
46
+ {
47
+ kind: "damage",
48
+ amount: 20,
49
+ },
46
50
  {
47
51
  kind: "apply_status",
48
52
  statusId: "burn",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pokemon-io-core",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",