diff --git a/public/images/ui/shiny_icons.json b/public/images/ui/shiny_icons.json new file mode 100644 index 00000000000..698b5b96e72 --- /dev/null +++ b/public/images/ui/shiny_icons.json @@ -0,0 +1,78 @@ +{ + "textures": [ + { + "image": "shiny_icons.png", + "format": "RGBA8888", + "size": { + "w": 15, + "h": 14 + }, + "scale": 1, + "frames": [ + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 15, + "h": 14 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 15, + "h": 14 + }, + "frame": { + "x": 0, + "y": 0, + "w": 15, + "h": 14 + } + }, + { + "filename": "1", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 15, + "h": 14 + }, + "spriteSourceSize": { + "x": 15, + "y": 0, + "w": 15, + "h": 14 + }, + "frame": { + "x": 15, + "y": 0, + "w": 15, + "h": 14 + } + }, + { + "filename": "2", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 15, + "h": 14 + }, + "spriteSourceSize": { + "x": 30, + "y": 0, + "w": 15, + "h": 14 + }, + "frame": { + "x": 30, + "y": 0, + "w": 15, + "h": 14 + } + } + ] + } + ] +} diff --git a/public/images/ui/shiny_icons.png b/public/images/ui/shiny_icons.png new file mode 100644 index 00000000000..f601d908d32 Binary files /dev/null and b/public/images/ui/shiny_icons.png differ diff --git a/src/data/variant.ts b/src/data/variant.ts index b16586108fd..48369d112db 100644 --- a/src/data/variant.ts +++ b/src/data/variant.ts @@ -1,3 +1,5 @@ +import { VariantTier } from "#app/enums/variant-tier.js"; + export type Variant = 0 | 1 | 2; export type VariantSet = [Variant, Variant, Variant]; @@ -16,3 +18,14 @@ export function getVariantTint(variant: Variant): integer { return 0xe81048; } } + +export function getVariantIcon(variant: Variant): integer { + switch (variant) { + case 0: + return VariantTier.STANDARD; + case 1: + return VariantTier.RARE; + case 2: + return VariantTier.EPIC; + } +} diff --git a/src/enums/variant-tier.ts b/src/enums/variant-tier.ts new file mode 100644 index 00000000000..279846d5f60 --- /dev/null +++ b/src/enums/variant-tier.ts @@ -0,0 +1,5 @@ +export enum VariantTier { + STANDARD, + RARE, + EPIC +} diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 92b9f952551..0a6648a9c57 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -90,6 +90,7 @@ export class LoadingScene extends SceneBase { this.loadImage("shiny_star_small", "ui", "shiny_small.png"); this.loadImage("shiny_star_small_1", "ui", "shiny_small_1.png"); this.loadImage("shiny_star_small_2", "ui", "shiny_small_2.png"); + this.loadAtlas("shiny_icons", "ui"); this.loadImage("ha_capsule", "ui", "ha_capsule.png"); this.loadImage("champion_ribbon", "ui", "champion_ribbon.png"); this.loadImage("icon_spliced", "ui"); diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts index 699dea31ad5..2eb77f81302 100644 --- a/src/test/utils/mocks/mocksContainer/mockSprite.ts +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -122,6 +122,10 @@ export default class MockSprite { return this.phaserSprite.setPositionRelative(source, x, y); } + setY(y) { + return this.phaserSprite.setY(y); + } + setCrop(x, y, width, height) { // Sets the crop size of this Game Object. return this.phaserSprite.setCrop(x, y, width, height); diff --git a/src/ui/settings/shiny_icons.json b/src/ui/settings/shiny_icons.json new file mode 100644 index 00000000000..d6465cf2c3a --- /dev/null +++ b/src/ui/settings/shiny_icons.json @@ -0,0 +1,41 @@ +{ + "textures": [ + { + "image": "shiny_icons.png", + "format": "RGBA8888", + "size": { + "w": 45, + "h": 14 + }, + "scale": 1, + "frames": [ + { + "filename": "0", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 45, + "h": 14 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 15, + "h": 14 + }, + "frame": { + "x": 0, + "y": 0, + "w": 15, + "h": 14 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:a3275c7504a9b35b288265e191b1d14c:420725f3fb73c2cac0ab3bbc0a46f2e1:3a8b8ca0f0e4be067dd46c07b78ee013$" + } +} diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index f32ea13deda..e70e8010b41 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1,6 +1,6 @@ import { BattleSceneEventType, CandyUpgradeNotificationChangedEvent } from "../events/battle-scene"; import { pokemonPrevolutions } from "#app/data/pokemon-evolutions"; -import { Variant, getVariantTint } from "#app/data/variant"; +import { Variant, getVariantTint, getVariantIcon } from "#app/data/variant"; import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; @@ -199,6 +199,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private pokemonCaughtCountText: Phaser.GameObjects.Text; private pokemonHatchedIcon : Phaser.GameObjects.Sprite; private pokemonHatchedCountText: Phaser.GameObjects.Text; + private pokemonShinyIcon: Phaser.GameObjects.Sprite; private genOptionsText: Phaser.GameObjects.Text; private instructionsContainer: Phaser.GameObjects.Container; @@ -616,6 +617,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonHatchedIcon.setScale(0.8); this.pokemonCaughtHatchedContainer.add(this.pokemonHatchedIcon); + this.pokemonShinyIcon = this.scene.add.sprite(14, 76, "shiny_icons"); + this.pokemonShinyIcon.setOrigin(0.15, 0.2); + this.pokemonShinyIcon.setScale(1); + this.pokemonCaughtHatchedContainer.add ((this.pokemonShinyIcon)); + this.pokemonHatchedCountText = addTextObject(this.scene, 24, 19, "0", TextStyle.SUMMARY_ALT); this.pokemonHatchedCountText.setOrigin(0, 0); this.pokemonCaughtHatchedContainer.add(this.pokemonHatchedCountText); @@ -1506,11 +1512,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler { switch (button) { case Button.CYCLE_SHINY: if (this.canCycleShiny) { - starterAttributes.variant = !props.shiny ? props.variant : -1; // update shiny setting + const newVariant = props.variant; this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined); if (this.dexAttrCursor & DexAttr.SHINY) { this.scene.playSound("sparkle"); + // Set the variant label to the shiny tint + const tint = getVariantTint(newVariant); + this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); + this.pokemonShinyIcon.setTint(tint); + this.pokemonShinyIcon.setVisible(true); } else { + this.pokemonShinyIcon.setVisible(false); success = true; } } @@ -1593,13 +1605,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } } while (newVariant !== props.variant); - starterAttributes.variant = newVariant; // store the selected variant this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant, undefined, undefined); - // Cycle tint based on current sprite tint const tint = getVariantTint(newVariant); - this.variantLabel.setTint(tint); - + this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); + this.pokemonShinyIcon.setTint(tint); success = true; } break; @@ -1875,8 +1885,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); const variant = defaultProps.variant; const tint = getVariantTint(variant); - - this.variantLabel.setTint(tint); + this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); + this.pokemonShinyIcon.setTint(tint); this.setSpecies(species); this.updateInstructions(); } @@ -1924,6 +1934,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { return false; } + + setSpecies(species: PokemonSpecies) { this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null; this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true) : 0n; @@ -2045,9 +2057,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species)); } this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`); + const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); + const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); + const variant = defaultProps.variant; + const tint = getVariantTint(variant); + this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); + this.pokemonShinyIcon.setTint(tint); this.pokemonCaughtHatchedContainer.setVisible(true); if (pokemonPrevolutions.hasOwnProperty(species.speciesId)) { this.pokemonCaughtHatchedContainer.setY(16); + this.pokemonShinyIcon.setY(135); + this.pokemonShinyIcon.setFrame(getVariantIcon(variant)); [ this.pokemonCandyIcon, this.pokemonCandyOverlayIcon, @@ -2056,12 +2076,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonHatchedIcon, this.pokemonHatchedCountText ].map(c => c.setVisible(false)); - this.pokemonFormText.setY(25); } else if (species.speciesId === Species.ETERNATUS) { this.pokemonHatchedIcon.setVisible(false); this.pokemonHatchedCountText.setVisible(false); } else { this.pokemonCaughtHatchedContainer.setY(25); + this.pokemonShinyIcon.setY(117); this.pokemonCandyIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[0]))); this.pokemonCandyIcon.setVisible(true); this.pokemonCandyOverlayIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[1]))); @@ -2070,8 +2090,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`); this.pokemonCandyCountText.setVisible(true); this.pokemonFormText.setVisible(true); - this.pokemonFormText.setY(42); this.pokemonHatchedIcon.setVisible(true); + this.pokemonShinyIcon.setVisible(true); this.pokemonHatchedCountText.setVisible(true); let currentFriendship = this.scene.gameData.starterData[this.lastSpecies.speciesId].friendship; @@ -2124,17 +2144,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]); } else { const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); - const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); - // load default nature from stater save data, if set - const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species); + const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); + const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species); props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); - if (!isNaN(starterAttributes?.variant)) { - if (props.shiny = (starterAttributes.variant >= 0)) { - props.variant = starterAttributes.variant as Variant; - } - } - props.formIndex = starterAttributes?.form ?? props.formIndex; - props.female = starterAttributes?.female ?? props.female; this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, defaultAbilityIndex, defaultNature); } @@ -2197,6 +2209,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } + + setSpeciesDetails(species: PokemonSpecies, shiny: boolean, formIndex: integer, female: boolean, variant: Variant, abilityIndex: integer, natureIndex: integer, forSeen: boolean = false): void { const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null; const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);