Update accuracy calculation for latest Gen 7 research (#7806)

This commit is contained in:
urkerab 2020-12-15 23:37:24 +00:00 committed by GitHub
parent 721a48ea38
commit 74ae95a91c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 284 additions and 47 deletions

View File

@ -487,11 +487,11 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
num: 172,
},
compoundeyes: {
onSourceModifyAccuracyPriority: 9,
onSourceModifyAccuracyPriority: -1,
onSourceModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('compoundeyes - enhancing accuracy');
return accuracy * 1.3;
return this.chainModify([0x14CD, 0x1000]);
},
name: "Compound Eyes",
rating: 3,
@ -1430,10 +1430,10 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
onModifyAtk(atk) {
return this.modify(atk, 1.5);
},
onSourceModifyAccuracyPriority: 7,
onSourceModifyAccuracyPriority: -1,
onSourceModifyAccuracy(accuracy, target, source, move) {
if (move.category === 'Physical' && typeof accuracy === 'number') {
return accuracy * 0.8;
return this.chainModify([0x0CCD, 0x1000]);
}
},
name: "Hustle",
@ -3076,12 +3076,12 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
onImmunity(type, pokemon) {
if (type === 'sandstorm') return false;
},
onModifyAccuracyPriority: 8,
onModifyAccuracyPriority: -1,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
if (this.field.isWeather('sandstorm')) {
this.debug('Sand Veil - decreasing accuracy');
return accuracy * 0.8;
return this.chainModify([0x0CCD, 0x1000]);
}
},
name: "Sand Veil",
@ -3400,12 +3400,12 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
onImmunity(type, pokemon) {
if (type === 'hail') return false;
},
onModifyAccuracyPriority: 8,
onModifyAccuracyPriority: -1,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
if (this.field.isWeather('hail')) {
this.debug('Snow Cloak - decreasing accuracy');
return accuracy * 0.8;
return this.chainModify([0x0CCD, 0x1000]);
}
},
name: "Snow Cloak",
@ -3799,12 +3799,12 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
num: 28,
},
tangledfeet: {
onModifyAccuracyPriority: 6,
onModifyAccuracyPriority: -1,
onModifyAccuracy(accuracy, target) {
if (typeof accuracy !== 'number') return;
if (target?.volatiles['confusion']) {
this.debug('Tangled Feet - decreasing accuracy');
return accuracy * 0.5;
return this.chainModify(0.5);
}
},
name: "Tangled Feet",
@ -4080,9 +4080,10 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
num: 260,
},
victorystar: {
onAllyModifyMove(move) {
if (typeof move.accuracy === 'number') {
move.accuracy *= 1.1;
onAnyModifyAccuracyPriority: -1,
onAnyModifyAccuracy(accuracy, target, source) {
if (source.side === this.effectData.target.side && typeof accuracy === 'number') {
return this.chainModify([0x119A, 0x1000]);
}
},
name: "Victory Star",

View File

@ -562,11 +562,11 @@ export const Items: {[itemid: string]: ItemData} = {
fling: {
basePower: 10,
},
onModifyAccuracyPriority: 5,
onModifyAccuracyPriority: -2,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('brightpowder - decreasing accuracy');
return accuracy * 0.9;
return this.chainModify([0x0F1C, 0x1000]);
},
num: 213,
gen: 2,
@ -2794,11 +2794,11 @@ export const Items: {[itemid: string]: ItemData} = {
fling: {
basePower: 10,
},
onModifyAccuracyPriority: 5,
onModifyAccuracyPriority: -2,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('lax incense - decreasing accuracy');
return accuracy * 0.9;
return this.chainModify([0x0F1C, 0x1000]);
},
num: 255,
gen: 3,
@ -3463,12 +3463,13 @@ export const Items: {[itemid: string]: ItemData} = {
},
condition: {
duration: 2,
onSourceModifyAccuracyPriority: 3,
onSourceModifyAccuracy(accuracy, target, source) {
this.add('-enditem', source, 'Micle Berry');
source.removeVolatile('micleberry');
if (typeof accuracy === 'number') {
return accuracy * 1.2;
onSourceAccuracy(accuracy, target, source, move) {
if (!move.ohko) {
this.add('-enditem', source, 'Micle Berry');
source.removeVolatile('micleberry');
if (typeof accuracy === 'number') {
return this.chainModify([0x1333, 0x1000]);
}
}
},
},
@ -6737,10 +6738,10 @@ export const Items: {[itemid: string]: ItemData} = {
fling: {
basePower: 10,
},
onSourceModifyAccuracyPriority: 4,
onSourceModifyAccuracyPriority: -2,
onSourceModifyAccuracy(accuracy) {
if (typeof accuracy === 'number') {
return accuracy * 1.1;
return this.chainModify([0x1199, 0x1000]);
}
},
num: 265,
@ -6837,11 +6838,11 @@ export const Items: {[itemid: string]: ItemData} = {
fling: {
basePower: 10,
},
onSourceModifyAccuracyPriority: 4,
onSourceModifyAccuracyPriority: -2,
onSourceModifyAccuracy(accuracy, target) {
if (typeof accuracy === 'number' && !this.queue.willMove(target)) {
this.debug('Zoom Lens boosting accuracy');
return accuracy * 1.2;
return this.chainModify([0x1333, 0x1000]);
}
},
num: 276,

View File

@ -44,6 +44,15 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
},
onAfterMoveSecondary() {},
},
compoundeyes: {
onSourceModifyAccuracyPriority: 9,
onSourceModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('compoundeyes - enhancing accuracy');
return accuracy * 1.3;
},
inherit: true,
},
cutecharm: {
inherit: true,
onDamagingHit(damage, target, source, move) {
@ -147,6 +156,15 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
this.add('-activate', pokemon, 'ability: Forewarn', warnMove);
},
},
hustle: {
inherit: true,
onSourceModifyAccuracyPriority: 7,
onSourceModifyAccuracy(accuracy, target, source, move) {
if (move.category === 'Physical' && typeof accuracy === 'number') {
return accuracy * 0.8;
}
},
},
insomnia: {
inherit: true,
rating: 2.5,
@ -313,6 +331,17 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
}
},
},
sandveil: {
inherit: true,
onModifyAccuracyPriority: 8,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
if (this.field.isWeather('sandstorm')) {
this.debug('Sand Veil - decreasing accuracy');
return accuracy * 0.8;
}
},
},
serenegrace: {
inherit: true,
onModifyMove(move) {
@ -335,8 +364,16 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
rating: 4,
num: 86,
},
soundproof: {
snowcloak: {
inherit: true,
onModifyAccuracyPriority: 8,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
if (this.field.isWeather('hail')) {
this.debug('Snow Cloak - decreasing accuracy');
return accuracy * 0.8;
}
},
},
static: {
inherit: true,
@ -396,6 +433,17 @@ export const Abilities: {[k: string]: ModdedAbilityData} = {
source.trySetStatus(id, target);
},
},
tangledfeet: {
inherit: true,
onModifyAccuracyPriority: 6,
onModifyAccuracy(accuracy, target) {
if (typeof accuracy !== 'number') return;
if (target?.volatiles['confusion']) {
this.debug('Tangled Feet - decreasing accuracy');
return accuracy * 0.5;
}
},
},
thickfat: {
onSourceBasePowerPriority: 1,
onSourceBasePower(basePower, attacker, defender, move) {

View File

@ -16,6 +16,15 @@ export const Items: {[k: string]: ModdedItemData} = {
}
},
},
brightpowder: {
inherit: true,
onModifyAccuracyPriority: 5,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('brightpowder - decreasing accuracy');
return accuracy * 0.9;
},
},
choiceband: {
inherit: true,
onStart() { },
@ -139,6 +148,15 @@ export const Items: {[k: string]: ModdedItemData} = {
}
},
},
laxincense: {
inherit: true,
onModifyAccuracyPriority: 5,
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
this.debug('lax incense - decreasing accuracy');
return accuracy * 0.9;
},
},
lifeorb: {
inherit: true,
onModifyDamage() {},
@ -235,6 +253,20 @@ export const Items: {[k: string]: ModdedItemData} = {
},
},
},
micleberry: {
inherit: true,
condition: {
duration: 2,
onSourceModifyAccuracyPriority: 3,
onSourceModifyAccuracy(accuracy, target, source) {
this.add('-enditem', source, 'Micle Berry');
source.removeVolatile('micleberry');
if (typeof accuracy === 'number') {
return accuracy * 1.2;
}
},
},
},
razorfang: {
inherit: true,
onModifyMove(move) {
@ -266,4 +298,23 @@ export const Items: {[k: string]: ModdedItemData} = {
}
},
},
widelens: {
inherit: true,
onSourceModifyAccuracyPriority: 4,
onSourceModifyAccuracy(accuracy) {
if (typeof accuracy === 'number') {
return accuracy * 1.1;
}
},
},
zoomlens: {
inherit: true,
onSourceModifyAccuracyPriority: 4,
onSourceModifyAccuracy(accuracy, target) {
if (typeof accuracy === 'number' && !this.queue.willMove(target)) {
this.debug('Zoom Lens boosting accuracy');
return accuracy * 1.2;
}
},
},
};

View File

@ -97,6 +97,63 @@ export const Scripts: ModdedBattleScriptsData = {
}
return hitResults;
},
hitStepAccuracy(targets, pokemon, move) {
const hitResults = [];
for (const [i, target] of targets.entries()) {
this.activeTarget = target;
// calculate true accuracy
let accuracy = move.accuracy;
if (move.ohko) { // bypasses accuracy modifiers
if (!target.isSemiInvulnerable()) {
if (pokemon.level < target.level) {
this.add('-immune', target, '[ohko]');
hitResults[i] = false;
continue;
}
accuracy = 30 + pokemon.level - target.level;
}
} else {
const boostTable = [1, 4 / 3, 5 / 3, 2, 7 / 3, 8 / 3, 3];
let boosts;
let boost!: number;
if (accuracy !== true) {
if (!move.ignoreAccuracy) {
boosts = this.runEvent('ModifyBoost', pokemon, null, null, {...pokemon.boosts});
boost = this.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
accuracy /= boostTable[-boost];
}
}
if (!move.ignoreEvasion) {
boosts = this.runEvent('ModifyBoost', target, null, null, {...target.boosts});
boost = this.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
accuracy *= boostTable[-boost];
}
}
}
accuracy = this.runEvent('ModifyAccuracy', target, pokemon, move, accuracy);
}
if (move.alwaysHit) {
accuracy = true; // bypasses ohko accuracy modifiers
} else {
accuracy = this.runEvent('Accuracy', target, pokemon, move, accuracy);
}
if (accuracy !== true && !this.randomChance(accuracy, 100)) {
if (!move.spreadHit) this.attrLastMove('[miss]');
this.add('-miss', pokemon, target);
hitResults[i] = false;
continue;
}
hitResults[i] = true;
}
return hitResults;
},
calcRecoilDamage(damageDealt, move) {
return this.clampIntRange(Math.floor(damageDealt * move.recoil![0] / move.recoil![1]), 1);

View File

@ -7279,7 +7279,7 @@ export const Moves: {[moveid: string]: MoveData} = {
},
onModifyAccuracy(accuracy) {
if (typeof accuracy !== 'number') return;
return accuracy * 5 / 3;
return this.chainModify([0x1AB8, 0x1000]);
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {

View File

@ -452,31 +452,23 @@ export const Scripts: BattleScriptsData = {
}
}
} else {
const boostTable = [1, 4 / 3, 5 / 3, 2, 7 / 3, 8 / 3, 3];
let boosts;
let boost!: number;
accuracy = this.runEvent('ModifyAccuracy', target, pokemon, move, accuracy);
if (accuracy !== true) {
let boost = 0;
if (!move.ignoreAccuracy) {
boosts = this.runEvent('ModifyBoost', pokemon, null, null, {...pokemon.boosts});
const boosts = this.runEvent('ModifyBoost', pokemon, null, null, {...pokemon.boosts});
boost = this.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
accuracy /= boostTable[-boost];
}
}
if (!move.ignoreEvasion) {
boosts = this.runEvent('ModifyBoost', target, null, null, {...target.boosts});
boost = this.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
accuracy *= boostTable[-boost];
}
const boosts = this.runEvent('ModifyBoost', target, null, null, {...target.boosts});
boost = this.clampIntRange(boost - boosts['evasion'], -6, 6);
}
if (boost > 0) {
accuracy = this.trunc(accuracy * (3 + boost) / 3);
} else if (boost < 0) {
accuracy = this.trunc(accuracy * 3 / (3 - boost));
}
}
accuracy = this.runEvent('ModifyAccuracy', target, pokemon, move, accuracy);
}
if (move.alwaysHit || (move.id === 'toxic' && this.gen >= 6 && pokemon.hasType('Poison'))) {
accuracy = true; // bypasses ohko accuracy modifiers

View File

@ -524,6 +524,7 @@ export interface EventMethods {
onAfterMoveSelfPriority?: number;
onAnyBasePowerPriority?: number;
onAnyInvulnerabilityPriority?: number;
onAnyModifyAccuracyPriority?: number;
onAnyFaintPriority?: number;
onAnyPrepareHitPriority?: number;
onAllyBasePowerPriority?: number;

86
test/sim/misc/accuracy.js Normal file
View File

@ -0,0 +1,86 @@
'use strict';
const assert = require('./../../assert');
const common = require('./../../common');
let battle;
describe("Accuracy", function () {
afterEach(function () {
battle.destroy();
});
it(`should round half down when applying a modifier`, function () {
battle = common.createBattle([
[{species: 'Butterfree', ability: 'compoundeyes', moves: ['sleeppowder']}],
[{species: 'Beldum', moves: ['poltergeist']}],
]);
battle.onEvent('Accuracy', battle.format, function (accuracy) {
assert.equal(accuracy, 98, 'CompoundEyes Sleep Powder should be 98% accurate');
});
battle.makeChoices();
battle = common.createBattle([
[{species: 'Butterfree', ability: 'victorystar', moves: ['fireblast']}],
[{species: 'Regirock', moves: ['sleeptalk']}],
]);
battle.onEvent('Accuracy', battle.format, function (accuracy) {
assert.equal(accuracy, 94, 'Victory Star Fire Blast should be 94% accurate');
});
battle.makeChoices();
battle = common.createBattle([
[{species: 'Butterfree', item: 'widelens', moves: ['fireblast']}],
[{species: 'Regirock', moves: ['sleeptalk']}],
]);
battle.onEvent('Accuracy', battle.format, function (accuracy) {
assert.equal(accuracy, 93, 'Wide Lens Fire Blast should be 93% accurate');
});
battle.makeChoices();
});
it(`should chain modifiers in order of the Pokemon's raw speed`, function () {
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Mewtwo', ability: 'victorystar', moves: ['gravity', 'sleeptalk', 'sandattack']},
{species: 'Charizard', ability: 'compoundeyes', moves: ['sleeptalk', 'fireblast']},
], [
{species: 'Bonsly', ability: 'tangledfeet', moves: ['doubleteam', 'sleeptalk']},
{species: 'Pyukumuku', ability: 'noguard', moves: ['confuseray', 'sandattack', 'sleeptalk']},
]]);
battle.makeChoices('move sandattack -2, move sleeptalk', 'move doubleteam, move sandattack 2');
battle.makeChoices('auto', 'move sleeptalk, move confuseray -1');
battle.onEvent('Accuracy', battle.format, function (accuracy, target, source, move) {
if (move.id !== 'fireblast') return;
assert.equal(accuracy, 51);
});
battle.makeChoices('move gravity, move fire blast 1', 'move sleeptalk, move sleeptalk');
// Changing the Pokemon's Speeds around changes the chaining order, which affects the result
battle = common.createBattle({gameType: 'doubles'}, [[
{species: 'Bonsly', ability: 'victorystar', moves: ['gravity', 'sleeptalk', 'sandattack']},
{species: 'Charizard', ability: 'compoundeyes', moves: ['sleeptalk', 'fireblast']},
], [
{species: 'Mewtwo', ability: 'tangledfeet', moves: ['doubleteam', 'sleeptalk']},
{species: 'Pyukumuku', ability: 'noguard', moves: ['confuseray', 'sandattack', 'sleeptalk']},
]]);
battle.makeChoices('move sandattack -2, move sleeptalk', 'move doubleteam, move sandattack 2');
battle.makeChoices('auto', 'move sleeptalk, move confuseray -1');
battle.onEvent('Accuracy', battle.format, function (accuracy, target, source, move) {
if (move.id !== 'fireblast') return;
assert.equal(accuracy, 50);
});
battle.makeChoices('move gravity, move fire blast 1', 'move sleeptalk, move sleeptalk');
});
});