btr
Browse files
src/lib/battle-engine/BattleEngine.ts
CHANGED
|
@@ -34,9 +34,11 @@ export class BattleEngine {
|
|
| 34 |
playerLevel = 50,
|
| 35 |
opponentLevel = 50
|
| 36 |
) {
|
| 37 |
-
// Handle roster setup
|
| 38 |
-
this.playerRoster = Array.isArray(playerPiclet) ? playerPiclet : [playerPiclet]
|
| 39 |
-
|
|
|
|
|
|
|
| 40 |
|
| 41 |
// Initialize roster states
|
| 42 |
this.playerRosterStates = this.initializeRosterStates(this.playerRoster, playerLevel);
|
|
|
|
| 34 |
playerLevel = 50,
|
| 35 |
opponentLevel = 50
|
| 36 |
) {
|
| 37 |
+
// Handle roster setup with internal prefixes for reliable animation targeting
|
| 38 |
+
this.playerRoster = (Array.isArray(playerPiclet) ? playerPiclet : [playerPiclet])
|
| 39 |
+
.map(piclet => ({ ...piclet, name: `player-${piclet.name}` }));
|
| 40 |
+
this.opponentRoster = (Array.isArray(opponentPiclet) ? opponentPiclet : [opponentPiclet])
|
| 41 |
+
.map(piclet => ({ ...piclet, name: `enemy-${piclet.name}` }));
|
| 42 |
|
| 43 |
// Initialize roster states
|
| 44 |
this.playerRosterStates = this.initializeRosterStates(this.playerRoster, playerLevel);
|
src/lib/components/Pages/Battle.svelte
CHANGED
|
@@ -6,7 +6,7 @@
|
|
| 6 |
import BattleControls from '../Battle/BattleControls.svelte';
|
| 7 |
import { BattleEngine } from '$lib/battle-engine/BattleEngine';
|
| 8 |
import type { BattleState, MoveAction } from '$lib/battle-engine/types';
|
| 9 |
-
import { picletInstanceToBattleDefinition, battlePicletToInstance } from '$lib/utils/battleConversion';
|
| 10 |
import { getEffectivenessText, getEffectivenessColor } from '$lib/types/picletTypes';
|
| 11 |
|
| 12 |
export let playerPiclet: PicletInstance;
|
|
@@ -41,6 +41,7 @@
|
|
| 41 |
let playerFaint = false;
|
| 42 |
let enemyFaint = false;
|
| 43 |
|
|
|
|
| 44 |
onMount(() => {
|
| 45 |
// Initialize battle engine with converted piclet definitions
|
| 46 |
const playerDefinition = picletInstanceToBattleDefinition(playerPiclet);
|
|
@@ -181,18 +182,17 @@
|
|
| 181 |
|
| 182 |
|
| 183 |
function triggerVisualEffectsFromMessage(message: string) {
|
| 184 |
-
|
| 185 |
-
const
|
|
|
|
| 186 |
|
| 187 |
// Damage effects
|
| 188 |
if (message.includes('took') && message.includes('damage')) {
|
| 189 |
-
if (message.includes(
|
| 190 |
triggerDamageFlash('player');
|
| 191 |
-
// Update HP bar immediately for damage animation sync
|
| 192 |
updateUIFromBattleState();
|
| 193 |
-
} else if (message.includes(
|
| 194 |
triggerDamageFlash('enemy');
|
| 195 |
-
// Update HP bar immediately for damage animation sync
|
| 196 |
updateUIFromBattleState();
|
| 197 |
}
|
| 198 |
}
|
|
@@ -211,25 +211,25 @@
|
|
| 211 |
|
| 212 |
// Status effects
|
| 213 |
if (message.includes('was burned')) {
|
| 214 |
-
const target = message.includes(
|
| 215 |
triggerEffect(target, 'burn', 'π₯', 1200);
|
| 216 |
} else if (message.includes('was poisoned')) {
|
| 217 |
-
const target = message.includes(
|
| 218 |
triggerEffect(target, 'poison', 'β οΈ', 1200);
|
| 219 |
} else if (message.includes('was paralyzed')) {
|
| 220 |
-
const target = message.includes(
|
| 221 |
triggerEffect(target, 'paralyze', 'β‘', 1200);
|
| 222 |
} else if (message.includes('fell asleep')) {
|
| 223 |
-
const target = message.includes(
|
| 224 |
triggerEffect(target, 'sleep', 'π΄', 1200);
|
| 225 |
} else if (message.includes('was frozen')) {
|
| 226 |
-
const target = message.includes(
|
| 227 |
triggerEffect(target, 'freeze', 'βοΈ', 1200);
|
| 228 |
}
|
| 229 |
|
| 230 |
// Stat changes
|
| 231 |
if (message.includes("'s") && (message.includes('rose') || message.includes('fell'))) {
|
| 232 |
-
const target = message.includes(
|
| 233 |
const isIncrease = message.includes('rose');
|
| 234 |
|
| 235 |
if (message.includes('attack')) {
|
|
@@ -245,7 +245,7 @@
|
|
| 245 |
|
| 246 |
// Healing effects
|
| 247 |
if (message.includes('recovered') && message.includes('HP')) {
|
| 248 |
-
const target = message.includes(
|
| 249 |
triggerEffect(target, 'heal', 'π', 1000);
|
| 250 |
// Update HP bar immediately for healing animation sync
|
| 251 |
updateUIFromBattleState();
|
|
@@ -258,9 +258,9 @@
|
|
| 258 |
|
| 259 |
// Faint effects
|
| 260 |
if (message.includes('fainted')) {
|
| 261 |
-
if (message.includes(
|
| 262 |
triggerFaintAnimation('player');
|
| 263 |
-
} else if (message.includes(
|
| 264 |
triggerFaintAnimation('enemy');
|
| 265 |
}
|
| 266 |
}
|
|
|
|
| 6 |
import BattleControls from '../Battle/BattleControls.svelte';
|
| 7 |
import { BattleEngine } from '$lib/battle-engine/BattleEngine';
|
| 8 |
import type { BattleState, MoveAction } from '$lib/battle-engine/types';
|
| 9 |
+
import { picletInstanceToBattleDefinition, battlePicletToInstance, stripBattlePrefix } from '$lib/utils/battleConversion';
|
| 10 |
import { getEffectivenessText, getEffectivenessColor } from '$lib/types/picletTypes';
|
| 11 |
|
| 12 |
export let playerPiclet: PicletInstance;
|
|
|
|
| 41 |
let playerFaint = false;
|
| 42 |
let enemyFaint = false;
|
| 43 |
|
| 44 |
+
|
| 45 |
onMount(() => {
|
| 46 |
// Initialize battle engine with converted piclet definitions
|
| 47 |
const playerDefinition = picletInstanceToBattleDefinition(playerPiclet);
|
|
|
|
| 182 |
|
| 183 |
|
| 184 |
function triggerVisualEffectsFromMessage(message: string) {
|
| 185 |
+
// Use internal battle prefixes for reliable animation targeting
|
| 186 |
+
const playerInternalName = battleState?.playerPiclet?.definition?.name || '';
|
| 187 |
+
const enemyInternalName = battleState?.opponentPiclet?.definition?.name || '';
|
| 188 |
|
| 189 |
// Damage effects
|
| 190 |
if (message.includes('took') && message.includes('damage')) {
|
| 191 |
+
if (message.includes(playerInternalName)) {
|
| 192 |
triggerDamageFlash('player');
|
|
|
|
| 193 |
updateUIFromBattleState();
|
| 194 |
+
} else if (message.includes(enemyInternalName)) {
|
| 195 |
triggerDamageFlash('enemy');
|
|
|
|
| 196 |
updateUIFromBattleState();
|
| 197 |
}
|
| 198 |
}
|
|
|
|
| 211 |
|
| 212 |
// Status effects
|
| 213 |
if (message.includes('was burned')) {
|
| 214 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 215 |
triggerEffect(target, 'burn', 'π₯', 1200);
|
| 216 |
} else if (message.includes('was poisoned')) {
|
| 217 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 218 |
triggerEffect(target, 'poison', 'β οΈ', 1200);
|
| 219 |
} else if (message.includes('was paralyzed')) {
|
| 220 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 221 |
triggerEffect(target, 'paralyze', 'β‘', 1200);
|
| 222 |
} else if (message.includes('fell asleep')) {
|
| 223 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 224 |
triggerEffect(target, 'sleep', 'π΄', 1200);
|
| 225 |
} else if (message.includes('was frozen')) {
|
| 226 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 227 |
triggerEffect(target, 'freeze', 'βοΈ', 1200);
|
| 228 |
}
|
| 229 |
|
| 230 |
// Stat changes
|
| 231 |
if (message.includes("'s") && (message.includes('rose') || message.includes('fell'))) {
|
| 232 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 233 |
const isIncrease = message.includes('rose');
|
| 234 |
|
| 235 |
if (message.includes('attack')) {
|
|
|
|
| 245 |
|
| 246 |
// Healing effects
|
| 247 |
if (message.includes('recovered') && message.includes('HP')) {
|
| 248 |
+
const target = message.includes(playerInternalName) ? 'player' : 'enemy';
|
| 249 |
triggerEffect(target, 'heal', 'π', 1000);
|
| 250 |
// Update HP bar immediately for healing animation sync
|
| 251 |
updateUIFromBattleState();
|
|
|
|
| 258 |
|
| 259 |
// Faint effects
|
| 260 |
if (message.includes('fainted')) {
|
| 261 |
+
if (message.includes(playerInternalName)) {
|
| 262 |
triggerFaintAnimation('player');
|
| 263 |
+
} else if (message.includes(enemyInternalName)) {
|
| 264 |
triggerFaintAnimation('enemy');
|
| 265 |
}
|
| 266 |
}
|
src/lib/utils/battleConversion.ts
CHANGED
|
@@ -37,7 +37,7 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
|
|
| 37 |
else tier = 'legendary';
|
| 38 |
|
| 39 |
return {
|
| 40 |
-
name: instance.nickname || instance.typeId,
|
| 41 |
description: instance.concept,
|
| 42 |
tier,
|
| 43 |
primaryType: instance.primaryType,
|
|
@@ -121,4 +121,18 @@ export function picletStatsToBattleDefinition(stats: PicletStats, name: string,
|
|
| 121 |
specialAbility: stats.specialAbility,
|
| 122 |
movepool: stats.movepool
|
| 123 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
}
|
|
|
|
| 37 |
else tier = 'legendary';
|
| 38 |
|
| 39 |
return {
|
| 40 |
+
name: instance.nickname || instance.typeId, // Keep original name - we'll add prefixes in battle engine
|
| 41 |
description: instance.concept,
|
| 42 |
tier,
|
| 43 |
primaryType: instance.primaryType,
|
|
|
|
| 121 |
specialAbility: stats.specialAbility,
|
| 122 |
movepool: stats.movepool
|
| 123 |
};
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
/**
|
| 127 |
+
* Strip internal battle prefixes from piclet names for display purposes
|
| 128 |
+
* Removes "player-" and "enemy-" prefixes that are used internally for animation targeting
|
| 129 |
+
*/
|
| 130 |
+
export function stripBattlePrefix(name: string): string {
|
| 131 |
+
if (name.startsWith('player-')) {
|
| 132 |
+
return name.substring('player-'.length);
|
| 133 |
+
}
|
| 134 |
+
if (name.startsWith('enemy-')) {
|
| 135 |
+
return name.substring('enemy-'.length);
|
| 136 |
+
}
|
| 137 |
+
return name;
|
| 138 |
}
|