/** * Conversion utilities for transforming database types to battle engine types */ import type { PicletInstance, BattleMove } from '$lib/db/schema'; import type { PicletDefinition, Move, BaseStats, SpecialAbility } from '$lib/battle-engine/types'; import type { PicletStats, BattleEffect, AbilityTrigger } from '$lib/types'; import { PicletType, AttackType } from '$lib/types/picletTypes'; import { recalculatePicletStats } from '$lib/services/levelingService'; /** * Convert PicletInstance to PicletDefinition for battle engine use * Uses levelingService to ensure stats are properly calculated for current level */ export function picletInstanceToBattleDefinition(instance: PicletInstance): PicletDefinition { // First ensure stats are up-to-date for current level and nature const updatedInstance = recalculatePicletStats(instance); // Use the calculated stats directly (no need for complex reverse formulas) const baseStats: BaseStats = { hp: updatedInstance.maxHp, // Pokemon-calculated HP attack: updatedInstance.attack, // Includes level scaling and nature modifiers defense: updatedInstance.defense, // Includes level scaling and nature modifiers speed: updatedInstance.speed // Includes level scaling and nature modifiers }; // Convert simple moves to full battle moves const movepool: Move[] = instance.moves.map(move => convertBattleMoveToMove(move, instance.primaryType)); // All Piclets must now have special abilities if (!instance.specialAbility) { throw new Error('Piclet must have a special ability. Legacy Piclets are no longer supported.'); } const specialAbility: SpecialAbility = instance.specialAbility; // Determine tier based on BST (Base Stat Total) const bst = baseStats.hp + baseStats.attack + baseStats.defense + baseStats.speed; let tier: 'low' | 'medium' | 'high' | 'legendary'; if (bst <= 300) tier = 'low'; else if (bst <= 400) tier = 'medium'; else if (bst <= 500) tier = 'high'; else tier = 'legendary'; return { name: instance.nickname || instance.typeId, // Keep original name - we'll add prefixes in battle engine description: instance.concept, tier, primaryType: instance.primaryType, secondaryType: instance.secondaryType, baseStats, nature: instance.nature, specialAbility, movepool }; } /** * Convert BattleMove to full Move for battle engine */ function convertBattleMoveToMove(battleMove: BattleMove, primaryType: PicletType): Move { // Create basic effects based on move properties const effects: any[] = []; if (battleMove.power > 0) { effects.push({ type: 'damage', target: 'opponent', amount: battleMove.power >= 80 ? 'strong' : battleMove.power >= 60 ? 'normal' : 'weak' }); } // Add status or stat effects for non-damaging moves if (battleMove.power === 0) { effects.push({ type: 'modifyStats', target: 'self', stats: { attack: 'increase' } }); } return { name: battleMove.name, type: battleMove.type, power: battleMove.power, accuracy: battleMove.accuracy, pp: battleMove.pp, priority: 0, flags: battleMove.power > 0 && battleMove.name.toLowerCase().includes('tackle') ? ['contact'] : [], effects }; } /** * Convert battle engine BattlePiclet back to PicletInstance for state updates */ export function battlePicletToInstance(battlePiclet: any, originalInstance: PicletInstance): PicletInstance { return { ...originalInstance, currentHp: battlePiclet.currentHp, level: battlePiclet.level, attack: battlePiclet.attack, defense: battlePiclet.defense, speed: battlePiclet.speed, // Update moves with current PP moves: battlePiclet.moves.map((moveData: any, index: number) => ({ ...originalInstance.moves[index], currentPp: moveData.currentPP })) }; } /** * Convert PicletStats (from generation) to PicletDefinition for battle engine */ export function picletStatsToBattleDefinition(stats: PicletStats, name: string, concept: string): PicletDefinition { return { name: stats.name || name, description: stats.description || concept, tier: stats.tier, primaryType: stats.primaryType, secondaryType: stats.secondaryType || undefined, baseStats: stats.baseStats, nature: stats.nature, specialAbility: stats.specialAbility, movepool: stats.movepool }; } /** * Strip internal battle prefixes from piclet names for display purposes * Removes "player-" and "enemy-" prefixes that are used internally for animation targeting */ export function stripBattlePrefix(name: string): string { if (name.startsWith('player-')) { return name.substring('player-'.length); } if (name.startsWith('enemy-')) { return name.substring('enemy-'.length); } return name; }