EZ
Browse files
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
}
|
| 376 |
|
| 377 |
-
// Effectiveness messages
|
| 378 |
if (message.includes("It's super effective")) {
|
| 379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
} else if (message.includes("not very effective")) {
|
| 381 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
}
|
| 383 |
|
| 384 |
// Status effects
|
|
@@ -423,9 +443,12 @@
|
|
| 423 |
updateUIFromBattleState();
|
| 424 |
}
|
| 425 |
|
| 426 |
-
// Miss effects
|
| 427 |
if (message.includes('missed')) {
|
| 428 |
-
|
|
|
|
|
|
|
|
|
|
| 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 |
-
*
|
| 11 |
*/
|
| 12 |
export function calculateMoveUnlockLevel(move: BattleMove, moveIndex: number): number {
|
| 13 |
-
//
|
| 14 |
-
|
| 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 |
-
//
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
}
|
| 41 |
|
| 42 |
-
//
|
| 43 |
-
|
|
|
|
| 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
|
| 42 |
if (movepool.length === 0) {
|
| 43 |
console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
|
| 44 |
-
// Emergency fallback - unlock first
|
| 45 |
-
|
| 46 |
-
|
|
|
|
| 47 |
movepool.push({
|
| 48 |
-
name:
|
| 49 |
-
type:
|
| 50 |
-
power:
|
| 51 |
-
accuracy:
|
| 52 |
-
pp:
|
| 53 |
-
priority:
|
| 54 |
-
flags:
|
| 55 |
-
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 |
}
|