Prevent Fusing Status Errors (#465)
parent
d170aeeab6
commit
68eca464f7
|
@ -3,7 +3,7 @@
|
||||||
"short_name": "PokéRogue",
|
"short_name": "PokéRogue",
|
||||||
"description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.",
|
"description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.",
|
||||||
"scope": "/",
|
"scope": "/",
|
||||||
"start_url": "https://pokerogue.net",
|
"start_url": "/",
|
||||||
"display": "fullscreen",
|
"display": "fullscreen",
|
||||||
"background_color": "#8c8c8c",
|
"background_color": "#8c8c8c",
|
||||||
"theme_color": "#8c8c8c",
|
"theme_color": "#8c8c8c",
|
||||||
|
|
|
@ -135,3 +135,43 @@ export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect):
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random non-volatile StatusEffect
|
||||||
|
*/
|
||||||
|
export function generateRandomStatusEffect(): StatusEffect {
|
||||||
|
return Utils.randIntRange(1, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random non-volatile StatusEffect between the two provided
|
||||||
|
* @param statusEffectA The first StatusEffect
|
||||||
|
* @param statusEffectA The second StatusEffect
|
||||||
|
*/
|
||||||
|
export function getRandomStatusEffect(statusEffectA: StatusEffect, statusEffectB: StatusEffect): StatusEffect {
|
||||||
|
if (statusEffectA === StatusEffect.NONE || statusEffectA === StatusEffect.FAINT) {
|
||||||
|
return statusEffectB;
|
||||||
|
}
|
||||||
|
if (statusEffectB === StatusEffect.NONE || statusEffectB === StatusEffect.FAINT) {
|
||||||
|
return statusEffectA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils.randIntRange(0, 2) ? statusEffectA : statusEffectB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random non-volatile StatusEffect between the two provided
|
||||||
|
* @param statusA The first Status
|
||||||
|
* @param statusB The second Status
|
||||||
|
*/
|
||||||
|
export function getRandomStatus(statusA: Status, statusB: Status): Status {
|
||||||
|
if (statusA === undefined || statusA.effect === StatusEffect.NONE || statusA.effect === StatusEffect.FAINT) {
|
||||||
|
return statusB;
|
||||||
|
}
|
||||||
|
if (statusB === undefined || statusB.effect === StatusEffect.NONE || statusB.effect === StatusEffect.FAINT) {
|
||||||
|
return statusA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Utils.randIntRange(0, 2) ? statusA : statusB;
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBooste
|
||||||
import { PokeballType } from '../data/pokeball';
|
import { PokeballType } from '../data/pokeball';
|
||||||
import { Gender } from '../data/gender';
|
import { Gender } from '../data/gender';
|
||||||
import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims';
|
import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims';
|
||||||
import { Status, StatusEffect } from '../data/status-effect';
|
import { Status, StatusEffect, getRandomStatus } from '../data/status-effect';
|
||||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions';
|
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions';
|
||||||
import { reverseCompatibleTms, tmSpecies } from '../data/tms';
|
import { reverseCompatibleTms, tmSpecies } from '../data/tms';
|
||||||
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases';
|
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases';
|
||||||
|
@ -2542,6 +2542,10 @@ export class PlayerPokemon extends Pokemon {
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Promise to fuse two PlayerPokemon together
|
||||||
|
* @param pokemon The PlayerPokemon to fuse to this one
|
||||||
|
*/
|
||||||
fuse(pokemon: PlayerPokemon): Promise<void> {
|
fuse(pokemon: PlayerPokemon): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
this.fusionSpecies = pokemon.species;
|
this.fusionSpecies = pokemon.species;
|
||||||
|
@ -2555,8 +2559,25 @@ export class PlayerPokemon extends Pokemon {
|
||||||
this.scene.validateAchv(achvs.SPLICE);
|
this.scene.validateAchv(achvs.SPLICE);
|
||||||
this.scene.gameData.gameStats.pokemonFused++;
|
this.scene.gameData.gameStats.pokemonFused++;
|
||||||
|
|
||||||
|
// Store the average HP% that each Pokemon has
|
||||||
|
const newHpPercent = ((pokemon.hp / pokemon.stats[Stat.HP]) + (this.hp / this.stats[Stat.HP])) / 2;
|
||||||
|
|
||||||
this.generateName();
|
this.generateName();
|
||||||
this.calculateStats();
|
this.calculateStats();
|
||||||
|
|
||||||
|
// Set this Pokemon's HP to the average % of both fusion components
|
||||||
|
this.hp = Math.round(this.stats[Stat.HP] * newHpPercent);
|
||||||
|
if (!this.isFainted()) {
|
||||||
|
// If this Pokemon hasn't fainted, make sure the HP wasn't set over the new maximum
|
||||||
|
this.hp = Math.min(this.hp, this.stats[Stat.HP]);
|
||||||
|
this.status = getRandomStatus(this.status, pokemon.status); // Get a random valid status between the two
|
||||||
|
}
|
||||||
|
else if (!pokemon.isFainted()) {
|
||||||
|
// If this Pokemon fainted but the other hasn't, make sure the HP wasn't set to zero
|
||||||
|
this.hp = Math.max(this.hp, 1);
|
||||||
|
this.status = pokemon.status; // Inherit the other Pokemon's status
|
||||||
|
}
|
||||||
|
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
this.updateInfo(true);
|
this.updateInfo(true);
|
||||||
const fusedPartyMemberIndex = this.scene.getParty().indexOf(pokemon);
|
const fusedPartyMemberIndex = this.scene.getParty().indexOf(pokemon);
|
||||||
|
|
|
@ -1179,14 +1179,25 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
||||||
this.preSummon();
|
this.preSummon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends out a Pokemon before the battle begins and shows the appropriate messages
|
||||||
|
*/
|
||||||
preSummon(): void {
|
preSummon(): void {
|
||||||
const partyMember = this.getPokemon();
|
const partyMember = this.getPokemon();
|
||||||
|
// If the Pokemon about to be sent out is fainted, switch to the first non-fainted Pokemon
|
||||||
if (partyMember.isFainted()) {
|
if (partyMember.isFainted()) {
|
||||||
|
console.warn("The Pokemon about to be sent out is fainted. Attempting to resolve...");
|
||||||
const party = this.getParty();
|
const party = this.getParty();
|
||||||
const nonFaintedIndex = party.slice(this.partyMemberIndex).findIndex(p => !p.isFainted()) + this.partyMemberIndex;
|
|
||||||
const nonFaintedPartyMember = party[nonFaintedIndex];
|
const nonFaintedIndex = party.findIndex(x => !x.isFainted()); // Find the first non-fainted Pokemon index
|
||||||
party[nonFaintedIndex] = partyMember;
|
if (nonFaintedIndex === -1) {
|
||||||
party[this.partyMemberIndex] = nonFaintedPartyMember;
|
console.error("Party Details:\n", party);
|
||||||
|
throw new Error("All available Pokemon were fainted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swaps the fainted Pokemon and the first non-fainted Pokemon in the party
|
||||||
|
[party[this.partyMemberIndex], party[nonFaintedIndex]] = [party[nonFaintedIndex], party[this.partyMemberIndex]];
|
||||||
|
console.warn("Swapped %s %O with %s %O", partyMember?.name, partyMember, party[0]?.name, party[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.player) {
|
if (this.player) {
|
||||||
|
|
10
src/utils.ts
10
src/utils.ts
|
@ -62,6 +62,11 @@ export function padInt(value: integer, length: integer, padWith?: string): strin
|
||||||
return valueStr;
|
return valueStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random integer between min and min + range
|
||||||
|
* @param range The amount of possible numbers
|
||||||
|
* @param min The starting number
|
||||||
|
*/
|
||||||
export function randInt(range: integer, min: integer = 0): integer {
|
export function randInt(range: integer, min: integer = 0): integer {
|
||||||
if (range === 1)
|
if (range === 1)
|
||||||
return min;
|
return min;
|
||||||
|
@ -74,6 +79,11 @@ export function randSeedInt(range: integer, min: integer = 0): integer {
|
||||||
return Phaser.Math.RND.integerInRange(min, (range - 1) + min);
|
return Phaser.Math.RND.integerInRange(min, (range - 1) + min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random integer between min and max (non-inclusive)
|
||||||
|
* @param min The lowest number
|
||||||
|
* @param max The highest number
|
||||||
|
*/
|
||||||
export function randIntRange(min: integer, max: integer): integer {
|
export function randIntRange(min: integer, max: integer): integer {
|
||||||
return randInt(max - min, min);
|
return randInt(max - min, min);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue