mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-12-12 00:26:15 +00:00
Merge branch 'beta' into variant_update_oct
This commit is contained in:
commit
fb94e7801b
@ -399,13 +399,13 @@
|
|||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 6,
|
"y": 6,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 72,
|
"x": 72,
|
||||||
"y": 55,
|
"y": 55,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -420,13 +420,13 @@
|
|||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 6,
|
"y": 6,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 72,
|
"x": 72,
|
||||||
"y": 55,
|
"y": 55,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -399,13 +399,13 @@
|
|||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 6,
|
"y": 6,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 72,
|
"x": 72,
|
||||||
"y": 55,
|
"y": 55,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -420,13 +420,13 @@
|
|||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 6,
|
"y": 6,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 72,
|
"x": 72,
|
||||||
"y": 55,
|
"y": 55,
|
||||||
"w": 36,
|
"w": 36,
|
||||||
"h": 55
|
"h": 54
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b44ee2173788018ffd5dc6b7b7fa159be5b9d514
|
Subproject commit fc4a1effd5170def3c8314208a52cd0d8e6913ef
|
@ -970,13 +970,16 @@ export class MoveEffectAttr extends MoveAttr {
|
|||||||
public lastHitOnly: boolean;
|
public lastHitOnly: boolean;
|
||||||
/** Should this effect only apply on the first target hit? */
|
/** Should this effect only apply on the first target hit? */
|
||||||
public firstTargetOnly: boolean;
|
public firstTargetOnly: boolean;
|
||||||
|
/** Overrides the secondary effect chance for this attr if set. */
|
||||||
|
public effectChanceOverride?: number;
|
||||||
|
|
||||||
constructor(selfTarget?: boolean, trigger?: MoveEffectTrigger, firstHitOnly: boolean = false, lastHitOnly: boolean = false, firstTargetOnly: boolean = false) {
|
constructor(selfTarget?: boolean, trigger?: MoveEffectTrigger, firstHitOnly: boolean = false, lastHitOnly: boolean = false, firstTargetOnly: boolean = false, effectChanceOverride?: number) {
|
||||||
super(selfTarget);
|
super(selfTarget);
|
||||||
this.trigger = trigger !== undefined ? trigger : MoveEffectTrigger.POST_APPLY;
|
this.trigger = trigger ?? MoveEffectTrigger.POST_APPLY;
|
||||||
this.firstHitOnly = firstHitOnly;
|
this.firstHitOnly = firstHitOnly;
|
||||||
this.lastHitOnly = lastHitOnly;
|
this.lastHitOnly = lastHitOnly;
|
||||||
this.firstTargetOnly = firstTargetOnly;
|
this.firstTargetOnly = firstTargetOnly;
|
||||||
|
this.effectChanceOverride = effectChanceOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1001,15 +1004,15 @@ export class MoveEffectAttr extends MoveAttr {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the used move's additional effect chance.
|
* Gets the used move's additional effect chance.
|
||||||
* If user's ability has MoveEffectChanceMultiplierAbAttr or IgnoreMoveEffectsAbAttr modifies the base chance.
|
* Chance is modified by {@linkcode MoveEffectChanceMultiplierAbAttr} and {@linkcode IgnoreMoveEffectsAbAttr}.
|
||||||
* @param user {@linkcode Pokemon} using this move
|
* @param user {@linkcode Pokemon} using this move
|
||||||
* @param target {@linkcode Pokemon} target of this move
|
* @param target {@linkcode Pokemon | Target} of this move
|
||||||
* @param move {@linkcode Move} being used
|
* @param move {@linkcode Move} being used
|
||||||
* @param selfEffect {@linkcode Boolean} if move targets user.
|
* @param selfEffect `true` if move targets user.
|
||||||
* @returns Move chance value.
|
* @returns Move effect chance value.
|
||||||
*/
|
*/
|
||||||
getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer {
|
getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer {
|
||||||
const moveChance = new Utils.NumberHolder(move.chance);
|
const moveChance = new Utils.NumberHolder(this.effectChanceOverride ?? move.chance);
|
||||||
|
|
||||||
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility);
|
applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility);
|
||||||
|
|
||||||
@ -2752,14 +2755,17 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute used for moves that change stat stages
|
* Attribute used for moves that change stat stages
|
||||||
* @param stats {@linkcode BattleStat} array of stats to be changed
|
*
|
||||||
* @param stages stages by which to change the stats, from -6 to 6
|
* @param stats {@linkcode BattleStat} Array of stat(s) to change
|
||||||
* @param selfTarget whether the changes are applied to the user (true) or the target (false)
|
* @param stages How many stages to change the stat(s) by, [-6, 6]
|
||||||
* @param condition {@linkcode MoveConditionFunc} optional condition to trigger the stat change
|
* @param selfTarget `true` if the move is self-targetting
|
||||||
* @param firstHitOnly whether the stat change only applies on the first hit of a multi hit move
|
* @param condition {@linkcode MoveConditionFunc} Optional condition to be checked in order to apply the changes
|
||||||
* @param moveEffectTrigger {@linkcode MoveEffectTrigger} the trigger for the effect to take place
|
* @param showMessage `true` to display a message; default `true`
|
||||||
* @param firstTargetOnly whether, if this is a multi target move, to only apply the effect after the first target is hit, rather than once for each target
|
* @param firstHitOnly `true` if only the first hit of a multi hit move should cause a stat stage change; default `false`
|
||||||
* @param lastHitOnly whether the effect should only apply after the last hit of a multi hit move
|
* @param moveEffectTrigger {@linkcode MoveEffectTrigger} When the stat change should trigger; default {@linkcode MoveEffectTrigger.HIT}
|
||||||
|
* @param firstTargetOnly `true` if a move that hits multiple pokemon should only trigger the stat change if it hits at least one pokemon, rather than once per hit pokemon; default `false`
|
||||||
|
* @param lastHitOnly `true` if the effect should only apply after the last hit of a multi hit move; default `false`
|
||||||
|
* @param effectChanceOverride Will override the move's normal secondary effect chance if specified
|
||||||
*
|
*
|
||||||
* @extends MoveEffectAttr
|
* @extends MoveEffectAttr
|
||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
@ -2767,14 +2773,14 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
|||||||
export class StatStageChangeAttr extends MoveEffectAttr {
|
export class StatStageChangeAttr extends MoveEffectAttr {
|
||||||
public stats: BattleStat[];
|
public stats: BattleStat[];
|
||||||
public stages: integer;
|
public stages: integer;
|
||||||
private condition: MoveConditionFunc | null;
|
private condition?: MoveConditionFunc | null;
|
||||||
private showMessage: boolean;
|
private showMessage: boolean;
|
||||||
|
|
||||||
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false) {
|
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false, effectChanceOverride?: number) {
|
||||||
super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly);
|
super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly, effectChanceOverride);
|
||||||
this.stats = stats;
|
this.stats = stats;
|
||||||
this.stages = stages;
|
this.stages = stages;
|
||||||
this.condition = condition!; // TODO: is this bang correct?
|
this.condition = condition;
|
||||||
this.showMessage = showMessage;
|
this.showMessage = showMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9556,9 +9562,8 @@ export function initMoves() {
|
|||||||
new AttackMove(Moves.TRIPLE_ARROWS, Type.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 30, 0, 8)
|
new AttackMove(Moves.TRIPLE_ARROWS, Type.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 30, 0, 8)
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.attr(HighCritAttr)
|
.attr(HighCritAttr)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 50)
|
||||||
.attr(FlinchAttr)
|
.attr(FlinchAttr),
|
||||||
.partial(),
|
|
||||||
new AttackMove(Moves.INFERNAL_PARADE, Type.GHOST, MoveCategory.SPECIAL, 60, 100, 15, 30, 0, 8)
|
new AttackMove(Moves.INFERNAL_PARADE, Type.GHOST, MoveCategory.SPECIAL, 60, 100, 15, 30, 0, 8)
|
||||||
.attr(StatusEffectAttr, StatusEffect.BURN)
|
.attr(StatusEffectAttr, StatusEffect.BURN)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1),
|
.attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1),
|
||||||
|
@ -2758,7 +2758,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
if (damage > 0) {
|
if (damage > 0) {
|
||||||
if (source.isPlayer()) {
|
if (source.isPlayer()) {
|
||||||
this.scene.validateAchvs(DamageAchv, damage);
|
this.scene.validateAchvs(DamageAchv, new Utils.NumberHolder(damage));
|
||||||
if (damage > this.scene.gameData.gameStats.highestDamage) {
|
if (damage > this.scene.gameData.gameStats.highestDamage) {
|
||||||
this.scene.gameData.gameStats.highestDamage = damage;
|
this.scene.gameData.gameStats.highestDamage = damage;
|
||||||
}
|
}
|
||||||
|
@ -156,6 +156,7 @@ class DefaultOverrides {
|
|||||||
readonly EGG_VARIANT_OVERRIDE: VariantTier | null = null;
|
readonly EGG_VARIANT_OVERRIDE: VariantTier | null = null;
|
||||||
readonly EGG_FREE_GACHA_PULLS_OVERRIDE: boolean = false;
|
readonly EGG_FREE_GACHA_PULLS_OVERRIDE: boolean = false;
|
||||||
readonly EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
|
readonly EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
|
||||||
|
readonly UNLIMITED_EGG_COUNT_OVERRIDE: boolean = false;
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// MYSTERY ENCOUNTER OVERRIDES
|
// MYSTERY ENCOUNTER OVERRIDES
|
||||||
|
@ -28,7 +28,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
this.scene.gameData.gameStats.highestLevel = this.level;
|
this.scene.gameData.gameStats.highestLevel = this.level;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scene.validateAchvs(LevelAchv, new Utils.IntegerHolder(this.level));
|
this.scene.validateAchvs(LevelAchv, new Utils.NumberHolder(this.level));
|
||||||
|
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
const prevStats = pokemon.stats.slice(0);
|
const prevStats = pokemon.stats.slice(0);
|
||||||
|
@ -81,6 +81,8 @@ const namespaceMap = {
|
|||||||
miscDialogue: "dialogue-misc",
|
miscDialogue: "dialogue-misc",
|
||||||
battleSpecDialogue: "dialogue-final-boss",
|
battleSpecDialogue: "dialogue-final-boss",
|
||||||
doubleBattleDialogue: "dialogue-double-battle",
|
doubleBattleDialogue: "dialogue-double-battle",
|
||||||
|
splashMessages: "splash-texts",
|
||||||
|
mysteryEncounterMessages: "mystery-encounter-texts",
|
||||||
};
|
};
|
||||||
|
|
||||||
//#region Functions
|
//#region Functions
|
||||||
|
@ -109,7 +109,7 @@ export class DamageAchv extends Achv {
|
|||||||
damageAmount: integer;
|
damageAmount: integer;
|
||||||
|
|
||||||
constructor(localizationKey: string, name: string, damageAmount: integer, iconImage: string, score: integer) {
|
constructor(localizationKey: string, name: string, damageAmount: integer, iconImage: string, score: integer) {
|
||||||
super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.damageAmount);
|
super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.damageAmount);
|
||||||
this.damageAmount = damageAmount;
|
this.damageAmount = damageAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ export class HealAchv extends Achv {
|
|||||||
healAmount: integer;
|
healAmount: integer;
|
||||||
|
|
||||||
constructor(localizationKey: string, name: string, healAmount: integer, iconImage: string, score: integer) {
|
constructor(localizationKey: string, name: string, healAmount: integer, iconImage: string, score: integer) {
|
||||||
super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.healAmount);
|
super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.healAmount);
|
||||||
this.healAmount = healAmount;
|
this.healAmount = healAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ export class LevelAchv extends Achv {
|
|||||||
level: integer;
|
level: integer;
|
||||||
|
|
||||||
constructor(localizationKey: string, name: string, level: integer, iconImage: string, score: integer) {
|
constructor(localizationKey: string, name: string, level: integer, iconImage: string, score: integer) {
|
||||||
super(localizationKey, name, "", iconImage, score, (scene: BattleScene, args: any[]) => (args[0] as Utils.IntegerHolder).value >= this.level);
|
super(localizationKey, name, "", iconImage, score, (scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.level);
|
||||||
this.level = level;
|
this.level = level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1125,10 +1125,16 @@ export class GameData {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the session data at the given slot when overwriting a save file
|
||||||
|
* For deleting the session of a finished run, use {@linkcode tryClearSession}
|
||||||
|
* @param slotId the slot to clear
|
||||||
|
* @returns Promise with result `true` if the session was deleted successfully, `false` otherwise
|
||||||
|
*/
|
||||||
deleteSession(slotId: integer): Promise<boolean> {
|
deleteSession(slotId: integer): Promise<boolean> {
|
||||||
return new Promise<boolean>(resolve => {
|
return new Promise<boolean>(resolve => {
|
||||||
if (bypassLogin) {
|
if (bypassLogin) {
|
||||||
localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`);
|
localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`);
|
||||||
return resolve(true);
|
return resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1139,7 +1145,7 @@ export class GameData {
|
|||||||
Utils.apiFetch(`savedata/session/delete?slot=${slotId}&clientSessionId=${clientSessionId}`, true).then(response => {
|
Utils.apiFetch(`savedata/session/delete?slot=${slotId}&clientSessionId=${clientSessionId}`, true).then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct?
|
loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct?
|
||||||
localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`);
|
localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
return response.text();
|
return response.text();
|
||||||
@ -1190,7 +1196,9 @@ export class GameData {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to clear session data. After session data is removed, attempt to update user info so the menu updates
|
* Attempt to clear session data after the end of a run
|
||||||
|
* After session data is removed, attempt to update user info so the menu updates
|
||||||
|
* To delete an unfinished run instead, use {@linkcode deleteSession}
|
||||||
*/
|
*/
|
||||||
async tryClearSession(scene: BattleScene, slotId: integer): Promise<[success: boolean, newClear: boolean]> {
|
async tryClearSession(scene: BattleScene, slotId: integer): Promise<[success: boolean, newClear: boolean]> {
|
||||||
let result: [boolean, boolean] = [ false, false ];
|
let result: [boolean, boolean] = [ false, false ];
|
||||||
@ -1204,7 +1212,7 @@ export class GameData {
|
|||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct?
|
loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct?
|
||||||
localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`);
|
localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsonResponse: PokerogueApiClearSessionData = await response.json();
|
const jsonResponse: PokerogueApiClearSessionData = await response.json();
|
||||||
|
60
src/test/moves/triple_arrows.test.ts
Normal file
60
src/test/moves/triple_arrows.test.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { allMoves, FlinchAttr, StatStageChangeAttr } from "#app/data/move";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
describe("Moves - Triple Arrows", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
const tripleArrows = allMoves[Moves.TRIPLE_ARROWS];
|
||||||
|
const flinchAttr = tripleArrows.getAttrs(FlinchAttr)[0];
|
||||||
|
const defDropAttr = tripleArrows.getAttrs(StatStageChangeAttr)[0];
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.moveset([ Moves.TRIPLE_ARROWS ])
|
||||||
|
.battleType("single")
|
||||||
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
.enemyAbility(Abilities.STURDY)
|
||||||
|
.enemyMoveset(Moves.SPLASH);
|
||||||
|
|
||||||
|
vi.spyOn(flinchAttr, "getMoveChance");
|
||||||
|
vi.spyOn(defDropAttr, "getMoveChance");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has a 30% flinch chance and 50% defense drop chance", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS ]);
|
||||||
|
|
||||||
|
game.move.select(Moves.TRIPLE_ARROWS);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(flinchAttr.getMoveChance).toHaveReturnedWith(30);
|
||||||
|
expect(defDropAttr.getMoveChance).toHaveReturnedWith(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is affected normally by Serene Grace", async () => {
|
||||||
|
game.override.ability(Abilities.SERENE_GRACE);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS ]);
|
||||||
|
|
||||||
|
game.move.select(Moves.TRIPLE_ARROWS);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(flinchAttr.getMoveChance).toHaveReturnedWith(60);
|
||||||
|
expect(defDropAttr.getMoveChance).toHaveReturnedWith(100);
|
||||||
|
});
|
||||||
|
});
|
@ -34,6 +34,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
private cursorObj: Phaser.GameObjects.Image;
|
private cursorObj: Phaser.GameObjects.Image;
|
||||||
private transitioning: boolean;
|
private transitioning: boolean;
|
||||||
private transitionCancelled: boolean;
|
private transitionCancelled: boolean;
|
||||||
|
private summaryFinished: boolean;
|
||||||
private defaultText: string;
|
private defaultText: string;
|
||||||
|
|
||||||
private scale: number = 0.1666666667;
|
private scale: number = 0.1666666667;
|
||||||
@ -479,7 +480,12 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showSummary(eggs: Egg[]): void {
|
showSummary(eggs: Egg[]): void {
|
||||||
this.transitioning = false;
|
// the overlay will appear faster if the egg pulling animation was skipped
|
||||||
|
const overlayEaseInDuration = this.getDelayValue(750);
|
||||||
|
|
||||||
|
this.summaryFinished = false;
|
||||||
|
this.transitionCancelled = false;
|
||||||
|
this.setTransitioning(true);
|
||||||
this.eggGachaSummaryContainer.setVisible(true);
|
this.eggGachaSummaryContainer.setVisible(true);
|
||||||
|
|
||||||
const eggScale = eggs.length < 20 ? 1 : 0.5;
|
const eggScale = eggs.length < 20 ? 1 : 0.5;
|
||||||
@ -488,12 +494,14 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
targets: this.eggGachaOverlay,
|
targets: this.eggGachaOverlay,
|
||||||
alpha: 0.5,
|
alpha: 0.5,
|
||||||
ease: "Sine.easeOut",
|
ease: "Sine.easeOut",
|
||||||
duration: 750,
|
duration: overlayEaseInDuration,
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
const rowItems = 5;
|
const rowItems = 5;
|
||||||
const rows = Math.ceil(eggs.length / rowItems);
|
const rows = Math.ceil(eggs.length / rowItems);
|
||||||
const cols = Math.min(eggs.length, rowItems);
|
const cols = Math.min(eggs.length, rowItems);
|
||||||
const height = this.eggGachaOverlay.displayHeight - this.eggGachaMessageBox.displayHeight;
|
const height = this.eggGachaOverlay.displayHeight - this.eggGachaMessageBox.displayHeight;
|
||||||
|
|
||||||
|
// Create sprites for each egg
|
||||||
const eggContainers = eggs.map((egg, t) => {
|
const eggContainers = eggs.map((egg, t) => {
|
||||||
const col = t % rowItems;
|
const col = t % rowItems;
|
||||||
const row = Math.floor(t / rowItems);
|
const row = Math.floor(t / rowItems);
|
||||||
@ -515,14 +523,24 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
eggContainers.forEach((eggContainer, e) => {
|
// If action/cancel was pressed when the overlay was easing in, show all eggs at once
|
||||||
this.scene.tweens.add({
|
// Otherwise show the eggs one by one with a small delay between each
|
||||||
targets: eggContainer,
|
eggContainers.forEach((eggContainer, index) => {
|
||||||
delay: this.getDelayValue(e * 100),
|
const delay = !this.transitionCancelled ? this.getDelayValue(index * 100) : 0;
|
||||||
duration: this.getDelayValue(350),
|
this.scene.time.delayedCall(delay, () =>
|
||||||
scale: eggScale,
|
this.scene.tweens.add({
|
||||||
ease: "Sine.easeOut"
|
targets: eggContainer,
|
||||||
});
|
duration: this.getDelayValue(350),
|
||||||
|
scale: eggScale,
|
||||||
|
ease: "Sine.easeOut",
|
||||||
|
onComplete: () => {
|
||||||
|
if (index === eggs.length - 1) {
|
||||||
|
this.setTransitioning(false);
|
||||||
|
this.summaryFinished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -540,6 +558,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
this.eggGachaSummaryContainer.setAlpha(1);
|
this.eggGachaSummaryContainer.setAlpha(1);
|
||||||
this.eggGachaSummaryContainer.removeAll(true);
|
this.eggGachaSummaryContainer.removeAll(true);
|
||||||
this.setTransitioning(false);
|
this.setTransitioning(false);
|
||||||
|
this.summaryFinished = false;
|
||||||
this.eggGachaOptionsContainer.setVisible(true);
|
this.eggGachaOptionsContainer.setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -613,7 +632,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (this.eggGachaSummaryContainer.visible) {
|
if (this.eggGachaSummaryContainer.visible) {
|
||||||
if (button === Button.ACTION || button === Button.CANCEL) {
|
if (this.summaryFinished && (button === Button.ACTION || button === Button.CANCEL)) {
|
||||||
this.hideSummary();
|
this.hideSummary();
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@ -625,7 +644,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
error = true;
|
error = true;
|
||||||
this.showError(i18next.t("egg:notEnoughVouchers"));
|
this.showError(i18next.t("egg:notEnoughVouchers"));
|
||||||
} else if (this.scene.gameData.eggs.length < 99) {
|
} else if (this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
|
||||||
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
this.consumeVouchers(VoucherType.REGULAR, 1);
|
this.consumeVouchers(VoucherType.REGULAR, 1);
|
||||||
}
|
}
|
||||||
@ -640,7 +659,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
error = true;
|
error = true;
|
||||||
this.showError(i18next.t("egg:notEnoughVouchers"));
|
this.showError(i18next.t("egg:notEnoughVouchers"));
|
||||||
} else if (this.scene.gameData.eggs.length < 95) {
|
} else if (this.scene.gameData.eggs.length < 95 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
|
||||||
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
this.consumeVouchers(VoucherType.PLUS, 1);
|
this.consumeVouchers(VoucherType.PLUS, 1);
|
||||||
}
|
}
|
||||||
@ -657,7 +676,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
|| (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)) {
|
|| (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)) {
|
||||||
error = true;
|
error = true;
|
||||||
this.showError(i18next.t("egg:notEnoughVouchers"));
|
this.showError(i18next.t("egg:notEnoughVouchers"));
|
||||||
} else if (this.scene.gameData.eggs.length < 90) {
|
} else if (this.scene.gameData.eggs.length < 90 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
|
||||||
if (this.cursor === 3) {
|
if (this.cursor === 3) {
|
||||||
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
this.consumeVouchers(VoucherType.PREMIUM, 1);
|
this.consumeVouchers(VoucherType.PREMIUM, 1);
|
||||||
@ -678,7 +697,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
error = true;
|
error = true;
|
||||||
this.showError(i18next.t("egg:notEnoughVouchers"));
|
this.showError(i18next.t("egg:notEnoughVouchers"));
|
||||||
} else if (this.scene.gameData.eggs.length < 75) {
|
} else if (this.scene.gameData.eggs.length < 75 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) {
|
||||||
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) {
|
||||||
this.consumeVouchers(VoucherType.GOLDEN, 1);
|
this.consumeVouchers(VoucherType.GOLDEN, 1);
|
||||||
}
|
}
|
||||||
|
@ -1789,7 +1789,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
options.push({
|
options.push({
|
||||||
label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`,
|
label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`,
|
||||||
handler: () => {
|
handler: () => {
|
||||||
if (this.scene.gameData.eggs.length < 99 && (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost)) {
|
if ((this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE)
|
||||||
|
&& (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost)) {
|
||||||
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) {
|
||||||
starterData.candyCount -= sameSpeciesEggCost;
|
starterData.candyCount -= sameSpeciesEggCost;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user