File size: 4,495 Bytes
7428b13 |
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 |
import type { PicletInstance, BattleState, BattlePhase } from './schema';
import { db } from './index';
export class BattleService {
// Initialize a new battle
static createBattleState(
playerPiclet: PicletInstance,
enemyPiclet: PicletInstance,
isWildBattle: boolean = true
): BattleState {
return {
phase: 'intro' as BattlePhase,
currentTurn: 0,
playerPiclet,
enemyPiclet,
isWildBattle,
processingTurn: false,
battleEnded: false
};
}
// Calculate damage (simplified formula)
static calculateDamage(
attacker: PicletInstance,
defender: PicletInstance,
move: any
): number {
const baseDamage = move.power || 50;
const attackStat = move.type === 'physical' ? attacker.attack : attacker.fieldAttack;
const defenseStat = move.type === 'physical' ? defender.defense : defender.fieldDefense;
// Simple damage formula
const damage = Math.floor((baseDamage * (attackStat / defenseStat) * 0.5) + 10);
// Add some randomness (85-100% of calculated damage)
const randomFactor = 0.85 + Math.random() * 0.15;
return Math.floor(damage * randomFactor);
}
// Check if move hits (based on accuracy)
static doesMoveHit(accuracy: number): boolean {
return Math.random() * 100 < accuracy;
}
// Calculate capture rate for wild piclets
static calculateCaptureRate(
targetPiclet: PicletInstance,
targetMaxHp: number
): number {
const hpFactor = (targetMaxHp - targetPiclet.currentHp) / targetMaxHp;
const levelFactor = Math.max(0.5, 1 - (targetPiclet.level / 100));
// Base capture rate increases with damage and lower level
const baseRate = 0.3; // 30% base rate
const captureRate = baseRate + (hpFactor * 0.4) + (levelFactor * 0.3);
return Math.min(0.95, captureRate); // Cap at 95%
}
// Attempt to catch a wild piclet
static attemptCapture(
targetPiclet: PicletInstance
): { success: boolean; shakes: number } {
const captureRate = this.calculateCaptureRate(targetPiclet, targetPiclet.maxHp);
const roll = Math.random();
// Calculate shakes (0-3)
let shakes = 0;
if (roll < captureRate * 0.9) shakes = 1;
if (roll < captureRate * 0.7) shakes = 2;
if (roll < captureRate * 0.5) shakes = 3;
return {
success: roll < captureRate,
shakes
};
}
// Create a caught piclet instance
static async createCaughtPiclet(
wildPiclet: PicletInstance
): Promise<PicletInstance> {
const caughtPiclet: Omit<PicletInstance, 'id'> = {
...wildPiclet,
isInRoster: false, // Goes to storage initially
rosterPosition: undefined,
caughtAt: new Date()
};
const id = await db.picletInstances.add(caughtPiclet);
return { ...caughtPiclet, id };
}
// Calculate experience gain
static calculateExpGain(
defeatedPiclet: PicletInstance,
isWild: boolean
): number {
const baseExp = 50 + (defeatedPiclet.level * 10);
const wildModifier = isWild ? 1 : 1.5; // Trainer piclets give more exp
return Math.floor(baseExp * wildModifier);
}
// Check if piclet should level up
static checkLevelUp(
piclet: PicletInstance,
expGained: number
): { leveledUp: boolean; newLevel: number } {
const newExp = piclet.xp + expGained;
const expForNextLevel = this.getExpForLevel(piclet.level + 1);
if (newExp >= expForNextLevel) {
return {
leveledUp: true,
newLevel: piclet.level + 1
};
}
return {
leveledUp: false,
newLevel: piclet.level
};
}
// Get experience required for a level
static getExpForLevel(level: number): number {
// Simple exponential growth formula
return Math.floor(Math.pow(level, 2.5) * 10);
}
// Apply stat boosts for level up
static applyLevelUpStats(piclet: PicletInstance): PicletInstance {
// Simple stat growth (5-10% increase per level)
const growthFactor = 1.07;
return {
...piclet,
level: piclet.level + 1,
maxHp: Math.floor(piclet.maxHp * growthFactor),
currentHp: Math.floor(piclet.currentHp * growthFactor),
attack: Math.floor(piclet.attack * growthFactor),
defense: Math.floor(piclet.defense * growthFactor),
fieldAttack: Math.floor(piclet.fieldAttack * growthFactor),
fieldDefense: Math.floor(piclet.fieldDefense * growthFactor),
speed: Math.floor(piclet.speed * growthFactor)
};
}
} |