mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-04 15:32:18 +02:00
Merge branch 'pagefaultgames:main' into main
This commit is contained in:
commit
5744aa41eb
@ -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
4
package-lock.json
generated
@ -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",
|
||||
|
2477
public/battle-anims/common-snow.json
Normal file
2477
public/battle-anims/common-snow.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/images/intro_dark.mp4
Normal file
BIN
public/images/intro_dark.mp4
Normal file
Binary file not shown.
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -1141,6 +1155,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);
|
||||
@ -2206,7 +2222,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),
|
||||
@ -2343,10 +2359,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),
|
||||
@ -2424,14 +2440,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)
|
||||
@ -2632,9 +2649,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)
|
||||
@ -2671,7 +2688,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),
|
||||
@ -2680,7 +2698,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),
|
||||
@ -2813,7 +2832,8 @@ export function initAbilities() {
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.SEED_SOWER, "Seed Sower", "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", 9)
|
||||
.attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY),
|
||||
new Ability(Abilities.THERMAL_EXCHANGE, "Thermal Exchange (P)", "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", 9)
|
||||
new Ability(Abilities.THERMAL_EXCHANGE, "Thermal Exchange", "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", 9)
|
||||
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE, BattleStat.ATK, 1)
|
||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN)
|
||||
.ignorable(),
|
||||
new Ability(Abilities.ANGER_SHELL, "Anger Shell (N)", "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", 9),
|
||||
@ -2878,7 +2898,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)
|
||||
|
@ -89,6 +89,7 @@ export enum CommonAnim {
|
||||
RAIN,
|
||||
SANDSTORM,
|
||||
HAIL,
|
||||
SNOW,
|
||||
WIND,
|
||||
HEAVY_RAIN,
|
||||
HARSH_SUN,
|
||||
|
@ -1077,6 +1077,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:
|
||||
@ -1093,6 +1094,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.NONE:
|
||||
@ -1100,3 +1103,4 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
||||
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
|
||||
}
|
||||
}
|
||||
|
@ -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 = {};
|
||||
|
@ -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",
|
||||
@ -46,5 +47,6 @@ export enum BattlerTagType {
|
||||
IGNORE_ACCURACY = "IGNORE_ACCURACY",
|
||||
BYPASS_SLEEP = "BYPASS_SLEEP",
|
||||
IGNORE_FLYING = "IGNORE_FLYING",
|
||||
GROUNDED = "GROUNDED",
|
||||
SALT_CURED = "SALT_CURED"
|
||||
}
|
||||
|
2704
src/data/move.ts
2704
src/data/move.ts
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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!',
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -1208,7 +1213,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);
|
||||
@ -1294,6 +1299,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) {
|
||||
@ -1344,8 +1353,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;
|
||||
|
@ -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() {
|
||||
|
3678
src/locales/en/move.ts
Normal file
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
6
src/locales/fr/move.ts
Normal 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;
|
@ -44,6 +44,7 @@ const config: Phaser.Types.Core.GameConfig = {
|
||||
touch: {
|
||||
target: 'app'
|
||||
},
|
||||
gamepad: true
|
||||
},
|
||||
dom: {
|
||||
createContainer: true
|
||||
|
@ -1001,9 +1001,11 @@ 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 true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
setNextBiome(biomes[biomeIndex]);
|
||||
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(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) {
|
||||
this.scene.money -= cost;
|
||||
this.scene.updateMoneyText();
|
||||
this.scene.playSound('buy');
|
||||
(this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ const systemShortKeys = {
|
||||
ivs: '$i',
|
||||
moveset: '$m',
|
||||
eggMoves: '$em',
|
||||
candyCount: '$cc',
|
||||
candyCount: '$x',
|
||||
passive: '$p',
|
||||
valueReduction: '$vr'
|
||||
};
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user