Skip to content

Commit

Permalink
Merge pull request pagefaultgames#4142 from ben-lear/mystery-encounte…
Browse files Browse the repository at this point in the history
…rs-feedback

Mystery encounters feedback
  • Loading branch information
ben-lear authored Sep 9, 2024
2 parents b25a096 + e950386 commit 08e023e
Show file tree
Hide file tree
Showing 171 changed files with 2,413 additions and 1,805 deletions.
49 changes: 27 additions & 22 deletions create-test-boilerplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,58 @@ const type = args[0]; // "move" or "ability"
let fileName = args[1]; // The file name

if (!type || !fileName) {
console.error('Please provide both a type ("move", "ability", or "item") and a file name.');
process.exit(1);
console.error('Please provide a type ("move", "ability", or "item") and a file name.');
process.exit(1);
}

// Convert fileName from to snake_case if camelCase is given
fileName = fileName.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
// Convert fileName from kebab-case or camelCase to snake_case
fileName = fileName
.replace(/-+/g, '_') // Convert kebab-case (dashes) to underscores
.replace(/([a-z])([A-Z])/g, '$1_$2') // Convert camelCase to snake_case
.toLowerCase(); // Ensure all lowercase

// Format the description for the test case
const formattedName = fileName
.replace(/_/g, ' ')
.replace(/\b\w/g, char => char.toUpperCase());
.replace(/_/g, ' ')
.replace(/\b\w/g, char => char.toUpperCase());

// Determine the directory based on the type
let dir;
let description;
if (type === 'move') {
dir = path.join(__dirname, 'src', 'test', 'moves');
description = `Moves - ${formattedName}`;
dir = path.join(__dirname, 'src', 'test', 'moves');
description = `Moves - ${formattedName}`;
} else if (type === 'ability') {
dir = path.join(__dirname, 'src', 'test', 'abilities');
description = `Abilities - ${formattedName}`;
dir = path.join(__dirname, 'src', 'test', 'abilities');
description = `Abilities - ${formattedName}`;
} else if (type === "item") {
dir = path.join(__dirname, 'src', 'test', 'items');
description = `Items - ${formattedName}`;
dir = path.join(__dirname, 'src', 'test', 'items');
description = `Items - ${formattedName}`;
} else {
console.error('Invalid type. Please use "move", "ability", or "item".');
process.exit(1);
console.error('Invalid type. Please use "move", "ability", or "item".');
process.exit(1);
}

// Ensure the directory exists
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
fs.mkdirSync(dir, { recursive: true });
}

// Create the file with the given name
const filePath = path.join(dir, `${fileName}.test.ts`);

if (fs.existsSync(filePath)) {
console.error(`File "${fileName}.test.ts" already exists.`);
process.exit(1);
console.error(`File "${fileName}.test.ts" already exists.`);
process.exit(1);
}

// Define the content template
const content = `import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, it } from "vitest";
import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest";
describe("${description}", () => {
let phaserGame: Phaser.Game;
Expand All @@ -87,14 +91,15 @@ describe("${description}", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([Moves.SPLASH])
.battleType("single")
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(SPLASH_ONLY);
.enemyMoveset(Moves.SPLASH);
});
it("test case", async () => {
// await game.classicMode.startBattle();
// game.move.select();
// await game.classicMode.startBattle([Species.MAGIKARP]);
// game.move.select(Moves.SPLASH);
}, TIMEOUT);
});
`;
Expand Down
Binary file removed public/images/ui/legacy/summary_moves_effect_de.png
Binary file not shown.
Binary file removed public/images/ui/legacy/summary_moves_effect_es.png
Binary file not shown.
Binary file removed public/images/ui/legacy/summary_moves_effect_fr.png
Binary file not shown.
Binary file removed public/images/ui/legacy/summary_moves_effect_it.png
Binary file not shown.
Binary file removed public/images/ui/legacy/summary_moves_effect_pt-BR.png
Binary file not shown.
Binary file removed public/images/ui/legacy/summary_moves_effect_zh-CN.png
Binary file not shown.
11 changes: 5 additions & 6 deletions src/battle-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ import { ToggleDoublePositionPhase } from "./phases/toggle-double-position-phase
import { TurnInitPhase } from "./phases/turn-init-phase";
import { ShopCursorTarget } from "./enums/shop-cursor-target";
import MysteryEncounter from "./data/mystery-encounters/mystery-encounter";
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters";
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
Expand Down Expand Up @@ -411,7 +411,6 @@ export default class BattleScene extends SceneBase {

this.fieldUI = fieldUI;

// @ts-ignore
const transition = this.make.rexTransitionImagePack({
x: 0,
y: 0,
Expand Down Expand Up @@ -1171,10 +1170,10 @@ export default class BattleScene extends SceneBase {

// Check for mystery encounter
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180
const highestMysteryEncounterWave = 180;
const lowestMysteryEncounterWave = 10;
const highestMysteryEncounterWave = this.gameMode.maxMysteryEncounterWave;
const lowestMysteryEncounterWave = this.gameMode.minMysteryEncounterWave;
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < highestMysteryEncounterWave && newWaveIndex > lowestMysteryEncounterWave) {
const roll = Utils.randSeedInt(256);
const roll = Utils.randSeedInt(MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT);

// Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor
const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance;
Expand Down Expand Up @@ -1254,7 +1253,7 @@ export default class BattleScene extends SceneBase {
const isEndlessFifthWave = this.gameMode.hasShortBiomes && (lastBattle.waveIndex % 5) === 0;
const isWaveIndexMultipleOfFiftyMinusOne = (lastBattle.waveIndex % 50) === 49;
const isNewBiome = isWaveIndexMultipleOfTen || isEndlessFifthWave || (isEndlessOrDaily && isWaveIndexMultipleOfFiftyMinusOne);
const resetArenaState = isNewBiome || this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
const resetArenaState = isNewBiome || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
this.trySpreadPokerus();
if (!isNewBiome && (newWaveIndex % 10) === 5) {
Expand Down
54 changes: 44 additions & 10 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1595,8 +1595,8 @@ export class PostAttackAbAttr extends AbAttr {
private attackCondition: PokemonAttackCondition;

/** The default attackCondition requires that the selected move is a damaging move */
constructor(attackCondition: PokemonAttackCondition = (user, target, move) => (move.category !== MoveCategory.STATUS)) {
super();
constructor(attackCondition: PokemonAttackCondition = (user, target, move) => (move.category !== MoveCategory.STATUS), showAbility: boolean = true) {
super(showAbility);

this.attackCondition = attackCondition;
}
Expand Down Expand Up @@ -1624,6 +1624,40 @@ export class PostAttackAbAttr extends AbAttr {
}
}

/**
* Ability attribute for Gorilla Tactics
* @extends PostAttackAbAttr
*/
export class GorillaTacticsAbAttr extends PostAttackAbAttr {
constructor() {
super((user, target, move) => true, false);
}

/**
*
* @param {Pokemon} pokemon the {@linkcode Pokemon} with this ability
* @param passive n/a
* @param simulated whether the ability is being simulated
* @param defender n/a
* @param move n/a
* @param hitResult n/a
* @param args n/a
* @returns `true` if the ability is applied
*/
applyPostAttackAfterMoveTypeCheck(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, hitResult: HitResult | null, args: any[]): boolean | Promise<boolean> {
if (simulated) {
return simulated;
}

if (pokemon.getTag(BattlerTagType.GORILLA_TACTICS)) {
return false;
}

pokemon.addTag(BattlerTagType.GORILLA_TACTICS);
return true;
}
}

export class PostAttackStealHeldItemAbAttr extends PostAttackAbAttr {
private stealCondition: PokemonAttackCondition | null;

Expand Down Expand Up @@ -3923,7 +3957,7 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
}

export class PostFaintAbAttr extends AbAttr {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
return false;
}
}
Expand Down Expand Up @@ -3974,7 +4008,7 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr {
* @param args N/A
* @returns {boolean} Returns true if the weather clears, otherwise false.
*/
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
const weatherType = pokemon.scene.arena.weather?.weatherType;
let turnOffWeather = false;

Expand Down Expand Up @@ -4022,8 +4056,8 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
this.damageRatio = damageRatio;
}

applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
if (move !== undefined && attacker !== undefined && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { //If the mon didn't die to indirect damage
const cancelled = new Utils.BooleanHolder(false);
pokemon.scene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated));
if (cancelled.value || attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
Expand Down Expand Up @@ -4052,8 +4086,8 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr {
super ();
}

applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
if (!simulated) {
applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): boolean {
if (move !== undefined && attacker !== undefined && !simulated) { //If the mon didn't die to indirect damage
const damage = pokemon.turnData.attacksReceived[0].damage;
attacker.damageAndUpdate((damage), HitResult.OTHER);
attacker.turnData.damageTaken += damage;
Expand Down Expand Up @@ -4711,7 +4745,7 @@ export function applyPostBattleAbAttrs(attrType: Constructor<PostBattleAbAttr>,
}

export function applyPostFaintAbAttrs(attrType: Constructor<PostFaintAbAttr>,
pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, simulated: boolean = false, ...args: any[]): Promise<void> {
pokemon: Pokemon, attacker?: Pokemon, move?: Move, hitResult?: HitResult, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostFaintAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, simulated, attacker, move, hitResult, args), args, false, simulated);
}

Expand Down Expand Up @@ -5597,7 +5631,7 @@ export function initAbilities() {
.bypassFaint()
.partial(),
new Ability(Abilities.GORILLA_TACTICS, 8)
.unimplemented(),
.attr(GorillaTacticsAbAttr),
new Ability(Abilities.NEUTRALIZING_GAS, 8)
.attr(SuppressFieldAbilitiesAbAttr)
.attr(UncopiableAbilityAbAttr)
Expand Down
Loading

0 comments on commit 08e023e

Please sign in to comment.