diff --git a/README.md b/README.md index 424d47ff1..b2955f8c4 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,11 @@ PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite If you have the motivation and experience with Typescript/Javascript (or are willing to learn) please feel free to fork the repository and make pull requests with contributions. If you don't know what to work on but want to help, reference the below **To-Do** section or the **#vote** channel in the discord. ### 💻 Environment Setup -node: 18.3.0 +#### Prerequisites +- node: 18.3.0 +- npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) +#### Running Locally 1. Clone the repo and in the root directory run `npm install` - *if you run into any errors, reach out in the **#dev-corner** channel in discord* 2. Run `npm run start:dev` to locally run the project in `localhost:8000` diff --git a/public/audio/cry/25-gigantamax.m4a b/public/audio/cry/25-gigantamax.m4a index ea4becab5..2cf38814b 100644 Binary files a/public/audio/cry/25-gigantamax.m4a and b/public/audio/cry/25-gigantamax.m4a differ diff --git a/public/audio/cry/25.m4a b/public/audio/cry/25.m4a index ea4becab5..2cf38814b 100644 Binary files a/public/audio/cry/25.m4a and b/public/audio/cry/25.m4a differ diff --git a/public/audio/cry/669-white.m4a b/public/audio/cry/669-white.m4a new file mode 100644 index 000000000..773241dac Binary files /dev/null and b/public/audio/cry/669-white.m4a differ diff --git a/public/audio/cry/670-white.m4a b/public/audio/cry/670-white.m4a new file mode 100644 index 000000000..45e83e386 Binary files /dev/null and b/public/audio/cry/670-white.m4a differ diff --git a/public/audio/cry/671-white.m4a b/public/audio/cry/671-white.m4a new file mode 100644 index 000000000..e604dea40 Binary files /dev/null and b/public/audio/cry/671-white.m4a differ diff --git a/public/images/pokemon/1024-stellar.json b/public/images/pokemon/1024-stellar.json index 3f8ffe6c4..0972c5632 100644 --- a/public/images/pokemon/1024-stellar.json +++ b/public/images/pokemon/1024-stellar.json @@ -4,30 +4,30 @@ "image": "1024-stellar.png", "format": "RGBA8888", "size": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, - "scale": 0.5, + "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, "trimmed": false, "sourceSize": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, "spriteSourceSize": { - "x": 9, + "x": 0, "y": 0, - "w": 78, - "h": 96 + "w": 115, + "h": 119 }, "frame": { "x": 0, "y": 0, - "w": 78, - "h": 96 + "w": 115, + "h": 119 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c9ee64bda72f2dadb06109338796ccac:1313f1218b7da2c57ad9f290d1323840:c1508f3b01ae78a28a1267fd6caa4f7b$" + "smartupdate": "$TexturePacker:SmartUpdate:bc663acf2e62803fce6c3a525dc8dd98:ccd7d0de8a487235cfbd6f372afa931f:c1508f3b01ae78a28a1267fd6caa4f7b$" } } diff --git a/public/images/pokemon/1024-stellar.png b/public/images/pokemon/1024-stellar.png index 6500eddec..7e40fb004 100644 Binary files a/public/images/pokemon/1024-stellar.png and b/public/images/pokemon/1024-stellar.png differ diff --git a/public/images/pokemon/back/1024-stellar.json b/public/images/pokemon/back/1024-stellar.json index f80edd886..ce84b0d45 100644 --- a/public/images/pokemon/back/1024-stellar.json +++ b/public/images/pokemon/back/1024-stellar.json @@ -4,30 +4,30 @@ "image": "1024-stellar.png", "format": "RGBA8888", "size": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, - "scale": 0.333, + "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, "trimmed": false, "sourceSize": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, "spriteSourceSize": { - "x": 5, + "x": 0, "y": 0, - "w": 86, - "h": 96 + "w": 115, + "h": 119 }, "frame": { "x": 0, "y": 0, - "w": 86, - "h": 96 + "w": 115, + "h": 119 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:ac5e775f77477eeabd029932804747c4:f7a112a87c35dc81cb0da88b7cbb39e8:c1508f3b01ae78a28a1267fd6caa4f7b$" + "smartupdate": "$TexturePacker:SmartUpdate:210ba1c2e6e58501571ae226d073a3c5:f12bdf191842f7ec3a4be98a43fb8121:c1508f3b01ae78a28a1267fd6caa4f7b$" } } diff --git a/public/images/pokemon/back/1024-stellar.png b/public/images/pokemon/back/1024-stellar.png index 7940444f5..0bb2993d8 100644 Binary files a/public/images/pokemon/back/1024-stellar.png and b/public/images/pokemon/back/1024-stellar.png differ diff --git a/public/images/pokemon/back/shiny/1024-stellar.json b/public/images/pokemon/back/shiny/1024-stellar.json index eeabac109..ce84b0d45 100644 --- a/public/images/pokemon/back/shiny/1024-stellar.json +++ b/public/images/pokemon/back/shiny/1024-stellar.json @@ -4,30 +4,30 @@ "image": "1024-stellar.png", "format": "RGBA8888", "size": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, - "scale": 0.333, + "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, "trimmed": false, "sourceSize": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, "spriteSourceSize": { - "x": 5, + "x": 0, "y": 0, - "w": 86, - "h": 96 + "w": 115, + "h": 119 }, "frame": { "x": 0, "y": 0, - "w": 86, - "h": 96 + "w": 115, + "h": 119 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:2bd25bae0fabcfbc35e24bd578a7b4b5:aec60788a0d77f38fb599d721e41a0d6:c1508f3b01ae78a28a1267fd6caa4f7b$" + "smartupdate": "$TexturePacker:SmartUpdate:210ba1c2e6e58501571ae226d073a3c5:f12bdf191842f7ec3a4be98a43fb8121:c1508f3b01ae78a28a1267fd6caa4f7b$" } } diff --git a/public/images/pokemon/back/shiny/1024-stellar.png b/public/images/pokemon/back/shiny/1024-stellar.png index 6b9e35174..0bb2993d8 100644 Binary files a/public/images/pokemon/back/shiny/1024-stellar.png and b/public/images/pokemon/back/shiny/1024-stellar.png differ diff --git a/public/images/pokemon/shiny/1024-stellar.json b/public/images/pokemon/shiny/1024-stellar.json index dd07eb812..ba751e2bc 100644 --- a/public/images/pokemon/shiny/1024-stellar.json +++ b/public/images/pokemon/shiny/1024-stellar.json @@ -4,30 +4,30 @@ "image": "1024-stellar.png", "format": "RGBA8888", "size": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, - "scale": 0.5, + "scale": 1, "frames": [ { "filename": "0001.png", "rotated": false, "trimmed": false, "sourceSize": { - "w": 96, - "h": 96 + "w": 119, + "h": 119 }, "spriteSourceSize": { - "x": 9, + "x": 0, "y": 0, - "w": 78, - "h": 96 + "w": 115, + "h": 119 }, "frame": { "x": 0, "y": 0, - "w": 78, - "h": 96 + "w": 115, + "h": 119 } } ] @@ -36,6 +36,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:a7e89af07a22475413df24b510c193f7:45261af90c4a51e3dc73cccb894a2aad:c1508f3b01ae78a28a1267fd6caa4f7b$" + "smartupdate": "$TexturePacker:SmartUpdate:3510deaf42eaa3ee2fdfa22c00a2b30b:3beb6b12ca1bb50ad260593b41939f27:c1508f3b01ae78a28a1267fd6caa4f7b$" } } diff --git a/public/images/pokemon/shiny/1024-stellar.png b/public/images/pokemon/shiny/1024-stellar.png index 42ed145d9..b00b395ec 100644 Binary files a/public/images/pokemon/shiny/1024-stellar.png and b/public/images/pokemon/shiny/1024-stellar.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index fdd50661b..26fbe1b2f 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -17,7 +17,7 @@ import { TextStyle, addTextObject } from './ui/text'; import { Moves } from "./data/enums/moves"; import { allMoves } from "./data/move"; import { initMoves } from './data/move'; -import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; +import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getModifierPoolForType } from './modifier/modifier-type'; import AbilityBar from './ui/ability-bar'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { Abilities } from "./data/enums/abilities"; @@ -795,7 +795,10 @@ export default class BattleScene extends SceneBase { this.trainer.setVisible(true); if (reloadI18n) { - const localizable: Localizable[] = [ ...allMoves ]; + const localizable: Localizable[] = [ + ...allMoves, + ...Utils.getEnumValues(ModifierPoolType).map(mpt => getModifierPoolForType(mpt)).map(mp => Object.values(mp).flat().map(mt => mt.modifierType).filter(mt => 'localize' in mt).map(lpb => lpb as unknown as Localizable)).flat() + ]; for (let item of localizable) item.localize(); } @@ -975,6 +978,9 @@ export default class BattleScene extends SceneBase { case Species.DEERLING: case Species.SAWSBUCK: case Species.VIVILLON: + case Species.FLABEBE: + case Species.FLOETTE: + case Species.FLORGES: case Species.ORICORIO: case Species.SQUAWKABILLY: case Species.TATSUGIRI: diff --git a/src/data/ability.ts b/src/data/ability.ts index b2399844a..348f78da6 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2134,6 +2134,9 @@ export class SuppressFieldAbilitiesAbAttr extends AbAttr { } } + +export class AlwaysHitAbAttr extends AbAttr { } + export class UncopiableAbilityAbAttr extends AbAttr { constructor() { super(false); @@ -2615,7 +2618,9 @@ export function initAbilities() { new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits when attacking.", 4), new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "The Pokémon only takes damage from attacks.", 4) .attr(BlockNonDirectDamageAbAttr), - new Ability(Abilities.NO_GUARD, "No Guard (N)", "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", 4), + new Ability(Abilities.NO_GUARD, "No Guard", "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", 4) + .attr(AlwaysHitAbAttr) + .attr(DoubleBattleChanceAbAttr), new Ability(Abilities.STALL, "Stall (N)", "The Pokémon moves after all other Pokémon do.", 4), new Ability(Abilities.TECHNICIAN, "Technician", "Powers up the Pokémon's weaker moves.", 4) .attr(MovePowerBoostAbAttr, (user, target, move) => move.power <= 60, 1.5), diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index ce90b038f..58c017c7a 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1024,6 +1024,39 @@ export class SaltCuredTag extends BattlerTag { } } +export class CursedTag extends BattlerTag { + private sourceIndex: integer; + + constructor(sourceId: integer) { + super(BattlerTagType.CURSED, BattlerTagLapseType.TURN_END, 1, Moves.CURSE, sourceId); + } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' has been cursed!')); + this.sourceIndex = pokemon.scene.getPokemonById(this.sourceId).getBattlerIndex(); + } + + lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType); + + if (ret) { + pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.SALT_CURE)); + + const cancelled = new Utils.BooleanHolder(false); + applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); + + if (!cancelled.value) { + pokemon.damageAndUpdate(Math.floor(pokemon.getMaxHp() / 4)); + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt by the ${this.getMoveName()}!`)); + } + } + + return ret; + } +} + export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag { switch (tagType) { case BattlerTagType.RECHARGING: @@ -1121,6 +1154,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount - 1, sourceMove); case BattlerTagType.SALT_CURED: return new SaltCuredTag(sourceId); + case BattlerTagType.CURSED: + return new CursedTag(sourceId); case BattlerTagType.CHARGED: return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); case BattlerTagType.NONE: diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index b0fb7c2cc..9c740ef46 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -49,6 +49,7 @@ export enum BattlerTagType { BYPASS_SLEEP = "BYPASS_SLEEP", IGNORE_FLYING = "IGNORE_FLYING", SALT_CURED = "SALT_CURED", + CURSED = "CURSED", CHARGED = "CHARGED", GROUNDED = "GROUNDED" } diff --git a/src/data/move.ts b/src/data/move.ts index c19c822a5..03fd53ec2 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2493,6 +2493,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { return -5; case BattlerTagType.SEEDED: case BattlerTagType.SALT_CURED: + case BattlerTagType.CURSED: case BattlerTagType.FRENZY: case BattlerTagType.TRAPPED: case BattlerTagType.BIND: @@ -2527,6 +2528,34 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } } +export class CurseAttr extends MoveEffectAttr { + + apply(user: Pokemon, target: Pokemon, move:Move, args: any[]): boolean { + // Determine the correct target based on the user's type + if (!user.getTypes(true).includes(Type.GHOST)) { + // For non-Ghost types, target the user itself + target = user; + } + + if (user.getTypes(true).includes(Type.GHOST)) { + if (target.getTag(BattlerTagType.CURSED)) { + user.scene.queueMessage('But it failed!'); + return false; + } + let curseRecoilDamage = Math.floor(user.getMaxHp() / 2); + user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true, true); + user.scene.queueMessage(getPokemonMessage(user, ' cut its own HP!')); + target.addTag(BattlerTagType.CURSED, 0, move.id, user.id); + return true; + } else { + target = user; + user.scene.unshiftPhase(new StatChangePhase(user.scene, user.getBattlerIndex(), this.selfTarget, [BattleStat.ATK, BattleStat.DEF], 1)); + user.scene.unshiftPhase(new StatChangePhase(user.scene, user.getBattlerIndex(), this.selfTarget, [BattleStat.SPD], -1)); + return true; + } + } +} + export class LapseBattlerTagAttr extends MoveEffectAttr { public tagTypes: BattlerTagType[]; @@ -5132,6 +5161,7 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPATK, 1, true) .danceMove(), new AttackMove(Moves.FREEZE_SHOCK, Type.ICE, MoveCategory.PHYSICAL, 140, 90, 5, 30, 0, 5) + .attr(ChargeAttr, ChargeAnim.FREEZE_SHOCK_CHARGING, 'became cloaked\nin a freezing light!') .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .makesContact(false), new AttackMove(Moves.ICE_BURN, Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, 30, 0, 5) diff --git a/src/data/pokeball.ts b/src/data/pokeball.ts index 45775f33d..f5e39ba38 100644 --- a/src/data/pokeball.ts +++ b/src/data/pokeball.ts @@ -1,4 +1,5 @@ import BattleScene from "../battle-scene"; +import i18next from '../plugins/i18n'; export enum PokeballType { POKEBALL, @@ -30,22 +31,22 @@ export function getPokeballName(type: PokeballType): string { let ret: string; switch (type) { case PokeballType.POKEBALL: - ret = 'Poké Ball'; + ret = i18next.t('pokeball:pokeBall'); break; case PokeballType.GREAT_BALL: - ret = 'Great Ball'; + ret = i18next.t('pokeball:greatBall'); break; case PokeballType.ULTRA_BALL: - ret = 'Ultra Ball'; + ret = i18next.t('pokeball:ultraBall'); break; case PokeballType.ROGUE_BALL: - ret = 'Rogue Ball'; + ret = i18next.t('pokeball:rogueBall'); break; case PokeballType.MASTER_BALL: - ret = 'Master Ball'; + ret = i18next.t('pokeball:masterBall'); break; case PokeballType.LUXURY_BALL: - ret = 'Luxury Ball'; + ret = i18next.t('pokeball:luxuryBall'); break; } return ret; diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index fca8dbd76..683693890 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -917,7 +917,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.TRUMBEAK, 14, null, null) ], [Species.TRUMBEAK]: [ - new SpeciesEvolution(Species.TOUCANNON, 36, null, null) + new SpeciesEvolution(Species.TOUCANNON, 28, null, null) ], [Species.YUNGOOS]: [ new SpeciesEvolution(Species.GUMSHOOS, 20, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), SpeciesWildEvolutionDelay.SHORT) diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index fe7f9a0a7..e205febcd 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -10919,8 +10919,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.CHESPIN]: [ [ 1, Moves.TACKLE ], - [ 1, Moves.VINE_WHIP ], [ 1, Moves.GROWL ], + [ 1, Moves.VINE_WHIP ], [ 8, Moves.ROLLOUT ], [ 11, Moves.BITE ], [ 15, Moves.LEECH_SEED ], @@ -10934,8 +10934,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.QUILLADIN]: [ [ 1, Moves.TACKLE ], - [ 1, Moves.VINE_WHIP ], [ 1, Moves.GROWL ], + [ 1, Moves.VINE_WHIP ], [ 8, Moves.ROLLOUT ], [ 11, Moves.BITE ], [ 15, Moves.LEECH_SEED ], diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 409c32b68..30622fb03 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -1473,7 +1473,7 @@ export function initSpecies() { new PokemonSpecies(Species.PORYGON_Z, "Porygon-Z", 4, false, false, false, "Virtual Pokémon", Type.NORMAL, null, 0.9, 34, Abilities.ADAPTABILITY, Abilities.DOWNLOAD, Abilities.ANALYTIC, 535, 85, 80, 70, 135, 75, 90, 30, 50, 268, GrowthRate.MEDIUM_FAST, null, false), new PokemonSpecies(Species.GALLADE, "Gallade", 4, false, false, false, "Blade Pokémon", Type.PSYCHIC, Type.FIGHTING, 1.6, 52, Abilities.STEADFAST, Abilities.SHARPNESS, Abilities.JUSTIFIED, 518, 68, 125, 65, 65, 115, 80, 45, 35, 259, GrowthRate.SLOW, 100, false, true, new PokemonForm("Normal", "", Type.PSYCHIC, Type.FIGHTING, 1.6, 52, Abilities.STEADFAST, Abilities.SHARPNESS, Abilities.JUSTIFIED, 518, 68, 125, 65, 65, 115, 80, 45, 35, 259), - new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FIGHTING, 1.6, 56.4, Abilities.INNER_FOCUS, Abilities.INNER_FOCUS, Abilities.INNER_FOCUS, 618, 68, 165, 95, 65, 115, 110, 45, 35, 259), + new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.PSYCHIC, Type.FIGHTING, 1.6, 56.4, Abilities.SHARPNESS, Abilities.SHARPNESS, Abilities.SHARPNESS, 618, 68, 165, 95, 65, 115, 110, 45, 35, 259), ), new PokemonSpecies(Species.PROBOPASS, "Probopass", 4, false, false, false, "Compass Pokémon", Type.ROCK, Type.STEEL, 1.4, 340, Abilities.STURDY, Abilities.MAGNET_PULL, Abilities.SAND_FORCE, 525, 60, 55, 145, 75, 150, 40, 60, 70, 184, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.DUSKNOIR, "Dusknoir", 4, false, false, false, "Gripper Pokémon", Type.GHOST, null, 2.2, 106.6, Abilities.PRESSURE, Abilities.NONE, Abilities.FRISK, 525, 45, 100, 135, 65, 135, 45, 45, 35, 263, GrowthRate.FAST, 50, false), @@ -3058,7 +3058,7 @@ export const speciesStarters = { [Species.FUECOCO]: 3, [Species.QUAXLY]: 3, [Species.LECHONK]: 2, - [Species.TAROUNTULA]: 2, + [Species.TAROUNTULA]: 1, [Species.NYMBLE]: 3, [Species.PAWMI]: 3, [Species.TANDEMAUS]: 4, diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 10e88acc5..044bd4ec8 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -697,9 +697,9 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader([ Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F ], Type.DARK).setBattleBgm('battle_kanto_gym'), [TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader([ Species.PIDGEY, Species.HOOTHOOT, Species.DODUO ], Type.FLYING).setBattleBgm('battle_johto_gym'), [TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader([ Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR ], Type.BUG).setBattleBgm('battle_johto_gym'), - [TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader([ Species.CLEFAIRY, Species.MILTANK ], Type.NORMAL).setBattleBgm('battle_johto_gym'), + [TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader([ Species.GIRAFARIG, Species.MILTANK ], Type.NORMAL).setBattleBgm('battle_johto_gym'), [TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader([ Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE ], Type.GHOST).setBattleBgm('battle_johto_gym'), - [TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader([ Species.POLIWRATH, ], Type.FIGHTING).setBattleBgm('battle_johto_gym'), + [TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader([ Species.POLIWRATH, Species.MANKEY ], Type.FIGHTING).setBattleBgm('battle_johto_gym'), [TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader([ Species.MAGNEMITE, Species.STEELIX ], Type.STEEL).setBattleBgm('battle_johto_gym'), [TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader([ Species.SEEL, Species.SWINUB ], Type.ICE).setBattleBgm('battle_johto_gym'), [TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader([ Species.DRATINI, Species.HORSEA, Species.GYARADOS ], Type.DRAGON).setBattleBgm('battle_johto_gym'), diff --git a/src/egg-hatch-phase.ts b/src/egg-hatch-phase.ts index 9259e7b10..a28d8e298 100644 --- a/src/egg-hatch-phase.ts +++ b/src/egg-hatch-phase.ts @@ -82,7 +82,11 @@ export class EggHatchPhase extends Phase { this.eggContainer.add(this.eggLightraysOverlay); this.eggHatchContainer.add(this.eggContainer); - const getPokemonSprite = () => this.scene.add.sprite(this.eggHatchBg.displayWidth / 2, this.eggHatchBg.displayHeight / 2, `pkmn__sub`); + const getPokemonSprite = () => { + const ret = this.scene.add.sprite(this.eggHatchBg.displayWidth / 2, this.eggHatchBg.displayHeight / 2, `pkmn__sub`); + ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true }); + return ret; + }; this.eggHatchContainer.add((this.pokemonSprite = getPokemonSprite())); @@ -245,7 +249,7 @@ export class EggHatchPhase extends Phase { this.scene.validateAchv(achvs.HATCH_SHINY); this.eggContainer.setVisible(false); this.pokemonSprite.play(this.pokemon.getSpriteKey(true)); - this.pokemonSprite.pipelineData['ignoreTimeTint'] = true; + this.pokemonSprite.setPipelineData('ignoreTimeTint', true); this.pokemonSprite.setPipelineData('spriteKey', this.pokemon.getSpriteKey()); this.pokemonSprite.setPipelineData('shiny', this.pokemon.shiny); this.pokemonSprite.setPipelineData('variant', this.pokemon.variant); diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts index fc58d1413..fb3803a1e 100644 --- a/src/evolution-phase.ts +++ b/src/evolution-phase.ts @@ -71,7 +71,11 @@ export class EvolutionPhase extends Phase { this.evolutionBgOverlay.setAlpha(0); this.evolutionContainer.add(this.evolutionBgOverlay); - const getPokemonSprite = () => this.scene.addPokemonSprite(this.pokemon, this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`); + const getPokemonSprite = () => { + const ret = this.scene.addPokemonSprite(this.pokemon, this.evolutionBaseBg.displayWidth / 2, this.evolutionBaseBg.displayHeight / 2, `pkmn__sub`); + ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true }); + return ret; + }; this.evolutionContainer.add((this.pokemonSprite = getPokemonSprite())); this.evolutionContainer.add((this.pokemonTintSprite = getPokemonSprite())); @@ -92,7 +96,10 @@ export class EvolutionPhase extends Phase { [ this.pokemonSprite, this.pokemonTintSprite, this.pokemonEvoSprite, this.pokemonEvoTintSprite ].map(sprite => { sprite.play(this.pokemon.getSpriteKey(true)); sprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) }); - sprite.pipelineData['ignoreTimeTint'] = true; + sprite.setPipelineData('ignoreTimeTint', true); + sprite.setPipelineData('spriteKey', this.pokemon.getSpriteKey()); + sprite.setPipelineData('shiny', this.pokemon.shiny); + sprite.setPipelineData('variant', this.pokemon.variant); [ 'spriteColors', 'fusionSpriteColors' ].map(k => { if (this.pokemon.summonData?.speciesForm) k += 'Base'; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 21a665fc3..608f0c550 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1832,7 +1832,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return false; break; case StatusEffect.FREEZE: - if (this.isOfType(Type.ICE)) + if (this.isOfType(Type.ICE) || [WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(this.scene?.arena.weather?.weatherType)) return false; break; case StatusEffect.BURN: diff --git a/src/locales/en/pokeball.ts b/src/locales/en/pokeball.ts new file mode 100644 index 000000000..6f774d416 --- /dev/null +++ b/src/locales/en/pokeball.ts @@ -0,0 +1,8 @@ +export const pokeball = { + "pokeBall": "Poké Ball", + "greatBall": "Great Ball", + "ultraBall": "Ultra Ball", + "rogueBall": "Rogue Ball", + "masterBall": "Master Ball", + "luxuryBall": "Luxury Ball", +} as const; \ No newline at end of file diff --git a/src/locales/fr/move.ts b/src/locales/fr/move.ts index 3a7eca942..c75c5448f 100644 --- a/src/locales/fr/move.ts +++ b/src/locales/fr/move.ts @@ -1443,7 +1443,7 @@ export const move: MoveTranslations = { }, "healingWish": { name: "Voeu Soin", - effect: "Un soin qui permet au lanceur de récupérer jusqu’à la moitié de ses PV max." + effect: "Le lanceur tombe K.O. pour soigner les altérations de statut et les PV du Pokémon qui viendra le remplacer sur le terrain." }, "brine": { name: "Saumure", diff --git a/src/locales/fr/pokeball.ts b/src/locales/fr/pokeball.ts new file mode 100644 index 000000000..0244550c5 --- /dev/null +++ b/src/locales/fr/pokeball.ts @@ -0,0 +1,8 @@ +export const pokeball = { + "pokeBall": "Poké Ball", + "greatBall": "Super Ball", + "ultraBall": "Hyper Ball", + "rogueBall": "Rogue Ball", + "masterBall": "Master Ball", + "luxuryBall": "Luxe Ball", +} as const; \ No newline at end of file diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 77d709547..6197db237 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -19,6 +19,7 @@ import { VoucherType, getVoucherTypeIcon, getVoucherTypeName } from '../system/v import { FormChangeItem, SpeciesFormChangeItemTrigger, pokemonFormChanges } from '../data/pokemon-forms'; import { ModifierTier } from './modifier-tier'; import { Nature, getNatureName, getNatureStatMultiplier } from '#app/data/nature'; +import { Localizable } from '#app/plugins/i18n'; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -131,10 +132,19 @@ export interface GeneratedPersistentModifierType { getPregenArgs(): any[]; } -class AddPokeballModifierType extends ModifierType { +class AddPokeballModifierType extends ModifierType implements Localizable { + private pokeballType: PokeballType; + private count: integer; + constructor(pokeballType: PokeballType, count: integer, iconImage?: string) { - super(`${count}x ${getPokeballName(pokeballType)}`, `Receive ${getPokeballName(pokeballType)} x${count}\nCatch Rate: ${getPokeballCatchMultiplier(pokeballType) > -1 ? `${getPokeballCatchMultiplier(pokeballType)}x` : 'Certain'}`, - (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage, 'pb', 'pb_bounce_1'); + super('', '', (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage, 'pb', 'pb_bounce_1'); + this.pokeballType = pokeballType; + this.count = count; + } + + localize() { + this.name = `${this.count}x ${getPokeballName(this.pokeballType)}`; + this.description = `Receive ${getPokeballName(this.pokeballType)} x${this.count}\nCatch Rate: ${getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : 'Certain'}`; } } diff --git a/src/phases.ts b/src/phases.ts index 98d474390..31f631bf4 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs } from "./data/ability"; +import { CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -379,6 +379,33 @@ export class UnavailablePhase extends Phase { } } +export class ReloadSessionPhase extends Phase { + constructor(scene: BattleScene) { + super(scene); + } + + start(): void { + this.scene.ui.setMode(Mode.SESSION_RELOAD); + + let delayElapsed = false; + let loaded = false; + + this.scene.time.delayedCall(Utils.fixedInt(1500), () => { + if (loaded) + this.end(); + else + delayElapsed = true; + }); + + this.scene.gameData.loadSystem().then(() => { + if (delayElapsed) + this.end(); + else + loaded = true; + }); + } +} + export class OutdatedPhase extends Phase { constructor(scene: BattleScene) { super(scene); @@ -767,7 +794,8 @@ export class EncounterPhase extends BattlePhase { pokemon.resetBattleData(); } - this.scene.arena.trySetWeather(getRandomWeatherType(this.scene.arena), false); + if (!this.loaded) + this.scene.arena.trySetWeather(getRandomWeatherType(this.scene.arena), false); const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ @@ -2173,7 +2201,7 @@ export class MovePhase extends BattlePhase { const targets = this.scene.getField(true).filter(p => { if (this.targets.indexOf(p.getBattlerIndex()) > -1) { const hiddenTag = p.getTag(HiddenTag); - if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length) + if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length && !p.hasAbilityWithAttr(AlwaysHitAbAttr) && !this.pokemon.hasAbilityWithAttr(AlwaysHitAbAttr)) return false; return true; } @@ -2467,6 +2495,9 @@ export class MoveEffectPhase extends PokemonPhase { if (user.turnData.hitsLeft < user.turnData.hitCount) return true; + if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) + return true; + const hiddenTag = target.getTag(HiddenTag); if (hiddenTag && !this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length) return false; @@ -3389,6 +3420,8 @@ export class GameOverPhase extends BattlePhase { handleClearSession(): void { this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => { + if (!success[0]) + return this.scene.reset(true); this.scene.time.delayedCall(1000, () => { let firstClear = false; if (this.victory && success[1]) { @@ -4296,7 +4329,7 @@ export class EggLapsePhase extends Phase { const eggsToHatch: Egg[] = this.scene.gameData.eggs.filter((egg: Egg) => { return --egg.hatchWaves < 1 - }) + }); if (eggsToHatch.length) { this.scene.queueMessage('Oh?'); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 9a72ff55f..eabafd82c 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -6,6 +6,9 @@ import { menu as frMenu } from '../locales/fr/menu'; import { move as enMove } from '../locales/en/move'; import { move as frMove } from '../locales/fr/move'; +import { pokeball as enPokeball } from '../locales/en/pokeball'; +import { pokeball as frPokeball } from '../locales/fr/pokeball'; + export interface MoveTranslationEntry { name: string, effect: string @@ -50,6 +53,7 @@ export function initI18n(): void { en: { menu: enMenu, move: enMove, + pokeball: enPokeball, }, it: { menu: itMenu, @@ -57,6 +61,7 @@ export function initI18n(): void { fr: { menu: frMenu, move: frMove, + pokeball: frPokeball, } }, }); @@ -68,6 +73,7 @@ declare module 'i18next' { resources: { menu: typeof enMenu; move: typeof enMove; + pokeball: typeof enPokeball; }; } } diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 88fcb2ce7..c5b9f32cf 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1,7 +1,7 @@ import BattleScene, { PokeballCounts, bypassLogin } from "../battle-scene"; import Pokemon, { EnemyPokemon, PlayerPokemon } from "../field/pokemon"; import { pokemonEvolutions, pokemonPrevolutions } from "../data/pokemon-evolutions"; -import PokemonSpecies, { SpeciesFormKey, allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species"; +import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species"; import { Species, defaultStarterSpecies } from "../data/enums/species"; import * as Utils from "../utils"; import PokemonData from "./pokemon-data"; @@ -27,7 +27,7 @@ import { Moves } from "../data/enums/moves"; import { speciesEggMoves } from "../data/egg-moves"; import { allMoves } from "../data/move"; import { TrainerVariant } from "../field/trainer"; -import { OutdatedPhase, UnavailablePhase } from "#app/phases"; +import { OutdatedPhase, ReloadSessionPhase } from "#app/phases"; import { Variant, variantData } from "#app/data/variant"; const saveKey = 'x0i2O7WRiANTqPmZ'; // Temporary; secure encryption is not yet necessary @@ -280,6 +280,9 @@ export class GameData { if (error.startsWith('client version out of date')) { this.scene.clearPhaseQueue(); this.scene.unshiftPhase(new OutdatedPhase(this.scene)); + } else if (error.startsWith('session out of date')) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); } console.error(error); return resolve(false); @@ -340,7 +343,7 @@ export class GameData { this.starterData[s].eggMoves = starterEggMoveData[s]; } - this.migrateStarterAbilities(systemData); + this.migrateStarterAbilities(systemData, this.starterData); } else { if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion)) this.migrateStarterAbilities(systemData); @@ -551,6 +554,10 @@ export class GameData { .then(response => response.text()) .then(error => { if (error) { + if (error.startsWith('session out of date')) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); + } console.error(error); return resolve(false); } @@ -715,9 +722,19 @@ export class GameData { Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}`, true).then(response => { if (response.ok) { loggedInUser.lastSessionSlot = -1; - return resolve(true); + resolve(true); } - resolve(false); + return response.text(); + }).then(error => { + if (error) { + if (error.startsWith('session out of date')) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); + } + console.error(error); + resolve(false); + } + resolve(true); }); }); }); @@ -735,12 +752,19 @@ export class GameData { return resolve([false, false]); const sessionData = this.getSessionSaveData(scene); Utils.apiPost(`savedata/clear?slot=${slotId}`, JSON.stringify(sessionData)).then(response => { - if (response.ok) { + if (response.ok) loggedInUser.lastSessionSlot = -1; - return response.json(); + return response.json(); + }).then(jsonResponse => { + if (!jsonResponse.error) + return resolve([true, jsonResponse.success as boolean]); + if (jsonResponse && jsonResponse.error.startsWith('session out of date')) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); } + console.error(jsonResponse); resolve([false, false]); - }).then(jsonResponse => resolve([true, jsonResponse.success as boolean])); + }); }); }); } @@ -1207,9 +1231,9 @@ export class GameData { } } - migrateStarterAbilities(systemData: SystemSaveData): void { + migrateStarterAbilities(systemData: SystemSaveData, initialStarterData?: StarterData): void { const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); - const starterData = systemData.starterData; + const starterData = initialStarterData || systemData.starterData; const dexData = systemData.dexData; for (let s of starterIds) { const dexAttr = dexData[s].caughtAttr; diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 88a80f7d2..8b2c56469 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -336,10 +336,14 @@ export default class MenuUiHandler extends MessageUiHandler { case Button.UP: if (this.cursor) success = this.setCursor(this.cursor - 1); + else + success = this.setCursor(this.menuOptions.length - 1); break; case Button.DOWN: if (this.cursor + 1 < this.menuOptions.length) success = this.setCursor(this.cursor + 1); + else + success = this.setCursor(0); break; } } diff --git a/src/ui/session-reload-modal-ui-handler.ts b/src/ui/session-reload-modal-ui-handler.ts new file mode 100644 index 000000000..fdcd9b2c2 --- /dev/null +++ b/src/ui/session-reload-modal-ui-handler.ts @@ -0,0 +1,47 @@ +import BattleScene from "../battle-scene"; +import { ModalConfig, ModalUiHandler } from "./modal-ui-handler"; +import { addTextObject, TextStyle } from "./text"; +import { Mode } from "./ui"; + +export default class SessionReloadModalUiHandler extends ModalUiHandler { + constructor(scene: BattleScene, mode?: Mode) { + super(scene, mode); + } + + getModalTitle(): string { + return ''; + } + + getWidth(): number { + return 160; + } + + getHeight(): number { + return 32; + } + + getMargin(): [number, number, number, number] { + return [ 0, 0, 48, 0 ]; + } + + getButtonLabels(): string[] { + return [ ]; + } + + setup(): void { + super.setup(); + + const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, 'Your session is out of date.\nYour data will be reloaded…', TextStyle.WINDOW, { fontSize: '48px', align: 'center' }); + label.setOrigin(0.5, 0.5); + + this.modalContainer.add(label); + } + + show(args: any[]): boolean { + const config: ModalConfig = { + buttonActions: [] + }; + + return super.show([ config ]); + } +} \ No newline at end of file diff --git a/src/ui/ui.ts b/src/ui/ui.ts index f1fe29d90..6e20b2cb8 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -34,6 +34,7 @@ import TitleUiHandler from './title-ui-handler'; import SavingIconHandler from './saving-icon-handler'; import UnavailableModalUiHandler from './unavailable-modal-ui-handler'; import OutdatedModalUiHandler from './outdated-modal-ui-handler'; +import SessionReloadModalUiHandler from './session-reload-modal-ui-handler'; export enum Mode { MESSAGE, @@ -62,6 +63,7 @@ export enum Mode { LOGIN_FORM, REGISTRATION_FORM, LOADING, + SESSION_RELOAD, UNAVAILABLE, OUTDATED }; @@ -90,6 +92,7 @@ const noTransitionModes = [ Mode.LOGIN_FORM, Mode.REGISTRATION_FORM, Mode.LOADING, + Mode.SESSION_RELOAD, Mode.UNAVAILABLE, Mode.OUTDATED ]; @@ -141,6 +144,7 @@ export default class UI extends Phaser.GameObjects.Container { new LoginFormUiHandler(scene), new RegistrationFormUiHandler(scene), new LoadingModalUiHandler(scene), + new SessionReloadModalUiHandler(scene), new UnavailableModalUiHandler(scene), new OutdatedModalUiHandler(scene) ];