mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2024-11-30 10:46:05 +00:00
Merge pull request #42 from AsdarDevelops/field-trip
Field Trip encounter and misc Improvements
This commit is contained in:
commit
c0a900cd02
@ -4,8 +4,8 @@
|
|||||||
"image": "mad_scientist_m.png",
|
"image": "mad_scientist_m.png",
|
||||||
"format": "RGBA8888",
|
"format": "RGBA8888",
|
||||||
"size": {
|
"size": {
|
||||||
"w": 44,
|
"w": 46,
|
||||||
"h": 74
|
"h": 76
|
||||||
},
|
},
|
||||||
"scale": 1,
|
"scale": 1,
|
||||||
"frames": [
|
"frames": [
|
||||||
@ -24,8 +24,8 @@
|
|||||||
"h": 74
|
"h": 74
|
||||||
},
|
},
|
||||||
"frame": {
|
"frame": {
|
||||||
"x": 0,
|
"x": 1,
|
||||||
"y": 0,
|
"y": 1,
|
||||||
"w": 44,
|
"w": 44,
|
||||||
"h": 74
|
"h": 74
|
||||||
}
|
}
|
||||||
@ -36,6 +36,6 @@
|
|||||||
"meta": {
|
"meta": {
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
"version": "3.0",
|
"version": "3.0",
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:895f0a79b89fa0fb44167f4584fd9a22:357b46953b7e17c6b2f43a62d52855d8:cc1ed0e4f90aaa9dcf1b39a0af1283b0$"
|
"smartupdate": "$TexturePacker:SmartUpdate:a7f8ff2bbb362868f51125c254eb6681:cf76e61ddd31a8f46af67ced168c44a2:4fc09abe16c0608828269e5da81d0744$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 920 B |
41
public/images/mystery-encounters/teacher.json
Normal file
41
public/images/mystery-encounters/teacher.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"textures": [
|
||||||
|
{
|
||||||
|
"image": "teacher.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {
|
||||||
|
"w": 43,
|
||||||
|
"h": 74
|
||||||
|
},
|
||||||
|
"scale": 1,
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"filename": "0001.png",
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": true,
|
||||||
|
"sourceSize": {
|
||||||
|
"w": 80,
|
||||||
|
"h": 80
|
||||||
|
},
|
||||||
|
"spriteSourceSize": {
|
||||||
|
"x": 19,
|
||||||
|
"y": 8,
|
||||||
|
"w": 41,
|
||||||
|
"h": 72
|
||||||
|
},
|
||||||
|
"frame": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"w": 41,
|
||||||
|
"h": 72
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "3.0",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:506e5a4ce79c134a7b4af90a90aef244:1b81d3d84bf12cedc419805eaff82548:59bc5dd000b5e72588320b473e31c312$"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/images/mystery-encounters/teacher.png
Normal file
BIN
public/images/mystery-encounters/teacher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 727 B |
@ -2696,7 +2696,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
encounter = availableEncounters[Utils.randSeedInt(availableEncounters.length)];
|
encounter = availableEncounters[Utils.randSeedInt(availableEncounters.length)];
|
||||||
// New encounter object to not dirty flags
|
// New encounter object to not dirty flags
|
||||||
encounter = new MysteryEncounter(encounter);
|
encounter = new MysteryEncounter(encounter);
|
||||||
encounter.meetsRequirements(this);
|
encounter.populateDialogueTokensFromRequirements(this);
|
||||||
return encounter;
|
return encounter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
50
src/data/mystery-encounters/dialogue/field-trip-dialogue.ts
Normal file
50
src/data/mystery-encounters/dialogue/field-trip-dialogue.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import MysteryEncounterDialogue from "#app/data/mystery-encounters/mystery-encounter-dialogue";
|
||||||
|
|
||||||
|
export const FieldTripDialogue: MysteryEncounterDialogue = {
|
||||||
|
intro: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_intro_message"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_intro_dialogue",
|
||||||
|
speaker: "mysteryEncounter:field_trip_speaker"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
encounterOptionsDialogue: {
|
||||||
|
title: "mysteryEncounter:field_trip_title",
|
||||||
|
description: "mysteryEncounter:field_trip_description",
|
||||||
|
query: "mysteryEncounter:field_trip_query",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
buttonLabel: "mysteryEncounter:field_trip_option_1_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:field_trip_option_1_tooltip",
|
||||||
|
secondOptionPrompt: "mysteryEncounter:field_trip_second_option_prompt",
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonLabel: "mysteryEncounter:field_trip_option_2_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:field_trip_option_2_tooltip",
|
||||||
|
secondOptionPrompt: "mysteryEncounter:field_trip_second_option_prompt",
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonLabel: "mysteryEncounter:field_trip_option_3_label",
|
||||||
|
buttonTooltip: "mysteryEncounter:field_trip_option_3_tooltip",
|
||||||
|
secondOptionPrompt: "mysteryEncounter:field_trip_second_option_prompt",
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
@ -21,7 +21,7 @@ export const ShadyVitaminDealerDialogue: MysteryEncounterDialogue = {
|
|||||||
selected: [
|
selected: [
|
||||||
{
|
{
|
||||||
text: "mysteryEncounter:shady_vitamin_dealer_option_selected"
|
text: "mysteryEncounter:shady_vitamin_dealer_option_selected"
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ export const ShadyVitaminDealerDialogue: MysteryEncounterDialogue = {
|
|||||||
selected: [
|
selected: [
|
||||||
{
|
{
|
||||||
text: "mysteryEncounter:shady_vitamin_dealer_option_selected"
|
text: "mysteryEncounter:shady_vitamin_dealer_option_selected"
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
leaveEncounterWithoutBattle, setEncounterExp,
|
leaveEncounterWithoutBattle,
|
||||||
setEncounterRewards,
|
setEncounterRewards,
|
||||||
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
||||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
@ -46,7 +46,6 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
setEncounterExp(scene, scene.getParty().map(p => p.id), 300);
|
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false });
|
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false });
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene);
|
||||||
})
|
})
|
||||||
|
220
src/data/mystery-encounters/encounters/field-trip-encounter.ts
Normal file
220
src/data/mystery-encounters/encounters/field-trip-encounter.ts
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards, } from "#app/data/mystery-encounters/mystery-encounter-utils";
|
||||||
|
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||||
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
|
import BattleScene from "../../../battle-scene";
|
||||||
|
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
||||||
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
|
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||||
|
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||||
|
import { MoveCategory } from "#app/data/move";
|
||||||
|
import { TempBattleStat } from "#app/data/temp-battle-stat";
|
||||||
|
|
||||||
|
export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||||
|
.withEncounterType(MysteryEncounterType.FIELD_TRIP)
|
||||||
|
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||||
|
.withIntroSpriteConfigs([
|
||||||
|
{
|
||||||
|
spriteKey: "preschooler_m",
|
||||||
|
fileRoot: "trainer",
|
||||||
|
hasShadow: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
spriteKey: "teacher",
|
||||||
|
fileRoot: "mystery-encounters",
|
||||||
|
hasShadow: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
spriteKey: "preschooler_f",
|
||||||
|
fileRoot: "trainer",
|
||||||
|
hasShadow: true
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.withHideIntroVisuals(false)
|
||||||
|
.withSceneWaveRangeRequirement(10, 180)
|
||||||
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Return the options for Pokemon move valid for this option
|
||||||
|
return pokemon.moveset.map((move: PokemonMove) => {
|
||||||
|
const option: OptionSelectItem = {
|
||||||
|
label: move.getName(),
|
||||||
|
handler: () => {
|
||||||
|
// Pokemon and move selected
|
||||||
|
const correctMove = move.getMove().category === MoveCategory.PHYSICAL;
|
||||||
|
encounter.setDialogueToken("moveCategory", "Physical");
|
||||||
|
if (!correctMove) {
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[0].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_incorrect",
|
||||||
|
speaker: "mysteryEncounter:field_trip_speaker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_lesson_learned",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, scene.getParty().map(p => p.id), 50);
|
||||||
|
} else {
|
||||||
|
encounter.setDialogueToken("pokeName", pokemon.name);
|
||||||
|
encounter.setDialogueToken("move", move.getName());
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[0].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, [pokemon.id], 100);
|
||||||
|
}
|
||||||
|
encounter.misc = {
|
||||||
|
correctMove: correctMove
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
if (encounter.misc.correctMove) {
|
||||||
|
const modifiers = [
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ATK]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.DEF]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)
|
||||||
|
];
|
||||||
|
|
||||||
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Return the options for Pokemon move valid for this option
|
||||||
|
return pokemon.moveset.map((move: PokemonMove) => {
|
||||||
|
const option: OptionSelectItem = {
|
||||||
|
label: move.getName(),
|
||||||
|
handler: () => {
|
||||||
|
// Pokemon and move selected
|
||||||
|
const correctMove = move.getMove().category === MoveCategory.SPECIAL;
|
||||||
|
encounter.setDialogueToken("moveCategory", "Special");
|
||||||
|
if (!correctMove) {
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[1].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_incorrect",
|
||||||
|
speaker: "mysteryEncounter:field_trip_speaker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_lesson_learned",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, scene.getParty().map(p => p.id), 50);
|
||||||
|
} else {
|
||||||
|
encounter.setDialogueToken("pokeName", pokemon.name);
|
||||||
|
encounter.setDialogueToken("move", move.getName());
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[1].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, [pokemon.id], 100);
|
||||||
|
}
|
||||||
|
encounter.misc = {
|
||||||
|
correctMove: correctMove
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
if (encounter.misc.correctMove) {
|
||||||
|
const modifiers = [
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPATK]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPDEF]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)
|
||||||
|
];
|
||||||
|
|
||||||
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Return the options for Pokemon move valid for this option
|
||||||
|
return pokemon.moveset.map((move: PokemonMove) => {
|
||||||
|
const option: OptionSelectItem = {
|
||||||
|
label: move.getName(),
|
||||||
|
handler: () => {
|
||||||
|
// Pokemon and move selected
|
||||||
|
const correctMove = move.getMove().category === MoveCategory.STATUS;
|
||||||
|
encounter.setDialogueToken("moveCategory", "Status");
|
||||||
|
if (!correctMove) {
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[2].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_incorrect",
|
||||||
|
speaker: "mysteryEncounter:field_trip_speaker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_lesson_learned",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, scene.getParty().map(p => p.id), 50);
|
||||||
|
} else {
|
||||||
|
encounter.setDialogueToken("pokeName", pokemon.name);
|
||||||
|
encounter.setDialogueToken("move", move.getName());
|
||||||
|
encounter.dialogue.encounterOptionsDialogue.options[2].selected = [
|
||||||
|
{
|
||||||
|
text: "mysteryEncounter:field_trip_option_selected"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setEncounterExp(scene, [pokemon.id], 100);
|
||||||
|
}
|
||||||
|
encounter.misc = {
|
||||||
|
correctMove: correctMove
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected);
|
||||||
|
})
|
||||||
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
if (encounter.misc.correctMove) {
|
||||||
|
const modifiers = [
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.ACC]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_BOOSTER, [TempBattleStat.SPD]),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.GREAT_BALL),
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)
|
||||||
|
];
|
||||||
|
|
||||||
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: modifiers, fillRemaining: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveEncounterWithoutBattle(scene, !encounter.misc.correctMove);
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build();
|
@ -16,24 +16,14 @@ import {
|
|||||||
regenerateModifierPoolThresholds
|
regenerateModifierPoolThresholds
|
||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import { StatChangePhase } from "#app/phases";
|
import { StatChangePhase } from "#app/phases";
|
||||||
import { TextStyle } from "#app/ui/text";
|
|
||||||
import { randSeedInt } from "#app/utils";
|
import { randSeedInt } from "#app/utils";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { Moves } from "#enums/moves";
|
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "../../../battle-scene";
|
||||||
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
import MysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier } from "../mystery-encounter";
|
||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "../mystery-encounter-requirements";
|
||||||
|
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||||
const validMovesForSteal = [
|
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
Moves.PLUCK,
|
|
||||||
Moves.COVET,
|
|
||||||
Moves.FAKE_OUT,
|
|
||||||
Moves.THIEF,
|
|
||||||
Moves.TRICK,
|
|
||||||
Moves.SWITCHEROO,
|
|
||||||
Moves.GIGA_DRAIN
|
|
||||||
];
|
|
||||||
|
|
||||||
export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
|
export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||||
.withEncounterType(MysteryEncounterType.FIGHT_OR_FLIGHT)
|
.withEncounterType(MysteryEncounterType.FIGHT_OR_FLIGHT)
|
||||||
@ -82,18 +72,13 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
];
|
];
|
||||||
|
|
||||||
// If player has a stealing move, they succeed automatically
|
// If player has a stealing move, they succeed automatically
|
||||||
const moveRequirement = new MoveRequirement(validMovesForSteal);
|
encounter.options[1].meetsRequirements(scene);
|
||||||
const validPokemon = moveRequirement.queryParty(scene.getParty());
|
const primaryPokemon = encounter.options[1].primaryPokemon;
|
||||||
if (validPokemon?.length > 0) {
|
if (primaryPokemon) {
|
||||||
// Use first valid pokemon to execute the theivery
|
// Use primaryPokemon to execute the thievery
|
||||||
const pokemon = validPokemon[0];
|
|
||||||
encounter.setDialogueToken("thiefPokemon", pokemon.name);
|
|
||||||
encounter.setDialogueToken(...moveRequirement.getDialogueToken(scene, pokemon));
|
|
||||||
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_steal_tooltip";
|
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_steal_tooltip";
|
||||||
encounter.dialogue.encounterOptionsDialogue.options[1].style = TextStyle.SUMMARY_GREEN;
|
|
||||||
} else {
|
} else {
|
||||||
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_tooltip";
|
encounter.dialogue.encounterOptionsDialogue.options[1].buttonTooltip = "mysteryEncounter:fight_or_flight_option_2_tooltip";
|
||||||
encounter.dialogue.encounterOptionsDialogue.options[1].style = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -104,44 +89,44 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder
|
|||||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||||
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]);
|
await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0]);
|
||||||
})
|
})
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
// Pick steal
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
.withDisabledOnRequirementsNotMet(false)
|
||||||
const item = scene.currentBattle.mysteryEncounter.misc as ModifierTypeOption;
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
// Pick steal
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const item = scene.currentBattle.mysteryEncounter.misc as ModifierTypeOption;
|
||||||
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false });
|
||||||
|
|
||||||
// If player has a stealing move, they succeed automatically
|
// If player has a stealing move, they succeed automatically
|
||||||
const moveRequirement = new MoveRequirement(validMovesForSteal);
|
const primaryPokemon = encounter.options[1].primaryPokemon;
|
||||||
const validPokemon = moveRequirement.queryParty(scene.getParty());
|
if (primaryPokemon) {
|
||||||
if (validPokemon?.length > 0) {
|
// Use primaryPokemon to execute the thievery
|
||||||
// Use first valid pokemon to execute the theivery
|
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_steal_result");
|
||||||
const pokemon = validPokemon[0];
|
leaveEncounterWithoutBattle(scene);
|
||||||
encounter.setDialogueToken("thiefPokemon", pokemon.name);
|
return;
|
||||||
encounter.setDialogueToken(...moveRequirement.getDialogueToken(scene, pokemon));
|
}
|
||||||
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_steal_result");
|
|
||||||
leaveEncounterWithoutBattle(scene);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const roll = randSeedInt(16);
|
const roll = randSeedInt(16);
|
||||||
if (roll > 6) {
|
if (roll > 6) {
|
||||||
// Noticed and attacked by boss, gets +1 to all stats at start of fight (62.5%)
|
// Noticed and attacked by boss, gets +1 to all stats at start of fight (62.5%)
|
||||||
const config = scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
const config = scene.currentBattle.mysteryEncounter.enemyPartyConfigs[0];
|
||||||
config.pokemonConfigs[0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
config.pokemonConfigs[0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON];
|
||||||
config.pokemonConfigs[0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
config.pokemonConfigs[0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => {
|
||||||
pokemon.scene.currentBattle.mysteryEncounter.setDialogueToken("enemyPokemon", pokemon.name);
|
pokemon.scene.currentBattle.mysteryEncounter.setDialogueToken("enemyPokemon", pokemon.name);
|
||||||
queueEncounterMessage(pokemon.scene, "mysteryEncounter:fight_or_flight_boss_enraged");
|
queueEncounterMessage(pokemon.scene, "mysteryEncounter:fight_or_flight_boss_enraged");
|
||||||
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD], 1));
|
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD], 1));
|
||||||
};
|
};
|
||||||
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_bad_result");
|
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_bad_result");
|
||||||
await initBattleWithEnemyConfig(scene, config);
|
await initBattleWithEnemyConfig(scene, config);
|
||||||
} else {
|
} else {
|
||||||
// Steal item (37.5%)
|
// Steal item (37.5%)
|
||||||
// Display result message then proceed to rewards
|
// Display result message then proceed to rewards
|
||||||
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_good_result");
|
await showEncounterText(scene, "mysteryEncounter:fight_or_flight_option_2_good_result");
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.build())
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Leave encounter with no rewards or exp
|
// Leave encounter with no rewards or exp
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
generateModifierType,
|
generateModifierTypeOption,
|
||||||
leaveEncounterWithoutBattle,
|
leaveEncounterWithoutBattle,
|
||||||
queueEncounterMessage,
|
queueEncounterMessage,
|
||||||
selectPokemonForOption,
|
selectPokemonForOption, setEncounterExp,
|
||||||
setEncounterRewards,
|
|
||||||
updatePlayerMoney,
|
updatePlayerMoney,
|
||||||
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
||||||
import { StatusEffect } from "#app/data/status-effect";
|
import { StatusEffect } from "#app/data/status-effect";
|
||||||
@ -18,6 +17,7 @@ import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
|||||||
import {
|
import {
|
||||||
MoneyRequirement
|
MoneyRequirement
|
||||||
} from "../mystery-encounter-requirements";
|
} from "../mystery-encounter-requirements";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBuilder
|
export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||||
.withEncounterType(MysteryEncounterType.SHADY_VITAMIN_DEALER)
|
.withEncounterType(MysteryEncounterType.SHADY_VITAMIN_DEALER)
|
||||||
@ -43,7 +43,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
.withPrimaryPokemonStatusEffectRequirement([StatusEffect.NONE]) // Pokemon must not have status
|
.withPrimaryPokemonStatusEffectRequirement([StatusEffect.NONE]) // Pokemon must not have status
|
||||||
.withPrimaryPokemonHealthRatioRequirement([0.34, 1]) // Pokemon must have above 1/3rd HP
|
.withPrimaryPokemonHealthRatioRequirement([0.34, 1]) // Pokemon must have above 1/3rd HP
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
.withSceneMoneyRequirement(0, 2) // Wave scaling multiplier of 2 for cost
|
.withSceneMoneyRequirement(0, 2) // Wave scaling money multiplier of 2
|
||||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
const encounter = scene.currentBattle.mysteryEncounter;
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
@ -51,8 +51,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney);
|
updatePlayerMoney(scene, -(encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney);
|
||||||
// Calculate modifiers and dialogue tokens
|
// Calculate modifiers and dialogue tokens
|
||||||
const modifiers = [
|
const modifiers = [
|
||||||
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER),
|
generateModifierTypeOption(scene, modifierTypes.BASE_STAT_BOOSTER).type,
|
||||||
generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER)
|
generateModifierTypeOption(scene, modifierTypes.BASE_STAT_BOOSTER).type
|
||||||
];
|
];
|
||||||
encounter.setDialogueToken("boost1", modifiers[0].name);
|
encounter.setDialogueToken("boost1", modifiers[0].name);
|
||||||
encounter.setDialogueToken("boost2", modifiers[1].name);
|
encounter.setDialogueToken("boost2", modifiers[1].name);
|
||||||
@ -62,12 +62,12 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only Pokemon that can gain benefits are unfainted with no status
|
// Only Pokemon that can gain benefits are above 1/3rd HP with no status
|
||||||
const selectableFilter = (pokemon: Pokemon) => {
|
const selectableFilter = (pokemon: Pokemon) => {
|
||||||
// If pokemon meets primary pokemon reqs, it can be selected
|
// If pokemon meets primary pokemon reqs, it can be selected
|
||||||
const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon);
|
const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||||
if (!meetsReqs) {
|
if (!meetsReqs) {
|
||||||
return "Pokémon must be healthy enough.";
|
return i18next.t("mysteryEncounter:shady_vitamin_dealer_invalid_selection");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -99,7 +99,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
chosenPokemon.hp = Math.max(chosenPokemon.hp - damage, 0);
|
chosenPokemon.hp = Math.max(chosenPokemon.hp - damage, 0);
|
||||||
|
|
||||||
// Roll for poison (80%)
|
// Roll for poison (80%)
|
||||||
if (randSeedInt(10) < 10) {
|
if (randSeedInt(10) < 8) {
|
||||||
if (chosenPokemon.trySetStatus(StatusEffect.TOXIC)) {
|
if (chosenPokemon.trySetStatus(StatusEffect.TOXIC)) {
|
||||||
// Toxic applied
|
// Toxic applied
|
||||||
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_bad_poison");
|
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_bad_poison");
|
||||||
@ -111,32 +111,81 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
|||||||
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_damage_only");
|
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_damage_only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||||
|
|
||||||
chosenPokemon.updateInfo();
|
chosenPokemon.updateInfo();
|
||||||
})
|
})
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
.withSceneMoneyRequirement(0, 5) // Wave scaling multiplier of 2 for cost
|
.withSceneMoneyRequirement(0, 5) // Wave scaling money multiplier of 5
|
||||||
|
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||||
|
// Update money
|
||||||
|
updatePlayerMoney(scene, -(encounter.options[1].requirements[0] as MoneyRequirement).requiredMoney);
|
||||||
|
// Calculate modifiers and dialogue tokens
|
||||||
|
const modifiers = [
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.BASE_STAT_BOOSTER).type,
|
||||||
|
generateModifierTypeOption(scene, modifierTypes.BASE_STAT_BOOSTER).type
|
||||||
|
];
|
||||||
|
encounter.setDialogueToken("boost1", modifiers[0].name);
|
||||||
|
encounter.setDialogueToken("boost2", modifiers[1].name);
|
||||||
|
encounter.misc = {
|
||||||
|
chosenPokemon: pokemon,
|
||||||
|
modifiers: modifiers
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only Pokemon that can gain benefits are above 1/3rd HP with no status
|
||||||
|
const selectableFilter = (pokemon: Pokemon) => {
|
||||||
|
// If pokemon meets primary pokemon reqs, it can be selected
|
||||||
|
const meetsReqs = encounter.pokemonMeetsPrimaryRequirements(scene, pokemon);
|
||||||
|
if (!meetsReqs) {
|
||||||
|
return i18next.t("mysteryEncounter:shady_vitamin_dealer_invalid_selection");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||||
|
})
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Choose Expensive Option
|
// Choose Expensive Option
|
||||||
const modifiers = [];
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
let i = 0;
|
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||||
while (i < 3) {
|
const modifiers = encounter.misc.modifiers;
|
||||||
// 2/1 weight on base stat booster vs PP Up
|
|
||||||
const roll = randSeedInt(3);
|
|
||||||
if (roll === 0) {
|
|
||||||
modifiers.push(modifierTypes.PP_UP);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
for (const modType of modifiers) {
|
||||||
i++;
|
const modifier = modType.newModifier(chosenPokemon);
|
||||||
|
await scene.addModifier(modifier, true, false, false, true);
|
||||||
}
|
}
|
||||||
|
scene.updateModifiers(true);
|
||||||
|
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: modifiers, fillRemaining: false });
|
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene);
|
||||||
})
|
})
|
||||||
.build()
|
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||||
)
|
// Status applied after dealer leaves (to make thematic sense)
|
||||||
|
const encounter = scene.currentBattle.mysteryEncounter;
|
||||||
|
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||||
|
|
||||||
|
// Roll for poison (20%)
|
||||||
|
if (randSeedInt(10) < 2) {
|
||||||
|
if (chosenPokemon.trySetStatus(StatusEffect.POISON)) {
|
||||||
|
// Poison applied
|
||||||
|
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_poison");
|
||||||
|
} else {
|
||||||
|
// Pokemon immune or something else prevents status
|
||||||
|
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_no_bad_effects");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queueEncounterMessage(scene, "mysteryEncounter:shady_vitamin_dealer_no_bad_effects");
|
||||||
|
}
|
||||||
|
|
||||||
|
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||||
|
|
||||||
|
chosenPokemon.updateInfo();
|
||||||
|
})
|
||||||
|
.build())
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Leave encounter with no rewards or exp
|
// Leave encounter with no rewards or exp
|
||||||
leaveEncounterWithoutBattle(scene, true);
|
leaveEncounterWithoutBattle(scene, true);
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ModifierTypeOption,
|
|
||||||
modifierTypes
|
modifierTypes
|
||||||
} from "#app/modifier/modifier-type";
|
} from "#app/modifier/modifier-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Moves } from "#enums/moves";
|
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import BattleScene from "../../../battle-scene";
|
import BattleScene from "../../../battle-scene";
|
||||||
@ -15,11 +13,12 @@ import { MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
|||||||
import { MoveRequirement } from "../mystery-encounter-requirements";
|
import { MoveRequirement } from "../mystery-encounter-requirements";
|
||||||
import {
|
import {
|
||||||
EnemyPartyConfig,
|
EnemyPartyConfig,
|
||||||
EnemyPokemonConfig, generateModifierType,
|
EnemyPokemonConfig, generateModifierTypeOption,
|
||||||
initBattleWithEnemyConfig,
|
initBattleWithEnemyConfig,
|
||||||
leaveEncounterWithoutBattle, queueEncounterMessage,
|
leaveEncounterWithoutBattle, queueEncounterMessage, setEncounterExp,
|
||||||
setEncounterRewards
|
setEncounterRewards
|
||||||
} from "../mystery-encounter-utils";
|
} from "../mystery-encounter-utils";
|
||||||
|
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||||
|
|
||||||
export const SleepingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuilder
|
export const SleepingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||||
.withEncounterType(MysteryEncounterType.SLEEPING_SNORLAX)
|
.withEncounterType(MysteryEncounterType.SLEEPING_SNORLAX)
|
||||||
@ -30,7 +29,9 @@ export const SleepingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
fileRoot: "pokemon",
|
fileRoot: "pokemon",
|
||||||
hasShadow: true,
|
hasShadow: true,
|
||||||
tint: 0.25,
|
tint: 0.25,
|
||||||
repeat: true
|
scale: 1.5,
|
||||||
|
repeat: true,
|
||||||
|
y: 5
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
|
.withSceneWaveRangeRequirement(10, 180) // waves 10 to 180
|
||||||
@ -66,16 +67,19 @@ export const SleepingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
scene.executeWithSeedOffset(() => {
|
scene.executeWithSeedOffset(() => {
|
||||||
roll = Utils.randSeedInt(16, 0);
|
roll = Utils.randSeedInt(16, 0);
|
||||||
}, scene.currentBattle.waveIndex);
|
}, scene.currentBattle.waveIndex);
|
||||||
console.log(roll);
|
|
||||||
|
// Half Snorlax exp to entire party
|
||||||
|
setEncounterExp(scene, scene.getParty().map(p => p.id), 98);
|
||||||
|
|
||||||
if (roll > 4) {
|
if (roll > 4) {
|
||||||
// Fall asleep and get a sitrus berry (75%)
|
// Fall asleep and get a sitrus berry (75%)
|
||||||
const p = instance.primaryPokemon;
|
const p = instance.primaryPokemon;
|
||||||
p.status = new Status(StatusEffect.SLEEP, 0, 3);
|
p.status = new Status(StatusEffect.SLEEP, 0, 3);
|
||||||
p.updateInfo(true);
|
p.updateInfo(true);
|
||||||
// const sitrus = (modifierTypes.BERRY?.() as ModifierTypeGenerator).generateType(scene.getParty(), [BerryType.SITRUS]);
|
// const sitrus = (modifierTypes.BERRY?.() as ModifierTypeGenerator).generateType(scene.getParty(), [BerryType.SITRUS]);
|
||||||
const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]);
|
const sitrus = generateModifierTypeOption(scene, modifierTypes.BERRY, [BerryType.SITRUS]);
|
||||||
|
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [new ModifierTypeOption(sitrus, 0)], fillRemaining: false });
|
setEncounterRewards(scene, { guaranteedModifierTypeOptions: [sitrus], fillRemaining: false });
|
||||||
queueEncounterMessage(scene, "mysteryEncounter:sleeping_snorlax_option_2_bad_result");
|
queueEncounterMessage(scene, "mysteryEncounter:sleeping_snorlax_option_2_bad_result");
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene);
|
||||||
} else {
|
} else {
|
||||||
@ -94,11 +98,14 @@ export const SleepingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuilde
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.withOption(new MysteryEncounterOptionBuilder()
|
.withOption(new MysteryEncounterOptionBuilder()
|
||||||
.withPrimaryPokemonRequirement(new MoveRequirement([Moves.PLUCK, Moves.COVET, Moves.KNOCK_OFF, Moves.THIEF, Moves.TRICK, Moves.SWITCHEROO]))
|
.withPrimaryPokemonRequirement(new MoveRequirement(STEALING_MOVES))
|
||||||
.withOptionPhase(async (scene: BattleScene) => {
|
.withOptionPhase(async (scene: BattleScene) => {
|
||||||
// Leave encounter with no rewards or exp
|
// Steal the Snorlax's Leftovers
|
||||||
|
const instance = scene.currentBattle.mysteryEncounter;
|
||||||
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false });
|
setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false });
|
||||||
queueEncounterMessage(scene, "mysteryEncounter:sleeping_snorlax_option_3_good_result");
|
queueEncounterMessage(scene, "mysteryEncounter:sleeping_snorlax_option_3_good_result");
|
||||||
|
// Snorlax exp to Pokemon that did the stealing
|
||||||
|
setEncounterExp(scene, [instance.primaryPokemon.id], 189);
|
||||||
leaveEncounterWithoutBattle(scene);
|
leaveEncounterWithoutBattle(scene);
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
@ -8,6 +8,7 @@ import { SleepingSnorlaxDialogue } from "./dialogue/sleeping-snorlax-dialogue";
|
|||||||
import { DepartmentStoreSaleDialogue } from "#app/data/mystery-encounters/dialogue/department-store-sale-dialogue";
|
import { DepartmentStoreSaleDialogue } from "#app/data/mystery-encounters/dialogue/department-store-sale-dialogue";
|
||||||
import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer";
|
import { ShadyVitaminDealerDialogue } from "#app/data/mystery-encounters/dialogue/shady-vitamin-dealer";
|
||||||
import { TextStyle } from "#app/ui/text";
|
import { TextStyle } from "#app/ui/text";
|
||||||
|
import { FieldTripDialogue } from "#app/data/mystery-encounters/dialogue/field-trip-dialogue";
|
||||||
|
|
||||||
export class TextDisplay {
|
export class TextDisplay {
|
||||||
speaker?: TemplateStringsArray | `mysteryEncounter:${string}`;
|
speaker?: TemplateStringsArray | `mysteryEncounter:${string}`;
|
||||||
@ -92,4 +93,5 @@ export function initMysteryEncounterDialogue() {
|
|||||||
allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue;
|
allMysteryEncounterDialogue[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxDialogue;
|
||||||
allMysteryEncounterDialogue[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleDialogue;
|
allMysteryEncounterDialogue[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleDialogue;
|
||||||
allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue;
|
allMysteryEncounterDialogue[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerDialogue;
|
||||||
|
allMysteryEncounterDialogue[MysteryEncounterType.FIELD_TRIP] = FieldTripDialogue;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { PlayerPokemon } from "#app/field/pokemon";
|
|||||||
import BattleScene from "../../battle-scene";
|
import BattleScene from "../../battle-scene";
|
||||||
import * as Utils from "../../utils";
|
import * as Utils from "../../utils";
|
||||||
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement } from "./mystery-encounter-requirements";
|
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement } from "./mystery-encounter-requirements";
|
||||||
|
import { isNullOrUndefined } from "../../utils";
|
||||||
|
|
||||||
|
|
||||||
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
|
export type OptionPhaseCallback = (scene: BattleScene) => Promise<void | boolean>;
|
||||||
@ -14,6 +15,12 @@ export default interface MysteryEncounterOption {
|
|||||||
primaryPokemon?: PlayerPokemon;
|
primaryPokemon?: PlayerPokemon;
|
||||||
secondaryPokemon?: PlayerPokemon[];
|
secondaryPokemon?: PlayerPokemon[];
|
||||||
excludePrimaryFromSecondaryRequirements?: boolean;
|
excludePrimaryFromSecondaryRequirements?: boolean;
|
||||||
|
/**
|
||||||
|
* There are two modes of option requirements:
|
||||||
|
* 1 (DEFAULT): Option is completely disabled if requirements are not met (unselectable and greyed out)
|
||||||
|
* 2: Option is *NOT* disabled if requirements are not met
|
||||||
|
*/
|
||||||
|
isDisabledOnRequirementsNotMet?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogue object containing all the dialogue, messages, tooltips, etc. for this option
|
* Dialogue object containing all the dialogue, messages, tooltips, etc. for this option
|
||||||
@ -33,12 +40,19 @@ export default class MysteryEncounterOption implements MysteryEncounterOption {
|
|||||||
constructor(option: MysteryEncounterOption) {
|
constructor(option: MysteryEncounterOption) {
|
||||||
Object.assign(this, option);
|
Object.assign(this, option);
|
||||||
this.requirements = this.requirements ? this.requirements : [];
|
this.requirements = this.requirements ? this.requirements : [];
|
||||||
|
this.primaryPokemonRequirements = this.primaryPokemonRequirements ? this.primaryPokemonRequirements : [];
|
||||||
|
this.secondaryPokemonRequirements = this.secondaryPokemonRequirements ? this.secondaryPokemonRequirements : [];
|
||||||
|
this.isDisabledOnRequirementsNotMet = isNullOrUndefined(this.isDisabledOnRequirementsNotMet) ? true : this.isDisabledOnRequirementsNotMet;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasRequirements?() {
|
||||||
|
return this.requirements.length > 0 || this.primaryPokemonRequirements.length > 0 || this.secondaryPokemonRequirements.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
meetsRequirements?(scene: BattleScene) {
|
meetsRequirements?(scene: BattleScene) {
|
||||||
return !this.requirements.some(requirement => !requirement.meetsRequirement(scene)) &&
|
return !this.requirements.some(requirement => !requirement.meetsRequirement(scene)) &&
|
||||||
this.meetsPrimaryRequirementAndPrimaryPokemonSelected(scene) &&
|
this.meetsSupportingRequirementAndSupportingPokemonSelected(scene) &&
|
||||||
this.meetsSupportingRequirementAndSupportingPokemonSelected(scene);
|
this.meetsPrimaryRequirementAndPrimaryPokemonSelected(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
meetsPrimaryRequirementAndPrimaryPokemonSelected?(scene: BattleScene) {
|
meetsPrimaryRequirementAndPrimaryPokemonSelected?(scene: BattleScene) {
|
||||||
@ -124,6 +138,7 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
primaryPokemonRequirements?: EncounterPokemonRequirement[] = [];
|
primaryPokemonRequirements?: EncounterPokemonRequirement[] = [];
|
||||||
secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = [];
|
secondaryPokemonRequirements ?: EncounterPokemonRequirement[] = [];
|
||||||
excludePrimaryFromSecondaryRequirements?: boolean;
|
excludePrimaryFromSecondaryRequirements?: boolean;
|
||||||
|
isDisabledOnRequirementsNotMet?: boolean;
|
||||||
onPreOptionPhase?: OptionPhaseCallback;
|
onPreOptionPhase?: OptionPhaseCallback;
|
||||||
onOptionPhase?: OptionPhaseCallback;
|
onOptionPhase?: OptionPhaseCallback;
|
||||||
onPostOptionPhase?: OptionPhaseCallback;
|
onPostOptionPhase?: OptionPhaseCallback;
|
||||||
@ -163,4 +178,9 @@ export class MysteryEncounterOptionBuilder implements Partial<MysteryEncounterOp
|
|||||||
this.excludePrimaryFromSecondaryRequirements = excludePrimaryFromSecondaryRequirements;
|
this.excludePrimaryFromSecondaryRequirements = excludePrimaryFromSecondaryRequirements;
|
||||||
return Object.assign(this, { secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
return Object.assign(this, { secondaryPokemonRequirements: this.secondaryPokemonRequirements });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withDisabledOnRequirementsNotMet(disabled: boolean): this & Required<Pick<MysteryEncounterOption, "isDisabledOnRequirementsNotMet">> {
|
||||||
|
this.isDisabledOnRequirementsNotMet = disabled;
|
||||||
|
return Object.assign(this, { isDisabledOnRequirementsNotMet: this.isDisabledOnRequirementsNotMet });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { TrainerConfig, trainerConfigs, TrainerSlot } from "../trainer-config";
|
|||||||
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
|
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
|
||||||
import Trainer, { TrainerVariant } from "../../field/trainer";
|
import Trainer, { TrainerVariant } from "../../field/trainer";
|
||||||
import { ExpBalanceModifier, ExpShareModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier";
|
import { ExpBalanceModifier, ExpShareModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier";
|
||||||
import { CustomModifierSettings, getModifierPoolForType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
import { CustomModifierSettings, getModifierPoolForType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, PokemonHeldItemModifierType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
import { BattleEndPhase, EggLapsePhase, ExpPhase, ModifierRewardPhase, SelectModifierPhase, ShowPartyExpBarPhase, TrainerVictoryPhase } from "#app/phases";
|
import { BattleEndPhase, EggLapsePhase, ExpPhase, ModifierRewardPhase, SelectModifierPhase, ShowPartyExpBarPhase, TrainerVictoryPhase } from "#app/phases";
|
||||||
import { MysteryEncounterBattlePhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phase";
|
import { MysteryEncounterBattlePhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phase";
|
||||||
import * as Utils from "../../utils";
|
import * as Utils from "../../utils";
|
||||||
@ -443,7 +443,7 @@ export function updatePlayerMoney(scene: BattleScene, changeValue: number, playS
|
|||||||
* @param modifier
|
* @param modifier
|
||||||
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||||
*/
|
*/
|
||||||
export function generateModifierType(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierType {
|
export function generateModifierTypeOption(scene: BattleScene, modifier: () => ModifierType, pregenArgs?: any[]): ModifierTypeOption {
|
||||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier);
|
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier);
|
||||||
let result: ModifierType = modifierTypes[modifierId]?.();
|
let result: ModifierType = modifierTypes[modifierId]?.();
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ export function generateModifierType(scene: BattleScene, modifier: () => Modifie
|
|||||||
});
|
});
|
||||||
|
|
||||||
result = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
result = result instanceof ModifierTypeGenerator ? result.generateType(scene.getParty(), pregenArgs) : result;
|
||||||
return result;
|
return new ModifierTypeOption(result, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -593,6 +593,7 @@ export function setEncounterRewards(scene: BattleScene, customShopRewards?: Cust
|
|||||||
* 290 - trio legendaries
|
* 290 - trio legendaries
|
||||||
* 340 - box legendaries
|
* 340 - box legendaries
|
||||||
* 608 - Blissey (highest in game)
|
* 608 - Blissey (highest in game)
|
||||||
|
* https://bulbapedia.bulbagarden.net/wiki/List_of_Pok%C3%A9mon_by_effort_value_yield_(Generation_IX)
|
||||||
* @param useWaveIndex - set to false when directly passing the the full exp value instead of baseExpValue
|
* @param useWaveIndex - set to false when directly passing the the full exp value instead of baseExpValue
|
||||||
*/
|
*/
|
||||||
export function setEncounterExp(scene: BattleScene, participantIds: integer[], baseExpValue: number, useWaveIndex: boolean = true) {
|
export function setEncounterExp(scene: BattleScene, participantIds: integer[], baseExpValue: number, useWaveIndex: boolean = true) {
|
||||||
|
@ -120,6 +120,7 @@ export default interface MysteryEncounter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic property to set any custom data required for the encounter
|
* Generic property to set any custom data required for the encounter
|
||||||
|
* Extremely useful for carrying state/data between onPreOptionPhase/onOptionPhase/onPostOptionPhase
|
||||||
*/
|
*/
|
||||||
misc?: any;
|
misc?: any;
|
||||||
}
|
}
|
||||||
@ -276,6 +277,7 @@ export default class MysteryEncounter implements MysteryEncounter {
|
|||||||
* For multiple support pokemon in the dialogue token, it will have to be overridden.
|
* For multiple support pokemon in the dialogue token, it will have to be overridden.
|
||||||
*/
|
*/
|
||||||
populateDialogueTokensFromRequirements?(scene: BattleScene) {
|
populateDialogueTokensFromRequirements?(scene: BattleScene) {
|
||||||
|
this.meetsRequirements(scene);
|
||||||
if (this.requirements?.length > 0) {
|
if (this.requirements?.length > 0) {
|
||||||
for (const req of this.requirements) {
|
for (const req of this.requirements) {
|
||||||
const dialogueToken = req.getDialogueToken(scene);
|
const dialogueToken = req.getDialogueToken(scene);
|
||||||
@ -304,6 +306,7 @@ export default class MysteryEncounter implements MysteryEncounter {
|
|||||||
// Dialogue tokens for options
|
// Dialogue tokens for options
|
||||||
for (let i = 0; i < this.options.length; i++) {
|
for (let i = 0; i < this.options.length; i++) {
|
||||||
const opt = this.options[i];
|
const opt = this.options[i];
|
||||||
|
opt.meetsRequirements(scene);
|
||||||
const j = i + 1;
|
const j = i + 1;
|
||||||
if (opt.requirements?.length > 0) {
|
if (opt.requirements?.length > 0) {
|
||||||
for (const req of opt.requirements) {
|
for (const req of opt.requirements) {
|
||||||
@ -316,7 +319,7 @@ export default class MysteryEncounter implements MysteryEncounter {
|
|||||||
for (const req of opt.primaryPokemonRequirements) {
|
for (const req of opt.primaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, opt.primaryPokemon);
|
const value = req.getDialogueToken(scene, opt.primaryPokemon);
|
||||||
this.setDialogueToken("option" + j + "Primary", value[1]);
|
this.setDialogueToken("option" + j + "Primary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +328,7 @@ export default class MysteryEncounter implements MysteryEncounter {
|
|||||||
for (const req of opt.secondaryPokemonRequirements) {
|
for (const req of opt.secondaryPokemonRequirements) {
|
||||||
if (!req.invertQuery) {
|
if (!req.invertQuery) {
|
||||||
const value = req.getDialogueToken(scene, opt.secondaryPokemon[0]);
|
const value = req.getDialogueToken(scene, opt.secondaryPokemon[0]);
|
||||||
this.setDialogueToken("option" + j + "Secondary", value[1]);
|
this.setDialogueToken("option" + j + "Secondary" + this.capitalizeFirstLetter(value[0]), value[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,42 +9,164 @@ import { SleepingSnorlaxEncounter } from "./encounters/sleeping-snorlax";
|
|||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { DepartmentStoreSaleEncounter } from "#app/data/mystery-encounters/encounters/department-store-sale";
|
import { DepartmentStoreSaleEncounter } from "#app/data/mystery-encounters/encounters/department-store-sale";
|
||||||
import { ShadyVitaminDealerEncounter } from "#app/data/mystery-encounters/encounters/shady-vitamin-dealer";
|
import { ShadyVitaminDealerEncounter } from "#app/data/mystery-encounters/encounters/shady-vitamin-dealer";
|
||||||
|
import { FieldTripEncounter } from "#app/data/mystery-encounters/encounters/field-trip-encounter";
|
||||||
|
|
||||||
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
|
// Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / 256
|
||||||
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
|
export const BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT = 1;
|
||||||
export const WIGHT_INCREMENT_ON_SPAWN_MISS = 5;
|
export const WIGHT_INCREMENT_ON_SPAWN_MISS = 5;
|
||||||
export const AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 15;
|
export const AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 15;
|
||||||
|
|
||||||
|
export const EXTREME_ENCOUNTER_BIOMES = [
|
||||||
|
Biome.SEA,
|
||||||
|
Biome.SEABED,
|
||||||
|
Biome.BADLANDS,
|
||||||
|
Biome.DESERT,
|
||||||
|
Biome.ICE_CAVE,
|
||||||
|
Biome.VOLCANO,
|
||||||
|
Biome.WASTELAND,
|
||||||
|
Biome.ABYSS,
|
||||||
|
Biome.SPACE,
|
||||||
|
Biome.END
|
||||||
|
];
|
||||||
|
|
||||||
|
export const NON_EXTREME_ENCOUNTER_BIOMES = [
|
||||||
|
Biome.TOWN,
|
||||||
|
Biome.PLAINS,
|
||||||
|
Biome.GRASS,
|
||||||
|
Biome.TALL_GRASS,
|
||||||
|
Biome.METROPOLIS,
|
||||||
|
Biome.FOREST,
|
||||||
|
Biome.SWAMP,
|
||||||
|
Biome.BEACH,
|
||||||
|
Biome.LAKE,
|
||||||
|
Biome.MOUNTAIN,
|
||||||
|
Biome.CAVE,
|
||||||
|
Biome.MEADOW,
|
||||||
|
Biome.POWER_PLANT,
|
||||||
|
Biome.GRAVEYARD,
|
||||||
|
Biome.DOJO,
|
||||||
|
Biome.FACTORY,
|
||||||
|
Biome.RUINS,
|
||||||
|
Biome.CONSTRUCTION_SITE,
|
||||||
|
Biome.JUNGLE,
|
||||||
|
Biome.FAIRY_CAVE,
|
||||||
|
Biome.TEMPLE,
|
||||||
|
Biome.SLUM,
|
||||||
|
Biome.SNOWY_FOREST,
|
||||||
|
Biome.ISLAND,
|
||||||
|
Biome.LABORATORY
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places where you could very reasonably expect to encounter a single human
|
||||||
|
*
|
||||||
|
* Diff from NON_EXTREME_ENCOUNTER_BIOMES:
|
||||||
|
* + BADLANDS
|
||||||
|
* + DESERT
|
||||||
|
* + ICE_CAVE
|
||||||
|
*/
|
||||||
|
export const HUMAN_TRANSITABLE_BIOMES = [
|
||||||
|
Biome.TOWN,
|
||||||
|
Biome.PLAINS,
|
||||||
|
Biome.GRASS,
|
||||||
|
Biome.TALL_GRASS,
|
||||||
|
Biome.METROPOLIS,
|
||||||
|
Biome.FOREST,
|
||||||
|
Biome.SWAMP,
|
||||||
|
Biome.BEACH,
|
||||||
|
Biome.LAKE,
|
||||||
|
Biome.MOUNTAIN,
|
||||||
|
Biome.BADLANDS,
|
||||||
|
Biome.CAVE,
|
||||||
|
Biome.DESERT,
|
||||||
|
Biome.ICE_CAVE,
|
||||||
|
Biome.MEADOW,
|
||||||
|
Biome.POWER_PLANT,
|
||||||
|
Biome.GRAVEYARD,
|
||||||
|
Biome.DOJO,
|
||||||
|
Biome.FACTORY,
|
||||||
|
Biome.RUINS,
|
||||||
|
Biome.CONSTRUCTION_SITE,
|
||||||
|
Biome.JUNGLE,
|
||||||
|
Biome.FAIRY_CAVE,
|
||||||
|
Biome.TEMPLE,
|
||||||
|
Biome.SLUM,
|
||||||
|
Biome.SNOWY_FOREST,
|
||||||
|
Biome.ISLAND,
|
||||||
|
Biome.LABORATORY
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places where you could expect a town or city, some form of large civilization
|
||||||
|
*/
|
||||||
|
export const CIVILIZATION_ENCOUNTER_BIOMES = [
|
||||||
|
Biome.TOWN,
|
||||||
|
Biome.PLAINS,
|
||||||
|
Biome.GRASS,
|
||||||
|
Biome.TALL_GRASS,
|
||||||
|
Biome.METROPOLIS,
|
||||||
|
Biome.BEACH,
|
||||||
|
Biome.LAKE,
|
||||||
|
Biome.MEADOW,
|
||||||
|
Biome.POWER_PLANT,
|
||||||
|
Biome.GRAVEYARD,
|
||||||
|
Biome.DOJO,
|
||||||
|
Biome.FACTORY,
|
||||||
|
Biome.CONSTRUCTION_SITE,
|
||||||
|
Biome.SLUM,
|
||||||
|
Biome.ISLAND
|
||||||
|
];
|
||||||
|
|
||||||
export const allMysteryEncounters: { [encounterType: number]: MysteryEncounter } = {};
|
export const allMysteryEncounters: { [encounterType: number]: MysteryEncounter } = {};
|
||||||
|
|
||||||
// Add MysteryEncounterType to biomes to enable it exclusively for those biomes
|
|
||||||
// To enable an encounter in all biomes, do not add to this map
|
const extremeBiomeEncounters: MysteryEncounterType[] = [];
|
||||||
|
|
||||||
|
const nonExtremeBiomeEncounters: MysteryEncounterType[] = [
|
||||||
|
MysteryEncounterType.FIELD_TRIP
|
||||||
|
];
|
||||||
|
|
||||||
|
const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
|
||||||
|
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
||||||
|
MysteryEncounterType.SHADY_VITAMIN_DEALER
|
||||||
|
];
|
||||||
|
|
||||||
|
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
||||||
|
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To add an encounter to every biome possible, use this array
|
||||||
|
*/
|
||||||
|
const anyBiomeEncounters: MysteryEncounterType[] = [
|
||||||
|
MysteryEncounterType.FIGHT_OR_FLIGHT,
|
||||||
|
MysteryEncounterType.DARK_DEAL,
|
||||||
|
MysteryEncounterType.MYSTERIOUS_CHEST,
|
||||||
|
MysteryEncounterType.TRAINING_SESSION
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ENCOUNTER BIOME MAPPING
|
||||||
|
* To add an Encounter to a biome group, instead of cluttering the map, use the biome group arrays above
|
||||||
|
*
|
||||||
|
* Adding specific Encounters to the mysteryEncountersByBiome map is for specific cases and special circumstances
|
||||||
|
* that biome groups do not cover
|
||||||
|
*/
|
||||||
export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
||||||
[Biome.TOWN, [
|
[Biome.TOWN, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
[Biome.PLAINS, []],
|
||||||
]],
|
|
||||||
[Biome.PLAINS, [
|
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.GRASS, [
|
[Biome.GRASS, [
|
||||||
MysteryEncounterType.SLEEPING_SNORLAX,
|
MysteryEncounterType.SLEEPING_SNORLAX,
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.TALL_GRASS, [
|
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.METROPOLIS, [
|
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
]],
|
||||||
|
[Biome.TALL_GRASS, []],
|
||||||
|
[Biome.METROPOLIS, []],
|
||||||
[Biome.FOREST, [
|
[Biome.FOREST, [
|
||||||
MysteryEncounterType.SLEEPING_SNORLAX
|
MysteryEncounterType.SLEEPING_SNORLAX
|
||||||
]],
|
]],
|
||||||
|
|
||||||
[Biome.SEA, []],
|
[Biome.SEA, []],
|
||||||
[Biome.SWAMP, []],
|
[Biome.SWAMP, []],
|
||||||
[Biome.BEACH, [
|
[Biome.BEACH, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.LAKE, []],
|
[Biome.LAKE, []],
|
||||||
[Biome.SEABED, []],
|
[Biome.SEABED, []],
|
||||||
[Biome.MOUNTAIN, [
|
[Biome.MOUNTAIN, [
|
||||||
@ -56,31 +178,21 @@ export const mysteryEncountersByBiome = new Map<Biome, MysteryEncounterType[]>([
|
|||||||
]],
|
]],
|
||||||
[Biome.DESERT, []],
|
[Biome.DESERT, []],
|
||||||
[Biome.ICE_CAVE, []],
|
[Biome.ICE_CAVE, []],
|
||||||
[Biome.MEADOW, [
|
[Biome.MEADOW, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
[Biome.POWER_PLANT, []],
|
||||||
]],
|
|
||||||
[Biome.POWER_PLANT, [
|
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.VOLCANO, []],
|
[Biome.VOLCANO, []],
|
||||||
[Biome.GRAVEYARD, []],
|
[Biome.GRAVEYARD, []],
|
||||||
[Biome.DOJO, []],
|
[Biome.DOJO, []],
|
||||||
[Biome.FACTORY, [
|
[Biome.FACTORY, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.RUINS, []],
|
[Biome.RUINS, []],
|
||||||
[Biome.WASTELAND, []],
|
[Biome.WASTELAND, []],
|
||||||
[Biome.ABYSS, []],
|
[Biome.ABYSS, []],
|
||||||
[Biome.SPACE, []],
|
[Biome.SPACE, []],
|
||||||
[Biome.CONSTRUCTION_SITE, [
|
[Biome.CONSTRUCTION_SITE, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.JUNGLE, []],
|
[Biome.JUNGLE, []],
|
||||||
[Biome.FAIRY_CAVE, []],
|
[Biome.FAIRY_CAVE, []],
|
||||||
[Biome.TEMPLE, []],
|
[Biome.TEMPLE, []],
|
||||||
[Biome.SLUM, [
|
[Biome.SLUM, []],
|
||||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
|
||||||
]],
|
|
||||||
[Biome.SNOWY_FOREST, []],
|
[Biome.SNOWY_FOREST, []],
|
||||||
[Biome.ISLAND, []],
|
[Biome.ISLAND, []],
|
||||||
[Biome.LABORATORY, []]
|
[Biome.LABORATORY, []]
|
||||||
@ -95,16 +207,51 @@ export function initMysteryEncounters() {
|
|||||||
allMysteryEncounters[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxEncounter;
|
allMysteryEncounters[MysteryEncounterType.SLEEPING_SNORLAX] = SleepingSnorlaxEncounter;
|
||||||
allMysteryEncounters[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleEncounter;
|
allMysteryEncounters[MysteryEncounterType.DEPARTMENT_STORE_SALE] = DepartmentStoreSaleEncounter;
|
||||||
allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter;
|
allMysteryEncounters[MysteryEncounterType.SHADY_VITAMIN_DEALER] = ShadyVitaminDealerEncounter;
|
||||||
|
allMysteryEncounters[MysteryEncounterType.FIELD_TRIP] = FieldTripEncounter;
|
||||||
|
|
||||||
// Append encounters that can occur in any biome to biome map
|
// Add extreme encounters to biome map
|
||||||
const anyBiomeEncounters: MysteryEncounterType[] = Object.keys(MysteryEncounterType).filter(e => !isNaN(Number(e))).map(k => Number(k) as MysteryEncounterType);
|
extremeBiomeEncounters.forEach(encounter => {
|
||||||
mysteryEncountersByBiome.forEach(biomeEncounters => {
|
EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
||||||
biomeEncounters.forEach(e => {
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||||
if (anyBiomeEncounters.includes(e)) {
|
if (!encountersForBiome.includes(encounter)) {
|
||||||
anyBiomeEncounters.splice(anyBiomeEncounters.indexOf(e), 1);
|
encountersForBiome.push(encounter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Add non-extreme encounters to biome map
|
||||||
|
nonExtremeBiomeEncounters.forEach(encounter => {
|
||||||
|
NON_EXTREME_ENCOUNTER_BIOMES.forEach(biome => {
|
||||||
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||||
|
if (!encountersForBiome.includes(encounter)) {
|
||||||
|
encountersForBiome.push(encounter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Add human encounters to biome map
|
||||||
|
humanTransitableBiomeEncounters.forEach(encounter => {
|
||||||
|
HUMAN_TRANSITABLE_BIOMES.forEach(biome => {
|
||||||
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||||
|
if (!encountersForBiome.includes(encounter)) {
|
||||||
|
encountersForBiome.push(encounter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Add civilization encounters to biome map
|
||||||
|
civilizationBiomeEncounters.forEach(encounter => {
|
||||||
|
CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => {
|
||||||
|
const encountersForBiome = mysteryEncountersByBiome.get(biome);
|
||||||
|
if (!encountersForBiome.includes(encounter)) {
|
||||||
|
encountersForBiome.push(encounter);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
mysteryEncountersByBiome.forEach(biomeEncounters => biomeEncounters.push(...anyBiomeEncounters));
|
// Add ANY biome encounters to biome map
|
||||||
|
mysteryEncountersByBiome.forEach(biomeEncounters => {
|
||||||
|
anyBiomeEncounters.forEach(encounter => {
|
||||||
|
if (!biomeEncounters.includes(encounter)) {
|
||||||
|
biomeEncounters.push(encounter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
|
||||||
|
export const STEALING_MOVES = [
|
||||||
|
Moves.PLUCK,
|
||||||
|
Moves.COVET,
|
||||||
|
Moves.KNOCK_OFF,
|
||||||
|
Moves.THIEF,
|
||||||
|
Moves.TRICK,
|
||||||
|
Moves.SWITCHEROO
|
||||||
|
];
|
||||||
|
|
||||||
|
export const DISTRACTION_MOVES = [
|
||||||
|
Moves.FAKE_OUT,
|
||||||
|
Moves.FOLLOW_ME,
|
||||||
|
Moves.TAUNT,
|
||||||
|
Moves.ROAR,
|
||||||
|
Moves.TELEPORT,
|
||||||
|
Moves.CHARM,
|
||||||
|
Moves.FAKE_TEARS,
|
||||||
|
Moves.TICKLE,
|
||||||
|
Moves.CAPTIVATE,
|
||||||
|
Moves.RAGE_POWDER,
|
||||||
|
Moves.SUBSTITUTE,
|
||||||
|
Moves.SHED_TAIL
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROTECTING_MOVES = [
|
||||||
|
Moves.PROTECT,
|
||||||
|
Moves.WIDE_GUARD,
|
||||||
|
Moves.MAX_GUARD,
|
||||||
|
Moves.SAFEGUARD,
|
||||||
|
Moves.REFLECT,
|
||||||
|
Moves.BARRIER,
|
||||||
|
Moves.QUICK_GUARD,
|
||||||
|
Moves.FLOWER_SHIELD,
|
||||||
|
Moves.KINGS_SHIELD,
|
||||||
|
Moves.CRAFTY_SHIELD,
|
||||||
|
Moves.SPIKY_SHIELD,
|
||||||
|
Moves.OBSTRUCT,
|
||||||
|
Moves.DETECT
|
||||||
|
];
|
@ -6,5 +6,6 @@ export enum MysteryEncounterType {
|
|||||||
SLEEPING_SNORLAX,
|
SLEEPING_SNORLAX,
|
||||||
TRAINING_SESSION,
|
TRAINING_SESSION,
|
||||||
DEPARTMENT_STORE_SALE,
|
DEPARTMENT_STORE_SALE,
|
||||||
SHADY_VITAMIN_DEALER
|
SHADY_VITAMIN_DEALER,
|
||||||
|
FIELD_TRIP
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"unit_test_dialogue": "@ec{test}@ec{test} @ec{test@ec{test}} @ec{test1} @ec{test\} @ec{test\\} @ec{test\\\} {test}",
|
"unit_test_dialogue": "@ec{test}@ec{test} @ec{test@ec{test}} @ec{test1} @ec{test\} @ec{test\\} @ec{test\\\} {test}",
|
||||||
|
|
||||||
// Mystery Encounters -- Common Tier
|
// Mystery Encounters -- Common Tier
|
||||||
|
|
||||||
"mysterious_chest_intro_message": "You found...@d{32} a chest?",
|
"mysterious_chest_intro_message": "You found...@d{32} a chest?",
|
||||||
"mysterious_chest_title": "The Mysterious Chest",
|
"mysterious_chest_title": "The Mysterious Chest",
|
||||||
"mysterious_chest_description": "A beautifully ornamented chest stands on the ground. There must be something good inside... right?",
|
"mysterious_chest_description": "A beautifully ornamented chest stands on the ground. There must be something good inside... right?",
|
||||||
@ -42,14 +43,14 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"fight_or_flight_option_1_tooltip": "(-) Hard Battle\n(+) New Item",
|
"fight_or_flight_option_1_tooltip": "(-) Hard Battle\n(+) New Item",
|
||||||
"fight_or_flight_option_2_label": "Steal the item",
|
"fight_or_flight_option_2_label": "Steal the item",
|
||||||
"fight_or_flight_option_2_tooltip": "@[SUMMARY_GREEN]{(35%) Steal Item}\n@[SUMMARY_BLUE]{(65%) Harder Battle}",
|
"fight_or_flight_option_2_tooltip": "@[SUMMARY_GREEN]{(35%) Steal Item}\n@[SUMMARY_BLUE]{(65%) Harder Battle}",
|
||||||
"fight_or_flight_option_2_steal_tooltip": "@[SUMMARY_GREEN]{(?) Use a Pokémon Move}",
|
"fight_or_flight_option_2_steal_tooltip": "(+) @ec{option2PrimaryName} uses @ec{option2PrimaryMove}",
|
||||||
"fight_or_flight_option_3_label": "Leave",
|
"fight_or_flight_option_3_label": "Leave",
|
||||||
"fight_or_flight_option_3_tooltip": "(-) No Rewards",
|
"fight_or_flight_option_3_tooltip": "(-) No Rewards",
|
||||||
"fight_or_flight_option_1_selected_message": "You approach the\nPokémon without fear.",
|
"fight_or_flight_option_1_selected_message": "You approach the\nPokémon without fear.",
|
||||||
"fight_or_flight_option_2_good_result": `.@d{32}.@d{32}.@d{32}
|
"fight_or_flight_option_2_good_result": `.@d{32}.@d{32}.@d{32}
|
||||||
$You manage to sneak your way\npast and grab the item!`,
|
$You manage to sneak your way\npast and grab the item!`,
|
||||||
"fight_or_flight_option_2_steal_result": `.@d{32}.@d{32}.@d{32}
|
"fight_or_flight_option_2_steal_result": `.@d{32}.@d{32}.@d{32}
|
||||||
$Your @ec{thiefPokemon} helps you out and uses @ec{move}!
|
$Your @ec{option2PrimaryName} helps you out and uses @ec{option2PrimaryMove}!
|
||||||
$ You nabbed the item!`,
|
$ You nabbed the item!`,
|
||||||
"fight_or_flight_option_2_bad_result": `.@d{32}.@d{32}.@d{32}
|
"fight_or_flight_option_2_bad_result": `.@d{32}.@d{32}.@d{32}
|
||||||
$The Pokémon catches you\nas you try to sneak around!`,
|
$The Pokémon catches you\nas you try to sneak around!`,
|
||||||
@ -82,6 +83,7 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"shady_vitamin_dealer_title": "The Vitamin Dealer",
|
"shady_vitamin_dealer_title": "The Vitamin Dealer",
|
||||||
"shady_vitamin_dealer_description": "The man opens his jacket to reveal some Pokémon vitamins. The numbers he quotes seem like a really good deal. Almost too good...\nHe offers two package deals to choose from.",
|
"shady_vitamin_dealer_description": "The man opens his jacket to reveal some Pokémon vitamins. The numbers he quotes seem like a really good deal. Almost too good...\nHe offers two package deals to choose from.",
|
||||||
"shady_vitamin_dealer_query": "Which deal will choose?",
|
"shady_vitamin_dealer_query": "Which deal will choose?",
|
||||||
|
"shady_vitamin_dealer_invalid_selection": "Pokémon must be healthy enough.",
|
||||||
"shady_vitamin_dealer_option_1_label": "The Cheap Deal",
|
"shady_vitamin_dealer_option_1_label": "The Cheap Deal",
|
||||||
"shady_vitamin_dealer_option_1_tooltip": "(-) Pay @ec{option1Money}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
|
"shady_vitamin_dealer_option_1_tooltip": "(-) Pay @ec{option1Money}\n(-) Side Effects?\n(+) Chosen Pokémon Gains 2 Random Vitamins",
|
||||||
"shady_vitamin_dealer_option_2_label": "The Pricey Deal",
|
"shady_vitamin_dealer_option_2_label": "The Pricey Deal",
|
||||||
@ -94,9 +96,33 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
$Your @ec{selectedPokemon} takes some damage\nand becomes badly poisoned...`,
|
$Your @ec{selectedPokemon} takes some damage\nand becomes badly poisoned...`,
|
||||||
"shady_vitamin_dealer_poison": `But the medicine had some side effects!
|
"shady_vitamin_dealer_poison": `But the medicine had some side effects!
|
||||||
$Your @ec{selectedPokemon} becomes poisoned...`,
|
$Your @ec{selectedPokemon} becomes poisoned...`,
|
||||||
|
"shady_vitamin_dealer_no_bad_effects": "Looks like there were no side-effects this time.",
|
||||||
"shady_vitamin_dealer_option_3_label": "Leave",
|
"shady_vitamin_dealer_option_3_label": "Leave",
|
||||||
"shady_vitamin_dealer_option_3_tooltip": "(-) No Rewards",
|
"shady_vitamin_dealer_option_3_tooltip": "(-) No Rewards",
|
||||||
"shady_vitamin_dealer_outro_good": "Looks like there were no side-effects this time.",
|
|
||||||
|
"field_trip_intro_message": "It's a teacher and some school children!",
|
||||||
|
"field_trip_speaker": "Teacher",
|
||||||
|
"field_trip_intro_dialogue": `Hello, there! Would you be able to\nspare a minute for my students?
|
||||||
|
$I'm teaching them about Pokémon moves\nand would love to show them a demonstration.
|
||||||
|
$Would you mind showing us one of\nthe moves your Pokémon can use?`,
|
||||||
|
"field_trip_title": "Field Trip",
|
||||||
|
"field_trip_description": "A teacher is requesting a move demonstration from a Pokémon. Depending on the move you choose, she might have something useful for you in exchange.",
|
||||||
|
"field_trip_query": "Which move category will you show off?",
|
||||||
|
"field_trip_option_1_label": "A Physical Move",
|
||||||
|
"field_trip_option_1_tooltip": "(+) Physical Item Rewards",
|
||||||
|
"field_trip_option_2_label": "A Special Move",
|
||||||
|
"field_trip_option_2_tooltip": "(+) Special Item Rewards",
|
||||||
|
"field_trip_option_3_label": "A Status Move",
|
||||||
|
"field_trip_option_3_tooltip": "(+) Status Item Rewards",
|
||||||
|
"field_trip_second_option_prompt": "Choose a move for your Pokémon to use.",
|
||||||
|
"field_trip_option_selected": "@ec{pokeName} shows off an awesome display of @ec{move}!",
|
||||||
|
"field_trip_option_incorrect": `...
|
||||||
|
$That isn't a @ec{moveCategory} move!
|
||||||
|
$I'm sorry, but I can't give you anything.`,
|
||||||
|
"field_trip_lesson_learned": `Looks like you learned a valuable lesson?
|
||||||
|
$Your Pokémon also gained some knowledge.`,
|
||||||
|
"field_trip_outro_good": "Thank you so much for your kindness!\nI hope the items I had were helpful!",
|
||||||
|
"field_trip_outro_bad": "Come along children, we'll\nfind a better demonstration elsewhere.",
|
||||||
|
|
||||||
// Mystery Encounters -- Uncommon Tier
|
// Mystery Encounters -- Uncommon Tier
|
||||||
|
|
||||||
@ -114,6 +140,7 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"mysterious_challengers_outro_win": "The mysterious challenger was defeated!",
|
"mysterious_challengers_outro_win": "The mysterious challenger was defeated!",
|
||||||
|
|
||||||
// Mystery Encounters -- Rare Tier
|
// Mystery Encounters -- Rare Tier
|
||||||
|
|
||||||
"training_session_intro_message": "You've come across some\ntraining tools and supplies.",
|
"training_session_intro_message": "You've come across some\ntraining tools and supplies.",
|
||||||
"training_session_title": "Training Session",
|
"training_session_title": "Training Session",
|
||||||
"training_session_description": "These supplies look like they could be used to train a member of your party! There are a few ways you could train your Pokémon, by battling against it with the rest of your team.",
|
"training_session_description": "These supplies look like they could be used to train a member of your party! There are a few ways you could train your Pokémon, by battling against it with the rest of your team.",
|
||||||
@ -146,8 +173,8 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"dark_deal_title": "Dark Deal",
|
"dark_deal_title": "Dark Deal",
|
||||||
"dark_deal_description": "The disturbing fellow holds up some Pokéballs.\n\"I'll make it worth your while! You can have these strong Pokéballs as payment, All I need is a Pokémon from your team! Hehe...\"",
|
"dark_deal_description": "The disturbing fellow holds up some Pokéballs.\n\"I'll make it worth your while! You can have these strong Pokéballs as payment, All I need is a Pokémon from your team! Hehe...\"",
|
||||||
"dark_deal_query": "What will you do?",
|
"dark_deal_query": "What will you do?",
|
||||||
"dark_deal_option_1_label": "Accept", // Give player 10 rogue balls. Remove a random Pokémon from player's party. Fight a legendary Pokémon as a boss
|
"dark_deal_option_1_label": "Accept",
|
||||||
"dark_deal_option_1_tooltip": "(+) 5 Rogue Balls\n(?) Enhance a Random Pokémon", // Give player 10 rogue balls. Remove a random Pokémon from player's party. Fight a legendary Pokémon as a boss
|
"dark_deal_option_1_tooltip": "(+) 5 Rogue Balls\n(?) Enhance a Random Pokémon",
|
||||||
"dark_deal_option_2_label": "Refuse",
|
"dark_deal_option_2_label": "Refuse",
|
||||||
"dark_deal_option_2_tooltip": "(-) No Rewards",
|
"dark_deal_option_2_tooltip": "(-) No Rewards",
|
||||||
"dark_deal_option_1_selected": `Let's see, that @ec{pokeName} will do nicely!
|
"dark_deal_option_1_selected": `Let's see, that @ec{pokeName} will do nicely!
|
||||||
@ -162,14 +189,14 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
"sleeping_snorlax_intro_message": `As you walk down a narrow pathway, you see a towering silhouette blocking your path.
|
"sleeping_snorlax_intro_message": `As you walk down a narrow pathway, you see a towering silhouette blocking your path.
|
||||||
$You get closer to see a Snorlax sleeping peacefully.\nIt seems like there's no way around it.`,
|
$You get closer to see a Snorlax sleeping peacefully.\nIt seems like there's no way around it.`,
|
||||||
"sleeping_snorlax_title": "Sleeping Snorlax",
|
"sleeping_snorlax_title": "Sleeping Snorlax",
|
||||||
"sleeping_snorlax_description": "You could attack it to try and get it to move, or simply wait for it to wake up.",
|
"sleeping_snorlax_description": "You could attack it to try and get it to move, or simply wait for it to wake up. Who knows how long that could take, though...",
|
||||||
"sleeping_snorlax_query": "What will you do?",
|
"sleeping_snorlax_query": "What will you do?",
|
||||||
"sleeping_snorlax_option_1_label": "Fight it",
|
"sleeping_snorlax_option_1_label": "Fight it",
|
||||||
"sleeping_snorlax_option_1_tooltip": "(-) Fight Sleeping Snorlax",
|
"sleeping_snorlax_option_1_tooltip": "(-) Fight Sleeping Snorlax",
|
||||||
"sleeping_snorlax_option_2_label": "Wait for it to move",
|
"sleeping_snorlax_option_2_label": "Wait for it to move",
|
||||||
"sleeping_snorlax_option_2_tooltip": "@[SUMMARY_BLUE]{(75%) Wait a short time}\n@[SUMMARY_BLUE]{(25%) Wait a long time}",
|
"sleeping_snorlax_option_2_tooltip": "@[SUMMARY_BLUE]{(75%) Wait a short time}\n@[SUMMARY_BLUE]{(25%) Wait a long time}",
|
||||||
"sleeping_snorlax_option_3_label": "Steal",
|
"sleeping_snorlax_option_3_label": "Steal its item",
|
||||||
"sleeping_snorlax_option_3_tooltip": "(+) Leftovers",
|
"sleeping_snorlax_option_3_tooltip": "(+) @ec{option3PrimaryName} uses @ec{option3PrimaryMove}\n(+) Leftovers",
|
||||||
"sleeping_snorlax_option_3_disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
|
"sleeping_snorlax_option_3_disabled_tooltip": "Your Pokémon need to know certain moves to choose this",
|
||||||
"sleeping_snorlax_option_1_selected_message": "You approach the\nPokémon without fear.",
|
"sleeping_snorlax_option_1_selected_message": "You approach the\nPokémon without fear.",
|
||||||
"sleeping_snorlax_option_2_selected_message": `.@d{32}.@d{32}.@d{32}
|
"sleeping_snorlax_option_2_selected_message": `.@d{32}.@d{32}.@d{32}
|
||||||
@ -179,6 +206,5 @@ export const mysteryEncounter: SimpleTranslationEntries = {
|
|||||||
$But on the bright side, the Snorlax left something behind...
|
$But on the bright side, the Snorlax left something behind...
|
||||||
$@s{item_fanfare}You gained a Berry!`,
|
$@s{item_fanfare}You gained a Berry!`,
|
||||||
"sleeping_snorlax_option_3_good_result": "Your @ec{option3PrimaryName} uses @ec{option3PrimaryMove}! @s{item_fanfare}It steals Leftovers off the sleeping Snorlax and you make out like bandits!",
|
"sleeping_snorlax_option_3_good_result": "Your @ec{option3PrimaryName} uses @ec{option3PrimaryMove}! @s{item_fanfare}It steals Leftovers off the sleeping Snorlax and you make out like bandits!",
|
||||||
// "sleeping_snorlax_outro_win": "The mysterious challengers were defeated!",
|
|
||||||
|
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -8,18 +8,17 @@ import { PokeballCounts } from "./battle-scene";
|
|||||||
import { PokeballType } from "./data/pokeball";
|
import { PokeballType } from "./data/pokeball";
|
||||||
import { Gender } from "./data/gender";
|
import { Gender } from "./data/gender";
|
||||||
import { StatusEffect } from "./data/status-effect";
|
import { StatusEffect } from "./data/status-effect";
|
||||||
import { SpeciesStatBoosterItem, modifierTypes } from "./modifier/modifier-type";
|
import { modifierTypes, SpeciesStatBoosterItem } from "./modifier/modifier-type";
|
||||||
import { VariantTier } from "./enums/variant-tiers";
|
import { VariantTier } from "./enums/variant-tiers";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { allSpecies } from "./data/pokemon-species"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { Biome } from "#enums/biome";
|
import { Biome } from "#enums/biome";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TimeOfDay } from "#enums/time-of-day";
|
import { TimeOfDay } from "#enums/time-of-day";
|
||||||
import {MysteryEncounterType} from "#enums/mystery-encounter-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
import {MysteryEncounterTier} from "#app/data/mystery-encounters/mystery-encounter"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides for testing different in game situations
|
* Overrides for testing different in game situations
|
||||||
|
@ -5363,6 +5363,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||||||
this.scene.ui.revertMode();
|
this.scene.ui.revertMode();
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
super.end();
|
super.end();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
modifierType = typeOptions[cursor].type;
|
modifierType = typeOptions[cursor].type;
|
||||||
break;
|
break;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import BattleScene from "../battle-scene";
|
import BattleScene from "../battle-scene";
|
||||||
import {addBBCodeTextObject, getBBCodeFrag, TextStyle} from "./text";
|
import { addBBCodeTextObject, getBBCodeFrag, TextStyle } from "./text";
|
||||||
import {Mode} from "./ui";
|
import { Mode } from "./ui";
|
||||||
import UiHandler from "./ui-handler";
|
import UiHandler from "./ui-handler";
|
||||||
import {Button} from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import {addWindow, WindowVariant} from "./ui-theme";
|
import { addWindow, WindowVariant } from "./ui-theme";
|
||||||
import {MysteryEncounterPhase} from "../phases/mystery-encounter-phase";
|
import { MysteryEncounterPhase } from "../phases/mystery-encounter-phase";
|
||||||
import {PartyUiMode} from "./party-ui-handler";
|
import { PartyUiMode } from "./party-ui-handler";
|
||||||
import MysteryEncounterOption from "../data/mystery-encounters/mystery-encounter-option";
|
import MysteryEncounterOption from "../data/mystery-encounters/mystery-encounter-option";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import {isNullOrUndefined} from "../utils";
|
import { isNullOrUndefined } from "../utils";
|
||||||
import {getPokeballAtlasKey} from "../data/pokeball";
|
import { getPokeballAtlasKey } from "../data/pokeball";
|
||||||
import {getEncounterText} from "#app/data/mystery-encounters/mystery-encounter-utils";
|
import { getEncounterText } from "#app/data/mystery-encounters/mystery-encounter-utils";
|
||||||
|
|
||||||
export default class MysteryEncounterUiHandler extends UiHandler {
|
export default class MysteryEncounterUiHandler extends UiHandler {
|
||||||
private cursorContainer: Phaser.GameObjects.Container;
|
private cursorContainer: Phaser.GameObjects.Container;
|
||||||
@ -110,7 +110,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
this.unblockInput();
|
this.unblockInput();
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
} else if (this.blockInput || !this.optionsMeetsReqs[cursor]) {
|
} else if (this.blockInput || (!this.optionsMeetsReqs[cursor] && this.filteredEncounterOptions[cursor].isDisabledOnRequirementsNotMet)) {
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
const selected = this.filteredEncounterOptions[cursor];
|
const selected = this.filteredEncounterOptions[cursor];
|
||||||
@ -253,7 +253,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
if (this.blockInput) {
|
if (this.blockInput) {
|
||||||
this.blockInput = false;
|
this.blockInput = false;
|
||||||
for (let i = 0; i < this.optionsContainer.length - 1; i++) {
|
for (let i = 0; i < this.optionsContainer.length - 1; i++) {
|
||||||
if (!this.optionsMeetsReqs[i]) {
|
if (!this.optionsMeetsReqs[i] && this.filteredEncounterOptions[i].isDisabledOnRequirementsNotMet) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(this.optionsContainer.getAt(i) as Phaser.GameObjects.Text).setAlpha(1);
|
(this.optionsContainer.getAt(i) as Phaser.GameObjects.Text).setAlpha(1);
|
||||||
@ -319,15 +319,23 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { wordWrap: { width: 558 }, fontSize: "80px", lineSpacing: -8 });
|
optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { wordWrap: { width: 558 }, fontSize: "80px", lineSpacing: -8 });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const option = mysteryEncounter.dialogue.encounterOptionsDialogue.options[i];
|
this.optionsMeetsReqs.push(this.filteredEncounterOptions[i].meetsRequirements(this.scene));
|
||||||
const text = getEncounterText(this.scene, option.buttonLabel, option.style ? option.style : TextStyle.WINDOW);
|
|
||||||
|
const optionDialogue = mysteryEncounter.dialogue.encounterOptionsDialogue.options[i];
|
||||||
|
let text;
|
||||||
|
if (this.filteredEncounterOptions[i].hasRequirements() && this.optionsMeetsReqs[i]) {
|
||||||
|
// Options with special requirements that are met are automatically colored green
|
||||||
|
// In cases where isDisabledOnRequirementsNotMet = false and requirements are not met, option will not be auto-colored
|
||||||
|
text = getEncounterText(this.scene, optionDialogue.buttonLabel, TextStyle.SUMMARY_GREEN);
|
||||||
|
} else {
|
||||||
|
text = getEncounterText(this.scene, optionDialogue.buttonLabel, optionDialogue.style ? optionDialogue.style : TextStyle.WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
optionText.setText(text);
|
optionText.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.optionsMeetsReqs.push(this.filteredEncounterOptions[i].meetsRequirements(this.scene));
|
if (!this.optionsMeetsReqs[i] && this.filteredEncounterOptions[i].isDisabledOnRequirementsNotMet) {
|
||||||
|
|
||||||
if (!this.optionsMeetsReqs[i]) {
|
|
||||||
optionText.setAlpha(0.5);
|
optionText.setAlpha(0.5);
|
||||||
}
|
}
|
||||||
if (this.blockInput) {
|
if (this.blockInput) {
|
||||||
@ -415,7 +423,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
|
|||||||
const mysteryEncounter = this.scene.currentBattle.mysteryEncounter;
|
const mysteryEncounter = this.scene.currentBattle.mysteryEncounter;
|
||||||
let text;
|
let text;
|
||||||
const option = mysteryEncounter.dialogue.encounterOptionsDialogue.options[cursor];
|
const option = mysteryEncounter.dialogue.encounterOptionsDialogue.options[cursor];
|
||||||
if (!this.optionsMeetsReqs[cursor] && option.disabledTooltip) {
|
if (!this.optionsMeetsReqs[cursor] && this.filteredEncounterOptions[cursor].isDisabledOnRequirementsNotMet && option.disabledTooltip) {
|
||||||
text = getEncounterText(this.scene, option.disabledTooltip, TextStyle.TOOLTIP_CONTENT);
|
text = getEncounterText(this.scene, option.disabledTooltip, TextStyle.TOOLTIP_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
text = getEncounterText(this.scene, option.buttonTooltip, TextStyle.TOOLTIP_CONTENT);
|
text = getEncounterText(this.scene, option.buttonTooltip, TextStyle.TOOLTIP_CONTENT);
|
||||||
|
Loading…
Reference in New Issue
Block a user