diff --git a/package-lock.json b/package-lock.json index 7db944a45..565eac97e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2565,33 +2565,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/happy-dom": { - "version": "14.3.9", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.3.9.tgz", - "integrity": "sha512-0kPQchwthekcYpYN8CvCiq+/z5bqFYDLbTxZ+yDLwT8AFRVJDFadShHRxp3VAZRy7a5isOZ1j/LzsU1dtAIZMQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "entities": "^4.5.0", - "webidl-conversions": "^7.0.0", - "whatwg-mimetype": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/happy-dom/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5802,17 +5775,6 @@ "node": ">=0.10.0" } }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", diff --git a/src/battle-scene.ts b/src/battle-scene.ts index f15cf1a52..11ce52957 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -4,7 +4,7 @@ import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePh import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon'; import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies, speciesStarters } from './data/pokemon-species'; import * as Utils from './utils'; -import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from './modifier/modifier'; +import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, DoubleBattleChancePreventerModifier, overrideModifiers, overrideHeldItems } from './modifier/modifier'; import { PokeballType } from './data/pokeball'; import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './data/battle-anims'; import { Phase } from './phase'; @@ -861,6 +861,8 @@ export default class BattleScene extends SceneBase { this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance)); doubleTrainer = !Utils.randSeedInt(doubleChance.value); + if (this.getModifiers(DoubleBattleChancePreventerModifier).length != 0) + doubleTrainer = false; } newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, doubleTrainer ? TrainerVariant.DOUBLE : Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); this.field.add(newTrainer); @@ -873,6 +875,8 @@ export default class BattleScene extends SceneBase { this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, doubleChance)); newDouble = !Utils.randSeedInt(doubleChance.value); + if (this.getModifiers(DoubleBattleChancePreventerModifier).length != 0) + newDouble = false; } else if (newBattleType === BattleType.TRAINER) newDouble = newTrainer.variant === TrainerVariant.DOUBLE; } else if (!battleConfig) diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 541e18336..360eb527e 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -339,6 +339,17 @@ export class DoubleBattleChanceBoosterModifierType extends ModifierType { } } +export class DoubleBattleChancePreventerModifierType extends ModifierType { + public battleCount: integer; + + constructor(name: string, battleCount: integer) { + super(name, `Prevents double battles for ${battleCount} battles`, (_type, _args) => new Modifiers.DoubleBattleChancePreventerModifier(this, this.battleCount), + null, 'repel'); + + this.battleCount = battleCount; + } +} + export class TempBattleStatBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType { public tempBattleStat: TempBattleStat; @@ -811,9 +822,9 @@ export const modifierTypes = { PP_UP: () => new PokemonPpUpModifierType('PP Up', 1), PP_MAX: () => new PokemonPpUpModifierType('PP Max', 3), - /*REPEL: () => new DoubleBattleChanceBoosterModifierType('Repel', 5), - SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), - MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ + REPEL: () => new DoubleBattleChancePreventerModifierType('Repel', 5), + SUPER_REPEL: () => new DoubleBattleChancePreventerModifierType('Super Repel', 10), + MAX_REPEL: () => new DoubleBattleChancePreventerModifierType('Max Repel', 25), LURE: () => new DoubleBattleChanceBoosterModifierType('Lure', 5), SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType('Super Lure', 10), @@ -993,7 +1004,14 @@ const modifierPool: ModifierPool = { const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); return thresholdPartyMemberCount; }, 3), - new WeightedModifierType(modifierTypes.LURE, 2), + new WeightedModifierType(modifierTypes.REPEL, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 2; + }), + new WeightedModifierType(modifierTypes.LURE, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 2; + }), new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4), new WeightedModifierType(modifierTypes.BERRY, 2), new WeightedModifierType(modifierTypes.TM_COMMON, 1), @@ -1037,7 +1055,14 @@ const modifierPool: ModifierPool = { return thresholdPartyMemberCount; }, 3), new WeightedModifierType(modifierTypes.DIRE_HIT, 4), - new WeightedModifierType(modifierTypes.SUPER_LURE, 4), + new WeightedModifierType(modifierTypes.SUPER_REPEL, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 4; + }), + new WeightedModifierType(modifierTypes.SUPER_LURE, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 4; + }), new WeightedModifierType(modifierTypes.NUGGET, 5), new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, (party: Pokemon[]) => { return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15), 8); @@ -1056,7 +1081,14 @@ const modifierPool: ModifierPool = { ].map(m => { m.setTier(ModifierTier.GREAT); return m; }), [ModifierTier.ULTRA]: [ new WeightedModifierType(modifierTypes.ULTRA_BALL, 24), - new WeightedModifierType(modifierTypes.MAX_LURE, 4), + new WeightedModifierType(modifierTypes.MAX_REPEL, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 4; + }), + new WeightedModifierType(modifierTypes.MAX_LURE, (party: Pokemon[]) => { + const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType); + return existingItem ? 0 : 4; + }), new WeightedModifierType(modifierTypes.BIG_NUGGET, 12), new WeightedModifierType(modifierTypes.PP_UP, 9), new WeightedModifierType(modifierTypes.PP_MAX, 3), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 0736831a0..5a1af6ef5 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -310,6 +310,32 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier } } +export class DoubleBattleChancePreventerModifier extends LapsingPersistentModifier { + constructor(type: ModifierTypes.DoubleBattleChancePreventerModifierType, battlesLeft: integer, stackCount?: integer) { + super(type, battlesLeft, stackCount); + } + + match(modifier: Modifier): boolean { + if (modifier instanceof DoubleBattleChancePreventerModifier) + return (modifier as DoubleBattleChancePreventerModifier).battlesLeft === this.battlesLeft; + return false; + } + + clone(): DoubleBattleChancePreventerModifier { + return new DoubleBattleChancePreventerModifier(this.type as ModifierTypes.DoubleBattleChancePreventerModifierType, this.battlesLeft, this.stackCount); + } + + getArgs(): any[] { + return [ this.battlesLeft ]; + } + + apply(args: any[]): boolean { + const doubleBattleChance = args[0] as Utils.NumberHolder; + doubleBattleChance.value = 0; + return true; + } +} + export class TempBattleStatBoosterModifier extends LapsingPersistentModifier { private tempBattleStat: TempBattleStat;