File size: 6,005 Bytes
4c208f2 60e0688 4c208f2 60e0688 e8aa797 74f8c2c 4c208f2 e8aa797 4c208f2 e8aa797 4c208f2 e8aa797 4c208f2 60e0688 74f8c2c 60e0688 74f8c2c 89b51fc 74f8c2c 89b51fc 60e0688 89b51fc 60e0688 74f8c2c 4c208f2 4256f70 1f2c086 4256f70 74f8c2c 4c208f2 a6cc65f 4c208f2 e3f93ae 4c208f2 60e0688 4c208f2 60e0688 4c208f2 0959fa0 60e0688 4c208f2 a6cc65f 4c208f2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
/**
* Conversion utilities for transforming database types to battle engine types
*/
import type { PicletInstance } from '$lib/db/schema';
import type { PicletDefinition, Move, BaseStats, SpecialAbility } from '$lib/battle-engine/types';
import type { PicletStats } from '$lib/types';
import { PicletType } from '$lib/types/picletTypes';
import { recalculatePicletStats } from '$lib/services/levelingService';
import { getUnlockedMoves, isSpecialAbilityUnlocked } from '$lib/services/unlockLevels';
/**
* 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
};
// Only include unlocked moves - BattleMove now contains complete Move data
const unlockedMoves = getUnlockedMoves(instance.moves, updatedInstance.level);
const movepool: Move[] = unlockedMoves.map(move => ({
name: move.name,
type: move.type,
power: move.power,
accuracy: move.accuracy,
pp: move.pp,
priority: move.priority,
flags: move.flags,
effects: move.effects
}));
// Ensure at least two moves are available (first two moves should always be unlocked at level 1)
if (movepool.length === 0) {
console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
// Emergency fallback - unlock first two moves
const movesToUnlock = Math.min(2, instance.moves.length);
for (let i = 0; i < movesToUnlock; i++) {
const move = instance.moves[i];
movepool.push({
name: move.name,
type: move.type,
power: move.power,
accuracy: move.accuracy,
pp: move.pp,
priority: move.priority,
flags: move.flags,
effects: move.effects
});
}
} else if (movepool.length === 1 && instance.moves.length > 1) {
// Ensure we have at least 2 moves if possible
const secondMove = instance.moves[1];
if (secondMove && secondMove.unlockLevel > updatedInstance.level) {
movepool.push({
name: secondMove.name,
type: secondMove.type,
power: secondMove.power,
accuracy: secondMove.accuracy,
pp: secondMove.pp,
priority: secondMove.priority,
flags: secondMove.flags,
effects: secondMove.effects
});
}
}
// All Piclets must now have special abilities
if (!instance.specialAbility) {
throw new Error('Piclet must have a special ability.');
}
// Only include special ability if unlocked
let specialAbility: SpecialAbility | undefined;
if (isSpecialAbilityUnlocked(instance.specialAbilityUnlockLevel, updatedInstance.level)) {
specialAbility = instance.specialAbility;
} else {
// Create a placeholder ability for locked special abilities
specialAbility = {
name: "Locked Ability",
description: `Unlocks at level ${instance.specialAbilityUnlockLevel}`,
effects: []
};
}
// 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: specialAbility!,
movepool
};
}
/**
* 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 as PicletType,
secondaryType: stats.secondaryType as PicletType || undefined,
baseStats: stats.baseStats,
nature: stats.nature,
specialAbility: {
...stats.specialAbility,
description: `Special ability of ${stats.name || name}` // Add description since it's removed from generation
} as any,
movepool: stats.movepool as any
};
}
/**
* 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;
} |