From cbdfc160453f8e2c8824a041a3987bb738df2fd4 Mon Sep 17 00:00:00 2001 From: Waleed Hassan Date: Wed, 27 Sep 2023 16:19:26 +0300 Subject: [PATCH] Add a calculateBaseDamage func --- calc/src/mechanics/gen56.ts | 99 ++++++++++++++++-------- calc/src/mechanics/gen789.ts | 141 ++++++++++++++++++++--------------- 2 files changed, 149 insertions(+), 91 deletions(-) diff --git a/calc/src/mechanics/gen56.ts b/calc/src/mechanics/gen56.ts index 38d793388..4640ddf0b 100644 --- a/calc/src/mechanics/gen56.ts +++ b/calc/src/mechanics/gen56.ts @@ -740,34 +740,17 @@ export function calculateBWXY( // #endregion // #region Damage - let baseDamage = getBaseDamage(attacker.level, basePower, attack, defense); - - const isSpread = field.gameType !== 'Singles' && - ['allAdjacent', 'allAdjacentFoes'].includes(move.target); - if (isSpread) { - baseDamage = pokeRound(OF32(baseDamage * 3072) / 4096); - } - - if (attacker.hasAbility('Parental Bond (Child)')) { - baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); - } - - if ((field.hasWeather('Sun', 'Harsh Sunshine') && move.hasType('Fire')) || - (field.hasWeather('Rain', 'Heavy Rain') && move.hasType('Water'))) { - baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); - desc.weather = field.weather; - } else if ( - (field.hasWeather('Sun') && move.hasType('Water')) || - (field.hasWeather('Rain') && move.hasType('Fire')) - ) { - baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); - desc.weather = field.weather; - } - - if (isCritical) { - baseDamage = Math.floor(OF32(baseDamage * (gen.num > 5 ? 1.5 : 2))); - desc.isCritical = isCritical; - } + const baseDamage = calculateBaseDamageBWXY( + gen, + attacker, + basePower, + attack, + defense, + move, + field, + desc, + isCritical + ); // the random factor is applied between the crit mod and the stab mod, so don't apply anything // below this until we're inside the loop @@ -803,6 +786,9 @@ export function calculateBWXY( ); const finalMod = chainMods(finalMods, 41, 131072); + const isSpread = field.gameType !== 'Singles' && + ['allAdjacent', 'allAdjacentFoes'].includes(move.target); + let childDamage: number[] | undefined; if (attacker.hasAbility('Parental Bond') && move.hits === 1 && !isSpread) { const child = attacker.clone(); @@ -870,7 +856,6 @@ export function calculateBWXY( let damageMultiplier = 0; damage = damage.map(affectedAmount => { if (times) { - const newDefense = getModifiedStat(defense, defenderDefBoost); const newFinalMods = calculateFinalModsBWXY( gen, attacker, @@ -883,7 +868,18 @@ export function calculateBWXY( times ); const newFinalMod = chainMods(newFinalMods, 41, 131072); - const newBaseDamage = getBaseDamage(attacker.level, basePower, attack, newDefense); + const newDefense = getModifiedStat(defense, defenderDefBoost); + const newBaseDamage = calculateBaseDamageBWXY( + gen, + attacker, + basePower, + attack, + newDefense, + move, + field, + desc, + isCritical + ); const newFinalDamage = getFinalDamage( newBaseDamage, damageMultiplier, @@ -914,6 +910,49 @@ export function calculateBWXY( return result; } +function calculateBaseDamageBWXY( + gen: Generation, + attacker: Pokemon, + basePower: number, + attack: number, + defense: number, + move: Move, + field: Field, + desc: RawDesc, + isCritical = false, +) { + let baseDamage = getBaseDamage(attacker.level, basePower, attack, defense); + + const isSpread = field.gameType !== 'Singles' && + ['allAdjacent', 'allAdjacentFoes'].includes(move.target); + if (isSpread) { + baseDamage = pokeRound(OF32(baseDamage * 3072) / 4096); + } + + if (attacker.hasAbility('Parental Bond (Child)')) { + baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); + } + + if ((field.hasWeather('Sun', 'Harsh Sunshine') && move.hasType('Fire')) || + (field.hasWeather('Rain', 'Heavy Rain') && move.hasType('Water'))) { + baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); + desc.weather = field.weather; + } else if ( + (field.hasWeather('Sun') && move.hasType('Water')) || + (field.hasWeather('Rain') && move.hasType('Fire')) + ) { + baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); + desc.weather = field.weather; + } + + if (isCritical) { + baseDamage = Math.floor(OF32(baseDamage * (gen.num > 5 ? 1.5 : 2))); + desc.isCritical = isCritical; + } + + return baseDamage; +} + function calculateFinalModsBWXY( gen: Generation, attacker: Pokemon, diff --git a/calc/src/mechanics/gen789.ts b/calc/src/mechanics/gen789.ts index d9712cb4a..9d85bbb28 100644 --- a/calc/src/mechanics/gen789.ts +++ b/calc/src/mechanics/gen789.ts @@ -469,38 +469,18 @@ export function calculateSMSSSV( // #endregion // #region Damage - let baseDamage = getBaseDamage(attacker.level, basePower, attack, defense); - - const isSpread = field.gameType !== 'Singles' && - ['allAdjacent', 'allAdjacentFoes'].includes(move.target); - if (isSpread) { - baseDamage = pokeRound(OF32(baseDamage * 3072) / 4096); - } - - if (attacker.hasAbility('Parental Bond (Child)')) { - baseDamage = pokeRound(OF32(baseDamage * 1024) / 4096); - } - - if ( - field.hasWeather('Sun') && move.named('Hydro Steam') && !attacker.hasItem('Utility Umbrella') - ) { - baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); - desc.weather = field.weather; - } else if (!defender.hasItem('Utility Umbrella')) { - if ( - (field.hasWeather('Sun', 'Harsh Sunshine') && move.hasType('Fire')) || - (field.hasWeather('Rain', 'Heavy Rain') && move.hasType('Water')) - ) { - baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); - desc.weather = field.weather; - } else if ( - (field.hasWeather('Sun') && move.hasType('Water')) || - (field.hasWeather('Rain') && move.hasType('Fire')) - ) { - baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); - desc.weather = field.weather; - } - } + const baseDamage = calculateBaseDamageSMSSSV( + gen, + attacker, + defender, + basePower, + attack, + defense, + move, + field, + desc, + isCritical + ); if (hasTerrainSeed(defender) && field.hasTerrain(defender.item!.substring(0, defender.item!.indexOf(' ')) as Terrain) && @@ -510,11 +490,6 @@ export function calculateSMSSSV( desc.defenderItem = defender.item; } - if (isCritical) { - baseDamage = Math.floor(OF32(baseDamage * 1.5)); - desc.isCritical = isCritical; - } - // the random factor is applied between the crit mod and the stab mod, so don't apply anything // below this until we're inside the loop let stabMod = 4096; @@ -560,6 +535,9 @@ export function calculateSMSSSV( const finalMod = chainMods(finalMods, 41, 131072); + const isSpread = field.gameType !== 'Singles' && + ['allAdjacent', 'allAdjacentFoes'].includes(move.target); + let childDamage: number[] | undefined; if (attacker.hasAbility('Parental Bond') && move.hits === 1 && !isSpread) { const child = attacker.clone(); @@ -628,7 +606,6 @@ export function calculateSMSSSV( let damageMultiplier = 0; damage = damage.map(affectedAmount => { if (times) { - const newDefense = getModifiedStat(defense, defenderDefBoost); const newFinalMods = calculateFinalModsSMSSSV( gen, attacker, @@ -641,29 +618,19 @@ export function calculateSMSSSV( times ); const newFinalMod = chainMods(newFinalMods, 41, 131072); - let newBaseDamage = getBaseDamage(attacker.level, basePower, attack, newDefense); - if (isCritical) { - newBaseDamage = Math.floor(OF32(newBaseDamage * 1.5)); - } - // TODO probably move these to a common function - const isSpread = field.gameType !== 'Singles' && - ['allAdjacent', 'allAdjacentFoes'].includes(move.target); - if (isSpread) { - newBaseDamage = pokeRound(OF32(newBaseDamage * 3072) / 4096); - } - if (!defender.hasItem('Utility Umbrella')) { - if ( - (field.hasWeather('Sun', 'Harsh Sunshine') && move.hasType('Fire')) || - (field.hasWeather('Rain', 'Heavy Rain') && move.hasType('Water')) - ) { - newBaseDamage = pokeRound(OF32(newBaseDamage * 6144) / 4096); - } else if ( - (field.hasWeather('Sun') && move.hasType('Water')) || - (field.hasWeather('Rain') && move.hasType('Fire')) - ) { - newBaseDamage = pokeRound(OF32(newBaseDamage * 2048) / 4096); - } - } + const newDefense = getModifiedStat(defense, defenderDefBoost); + const newBaseDamage = calculateBaseDamageSMSSSV( + gen, + attacker, + defender, + basePower, + attack, + newDefense, + move, + field, + desc, + isCritical + ); const newFinalDamage = getFinalDamage( newBaseDamage, damageMultiplier, @@ -1507,6 +1474,58 @@ export function calculateDfModsSMSSSV( return dfMods; } +function calculateBaseDamageSMSSSV( + gen: Generation, + attacker: Pokemon, + defender: Pokemon, + basePower: number, + attack: number, + defense: number, + move: Move, + field: Field, + desc: RawDesc, + isCritical = false, +) { + let baseDamage = getBaseDamage(attacker.level, basePower, attack, defense); + const isSpread = field.gameType !== 'Singles' && + ['allAdjacent', 'allAdjacentFoes'].includes(move.target); + if (isSpread) { + baseDamage = pokeRound(OF32(baseDamage * 3072) / 4096); + } + + if (attacker.hasAbility('Parental Bond (Child)')) { + baseDamage = pokeRound(OF32(baseDamage * 1024) / 4096); + } + + if ( + field.hasWeather('Sun') && move.named('Hydro Steam') && !attacker.hasItem('Utility Umbrella') + ) { + baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); + desc.weather = field.weather; + } else if (!defender.hasItem('Utility Umbrella')) { + if ( + (field.hasWeather('Sun', 'Harsh Sunshine') && move.hasType('Fire')) || + (field.hasWeather('Rain', 'Heavy Rain') && move.hasType('Water')) + ) { + baseDamage = pokeRound(OF32(baseDamage * 6144) / 4096); + desc.weather = field.weather; + } else if ( + (field.hasWeather('Sun') && move.hasType('Water')) || + (field.hasWeather('Rain') && move.hasType('Fire')) + ) { + baseDamage = pokeRound(OF32(baseDamage * 2048) / 4096); + desc.weather = field.weather; + } + } + + if (isCritical) { + baseDamage = Math.floor(OF32(baseDamage * 1.5)); + desc.isCritical = isCritical; + } + + return baseDamage; +} + export function calculateFinalModsSMSSSV( gen: Generation, attacker: Pokemon,