Merge branch 'main' into chargewind

This commit is contained in:
Temps Ray 2024-04-16 20:43:58 -04:00
commit 3a110989ef
29 changed files with 8011 additions and 1346 deletions

View File

@ -55,6 +55,9 @@ Check out our [Trello Board](https://trello.com/b/z10B703R/pokerogue-board) to s
- GAMEFREAK
- LJ Birdman
### 🎨 Pagefault Games Intro
- Spectremint
### 🎨 Game Logo
- Gonstar (Paid Commission)

4
package-lock.json generated
View File

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

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -128,6 +128,7 @@ export default class BattleScene extends SceneBase {
public moveAnimations: boolean = true;
public hpBarSpeed: integer = 0;
public fusionPaletteSwaps: boolean = true;
public gamepadSupport: boolean = true;
public enableTouchControls: boolean = false;
public enableVibration: boolean = false;
@ -198,6 +199,26 @@ export default class BattleScene extends SceneBase {
// (i.e. by holding down a button) at a time
private movementButtonLock: Button;
// using a dualshock controller as a map
private gamepadKeyConfig = {
[Button.UP]: 12, // up
[Button.DOWN]: 13, // down
[Button.LEFT]: 14, // left
[Button.RIGHT]: 15, // right
[Button.SUBMIT]: 17, // touchpad
[Button.ACTION]: 0, // X
[Button.CANCEL]: 1, // O
[Button.MENU]: 9, // options
[Button.CYCLE_SHINY]: 5, // RB
[Button.CYCLE_FORM]: 4, // LB
[Button.CYCLE_GENDER]: 6, // LT
[Button.CYCLE_ABILITY]: 7, // RT
[Button.CYCLE_NATURE]: 2, // square
[Button.SPEED_UP]: 10, // L3
[Button.SLOW_DOWN]: 11 // R3
};
public gamepadButtonStates: boolean[] = new Array(17).fill(false);
public rngCounter: integer = 0;
public rngSeedOverride: string = '';
public rngOffset: integer = 0;
@ -1225,7 +1246,6 @@ export default class BattleScene extends SceneBase {
case Mode.SAVE_SLOT:
case Mode.PARTY:
case Mode.SUMMARY:
case Mode.BIOME_SELECT:
case Mode.STARTER_SELECT:
case Mode.CONFIRM:
case Mode.OPTION_SELECT:
@ -1245,14 +1265,19 @@ export default class BattleScene extends SceneBase {
} else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
if (this.buttonJustPressed(Button.CYCLE_SHINY)) {
inputSuccess = this.ui.processInput(Button.CYCLE_SHINY);
this.setLastProcessedMovementTime(Button.CYCLE_SHINY);
} else if (this.buttonJustPressed(Button.CYCLE_FORM)) {
inputSuccess = this.ui.processInput(Button.CYCLE_FORM);
this.setLastProcessedMovementTime(Button.CYCLE_FORM);
} else if (this.buttonJustPressed(Button.CYCLE_GENDER)) {
inputSuccess = this.ui.processInput(Button.CYCLE_GENDER);
this.setLastProcessedMovementTime(Button.CYCLE_GENDER);
} else if (this.buttonJustPressed(Button.CYCLE_ABILITY)) {
inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
this.setLastProcessedMovementTime(Button.CYCLE_ABILITY);
} else if (this.buttonJustPressed(Button.CYCLE_NATURE)) {
inputSuccess = this.ui.processInput(Button.CYCLE_NATURE);
this.setLastProcessedMovementTime(Button.CYCLE_NATURE);
} else
return;
} else if (this.buttonJustPressed(Button.SPEED_UP)) {
@ -1273,8 +1298,29 @@ export default class BattleScene extends SceneBase {
navigator.vibrate(vibrationLength || 10);
}
/**
* gamepadButtonJustDown returns true if @param button has just been pressed down
* or not. It will only return true once, until the key is released and pressed down
* again.
*/
gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button) : boolean {
if (!button || !this.gamepadSupport)
return false;
let ret = false;
if (button.pressed) {
if (!this.gamepadButtonStates[button.index])
ret = true;
this.gamepadButtonStates[button.index] = true;
} else
this.gamepadButtonStates[button.index] = false;
return ret;
}
buttonJustPressed(button: Button): boolean {
return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k));
const gamepad = this.input.gamepad?.gamepads[0];
return this.buttonKeys[button].some(k => Phaser.Input.Keyboard.JustDown(k)) || this.gamepadButtonJustDown(gamepad?.buttons[this.gamepadKeyConfig[button]]);
}
/**
@ -1286,7 +1332,7 @@ export default class BattleScene extends SceneBase {
if (this.movementButtonLock !== null && this.movementButtonLock !== button) {
return false;
}
if (this.buttonKeys[button].every(k => k.isUp)) {
if (this.buttonKeys[button].every(k => k.isUp) && this.gamepadButtonStates.every(b => b == false)) {
this.movementButtonLock = null;
return false;
}
@ -1606,8 +1652,9 @@ export default class BattleScene extends SceneBase {
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 => {
let success = false;
const soundName = modifier.type.soundName;
this.validateAchvs(ModifierAchv, modifier);
const modifiersToRemove: PersistentModifier[] = [];
@ -1617,20 +1664,20 @@ export default class BattleScene extends SceneBase {
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId)));
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) {
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))
this.playSound(soundName);
} else if (!virtual) {
const defaultModifierType = getDefaultModifierTypeForTier(modifier.type.tier);
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)
this.removeModifier(rm);
if (!ignoreUpdate && !virtual)
return this.updateModifiers(true, instant).then(() => resolve());
return this.updateModifiers(true, instant).then(() => resolve(success));
} else if (modifier instanceof ConsumableModifier) {
if (playSound && !this.sound.get(soundName))
this.playSound(soundName);
@ -1653,19 +1700,26 @@ export default class BattleScene extends SceneBase {
if (modifier.shouldApply(args)) {
const result = modifier.apply(args);
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 {
const args = [ this ];
if (modifier.shouldApply(args))
modifier.apply(args);
if (modifier.shouldApply(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 {
if (range <= 1)
return min;
let ret: integer;
const tempRngCounter = scene.rngCounter;
const tempSeedOverride = scene.rngSeedOverride;

View File

@ -386,6 +386,20 @@ export class PostDefendAbAttr extends AbAttr {
}
}
export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const attackPriority = new Utils.IntegerHolder(move.getMove().priority);
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority);
if(attackPriority.value > 0 && !move.getMove().isMultiTarget()) {
cancelled.value = true;
return true;
}
return false;
}
}
export class PostStatChangeAbAttr extends AbAttr {
applyPostStatChange(pokemon: Pokemon, statsChanged: BattleStat[], levelChanged: integer, selfTarget: boolean, args: any[]): boolean | Promise<boolean> {
return false;
@ -1180,6 +1194,8 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr {
export class TraceAbAttr extends PostSummonAbAttr {
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
const targets = pokemon.getOpponents();
if (!targets.length)
return false;
let target: Pokemon;
if (targets.length > 1)
pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex);
@ -2245,7 +2261,7 @@ export function initAbilities() {
.attr(UnswappableAbilityAbAttr)
.ignorable(),
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(),
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),
@ -2382,10 +2398,10 @@ export function initAbilities() {
.attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75),
new Ability(Abilities.STEADFAST, "Steadfast", "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", 4)
.attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1),
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Boosts evasiveness in a hailstorm.", 4)
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Boosts the Pokémon's evasiveness in snow.", 4)
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
.condition(getWeatherCondition(WeatherType.HAIL))
.condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW))
.ignorable(),
new Ability(Abilities.GLUTTONY, "Gluttony", "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", 4)
.attr(ReduceBerryUseThresholdAbAttr),
@ -2463,14 +2479,15 @@ export function initAbilities() {
.attr(RedirectTypeMoveAbAttr, Type.WATER)
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1)
.ignorable(),
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in a hailstorm.", 4)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL),
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in snow.", 4)
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW),
new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
.ignorable(),
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon summons a hailstorm when it enters a battle.", 4)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HAIL)
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HAIL),
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon makes it snow when it enters a battle.", 4)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW)
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SNOW),
new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The Pokémon may gather Honey after a battle.", 4),
new Ability(Abilities.FRISK, "Frisk (N)", "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", 4),
new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4)
@ -2676,9 +2693,9 @@ export function initAbilities() {
new Ability(Abilities.STEELWORKER, "Steelworker", "Powers up Steel-type moves.", 7)
.attr(MoveTypePowerBoostAbAttr, Type.STEEL),
new Ability(Abilities.BERSERK, "Berserk (N)", "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", 7),
new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the Pokémon's Speed stat in a hailstorm.", 7)
new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the Pokémon's Speed stat in snow.", 7)
.attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
.condition(getWeatherCondition(WeatherType.HAIL)),
.condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW)),
new Ability(Abilities.LONG_REACH, "Long Reach", "The Pokémon uses its moves without making contact with the target.", 7)
.attr(IgnoreContactAbAttr),
new Ability(Abilities.LIQUID_VOICE, "Liquid Voice", "All sound-based moves become Water-type moves.", 7)
@ -2715,7 +2732,8 @@ export function initAbilities() {
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr),
new Ability(Abilities.QUEENLY_MAJESTY, "Queenly Majesty (N)", "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", 7)
new Ability(Abilities.QUEENLY_MAJESTY, "Queenly Majesty", "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", 7)
.attr(FieldPriorityMoveImmunityAbAttr)
.ignorable(),
new Ability(Abilities.INNARDS_OUT, "Innards Out (N)", "Damages the attacker landing the finishing hit by the amount equal to its last HP.", 7),
new Ability(Abilities.DANCER, "Dancer (N)", "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", 7),
@ -2724,7 +2742,8 @@ export function initAbilities() {
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5)
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.type === Type.FIRE, 2)
.ignorable(),
new Ability(Abilities.DAZZLING, "Dazzling (N)", "Surprises the opposing Pokémon, making it unable to attack using priority moves.", 7)
new Ability(Abilities.DAZZLING, "Dazzling", "Surprises the opposing Pokémon, making it unable to attack using priority moves.", 7)
.attr(FieldPriorityMoveImmunityAbAttr)
.ignorable(),
new Ability(Abilities.SOUL_HEART, "Soul-Heart", "Boosts its Sp. Atk stat every time a Pokémon faints.", 7)
.attr(PostKnockOutStatChangeAbAttr, BattleStat.SPATK, 1),
@ -2926,7 +2945,8 @@ export function initAbilities() {
new Ability(Abilities.SUPREME_OVERLORD, "Supreme Overlord (N)", "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", 9),
new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9),
new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris (N)", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9),
new Ability(Abilities.ARMOR_TAIL, "Armor Tail (N)", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9)
new Ability(Abilities.ARMOR_TAIL, "Armor Tail", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9)
.attr(FieldPriorityMoveImmunityAbAttr)
.ignorable(),
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
.attr(TypeImmunityHealAbAttr, Type.GROUND)

View File

@ -89,6 +89,7 @@ export enum CommonAnim {
RAIN,
SANDSTORM,
HAIL,
SNOW,
WIND,
HEAVY_RAIN,
HARSH_SUN,

View File

@ -1081,6 +1081,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC);
case BattlerTagType.FLYING:
case BattlerTagType.UNDERGROUND:
case BattlerTagType.UNDERWATER:
case BattlerTagType.HIDDEN:
return new HideSpriteTag(tagType, turnCount, sourceMove);
case BattlerTagType.FIRE_BOOST:
@ -1097,6 +1098,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
case BattlerTagType.IGNORE_FLYING:
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:
return new SaltCuredTag(sourceId);
case BattlerTagType.CHARGED:
@ -1106,3 +1109,4 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
}
}

View File

@ -44,7 +44,7 @@ export const biomeLinks: BiomeLinks = {
[Biome.SEA]: [ Biome.SEABED, Biome.ICE_CAVE ],
[Biome.SWAMP]: [ Biome.GRAVEYARD, Biome.TALL_GRASS ],
[Biome.BEACH]: [ Biome.SEA, [ Biome.ISLAND, 4 ] ],
[Biome.LAKE]: [ Biome.BEACH, Biome.SWAMP ],
[Biome.LAKE]: [ Biome.BEACH, Biome.SWAMP, Biome.CONSTRUCTION_SITE ],
[Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 4 ] ],
[Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 3 ] ],
[Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ],
@ -66,9 +66,9 @@ export const biomeLinks: BiomeLinks = {
[Biome.FAIRY_CAVE]: [ Biome.ICE_CAVE, [ Biome.SPACE, 3 ] ],
[Biome.TEMPLE]: [ Biome.SWAMP, [ Biome.RUINS, 3 ] ],
[Biome.METROPOLIS]: Biome.SLUM,
[Biome.SNOWY_FOREST]: Biome.LAKE,
[Biome.SNOWY_FOREST]: [ Biome.FOREST, Biome.LAKE, Biome.MOUNTAIN ],
[Biome.ISLAND]: Biome.SEA,
[Biome.LABORATORY]: Biome.METROPOLIS
[Biome.LABORATORY]: Biome.CONSTRUCTION_SITE
};
export const biomeDepths: BiomeDepths = {};

View File

@ -38,6 +38,7 @@ export enum BattlerTagType {
QUARK_DRIVE = "QUARK_DRIVE",
FLYING = "FLYING",
UNDERGROUND = "UNDERGROUND",
UNDERWATER = "UNDERWATER",
HIDDEN = "HIDDEN",
FIRE_BOOST = "FIRE_BOOST",
CRIT_BOOST = "CRIT_BOOST",
@ -47,5 +48,6 @@ export enum BattlerTagType {
BYPASS_SLEEP = "BYPASS_SLEEP",
IGNORE_FLYING = "IGNORE_FLYING",
SALT_CURED = "SALT_CURED",
CHARGED = "CHARGED"
CHARGED = "CHARGED",
GROUNDED = "GROUNDED"
}

File diff suppressed because it is too large Load Diff

View File

@ -968,8 +968,8 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.COSMOEM, 43, null, null)
],
[Species.COSMOEM]: [
new SpeciesEvolution(Species.SOLGALEO, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.biomeType !== Biome.SPACE && p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), null),
new SpeciesEvolution(Species.LUNALA, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.biomeType !== Biome.SPACE && p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), null)
new SpeciesEvolution(Species.SOLGALEO, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), null),
new SpeciesEvolution(Species.LUNALA, 53, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), null)
],
[Species.MELTAN]: [
new SpeciesEvolution(Species.MELMETAL, 48, null, null)

View File

@ -15,6 +15,7 @@ splashMessages.push(...[
'Now with 33% More Salt!',
'Infinite Fusion at Home!',
'Broken Egg Moves!',
'Magnificent!',
'Mubstitute!',
'That\'s Crazy!',
'Orance Juice!',

View File

@ -14,6 +14,7 @@ export enum WeatherType {
RAIN,
SANDSTORM,
HAIL,
SNOW,
FOG,
HEAVY_RAIN,
HARSH_SUN,
@ -127,6 +128,8 @@ export function getWeatherStartMessage(weatherType: WeatherType): string {
return 'A sandstorm brewed!';
case WeatherType.HAIL:
return 'It started to hail!';
case WeatherType.SNOW:
return 'It started to snow!';
case WeatherType.FOG:
return 'A thick fog emerged!'
case WeatherType.HEAVY_RAIN:
@ -150,6 +153,8 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string {
return 'The sandstorm rages.';
case WeatherType.HAIL:
return 'Hail continues to fall.';
case WeatherType.SNOW:
return 'The snow is falling down.';
case WeatherType.FOG:
return 'The fog continues.';
case WeatherType.HEAVY_RAIN:
@ -184,6 +189,8 @@ export function getWeatherClearMessage(weatherType: WeatherType): string {
return 'The sandstorm subsided.';
case WeatherType.HAIL:
return 'The hail stopped.';
case WeatherType.SNOW:
return 'The snow stopped.';
case WeatherType.FOG:
return 'The fog disappeared.'
case WeatherType.HEAVY_RAIN:
@ -292,11 +299,6 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
{ weatherType: WeatherType.RAIN, weight: 1 }
];
break;
case Biome.MOUNTAIN:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 1 }
];
break;
case Biome.BADLANDS:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 8 },
@ -314,6 +316,8 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
break;
case Biome.ICE_CAVE:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 3 },
{ weatherType: WeatherType.SNOW, weight: 4 },
{ weatherType: WeatherType.HAIL, weight: 1 }
];
break;
@ -334,20 +338,25 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
{ weatherType: WeatherType.FOG, weight: 1 }
];
break;
case Biome.RUINS:
case Biome.JUNGLE:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 4 }
{ weatherType: WeatherType.NONE, weight: 8 },
{ weatherType: WeatherType.RAIN, weight: 2 }
];
break;
case Biome.WASTELAND:
case Biome.SNOWY_FOREST:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 4 }
{ weatherType: WeatherType.SNOW, weight: 7 },
{ weatherType: WeatherType.HAIL, weight: 1 }
];
break;
case Biome.ABYSS:
case Biome.ISLAND:
weatherPool = [
{ weatherType: WeatherType.NONE, weight: 4 }
{ weatherType: WeatherType.NONE, weight: 5 },
{ weatherType: WeatherType.RAIN, weight: 1 },
];
if (hasSun)
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
break;
}

View File

@ -25,10 +25,10 @@ import { TempBattleStat } from '../data/temp-battle-stat';
import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag';
import { ArenaTagType } from "../data/enums/arena-tag-type";
import { Biome } from "../data/enums/biome";
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, 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 PokemonData from '../system/pokemon-data';
import { BattlerIndex } from '../battle';
import Battle, { BattlerIndex } from '../battle';
import { BattleSpec } from "../enums/battle-spec";
import { Mode } from '../ui/ui';
import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler';
@ -523,6 +523,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
ret >>= 1;
break;
case Stat.DEF:
if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW)
ret *= 1.5;
break;
case Stat.SPATK:
break;
@ -534,7 +536,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.getTag(BattlerTagType.SLOW_START))
ret >>= 1;
if (this.status && this.status.effect === StatusEffect.PARALYSIS)
ret >>= 2;
ret >>= 1;
break;
}
@ -692,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);
if (flyingIndex > -1)
types.splice(flyingIndex, 1);
@ -1130,6 +1132,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let result: HitResult;
const move = battlerMove.getMove();
let damage = new Utils.NumberHolder(0);
const defendingSidePlayField = this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField();
const variableCategory = new Utils.IntegerHolder(move.category);
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
@ -1172,8 +1175,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
if (!cancelled.value)
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
}
if (cancelled.value)
result = HitResult.NO_EFFECT;
@ -1213,7 +1218,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
if (source.getTag(BattlerTagType.CRIT_BOOST))
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));
if (isCritical) {
const blockCrit = new Utils.BooleanHolder(false);
@ -1299,6 +1304,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage);
if (power.value === 0) {
damage.value = 0;
}
console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef);
if (damage.value) {
@ -1349,8 +1358,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
case MoveCategory.STATUS:
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
if (!cancelled.value)
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, battlerMove, cancelled, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
}
if (!typeMultiplier.value)
this.scene.queueMessage(`It doesn\'t affect ${this.name}!`);
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;

View File

@ -6,6 +6,7 @@ import { getBiomeHasProps } from "./field/arena";
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
import { SceneBase } from "./scene-base";
import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
import { isMobile } from "./touch-controls";
import * as Utils from "./utils";
export class LoadingScene extends SceneBase {
@ -23,6 +24,9 @@ export class LoadingScene extends SceneBase {
this.load['cacheBuster'] = buildIdMatch[1];
}
if (!isMobile())
this.load.video('intro_dark', 'images/intro_dark.mp4', true);
this.loadImage('loading_bg', 'arenas');
this.loadImage('logo', '');
@ -250,6 +254,10 @@ export class LoadingScene extends SceneBase {
}
loadLoadingScreen() {
const mobile = isMobile();
const loadingGraphics: any[] = [];
const bg = this.add.image(0, 0, '');
bg.setOrigin(0, 0);
bg.setScale(6);
@ -294,6 +302,10 @@ export class LoadingScene extends SceneBase {
});
assetText.setOrigin(0.5, 0.5);
const intro = this.add.video(0, 0);
intro.setOrigin(0, 0);
intro.setScale(3);
this.load.on("progress", (value: string) => {
const parsedValue = parseFloat(value);
percentText.setText(`${Math.floor(parsedValue * 100)}%`);
@ -306,27 +318,50 @@ export class LoadingScene extends SceneBase {
assetText.setText(`Loading asset: ${file.key}`);
});
this.load.on('filecomplete', key => {
switch (key) {
case 'loading_bg':
bg.setVisible(true);
bg.setTexture('loading_bg');
break;
case 'logo':
logo.setVisible(true);
logo.setTexture('logo');
break;
}
});
loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText);
this.load.on("complete", () => {
if (!mobile)
loadingGraphics.map(g => g.setVisible(false));
const destroyLoadingAssets = () => {
intro.destroy();
bg.destroy();
logo.destroy();
progressBar.destroy();
progressBox.destroy();
percentText.destroy();
assetText.destroy();
};
this.load.on('filecomplete', key => {
switch (key) {
case 'intro_dark':
intro.load('intro_dark');
intro.on('complete', () => {
this.tweens.add({
targets: intro,
duration: 500,
alpha: 0,
ease: 'Sine.easeIn'
});
loadingGraphics.map(g => g.setVisible(true));
});
intro.play();
break;
case 'loading_bg':
bg.setTexture('loading_bg');
if (mobile)
bg.setVisible(true);
break;
case 'logo':
logo.setTexture('logo');
if (mobile)
logo.setVisible(true);
break;
}
});
this.load.on("complete", () => destroyLoadingAssets());
}
get gameHeight() {

3687
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

@ -44,6 +44,7 @@ const config: Phaser.Types.Core.GameConfig = {
touch: {
target: 'app'
},
gamepad: true
},
dom: {
createContainer: true

View File

@ -1001,10 +1001,12 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
if (this.fainted || this.healStatus)
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());
}
return true;
}
return false;
}
}
export class PokemonStatusHealModifier extends ConsumablePokemonModifier {

View File

@ -16,7 +16,7 @@ import EvolutionSceneHandler from "./ui/evolution-scene-handler";
import { EvolutionPhase } from "./evolution-phase";
import { Phase } from "./phase";
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat";
import { biomeLinks } from "./data/biomes";
import { biomeLinks, getBiomeName } from "./data/biomes";
import { Biome } from "./data/enums/biome";
import { ModifierTier } from "./modifier/modifier-tier";
import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
@ -1034,9 +1034,26 @@ export class SelectBiomePhase extends BattlePhase {
.map(b => !Array.isArray(b) ? b : b[0]);
}, this.scene.currentBattle.waveIndex);
if (biomes.length > 1 && this.scene.findModifier(m => m instanceof MapModifier)) {
this.scene.ui.setMode(Mode.BIOME_SELECT, currentBiome, (biomeIndex: integer) => {
let biomeChoices: Biome[];
this.scene.executeWithSeedOffset(() => {
biomeChoices = (!Array.isArray(biomeLinks[currentBiome])
? [ biomeLinks[currentBiome] as Biome ]
: biomeLinks[currentBiome] as (Biome | [Biome, integer])[])
.filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1]))
.map(b => Array.isArray(b) ? b[0] : b);
}, this.scene.currentBattle.waveIndex);
const biomeSelectItems = biomeChoices.map(b => {
return {
label: getBiomeName(b),
handler: () => {
this.scene.ui.setMode(Mode.MESSAGE);
setNextBiome(biomes[biomeIndex]);
setNextBiome(b);
}
};
});
this.scene.ui.setMode(Mode.OPTION_SELECT, {
options: biomeSelectItems,
delay: 1000
});
} else
setNextBiome(biomes[Utils.randSeedInt(biomes.length)]);
@ -4162,10 +4179,15 @@ export class SelectModifierPhase extends BattlePhase {
const applyModifier = (modifier: Modifier, playSound: boolean = false) => {
const result = this.scene.addModifier(modifier, false, playSound);
if (cost) {
result.then(success => {
if (success) {
this.scene.money -= cost;
this.scene.updateMoneyText();
this.scene.playSound('buy');
(this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText();
} else
this.scene.ui.playError();
});
} else {
const doEnd = () => {
this.scene.ui.clearText();
@ -4251,7 +4273,7 @@ export class SelectModifierPhase extends BattlePhase {
return getPlayerModifierTypeOptions(modifierCount, this.scene.getParty(), this.scene.lockModifierTiers ? this.modifierTiers : undefined);
}
addModifier(modifier: Modifier): Promise<void> {
addModifier(modifier: Modifier): Promise<boolean> {
return this.scene.addModifier(modifier, false, true);
}
}

View File

@ -1,5 +1,7 @@
let cacheBuster = '';
const ignoredFiles = [ 'intro_dark' ];
export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin {
constructor(scene: Phaser.Scene) {
super(scene)
@ -15,9 +17,9 @@ export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin
addFile(file): void {
if (!Array.isArray(file))
file = [ file ]
file = [ file ];
if (cacheBuster)
if (!ignoredFiles.includes(file?.key) && cacheBuster)
file.forEach(item => item.url += '?v=' + cacheBuster);
super.addFile(file);

View File

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

View File

@ -184,7 +184,7 @@ const systemShortKeys = {
ivs: '$i',
moveset: '$m',
eggMoves: '$em',
candyCount: '$cc',
candyCount: '$x',
passive: '$p',
valueReduction: '$vr'
};

View File

@ -19,6 +19,7 @@ export enum Setting {
HP_Bar_Speed = "HP_BAR_SPEED",
Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS",
Player_Gender = "PLAYER_GENDER",
Gamepad_Support = "GAMEPAD_SUPPORT",
Touch_Controls = "TOUCH_CONTROLS",
Vibration = "VIBRATION"
}
@ -47,6 +48,7 @@ export const settingOptions: SettingOptions = {
[Setting.HP_Bar_Speed]: [ 'Normal', 'Fast', 'Faster', 'Instant' ],
[Setting.Fusion_Palette_Swaps]: [ 'Off', 'On' ],
[Setting.Player_Gender]: [ 'Boy', 'Girl' ],
[Setting.Gamepad_Support]: [ 'Auto', 'Disabled' ],
[Setting.Touch_Controls]: [ 'Auto', 'Disabled' ],
[Setting.Vibration]: [ 'Auto', 'Disabled' ]
};
@ -67,6 +69,7 @@ export const settingDefaults: SettingDefaults = {
[Setting.HP_Bar_Speed]: 0,
[Setting.Fusion_Palette_Swaps]: 1,
[Setting.Player_Gender]: 0,
[Setting.Gamepad_Support]: 0,
[Setting.Touch_Controls]: 0,
[Setting.Vibration]: 0
};
@ -130,6 +133,9 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
} else
return false;
break;
case Setting.Gamepad_Support:
scene.gamepadSupport = settingOptions[setting][value] !== 'Disabled';
break;
case Setting.Touch_Controls:
scene.enableTouchControls = settingOptions[setting][value] !== 'Disabled' && hasTouchscreen();
const touchControls = document.getElementById('touchControls');

View File

@ -1,134 +0,0 @@
import BattleScene, { Button } from "../battle-scene";
import { biomeLinks, getBiomeName } from "../data/biomes";
import { Biome } from "../data/enums/biome";
import { addTextObject, TextStyle } from "./text";
import { Mode } from "./ui";
import UiHandler from "./ui-handler";
import * as Utils from "../utils";
import { addWindow } from "./ui-theme";
export default class BiomeSelectUiHandler extends UiHandler {
private biomeSelectContainer: Phaser.GameObjects.Container;
private biomeSelectBg: Phaser.GameObjects.NineSlice;
private biomesText: Phaser.GameObjects.Text;
private biomeChoices: Biome[];
private cursorObj: Phaser.GameObjects.Image;
private blockInput: boolean;
private biomeSelectHandler: Function;
constructor(scene: BattleScene) {
super(scene, Mode.BIOME_SELECT);
}
setup() {
const ui = this.getUi();
this.biomeSelectContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 97, -49);
this.biomeSelectContainer.setVisible(false);
ui.add(this.biomeSelectContainer);
this.biomeSelectBg = addWindow(this.scene, 0, 0, 96, 32);
this.biomeSelectBg.setOrigin(0, 1);
this.biomeSelectContainer.add(this.biomeSelectBg);
this.biomesText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW, { maxLines: 3 });
this.biomesText.setLineSpacing(12);
this.biomeSelectContainer.add(this.biomesText);
}
show(args: any[]): boolean {
if (args.length >= 2 && typeof(args[0]) === 'number' && args[1] instanceof Function) {
super.show(args);
this.scene.executeWithSeedOffset(() => {
this.biomeChoices = (!Array.isArray(biomeLinks[args[0]])
? [ biomeLinks[args[0]] as Biome ]
: biomeLinks[args[0]] as (Biome | [Biome, integer])[])
.filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1]))
.map(b => Array.isArray(b) ? b[0] : b);
}, this.scene.currentBattle.waveIndex);
if (this.biomeChoices.length <= 1)
return;
this.biomeSelectBg.height = (this.biomeChoices.length + 1) * 16;
this.biomesText.setText(this.biomeChoices.map(b => getBiomeName(b)).join('\n'));
this.biomesText.setPositionRelative(this.biomeSelectBg, 16, 9);
this.biomeSelectHandler = args[1] as Function;
this.biomeSelectContainer.setVisible(true);
this.setCursor(0);
this.blockInput = true;
this.biomesText.setAlpha(0.5);
this.scene.time.delayedCall(Utils.fixedInt(1000), () => {
this.blockInput = false;
this.biomesText.setAlpha(1);
});
}
return true;
}
processInput(button: Button): boolean {
const ui = this.getUi();
let success = false;
if (button === Button.ACTION || button === Button.CANCEL) {
if (this.blockInput)
return false;
success = true;
const originalBiomeSelectHandler = this.biomeSelectHandler;
this.biomeSelectHandler = null;
originalBiomeSelectHandler(this.cursor);
this.clear();
} else {
switch (button) {
case Button.UP:
if (this.cursor)
success = this.setCursor(this.cursor - 1);
break;
case Button.DOWN:
if (this.cursor < this.biomeChoices.length - 1)
success = this.setCursor(this.cursor + 1);
break;
}
}
if (success)
ui.playSelect();
return success;
}
setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor);
if (!this.cursorObj) {
this.cursorObj = this.scene.add.image(0, 0, 'cursor');
this.biomeSelectContainer.add(this.cursorObj);
}
this.cursorObj.setPositionRelative(this.biomeSelectBg, 12, 17 + 16 * this.cursor);
return ret;
}
clear() {
super.clear();
this.biomeSelectContainer.setVisible(false);
this.biomeSelectHandler = null;
this.eraseCursor();
}
eraseCursor() {
if (this.cursorObj)
this.cursorObj.destroy();
this.cursorObj = null;
}
}

View File

@ -1304,6 +1304,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.dexAttrCursor = 0n;
this.natureCursor = -1;
if (species?.forms?.find(f => f.formKey === 'female')) {
if (female !== undefined)
formIndex = female ? 1 : 0;
else if (formIndex !== undefined)
female = formIndex === 1;
}
if (species) {
this.dexAttrCursor |= (shiny !== undefined ? !shiny : !(shiny = oldProps.shiny)) ? DexAttr.NON_SHINY : DexAttr.SHINY;
this.dexAttrCursor |= (female !== undefined ? !female : !(female = oldProps.female)) ? DexAttr.MALE : DexAttr.FEMALE;

View File

@ -11,7 +11,6 @@ import BallUiHandler from './ball-ui-handler';
import SummaryUiHandler from './summary-ui-handler';
import StarterSelectUiHandler from './starter-select-ui-handler';
import EvolutionSceneHandler from './evolution-scene-handler';
import BiomeSelectUiHandler from './biome-select-ui-handler';
import TargetSelectUiHandler from './target-select-ui-handler';
import SettingsUiHandler from './settings-ui-handler';
import { TextStyle, addTextObject } from './text';
@ -47,7 +46,6 @@ export enum Mode {
SAVE_SLOT,
PARTY,
SUMMARY,
BIOME_SELECT,
STARTER_SELECT,
EVOLUTION_SCENE,
EGG_HATCH_SCENE,
@ -127,7 +125,6 @@ export default class UI extends Phaser.GameObjects.Container {
new SaveSlotSelectUiHandler(scene),
new PartyUiHandler(scene),
new SummaryUiHandler(scene),
new BiomeSelectUiHandler(scene),
new StarterSelectUiHandler(scene),
new EvolutionSceneHandler(scene),
new EggHatchSceneHandler(scene),