mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-21 14:59:26 +02:00
[ME] update CombinationRequirements to allow AND or OR combinations
* refactor: CombinationPokemonRequirement `.Some()` and `Every()` * chore: rename `orRequirements` to `requirements` * fix: returns of `Some()` and `Any()` * apply `Some()` / `Any()` pattern to `CombinationSceneRequirement` too
This commit is contained in:
parent
96d8a2127a
commit
a3fb7bc829
@ -135,9 +135,11 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
|||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
.withPrimaryPokemonRequirement(
|
||||||
new MoveRequirement(EXTORTION_MOVES, true),
|
CombinationPokemonRequirement.Some(
|
||||||
new AbilityRequirement(EXTORTION_ABILITIES, true))
|
new MoveRequirement(EXTORTION_MOVES, true),
|
||||||
|
new AbilityRequirement(EXTORTION_ABILITIES, true)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.2.label`,
|
buttonLabel: `${namespace}:option.2.label`,
|
||||||
|
@ -193,12 +193,14 @@ const WAVE_LEVEL_BREAKPOINTS = [ 30, 50, 70, 100, 120, 140, 160 ];
|
|||||||
export const BugTypeSuperfanEncounter: MysteryEncounter =
|
export const BugTypeSuperfanEncounter: MysteryEncounter =
|
||||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.BUG_TYPE_SUPERFAN)
|
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.BUG_TYPE_SUPERFAN)
|
||||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
.withPrimaryPokemonRequirement(
|
||||||
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
|
CombinationPokemonRequirement.Some(
|
||||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
// Must have at least 1 Bug type on team, OR have a bug item somewhere on the team
|
||||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||||
new TypeRequirement(Type.BUG, false, 1)
|
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1),
|
||||||
))
|
new TypeRequirement(Type.BUG, false, 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
.withMaxAllowedEncounters(1)
|
.withMaxAllowedEncounters(1)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withIntroSpriteConfigs([]) // These are set in onInit()
|
.withIntroSpriteConfigs([]) // These are set in onInit()
|
||||||
@ -405,11 +407,13 @@ export const BugTypeSuperfanEncounter: MysteryEncounter =
|
|||||||
.build())
|
.build())
|
||||||
.withOption(MysteryEncounterOptionBuilder
|
.withOption(MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
.withPrimaryPokemonRequirement(
|
||||||
// Meets one or both of the below reqs
|
CombinationPokemonRequirement.Some(
|
||||||
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
// Meets one or both of the below reqs
|
||||||
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
|
new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1),
|
||||||
))
|
new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
@ -45,10 +45,13 @@ export const DelibirdyEncounter: MysteryEncounter =
|
|||||||
.withEncounterTier(MysteryEncounterTier.GREAT)
|
.withEncounterTier(MysteryEncounterTier.GREAT)
|
||||||
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
.withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES)
|
||||||
.withSceneRequirement(new MoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER)) // Must have enough money for it to spawn at the very least
|
.withSceneRequirement(new MoneyRequirement(0, DELIBIRDY_MONEY_PRICE_MULTIPLIER)) // Must have enough money for it to spawn at the very least
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must also have either option 2 or 3 available to spawn
|
.withPrimaryPokemonRequirement(
|
||||||
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
CombinationPokemonRequirement.Some(
|
||||||
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
// Must also have either option 2 or 3 available to spawn
|
||||||
))
|
new HeldItemRequirement(OPTION_2_ALLOWED_MODIFIERS),
|
||||||
|
new HeldItemRequirement(OPTION_3_DISALLOWED_MODIFIERS, 1, true)
|
||||||
|
)
|
||||||
|
)
|
||||||
.withIntroSpriteConfigs([
|
.withIntroSpriteConfigs([
|
||||||
{
|
{
|
||||||
spriteKey: "",
|
spriteKey: "",
|
||||||
|
@ -215,10 +215,12 @@ export const FieryFalloutEncounter: MysteryEncounter =
|
|||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder
|
MysteryEncounterOptionBuilder
|
||||||
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||||
.withPrimaryPokemonRequirement(new CombinationPokemonRequirement(
|
.withPrimaryPokemonRequirement(
|
||||||
new TypeRequirement(Type.FIRE, true, 1),
|
CombinationPokemonRequirement.Some(
|
||||||
new AbilityRequirement(FIRE_RESISTANT_ABILITIES, true)
|
new TypeRequirement(Type.FIRE, true, 1),
|
||||||
)) // Will set option3PrimaryName dialogue token automatically
|
new AbilityRequirement(FIRE_RESISTANT_ABILITIES, true)
|
||||||
|
)
|
||||||
|
) // Will set option3PrimaryName dialogue token automatically
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.3.label`,
|
buttonLabel: `${namespace}:option.3.label`,
|
||||||
buttonTooltip: `${namespace}:option.3.tooltip`,
|
buttonTooltip: `${namespace}:option.3.tooltip`,
|
||||||
|
@ -37,31 +37,58 @@ export abstract class EncounterSceneRequirement implements EncounterRequirement
|
|||||||
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combination of multiple {@linkcode EncounterSceneRequirement | EncounterSceneRequirements} (OR/AND possible. See {@linkcode isAnd})
|
||||||
|
*/
|
||||||
export class CombinationSceneRequirement extends EncounterSceneRequirement {
|
export class CombinationSceneRequirement extends EncounterSceneRequirement {
|
||||||
orRequirements: EncounterSceneRequirement[];
|
/** If `true`, all requirements must be met (AND). If `false`, any requirement must be met (OR) */
|
||||||
|
private isAnd: boolean;
|
||||||
|
requirements: EncounterSceneRequirement[];
|
||||||
|
|
||||||
constructor(... orRequirements: EncounterSceneRequirement[]) {
|
public static Some(...requirements: EncounterSceneRequirement[]): CombinationSceneRequirement {
|
||||||
|
return new CombinationSceneRequirement(false, ...requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Every(...requirements: EncounterSceneRequirement[]): CombinationSceneRequirement {
|
||||||
|
return new CombinationSceneRequirement(true, ...requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(isAnd: boolean, ...requirements: EncounterSceneRequirement[]) {
|
||||||
super();
|
super();
|
||||||
this.orRequirements = orRequirements;
|
this.isAnd = isAnd;
|
||||||
|
this.requirements = requirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all/any requirements are met (depends on {@linkcode isAnd})
|
||||||
|
* @param scene The {@linkcode BattleScene} to check against
|
||||||
|
* @returns true if all/any requirements are met (depends on {@linkcode isAnd})
|
||||||
|
*/
|
||||||
override meetsRequirement(scene: BattleScene): boolean {
|
override meetsRequirement(scene: BattleScene): boolean {
|
||||||
for (const req of this.orRequirements) {
|
return this.isAnd
|
||||||
if (req.meetsRequirement(scene)) {
|
? this.requirements.every(req => req.meetsRequirement(scene))
|
||||||
return true;
|
: this.requirements.some(req => req.meetsRequirement(scene));
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a dialogue token key/value pair for the given {@linkcode EncounterSceneRequirement | requirements}.
|
||||||
|
* @param scene The {@linkcode BattleScene} to check against
|
||||||
|
* @param pokemon The {@linkcode PlayerPokemon} to check against
|
||||||
|
* @returns A dialogue token key/value pair
|
||||||
|
* @throws An {@linkcode Error} if {@linkcode isAnd} is `true` (not supported)
|
||||||
|
*/
|
||||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
for (const req of this.orRequirements) {
|
if (this.isAnd) {
|
||||||
if (req.meetsRequirement(scene)) {
|
throw new Error("Not implemented (Sorry)");
|
||||||
return req.getDialogueToken(scene, pokemon);
|
} else {
|
||||||
|
for (const req of this.requirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return req.getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return this.orRequirements[0].getDialogueToken(scene, pokemon);
|
return this.requirements[0].getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,44 +117,74 @@ export abstract class EncounterPokemonRequirement implements EncounterRequiremen
|
|||||||
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
abstract getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combination of multiple {@linkcode EncounterPokemonRequirement | EncounterPokemonRequirements} (OR/AND possible. See {@linkcode isAnd})
|
||||||
|
*/
|
||||||
export class CombinationPokemonRequirement extends EncounterPokemonRequirement {
|
export class CombinationPokemonRequirement extends EncounterPokemonRequirement {
|
||||||
orRequirements: EncounterPokemonRequirement[];
|
/** If `true`, all requirements must be met (AND). If `false`, any requirement must be met (OR) */
|
||||||
|
private isAnd: boolean;
|
||||||
|
private requirements: EncounterPokemonRequirement[];
|
||||||
|
|
||||||
constructor(...orRequirements: EncounterPokemonRequirement[]) {
|
public static Some(...requirements: EncounterPokemonRequirement[]): CombinationPokemonRequirement {
|
||||||
|
return new CombinationPokemonRequirement(false, ...requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Every(...requirements: EncounterPokemonRequirement[]): CombinationPokemonRequirement {
|
||||||
|
return new CombinationPokemonRequirement(true, ...requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(isAnd: boolean, ...requirements: EncounterPokemonRequirement[]) {
|
||||||
super();
|
super();
|
||||||
|
this.isAnd = isAnd;
|
||||||
this.invertQuery = false;
|
this.invertQuery = false;
|
||||||
this.minNumberOfPokemon = 1;
|
this.minNumberOfPokemon = 1;
|
||||||
this.orRequirements = orRequirements;
|
this.requirements = requirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all/any requirements are met (depends on {@linkcode isAnd})
|
||||||
|
* @param scene The {@linkcode BattleScene} to check against
|
||||||
|
* @returns true if all/any requirements are met (depends on {@linkcode isAnd})
|
||||||
|
*/
|
||||||
override meetsRequirement(scene: BattleScene): boolean {
|
override meetsRequirement(scene: BattleScene): boolean {
|
||||||
for (const req of this.orRequirements) {
|
return this.isAnd
|
||||||
if (req.meetsRequirement(scene)) {
|
? this.requirements.every(req => req.meetsRequirement(scene))
|
||||||
return true;
|
: this.requirements.some(req => req.meetsRequirement(scene));
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the players party for all party members that are compatible with all/any requirements (depends on {@linkcode isAnd})
|
||||||
|
* @param partyPokemon The party of {@linkcode PlayerPokemon}
|
||||||
|
* @returns All party members that are compatible with all/any requirements (depends on {@linkcode isAnd})
|
||||||
|
*/
|
||||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||||
for (const req of this.orRequirements) {
|
if (this.isAnd) {
|
||||||
const result = req.queryParty(partyPokemon);
|
return this.requirements.reduce((relevantPokemon, req) => req.queryParty(relevantPokemon), partyPokemon);
|
||||||
if (result?.length > 0) {
|
} else {
|
||||||
return result;
|
const matchingRequirement = this.requirements.find(req => req.queryParty(partyPokemon).length > 0);
|
||||||
}
|
return matchingRequirement ? matchingRequirement.queryParty(partyPokemon) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a dialogue token key/value pair for the given {@linkcode EncounterPokemonRequirement | requirements}.
|
||||||
|
* @param scene The {@linkcode BattleScene} to check against
|
||||||
|
* @param pokemon The {@linkcode PlayerPokemon} to check against
|
||||||
|
* @returns A dialogue token key/value pair
|
||||||
|
* @throws An {@linkcode Error} if {@linkcode isAnd} is `true` (not supported)
|
||||||
|
*/
|
||||||
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] {
|
||||||
for (const req of this.orRequirements) {
|
if (this.isAnd) {
|
||||||
if (req.meetsRequirement(scene)) {
|
throw new Error("Not implemented (Sorry)");
|
||||||
return req.getDialogueToken(scene, pokemon);
|
} else {
|
||||||
|
for (const req of this.requirements) {
|
||||||
|
if (req.meetsRequirement(scene)) {
|
||||||
|
return req.getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return this.orRequirements[0].getDialogueToken(scene, pokemon);
|
return this.requirements[0].getDialogueToken(scene, pokemon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user