Fraser commited on
Commit
89b51fc
Β·
1 Parent(s): afb1e97
src/lib/components/Pages/Battle.svelte CHANGED
@@ -349,12 +349,17 @@
349
  const playerName = stripBattlePrefix(battleState?.playerPiclet?.definition?.name || '');
350
  const enemyName = stripBattlePrefix(battleState?.opponentPiclet?.definition?.name || '');
351
 
 
 
 
352
  // Attack lunge effects - trigger immediately when a Piclet uses a move
353
  if (message.includes(' used ')) {
354
  if (message.includes(playerName)) {
355
  triggerLungeAnimation('player');
 
356
  } else if (message.includes(enemyName)) {
357
  triggerLungeAnimation('enemy');
 
358
  }
359
  }
360
 
@@ -369,16 +374,31 @@
369
  }
370
  }
371
 
372
- // Critical hit effects
373
  if (message.includes('critical hit')) {
374
- triggerEffect('both', 'critical', 'πŸ’₯', 1000);
 
 
 
 
 
375
  }
376
 
377
- // Effectiveness messages
378
  if (message.includes("It's super effective")) {
379
- triggerEffect('both', 'superEffective', '⚑', 800);
 
 
 
 
 
380
  } else if (message.includes("not very effective")) {
381
- triggerEffect('both', 'notVeryEffective', 'πŸ’¨', 800);
 
 
 
 
 
382
  }
383
 
384
  // Status effects
@@ -423,9 +443,12 @@
423
  updateUIFromBattleState();
424
  }
425
 
426
- // Miss effects
427
  if (message.includes('missed')) {
428
- triggerEffect('both', 'miss', 'πŸ’«', 800);
 
 
 
429
  }
430
 
431
  // Faint effects - only trigger when we see the faint message from battle log
 
349
  const playerName = stripBattlePrefix(battleState?.playerPiclet?.definition?.name || '');
350
  const enemyName = stripBattlePrefix(battleState?.opponentPiclet?.definition?.name || '');
351
 
352
+ // Track who is the current attacker for effects that should appear on the defender
353
+ let currentAttacker: 'player' | 'enemy' | null = null;
354
+
355
  // Attack lunge effects - trigger immediately when a Piclet uses a move
356
  if (message.includes(' used ')) {
357
  if (message.includes(playerName)) {
358
  triggerLungeAnimation('player');
359
+ currentAttacker = 'player';
360
  } else if (message.includes(enemyName)) {
361
  triggerLungeAnimation('enemy');
362
+ currentAttacker = 'enemy';
363
  }
364
  }
365
 
 
374
  }
375
  }
376
 
377
+ // Critical hit effects - show on the target that was hit
378
  if (message.includes('critical hit')) {
379
+ // Critical hits appear after damage, so check who took damage
380
+ const target = message.includes(`${enemyName} took`) ? 'enemy' :
381
+ message.includes(`${playerName} took`) ? 'player' :
382
+ // Fallback: if player used move, enemy is target and vice versa
383
+ message.includes(`${playerName} used`) ? 'enemy' : 'player';
384
+ triggerEffect(target, 'critical', 'πŸ’₯', 1000);
385
  }
386
 
387
+ // Effectiveness messages - show on the target that was hit
388
  if (message.includes("It's super effective")) {
389
+ // Super effective appears after the move, determine target based on attacker
390
+ const target = message.includes(`${playerName} used`) ? 'enemy' :
391
+ message.includes(`${enemyName} used`) ? 'player' :
392
+ // Fallback based on damage message
393
+ message.includes(`${enemyName} took`) ? 'enemy' : 'player';
394
+ triggerEffect(target, 'superEffective', '⚑', 800);
395
  } else if (message.includes("not very effective")) {
396
+ // Not very effective appears after the move, determine target based on attacker
397
+ const target = message.includes(`${playerName} used`) ? 'enemy' :
398
+ message.includes(`${enemyName} used`) ? 'player' :
399
+ // Fallback based on damage message
400
+ message.includes(`${enemyName} took`) ? 'enemy' : 'player';
401
+ triggerEffect(target, 'notVeryEffective', 'πŸ’¨', 800);
402
  }
403
 
404
  // Status effects
 
443
  updateUIFromBattleState();
444
  }
445
 
446
+ // Miss effects - show on the attacker who missed
447
  if (message.includes('missed')) {
448
+ const target = message.includes(`${playerName}'s attack`) || message.includes(`${playerName} used`) ? 'player' :
449
+ message.includes(`${enemyName}'s attack`) || message.includes(`${enemyName} used`) ? 'enemy' :
450
+ 'player'; // Fallback
451
+ triggerEffect(target, 'miss', 'πŸ’«', 800);
452
  }
453
 
454
  // Faint effects - only trigger when we see the faint message from battle log
src/lib/services/unlockLevels.ts CHANGED
@@ -7,40 +7,28 @@ import type { SpecialAbility } from '$lib/battle-engine/types';
7
 
8
  /**
9
  * Calculate unlock level for a move based on its power and characteristics
10
- * More powerful moves unlock later, with some randomness
11
  */
12
  export function calculateMoveUnlockLevel(move: BattleMove, moveIndex: number): number {
13
- // Base unlock level based on power
14
- let baseLevel = 1;
15
-
16
- if (move.power === 0) {
17
- // Status/support moves - unlock early to mid game
18
- baseLevel = Math.floor(Math.random() * 20) + 5; // Level 5-25
19
- } else if (move.power <= 40) {
20
- // Weak moves - unlock early
21
- baseLevel = Math.floor(Math.random() * 15) + 1; // Level 1-15
22
- } else if (move.power <= 60) {
23
- // Medium moves - unlock early to mid
24
- baseLevel = Math.floor(Math.random() * 25) + 10; // Level 10-35
25
- } else if (move.power <= 80) {
26
- // Strong moves - unlock mid to late
27
- baseLevel = Math.floor(Math.random() * 30) + 25; // Level 25-55
28
- } else {
29
- // Very powerful moves - unlock late
30
- baseLevel = Math.floor(Math.random() * 25) + 40; // Level 40-65
31
  }
32
 
33
- // Adjust based on move position (later moves tend to be more powerful)
34
- const positionBonus = moveIndex * 5; // 0, 5, 10, 15 for moves 1-4
35
- baseLevel += positionBonus;
 
 
36
 
37
- // Ensure first move is always available at level 1
38
- if (moveIndex === 0) {
39
- baseLevel = 1;
40
  }
41
 
42
- // Cap at level 80 (everything must be unlocked by then)
43
- return Math.min(baseLevel, 80);
 
44
  }
45
 
46
  /**
 
7
 
8
  /**
9
  * Calculate unlock level for a move based on its power and characteristics
10
+ * First 2 moves are always unlocked, moves 3-4 unlock at levels 9-14
11
  */
12
  export function calculateMoveUnlockLevel(move: BattleMove, moveIndex: number): number {
13
+ // First two moves are always available at level 1
14
+ if (moveIndex === 0 || moveIndex === 1) {
15
+ return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
+ // Third and fourth moves unlock at levels 9-14
19
+ if (moveIndex === 2) {
20
+ // Third move unlocks between level 9-11
21
+ return Math.floor(Math.random() * 3) + 9; // Level 9, 10, or 11
22
+ }
23
 
24
+ if (moveIndex === 3) {
25
+ // Fourth move unlocks between level 12-14
26
+ return Math.floor(Math.random() * 3) + 12; // Level 12, 13, or 14
27
  }
28
 
29
+ // For any additional moves beyond the 4th (shouldn't normally happen)
30
+ // They unlock at higher levels
31
+ return 15 + (moveIndex - 4) * 5;
32
  }
33
 
34
  /**
src/lib/utils/battleConversion.ts CHANGED
@@ -38,21 +38,37 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
38
  effects: move.effects
39
  }));
40
 
41
- // Ensure at least one move is available (first move should always be unlocked at level 1)
42
  if (movepool.length === 0) {
43
  console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
44
- // Emergency fallback - unlock first move
45
- if (instance.moves.length > 0) {
46
- const firstMove = instance.moves[0];
 
47
  movepool.push({
48
- name: firstMove.name,
49
- type: firstMove.type,
50
- power: firstMove.power,
51
- accuracy: firstMove.accuracy,
52
- pp: firstMove.pp,
53
- priority: firstMove.priority,
54
- flags: firstMove.flags,
55
- effects: firstMove.effects
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  });
57
  }
58
  }
 
38
  effects: move.effects
39
  }));
40
 
41
+ // Ensure at least two moves are available (first two moves should always be unlocked at level 1)
42
  if (movepool.length === 0) {
43
  console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
44
+ // Emergency fallback - unlock first two moves
45
+ const movesToUnlock = Math.min(2, instance.moves.length);
46
+ for (let i = 0; i < movesToUnlock; i++) {
47
+ const move = instance.moves[i];
48
  movepool.push({
49
+ name: move.name,
50
+ type: move.type,
51
+ power: move.power,
52
+ accuracy: move.accuracy,
53
+ pp: move.pp,
54
+ priority: move.priority,
55
+ flags: move.flags,
56
+ effects: move.effects
57
+ });
58
+ }
59
+ } else if (movepool.length === 1 && instance.moves.length > 1) {
60
+ // Ensure we have at least 2 moves if possible
61
+ const secondMove = instance.moves[1];
62
+ if (secondMove && secondMove.unlockLevel > updatedInstance.level) {
63
+ movepool.push({
64
+ name: secondMove.name,
65
+ type: secondMove.type,
66
+ power: secondMove.power,
67
+ accuracy: secondMove.accuracy,
68
+ pp: secondMove.pp,
69
+ priority: secondMove.priority,
70
+ flags: secondMove.flags,
71
+ effects: secondMove.effects
72
  });
73
  }
74
  }