Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Moved code preventing MBH's transfer to post modifier generation #4858

Open
wants to merge 8 commits into
base: beta
Choose a base branch
from
121 changes: 64 additions & 57 deletions src/battle-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";

const DEBUG_RNG = false;

const OPP_IVS_OVERRIDE_VALIDATED : integer[] = (
const OPP_IVS_OVERRIDE_VALIDATED: integer[] = (
Array.isArray(Overrides.OPP_IVS_OVERRIDE) ?
Overrides.OPP_IVS_OVERRIDE :
new Array(6).fill(Overrides.OPP_IVS_OVERRIDE)
Expand All @@ -117,18 +117,18 @@ const expSpriteKeys: string[] = [];

export let starterColors: StarterColors;
interface StarterColors {
[key: string]: [string, string]
[key: string]: [string, string]
}

export interface PokeballCounts {
[pb: string]: integer;
[pb: string]: integer;
}

export type AnySound = Phaser.Sound.WebAudioSound | Phaser.Sound.HTML5AudioSound | Phaser.Sound.NoAudioSound;

export interface InfoToggle {
toggleInfo(force?: boolean): void;
isActive(): boolean;
toggleInfo(force?: boolean): void;
isActive(): boolean;
}

export default class BattleScene extends SceneBase {
Expand Down Expand Up @@ -342,7 +342,7 @@ export default class BattleScene extends SceneBase {
if (variant) {
atlasPath = atlasPath.replace("variant/", "");
}
this.load.atlas(key, `images/pokemon/${variant ? "variant/" : ""}${experimental ? "exp/" : ""}${atlasPath}.png`, `images/pokemon/${variant ? "variant/" : ""}${experimental ? "exp/" : ""}${atlasPath}.json`);
this.load.atlas(key, `images/pokemon/${variant ? "variant/" : ""}${experimental ? "exp/" : ""}${atlasPath}.png`, `images/pokemon/${variant ? "variant/" : ""}${experimental ? "exp/" : ""}${atlasPath}.json`);
}

async preload() {
Expand Down Expand Up @@ -1420,7 +1420,7 @@ export default class BattleScene extends SceneBase {
}
return 0;
case Species.GIMMIGHOUL:
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
// Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs
if (this.gameMode.hasMysteryEncounters) {
return 1; // Wandering form
} else {
Expand Down Expand Up @@ -1649,7 +1649,7 @@ export default class BattleScene extends SceneBase {
const isBoss = !(this.currentBattle.waveIndex % 10);
const biomeString: string = getBiomeName(this.arena.biomeType);
this.fieldUI.moveAbove(this.biomeWaveText, this.luckText);
this.biomeWaveText.setText( biomeString + " - " + this.currentBattle.waveIndex.toString());
this.biomeWaveText.setText(biomeString + " - " + this.currentBattle.waveIndex.toString());
this.biomeWaveText.setColor(!isBoss ? "#ffffff" : "#f89890");
this.biomeWaveText.setShadowColor(!isBoss ? "#636363" : "#984038");
this.biomeWaveText.setVisible(true);
Expand Down Expand Up @@ -1955,8 +1955,8 @@ export default class BattleScene extends SceneBase {
case "heal":
case "evolution":
case "evolution_fanfare":
// These sounds are loaded in as BGM, but played as sound effects
// When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM()
// These sounds are loaded in as BGM, but played as sound effects
// When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM()
config["volume"] *= (this.masterVolume * this.bgmVolume);
break;
case "battle_anims":
Expand All @@ -1968,7 +1968,7 @@ export default class BattleScene extends SceneBase {
}
break;
case "ui":
//As of, right now this applies to the "select", "menu_open", "error" sound effects
//As of, right now this applies to the "select", "menu_open", "error" sound effects
config["volume"] *= (this.masterVolume * this.uiVolume);
break;
case "se":
Expand Down Expand Up @@ -2584,61 +2584,68 @@ export default class BattleScene extends SceneBase {
return new Promise(resolve => {
const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null;
const cancelled = new Utils.BooleanHolder(false);
Utils.executeIf(!!source && source.isPlayer() !== target.isPlayer(), () => applyAbAttrs(BlockItemTheftAbAttr, source! /* checked in condition*/, cancelled)).then(() => {
if (cancelled.value) {
return resolve(false);
}
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
newItemModifier.pokemonId = target.id;
const matchingModifier = target.scene.findModifier(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier;
let removeOld = true;
if (matchingModifier) {
const maxStackCount = matchingModifier.getMaxStackCount(target.scene);
if (matchingModifier.stackCount >= maxStackCount) {
if (source && source.isPlayer() !== target.isPlayer()) {
//Check for abilities like Sticky Hold that prevent item transfer between player and opponent
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled).then(() => {
// Check to prevent player-to-opponent/opponent-to-player MBH transfer
if (!cancelled.value) {
cancelled.value = itemModifier instanceof TurnHeldItemTransferModifier;
}
if (cancelled.value) {
return resolve(false);
}
const countTaken = Math.min(transferQuantity, itemModifier.stackCount, maxStackCount - matchingModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = matchingModifier.stackCount + countTaken;
removeOld = !itemModifier.stackCount;
} else {
const countTaken = Math.min(transferQuantity, itemModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = countTaken;
});
}
const newItemModifier = itemModifier.clone() as PokemonHeldItemModifier;
newItemModifier.pokemonId = target.id;
const matchingModifier = target.scene.findModifier(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).matchType(itemModifier) && m.pokemonId === target.id, target.isPlayer()) as PokemonHeldItemModifier;
let removeOld = true;
if (matchingModifier) {
const maxStackCount = matchingModifier.getMaxStackCount(target.scene);
if (matchingModifier.stackCount >= maxStackCount) {
return resolve(false);
}
const countTaken = Math.min(transferQuantity, itemModifier.stackCount, maxStackCount - matchingModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = matchingModifier.stackCount + countTaken;
removeOld = !itemModifier.stackCount;
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
const addModifier = () => {
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
if (target.isPlayer()) {
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant).then(() => {
if (source && itemLost) {
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
}
resolve(true);
});
} else {
this.addEnemyModifier(newItemModifier, ignoreUpdate, instant).then(() => {
if (source && itemLost) {
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
}
resolve(true);
});
}
} else {
const countTaken = Math.min(transferQuantity, itemModifier.stackCount);
itemModifier.stackCount -= countTaken;
newItemModifier.stackCount = countTaken;
}
removeOld = !itemModifier.stackCount;
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
const addModifier = () => {
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
if (target.isPlayer()) {
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant).then(() => {
if (source && itemLost) {
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
}
resolve(true);
});
} else {
resolve(false);
this.addEnemyModifier(newItemModifier, ignoreUpdate, instant).then(() => {
if (source && itemLost) {
applyPostItemLostAbAttrs(PostItemLostAbAttr, source, false);
}
resolve(true);
});
}
};
if (source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate) {
this.updateModifiers(source.isPlayer(), instant).then(() => addModifier());
} else {
addModifier();
resolve(false);
}
return;
};
if (source && source.isPlayer() !== target.isPlayer() && !ignoreUpdate) {
this.updateModifiers(source.isPlayer(), instant).then(() => addModifier());
} else {
addModifier();
}
resolve(false);
});
return;
}
resolve(false);
});
}

Expand Down
8 changes: 4 additions & 4 deletions src/battle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Command } from "./ui/command-ui-handler";
import * as Utils from "./utils";
import Trainer, { TrainerVariant } from "./field/trainer";
import { GameMode } from "./game-mode";
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
import { MoneyMultiplierModifier, PokemonHeldItemModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
import { PokeballType } from "#enums/pokeball";
import { trainerConfigs } from "#app/data/trainer-config";
import { SpeciesFormKey } from "#enums/species-form-key";
Expand Down Expand Up @@ -169,7 +169,7 @@ export default class Battle {
}

addPostBattleLoot(enemyPokemon: EnemyPokemon): void {
this.postBattleLoot.push(...enemyPokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferable, false).map(i => {
this.postBattleLoot.push(...enemyPokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.pokemonId === enemyPokemon.id && m.isTransferable && !(m instanceof TurnHeldItemTransferModifier), false).map(i => {
const ret = i as PokemonHeldItemModifier;
//@ts-ignore - this is awful to fix/change
ret.pokemonId = null;
Expand Down Expand Up @@ -499,7 +499,7 @@ export class FixedBattleConfig {
* @param seedOffset the seed offset to use for the random generation of the trainer
* @returns the generated trainer
*/
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc {
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc {
return (scene: BattleScene) => {
const rand = Utils.randSeedInt(trainerPool.length);
const trainerTypes: TrainerType[] = [];
Expand Down Expand Up @@ -531,7 +531,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand
}

export interface FixedBattleConfigs {
[key: number]: FixedBattleConfig
[key: number]: FixedBattleConfig
}
/**
* Youngster/Lass on 5
Expand Down
4 changes: 2 additions & 2 deletions src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as Utils from "../utils";
import { WeatherType } from "#enums/weather-type";
import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
import { allAbilities, AllyMoveCategoryPowerBoostAbAttr, applyAbAttrs, applyPostAttackAbAttrs, applyPostItemLostAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, BlockItemTheftAbAttr, BlockNonDirectDamageAbAttr, BlockOneHitKOAbAttr, BlockRecoilDamageAttr, ChangeMovePriorityAbAttr, ConfusionOnStatusEffectAbAttr, FieldMoveTypePowerBoostAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, HealFromBerryUseAbAttr, IgnoreContactAbAttr, IgnoreMoveEffectsAbAttr, IgnoreProtectOnContactAbAttr, InfiltratorAbAttr, MaxMultiHitAbAttr, MoveAbilityBypassAbAttr, MoveEffectChanceMultiplierAbAttr, MoveTypeChangeAbAttr, PostDamageForceSwitchAbAttr, PostItemLostAbAttr, ReverseDrainAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, UnswappableAbilityAbAttr, UserFieldMoveTypePowerBoostAbAttr, VariableMovePowerAbAttr, WonderSkinAbAttr } from "./ability";
import { AttackTypeBoosterModifier, BerryModifier, PokemonHeldItemModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PreserveBerryModifier } from "../modifier/modifier";
import { AttackTypeBoosterModifier, BerryModifier, PokemonHeldItemModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PreserveBerryModifier, TurnHeldItemTransferModifier } from "../modifier/modifier";
import { BattlerIndex, BattleType } from "../battle";
import { TerrainType } from "./terrain";
import { ModifierPoolType } from "#app/modifier/modifier-type";
Expand Down Expand Up @@ -2371,7 +2371,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
if (heldItems.length) {
const poolType = target.isPlayer() ? ModifierPoolType.PLAYER : target.hasTrainer() ? ModifierPoolType.TRAINER : ModifierPoolType.WILD;
const highestItemTier = heldItems.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is the bang after tier correct?
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
const tierHeldItems = heldItems.filter(m => m.type.getOrInferTier(poolType) === highestItemTier && !(m instanceof TurnHeldItemTransferModifier));
const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)];
user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => {
if (success) {
Expand Down
7 changes: 7 additions & 0 deletions src/game-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ export class GameMode implements GameModeConfig {
return waveIndex % 10 === 0;
}

/**
* @returns `true` if the current battle is against classic mode's final boss
*/
isBattleClassicFinalBoss(waveIndex: number): boolean {
return (this.modeId === GameModes.CLASSIC || this.modeId === GameModes.CHALLENGE) && this.isWaveFinal(waveIndex);
}

/**
* Every 50 waves of an Endless mode is a boss
* At this time it is paradox pokemon
Expand Down
2 changes: 1 addition & 1 deletion src/modifier/modifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3181,7 +3181,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {

const transferredModifierTypes: ModifierType[] = [];
const itemModifiers = pokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& m.pokemonId === targetPokemon.id && m.isTransferable, targetPokemon.isPlayer()) as PokemonHeldItemModifier[];
&& m.pokemonId === targetPokemon.id && m.isTransferable && !(m instanceof TurnHeldItemTransferModifier), targetPokemon.isPlayer()) as PokemonHeldItemModifier[];
let highestItemTier = itemModifiers.map(m => m.type.getOrInferTier(poolType)).reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is this bang correct?
let tierItemModifiers = itemModifiers.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);

Expand Down
6 changes: 1 addition & 5 deletions src/phases/encounter-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getRandomWeatherType } from "#app/data/weather";
import { EncounterPhaseEvent } from "#app/events/battle-scene";
import Pokemon, { FieldPosition } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages";
import { BoostBugSpawnModifier, IvScannerModifier, TurnHeldItemTransferModifier } from "#app/modifier/modifier";
import { BoostBugSpawnModifier, IvScannerModifier } from "#app/modifier/modifier";
import { ModifierPoolType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
import Overrides from "#app/overrides";
import { BattlePhase } from "#app/phases/battle-phase";
Expand Down Expand Up @@ -141,10 +141,6 @@ export class EncounterPhase extends BattlePhase {
} else if (!(battle.waveIndex % 1000)) {
enemyPokemon.formIndex = 1;
enemyPokemon.updateScale();
const bossMBH = this.scene.findModifier(m => m instanceof TurnHeldItemTransferModifier && m.pokemonId === enemyPokemon.id, false) as TurnHeldItemTransferModifier;
this.scene.removeModifier(bossMBH!);
bossMBH?.setTransferrableFalse();
this.scene.addEnemyModifier(bossMBH!);
}
}

Expand Down
Loading