Add item shop when choosing items

Add item shop when choosing items; add full restore item; add egg art to egg gacha; fix some minor text errors
pull/14/head
Flashfyre 2024-02-04 00:30:19 -05:00
parent 8f55245a38
commit ac456fc5ba
8 changed files with 378 additions and 186 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -19,7 +19,7 @@ import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } fr
import { biomeDepths, biomeLinks } 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, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { BattlerTagLapseType, EncoreTag, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tags";
import { BattlerTagType } from "./data/enums/battler-tag-type";
@ -48,6 +48,7 @@ import { GameDataType } from "./system/game-data";
import { addPokeballCaptureStars, addPokeballOpenParticles } from "./anims";
import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeManualTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangeMoveUsedTrigger } from "./data/pokemon-forms";
import { battleSpecDialogue } from "./data/dialogue";
import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "./ui/modifier-select-ui-handler";
export class LoginPhase extends BattlePhase {
private showText: boolean;
@ -2735,7 +2736,7 @@ export class MoneyRewardPhase extends BattlePhase {
}
start() {
const moneyAmount = new Utils.IntegerHolder(this.scene.getMoneyAmountForWave(this.moneyMultiplier));
const moneyAmount = new Utils.IntegerHolder(this.scene.getWaveMoneyAmount(this.moneyMultiplier));
this.scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
@ -3464,57 +3465,88 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount);
const typeOptions: ModifierTypeOption[] = this.getModifierTypeOptions(modifierCount.value);
const modifierSelectCallback = (cursor: integer) => {
if (cursor < 0) {
const modifierSelectCallback = (rowCursor: integer, cursor: integer) => {
if (rowCursor < 0 || cursor < 0) {
this.scene.ui.setMode(Mode.MESSAGE);
super.end();
return true;
} else if (cursor === typeOptions.length) {
const rerollCost = this.getRerollCost();
if (this.scene.money < rerollCost) {
this.scene.ui.playError();
return false;
} else {
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1));
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
this.scene.money -= rerollCost;
this.scene.updateMoneyText();
this.scene.playSound('buy');
}
return true;
} else if (cursor === typeOptions.length + 1) {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, toSlotIndex: integer) => {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex];
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true).then(success => {
if (success) {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
super.end();
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
});
});
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
}, PartyUiHandler.FilterItemMaxStacks);
return true;
}
let modifierType: ModifierType;
let cost: integer;
switch (rowCursor) {
case 0:
if (!cursor) {
const rerollCost = this.getRerollCost();
if (this.scene.money < rerollCost) {
this.scene.ui.playError();
return false;
} else {
this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1));
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
this.scene.money -= rerollCost;
this.scene.updateMoneyText();
this.scene.playSound('buy');
}
} else {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, toSlotIndex: integer) => {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex];
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true).then(success => {
if (success) {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
super.end();
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
});
});
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
}, PartyUiHandler.FilterItemMaxStacks);
}
return true;
case 1:
modifierType = typeOptions[cursor].type;
break;
default:
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1));
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
modifierType = shopOption.type;
cost = shopOption.cost;
break;
}
const modifierType = typeOptions[cursor].type;
if (cost && this.scene.money < cost) {
this.scene.ui.playError();
return false;
}
const applyModifier = (modifier: Modifier, playSound: boolean = false) => {
this.scene.addModifier(modifier, false, playSound).then(() => {
if (cost) {
this.scene.money -= cost;
this.scene.updateMoneyText();
this.scene.playSound('buy');
(this.scene.ui.getHandler() as ModifierSelectUiHandler).updateCostText();
} else {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
super.end();
}
});
};
if (modifierType instanceof PokemonModifierType) {
if (modifierType instanceof FusePokemonModifierType) {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.SPLICE, -1, (fromSlotIndex: integer, spliceSlotIndex: integer) => {
if (spliceSlotIndex !== undefined && fromSlotIndex < 6 && spliceSlotIndex < 6 && fromSlotIndex !== spliceSlotIndex) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
const modifier = modifierType.newModifier(party[fromSlotIndex], party[spliceSlotIndex]);
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.addModifier(modifier, false, true).then(() => super.end());
applyModifier(modifier, true);
});
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
@ -3534,27 +3566,21 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.ui.setModeWithoutClear(Mode.PARTY, partyUiMode, -1, (slotIndex: integer, option: PartyOption) => {
if (slotIndex < 6) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
const modifierType = typeOptions[cursor].type;
const modifier = !isMoveModifier
? !isRememberMoveModifier
? modifierType.newModifier(party[slotIndex])
: modifierType.newModifier(party[slotIndex], option as integer)
: modifierType.newModifier(party[slotIndex], option - PartyOption.MOVE_1);
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.addModifier(modifier, false, true).then(() => super.end());
applyModifier(modifier, true);
});
} else
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
}, pokemonModifierType.selectFilter, modifierType instanceof PokemonMoveModifierType ? (modifierType as PokemonMoveModifierType).moveSelectFilter : undefined, tmMoveId);
}
} else {
this.addModifier(typeOptions[cursor].type.newModifier()).then(() => super.end());
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE);
}
} else
applyModifier(typeOptions[cursor].type.newModifier());
return true;
return !cost;
};
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost());
}

View File

@ -336,6 +336,7 @@ export default class BattleScene extends Phaser.Scene {
this.loadAtlas(`gacha_underlay_${key}`, 'egg');
});
this.loadImage('gacha_glass', 'egg');
this.loadImage('gacha_eggs', 'egg');
this.loadAtlas('gacha_hatch', 'egg');
this.loadImage('gacha_knob', 'egg');
@ -1437,7 +1438,7 @@ export default class BattleScene extends Phaser.Scene {
this.phaseQueue.push(new TurnInitPhase(this));
}
getMoneyAmountForWave(moneyMultiplier: number): integer {
getWaveMoneyAmount(moneyMultiplier: number): integer {
const waveIndex = this.currentBattle.waveIndex;
const waveSetIndex = Math.ceil(waveIndex / 10) - 1;
const moneyValue = Math.pow((waveSetIndex + 1 + (0.75 + (((waveIndex - 1) % 10) + 1) / 10)) * 100, 1 + 0.005 * waveSetIndex) * moneyMultiplier;

View File

@ -212,7 +212,6 @@ export class FixedBattleConfig {
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): GetTrainerFunc {
return (scene: BattleScene) => {
const rand = Utils.randSeedInt(trainerPool.length);
console.log(rand);
const trainerTypes: TrainerType[] = [];
for (let trainerPoolEntry of trainerPool) {
const trainerType = Array.isArray(trainerPoolEntry)

View File

@ -132,24 +132,26 @@ export class PokemonHeldItemModifierType extends PokemonModifierType {
export class PokemonHpRestoreModifierType extends PokemonModifierType {
protected restorePoints: integer;
protected restorePercent: integer;
protected healStatus: boolean;
constructor(name: string, restorePoints: integer, restorePercent: integer, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) {
super(name, restorePoints ? `Restore ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Restore ${restorePercent}% HP for one Pokémon`,
newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, false)),
constructor(name: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) {
super(name, restorePoints ? `Restore ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment ' : ''}`,
newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)),
selectFilter || ((pokemon: PlayerPokemon) => {
if (!pokemon.hp || pokemon.hp >= pokemon.getMaxHp())
if (!pokemon.hp || (pokemon.hp >= pokemon.getMaxHp() && (!this.healStatus || !pokemon.status)))
return PartyUiHandler.NoEffectMessage;
return null;
}), iconImage, group || 'potion');
this.restorePoints = restorePoints;
this.restorePercent = restorePercent;
this.healStatus = healStatus;
}
}
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
constructor(name: string, restorePercent: integer, iconImage?: string) {
super(name, 0, restorePercent, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, true),
super(name, 0, restorePercent, false, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true),
((pokemon: PlayerPokemon) => {
if (!pokemon.isFainted())
return PartyUiHandler.NoEffectMessage;
@ -367,7 +369,7 @@ export class AllPokemonLevelIncrementModifierType extends ModifierType {
function getBaseStatBoosterItemName(stat: Stat) {
switch (stat) {
case Stat.HP:
return 'Hp-Up';
return 'HP Up';
case Stat.ATK:
return 'Protein';
case Stat.DEF:
@ -397,13 +399,13 @@ export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierT
class AllPokemonFullHpRestoreModifierType extends ModifierType {
constructor(name: string, description?: string, newModifierFunc?: NewModifierFunc, iconImage?: string) {
super(name, description || `Restore 100% HP for all Pokémon`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100)), iconImage);
super(name, description || `Restore 100% HP for all Pokémon`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false)), iconImage);
}
}
class AllPokemonFullReviveModifierType extends AllPokemonFullHpRestoreModifierType {
constructor(name: string, iconImage?: string) {
super(name, `Revives all fainted Pokémon, restoring 100% HP`, (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, true), iconImage);
super(name, `Revives all fainted Pokémon, fully restoring HP`, (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false, true), iconImage);
}
}
@ -417,7 +419,7 @@ export class MoneyRewardModifierType extends ModifierType {
}
getDescription(scene: BattleScene): string {
return this.description.replace('{AMOUNT}', scene.getMoneyAmountForWave(this.moneyMultiplier).toLocaleString('en-US'));
return this.description.replace('{AMOUNT}', scene.getWaveMoneyAmount(this.moneyMultiplier).toLocaleString('en-US'));
}
}
@ -673,7 +675,8 @@ export const modifierTypes = {
POTION: () => new PokemonHpRestoreModifierType('Potion', 20, 10),
SUPER_POTION: () => new PokemonHpRestoreModifierType('Super Potion', 50, 25),
HYPER_POTION: () => new PokemonHpRestoreModifierType('Hyper Potion', 200, 50),
MAX_POTION: () => new PokemonHpRestoreModifierType('Max Potion', 100, 100),
MAX_POTION: () => new PokemonHpRestoreModifierType('Max Potion', 0, 100),
FULL_RESTORE: () => new PokemonHpRestoreModifierType('Full Restore', 0, 100, true),
REVIVE: () => new PokemonReviveModifierType('Revive', 50),
MAX_REVIVE: () => new PokemonReviveModifierType('Max Revive', 100),
@ -768,7 +771,7 @@ export const modifierTypes = {
HEALING_CHARM: () => new ModifierType('Healing Charm', 'Increases the effectiveness of HP restoring moves and items by 25% (excludes revives)',
(type, _args) => new Modifiers.HealingBoosterModifier(type, 1.25), 'healing_charm'),
CANDY_JAR: () => new ModifierType('Candy Jar', 'Increases the number of levels added by RARE CANDY items by 1', (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)),
CANDY_JAR: () => new ModifierType('Candy Jar', 'Increases the number of levels added by Rare Candy items by 1', (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)),
BERRY_POUCH: () => new ModifierType('Berry Pouch', 'Adds a 25% chance that a used berry will not be consumed',
(type, _args) => new Modifiers.PreserveBerryModifier(type)),
@ -869,6 +872,11 @@ const modifierPool = {
const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length, 3);
return thresholdPartyMemberCount;
}),
new WeightedModifierType(modifierTypes.FULL_RESTORE, (party: Pokemon[]) => {
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status).length, 3);
const thresholdPartyMemberCount = Math.floor((Math.min(party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length, 3) + statusEffectPartyMemberCount) / 2);
return thresholdPartyMemberCount;
}),
new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => {
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount * 3;
@ -1085,6 +1093,42 @@ export function getPlayerModifierTypeOptionsForWave(waveIndex: integer, count: i
return options;
}
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer): ModifierTypeOption[] {
if (!(waveIndex % 10))
return [];
const options = [
[
new ModifierTypeOption(modifierTypes.POTION(), false, baseCost * 0.1),
new ModifierTypeOption(modifierTypes.ETHER(), false, baseCost * 0.2),
new ModifierTypeOption(modifierTypes.REVIVE(), false, baseCost)
],
[
new ModifierTypeOption(modifierTypes.SUPER_POTION(), false, baseCost * 0.225),
new ModifierTypeOption(modifierTypes.ELIXIR(), false, baseCost * 0.5)
],
[
new ModifierTypeOption(modifierTypes.FULL_HEAL(), false, baseCost * 0.5),
new ModifierTypeOption(modifierTypes.MAX_ETHER(), false, baseCost * 0.5)
],
[
new ModifierTypeOption(modifierTypes.HYPER_POTION(), false, baseCost * 0.4),
new ModifierTypeOption(modifierTypes.MAX_REVIVE(), false, baseCost * 1.375)
],
[
new ModifierTypeOption(modifierTypes.MAX_POTION(), false, baseCost * 0.75),
new ModifierTypeOption(modifierTypes.MAX_ELIXIR(), false, baseCost * 1.25)
],
[
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), false, baseCost * 1.125)
],
[
new ModifierTypeOption(modifierTypes.SACRED_ASH(), false, baseCost * 6)
]
];
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
}
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: Modifiers.PersistentModifier[], scene: BattleScene): Modifiers.EnemyPersistentModifier {
const tierStackCount = tier === ModifierTier.ULTRA ? 10 : tier === ModifierTier.GREAT ? 5 : 1;
const retryCount = 50;
@ -1163,9 +1207,11 @@ export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType
export class ModifierTypeOption {
public type: ModifierType;
public upgraded: boolean;
public cost: integer;
constructor(type: ModifierType, upgraded: boolean) {
constructor(type: ModifierType, upgraded: boolean, cost: number = 0) {
this.type = type;
this.upgraded = upgraded;
this.cost = Math.round(cost);
}
}

View File

@ -836,13 +836,15 @@ export abstract class ConsumablePokemonModifier extends ConsumableModifier {
export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
private restorePoints: integer;
private restorePercent: number;
private healStatus: boolean;
public fainted: boolean;
constructor(type: ModifierType, pokemonId: integer, restorePoints: integer, restorePercent: number, fainted?: boolean) {
constructor(type: ModifierType, pokemonId: integer, restorePoints: integer, restorePercent: number, healStatus: boolean, fainted?: boolean) {
super(type, pokemonId);
this.restorePoints = restorePoints;
this.restorePercent = restorePercent;
this.healStatus = healStatus;
this.fainted = !!fainted;
}
@ -856,7 +858,7 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
let restorePoints = this.restorePoints;
if (!this.fainted)
restorePoints = Math.floor(restorePoints * (args[1] as number));
else
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());
}
@ -1323,7 +1325,7 @@ export class MoneyRewardModifier extends ConsumableModifier {
apply(args: any[]): boolean {
const scene = args[0] as BattleScene;
const moneyAmount = new Utils.IntegerHolder(scene.getMoneyAmountForWave(this.moneyMultiplier));
const moneyAmount = new Utils.IntegerHolder(scene.getWaveMoneyAmount(this.moneyMultiplier));
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);

View File

@ -80,6 +80,9 @@ export default class EggGachaUiHandler extends MessageUiHandler {
const gachaUnderlay = this.scene.add.sprite(115, 80, `gacha_underlay_${gachaTypeKey}`);
gachaUnderlay.setOrigin(0, 0);
const gachaEggs = this.scene.add.sprite(0, 0, 'gacha_eggs');
gachaEggs.setOrigin(0, 0);
const gachaGlass = this.scene.add.sprite(0, 0, 'gacha_glass');
gachaGlass.setOrigin(0, 0);
@ -118,6 +121,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
const gachaHatch = this.scene.add.sprite(115, 73, 'gacha_hatch');
gachaHatch.setOrigin(0, 0);
gachaContainer.add(gachaEggs);
gachaContainer.add(gachaUnderlay);
gachaContainer.add(gacha);
gachaContainer.add(gachaGlass);

View File

@ -1,21 +1,25 @@
import BattleScene, { Button } from "../battle-scene";
import { ModifierTypeOption } from "../modifier/modifier-type";
import { getPlayerShopModifierTypeOptionsForWave, ModifierTypeOption } from "../modifier/modifier-type";
import { getPokeballAtlasKey, PokeballType } from "../data/pokeball";
import { addTextObject, getModifierTierTextTint, getTextColor, TextStyle } from "./text";
import AwaitableUiHandler from "./awaitable-ui-handler";
import { Mode } from "./ui";
import { PokemonHeldItemModifier } from "../modifier/modifier";
export const SHOP_OPTIONS_ROW_LIMIT = 6;
export default class ModifierSelectUiHandler extends AwaitableUiHandler {
private modifierContainer: Phaser.GameObjects.Container;
private rerollButtonContainer: Phaser.GameObjects.Container;
private transferButtonContainer: Phaser.GameObjects.Container;
private rerollCostText: Phaser.GameObjects.Text;
private lastCursor: integer = 0;
private rowCursor: integer = 0;
private player: boolean;
private rerollCost: integer;
public options: ModifierOption[];
public shopOptionsRows: ModifierOption[][];
private cursorObj: Phaser.GameObjects.Image;
@ -23,6 +27,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
super(scene, Mode.CONFIRM);
this.options = [];
this.shopOptionsRows = [];
}
setup() {
@ -79,18 +84,38 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.rerollButtonContainer.setVisible(false);
this.rerollButtonContainer.setAlpha(0);
this.updateRerollCostText(args[3] as integer);
this.rerollCost = args[3] as integer;
this.updateRerollCostText();
const typeOptions = args[1] as ModifierTypeOption[];
const shopTypeOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1));
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;
for (let m = 0; m < typeOptions.length; m++) {
const sliceWidth = (this.scene.game.canvas.width / 6) / (typeOptions.length + 2);
const option = new ModifierOption(this.scene, sliceWidth * (m + 1) + (sliceWidth * 0.5), -this.scene.game.canvas.height / 12 - 24, typeOptions[m]);
const option = new ModifierOption(this.scene, sliceWidth * (m + 1) + (sliceWidth * 0.5), -this.scene.game.canvas.height / 12 + optionsYOffset, typeOptions[m]);
option.setScale(0.5);
this.scene.add.existing(option);
this.modifierContainer.add(option);
this.options.push(option);
}
for (let m = 0; m < shopTypeOptions.length; m++) {
const row = m < SHOP_OPTIONS_ROW_LIMIT ? 0 : 1;
const col = m < SHOP_OPTIONS_ROW_LIMIT ? m : m - SHOP_OPTIONS_ROW_LIMIT;
const rowOptions = shopTypeOptions.slice(row ? SHOP_OPTIONS_ROW_LIMIT : 0, row ? undefined : SHOP_OPTIONS_ROW_LIMIT);
const sliceWidth = (this.scene.game.canvas.width / SHOP_OPTIONS_ROW_LIMIT) / (rowOptions.length + 2);
const option = new ModifierOption(this.scene, sliceWidth * (col + 1) + (sliceWidth * 0.5), ((-this.scene.game.canvas.height / 12) - (this.scene.game.canvas.height / 32) - (40 - (28 * row - 1))), shopTypeOptions[m]);
option.setScale(0.375);
this.scene.add.existing(option);
this.modifierContainer.add(option);
if (row >= this.shopOptionsRows.length)
this.shopOptionsRows.push([]);
this.shopOptionsRows[row].push(option);
}
const hasUpgrade = typeOptions.filter(to => to.upgraded).length;
this.scene.showFieldOverlay(750);
@ -110,6 +135,11 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
}
});
this.scene.time.delayedCall(1000 + (hasUpgrade ? 2000 : 0), () => {
for (let shopOption of this.shopOptionsRows.flat())
shopOption.show(0);
});
this.scene.time.delayedCall(4000 + (hasUpgrade ? 2000 : 0), () => {
if (partyHasHeldItem) {
this.transferButtonContainer.setAlpha(0);
@ -132,6 +162,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
}
this.setCursor(0);
this.setRowCursor(1);
this.awaitingActionInput = true;
this.onActionInput = args[2];
});
@ -153,7 +184,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
const originalOnActionInput = this.onActionInput;
this.awaitingActionInput = false;
this.onActionInput = null;
if (!originalOnActionInput(this.cursor)) {
if (!originalOnActionInput(this.rowCursor, this.cursor)) {
this.awaitingActionInput = true;
this.onActionInput = originalOnActionInput;
}
@ -171,24 +202,28 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
} else {
switch (button) {
case Button.UP:
if (this.cursor >= this.options.length)
success = this.setCursor(this.lastCursor < this.options.length ? this.lastCursor : this.cursor - this.options.length ? this.options.length - 1 : 0);
if (this.rowCursor < this.shopOptionsRows.length + 1)
success = this.setRowCursor(this.rowCursor + 1);
break;
case Button.DOWN:
if (this.cursor < this.options.length && (this.rerollButtonContainer.visible || this.transferButtonContainer.visible)) {
const isLeftOption = this.cursor <= Math.floor(this.options.length / 2);
success = this.setCursor(this.options.length + (this.rerollButtonContainer.visible && (isLeftOption || !this.transferButtonContainer.visible) ? 0 : 1));
}
if (this.rowCursor)
success = this.setRowCursor(this.rowCursor - 1);
break;
case Button.LEFT:
if ((this.cursor || this.rerollButtonContainer.visible) && this.cursor !== this.options.length)
success = this.setCursor(this.cursor ? this.cursor - 1 : this.options.length);
if (!this.rowCursor)
success = this.rerollButtonContainer.visible && this.setCursor(0);
else if (this.cursor)
success = this.setCursor(this.cursor - 1);
else if (this.rowCursor === 1 && this.rerollButtonContainer.visible)
success = this.setRowCursor(0);
break;
case Button.RIGHT:
if (this.cursor < this.options.length - 1)
if (!this.rowCursor)
success = this.transferButtonContainer.visible && this.setCursor(1);
else if (this.cursor < this.getRowItems(this.rowCursor) - 1)
success = this.setCursor(this.cursor + 1);
else if (this.cursor === this.options.length && this.transferButtonContainer.visible)
success = this.setCursor(this.options.length + 1);
else if (this.rowCursor === 1 && this.transferButtonContainer.visible)
success = this.setRowCursor(0);
break;
}
}
@ -200,26 +235,26 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
}
setCursor(cursor: integer): boolean {
const lastCursor = this.cursor;
const ui = this.getUi();
const ret = super.setCursor(cursor);
if (ret)
this.lastCursor = lastCursor;
if (!this.cursorObj) {
this.cursorObj = this.scene.add.image(0, 0, 'cursor');
this.modifierContainer.add(this.cursorObj);
}
this.cursorObj.setScale(cursor < this.options.length ? 2 : 1);
const options = (this.rowCursor === 1 ? this.options : this.shopOptionsRows[this.shopOptionsRows.length - (this.rowCursor - 1)]);
if (cursor < this.options.length) {
const sliceWidth = (this.scene.game.canvas.width / 6) / (this.options.length + 2);
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, -this.scene.game.canvas.height / 12 - 20);
ui.showText(this.options[this.cursor].modifierTypeOption.type.getDescription(this.scene));
} else if (cursor === this.options.length) {
this.cursorObj.setScale(this.rowCursor === 1 ? 2 : this.rowCursor >= 2 ? 1.5 : 1);
if (this.rowCursor) {
let sliceWidth = (this.scene.game.canvas.width / 6) / (options.length + 2);
if (this.rowCursor < 2)
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? 6 : 22));
else
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-16 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1))));
ui.showText(options[this.cursor].modifierTypeOption.type.getDescription(this.scene));
} else if (!cursor) {
this.cursorObj.setPosition(6, -60);
ui.showText('Spend money to reroll your item options');
} else {
@ -230,10 +265,49 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
return ret;
}
updateRerollCostText(rerollCost: integer): void {
const canReroll = this.scene.money >= rerollCost;
setRowCursor(rowCursor: integer): boolean {
const lastRowCursor = this.rowCursor;
this.rerollCostText.setText(`${rerollCost.toLocaleString('en-US')}`);
if (rowCursor !== lastRowCursor && (rowCursor || this.rerollButtonContainer.visible || this.transferButtonContainer.visible)) {
this.rowCursor = rowCursor;
let newCursor = Math.round(this.cursor / Math.max(this.getRowItems(lastRowCursor) - 1, 1) * (this.getRowItems(rowCursor) - 1));
if (!rowCursor) {
if (!newCursor && !this.rerollButtonContainer.visible)
newCursor = 1;
else if (newCursor && !this.transferButtonContainer.visible)
newCursor = 0;
}
this.cursor = -1;
this.setCursor(newCursor);
return true;
}
return false;
}
private getRowItems(rowCursor: integer): integer {
switch (rowCursor) {
case 0:
return 2;
case 1:
return this.options.length;
default:
return this.shopOptionsRows[this.shopOptionsRows.length - (rowCursor - 1)].length;
}
}
updateCostText(): void {
const shopOptions = this.shopOptionsRows.flat();
for (let shopOption of shopOptions)
shopOption.updateCostText();
this.updateRerollCostText();
}
updateRerollCostText(): void {
const canReroll = this.scene.money >= this.rerollCost;
this.rerollCostText.setText(`${this.rerollCost.toLocaleString('en-US')}`);
this.rerollCostText.setColor(getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED));
this.rerollCostText.setShadowColor(getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED, true));
}
@ -248,8 +322,9 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.scene.hideFieldOverlay(250);
const options = this.options.slice(0);
const options = this.options.concat(this.shopOptionsRows.flat());
this.options.splice(0, this.options.length);
this.shopOptionsRows.splice(0, this.shopOptionsRows.length);
this.scene.tweens.add({
targets: options,
@ -292,6 +367,7 @@ class ModifierOption extends Phaser.GameObjects.Container {
private item: Phaser.GameObjects.Sprite;
private itemTint: Phaser.GameObjects.Sprite;
private itemText: Phaser.GameObjects.Text;
private itemCostText: Phaser.GameObjects.Text;
constructor(scene: BattleScene, x: number, y: number, modifierTypeOption: ModifierTypeOption) {
super(scene, x, y);
@ -302,18 +378,20 @@ class ModifierOption extends Phaser.GameObjects.Container {
}
setup() {
const getPb = (): Phaser.GameObjects.Sprite => {
const pb = this.scene.add.sprite(0, -150, 'pb', this.getPbAtlasKey(true));
pb.setScale(2);
return pb;
};
if (!this.modifierTypeOption.cost) {
const getPb = (): Phaser.GameObjects.Sprite => {
const pb = this.scene.add.sprite(0, -182, 'pb', this.getPbAtlasKey(true));
pb.setScale(2);
return pb;
};
this.pb = getPb();
this.add(this.pb);
this.pb = getPb();
this.add(this.pb);
this.pbTint = getPb();
this.pbTint.setVisible(false);
this.add(this.pbTint);
this.pbTint = getPb();
this.pbTint.setVisible(false);
this.add(this.pbTint);
}
this.itemContainer = this.scene.add.container(0, 0);
this.itemContainer.setScale(0.5);
@ -328,90 +406,107 @@ class ModifierOption extends Phaser.GameObjects.Container {
this.item = getItem();
this.itemContainer.add(this.item);
this.itemTint = getItem();
this.itemTint.setTintFill(Phaser.Display.Color.GetColor(255, 192, 255));
this.itemContainer.add(this.itemTint);
if (!this.modifierTypeOption.cost) {
this.itemTint = getItem();
this.itemTint.setTintFill(Phaser.Display.Color.GetColor(255, 192, 255));
this.itemContainer.add(this.itemTint);
}
this.itemText = addTextObject(this.scene, 0, 35, this.modifierTypeOption.type.name, TextStyle.PARTY, { align: 'center' });
this.itemText.setOrigin(0.5, 0);
this.itemText.setAlpha(0);
this.itemText.setTint(getModifierTierTextTint(this.modifierTypeOption.type.tier));
this.add(this.itemText);
if (this.modifierTypeOption.cost) {
this.itemCostText = addTextObject(this.scene, 0, 45, '', TextStyle.MONEY, { align: 'center' });
this.itemCostText.setOrigin(0.5, 0);
this.itemCostText.setAlpha(0);
this.add(this.itemCostText);
this.updateCostText();
}
}
show(remainingDuration: integer) {
this.scene.tweens.add({
targets: this.pb,
y: 0,
duration: 1250,
ease: 'Bounce.Out'
});
let lastValue = 1;
let bounceCount = 0;
let bounce = false;
this.scene.tweens.addCounter({
from: 1,
to: 0,
duration: 1250,
ease: 'Bounce.Out',
onUpdate: t => {
if (!this.scene)
return;
const value = t.getValue();
if (!bounce && value > lastValue) {
(this.scene as BattleScene).playSound('pb_bounce_1', { volume: 1 / ++bounceCount });
bounce = true;
} else if (bounce && value < lastValue)
bounce = false;
lastValue = value;
}
});
if (this.modifierTypeOption.upgraded) {
this.scene.time.delayedCall(remainingDuration, () => {
(this.scene as BattleScene).playSound('upgrade');
this.pbTint.setPosition(this.pb.x, this.pb.y);
this.pbTint.setTintFill(0xFFFFFF);
this.pbTint.setAlpha(0);
this.pbTint.setVisible(true);
this.scene.tweens.add({
targets: this.pbTint,
alpha: 1,
duration: 1000,
ease: 'Sine.easeIn',
onComplete: () => {
this.pb.setTexture('pb', this.getPbAtlasKey(false));
this.scene.tweens.add({
targets: this.pbTint,
alpha: 0,
duration: 1000,
ease: 'Sine.easeOut',
onComplete: () => {
this.pbTint.setVisible(false);
}
});
}
});
if (!this.modifierTypeOption.cost) {
this.scene.tweens.add({
targets: this.pb,
y: 0,
duration: 1250,
ease: 'Bounce.Out'
});
let lastValue = 1;
let bounceCount = 0;
let bounce = false;
this.scene.tweens.addCounter({
from: 1,
to: 0,
duration: 1250,
ease: 'Bounce.Out',
onUpdate: t => {
if (!this.scene)
return;
const value = t.getValue();
if (!bounce && value > lastValue) {
(this.scene as BattleScene).playSound('pb_bounce_1', { volume: 1 / ++bounceCount });
bounce = true;
} else if (bounce && value < lastValue)
bounce = false;
lastValue = value;
}
});
if (this.modifierTypeOption.upgraded) {
this.scene.time.delayedCall(remainingDuration, () => {
(this.scene as BattleScene).playSound('upgrade');
this.pbTint.setPosition(this.pb.x, this.pb.y);
this.pbTint.setTintFill(0xFFFFFF);
this.pbTint.setAlpha(0);
this.pbTint.setVisible(true);
this.scene.tweens.add({
targets: this.pbTint,
alpha: 1,
duration: 1000,
ease: 'Sine.easeIn',
onComplete: () => {
this.pb.setTexture('pb', this.getPbAtlasKey(false));
this.scene.tweens.add({
targets: this.pbTint,
alpha: 0,
duration: 1000,
ease: 'Sine.easeOut',
onComplete: () => {
this.pbTint.setVisible(false);
}
});
}
});
});
}
}
this.scene.time.delayedCall(remainingDuration + 2000, () => {
if (!this.scene)
return;
this.pb.setTexture('pb', `${this.getPbAtlasKey(false)}_open`);
(this.scene as BattleScene).playSound('pb_rel');
this.scene.tweens.add({
targets: this.pb,
duration: 500,
delay: 250,
ease: 'Sine.easeIn',
alpha: 0,
onComplete: () => this.pb.destroy()
})
if (!this.modifierTypeOption.cost) {
this.pb.setTexture('pb', `${this.getPbAtlasKey(false)}_open`);
(this.scene as BattleScene).playSound('pb_rel');
this.scene.tweens.add({
targets: this.pb,
duration: 500,
delay: 250,
ease: 'Sine.easeIn',
alpha: 0,
onComplete: () => this.pb.destroy()
});
}
this.scene.tweens.add({
targets: this.itemContainer,
duration: 500,
@ -419,13 +514,15 @@ class ModifierOption extends Phaser.GameObjects.Container {
scale: 2,
alpha: 1
});
this.scene.tweens.add({
targets: this.itemTint,
alpha: 0,
duration: 500,
ease: 'Sine.easeIn',
onComplete: () => this.itemTint.destroy()
});
if (!this.modifierTypeOption.cost) {
this.scene.tweens.add({
targets: this.itemTint,
alpha: 0,
duration: 500,
ease: 'Sine.easeIn',
onComplete: () => this.itemTint.destroy()
});
}
this.scene.tweens.add({
targets: this.itemText,
duration: 500,
@ -433,10 +530,27 @@ class ModifierOption extends Phaser.GameObjects.Container {
y: 25,
ease: 'Cubic.easeInOut'
});
})
if (this.itemCostText) {
this.scene.tweens.add({
targets: this.itemCostText,
duration: 500,
alpha: 1,
y: 35,
ease: 'Cubic.easeInOut'
});
}
});
}
getPbAtlasKey(beforeUpgrade: boolean) {
return getPokeballAtlasKey((this.modifierTypeOption.type.tier - (beforeUpgrade && this.modifierTypeOption.upgraded ? 1 : 0)) as integer as PokeballType);
}
updateCostText(): void {
const textStyle = this.modifierTypeOption.cost <= (this.scene as BattleScene).money ? TextStyle.MONEY : TextStyle.PARTY_RED;
this.itemCostText.setText(`${this.modifierTypeOption.cost.toLocaleString('en-US')}`);
this.itemCostText.setColor(getTextColor(textStyle));
this.itemCostText.setShadowColor(getTextColor(textStyle, true));
}
}