mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-25 16:26:25 +00:00
Merge branch 'beta' into eviolite_weight_bug
This commit is contained in:
commit
0ef983deb5
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"textures": [
|
"textures": [
|
||||||
{
|
{
|
||||||
"image": "statuses_es.png",
|
"image": "statuses_es-ES.png",
|
||||||
"format": "RGBA8888",
|
"format": "RGBA8888",
|
||||||
"size": {
|
"size": {
|
||||||
"w": 22,
|
"w": 22,
|
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 441 B |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"textures": [
|
"textures": [
|
||||||
{
|
{
|
||||||
"image": "types_es.png",
|
"image": "types_es-ES.png",
|
||||||
"format": "RGBA8888",
|
"format": "RGBA8888",
|
||||||
"size": {
|
"size": {
|
||||||
"w": 32,
|
"w": 32,
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@ -1 +1 @@
|
|||||||
Subproject commit 71390cba88f4103d0d2273d59a6dd8340a4fa54f
|
Subproject commit 3cf6d553541d79ba165387bc73fb06544d00f1f9
|
@ -323,6 +323,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
this.conditionalQueue = [];
|
this.conditionalQueue = [];
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
this.phaseQueuePrependSpliceIndex = -1;
|
||||||
this.nextCommandPhaseQueue = [];
|
this.nextCommandPhaseQueue = [];
|
||||||
|
this.eventManager = new TimedEventManager();
|
||||||
this.updateGameInfo();
|
this.updateGameInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +379,6 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
this.fieldSpritePipeline = new FieldSpritePipeline(this.game);
|
this.fieldSpritePipeline = new FieldSpritePipeline(this.game);
|
||||||
(this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.add("FieldSprite", this.fieldSpritePipeline);
|
(this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.add("FieldSprite", this.fieldSpritePipeline);
|
||||||
this.eventManager = new TimedEventManager();
|
|
||||||
|
|
||||||
this.launchBattle();
|
this.launchBattle();
|
||||||
}
|
}
|
||||||
|
360
src/data/move.ts
360
src/data/move.ts
@ -1049,31 +1049,80 @@ export enum MoveEffectTrigger {
|
|||||||
POST_TARGET,
|
POST_TARGET,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MoveEffectAttrOptions {
|
||||||
|
/**
|
||||||
|
* Defines when this effect should trigger in the move's effect order
|
||||||
|
* @see {@linkcode MoveEffectPhase}
|
||||||
|
*/
|
||||||
|
trigger?: MoveEffectTrigger;
|
||||||
|
/** Should this effect only apply on the first hit? */
|
||||||
|
firstHitOnly?: boolean;
|
||||||
|
/** Should this effect only apply on the last hit? */
|
||||||
|
lastHitOnly?: boolean;
|
||||||
|
/** Should this effect only apply on the first target hit? */
|
||||||
|
firstTargetOnly?: boolean;
|
||||||
|
/** Overrides the secondary effect chance for this attr if set. */
|
||||||
|
effectChanceOverride?: number;
|
||||||
|
}
|
||||||
|
|
||||||
/** Base class defining all Move Effect Attributes
|
/** Base class defining all Move Effect Attributes
|
||||||
* @extends MoveAttr
|
* @extends MoveAttr
|
||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class MoveEffectAttr extends MoveAttr {
|
export class MoveEffectAttr extends MoveAttr {
|
||||||
/** Defines when this effect should trigger in the move's effect order
|
/**
|
||||||
* @see {@linkcode phases.MoveEffectPhase.start}
|
* A container for this attribute's optional parameters
|
||||||
|
* @see {@linkcode MoveEffectAttrOptions} for supported params.
|
||||||
*/
|
*/
|
||||||
public trigger: MoveEffectTrigger;
|
protected options?: MoveEffectAttrOptions;
|
||||||
/** Should this effect only apply on the first hit? */
|
|
||||||
public firstHitOnly: boolean;
|
|
||||||
/** Should this effect only apply on the last hit? */
|
|
||||||
public lastHitOnly: boolean;
|
|
||||||
/** Should this effect only apply on the first target hit? */
|
|
||||||
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, effectChanceOverride?: number) {
|
constructor(selfTarget?: boolean, options?: MoveEffectAttrOptions) {
|
||||||
super(selfTarget);
|
super(selfTarget);
|
||||||
this.trigger = trigger ?? MoveEffectTrigger.POST_APPLY;
|
this.options = options;
|
||||||
this.firstHitOnly = firstHitOnly;
|
}
|
||||||
this.lastHitOnly = lastHitOnly;
|
|
||||||
this.firstTargetOnly = firstTargetOnly;
|
/**
|
||||||
this.effectChanceOverride = effectChanceOverride;
|
* Defines when this effect should trigger in the move's effect order.
|
||||||
|
* @default MoveEffectTrigger.POST_APPLY
|
||||||
|
* @see {@linkcode MoveEffectTrigger}
|
||||||
|
*/
|
||||||
|
public get trigger () {
|
||||||
|
return this.options?.trigger ?? MoveEffectTrigger.POST_APPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `true` if this effect should only trigger on the first hit of
|
||||||
|
* multi-hit moves.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
public get firstHitOnly () {
|
||||||
|
return this.options?.firstHitOnly ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `true` if this effect should only trigger on the last hit of
|
||||||
|
* multi-hit moves.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
public get lastHitOnly () {
|
||||||
|
return this.options?.lastHitOnly ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `true` if this effect should apply only upon hitting a target
|
||||||
|
* for the first time when targeting multiple {@linkcode Pokemon}.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
public get firstTargetOnly () {
|
||||||
|
return this.options?.firstTargetOnly ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If defined, overrides the move's base chance for this
|
||||||
|
* secondary effect to trigger.
|
||||||
|
*/
|
||||||
|
public get effectChanceOverride () {
|
||||||
|
return this.options?.effectChanceOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1398,7 +1447,7 @@ export class RecoilAttr extends MoveEffectAttr {
|
|||||||
private unblockable: boolean;
|
private unblockable: boolean;
|
||||||
|
|
||||||
constructor(useHp: boolean = false, damageRatio: number = 0.25, unblockable: boolean = false) {
|
constructor(useHp: boolean = false, damageRatio: number = 0.25, unblockable: boolean = false) {
|
||||||
super(true, MoveEffectTrigger.POST_APPLY, false, true);
|
super(true, { lastHitOnly: true });
|
||||||
|
|
||||||
this.useHp = useHp;
|
this.useHp = useHp;
|
||||||
this.damageRatio = damageRatio;
|
this.damageRatio = damageRatio;
|
||||||
@ -1456,7 +1505,7 @@ export class RecoilAttr extends MoveEffectAttr {
|
|||||||
**/
|
**/
|
||||||
export class SacrificialAttr extends MoveEffectAttr {
|
export class SacrificialAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.POST_TARGET);
|
super(true, { trigger: MoveEffectTrigger.POST_TARGET });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1489,7 +1538,7 @@ export class SacrificialAttr extends MoveEffectAttr {
|
|||||||
**/
|
**/
|
||||||
export class SacrificialAttrOnHit extends MoveEffectAttr {
|
export class SacrificialAttrOnHit extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.HIT);
|
super(true, { trigger: MoveEffectTrigger.HIT });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1528,7 +1577,7 @@ export class SacrificialAttrOnHit extends MoveEffectAttr {
|
|||||||
*/
|
*/
|
||||||
export class HalfSacrificialAttr extends MoveEffectAttr {
|
export class HalfSacrificialAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.POST_TARGET);
|
super(true, { trigger: MoveEffectTrigger.POST_TARGET });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1932,7 +1981,7 @@ export class HitHealAttr extends MoveEffectAttr {
|
|||||||
private healStat: EffectiveStat | null;
|
private healStat: EffectiveStat | null;
|
||||||
|
|
||||||
constructor(healRatio?: number | null, healStat?: EffectiveStat) {
|
constructor(healRatio?: number | null, healStat?: EffectiveStat) {
|
||||||
super(true, MoveEffectTrigger.HIT);
|
super(true, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.healRatio = healRatio ?? 0.5;
|
this.healRatio = healRatio ?? 0.5;
|
||||||
this.healStat = healStat ?? null;
|
this.healStat = healStat ?? null;
|
||||||
@ -2141,7 +2190,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
|
|||||||
public overrideStatus: boolean = false;
|
public overrideStatus: boolean = false;
|
||||||
|
|
||||||
constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) {
|
constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) {
|
||||||
super(selfTarget, MoveEffectTrigger.HIT);
|
super(selfTarget, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
this.turnsRemaining = turnsRemaining;
|
this.turnsRemaining = turnsRemaining;
|
||||||
@ -2214,7 +2263,7 @@ export class MultiStatusEffectAttr extends StatusEffectAttr {
|
|||||||
|
|
||||||
export class PsychoShiftEffectAttr extends MoveEffectAttr {
|
export class PsychoShiftEffectAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
@ -2251,7 +2300,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
|||||||
private chance: number;
|
private chance: number;
|
||||||
|
|
||||||
constructor(chance: number) {
|
constructor(chance: number) {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
this.chance = chance;
|
this.chance = chance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2312,7 +2361,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
|||||||
private berriesOnly: boolean;
|
private berriesOnly: boolean;
|
||||||
|
|
||||||
constructor(berriesOnly: boolean) {
|
constructor(berriesOnly: boolean) {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
this.berriesOnly = berriesOnly;
|
this.berriesOnly = berriesOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2386,7 +2435,7 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
|||||||
export class EatBerryAttr extends MoveEffectAttr {
|
export class EatBerryAttr extends MoveEffectAttr {
|
||||||
protected chosenBerry: BerryModifier | undefined;
|
protected chosenBerry: BerryModifier | undefined;
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.HIT);
|
super(true, { trigger: MoveEffectTrigger.HIT });
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Causes the target to eat a berry.
|
* Causes the target to eat a berry.
|
||||||
@ -2489,7 +2538,7 @@ export class HealStatusEffectAttr extends MoveEffectAttr {
|
|||||||
* @param ...effects - List of status effects to cure
|
* @param ...effects - List of status effects to cure
|
||||||
*/
|
*/
|
||||||
constructor(selfTarget: boolean, ...effects: StatusEffect[]) {
|
constructor(selfTarget: boolean, ...effects: StatusEffect[]) {
|
||||||
super(selfTarget, MoveEffectTrigger.POST_APPLY, false, true);
|
super(selfTarget, { lastHitOnly: true });
|
||||||
|
|
||||||
this.effects = effects;
|
this.effects = effects;
|
||||||
}
|
}
|
||||||
@ -2819,35 +2868,67 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of optional parameters that may be applied to stat stage changing effects
|
||||||
|
* @extends MoveEffectAttrOptions
|
||||||
|
* @see {@linkcode StatStageChangeAttr}
|
||||||
|
*/
|
||||||
|
interface StatStageChangeAttrOptions extends MoveEffectAttrOptions {
|
||||||
|
/** If defined, needs to be met in order for the stat change to apply */
|
||||||
|
condition?: MoveConditionFunc,
|
||||||
|
/** `true` to display a message */
|
||||||
|
showMessage?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute used for moves that change stat stages
|
* Attribute used for moves that change stat stages
|
||||||
*
|
*
|
||||||
* @param stats {@linkcode BattleStat} Array of stat(s) to change
|
* @param stats {@linkcode BattleStat} Array of stat(s) to change
|
||||||
* @param stages How many stages to change the stat(s) by, [-6, 6]
|
* @param stages How many stages to change the stat(s) by, [-6, 6]
|
||||||
* @param selfTarget `true` if the move is self-targetting
|
* @param selfTarget `true` if the move is self-targetting
|
||||||
* @param condition {@linkcode MoveConditionFunc} Optional condition to be checked in order to apply the changes
|
* @param options {@linkcode StatStageChangeAttrOptions} Container for any optional parameters for this attribute.
|
||||||
* @param showMessage `true` to display a message; default `true`
|
|
||||||
* @param firstHitOnly `true` if only the first hit of a multi hit move should cause a stat stage change; default `false`
|
|
||||||
* @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}
|
||||||
*/
|
*/
|
||||||
export class StatStageChangeAttr extends MoveEffectAttr {
|
export class StatStageChangeAttr extends MoveEffectAttr {
|
||||||
public stats: BattleStat[];
|
public stats: BattleStat[];
|
||||||
public stages: integer;
|
public stages: number;
|
||||||
private condition?: MoveConditionFunc | null;
|
/**
|
||||||
private showMessage: boolean;
|
* Container for optional parameters to this attribute.
|
||||||
|
* @see {@linkcode StatStageChangeAttrOptions} for available optional params
|
||||||
|
*/
|
||||||
|
protected override options?: StatStageChangeAttrOptions;
|
||||||
|
|
||||||
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) {
|
constructor(stats: BattleStat[], stages: number, selfTarget?: boolean, options?: StatStageChangeAttrOptions) {
|
||||||
super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly, effectChanceOverride);
|
super(selfTarget, options);
|
||||||
this.stats = stats;
|
this.stats = stats;
|
||||||
this.stages = stages;
|
this.stages = stages;
|
||||||
this.condition = condition;
|
this.options = options;
|
||||||
this.showMessage = showMessage;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The condition required for the stat stage change to apply.
|
||||||
|
* Defaults to `null` (i.e. no condition required).
|
||||||
|
*/
|
||||||
|
private get condition () {
|
||||||
|
return this.options?.condition ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `true` to display a message for the stat change.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
private get showMessage () {
|
||||||
|
return this.options?.showMessage ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates when the stat change should trigger
|
||||||
|
* @default MoveEffectTrigger.HIT
|
||||||
|
*/
|
||||||
|
public override get trigger () {
|
||||||
|
return this.options?.trigger ?? MoveEffectTrigger.HIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2932,20 +3013,6 @@ export class SecretPowerAttr extends MoveEffectAttr {
|
|||||||
super(false);
|
super(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to determine if the move should apply a secondary effect based on Secret Power's 30% chance
|
|
||||||
* @returns `true` if the move's secondary effect should apply
|
|
||||||
*/
|
|
||||||
override canApply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
|
||||||
this.effectChanceOverride = move.chance;
|
|
||||||
const moveChance = this.getMoveChance(user, target, move, this.selfTarget);
|
|
||||||
if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to apply the secondary effect to the target Pokemon
|
* Used to apply the secondary effect to the target Pokemon
|
||||||
* @returns `true` if a secondary effect is successfully applied
|
* @returns `true` if a secondary effect is successfully applied
|
||||||
@ -2962,8 +3029,6 @@ export class SecretPowerAttr extends MoveEffectAttr {
|
|||||||
const biome = user.scene.arena.biomeType;
|
const biome = user.scene.arena.biomeType;
|
||||||
secondaryEffect = this.determineBiomeEffect(biome);
|
secondaryEffect = this.determineBiomeEffect(biome);
|
||||||
}
|
}
|
||||||
// effectChanceOverride used in the application of the actual secondary effect
|
|
||||||
secondaryEffect.effectChanceOverride = 100;
|
|
||||||
return secondaryEffect.apply(user, target, move, []);
|
return secondaryEffect.apply(user, target, move, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3139,7 +3204,7 @@ export class CutHpStatStageBoostAttr extends StatStageChangeAttr {
|
|||||||
private messageCallback: ((user: Pokemon) => void) | undefined;
|
private messageCallback: ((user: Pokemon) => void) | undefined;
|
||||||
|
|
||||||
constructor(stat: BattleStat[], levels: integer, cutRatio: integer, messageCallback?: ((user: Pokemon) => void) | undefined) {
|
constructor(stat: BattleStat[], levels: integer, cutRatio: integer, messageCallback?: ((user: Pokemon) => void) | undefined) {
|
||||||
super(stat, levels, true, null, true);
|
super(stat, levels, true);
|
||||||
|
|
||||||
this.cutRatio = cutRatio;
|
this.cutRatio = cutRatio;
|
||||||
this.messageCallback = messageCallback;
|
this.messageCallback = messageCallback;
|
||||||
@ -4889,7 +4954,7 @@ export class BypassRedirectAttr extends MoveAttr {
|
|||||||
|
|
||||||
export class FrenzyAttr extends MoveEffectAttr {
|
export class FrenzyAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.HIT, false, true);
|
super(true, { trigger: MoveEffectTrigger.HIT, lastHitOnly: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]) {
|
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]) {
|
||||||
@ -4962,7 +5027,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
|||||||
private failOnOverlap: boolean;
|
private failOnOverlap: boolean;
|
||||||
|
|
||||||
constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: integer = 0, turnCountMax?: integer, lastHitOnly: boolean = false, cancelOnFail: boolean = false) {
|
constructor(tagType: BattlerTagType, selfTarget: boolean = false, failOnOverlap: boolean = false, turnCountMin: integer = 0, turnCountMax?: integer, lastHitOnly: boolean = false, cancelOnFail: boolean = false) {
|
||||||
super(selfTarget, MoveEffectTrigger.POST_APPLY, false, lastHitOnly);
|
super(selfTarget, { lastHitOnly: lastHitOnly });
|
||||||
|
|
||||||
this.tagType = tagType;
|
this.tagType = tagType;
|
||||||
this.turnCountMin = turnCountMin;
|
this.turnCountMin = turnCountMin;
|
||||||
@ -5397,7 +5462,7 @@ export class AddArenaTagAttr extends MoveEffectAttr {
|
|||||||
public selfSideTarget: boolean;
|
public selfSideTarget: boolean;
|
||||||
|
|
||||||
constructor(tagType: ArenaTagType, turnCount?: integer | null, failOnOverlap: boolean = false, selfSideTarget: boolean = false) {
|
constructor(tagType: ArenaTagType, turnCount?: integer | null, failOnOverlap: boolean = false, selfSideTarget: boolean = false) {
|
||||||
super(true, MoveEffectTrigger.POST_APPLY);
|
super(true);
|
||||||
|
|
||||||
this.tagType = tagType;
|
this.tagType = tagType;
|
||||||
this.turnCount = turnCount!; // TODO: is the bang correct?
|
this.turnCount = turnCount!; // TODO: is the bang correct?
|
||||||
@ -5435,7 +5500,7 @@ export class RemoveArenaTagsAttr extends MoveEffectAttr {
|
|||||||
public selfSideTarget: boolean;
|
public selfSideTarget: boolean;
|
||||||
|
|
||||||
constructor(tagTypes: ArenaTagType[], selfSideTarget: boolean) {
|
constructor(tagTypes: ArenaTagType[], selfSideTarget: boolean) {
|
||||||
super(true, MoveEffectTrigger.POST_APPLY);
|
super(true);
|
||||||
|
|
||||||
this.tagTypes = tagTypes;
|
this.tagTypes = tagTypes;
|
||||||
this.selfSideTarget = selfSideTarget;
|
this.selfSideTarget = selfSideTarget;
|
||||||
@ -5501,7 +5566,7 @@ export class RemoveArenaTrapAttr extends MoveEffectAttr {
|
|||||||
private targetBothSides: boolean;
|
private targetBothSides: boolean;
|
||||||
|
|
||||||
constructor(targetBothSides: boolean = false) {
|
constructor(targetBothSides: boolean = false) {
|
||||||
super(true, MoveEffectTrigger.PRE_APPLY);
|
super(true, { trigger: MoveEffectTrigger.PRE_APPLY });
|
||||||
this.targetBothSides = targetBothSides;
|
this.targetBothSides = targetBothSides;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5537,7 +5602,7 @@ export class RemoveScreensAttr extends MoveEffectAttr {
|
|||||||
private targetBothSides: boolean;
|
private targetBothSides: boolean;
|
||||||
|
|
||||||
constructor(targetBothSides: boolean = false) {
|
constructor(targetBothSides: boolean = false) {
|
||||||
super(true, MoveEffectTrigger.PRE_APPLY);
|
super(true, { trigger: MoveEffectTrigger.PRE_APPLY });
|
||||||
this.targetBothSides = targetBothSides;
|
this.targetBothSides = targetBothSides;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5575,7 +5640,7 @@ export class SwapArenaTagsAttr extends MoveEffectAttr {
|
|||||||
|
|
||||||
|
|
||||||
constructor(SwapTags: ArenaTagType[]) {
|
constructor(SwapTags: ArenaTagType[]) {
|
||||||
super(true, MoveEffectTrigger.POST_APPLY);
|
super(true);
|
||||||
this.SwapTags = SwapTags;
|
this.SwapTags = SwapTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5701,7 +5766,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
private selfSwitch: boolean = false,
|
private selfSwitch: boolean = false,
|
||||||
private switchType: SwitchType = SwitchType.SWITCH
|
private switchType: SwitchType = SwitchType.SWITCH
|
||||||
) {
|
) {
|
||||||
super(false, MoveEffectTrigger.POST_APPLY, false, true);
|
super(false, { lastHitOnly: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
isBatonPass() {
|
isBatonPass() {
|
||||||
@ -5750,6 +5815,11 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't allow wild mons to flee with U-turn et al
|
||||||
|
if (this.selfSwitch && !user.isPlayer() && move.category !== MoveCategory.STATUS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (switchOutTarget.hp > 0) {
|
if (switchOutTarget.hp > 0) {
|
||||||
switchOutTarget.leaveField(false);
|
switchOutTarget.leaveField(false);
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500);
|
user.scene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500);
|
||||||
@ -5834,7 +5904,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class ChillyReceptionAttr extends ForceSwitchOutAttr {
|
export class ChillyReceptionAttr extends ForceSwitchOutAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
user.scene.arena.trySetWeather(WeatherType.SNOW, true);
|
user.scene.arena.trySetWeather(WeatherType.SNOW, true);
|
||||||
@ -5852,7 +5921,7 @@ export class RemoveTypeAttr extends MoveEffectAttr {
|
|||||||
private messageCallback: ((user: Pokemon) => void) | undefined;
|
private messageCallback: ((user: Pokemon) => void) | undefined;
|
||||||
|
|
||||||
constructor(removedType: Type, messageCallback?: (user: Pokemon) => void) {
|
constructor(removedType: Type, messageCallback?: (user: Pokemon) => void) {
|
||||||
super(true, MoveEffectTrigger.POST_TARGET);
|
super(true, { trigger: MoveEffectTrigger.POST_TARGET });
|
||||||
this.removedType = removedType;
|
this.removedType = removedType;
|
||||||
this.messageCallback = messageCallback;
|
this.messageCallback = messageCallback;
|
||||||
|
|
||||||
@ -5921,22 +5990,114 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const biomeType = user.scene.arena.getTypeForBiome();
|
const terrainType = user.scene.arena.getTerrainType();
|
||||||
|
let typeChange: Type;
|
||||||
|
if (terrainType !== TerrainType.NONE) {
|
||||||
|
typeChange = this.getTypeForTerrain(user.scene.arena.getTerrainType());
|
||||||
|
} else {
|
||||||
|
typeChange = this.getTypeForBiome(user.scene.arena.biomeType);
|
||||||
|
}
|
||||||
|
|
||||||
user.summonData.types = [ biomeType ];
|
user.summonData.types = [ typeChange ];
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[biomeType]}`) }));
|
user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[typeChange]}`) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a type from the current terrain
|
||||||
|
* @param terrainType {@linkcode TerrainType}
|
||||||
|
* @returns {@linkcode Type}
|
||||||
|
*/
|
||||||
|
private getTypeForTerrain(terrainType: TerrainType): Type {
|
||||||
|
switch (terrainType) {
|
||||||
|
case TerrainType.ELECTRIC:
|
||||||
|
return Type.ELECTRIC;
|
||||||
|
case TerrainType.MISTY:
|
||||||
|
return Type.FAIRY;
|
||||||
|
case TerrainType.GRASSY:
|
||||||
|
return Type.GRASS;
|
||||||
|
case TerrainType.PSYCHIC:
|
||||||
|
return Type.PSYCHIC;
|
||||||
|
case TerrainType.NONE:
|
||||||
|
default:
|
||||||
|
return Type.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a type from the current biome
|
||||||
|
* @param biomeType {@linkcode Biome}
|
||||||
|
* @returns {@linkcode Type}
|
||||||
|
*/
|
||||||
|
private getTypeForBiome(biomeType: Biome): Type {
|
||||||
|
switch (biomeType) {
|
||||||
|
case Biome.TOWN:
|
||||||
|
case Biome.PLAINS:
|
||||||
|
case Biome.METROPOLIS:
|
||||||
|
return Type.NORMAL;
|
||||||
|
case Biome.GRASS:
|
||||||
|
case Biome.TALL_GRASS:
|
||||||
|
return Type.GRASS;
|
||||||
|
case Biome.FOREST:
|
||||||
|
case Biome.JUNGLE:
|
||||||
|
return Type.BUG;
|
||||||
|
case Biome.SLUM:
|
||||||
|
case Biome.SWAMP:
|
||||||
|
return Type.POISON;
|
||||||
|
case Biome.SEA:
|
||||||
|
case Biome.BEACH:
|
||||||
|
case Biome.LAKE:
|
||||||
|
case Biome.SEABED:
|
||||||
|
return Type.WATER;
|
||||||
|
case Biome.MOUNTAIN:
|
||||||
|
return Type.FLYING;
|
||||||
|
case Biome.BADLANDS:
|
||||||
|
return Type.GROUND;
|
||||||
|
case Biome.CAVE:
|
||||||
|
case Biome.DESERT:
|
||||||
|
return Type.ROCK;
|
||||||
|
case Biome.ICE_CAVE:
|
||||||
|
case Biome.SNOWY_FOREST:
|
||||||
|
return Type.ICE;
|
||||||
|
case Biome.MEADOW:
|
||||||
|
case Biome.FAIRY_CAVE:
|
||||||
|
case Biome.ISLAND:
|
||||||
|
return Type.FAIRY;
|
||||||
|
case Biome.POWER_PLANT:
|
||||||
|
return Type.ELECTRIC;
|
||||||
|
case Biome.VOLCANO:
|
||||||
|
return Type.FIRE;
|
||||||
|
case Biome.GRAVEYARD:
|
||||||
|
case Biome.TEMPLE:
|
||||||
|
return Type.GHOST;
|
||||||
|
case Biome.DOJO:
|
||||||
|
case Biome.CONSTRUCTION_SITE:
|
||||||
|
return Type.FIGHTING;
|
||||||
|
case Biome.FACTORY:
|
||||||
|
case Biome.LABORATORY:
|
||||||
|
return Type.STEEL;
|
||||||
|
case Biome.RUINS:
|
||||||
|
case Biome.SPACE:
|
||||||
|
return Type.PSYCHIC;
|
||||||
|
case Biome.WASTELAND:
|
||||||
|
case Biome.END:
|
||||||
|
return Type.DRAGON;
|
||||||
|
case Biome.ABYSS:
|
||||||
|
return Type.DARK;
|
||||||
|
default:
|
||||||
|
return Type.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeTypeAttr extends MoveEffectAttr {
|
export class ChangeTypeAttr extends MoveEffectAttr {
|
||||||
private type: Type;
|
private type: Type;
|
||||||
|
|
||||||
constructor(type: Type) {
|
constructor(type: Type) {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@ -5959,7 +6120,7 @@ export class AddTypeAttr extends MoveEffectAttr {
|
|||||||
private type: Type;
|
private type: Type;
|
||||||
|
|
||||||
constructor(type: Type) {
|
constructor(type: Type) {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@ -6486,7 +6647,7 @@ export class AbilityChangeAttr extends MoveEffectAttr {
|
|||||||
public ability: Abilities;
|
public ability: Abilities;
|
||||||
|
|
||||||
constructor(ability: Abilities, selfTarget?: boolean) {
|
constructor(ability: Abilities, selfTarget?: boolean) {
|
||||||
super(selfTarget, MoveEffectTrigger.HIT);
|
super(selfTarget, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.ability = ability;
|
this.ability = ability;
|
||||||
}
|
}
|
||||||
@ -6515,7 +6676,7 @@ export class AbilityCopyAttr extends MoveEffectAttr {
|
|||||||
public copyToPartner: boolean;
|
public copyToPartner: boolean;
|
||||||
|
|
||||||
constructor(copyToPartner: boolean = false) {
|
constructor(copyToPartner: boolean = false) {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
|
|
||||||
this.copyToPartner = copyToPartner;
|
this.copyToPartner = copyToPartner;
|
||||||
}
|
}
|
||||||
@ -6554,7 +6715,7 @@ export class AbilityGiveAttr extends MoveEffectAttr {
|
|||||||
public copyToPartner: boolean;
|
public copyToPartner: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(false, MoveEffectTrigger.HIT);
|
super(false, { trigger: MoveEffectTrigger.HIT });
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
@ -6866,7 +7027,7 @@ export class DiscourageFrequentUseAttr extends MoveAttr {
|
|||||||
|
|
||||||
export class MoneyAttr extends MoveEffectAttr {
|
export class MoneyAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.HIT, true);
|
super(true, { trigger: MoveEffectTrigger.HIT, firstHitOnly: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move): boolean {
|
||||||
@ -6883,7 +7044,7 @@ export class MoneyAttr extends MoveEffectAttr {
|
|||||||
*/
|
*/
|
||||||
export class DestinyBondAttr extends MoveEffectAttr {
|
export class DestinyBondAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true, MoveEffectTrigger.PRE_APPLY);
|
super(true, { trigger: MoveEffectTrigger.PRE_APPLY });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6933,7 +7094,7 @@ export class StatusIfBoostedAttr extends MoveEffectAttr {
|
|||||||
public effect: StatusEffect;
|
public effect: StatusEffect;
|
||||||
|
|
||||||
constructor(effect: StatusEffect) {
|
constructor(effect: StatusEffect) {
|
||||||
super(true, MoveEffectTrigger.HIT);
|
super(true, { trigger: MoveEffectTrigger.HIT });
|
||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7058,6 +7219,11 @@ const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target
|
|||||||
|
|
||||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => user.scene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => user.scene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
||||||
|
|
||||||
|
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
|
const party: Pokemon[] = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||||
|
return party.some(pokemon => pokemon.isActive() && !pokemon.isOnField());
|
||||||
|
};
|
||||||
|
|
||||||
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
||||||
|
|
||||||
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> {
|
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> {
|
||||||
@ -7967,6 +8133,7 @@ export function initMoves() {
|
|||||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
||||||
new SelfStatusMove(Moves.BATON_PASS, Type.NORMAL, -1, 40, -1, 0, 2)
|
new SelfStatusMove(Moves.BATON_PASS, Type.NORMAL, -1, 40, -1, 0, 2)
|
||||||
.attr(ForceSwitchOutAttr, true, SwitchType.BATON_PASS)
|
.attr(ForceSwitchOutAttr, true, SwitchType.BATON_PASS)
|
||||||
|
.condition(failIfLastInPartyCondition)
|
||||||
.hidesUser(),
|
.hidesUser(),
|
||||||
new StatusMove(Moves.ENCORE, Type.NORMAL, 100, 5, -1, 0, 2)
|
new StatusMove(Moves.ENCORE, Type.NORMAL, 100, 5, -1, 0, 2)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, true)
|
||||||
@ -8985,7 +9152,7 @@ export function initMoves() {
|
|||||||
// If any fielded pokémon is grass-type and grounded.
|
// If any fielded pokémon is grass-type and grounded.
|
||||||
return [ ...user.scene.getEnemyParty(), ...user.scene.getParty() ].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded());
|
return [ ...user.scene.getEnemyParty(), ...user.scene.getParty() ].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded());
|
||||||
})
|
})
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, (user, target, move) => target.isOfType(Type.GRASS) && target.isGrounded()),
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, { condition: (user, target, move) => target.isOfType(Type.GRASS) && target.isGrounded() }),
|
||||||
new StatusMove(Moves.STICKY_WEB, Type.BUG, -1, 20, -1, 0, 6)
|
new StatusMove(Moves.STICKY_WEB, Type.BUG, -1, 20, -1, 0, 6)
|
||||||
.attr(AddArenaTrapTagAttr, ArenaTagType.STICKY_WEB)
|
.attr(AddArenaTrapTagAttr, ArenaTagType.STICKY_WEB)
|
||||||
.target(MoveTarget.ENEMY_SIDE),
|
.target(MoveTarget.ENEMY_SIDE),
|
||||||
@ -9022,7 +9189,7 @@ export function initMoves() {
|
|||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new StatusMove(Moves.PARTING_SHOT, Type.DARK, 100, 20, -1, 0, 6)
|
new StatusMove(Moves.PARTING_SHOT, Type.DARK, 100, 20, -1, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, false, null, true, true, MoveEffectTrigger.PRE_APPLY)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, false, { trigger: MoveEffectTrigger.PRE_APPLY })
|
||||||
.attr(ForceSwitchOutAttr, true)
|
.attr(ForceSwitchOutAttr, true)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
new StatusMove(Moves.TOPSY_TURVY, Type.DARK, -1, 20, -1, 0, 6)
|
new StatusMove(Moves.TOPSY_TURVY, Type.DARK, -1, 20, -1, 0, 6)
|
||||||
@ -9037,7 +9204,7 @@ export function initMoves() {
|
|||||||
.condition(failIfLastCondition),
|
.condition(failIfLastCondition),
|
||||||
new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, -1, 0, 6)
|
new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, -1, 0, 6)
|
||||||
.target(MoveTarget.ALL)
|
.target(MoveTarget.ALL)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], 1, false, (user, target, move) => target.getTypes().includes(Type.GRASS) && !target.getTag(SemiInvulnerableTag)),
|
.attr(StatStageChangeAttr, [ Stat.DEF ], 1, false, { condition: (user, target, move) => target.getTypes().includes(Type.GRASS) && !target.getTag(SemiInvulnerableTag) }),
|
||||||
new StatusMove(Moves.GRASSY_TERRAIN, Type.GRASS, -1, 10, -1, 0, 6)
|
new StatusMove(Moves.GRASSY_TERRAIN, Type.GRASS, -1, 10, -1, 0, 6)
|
||||||
.attr(TerrainChangeAttr, TerrainType.GRASSY)
|
.attr(TerrainChangeAttr, TerrainType.GRASSY)
|
||||||
.target(MoveTarget.BOTH_SIDES),
|
.target(MoveTarget.BOTH_SIDES),
|
||||||
@ -9069,7 +9236,7 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], -1)
|
.attr(StatStageChangeAttr, [ Stat.SPATK ], -1)
|
||||||
.soundBased(),
|
.soundBased(),
|
||||||
new AttackMove(Moves.DIAMOND_STORM, Type.ROCK, MoveCategory.PHYSICAL, 100, 95, 5, 50, 0, 6)
|
new AttackMove(Moves.DIAMOND_STORM, Type.ROCK, MoveCategory.PHYSICAL, 100, 95, 5, 50, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], 2, true, undefined, undefined, undefined, undefined, true)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], 2, true, { firstTargetOnly: true })
|
||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.STEAM_ERUPTION, Type.WATER, MoveCategory.SPECIAL, 110, 95, 5, 30, 0, 6)
|
new AttackMove(Moves.STEAM_ERUPTION, Type.WATER, MoveCategory.SPECIAL, 110, 95, 5, 30, 0, 6)
|
||||||
@ -9095,7 +9262,7 @@ export function initMoves() {
|
|||||||
new StatusMove(Moves.EERIE_IMPULSE, Type.ELECTRIC, 100, 15, -1, 0, 6)
|
new StatusMove(Moves.EERIE_IMPULSE, Type.ELECTRIC, 100, 15, -1, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], -2),
|
.attr(StatStageChangeAttr, [ Stat.SPATK ], -2),
|
||||||
new StatusMove(Moves.VENOM_DRENCH, Type.POISON, 100, 20, -1, 0, 6)
|
new StatusMove(Moves.VENOM_DRENCH, Type.POISON, 100, 20, -1, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], -1, false, (user, target, move) => target.status?.effect === StatusEffect.POISON || target.status?.effect === StatusEffect.TOXIC)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], -1, false, { condition: (user, target, move) => target.status?.effect === StatusEffect.POISON || target.status?.effect === StatusEffect.TOXIC })
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6)
|
new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6)
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
@ -9106,7 +9273,7 @@ export function initMoves() {
|
|||||||
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
.attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new StatusMove(Moves.MAGNETIC_FLUX, Type.ELECTRIC, -1, 20, -1, 0, 6)
|
new StatusMove(Moves.MAGNETIC_FLUX, Type.ELECTRIC, -1, 20, -1, 0, 6)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)))
|
.attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], 1, false, { condition: (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)) })
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.target(MoveTarget.USER_AND_ALLIES)
|
.target(MoveTarget.USER_AND_ALLIES)
|
||||||
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))),
|
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))),
|
||||||
@ -9326,7 +9493,7 @@ export function initMoves() {
|
|||||||
new SelfStatusMove(Moves.LASER_FOCUS, Type.NORMAL, -1, 30, -1, 0, 7)
|
new SelfStatusMove(Moves.LASER_FOCUS, Type.NORMAL, -1, 30, -1, 0, 7)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false),
|
.attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false),
|
||||||
new StatusMove(Moves.GEAR_UP, Type.STEEL, -1, 20, -1, 0, 7)
|
new StatusMove(Moves.GEAR_UP, Type.STEEL, -1, 20, -1, 0, 7)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)))
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, { condition: (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false)) })
|
||||||
.ignoresSubstitute()
|
.ignoresSubstitute()
|
||||||
.target(MoveTarget.USER_AND_ALLIES)
|
.target(MoveTarget.USER_AND_ALLIES)
|
||||||
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))),
|
.condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))),
|
||||||
@ -9383,7 +9550,7 @@ export function initMoves() {
|
|||||||
.ballBombMove()
|
.ballBombMove()
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7)
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, true, null, true, false, MoveEffectTrigger.HIT, true)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, true, { firstTargetOnly: true })
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.DRAGON_HAMMER, Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 7),
|
new AttackMove(Moves.DRAGON_HAMMER, Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 7),
|
||||||
@ -9497,7 +9664,7 @@ export function initMoves() {
|
|||||||
.makesContact(false)
|
.makesContact(false)
|
||||||
.ignoresVirtual(),
|
.ignoresVirtual(),
|
||||||
new AttackMove(Moves.CLANGOROUS_SOULBLAZE, Type.DRAGON, MoveCategory.SPECIAL, 185, -1, 1, 100, 0, 7)
|
new AttackMove(Moves.CLANGOROUS_SOULBLAZE, Type.DRAGON, MoveCategory.SPECIAL, 185, -1, 1, 100, 0, 7)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, undefined, undefined, undefined, undefined, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, { firstTargetOnly: true })
|
||||||
.soundBased()
|
.soundBased()
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||||
.edgeCase() // I assume it needs clanging scales and Kommo-O
|
.edgeCase() // I assume it needs clanging scales and Kommo-O
|
||||||
@ -9735,8 +9902,8 @@ export function initMoves() {
|
|||||||
.attr(ClearTerrainAttr)
|
.attr(ClearTerrainAttr)
|
||||||
.condition((user, target, move) => !!user.scene.arena.terrain),
|
.condition((user, target, move) => !!user.scene.arena.terrain),
|
||||||
new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8)
|
new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true, { lastHitOnly: true })
|
||||||
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, true, { lastHitOnly: true })
|
||||||
.attr(MultiHitAttr)
|
.attr(MultiHitAttr)
|
||||||
.makesContact(false),
|
.makesContact(false),
|
||||||
new ChargingAttackMove(Moves.METEOR_BEAM, Type.ROCK, MoveCategory.SPECIAL, 120, 90, 10, -1, 0, 8)
|
new ChargingAttackMove(Moves.METEOR_BEAM, Type.ROCK, MoveCategory.SPECIAL, 120, 90, 10, -1, 0, 8)
|
||||||
@ -9870,7 +10037,7 @@ 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, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 50)
|
.attr(StatStageChangeAttr, [ Stat.DEF ], -1, false, { effectChanceOverride: 50 })
|
||||||
.attr(FlinchAttr),
|
.attr(FlinchAttr),
|
||||||
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)
|
||||||
@ -10006,7 +10173,7 @@ export function initMoves() {
|
|||||||
.attr(TeraMoveCategoryAttr)
|
.attr(TeraMoveCategoryAttr)
|
||||||
.attr(TeraBlastTypeAttr)
|
.attr(TeraBlastTypeAttr)
|
||||||
.attr(TeraBlastPowerAttr)
|
.attr(TeraBlastPowerAttr)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR))
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, { condition: (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR) })
|
||||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||||
new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9)
|
new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9)
|
||||||
.attr(ProtectAttr, BattlerTagType.SILK_TRAP)
|
.attr(ProtectAttr, BattlerTagType.SILK_TRAP)
|
||||||
@ -10090,7 +10257,7 @@ export function initMoves() {
|
|||||||
.attr(RemoveScreensAttr),
|
.attr(RemoveScreensAttr),
|
||||||
new AttackMove(Moves.MAKE_IT_RAIN, Type.STEEL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9)
|
new AttackMove(Moves.MAKE_IT_RAIN, Type.STEEL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9)
|
||||||
.attr(MoneyAttr)
|
.attr(MoneyAttr)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], -1, true, null, true, false, MoveEffectTrigger.HIT, true)
|
.attr(StatStageChangeAttr, [ Stat.SPATK ], -1, true, { firstTargetOnly: true })
|
||||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||||
new AttackMove(Moves.PSYBLADE, Type.PSYCHIC, MoveCategory.PHYSICAL, 80, 100, 15, -1, 0, 9)
|
new AttackMove(Moves.PSYBLADE, Type.PSYCHIC, MoveCategory.PHYSICAL, 80, 100, 15, -1, 0, 9)
|
||||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.ELECTRIC && user.isGrounded() ? 1.5 : 1)
|
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.ELECTRIC && user.isGrounded() ? 1.5 : 1)
|
||||||
@ -10107,12 +10274,13 @@ export function initMoves() {
|
|||||||
.makesContact(),
|
.makesContact(),
|
||||||
new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9)
|
new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9)
|
||||||
.attr(AddSubstituteAttr, 0.5)
|
.attr(AddSubstituteAttr, 0.5)
|
||||||
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL),
|
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL)
|
||||||
|
.condition(failIfLastInPartyCondition),
|
||||||
new SelfStatusMove(Moves.CHILLY_RECEPTION, Type.ICE, -1, 10, -1, 0, 9)
|
new SelfStatusMove(Moves.CHILLY_RECEPTION, Type.ICE, -1, 10, -1, 0, 9)
|
||||||
.attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
.attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
||||||
.attr(ChillyReceptionAttr, true),
|
.attr(ChillyReceptionAttr, true),
|
||||||
new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, -1, 0, 9)
|
new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, -1, 0, 9)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPD ], 1, true, null, true, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPD ], 1, true)
|
||||||
.attr(RemoveArenaTrapAttr, true)
|
.attr(RemoveArenaTrapAttr, true)
|
||||||
.attr(RemoveAllSubstitutesAttr),
|
.attr(RemoveAllSubstitutesAttr),
|
||||||
new StatusMove(Moves.SNOWSCAPE, Type.ICE, -1, 10, -1, 0, 9)
|
new StatusMove(Moves.SNOWSCAPE, Type.ICE, -1, 10, -1, 0, 9)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||||
import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config";
|
import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config";
|
||||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
import { ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import BattleScene from "#app/battle-scene";
|
import BattleScene from "#app/battle-scene";
|
||||||
@ -280,7 +280,7 @@ export const ClowningAroundEncounter: MysteryEncounter =
|
|||||||
let numRogue = 0;
|
let numRogue = 0;
|
||||||
items.filter(m => m.isTransferable && !(m instanceof BerryModifier))
|
items.filter(m => m.isTransferable && !(m instanceof BerryModifier))
|
||||||
.forEach(m => {
|
.forEach(m => {
|
||||||
const type = m.type.withTierFromPool();
|
const type = m.type.withTierFromPool(ModifierPoolType.PLAYER, party);
|
||||||
const tier = type.tier ?? ModifierTier.ULTRA;
|
const tier = type.tier ?? ModifierTier.ULTRA;
|
||||||
if (type.id === "GOLDEN_EGG" || tier === ModifierTier.ROGUE) {
|
if (type.id === "GOLDEN_EGG" || tier === ModifierTier.ROGUE) {
|
||||||
numRogue += m.stackCount;
|
numRogue += m.stackCount;
|
||||||
|
@ -418,7 +418,7 @@ export function generateModifierType(scene: BattleScene, modifier: () => Modifie
|
|||||||
// Populates item id and tier (order matters)
|
// Populates item id and tier (order matters)
|
||||||
result = result
|
result = result
|
||||||
.withIdFromFunc(modifierTypes[modifierId])
|
.withIdFromFunc(modifierTypes[modifierId])
|
||||||
.withTierFromPool();
|
.withTierFromPool(ModifierPoolType.PLAYER, scene.getParty());
|
||||||
|
|
||||||
return result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
return result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||||
}
|
}
|
||||||
|
@ -224,66 +224,6 @@ export class Arena {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypeForBiome() {
|
|
||||||
switch (this.biomeType) {
|
|
||||||
case Biome.TOWN:
|
|
||||||
case Biome.PLAINS:
|
|
||||||
case Biome.METROPOLIS:
|
|
||||||
return Type.NORMAL;
|
|
||||||
case Biome.GRASS:
|
|
||||||
case Biome.TALL_GRASS:
|
|
||||||
return Type.GRASS;
|
|
||||||
case Biome.FOREST:
|
|
||||||
case Biome.JUNGLE:
|
|
||||||
return Type.BUG;
|
|
||||||
case Biome.SLUM:
|
|
||||||
case Biome.SWAMP:
|
|
||||||
return Type.POISON;
|
|
||||||
case Biome.SEA:
|
|
||||||
case Biome.BEACH:
|
|
||||||
case Biome.LAKE:
|
|
||||||
case Biome.SEABED:
|
|
||||||
return Type.WATER;
|
|
||||||
case Biome.MOUNTAIN:
|
|
||||||
return Type.FLYING;
|
|
||||||
case Biome.BADLANDS:
|
|
||||||
return Type.GROUND;
|
|
||||||
case Biome.CAVE:
|
|
||||||
case Biome.DESERT:
|
|
||||||
return Type.ROCK;
|
|
||||||
case Biome.ICE_CAVE:
|
|
||||||
case Biome.SNOWY_FOREST:
|
|
||||||
return Type.ICE;
|
|
||||||
case Biome.MEADOW:
|
|
||||||
case Biome.FAIRY_CAVE:
|
|
||||||
case Biome.ISLAND:
|
|
||||||
return Type.FAIRY;
|
|
||||||
case Biome.POWER_PLANT:
|
|
||||||
return Type.ELECTRIC;
|
|
||||||
case Biome.VOLCANO:
|
|
||||||
return Type.FIRE;
|
|
||||||
case Biome.GRAVEYARD:
|
|
||||||
case Biome.TEMPLE:
|
|
||||||
return Type.GHOST;
|
|
||||||
case Biome.DOJO:
|
|
||||||
case Biome.CONSTRUCTION_SITE:
|
|
||||||
return Type.FIGHTING;
|
|
||||||
case Biome.FACTORY:
|
|
||||||
case Biome.LABORATORY:
|
|
||||||
return Type.STEEL;
|
|
||||||
case Biome.RUINS:
|
|
||||||
case Biome.SPACE:
|
|
||||||
return Type.PSYCHIC;
|
|
||||||
case Biome.WASTELAND:
|
|
||||||
case Biome.END:
|
|
||||||
return Type.DRAGON;
|
|
||||||
case Biome.ABYSS:
|
|
||||||
return Type.DARK;
|
|
||||||
default:
|
|
||||||
return Type.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getBgTerrainColorRatioForBiome(): number {
|
getBgTerrainColorRatioForBiome(): number {
|
||||||
switch (this.biomeType) {
|
switch (this.biomeType) {
|
||||||
case Biome.SPACE:
|
case Biome.SPACE:
|
||||||
|
@ -244,7 +244,7 @@ export class LoadingScene extends SceneBase {
|
|||||||
this.loadAtlas("statuses", "");
|
this.loadAtlas("statuses", "");
|
||||||
this.loadAtlas("types", "");
|
this.loadAtlas("types", "");
|
||||||
}
|
}
|
||||||
const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN" ];
|
const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ];
|
||||||
if (lang && availableLangs.includes(lang)) {
|
if (lang && availableLangs.includes(lang)) {
|
||||||
this.loadImage("halloween2024-event-" + lang, "events");
|
this.loadImage("halloween2024-event-" + lang, "events");
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,7 +19,7 @@ import { Unlockables } from "#app/system/unlockables";
|
|||||||
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher";
|
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher";
|
||||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||||
import { getModifierTierTextTint } from "#app/ui/text";
|
import { getModifierTierTextTint } from "#app/ui/text";
|
||||||
import { formatMoney, getEnumKeys, getEnumValues, IntegerHolder, NumberHolder, padInt, randSeedInt, randSeedItem } from "#app/utils";
|
import { formatMoney, getEnumKeys, getEnumValues, IntegerHolder, isNullOrUndefined, NumberHolder, padInt, randSeedInt, randSeedItem } from "#app/utils";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
@ -121,17 +121,40 @@ export class ModifierType {
|
|||||||
* Populates item tier for ModifierType instance
|
* Populates item tier for ModifierType instance
|
||||||
* Tier is a necessary field for items that appear in player shop (determines the Pokeball visual they use)
|
* Tier is a necessary field for items that appear in player shop (determines the Pokeball visual they use)
|
||||||
* To find the tier, this function performs a reverse lookup of the item type in modifier pools
|
* To find the tier, this function performs a reverse lookup of the item type in modifier pools
|
||||||
|
* It checks the weight of the item and will use the first tier for which the weight is greater than 0
|
||||||
|
* This is to allow items to be in multiple item pools depending on the conditions, for example for events
|
||||||
|
* If all tiers have a weight of 0 for the item, the first tier where the item was found is used
|
||||||
* @param poolType Default 'ModifierPoolType.PLAYER'. Which pool to lookup item tier from
|
* @param poolType Default 'ModifierPoolType.PLAYER'. Which pool to lookup item tier from
|
||||||
|
* @param party optional. Needed to check the weight of modifiers with conditional weight (see {@linkcode WeightedModifierTypeWeightFunc})
|
||||||
|
* if not provided or empty, the weight check will be ignored
|
||||||
|
* @param rerollCount Default `0`. Used to check the weight of modifiers with conditional weight (see {@linkcode WeightedModifierTypeWeightFunc})
|
||||||
*/
|
*/
|
||||||
withTierFromPool(poolType: ModifierPoolType = ModifierPoolType.PLAYER): ModifierType {
|
withTierFromPool(poolType: ModifierPoolType = ModifierPoolType.PLAYER, party?: PlayerPokemon[], rerollCount: number = 0): ModifierType {
|
||||||
|
let defaultTier: undefined | ModifierTier;
|
||||||
for (const tier of Object.values(getModifierPoolForType(poolType))) {
|
for (const tier of Object.values(getModifierPoolForType(poolType))) {
|
||||||
for (const modifier of tier) {
|
for (const modifier of tier) {
|
||||||
if (this.id === modifier.modifierType.id) {
|
if (this.id === modifier.modifierType.id) {
|
||||||
|
let weight: number;
|
||||||
|
if (modifier.weight instanceof Function) {
|
||||||
|
weight = party ? modifier.weight(party, rerollCount) : 0;
|
||||||
|
} else {
|
||||||
|
weight = modifier.weight;
|
||||||
|
}
|
||||||
|
if (weight > 0) {
|
||||||
this.tier = modifier.modifierType.tier;
|
this.tier = modifier.modifierType.tier;
|
||||||
return this;
|
return this;
|
||||||
|
} else if (isNullOrUndefined(defaultTier)) {
|
||||||
|
// If weight is 0, keep track of the first tier where the item was found
|
||||||
|
defaultTier = modifier.modifierType.tier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Didn't find a pool with weight > 0, fallback to first tier where the item was found, if any
|
||||||
|
if (defaultTier) {
|
||||||
|
this.tier = defaultTier;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -2123,7 +2146,7 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo
|
|||||||
// Populates item id and tier
|
// Populates item id and tier
|
||||||
guaranteedMod = guaranteedMod
|
guaranteedMod = guaranteedMod
|
||||||
.withIdFromFunc(modifierTypes[modifierId])
|
.withIdFromFunc(modifierTypes[modifierId])
|
||||||
.withTierFromPool();
|
.withTierFromPool(ModifierPoolType.PLAYER, party);
|
||||||
|
|
||||||
const modType = guaranteedMod instanceof ModifierTypeGenerator ? guaranteedMod.generateType(party) : guaranteedMod;
|
const modType = guaranteedMod instanceof ModifierTypeGenerator ? guaranteedMod.generateType(party) : guaranteedMod;
|
||||||
if (modType) {
|
if (modType) {
|
||||||
@ -2192,7 +2215,7 @@ export function overridePlayerModifierTypeOptions(options: ModifierTypeOption[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (modifierType) {
|
if (modifierType) {
|
||||||
options[i].type = modifierType.withIdFromFunc(modifierFunc).withTierFromPool();
|
options[i].type = modifierType.withIdFromFunc(modifierFunc).withTierFromPool(ModifierPoolType.PLAYER, party);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ export async function initI18n(): Promise<void> {
|
|||||||
i18next.use(new KoreanPostpositionProcessor());
|
i18next.use(new KoreanPostpositionProcessor());
|
||||||
await i18next.init({
|
await i18next.init({
|
||||||
fallbackLng: "en",
|
fallbackLng: "en",
|
||||||
supportedLngs: [ "en", "es", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca-ES" ],
|
supportedLngs: [ "en", "es-ES", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca-ES" ],
|
||||||
backend: {
|
backend: {
|
||||||
loadPath(lng: string, [ ns ]: string[]) {
|
loadPath(lng: string, [ ns ]: string[]) {
|
||||||
let fileName: string;
|
let fileName: string;
|
||||||
|
@ -866,8 +866,8 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
|
|||||||
handler: () => changeLocaleHandler("en")
|
handler: () => changeLocaleHandler("en")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Español",
|
label: "Español (ES)",
|
||||||
handler: () => changeLocaleHandler("es")
|
handler: () => changeLocaleHandler("es-ES")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Italiano",
|
label: "Italiano",
|
||||||
|
49
src/test/moves/camouflage.test.ts
Normal file
49
src/test/moves/camouflage.test.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { TerrainType } from "#app/data/terrain";
|
||||||
|
import { Type } from "#app/data/type";
|
||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Moves - Camouflage", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.moveset([ Moves.CAMOUFLAGE ])
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.battleType("single")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(Species.REGIELEKI)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.PSYCHIC_TERRAIN);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Camouflage should look at terrain first when selecting a type to change into", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.SHUCKLE ]);
|
||||||
|
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.CAMOUFLAGE);
|
||||||
|
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
expect(game.scene.arena.getTerrainType()).toBe(TerrainType.PSYCHIC);
|
||||||
|
const pokemonType = playerPokemon.getTypes()[0];
|
||||||
|
expect(pokemonType).toBe(Type.PSYCHIC);
|
||||||
|
});
|
||||||
|
});
|
@ -2,7 +2,7 @@ import { Abilities } from "#enums/abilities";
|
|||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { allMoves, SecretPowerAttr } from "#app/data/move";
|
import { allMoves } from "#app/data/move";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import GameManager from "#test/utils/gameManager";
|
import GameManager from "#test/utils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
@ -11,6 +11,7 @@ import { StatusEffect } from "#enums/status-effect";
|
|||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { ArenaTagSide } from "#app/data/arena-tag";
|
import { ArenaTagSide } from "#app/data/arena-tag";
|
||||||
|
import { allAbilities, MoveEffectChanceMultiplierAbAttr } from "#app/data/ability";
|
||||||
|
|
||||||
describe("Moves - Secret Power", () => {
|
describe("Moves - Secret Power", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -60,30 +61,38 @@ describe("Moves - Secret Power", () => {
|
|||||||
expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-1);
|
expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("the 'rainbow' effect of fire+water pledge does not double the chance of secret power's secondary effect",
|
it("Secret Power's effect chance is doubled by Serene Grace, but not by the 'rainbow' effect from Fire/Water Pledge",
|
||||||
async () => {
|
async () => {
|
||||||
game.override
|
game.override
|
||||||
.moveset([ Moves.FIRE_PLEDGE, Moves.WATER_PLEDGE, Moves.SECRET_POWER, Moves.SPLASH ])
|
.moveset([ Moves.FIRE_PLEDGE, Moves.WATER_PLEDGE, Moves.SECRET_POWER, Moves.SPLASH ])
|
||||||
|
.ability(Abilities.SERENE_GRACE)
|
||||||
.enemyMoveset([ Moves.SPLASH ])
|
.enemyMoveset([ Moves.SPLASH ])
|
||||||
.battleType("double");
|
.battleType("double");
|
||||||
await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]);
|
await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]);
|
||||||
|
|
||||||
const secretPowerAttr = allMoves[Moves.SECRET_POWER].getAttrs(SecretPowerAttr)[0];
|
const sereneGraceAttr = allAbilities[Abilities.SERENE_GRACE].getAttrs(MoveEffectChanceMultiplierAbAttr)[0];
|
||||||
vi.spyOn(secretPowerAttr, "getMoveChance");
|
vi.spyOn(sereneGraceAttr, "apply");
|
||||||
|
|
||||||
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
||||||
game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2);
|
game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2);
|
||||||
|
|
||||||
await game.phaseInterceptor.to("TurnEndPhase");
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
expect(game.scene.arena.getTagOnSide(ArenaTagType.WATER_FIRE_PLEDGE, ArenaTagSide.PLAYER)).toBeDefined();
|
let rainbowEffect = game.scene.arena.getTagOnSide(ArenaTagType.WATER_FIRE_PLEDGE, ArenaTagSide.PLAYER);
|
||||||
|
expect(rainbowEffect).toBeDefined();
|
||||||
|
|
||||||
|
rainbowEffect = rainbowEffect!;
|
||||||
|
vi.spyOn(rainbowEffect, "apply");
|
||||||
|
|
||||||
game.move.select(Moves.SECRET_POWER, 0, BattlerIndex.ENEMY);
|
game.move.select(Moves.SECRET_POWER, 0, BattlerIndex.ENEMY);
|
||||||
game.move.select(Moves.SPLASH, 1);
|
game.move.select(Moves.SPLASH, 1);
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
await game.phaseInterceptor.to("BerryPhase", false);
|
||||||
|
|
||||||
expect(secretPowerAttr.getMoveChance).toHaveLastReturnedWith(30);
|
expect(sereneGraceAttr.apply).toHaveBeenCalledOnce();
|
||||||
|
expect(sereneGraceAttr.apply).toHaveLastReturnedWith(true);
|
||||||
|
|
||||||
|
expect(rainbowEffect.apply).toHaveBeenCalledTimes(0);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { SubstituteTag } from "#app/data/battler-tags";
|
import { SubstituteTag } from "#app/data/battler-tags";
|
||||||
|
import { MoveResult } from "#app/field/pokemon";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
@ -53,4 +54,18 @@ describe("Moves - Shed Tail", () => {
|
|||||||
expect(substituteTag).toBeDefined();
|
expect(substituteTag).toBeDefined();
|
||||||
expect(substituteTag?.hp).toBe(Math.floor(magikarp.getMaxHp() / 4));
|
expect(substituteTag?.hp).toBe(Math.floor(magikarp.getMaxHp() / 4));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should fail if no ally is available to switch in", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const magikarp = game.scene.getPlayerPokemon()!;
|
||||||
|
expect(game.scene.getParty().length).toBe(1);
|
||||||
|
|
||||||
|
game.move.select(Moves.SHED_TAIL);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase", false);
|
||||||
|
|
||||||
|
expect(magikarp.isOnField()).toBeTruthy();
|
||||||
|
expect(magikarp.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,6 +24,7 @@ import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin;
|
|||||||
import EventEmitter = Phaser.Events.EventEmitter;
|
import EventEmitter = Phaser.Events.EventEmitter;
|
||||||
import UpdateList = Phaser.GameObjects.UpdateList;
|
import UpdateList = Phaser.GameObjects.UpdateList;
|
||||||
import { version } from "../../../package.json";
|
import { version } from "../../../package.json";
|
||||||
|
import { MockTimedEventManager } from "./mocks/mockTimedEventManager";
|
||||||
|
|
||||||
Object.defineProperty(window, "localStorage", {
|
Object.defineProperty(window, "localStorage", {
|
||||||
value: mockLocalStorage(),
|
value: mockLocalStorage(),
|
||||||
@ -232,6 +233,7 @@ export default class GameWrapper {
|
|||||||
this.scene.make = new MockGameObjectCreator(mockTextureManager);
|
this.scene.make = new MockGameObjectCreator(mockTextureManager);
|
||||||
this.scene.time = new MockClock(this.scene);
|
this.scene.time = new MockClock(this.scene);
|
||||||
this.scene.remove = vi.fn(); // TODO: this should be stubbed differently
|
this.scene.remove = vi.fn(); // TODO: this should be stubbed differently
|
||||||
|
this.scene.eventManager = new MockTimedEventManager(); // Disable Timed Events
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/test/utils/mocks/mockTimedEventManager.ts
Normal file
17
src/test/utils/mocks/mockTimedEventManager.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { TimedEventManager } from "#app/timed-event-manager";
|
||||||
|
|
||||||
|
/** Mock TimedEventManager so that ongoing events don't impact tests */
|
||||||
|
export class MockTimedEventManager extends TimedEventManager {
|
||||||
|
override activeEvent() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
override isEventActive(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
override getFriendshipMultiplier(): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
override getShinyMultiplier(): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ const timedEvents: TimedEvent[] = [
|
|||||||
endDate: new Date(Date.UTC(2024, 10, 4, 0)),
|
endDate: new Date(Date.UTC(2024, 10, 4, 0)),
|
||||||
bannerKey: "halloween2024-event-",
|
bannerKey: "halloween2024-event-",
|
||||||
scale: 0.21,
|
scale: 0.21,
|
||||||
availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN" ]
|
availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es-ES", "pt-BR", "zh-CN" ]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
let pokemonIconX = -20;
|
let pokemonIconX = -20;
|
||||||
let pokemonIconY = 6;
|
let pokemonIconY = 6;
|
||||||
|
|
||||||
if ([ "de", "es", "fr", "ko", "pt-BR" ].includes(currentLanguage)) {
|
if ([ "de", "es-ES", "fr", "ko", "pt-BR" ].includes(currentLanguage)) {
|
||||||
gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT;
|
gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT;
|
||||||
gachaX = 2;
|
gachaX = 2;
|
||||||
gachaY = 2;
|
gachaY = 2;
|
||||||
@ -115,7 +115,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
let legendaryLabelX = gachaX;
|
let legendaryLabelX = gachaX;
|
||||||
let legendaryLabelY = gachaY;
|
let legendaryLabelY = gachaY;
|
||||||
if ([ "de", "es" ].includes(currentLanguage)) {
|
if ([ "de", "es-ES" ].includes(currentLanguage)) {
|
||||||
pokemonIconX = -25;
|
pokemonIconX = -25;
|
||||||
pokemonIconY = 10;
|
pokemonIconY = 10;
|
||||||
legendaryLabelX = -6;
|
legendaryLabelX = -6;
|
||||||
@ -128,7 +128,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
switch (gachaType as GachaType) {
|
switch (gachaType as GachaType) {
|
||||||
case GachaType.LEGENDARY:
|
case GachaType.LEGENDARY:
|
||||||
if ([ "de", "es" ].includes(currentLanguage)) {
|
if ([ "de", "es-ES" ].includes(currentLanguage)) {
|
||||||
gachaUpLabel.setAlign("center");
|
gachaUpLabel.setAlign("center");
|
||||||
gachaUpLabel.setY(0);
|
gachaUpLabel.setY(0);
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
gachaInfoContainer.add(pokemonIcon);
|
gachaInfoContainer.add(pokemonIcon);
|
||||||
break;
|
break;
|
||||||
case GachaType.MOVE:
|
case GachaType.MOVE:
|
||||||
if ([ "de", "es", "fr", "pt-BR" ].includes(currentLanguage)) {
|
if ([ "de", "es-ES", "fr", "pt-BR" ].includes(currentLanguage)) {
|
||||||
gachaUpLabel.setAlign("center");
|
gachaUpLabel.setAlign("center");
|
||||||
gachaUpLabel.setY(0);
|
gachaUpLabel.setY(0);
|
||||||
}
|
}
|
||||||
|
@ -21,24 +21,6 @@ interface LanguageSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const languageSettings: { [key: string]: LanguageSetting } = {
|
const languageSettings: { [key: string]: LanguageSetting } = {
|
||||||
"en": {
|
|
||||||
infoContainerTextSize: "64px"
|
|
||||||
},
|
|
||||||
"de": {
|
|
||||||
infoContainerTextSize: "64px",
|
|
||||||
},
|
|
||||||
"es": {
|
|
||||||
infoContainerTextSize: "64px"
|
|
||||||
},
|
|
||||||
"fr": {
|
|
||||||
infoContainerTextSize: "64px"
|
|
||||||
},
|
|
||||||
"it": {
|
|
||||||
infoContainerTextSize: "64px"
|
|
||||||
},
|
|
||||||
"zh": {
|
|
||||||
infoContainerTextSize: "64px"
|
|
||||||
},
|
|
||||||
"pt": {
|
"pt": {
|
||||||
infoContainerTextSize: "60px",
|
infoContainerTextSize: "60px",
|
||||||
infoContainerLabelXPos: -15,
|
infoContainerLabelXPos: -15,
|
||||||
|
@ -13,7 +13,7 @@ interface LanguageSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const languageSettings: { [key: string]: LanguageSetting } = {
|
const languageSettings: { [key: string]: LanguageSetting } = {
|
||||||
"es":{
|
"es-ES": {
|
||||||
inputFieldFontSize: "50px",
|
inputFieldFontSize: "50px",
|
||||||
errorMessageFontSize: "40px",
|
errorMessageFontSize: "40px",
|
||||||
}
|
}
|
||||||
|
@ -674,7 +674,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||||||
const def = i18next.t("pokemonInfo:Stat.DEFshortened") + ": " + pStats[2];
|
const def = i18next.t("pokemonInfo:Stat.DEFshortened") + ": " + pStats[2];
|
||||||
const spatk = i18next.t("pokemonInfo:Stat.SPATKshortened") + ": " + pStats[3];
|
const spatk = i18next.t("pokemonInfo:Stat.SPATKshortened") + ": " + pStats[3];
|
||||||
const spdef = i18next.t("pokemonInfo:Stat.SPDEFshortened") + ": " + pStats[4];
|
const spdef = i18next.t("pokemonInfo:Stat.SPDEFshortened") + ": " + pStats[4];
|
||||||
const speedLabel = (currentLanguage === "es" || currentLanguage === "pt_BR") ? i18next.t("runHistory:SPDshortened") : i18next.t("pokemonInfo:Stat.SPDshortened");
|
const speedLabel = (currentLanguage === "es-ES" || currentLanguage === "pt_BR") ? i18next.t("runHistory:SPDshortened") : i18next.t("pokemonInfo:Stat.SPDshortened");
|
||||||
const speed = speedLabel + ": " + pStats[5];
|
const speed = speedLabel + ": " + pStats[5];
|
||||||
// Column 1: HP Atk Def
|
// Column 1: HP Atk Def
|
||||||
const pokeStatText1 = addBBCodeTextObject(this.scene, -5, 0, hp, TextStyle.SUMMARY, { fontSize: textContainerFontSize, lineSpacing: lineSpacing });
|
const pokeStatText1 = addBBCodeTextObject(this.scene, -5, 0, hp, TextStyle.SUMMARY, { fontSize: textContainerFontSize, lineSpacing: lineSpacing });
|
||||||
|
@ -29,10 +29,10 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
|
|||||||
label: "English",
|
label: "English",
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case "es":
|
case "es-ES":
|
||||||
this.settings[languageIndex].options[0] = {
|
this.settings[languageIndex].options[0] = {
|
||||||
value: "Español",
|
value: "Español (ES)",
|
||||||
label: "Español",
|
label: "Español (ES)",
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case "it":
|
case "it":
|
||||||
|
@ -81,7 +81,7 @@ const languageSettings: { [key: string]: LanguageSetting } = {
|
|||||||
instructionTextSize: "35px",
|
instructionTextSize: "35px",
|
||||||
starterInfoXPos: 33,
|
starterInfoXPos: 33,
|
||||||
},
|
},
|
||||||
"es":{
|
"es-ES":{
|
||||||
starterInfoTextSize: "56px",
|
starterInfoTextSize: "56px",
|
||||||
instructionTextSize: "35px",
|
instructionTextSize: "35px",
|
||||||
},
|
},
|
||||||
|
@ -184,6 +184,7 @@ export default class TargetSelectUiHandler extends UiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
|
this.cursor = -1;
|
||||||
super.clear();
|
super.clear();
|
||||||
this.eraseCursor();
|
this.eraseCursor();
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ export function verifyLang(lang?: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (lang) {
|
switch (lang) {
|
||||||
case "es":
|
case "es-ES":
|
||||||
case "fr":
|
case "fr":
|
||||||
case "de":
|
case "de":
|
||||||
case "it":
|
case "it":
|
||||||
|
Loading…
Reference in New Issue
Block a user