From 33ba66b236f2b8ef3990911c2df71b7d4f74dcbc Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Sun, 17 Mar 2024 13:38:27 -0400 Subject: [PATCH] Add daily rankings board --- src/battle-scene.ts | 7 +++ src/data/move.ts | 2 +- src/phases.ts | 5 ++ src/ui/daily-run-scoreboard.ts | 97 ++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/ui/daily-run-scoreboard.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 3cf8e547a..fe89ba039 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -54,6 +54,7 @@ import CharSprite from './ui/char-sprite'; import DamageNumberHandler from './field/damage-number-handler'; import PokemonInfoContainer from './ui/pokemon-info-container'; import { biomeDepths } from './data/biomes'; +import { DailyRunScoreboard } from './ui/daily-run-scoreboard'; export const bypassLogin = false; @@ -138,6 +139,7 @@ export default class BattleScene extends Phaser.Scene { public pokeballCounts: PokeballCounts; public money: integer; public pokemonInfoContainer: PokemonInfoContainer; + public dailyRunScoreboard: DailyRunScoreboard; private party: PlayerPokemon[]; private waveCountText: Phaser.GameObjects.Text; private moneyText: Phaser.GameObjects.Text; @@ -562,6 +564,11 @@ export default class BattleScene extends Phaser.Scene { this.fieldUI.add(this.pokemonInfoContainer); + this.dailyRunScoreboard = new DailyRunScoreboard(this, 1, -(this.game.canvas.height / 6) + 1); + this.dailyRunScoreboard.setup(); + + this.fieldUI.add(this.dailyRunScoreboard); + this.party = []; let loadPokemonAssets = []; diff --git a/src/data/move.ts b/src/data/move.ts index 1b890091d..95bc6dce3 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3392,7 +3392,7 @@ export function initMoves() { new AttackMove(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, -1, 30, 5, -1, "The target faints instantly. It's less likely to hit the target if it's used by Pokémon other than Ice types.", -1, 0, 3) .attr(OneHitKOAttr) .attr(OneHitKOAccuracyAttr), - new AttackMove(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 110, 85, 10, -1, "The user attacks by shooting muddy water at opposing Pokémon. This may also lower their accuracy.", 30, 0, 3) + new AttackMove(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "The user attacks by shooting muddy water at opposing Pokémon. This may also lower their accuracy.", 30, 0, 3) .attr(StatChangeAttr, BattleStat.ACC, -1) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BULLET_SEED, "Bullet Seed", Type.GRASS, MoveCategory.PHYSICAL, 25, 100, 30, 56, "The user forcefully shoots seeds at the target two to five times in a row.", -1, 0, 3) diff --git a/src/phases.ts b/src/phases.ts index 55c6fd577..0d5c9beec 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -181,11 +181,14 @@ export class TitlePhase extends Phase { noCancel: true }; this.scene.ui.setMode(Mode.OPTION_SELECT, config); + + this.scene.dailyRunScoreboard.showAndUpdate(true); } loadSaveSlot(slotId: integer): void { this.scene.sessionSlotId = slotId; this.scene.ui.setMode(Mode.MESSAGE); + this.scene.dailyRunScoreboard.hide(false); this.scene.gameData.loadSession(this.scene, slotId).then((success: boolean) => { if (success) { this.loaded = true; @@ -253,6 +256,8 @@ export class TitlePhase extends Phase { } end(): void { + this.scene.dailyRunScoreboard.hide(false); + if (!this.loaded && !this.scene.gameMode.isDaily) { this.scene.arena.preloadBgm(); this.scene.pushPhase(new SelectStarterPhase(this.scene)); diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts new file mode 100644 index 000000000..32521ab80 --- /dev/null +++ b/src/ui/daily-run-scoreboard.ts @@ -0,0 +1,97 @@ +import BattleScene from "../battle-scene"; +import { TextStyle, addTextObject } from "./text"; +import { WindowVariant, addWindow } from "./window"; +import * as Utils from "../utils"; + +interface RankingEntry { + rank: integer, + username: string, + score: integer +} + +export class DailyRunScoreboard extends Phaser.GameObjects.Container { + private loadingLabel: Phaser.GameObjects.Text; + private titleLabel: Phaser.GameObjects.Text; + private rankingsContainer: Phaser.GameObjects.Container; + + constructor(scene: BattleScene, x: number, y: number) { + super(scene, x, y); + + this.setup(); + } + + setup() { + const titleWindow = addWindow(this.scene, 0, 0, 110, 16, false, false, null, null, WindowVariant.THIN); + this.add(titleWindow); + + this.titleLabel = addTextObject(this.scene, titleWindow.displayWidth / 2, titleWindow.displayHeight / 2, 'Daily Rankings', TextStyle.WINDOW, { fontSize: '64px' }); + this.titleLabel.setOrigin(0.5, 0.5); + this.add(this.titleLabel); + + const window = addWindow(this.scene, 0, 15, 110, 115, false, false, null, null, WindowVariant.THIN); + this.add(window); + + this.rankingsContainer = this.scene.add.container(6, 19); + this.add(this.rankingsContainer); + + this.loadingLabel = addTextObject(this.scene, window.displayWidth / 2, window.displayHeight / 2 + 16, '', TextStyle.WINDOW); + this.loadingLabel.setOrigin(0.5, 0.5); + this.loadingLabel.setVisible(false); + + this.add(this.loadingLabel); + + this.setVisible(false); + } + + updateRankings(rankings: RankingEntry[]) { + const getEntry = (rank: string, username: string, score: string) => { + const entryContainer = this.scene.add.container(0, 0); + + const rankLabel = addTextObject(this.scene, 0, 0, rank, TextStyle.WINDOW, { fontSize: '54px' }); + entryContainer.add(rankLabel); + + const usernameLabel = addTextObject(this.scene, 12, 0, username, TextStyle.WINDOW, { fontSize: '54px' }); + entryContainer.add(usernameLabel); + + const scoreLabel = addTextObject(this.scene, 68, 0, score, TextStyle.WINDOW, { fontSize: '54px' }); + entryContainer.add(scoreLabel); + + return entryContainer; + }; + + this.rankingsContainer.add(getEntry('#', 'Username', 'Score')); + + rankings.forEach((r: RankingEntry, i: integer) => { + const entryContainer = getEntry(r.rank.toString(), r.username, r.score.toString()); + entryContainer.setY(r.rank * 9); + this.rankingsContainer.add(entryContainer); + }); + } + + showAndUpdate() { + this.rankingsContainer.removeAll(true); + + this.loadingLabel.setText('Loading…'); + this.loadingLabel.setVisible(true); + + Utils.apiFetch(`daily/rankings`) + .then(response => response.json()) + .then(jsonResponse => { + if (jsonResponse) { + this.loadingLabel.setVisible(false); + this.updateRankings(jsonResponse); + } else + this.loadingLabel.setText('No Rankings'); + }); + + this.setVisible(true); + } + + hide() { + this.setVisible(false); + } +} + +export interface DailyRunScoreboard { + scene: BattleScene +}; \ No newline at end of file