Merge branch 'mystery-battle-events' into event/getting-lost-at-the-sea
This commit is contained in:
commit
7653cffb5f
|
@ -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:
|
||||||
|
|
|
@ -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--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Reference in New Issue