Merge branch 'main' into main

This commit is contained in:
lucfd 2024-04-16 14:36:15 -04:00 committed by GitHub
commit 8cc5d2e947
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 5144 additions and 1125 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"version": "1.0.0", "version": "1.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"version": "1.0.0", "version": "1.0.1",
"dependencies": { "dependencies": {
"@material/material-color-utilities": "^0.2.7", "@material/material-color-utilities": "^0.2.7",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",

View File

@ -1653,8 +1653,9 @@ export default class BattleScene extends SceneBase {
return Math.floor(moneyValue / 10) * 10; return Math.floor(moneyValue / 10) * 10;
} }
addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise<void> { addModifier(modifier: Modifier, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise<boolean> {
return new Promise(resolve => { return new Promise(resolve => {
let success = false;
const soundName = modifier.type.soundName; const soundName = modifier.type.soundName;
this.validateAchvs(ModifierAchv, modifier); this.validateAchvs(ModifierAchv, modifier);
const modifiersToRemove: PersistentModifier[] = []; const modifiersToRemove: PersistentModifier[] = [];
@ -1664,20 +1665,20 @@ export default class BattleScene extends SceneBase {
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId))); modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId)));
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) { if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) {
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier)
modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]); success = modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]);
if (playSound && !this.sound.get(soundName)) if (playSound && !this.sound.get(soundName))
this.playSound(soundName); this.playSound(soundName);
} else if (!virtual) { } else if (!virtual) {
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier); const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
this.queueMessage(`The stack for this item is full.\n You will receive ${defaultModifierType.name} instead.`, null, true); this.queueMessage(`The stack for this item is full.\n You will receive ${defaultModifierType.name} instead.`, null, true);
return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(() => resolve()); return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(success => resolve(success));
} }
for (let rm of modifiersToRemove) for (let rm of modifiersToRemove)
this.removeModifier(rm); this.removeModifier(rm);
if (!ignoreUpdate && !virtual) if (!ignoreUpdate && !virtual)
return this.updateModifiers(true, instant).then(() => resolve()); return this.updateModifiers(true, instant).then(() => resolve(success));
} else if (modifier instanceof ConsumableModifier) { } else if (modifier instanceof ConsumableModifier) {
if (playSound && !this.sound.get(soundName)) if (playSound && !this.sound.get(soundName))
this.playSound(soundName); this.playSound(soundName);
@ -1700,19 +1701,26 @@ export default class BattleScene extends SceneBase {
if (modifier.shouldApply(args)) { if (modifier.shouldApply(args)) {
const result = modifier.apply(args); const result = modifier.apply(args);
if (result instanceof Promise) if (result instanceof Promise)
modifierPromises.push(result); modifierPromises.push(result.then(s => success ||= s));
else
success ||= result;
} }
} }
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve()); return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
} else { } else {
const args = [ this ]; const args = [ this ];
if (modifier.shouldApply(args)) if (modifier.shouldApply(args)) {
modifier.apply(args); const result = modifier.apply(args);
if (result instanceof Promise) {
return result.then(success => resolve(success));
} else
success ||= result;
}
} }
} }
resolve(); resolve(success);
}); });
} }

View File

@ -212,6 +212,8 @@ export default class Battle {
} }
randSeedInt(scene: BattleScene, range: integer, min: integer = 0): integer { randSeedInt(scene: BattleScene, range: integer, min: integer = 0): integer {
if (range <= 1)
return min;
let ret: integer; let ret: integer;
const tempRngCounter = scene.rngCounter; const tempRngCounter = scene.rngCounter;
const tempSeedOverride = scene.rngSeedOverride; const tempSeedOverride = scene.rngSeedOverride;

View File

@ -2222,7 +2222,7 @@ export function initAbilities() {
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.LEVITATE, "Levitate", "By floating in the air, the Pokémon receives full immunity to all Ground-type moves.", 3) new Ability(Abilities.LEVITATE, "Levitate", "By floating in the air, the Pokémon receives full immunity to all Ground-type moves.", 3)
.attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY)) .attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY) && !pokemon.getTag(BattlerTagType.GROUNDED))
.ignorable(), .ignorable(),
new Ability(Abilities.EFFECT_SPORE, "Effect Spore", "Contact with the Pokémon may inflict poison, sleep, or paralysis on its attacker.", 3) new Ability(Abilities.EFFECT_SPORE, "Effect Spore", "Contact with the Pokémon may inflict poison, sleep, or paralysis on its attacker.", 3)
.attr(PostDefendContactApplyStatusEffectAbAttr, 10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP), .attr(PostDefendContactApplyStatusEffectAbAttr, 10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP),

View File

@ -1094,6 +1094,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove); return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
case BattlerTagType.IGNORE_FLYING: case BattlerTagType.IGNORE_FLYING:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove); return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
case BattlerTagType.GROUNDED:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount - 1, sourceMove);
case BattlerTagType.SALT_CURED: case BattlerTagType.SALT_CURED:
return new SaltCuredTag(sourceId); return new SaltCuredTag(sourceId);
case BattlerTagType.NONE: case BattlerTagType.NONE:
@ -1101,3 +1103,4 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
} }
} }

View File

@ -47,5 +47,6 @@ export enum BattlerTagType {
IGNORE_ACCURACY = "IGNORE_ACCURACY", IGNORE_ACCURACY = "IGNORE_ACCURACY",
BYPASS_SLEEP = "BYPASS_SLEEP", BYPASS_SLEEP = "BYPASS_SLEEP",
IGNORE_FLYING = "IGNORE_FLYING", IGNORE_FLYING = "IGNORE_FLYING",
GROUNDED = "GROUNDED",
SALT_CURED = "SALT_CURED" SALT_CURED = "SALT_CURED"
} }

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ import { Biome } from "../data/enums/biome";
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability'; import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from '../data/ability';
import { Abilities } from "#app/data/enums/abilities"; import { Abilities } from "#app/data/enums/abilities";
import PokemonData from '../system/pokemon-data'; import PokemonData from '../system/pokemon-data';
import { BattlerIndex } from '../battle'; import Battle, { BattlerIndex } from '../battle';
import { BattleSpec } from "../enums/battle-spec"; import { BattleSpec } from "../enums/battle-spec";
import { Mode } from '../ui/ui'; import { Mode } from '../ui/ui';
import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler'; import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler';
@ -536,7 +536,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.getTag(BattlerTagType.SLOW_START)) if (this.getTag(BattlerTagType.SLOW_START))
ret >>= 1; ret >>= 1;
if (this.status && this.status.effect === StatusEffect.PARALYSIS) if (this.status && this.status.effect === StatusEffect.PARALYSIS)
ret >>= 2; ret >>= 1;
break; break;
} }
@ -694,7 +694,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
if (forDefend && (this.getTag(BattlerTagType.IGNORE_FLYING) || this.scene.arena.getTag(ArenaTagType.GRAVITY))) { if (forDefend && (this.getTag(BattlerTagType.IGNORE_FLYING) || this.scene.arena.getTag(ArenaTagType.GRAVITY) || this.getTag(BattlerTagType.GROUNDED))) {
const flyingIndex = types.indexOf(Type.FLYING); const flyingIndex = types.indexOf(Type.FLYING);
if (flyingIndex > -1) if (flyingIndex > -1)
types.splice(flyingIndex, 1); types.splice(flyingIndex, 1);
@ -730,7 +730,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId)) while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId))
starterSpeciesId = pokemonPrevolutions[starterSpeciesId]; starterSpeciesId = pokemonPrevolutions[starterSpeciesId];
return allAbilities[starterPassiveAbilities[starterSpeciesId]]; return allAbilities[starterPassiveAbilities[starterSpeciesId]];
} }
hasPassive(): boolean { hasPassive(): boolean {
return this.passive || this.isBoss(); return this.passive || this.isBoss();
@ -1213,7 +1213,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
if (source.getTag(BattlerTagType.CRIT_BOOST)) if (source.getTag(BattlerTagType.CRIT_BOOST))
critLevel.value += 2; critLevel.value += 2;
const critChance = Math.ceil(16 / Math.pow(2, critLevel.value)); const critChance = [24, 8, 2, 1][Math.max(0, Math.min(critLevel.value, 3))];
isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance)); isCritical = !source.getTag(BattlerTagType.NO_CRIT) && (critChance === 1 || !this.scene.randBattleSeedInt(critChance));
if (isCritical) { if (isCritical) {
const blockCrit = new Utils.BooleanHolder(false); const blockCrit = new Utils.BooleanHolder(false);

3678
src/locales/en/move.ts Normal file

File diff suppressed because it is too large Load Diff

6
src/locales/fr/move.ts Normal file
View File

@ -0,0 +1,6 @@
export const move = {
"ember": {
name: "Flammèche",
effect: "Flammèche inflige des dégâts et a des chances de brûler le Pokémon adverse."
},
} as const;

View File

@ -1001,9 +1001,11 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
if (this.fainted || this.healStatus) if (this.fainted || this.healStatus)
pokemon.resetStatus(); pokemon.resetStatus();
pokemon.hp = Math.min(pokemon.hp + Math.max(Math.ceil(Math.max(Math.floor((this.restorePercent * 0.01) * pokemon.getMaxHp()), restorePoints)), 1), pokemon.getMaxHp()); pokemon.hp = Math.min(pokemon.hp + Math.max(Math.ceil(Math.max(Math.floor((this.restorePercent * 0.01) * pokemon.getMaxHp()), restorePoints)), 1), pokemon.getMaxHp());
return true;
} }
return true; return false;
} }
} }

View File

@ -4162,10 +4162,15 @@ export class SelectModifierPhase extends BattlePhase {
const applyModifier = (modifier: Modifier, playSound: boolean = false) => { const applyModifier = (modifier: Modifier, playSound: boolean = false) => {
const result = this.scene.addModifier(modifier, false, playSound); const result = this.scene.addModifier(modifier, false, playSound);
if (cost) { if (cost) {
this.scene.money -= cost; result.then(success => {
this.scene.updateMoneyText(); if (success) {
this.scene.playSound('buy'); this.scene.money -= cost;
(this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText(); this.scene.updateMoneyText();
this.scene.playSound('buy');
(this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText();
} else
this.scene.ui.playError();
});
} else { } else {
const doEnd = () => { const doEnd = () => {
this.scene.ui.clearText(); this.scene.ui.clearText();

View File

@ -2,6 +2,9 @@ import i18next from 'i18next';
import { menu as enMenu } from '../locales/en/menu'; import { menu as enMenu } from '../locales/en/menu';
import { menu as itMenu } from '../locales/it/menu'; import { menu as itMenu } from '../locales/it/menu';
import { move as enMove } from '../locales/en/move';
import { move as frMove } from '../locales/fr/move';
const DEFAULT_LANGUAGE_OVERRIDE = ''; const DEFAULT_LANGUAGE_OVERRIDE = '';
/** /**
@ -26,9 +29,13 @@ i18next.init({
resources: { resources: {
en: { en: {
menu: enMenu, menu: enMenu,
move: enMove,
}, },
it: { it: {
menu: itMenu, menu: itMenu,
},
fr: {
move: frMove,
} }
}, },
}); });
@ -38,6 +45,7 @@ declare module 'i18next' {
interface CustomTypeOptions { interface CustomTypeOptions {
resources: { resources: {
menu: typeof enMenu; menu: typeof enMenu;
move: typeof enMove;
}; };
} }
} }