Compare commits

...

5 Commits

Author SHA1 Message Date
Flashfyre
9cfc09f673 Restructure game over logic to save before clear 2024-05-10 18:12:33 -04:00
td76099
acb61d6fb7
Fixes Tidy Up so it clears hazards from both sides (#717) 2024-05-10 11:31:27 -05:00
Flashfyre
d7d2320844 Fix Mega Latias animated sprites 2024-05-10 12:19:18 -04:00
Athebyne
2ab335a3c5
Implement Snipe Shot, and Propeller Tail/Stalwart (#661)
* Implemented Snipe Shot and Stalwart/Propeller Tail

* Remove Testing Overrides

I don't know why these got pushed, they are in the gitignore file.

* Snipe Shot also has a high crit rate

* Add Comment

* Add TsDoc documentation to BypassRedirectAttr

* Add ability pop-up for when Propeller Tail/Stalwart proc.

* Fix Formatting

* Tab align comment
2024-05-10 10:40:21 -05:00
Dakurei
593ac38267
Fix some errors from previous PR #711 (#716) 2024-05-10 10:29:22 -05:00
11 changed files with 111 additions and 71 deletions

View File

@ -1978,7 +1978,7 @@
}, },
{ {
"frameIndex": 0, "frameIndex": 0,
"resourceName": "PRAS- Sketch and Lick", "resourceName": "PRAS- Sketch + Lick",
"bgX": 0, "bgX": 0,
"bgY": 0, "bgY": 0,
"opacity": 0, "opacity": 0,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -759,6 +759,8 @@ export default class BattleScene extends SceneBase {
this.newArena(Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN); this.newArena(Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN);
this.field.setVisible(true);
this.arenaBgTransition.setPosition(0, 0); this.arenaBgTransition.setPosition(0, 0);
this.arenaPlayer.setPosition(300, 0); this.arenaPlayer.setPosition(300, 0);
this.arenaPlayerTransition.setPosition(0, 0); this.arenaPlayerTransition.setPosition(0, 0);

View File

@ -2377,6 +2377,8 @@ export class RedirectTypeMoveAbAttr extends RedirectMoveAbAttr {
} }
} }
export class BlockRedirectAbAttr extends AbAttr { }
export class ReduceStatusEffectDurationAbAttr extends AbAttr { export class ReduceStatusEffectDurationAbAttr extends AbAttr {
private statusEffect: StatusEffect; private statusEffect: StatusEffect;
@ -3465,7 +3467,7 @@ export function initAbilities() {
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.SPD, -1, false, true) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.SPD, -1, false, true)
.bypassFaint(), .bypassFaint(),
new Ability(Abilities.PROPELLER_TAIL, 8) new Ability(Abilities.PROPELLER_TAIL, 8)
.unimplemented(), .attr(BlockRedirectAbAttr),
new Ability(Abilities.MIRROR_ARMOR, 8) new Ability(Abilities.MIRROR_ARMOR, 8)
.ignorable() .ignorable()
.unimplemented(), .unimplemented(),
@ -3475,7 +3477,7 @@ export function initAbilities() {
.attr(NoFusionAbilityAbAttr) .attr(NoFusionAbilityAbAttr)
.unimplemented(), .unimplemented(),
new Ability(Abilities.STALWART, 8) new Ability(Abilities.STALWART, 8)
.unimplemented(), .attr(BlockRedirectAbAttr),
new Ability(Abilities.STEAM_ENGINE, 8) new Ability(Abilities.STEAM_ENGINE, 8)
.attr(PostDefendStatChangeAbAttr, (target, user, move) => (move.type === Type.FIRE || move.type === Type.WATER) && move.category !== MoveCategory.STATUS, BattleStat.SPD, 6), .attr(PostDefendStatChangeAbAttr, (target, user, move) => (move.type === Type.FIRE || move.type === Type.WATER) && move.category !== MoveCategory.STATUS, BattleStat.SPD, 6),
new Ability(Abilities.PUNK_ROCK, 8) new Ability(Abilities.PUNK_ROCK, 8)

View File

@ -2653,6 +2653,11 @@ const crashDamageFunc = (user: Pokemon, move: Move) => {
}; };
export class TypelessAttr extends MoveAttr { } export class TypelessAttr extends MoveAttr { }
/**
* Attribute used for moves which ignore redirection effects, and always target their original target, i.e. Snipe Shot
* Bypasses Storm Drain, Follow Me, Ally Switch, and the like.
*/
export class BypassRedirectAttr extends MoveAttr { }
export class DisableMoveAttr extends MoveEffectAttr { export class DisableMoveAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -6172,7 +6177,8 @@ export function initMoves() {
.attr(DiscourageFrequentUseAttr) .attr(DiscourageFrequentUseAttr)
.ignoresVirtual(), .ignoresVirtual(),
new AttackMove(Moves.SNIPE_SHOT, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 8) new AttackMove(Moves.SNIPE_SHOT, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 8)
.partial(), .attr(HighCritAttr)
.attr(BypassRedirectAttr),
new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8) new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8)
.attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1)
.attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1)
@ -6709,8 +6715,9 @@ export function initMoves() {
.attr(ForceSwitchOutAttr, true, false) .attr(ForceSwitchOutAttr, true, false)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, 100, 0, 9) new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, 100, 0, 9)
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true, null, true, true)
.attr(RemoveArenaTrapAttr), .attr(RemoveArenaTrapAttr)
.target(MoveTarget.BOTH_SIDES),
new StatusMove(Moves.SNOWSCAPE, Type.ICE, -1, 10, -1, 0, 9) new StatusMove(Moves.SNOWSCAPE, Type.ICE, -1, 10, -1, 0, 9)
.attr(WeatherChangeAttr, WeatherType.SNOW) .attr(WeatherChangeAttr, WeatherType.SNOW)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),

View File

@ -2,6 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const fightUiHandler: SimpleTranslationEntries = { export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP", "pp": "PP",
"power": "Power", "power": "Potencia",
"accuracy": "Accuracy", "accuracy": "Accuracy",
} as const; } as const;

View File

@ -2,6 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const fightUiHandler: SimpleTranslationEntries = { export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP", "pp": "PP",
"power": "Power", "power": "Potenza",
"accuracy": "Accuracy", "accuracy": "Accuracy",
} as const; } as const;

View File

@ -2,7 +2,7 @@ import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
import * as Utils from './utils'; import * as Utils from './utils';
import { Moves } from "./data/enums/moves"; import { Moves } from "./data/enums/moves";
import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr ,FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move";
import { Mode } from './ui/ui'; import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler"; import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat"; import { Stat } from "./data/pokemon-stat";
@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
import { TempBattleStat } from "./data/temp-battle-stat"; import { TempBattleStat } from "./data/temp-battle-stat";
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
import { ArenaTagType } from "./data/enums/arena-tag-type"; import { ArenaTagType } from "./data/enums/arena-tag-type";
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability";
import { Unlockables, getUnlockableName } from "./system/unlockables"; import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena"; import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle"; import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@ -2215,7 +2215,16 @@ export class MovePhase extends BattlePhase {
? new Utils.IntegerHolder(this.targets[0]) ? new Utils.IntegerHolder(this.targets[0])
: null; : null;
if (moveTarget) { if (moveTarget) {
var oldTarget = moveTarget.value;
this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget));
//Check if this move is immune to being redirected, and restore its target to the intended target if it is.
if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().getAttrs(BypassRedirectAttr).length)) {
//If an ability prevented this move from being redirected, display its ability pop up.
if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) && !this.move.getMove().getAttrs(BypassRedirectAttr).length) && oldTarget != moveTarget.value) {
this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr)));
}
moveTarget.value = oldTarget;
}
this.targets[0] = moveTarget.value; this.targets[0] = moveTarget.value;
} }
@ -3475,8 +3484,6 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase {
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
const newModifier = this.modifierType.newModifier(); const newModifier = this.modifierType.newModifier();
this.scene.addModifier(newModifier).then(() => { this.scene.addModifier(newModifier).then(() => {
this.scene.gameData.saveSystem().then(success => {
if (success) {
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.arenaBg.setVisible(false); this.scene.arenaBg.setVisible(false);
@ -3486,9 +3493,6 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase {
resolve(); resolve();
}, null, true, 1500); }, null, true, 1500);
}); });
} else
this.scene.reset(true);
});
}); });
}) })
} }
@ -3507,8 +3511,6 @@ export class RibbonModifierRewardPhase extends ModifierRewardPhase {
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
const newModifier = this.modifierType.newModifier(); const newModifier = this.modifierType.newModifier();
this.scene.addModifier(newModifier).then(() => { this.scene.addModifier(newModifier).then(() => {
this.scene.gameData.saveSystem().then(success => {
if (success) {
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.arenaBg.setVisible(false); this.scene.arenaBg.setVisible(false);
@ -3517,9 +3519,6 @@ export class RibbonModifierRewardPhase extends ModifierRewardPhase {
resolve(); resolve();
}, null, true, 1500); }, null, true, 1500);
}); });
} else
this.scene.reset(true);
});
}); });
}) })
} }
@ -3539,7 +3538,7 @@ export class GameOverPhase extends BattlePhase {
super.start(); super.start();
if (this.victory || !this.scene.enableRetries) if (this.victory || !this.scene.enableRetries)
this.handleClearSession(); this.handleGameOver();
else { else {
this.scene.ui.showText(`Would you like to retry from the start of the battle?`, null, () => { this.scene.ui.showText(`Would you like to retry from the start of the battle?`, null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.CONFIRM, () => {
@ -3564,18 +3563,16 @@ export class GameOverPhase extends BattlePhase {
this.end(); this.end();
}); });
}); });
}, () => this.handleClearSession(), false, 0, 0, 1000); }, () => this.handleGameOver(), false, 0, 0, 1000);
}); });
} }
} }
handleClearSession(): void { handleGameOver(): void {
this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => { const doGameOver = (newClear: boolean) => {
if (!success[0])
return this.scene.reset(true);
this.scene.time.delayedCall(1000, () => { this.scene.time.delayedCall(1000, () => {
let firstClear = false; let firstClear = false;
if (this.victory && success[1]) { if (this.victory && newClear) {
if (this.scene.gameMode.isClassic) { if (this.scene.gameMode.isClassic) {
firstClear = this.scene.validateAchv(achvs.CLASSIC_VICTORY); firstClear = this.scene.validateAchv(achvs.CLASSIC_VICTORY);
this.scene.gameData.gameStats.sessionsWon++; this.scene.gameData.gameStats.sessionsWon++;
@ -3586,29 +3583,37 @@ export class GameOverPhase extends BattlePhase {
this.awardRibbon(pokemon, true); this.awardRibbon(pokemon, true);
} }
} }
} else if (this.scene.gameMode.isDaily && success[1]) } else if (this.scene.gameMode.isDaily && newClear)
this.scene.gameData.gameStats.dailyRunSessionsWon++; this.scene.gameData.gameStats.dailyRunSessionsWon++;
} }
this.scene.gameData.saveSystem();
const fadeDuration = this.victory ? 10000 : 5000; const fadeDuration = this.victory ? 10000 : 5000;
this.scene.fadeOutBgm(fadeDuration, true); this.scene.fadeOutBgm(fadeDuration, true);
const activeBattlers = this.scene.getField().filter(p => p?.isActive(true));
activeBattlers.map(p => p.hideInfo());
this.scene.ui.fadeOut(fadeDuration).then(() => { this.scene.ui.fadeOut(fadeDuration).then(() => {
[ this.scene.field, ...activeBattlers ].map(a => a.setVisible(false));
this.scene.setFieldScale(1, true); this.scene.setFieldScale(1, true);
this.scene.clearPhaseQueue(); this.scene.clearPhaseQueue();
this.scene.ui.clearText(); this.scene.ui.clearText();
if (newClear)
this.handleUnlocks(); this.handleUnlocks();
if (this.victory && success[1]) { if (this.victory && newClear) {
for (let species of this.firstRibbons) for (let species of this.firstRibbons)
this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species)); this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species));
if (!firstClear) if (!firstClear)
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM)); this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
} }
this.scene.reset(); this.scene.pushPhase(new PostGameOverPhase(this.scene));
this.scene.unshiftPhase(new TitlePhase(this.scene));
this.end(); this.end();
}); });
}); });
}); };
if (this.victory) {
Utils.apiFetch(`savedata/newclear?slot=${this.scene.sessionSlotId}`, true)
.then(response => response.json())
.then(newClear => doGameOver(newClear));
} else
doGameOver(false);
} }
handleUnlocks(): void { handleUnlocks(): void {
@ -3644,8 +3649,6 @@ export class UnlockPhase extends Phase {
start(): void { start(): void {
this.scene.time.delayedCall(2000, () => { this.scene.time.delayedCall(2000, () => {
this.scene.gameData.unlocks[this.unlockable] = true; this.scene.gameData.unlocks[this.unlockable] = true;
this.scene.gameData.saveSystem().then(success => {
if (success) {
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.arenaBg.setVisible(false); this.scene.arenaBg.setVisible(false);
@ -3655,8 +3658,27 @@ export class UnlockPhase extends Phase {
this.end(); this.end();
}, null, true, 1500); }, null, true, 1500);
}); });
} else });
this.scene.reset(true); }
}
export class PostGameOverPhase extends Phase {
constructor(scene: BattleScene) {
super(scene);
}
start() {
super.start();
this.scene.gameData.saveSystem().then(success => {
if (!success)
return this.scene.reset(true);
this.scene.gameData.tryClearSession(this.scene, this.scene.sessionSlotId).then((success: boolean | [boolean, boolean]) => {
if (!success[0])
return this.scene.reset(true);
this.scene.reset();
this.scene.unshiftPhase(new TitlePhase(this.scene));
this.end();
}); });
}); });
} }

View File

@ -190,11 +190,14 @@ const systemShortKeys = {
natureAttr: '$na', natureAttr: '$na',
seenCount: '$s' , seenCount: '$s' ,
caughtCount: '$c', caughtCount: '$c',
hatchedCount: '$hc',
ivs: '$i', ivs: '$i',
moveset: '$m', moveset: '$m',
eggMoves: '$em', eggMoves: '$em',
candyCount: '$x', candyCount: '$x',
passive: '$p', friendship: '$f',
abilityAttr: '$a',
passiveAttr: '$pa',
valueReduction: '$vr', valueReduction: '$vr',
classicWinCount: '$wc' classicWinCount: '$wc'
}; };
@ -454,6 +457,10 @@ export class GameData {
} }
private convertSystemDataStr(dataStr: string, shorten: boolean = false): string { private convertSystemDataStr(dataStr: string, shorten: boolean = false): string {
if (!shorten) {
// Account for past key oversight
dataStr = dataStr.replace(/\$pAttr/g, '$pa');
}
const fromKeys = shorten ? Object.keys(systemShortKeys) : Object.values(systemShortKeys); const fromKeys = shorten ? Object.keys(systemShortKeys) : Object.values(systemShortKeys);
const toKeys = shorten ? Object.values(systemShortKeys) : Object.keys(systemShortKeys); const toKeys = shorten ? Object.values(systemShortKeys) : Object.keys(systemShortKeys);
for (let k in fromKeys) for (let k in fromKeys)