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 |
}
|