mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-09-23 15:03:24 +02:00
Merge pull request #6420 from pagefaultgames/hotfix-1.10.4
Hotfix 1.10.4 to main
This commit is contained in:
commit
cc7391448a
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.10.3",
|
||||
"version": "1.10.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
|
@ -1,3 +1,7 @@
|
||||
self.addEventListener('install', function () {
|
||||
console.log('Service worker installing...');
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(self.clients.claim());
|
||||
})
|
@ -77,7 +77,8 @@ export enum EvolutionItem {
|
||||
LEADERS_CREST
|
||||
}
|
||||
|
||||
type TyrogueMove = MoveId.LOW_SWEEP | MoveId.MACH_PUNCH | MoveId.RAPID_SPIN;
|
||||
const tyrogueMoves = [MoveId.LOW_SWEEP, MoveId.MACH_PUNCH, MoveId.RAPID_SPIN] as const;
|
||||
type TyrogueMove = typeof tyrogueMoves[number];
|
||||
|
||||
/**
|
||||
* Pokemon Evolution tuple type consisting of:
|
||||
@ -192,7 +193,7 @@ export class SpeciesEvolutionCondition {
|
||||
case EvoCondKey.WEATHER:
|
||||
return cond.weather.includes(globalScene.arena.getWeatherType());
|
||||
case EvoCondKey.TYROGUE:
|
||||
return pokemon.getMoveset(true).find(m => m.moveId as TyrogueMove)?.moveId === cond.move;
|
||||
return pokemon.getMoveset(true).find(m => (tyrogueMoves as readonly MoveId[]) .includes(m.moveId))?.moveId === cond.move;
|
||||
case EvoCondKey.NATURE:
|
||||
return cond.nature.includes(pokemon.getNature());
|
||||
case EvoCondKey.RANDOM_FORM: {
|
||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { allSpecies, modifierTypes } from "#data/data-lists";
|
||||
import { getLevelTotalExp } from "#data/exp";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
@ -10,8 +11,9 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { MAX_POKEMON_TYPE, PokemonType } from "#enums/pokemon-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import type { PokemonHeldItemModifier } from "#modifiers/modifier";
|
||||
@ -219,6 +221,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
await showEncounterText(`${namespace}:option.1.dreamComplete`);
|
||||
|
||||
await doNewTeamPostProcess(transformations);
|
||||
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [
|
||||
modifierTypes.MEMORY_MUSHROOM,
|
||||
@ -230,7 +233,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
],
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle(true);
|
||||
leaveEncounterWithoutBattle(false);
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
@ -431,6 +434,8 @@ function getTeamTransformations(): PokemonTransformation[] {
|
||||
newAbilityIndex,
|
||||
undefined,
|
||||
);
|
||||
|
||||
transformation.newPokemon.teraType = randSeedInt(MAX_POKEMON_TYPE);
|
||||
}
|
||||
|
||||
return pokemonTransformations;
|
||||
@ -440,6 +445,8 @@ async function doNewTeamPostProcess(transformations: PokemonTransformation[]) {
|
||||
let atLeastOneNewStarter = false;
|
||||
for (const transformation of transformations) {
|
||||
const previousPokemon = transformation.previousPokemon;
|
||||
const oldHpRatio = previousPokemon.getHpRatio(true);
|
||||
const oldStatus = previousPokemon.status;
|
||||
const newPokemon = transformation.newPokemon;
|
||||
const speciesRootForm = newPokemon.species.getRootSpeciesId();
|
||||
|
||||
@ -462,6 +469,19 @@ async function doNewTeamPostProcess(transformations: PokemonTransformation[]) {
|
||||
}
|
||||
|
||||
newPokemon.calculateStats();
|
||||
if (oldHpRatio > 0) {
|
||||
newPokemon.hp = Math.ceil(oldHpRatio * newPokemon.getMaxHp());
|
||||
// Assume that the `status` instance can always safely be transferred to the new pokemon
|
||||
// This is the case (as of version 1.10.4)
|
||||
// Safeguard against COMATOSE here
|
||||
if (!newPokemon.hasAbility(AbilityId.COMATOSE, false, true)) {
|
||||
newPokemon.status = oldStatus;
|
||||
}
|
||||
} else {
|
||||
newPokemon.hp = 0;
|
||||
newPokemon.doSetStatus(StatusEffect.FAINT);
|
||||
}
|
||||
|
||||
await newPokemon.updateInfo();
|
||||
}
|
||||
|
||||
|
@ -20,3 +20,6 @@ export enum PokemonType {
|
||||
FAIRY,
|
||||
STELLAR
|
||||
}
|
||||
|
||||
/** The largest legal value for a {@linkcode PokemonType} (includes Stellar) */
|
||||
export const MAX_POKEMON_TYPE = PokemonType.STELLAR;
|
@ -3243,6 +3243,18 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
rand -= stabMovePool[index++][1];
|
||||
}
|
||||
this.moveset.push(new PokemonMove(stabMovePool[index][0]));
|
||||
} else {
|
||||
// If there are no damaging STAB moves, just force a random damaging move
|
||||
const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS);
|
||||
if (attackMovePool.length) {
|
||||
const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0);
|
||||
let rand = randSeedInt(totalWeight);
|
||||
let index = 0;
|
||||
while (rand > attackMovePool[index][1]) {
|
||||
rand -= attackMovePool[index++][1];
|
||||
}
|
||||
this.moveset.push(new PokemonMove(attackMovePool[index][0], 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
while (baseWeights.length > this.moveset.length && this.moveset.length < 4) {
|
||||
|
@ -179,12 +179,11 @@ export class TurnStartPhase extends FieldPhase {
|
||||
// https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/page-64#post-9244179
|
||||
|
||||
phaseManager.pushNew("WeatherEffectPhase");
|
||||
phaseManager.pushNew("PositionalTagPhase");
|
||||
phaseManager.pushNew("BerryPhase");
|
||||
|
||||
/** Add a new phase to check who should be taking status damage */
|
||||
phaseManager.pushNew("CheckStatusEffectPhase", moveOrder);
|
||||
|
||||
phaseManager.pushNew("PositionalTagPhase");
|
||||
phaseManager.pushNew("TurnEndPhase");
|
||||
|
||||
/*
|
||||
|
@ -1828,9 +1828,9 @@ export class StarterSelectUiHandler extends MessageUiHandler {
|
||||
// The persistent starter data to apply e.g. candy upgrades
|
||||
const persistentStarterData = globalScene.gameData.starterData[this.lastSpecies.speciesId];
|
||||
// The sanitized starter preferences
|
||||
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
|
||||
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] ?? {};
|
||||
// The original starter preferences
|
||||
const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId];
|
||||
const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId] ?? {};
|
||||
|
||||
// this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons
|
||||
if (!this.starterIconsCursorObj.visible) {
|
||||
@ -3408,8 +3408,9 @@ export class StarterSelectUiHandler extends MessageUiHandler {
|
||||
if (species) {
|
||||
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||
const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||
// Bang is correct due to the `?` before variant
|
||||
const variant = this.starterPreferences[species.speciesId]?.variant
|
||||
? (this.starterPreferences[species.speciesId].variant as Variant)
|
||||
? (this.starterPreferences[species.speciesId]!.variant as Variant)
|
||||
: defaultProps.variant;
|
||||
const tint = getVariantTint(variant);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant)).setTint(tint);
|
||||
|
@ -64,7 +64,7 @@ const StarterPrefers_DEFAULT: string = "{}";
|
||||
let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT;
|
||||
|
||||
export interface StarterPreferences {
|
||||
[key: number]: StarterAttributes;
|
||||
[key: number]: StarterAttributes | undefined;
|
||||
}
|
||||
// called on starter selection show once
|
||||
|
||||
@ -74,10 +74,27 @@ export function loadStarterPreferences(): StarterPreferences {
|
||||
localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT),
|
||||
);
|
||||
}
|
||||
// called on starter selection clear, always
|
||||
|
||||
/**
|
||||
* Check if an object has no properties of its own (its shape is `{}`)
|
||||
* @param obj - Object to check
|
||||
* @returns - Whether the object is bare
|
||||
*/
|
||||
export function isBareObject(obj: object): boolean {
|
||||
for (const _ in obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function saveStarterPreferences(prefs: StarterPreferences): void {
|
||||
const pStr: string = JSON.stringify(prefs);
|
||||
// Fastest way to check if an object has any properties (does no allocation)
|
||||
if (isBareObject(prefs)) {
|
||||
console.warn("Refusing to save empty starter preferences");
|
||||
return;
|
||||
}
|
||||
// no reason to store `{}` (for starters not customized)
|
||||
const pStr: string = JSON.stringify(prefs, (_, value) => (isBareObject(value) ? undefined : value));
|
||||
if (pStr !== StarterPrefers_private_latest) {
|
||||
// something changed, store the update
|
||||
localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr);
|
||||
|
@ -175,4 +175,27 @@ describe("Evolution", () => {
|
||||
expect(fourForm.evoFormKey).toBe("four"); // meanwhile, according to the pokemon-forms, the evoFormKey for a 4 family maushold is "four"
|
||||
}
|
||||
});
|
||||
|
||||
it("tyrogue should evolve if move is not in first slot", async () => {
|
||||
game.override
|
||||
.moveset([MoveId.TACKLE, MoveId.RAPID_SPIN, MoveId.LOW_KICK])
|
||||
.enemySpecies(SpeciesId.GOLEM)
|
||||
.enemyMoveset(MoveId.SPLASH)
|
||||
.startingWave(41)
|
||||
.startingLevel(19)
|
||||
.enemyLevel(30);
|
||||
|
||||
await game.classicMode.startBattle([SpeciesId.TYROGUE]);
|
||||
|
||||
const tyrogue = game.field.getPlayerPokemon();
|
||||
|
||||
const golem = game.field.getEnemyPokemon();
|
||||
golem.hp = 1;
|
||||
expect(golem.hp).toBe(1);
|
||||
|
||||
game.move.select(MoveId.TACKLE);
|
||||
await game.phaseInterceptor.to("EndEvolutionPhase");
|
||||
|
||||
expect(tyrogue.species.speciesId).toBe(SpeciesId.HITMONTOP);
|
||||
});
|
||||
});
|
||||
|
@ -59,5 +59,12 @@
|
||||
"outDir": "./build",
|
||||
"noEmit": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"]
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"vitest.workspace.ts",
|
||||
"public/service-worker.js"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user