piclets / src /lib /utils /battleConversion.ts
Fraser's picture
LEVELS
e8aa797
/**
* 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;
}