mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-04 07:22:19 +02:00
Added permadeath gamemode modifier
- add enable/disable modifier to starter UI - Modifiers get saved/loaded - permadeath: - potions don't show up in shop/rewards - every 10th wave does not heal dead pokemon - achievement for winning classic with permadeath enabled
This commit is contained in:
parent
ca778e07d5
commit
411786bf20
@ -22,6 +22,9 @@ import AbilityBar from './ui/ability-bar';
|
|||||||
import { Abilities, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
import { Abilities, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
||||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
||||||
import { GameMode, GameModes, gameModes } from './game-mode';
|
import { GameMode, GameModes, gameModes } from './game-mode';
|
||||||
|
|
||||||
|
import GameModeModifiers from './system/game-mode-modifiers';
|
||||||
|
|
||||||
import FieldSpritePipeline from './pipelines/field-sprite';
|
import FieldSpritePipeline from './pipelines/field-sprite';
|
||||||
import SpritePipeline from './pipelines/sprite';
|
import SpritePipeline from './pipelines/sprite';
|
||||||
import PartyExpBar from './ui/party-exp-bar';
|
import PartyExpBar from './ui/party-exp-bar';
|
||||||
@ -149,6 +152,9 @@ export default class BattleScene extends SceneBase {
|
|||||||
public arenaNextEnemy: ArenaBase;
|
public arenaNextEnemy: ArenaBase;
|
||||||
public arena: Arena;
|
public arena: Arena;
|
||||||
public gameMode: GameMode;
|
public gameMode: GameMode;
|
||||||
|
|
||||||
|
public gameModeModifiers: GameModeModifiers;
|
||||||
|
|
||||||
public score: integer;
|
public score: integer;
|
||||||
public lockModifierTiers: boolean;
|
public lockModifierTiers: boolean;
|
||||||
public trainer: Phaser.GameObjects.Sprite;
|
public trainer: Phaser.GameObjects.Sprite;
|
||||||
|
@ -959,14 +959,14 @@ const modifierPool: ModifierPool = {
|
|||||||
}, 18),
|
}, 18),
|
||||||
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 9;
|
return party[0].scene.gameModeModifiers.isPermaDeath? 0 : faintedPartyMemberCount * 9;
|
||||||
}, 3),
|
}, 3),
|
||||||
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 3;
|
return party[0].scene.gameModeModifiers.isPermaDeath ? 0 : faintedPartyMemberCount * 3;
|
||||||
}, 9),
|
}, 9),
|
||||||
new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => {
|
||||||
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
return party[0].scene.gameModeModifiers.isPermaDeath ? 0 : party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||||
}, 1),
|
}, 1),
|
||||||
new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => {
|
||||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length, 3);
|
const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length, 3);
|
||||||
@ -1286,7 +1286,7 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer): ModifierTypeOption[] {
|
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer, permadeath:boolean = false): ModifierTypeOption[] {
|
||||||
if (!(waveIndex % 10))
|
if (!(waveIndex % 10))
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
@ -1294,7 +1294,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
|||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2),
|
new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2),
|
||||||
new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4),
|
new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4),
|
||||||
new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2)
|
... !permadeath ? [new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2)] : [],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45),
|
new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45),
|
||||||
@ -1306,7 +1306,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
||||||
new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75)
|
... !permadeath ? [new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75)] : [],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
||||||
@ -1316,7 +1316,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
|||||||
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 12)
|
... !permadeath ? [new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 12)] : []
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
||||||
|
@ -3293,6 +3293,9 @@ export class GameOverPhase extends BattlePhase {
|
|||||||
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++;
|
||||||
|
if (this.scene.gameModeModifiers.isPermaDeath){
|
||||||
|
this.scene.validateAchv(achvs.PERMADEATH_VICTORY);
|
||||||
|
}
|
||||||
} else if (this.scene.gameMode.isDaily && success[1])
|
} else if (this.scene.gameMode.isDaily && success[1])
|
||||||
this.scene.gameData.gameStats.dailyRunSessionsWon++;
|
this.scene.gameData.gameStats.dailyRunSessionsWon++;
|
||||||
}
|
}
|
||||||
@ -4065,7 +4068,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||||||
modifierType = typeOptions[cursor].type;
|
modifierType = typeOptions[cursor].type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1));
|
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1),this.scene.gameModeModifiers.isPermaDeath);
|
||||||
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
|
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
|
||||||
modifierType = shopOption.type;
|
modifierType = shopOption.type;
|
||||||
cost = shopOption.cost;
|
cost = shopOption.cost;
|
||||||
@ -4228,11 +4231,12 @@ export class PartyHealPhase extends BattlePhase {
|
|||||||
this.scene.fadeOutBgm(1000, false);
|
this.scene.fadeOutBgm(1000, false);
|
||||||
this.scene.ui.fadeOut(1000).then(() => {
|
this.scene.ui.fadeOut(1000).then(() => {
|
||||||
for (let pokemon of this.scene.getParty()) {
|
for (let pokemon of this.scene.getParty()) {
|
||||||
pokemon.hp = pokemon.getMaxHp();
|
if (!this.scene.gameModeModifiers.isPermaDeath && pokemon.hp == 0){
|
||||||
pokemon.resetStatus();
|
pokemon.hp = pokemon.getMaxHp();
|
||||||
for (let move of pokemon.moveset)
|
pokemon.resetStatus();
|
||||||
|
for (let move of pokemon.moveset)
|
||||||
move.ppUsed = 0;
|
move.ppUsed = 0;
|
||||||
pokemon.updateInfo(true);
|
pokemon.updateInfo(true);
|
||||||
}
|
}
|
||||||
const healSong = this.scene.playSoundWithoutBgm('heal');
|
const healSong = this.scene.playSoundWithoutBgm('heal');
|
||||||
this.scene.time.delayedCall(Utils.fixedInt(healSong.totalDuration * 1000), () => {
|
this.scene.time.delayedCall(Utils.fixedInt(healSong.totalDuration * 1000), () => {
|
||||||
@ -4241,7 +4245,7 @@ export class PartyHealPhase extends BattlePhase {
|
|||||||
this.scene.playBgm();
|
this.scene.playBgm();
|
||||||
this.scene.ui.fadeIn(500).then(() => this.end());
|
this.scene.ui.fadeIn(500).then(() => this.end());
|
||||||
});
|
});
|
||||||
});
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,8 @@ export const achvs = {
|
|||||||
HATCH_SHINY: new Achv('Shiny Egg', 'Hatch a shiny Pokémon from an egg', 'golden_mystic_ticket', 100).setSecret(),
|
HATCH_SHINY: new Achv('Shiny Egg', 'Hatch a shiny Pokémon from an egg', 'golden_mystic_ticket', 100).setSecret(),
|
||||||
HIDDEN_ABILITY: new Achv('Hidden Potential', 'Catch a Pokémon with a hidden ability', 'ability_charm', 75),
|
HIDDEN_ABILITY: new Achv('Hidden Potential', 'Catch a Pokémon with a hidden ability', 'ability_charm', 75),
|
||||||
PERFECT_IVS: new Achv('Certificate of Authenticity', 'Get perfect IVs on a Pokémon', 'blunder_policy', 100),
|
PERFECT_IVS: new Achv('Certificate of Authenticity', 'Get perfect IVs on a Pokémon', 'blunder_policy', 100),
|
||||||
CLASSIC_VICTORY: new Achv('Undefeated', 'Beat the game in classic mode', 'relic_crown', 150)
|
CLASSIC_VICTORY: new Achv('Undefeated', 'Beat the game in classic mode', 'relic_crown', 150),
|
||||||
|
PERMADEATH_VICTORY: new Achv('Mr. Fuji', 'Beat the game using the permadeath modifier', 'silph_scope', 50)
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ import PersistentModifierData from "./modifier-data";
|
|||||||
import ArenaData from "./arena-data";
|
import ArenaData from "./arena-data";
|
||||||
import { Unlockables } from "./unlockables";
|
import { Unlockables } from "./unlockables";
|
||||||
import { GameModes, gameModes } from "../game-mode";
|
import { GameModes, gameModes } from "../game-mode";
|
||||||
|
import GameModeModifiers from "./game-mode-modifiers";
|
||||||
import { BattleType } from "../battle";
|
import { BattleType } from "../battle";
|
||||||
import TrainerData from "./trainer-data";
|
import TrainerData from "./trainer-data";
|
||||||
import { trainerConfigs } from "../data/trainer-config";
|
import { trainerConfigs } from "../data/trainer-config";
|
||||||
@ -80,6 +81,7 @@ export interface SessionSaveData {
|
|||||||
seed: string;
|
seed: string;
|
||||||
playTime: integer;
|
playTime: integer;
|
||||||
gameMode: GameModes;
|
gameMode: GameModes;
|
||||||
|
gameModeModiefiers: GameModeModifiers
|
||||||
party: PokemonData[];
|
party: PokemonData[];
|
||||||
enemyParty: PokemonData[];
|
enemyParty: PokemonData[];
|
||||||
modifiers: PersistentModifierData[];
|
modifiers: PersistentModifierData[];
|
||||||
@ -468,6 +470,7 @@ export class GameData {
|
|||||||
seed: scene.seed,
|
seed: scene.seed,
|
||||||
playTime: scene.sessionPlayTime,
|
playTime: scene.sessionPlayTime,
|
||||||
gameMode: scene.gameMode.modeId,
|
gameMode: scene.gameMode.modeId,
|
||||||
|
gameModeModiefiers: scene.gameModeModifiers,
|
||||||
party: scene.getParty().map(p => new PokemonData(p)),
|
party: scene.getParty().map(p => new PokemonData(p)),
|
||||||
enemyParty: scene.getEnemyParty().map(p => new PokemonData(p)),
|
enemyParty: scene.getEnemyParty().map(p => new PokemonData(p)),
|
||||||
modifiers: scene.findModifiers(() => true).map(m => new PersistentModifierData(m, true)),
|
modifiers: scene.findModifiers(() => true).map(m => new PersistentModifierData(m, true)),
|
||||||
@ -554,6 +557,7 @@ export class GameData {
|
|||||||
console.debug(sessionData);
|
console.debug(sessionData);
|
||||||
|
|
||||||
scene.gameMode = gameModes[sessionData.gameMode || GameModes.CLASSIC];
|
scene.gameMode = gameModes[sessionData.gameMode || GameModes.CLASSIC];
|
||||||
|
scene.gameModeModifiers = sessionData.gameModeModiefiers || new GameModeModifiers({})
|
||||||
|
|
||||||
scene.setSeed(sessionData.seed || scene.game.config.seed[0]);
|
scene.setSeed(sessionData.seed || scene.game.config.seed[0]);
|
||||||
scene.resetSeed();
|
scene.resetSeed();
|
||||||
|
17
src/system/game-mode-modifiers.ts
Normal file
17
src/system/game-mode-modifiers.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Type } from "../data/type";
|
||||||
|
|
||||||
|
interface GameModeModifiersConfig {
|
||||||
|
isPermaDeath?: boolean;
|
||||||
|
isMonotype?: boolean;
|
||||||
|
monoTypeType?: Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class GameModeModifiers {
|
||||||
|
public isPermaDeath: boolean;
|
||||||
|
public isMonotype: boolean;
|
||||||
|
public monoTypeType: Type;
|
||||||
|
|
||||||
|
constructor(config: GameModeModifiersConfig) {
|
||||||
|
Object.assign(this, config);
|
||||||
|
}
|
||||||
|
}
|
@ -107,7 +107,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
|
|
||||||
const typeOptions = args[1] as ModifierTypeOption[];
|
const typeOptions = args[1] as ModifierTypeOption[];
|
||||||
const shopTypeOptions = !this.scene.gameMode.hasNoShop
|
const shopTypeOptions = !this.scene.gameMode.hasNoShop
|
||||||
? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1))
|
? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1),this.scene.gameModeModifiers.isPermaDeath)
|
||||||
: [];
|
: [];
|
||||||
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;
|
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import { Type } from "../data/type";
|
|||||||
import { Moves } from "../data/enums/moves";
|
import { Moves } from "../data/enums/moves";
|
||||||
import { speciesEggMoves } from "../data/egg-moves";
|
import { speciesEggMoves } from "../data/egg-moves";
|
||||||
import { TitlePhase } from "../phases";
|
import { TitlePhase } from "../phases";
|
||||||
|
import GameModeModifiers from "../system/game-mode-modifiers";
|
||||||
|
|
||||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||||
|
|
||||||
@ -112,6 +113,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
private starterSelectCallback: StarterSelectCallback;
|
private starterSelectCallback: StarterSelectCallback;
|
||||||
private gameMode: GameModes;
|
private gameMode: GameModes;
|
||||||
|
private gameModeModifierConfig = {isPermaDeath: false}
|
||||||
|
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
super(scene, Mode.STARTER_SELECT);
|
super(scene, Mode.STARTER_SELECT);
|
||||||
@ -1264,7 +1266,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tryStart(manualTrigger: boolean = false): boolean {
|
showRunMods(manualTrigger: boolean = false, permadeath: boolean = false): boolean {
|
||||||
|
const ui = this.getUi();
|
||||||
|
let options = [];
|
||||||
|
options.push(
|
||||||
|
{
|
||||||
|
label: permadeath ? 'Permadeath (enabled)' : 'Permadeath (disabled)',
|
||||||
|
handler: () => {
|
||||||
|
ui.setMode(Mode.STARTER_SELECT);
|
||||||
|
this.gameModeModifierConfig.isPermaDeath = !permadeath
|
||||||
|
this.showRunMods(manualTrigger,!permadeath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
options.push(
|
||||||
|
{
|
||||||
|
label: 'Done',
|
||||||
|
handler: () => {
|
||||||
|
this.scene.gameModeModifiers = new GameModeModifiers(this.gameModeModifierConfig)
|
||||||
|
ui.setMode(Mode.STARTER_SELECT);
|
||||||
|
this.tryStartRun(manualTrigger)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ui.showText('Select desired run modifiers', null, () => {
|
||||||
|
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||||
|
options: options,
|
||||||
|
yOffset: 20
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tryStart(manualTrigger: boolean = false): boolean{
|
||||||
|
const cancel = () => {
|
||||||
|
this.clearText();
|
||||||
|
ui.setMode(Mode.STARTER_SELECT);
|
||||||
|
this.tryStartRun(manualTrigger)
|
||||||
|
};
|
||||||
|
const ui = this.getUi();
|
||||||
|
ui.showText('Enable custom game modifiers?', null, () => {
|
||||||
|
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||||
|
ui.setMode(Mode.STARTER_SELECT);
|
||||||
|
this.showRunMods(manualTrigger)
|
||||||
|
}, cancel, null, null, 19);
|
||||||
|
});
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
tryStartRun(manualTrigger: boolean = false): boolean {
|
||||||
if (!this.starterGens.length)
|
if (!this.starterGens.length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1278,7 +1327,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ui.showText('Begin with these Pokémon?', null, () => {
|
ui.showText('Begin with these Pokémon?', null, () => {
|
||||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||||
const startRun = (gameMode: GameModes) => {
|
const startRun = (gameMode: GameModes) => {
|
||||||
this.scene.gameMode = gameModes[gameMode];
|
this.scene.gameMode = gameModes[gameMode];
|
||||||
this.scene.money = this.scene.gameMode.getStartingMoney();
|
this.scene.money = this.scene.gameMode.getStartingMoney();
|
||||||
|
Loading…
Reference in New Issue
Block a user