Skip to content

Commit

Permalink
Refactor & Fix Item/Modifier Overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
xsn34kzx committed Jul 9, 2024
1 parent 6c77fcf commit 2236452
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 101 deletions.
28 changes: 21 additions & 7 deletions src/modifier/modifier-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1907,14 +1907,28 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo
}
}

// OVERRIDE IF NECESSARY
if (Overrides.ITEM_REWARD_OVERRIDE?.length) {
options.forEach((mod, i) => {
// @ts-ignore: keeps throwing don't use string as index error in typedoc run
const override = modifierTypes[Overrides.ITEM_REWARD_OVERRIDE[i]]?.();
mod.type = (override instanceof ModifierTypeGenerator ? override.generateType(party) : override) || mod.type;
});
// Override rolled options if any override entries are present
for (let i = 0; i < Overrides.ITEM_REWARD_OVERRIDE.length; i++) {
if (options.length >= i) {
break;
}
const override = Overrides.ITEM_REWARD_OVERRIDE[i];
// If the item does not exist in modifierTypes, skip it
if (modifierTypes.hasOwnProperty(override.name)) {
// Retrieve the item entry from modifierTypes
const modifierFunc = modifierTypes[override.name];
let modifierType = modifierFunc();

// Generate modifier type if necessary
if (modifierType instanceof ModifierTypeGenerator) {
modifierType = modifierType.generateType(party, (override.type !== null) ? [override.type] : null);
}

// Replace the corresponding original option
options[i].type = modifierType.withIdFromFunc(modifierFunc);
}
}

return options;
}

Expand Down
110 changes: 61 additions & 49 deletions src/modifier/modifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2651,68 +2651,80 @@ export class EnemyFusionChanceModifier extends EnemyPersistentModifier {
}

/**
* Uses override from overrides.ts to set PersistentModifiers for starting a new game
* @param scene current BattleScene
* @param player is this for player for enemy
* Uses either `MODIFIER_OVERRIDE` in overrides.ts to set {@linkcode PersistentModifier}s for either:
* - The player
* - The enemy
* @param scene current {@linkcode BattleScene}
* @param isPlayer {@linkcode boolean} for whether the the player or enemy is being overridden
*/
export function overrideModifiers(scene: BattleScene, player: boolean = true): void {
const modifierOverride = player ? Overrides.STARTING_MODIFIER_OVERRIDE : Overrides.OPP_MODIFIER_OVERRIDE;
if (!modifierOverride || modifierOverride.length === 0 || !scene) {
export function overrideModifiers(scene: BattleScene, isPlayer: boolean = true): void {
const modifiersOverride = isPlayer ? Overrides.STARTING_MODIFIER_OVERRIDE : Overrides.OPP_MODIFIER_OVERRIDE;
if (!modifiersOverride || modifiersOverride.length === 0 || !scene) {
return;
} // if no override, do nothing
// if it's the opponent, we clear all his current modifiers to avoid stacking
if (!player) {
} // If no override is provided, do nothing

// If it's the opponent, clear all of their current modifiers to avoid stacking
if (!isPlayer) {
scene.clearEnemyModifiers();
}
// we loop through all the modifier name given in the override file
modifierOverride.forEach(item => {
const modifierName = item.name;
const qty = item.count || 1;
if (!modifierTypes.hasOwnProperty(modifierName)) {
return;
} // if the modifier does not exist, we skip it
const modifierType: ModifierType = modifierTypes[modifierName]();
const modifier: PersistentModifier = modifierType.withIdFromFunc(modifierTypes[modifierName]).newModifier() as PersistentModifier;
modifier.stackCount = qty;
if (player) {
scene.addModifier(modifier, true, false, false, true);
} else {
scene.addEnemyModifier(modifier, true, true);

// Loop through all the override items given
modifiersOverride.forEach(item => {
// If the item does not exist in modifierTypes, skip it
if (modifierTypes.hasOwnProperty(item.name)) {
// Retrieve the item entry from modifierTypes
const modifierFunc = modifierTypes[item.name];
const modifier = modifierFunc().withIdFromFunc(modifierFunc).newModifier() as PersistentModifier;
modifier.stackCount = item.count || 1; // Set quantity

if (isPlayer) {
scene.addModifier(modifier, true, false, false, true);
} else {
scene.addEnemyModifier(modifier, true, true);
}
}
});
}

/**
* Uses override from overrides.ts to set PokemonHeldItemModifiers for starting a new game
* @param scene current BattleScene
* @param player is this for player for enemy
* Uses either `HELD_ITEMS_OVERRIDE` in overrides.ts to set {@linkcode PokemonHeldItemModifier}s for either:
* - The first member of the player's team when starting a new game
* - An enemy {@linkcode Pokemon} being spawned in
* @param scene current {@linkcode BattleScene}
* @param pokemon {@linkcode Pokemon} whose held items are being overridden
* @param isPlayer {@linkcode boolean} for whether the {@linkcode pokemon} is the player's or an enemy
*/
export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, player: boolean = true): void {
const heldItemsOverride = player ? Overrides.STARTING_HELD_ITEMS_OVERRIDE : Overrides.OPP_HELD_ITEMS_OVERRIDE;
export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, isPlayer: boolean = true): void {
const heldItemsOverride = isPlayer ? Overrides.STARTING_HELD_ITEMS_OVERRIDE : Overrides.OPP_HELD_ITEMS_OVERRIDE;
if (!heldItemsOverride || heldItemsOverride.length === 0 || !scene) {
return;
} // if no override, do nothing
// we loop through all the itemName given in the override file
} // If no override is provided, do nothing

// Loop through all the override items given
heldItemsOverride.forEach(item => {
const itemName = item.name;
const qty = item.count || 1;
if (!modifierTypes.hasOwnProperty(itemName)) {
return;
} // if the item does not exist, we skip it
const modifierType: ModifierType = modifierTypes[itemName](); // we retrieve the item in the list
let itemModifier: PokemonHeldItemModifier;
if (modifierType instanceof ModifierTypes.ModifierTypeGenerator) {
itemModifier = modifierType.generateType(null, [item.type]).withIdFromFunc(modifierTypes[itemName]).newModifier(pokemon) as PokemonHeldItemModifier;
} else {
itemModifier = modifierType.withIdFromFunc(modifierTypes[itemName]).newModifier(pokemon) as PokemonHeldItemModifier;
}
// we create the item
itemModifier.pokemonId = pokemon.id; // we assign the created item to the pokemon
itemModifier.stackCount = qty; // we say how many items we want
if (player) {
scene.addModifier(itemModifier, true, false, false, true);
} else {
scene.addEnemyModifier(itemModifier, true, true);
// If the item does not exist in modifierTypes, skip it
if (modifierTypes.hasOwnProperty(item.name)) {
// Retrieve the item entry from modifierTypes
const modifierFunc = modifierTypes[item.name];
let modifierType = modifierFunc();
const qty = item.count || 1;

// Generate modifier type if necessary
if (modifierType instanceof ModifierTypes.ModifierTypeGenerator) {
modifierType = modifierType.generateType(null, (item.type !== null) ? [item.type] : null);
}

// Create the held item
const heldItemModifier = modifierType.withIdFromFunc(modifierFunc).newModifier(pokemon) as PokemonHeldItemModifier;
heldItemModifier.pokemonId = pokemon.id; // Assign the created item to the pokemon
heldItemModifier.stackCount = qty; // Set quantity

// Give it to the appropriate Pokemon
if (isPlayer) {
scene.addModifier(heldItemModifier, true, false, false, true);
} else {
scene.addEnemyModifier(heldItemModifier, true, true);
}
}
});
}
113 changes: 68 additions & 45 deletions src/overrides.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import {WeatherType} from "./data/weather";
import {Variant} from "./data/variant";
import {TempBattleStat} from "./data/temp-battle-stat";
import {Nature} from "./data/nature";
import {Type} from "./data/type";
import {Stat} from "./data/pokemon-stat";
import {PokeballCounts} from "./battle-scene";
import {PokeballType} from "./data/pokeball";
import {Gender} from "./data/gender";
import {StatusEffect} from "./data/status-effect";
import {modifierTypes, SpeciesStatBoosterItem} from "./modifier/modifier-type";
import {VariantTier} from "./enums/variant-tiers";
import {EggTier} from "#enums/egg-type";
import {Abilities} from "#enums/abilities";
import {BerryType} from "#enums/berry-type";
import {Biome} from "#enums/biome";
import {Moves} from "#enums/moves";
import {Species} from "#enums/species";
import {TimeOfDay} from "#enums/time-of-day";
import { WeatherType } from "./data/weather";
import { Variant } from "./data/variant";
import { TempBattleStat } from "./data/temp-battle-stat";
import { Nature } from "./data/nature";
import { Type } from "./data/type";
import { Stat } from "./data/pokemon-stat";
import { PokeballCounts } from "./battle-scene";
import { PokeballType } from "./data/pokeball";
import { Gender } from "./data/gender";
import { StatusEffect } from "./data/status-effect";
import { modifierTypes, PokemonHeldItemModifierType, ModifierType, ModifierTypeGenerator } from "./modifier/modifier-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { allSpecies } from "./data/pokemon-species"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { Abilities } from "#enums/abilities";
import { BerryType } from "#enums/berry-type";
import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import { TimeOfDay } from "#enums/time-of-day";
import {MysteryEncounterType} from "#enums/mystery-encounter-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
import {MysteryEncounterTier} from "#app/data/mystery-encounter"; // eslint-disable-line @typescript-eslint/no-unused-vars

Expand All @@ -38,6 +37,7 @@ export const STARTING_WAVE_OVERRIDE: integer = 0;
export const STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN;
export const ARENA_TINT_OVERRIDE: TimeOfDay = null;
// Multiplies XP gained by this value including 0. Set to null to ignore the override
export const NEVER_CRIT_OVERRIDE: boolean = false;
export const XP_MULTIPLIER_OVERRIDE: number = null;
// default 1000
export const STARTING_MONEY_OVERRIDE: integer = 0;
Expand Down Expand Up @@ -122,37 +122,60 @@ export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;

/**
* MODIFIER / ITEM OVERRIDES
* if count is not provided, it will default to 1
* @example Modifier Override [{name: "EXP_SHARE", count: 2}]
* @example Held Item Override [{name: "LUCKY_EGG"}]
* MODIFIER / HELD ITEM OVERRIDES
*/

/**
* Type used to construct modifiers and held items for overriding purposes.
*
* Some items are generated based on a sub-type (i.e. berries), to override those:
* @example [{name: "BERRY", count: 5, type: BerryType.SITRUS}]
* types are listed in interface below
* - TempBattleStat is for TEMP_STAT_BOOSTER / X Items (Dire hit is separate)
* - Stat is for BASE_STAT_BOOSTER / Vitamin
* - Nature is for MINT
* - Type is for TERA_SHARD or ATTACK_TYPE_BOOSTER (type boosting items i.e Silk Scarf)
* - BerryType is for BERRY
* - SpeciesStatBoosterItem is for SPECIES_STAT_BOOSTER
* While both pertain to modifiers in the class hierarchy, overrides labeled `HELD_ITEM`
* specifically pertain to any entry in {@linkcode modifierTypes} that is, extends, or generates
* {@linkcode PokemonHeldItemModifierType}s, like `SOUL_DEW`, `TOXIC_ORB`, etc. Overrides
* labeled `MODIFIER` deal with any modifier so long as it doesn't require a party
* member to hold it (typically is, extends, or generates {@linkcode ModifierType}s),
* like `EXP_SHARE`, `CANDY_JAR`, etc.
*
* Note that, if count is not provided, it will default to 1. Additionally, note that some
* held items and modifiers are grouped together via a {@linkcode ModifierTypeGenerator} and
* require pre-generation arguments to get a specific item.
*
* @example STARTING_MODIFIER_OVERRIDE = [{name: "EXP_SHARE", count: 2}] // will have a quantity of 2 in-game
* @example STARTING_HELD_ITEM_OVERRIDE = [{name: "LUCKY_EGG"}] // will have a quantity of 1 in-game
* @example {name: "BERRY", count: 5, type: BerryType.SITRUS} // type must be given to get a specific berry
*/
interface ModifierOverride {
type ModifierOverride = {
/** Key for any given modifier, held item, or generator in {@linkcode modifierTypes} */
name: keyof typeof modifierTypes & string,
/** Quantity of the held item or modifier desired */
count?: integer
type?: TempBattleStat|Stat|Nature|Type|BerryType|SpeciesStatBoosterItem
}
export const STARTING_MODIFIER_OVERRIDE: Array<ModifierOverride> = [];
export const OPP_MODIFIER_OVERRIDE: Array<ModifierOverride> = [];
/** Sub-type used for generator-based held items and modifiers. The available types are:
* - {@linkcode TempBattleStat}, for {@linkcode modifierTypes.TEMP_STAT_BOOSTER} / X-stat items (Dire Hit is separate)
* - {@linkcode Stat}, for {@linkcode modifierTypes.BASE_STAT_BOOSTER} / Vitamins
* - {@linkcode Nature}, for {@linkcode modifierTypes.MINT}
* - {@linkcode Type}, for {@linkcode modifierTypes.TERA_SHARD} or {@linkcode modifierTypes.ATTACK_TYPE_BOOSTER} / Type-boosting items
* - {@linkcode BerryType}, for {@linkcode modifierTypes.BERRY}
*/
type?: TempBattleStat|Stat|Nature|Type|BerryType
};

export const STARTING_HELD_ITEMS_OVERRIDE: Array<ModifierOverride> = [];
export const OPP_HELD_ITEMS_OVERRIDE: Array<ModifierOverride> = [];
export const NEVER_CRIT_OVERRIDE: boolean = false;
/** Override array of {@linkcode ModifierOverride}s used to provide modifiers to the player when starting a new game */
export const STARTING_MODIFIER_OVERRIDE: ModifierOverride[] = [];
/**
* Override array of {@linkcode ModifierOverride}s used to provide modifiers to enemies.
*
* Note that any previous modifiers are cleared.
*/
export const OPP_MODIFIER_OVERRIDE: ModifierOverride[] = [];

/** Override array of {@linkcode ModifierOverride}s used to provide held items to first party member when starting a new game*/
export const STARTING_HELD_ITEMS_OVERRIDE: ModifierOverride[] = [];
/** Override array of {@linkcode ModifierOverride}s used to provide held items to enemies on spawn */
export const OPP_HELD_ITEMS_OVERRIDE: ModifierOverride[] = [];

/**
* An array of items by keys as defined in the "modifierTypes" object in the "modifier/modifier-type.ts" file.
* Items listed will replace the normal rolls.
* If less items are listed than rolled, only some items will be replaced
* If more items are listed than rolled, only the first X items will be shown, where X is the number of items rolled.
* Override array of {@linkcode ModifierOverride}s used to replace the generated item rolls after a wave.
*
* If less entries are listed than rolled, only those entries will be used to replace the corresponding items while the rest randomly generated.
* If more entries are listed than rolled, only the first X entries will be used, where X is the number of items rolled.
*/
export const ITEM_REWARD_OVERRIDE: Array<String> = [];
export const ITEM_REWARD_OVERRIDE: ModifierOverride[] = [];

0 comments on commit 2236452

Please sign in to comment.