Merge branch 'mystery-battle-events' into event/getting-lost-at-the-sea

This commit is contained in:
Felix Staud 2024-07-16 21:40:48 -07:00
commit 7653cffb5f
4 changed files with 80 additions and 22 deletions

View File

@ -9,7 +9,7 @@ body:
attributes: attributes:
label: Event Name label: Event Name
description: Name of the event description: Name of the event
placeholder: e.g Fight or Flight placeholder: e.g. "Fight or Flight"
validations: validations:
required: true required: true
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
@ -20,15 +20,24 @@ body:
id: rarity id: rarity
attributes: attributes:
label: Rarity Tier label: Rarity Tier
description: Check out the [Event Proposal Guide](https://github.com/AsdarDevelops/PokeRogue-Events/blob/mystery-battle-events/MEs_Proposal_Guide.md) if you have not yet!
multiple: false multiple: false
options: options:
- Common - Common
- Great - Great
- Ultra - Ultra
- Rogue - Rogue
- Part of a "Quest"
- Other or unsure (please specify) - Other or unsure (please specify)
- type: input
id: rarity-other
attributes:
label: Rarity Tier - Other. Please Specify
description: If you chose `Other` on the `Rarity Tier` please specify it here
placeholder: e.g. "I'm unsure of whether this should be Common or Great"
validations: validations:
required: true required: false
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
attributes: attributes:
value: | value: |
@ -37,8 +46,8 @@ body:
id: waves id: waves
attributes: attributes:
label: Waves label: Waves
description: Classic/Challenge is 1 -200. Currently only 11-179 is supported. description: Classic/Challenge ranges 1-200. Currently only 11-179 is supported.
placeholder: 1-200 placeholder: 11-179
validations: validations:
required: true required: true
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
@ -49,8 +58,8 @@ body:
id: description id: description
attributes: attributes:
label: Description label: Description
description: Describe the event you are proposing description: Describe the event you are proposing. Explain its theme and how it's different from others. If the Event has any requirements to even trigger, detail them here too.
placeholder: What is it? placeholder: e.g. "Fight or Flight is a common event where the player can fight a boss PKMN of the biome. The PKMN is stronger than usual, but also holds an item that's better than usual."
validations: validations:
required: true required: true
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
@ -61,11 +70,13 @@ body:
id: biomes id: biomes
attributes: attributes:
label: Biomes label: Biomes
description: Select all biomes where the event can occur description: Select all biomes where the event can occur. "ANY, NON-EXTREME, CIVILIZATION and HUMAN are groups of biomes. Check the [Biomes part of the guide](https://github.com/AsdarDevelops/PokeRogue-Events/blob/mystery-battle-events/MEs_Proposal_Guide.md#biomes)."
multiple: true multiple: true
options: options:
- ANY (no need to select all) - ANY
- NON-EXTREME (almost all except Space, Seabed, etc...) - NON-EXTREME
- HUMAN
- CIVILIZATION
- TOWN - TOWN
- PLAINS - PLAINS
- GRASS - GRASS
@ -104,6 +115,15 @@ body:
- OTHER (please specify) - OTHER (please specify)
validations: validations:
required: true required: true
- type: input
id: biome-other
attributes:
label: Biome - Other. Please Specify
description: If you chose `Other` on the `Biome` please specify it here
placeholder: e.g. "I would like to only trigger at Graveyard at night!"
validations:
required: false
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
attributes: attributes:
value: | value: |
@ -134,13 +154,25 @@ body:
attributes: attributes:
label: Explanation/Notes on Design label: Explanation/Notes on Design
description: Explain why you think this design is right and what this Event brings to the table description: Explain why you think this design is right and what this Event brings to the table
placeholder: Explain why you think this design is right and what this Event brings to the table placeholder: e.g. "We need more simple Events that mix slightly higher stakes with slightly better rewards"
validations: validations:
required: true required: true
- type: markdown # SEPARATOR - type: markdown # SEPARATOR
attributes: attributes:
value: | value: |
--- ---
- type: textarea
id: artist-notes
attributes:
label: Notes to Artists
description: Does your Event need custom spriting? If so, please detail them here (reference screenshots are helpful)
placeholder: Ie. "We currently don't have a Cynthia sprite while dressed in a Garchomp costume. RAWR! This is highly needed for my Event!"
validations:
required: false
- type: markdown # SEPARATOR
attributes:
value: |
---
- type: textarea - type: textarea
id: dev-notes id: dev-notes
attributes: attributes:

View File

@ -1071,13 +1071,14 @@ export default class BattleScene extends SceneBase {
this.field.add(newTrainer); this.field.add(newTrainer);
} }
// Check for mystery encounter // TODO: remove this once spawn rates are finalized
// Can only occur in place of a standard wild battle, waves 10-180
// let testStartingWeight = 0; // let testStartingWeight = 0;
// while (testStartingWeight < 20) { // while (testStartingWeight < 3) {
// calculateMEAggregateStats(this, testStartingWeight); // calculateMEAggregateStats(this, testStartingWeight);
// testStartingWeight += 1; // testStartingWeight += 1;
// } // }
// Check for mystery encounter
// Can only occur in place of a standard wild battle, waves 10-180
if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < 180 && newWaveIndex > 10) { if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(newWaveIndex) && newWaveIndex < 180 && newWaveIndex > 10) {
const roll = Utils.randSeedInt(256); const roll = Utils.randSeedInt(256);
@ -2651,7 +2652,7 @@ export default class BattleScene extends SceneBase {
} }
// Common / Uncommon / Rare / Super Rare // Common / Uncommon / Rare / Super Rare
const tierWeights = [61, 40, 21, 6]; const tierWeights = [64, 40, 21, 3];
// Adjust tier weights by previously encountered events to lower odds of only common/uncommons in run // Adjust tier weights by previously encountered events to lower odds of only common/uncommons in run
this.mysteryEncounterData.encounteredEvents.forEach(val => { this.mysteryEncounterData.encounteredEvents.forEach(val => {
@ -2681,10 +2682,23 @@ export default class BattleScene extends SceneBase {
// If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available // If no valid encounters exist at tier, checks next tier down, continuing until there are some encounters available
while (availableEncounters.length === 0 && tier >= 0) { while (availableEncounters.length === 0 && tier >= 0) {
availableEncounters = biomeMysteryEncounters availableEncounters = biomeMysteryEncounters
.filter((encounterType) => .filter((encounterType) => {
allMysteryEncounters[encounterType]?.meetsRequirements(this) && if (allMysteryEncounters[encounterType].encounterTier !== tier) { // Encounter is in tier
allMysteryEncounters[encounterType].encounterTier === tier && return false;
(isNullOrUndefined(previousEncounter) || encounterType !== previousEncounter)) }
if (!allMysteryEncounters[encounterType]?.meetsRequirements(this)) { // Meets encounter requirements
return false;
}
if (!isNullOrUndefined(previousEncounter) && encounterType === previousEncounter) { // Previous encounter was not this one
return false;
}
if (this.mysteryEncounterData.encounteredEvents?.length > 0 && // Encounter has not exceeded max allowed encounters
allMysteryEncounters[encounterType].maxAllowedEncounters > 0
&& this.mysteryEncounterData.encounteredEvents.filter(e => e[0] === encounterType).length >= allMysteryEncounters[encounterType].maxAllowedEncounters) {
return false;
}
return true;
})
.map((m) => (allMysteryEncounters[m])); .map((m) => (allMysteryEncounters[m]));
tier--; tier--;
} }

View File

@ -50,6 +50,7 @@ export default interface IMysteryEncounter {
hideBattleIntroMessage?: boolean; hideBattleIntroMessage?: boolean;
hideIntroVisuals?: boolean; hideIntroVisuals?: boolean;
catchAllowed?: boolean; catchAllowed?: boolean;
maxAllowedEncounters?: number;
doEncounterExp?: (scene: BattleScene) => boolean; doEncounterExp?: (scene: BattleScene) => boolean;
doEncounterRewards?: (scene: BattleScene) => boolean; doEncounterRewards?: (scene: BattleScene) => boolean;
onInit?: (scene: BattleScene) => boolean; onInit?: (scene: BattleScene) => boolean;
@ -144,6 +145,8 @@ export default class IMysteryEncounter implements IMysteryEncounter {
} }
this.encounterTier = this.encounterTier ? this.encounterTier : MysteryEncounterTier.COMMON; this.encounterTier = this.encounterTier ? this.encounterTier : MysteryEncounterTier.COMMON;
this.dialogue = this.dialogue ?? {}; this.dialogue = this.dialogue ?? {};
// Default max is 1 for ROGUE encounters, 3 for others
this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? 1 : 3;
this.encounterVariant = MysteryEncounterVariant.DEFAULT; this.encounterVariant = MysteryEncounterVariant.DEFAULT;
this.requirements = this.requirements ? this.requirements : []; this.requirements = this.requirements ? this.requirements : [];
this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false; this.hideBattleIntroMessage = !isNullOrUndefined(this.hideBattleIntroMessage) ? this.hideBattleIntroMessage : false;
@ -440,9 +443,9 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
* If not specified, defaults to COMMON * If not specified, defaults to COMMON
* Tiers are: * Tiers are:
* COMMON 32/64 odds * COMMON 32/64 odds
* UNCOMMON 16/64 odds * GREAT 16/64 odds
* RARE 10/64 odds * ULTRA 10/64 odds
* SUPER_RARE 6/64 odds * ROGUE 6/64 odds
* ULTRA_RARE Not currently used * ULTRA_RARE Not currently used
* @param encounterTier * @param encounterTier
* @returns * @returns
@ -451,6 +454,15 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
return Object.assign(this, { encounterTier: encounterTier }); return Object.assign(this, { encounterTier: encounterTier });
} }
/**
* Sets the maximum number of times that an encounter can spawn in a given Classic run
* @param maxAllowedEncounters
* @returns
*/
withMaxAllowedEncounters(maxAllowedEncounters: number): this & Required<Pick<IMysteryEncounter, "maxAllowedEncounters">> {
return Object.assign(this, { maxAllowedEncounters: maxAllowedEncounters });
}
/** /**
* Specifies a requirement for an encounter * Specifies a requirement for an encounter
* For example, passing requirement as "new WaveCountRequirement([2, 180])" would create a requirement that the encounter can only be spawned between waves 2 and 180 * For example, passing requirement as "new WaveCountRequirement([2, 180])" would create a requirement that the encounter can only be spawned between waves 2 and 180

View File

@ -634,7 +634,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
// Calculate encounter rarity // Calculate encounter rarity
// Common / Uncommon / Rare / Super Rare (base is out of 128) // Common / Uncommon / Rare / Super Rare (base is out of 128)
const tierWeights = [61, 40, 21, 6]; const tierWeights = [64, 40, 21, 3];
// Adjust tier weights by currently encountered events (pity system that lowers odds of multiple common/uncommons) // Adjust tier weights by currently encountered events (pity system that lowers odds of multiple common/uncommons)
tierWeights[0] = tierWeights[0] - 6 * numEncounters[0]; tierWeights[0] = tierWeights[0] - 6 * numEncounters[0];