add shuckle juice modifier
This commit is contained in:
parent
4afcdad3db
commit
f2b3a9ba4c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "berry_juice.png",
|
||||
"image": "pokemon_salesman.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 24,
|
||||
"h": 23
|
||||
"w": 40,
|
||||
"h": 80
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
|
@ -14,20 +14,20 @@
|
|||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"sourceSize": {
|
||||
"w": 24,
|
||||
"h": 24
|
||||
"w": 80,
|
||||
"h": 80
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 1,
|
||||
"x": 21,
|
||||
"y": 2,
|
||||
"w": 22,
|
||||
"h": 21
|
||||
"w": 38,
|
||||
"h": 78
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"w": 22,
|
||||
"h": 21
|
||||
"w": 38,
|
||||
"h": 78
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -36,6 +36,6 @@
|
|||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:04685a0eb6ef9095824b65408ec1b38f:9891674d538df100fcddde29330c21ae:927f117bdb1c2a27226a5540ce00ee8b$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:dd57e3db21f3933c15be65bec261f4c1:05c7ef32252a5c2d3ad007b7e26fabd7:ae82f52e471ed81e2558206f05476cd7$"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 839 B |
|
@ -87,6 +87,7 @@ export const FightOrFlightEncounter: IMysteryEncounter =
|
|||
y: -5,
|
||||
scale: 0.75,
|
||||
isItem: true,
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: bossSpriteKey,
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import BattleScene from "../../../battle-scene";
|
||||
import IMysteryEncounter, { MysteryEncounterBuilder, MysteryEncounterTier, } from "../mystery-encounter";
|
||||
import { EncounterOptionMode, MysteryEncounterOptionBuilder } from "../mystery-encounter-option";
|
||||
import { MoneyRequirement } from "../mystery-encounter-requirements";
|
||||
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { applyDamageToPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { Species } from "#enums/species";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||
|
||||
/**
|
||||
* Pokemon Salesman encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/36 | GitHub Issue #36}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const PokemonSalesmanEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.POKEMON_SALESMAN)
|
||||
.withEncounterTier(MysteryEncounterTier.ULTRA)
|
||||
.withSceneWaveRangeRequirement(10, 180)
|
||||
.withSceneRequirement(new MoneyRequirement(null, 8)) // Some costs may not be as significant, this is the max you'd pay
|
||||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "pokemon_salesman",
|
||||
fileRoot: "mystery-encounters",
|
||||
hasShadow: true
|
||||
}
|
||||
])
|
||||
.withIntroDialogue([
|
||||
{
|
||||
text: `${namespace}:intro`,
|
||||
},
|
||||
{
|
||||
text: `${namespace}:intro_dialogue`,
|
||||
speaker: `${namespace}:speaker`,
|
||||
},
|
||||
])
|
||||
.withTitle(`${namespace}:title`)
|
||||
.withDescription(`${namespace}:description`)
|
||||
.withQuery(`${namespace}:query`)
|
||||
.withOnInit((scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
|
||||
let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5]));
|
||||
const tries = 0;
|
||||
|
||||
// Reroll any species that don't have HAs
|
||||
while (isNullOrUndefined(species.abilityHidden) && tries < 5) {
|
||||
species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5]));
|
||||
}
|
||||
|
||||
|
||||
let pokemon;
|
||||
if (isNullOrUndefined(species.abilityHidden) || randSeedInt(100) === 0) {
|
||||
// If no HA mon found or you roll 1%, give shiny Magikarp
|
||||
species = getPokemonSpecies(Species.MAGIKARP);
|
||||
const hiddenIndex = species.ability2 ? 2 : 1;
|
||||
pokemon = scene.addPlayerPokemon(species, 5, hiddenIndex, species.formIndex, null, true);
|
||||
} else {
|
||||
const hiddenIndex = species.ability2 ? 2 : 1;
|
||||
pokemon = scene.addPlayerPokemon(species, 5, hiddenIndex, species.formIndex);
|
||||
}
|
||||
|
||||
const starterTier = speciesStarters[species.speciesId];
|
||||
// Prices by starter tier: 8/6.4/4.8/4/4
|
||||
let priceMultiplier = 8 * (Math.max(starterTier, 2.5) / 5);
|
||||
if (pokemon.shiny) {
|
||||
// Always max price for shiny, and add special message to intro
|
||||
priceMultiplier = 8;
|
||||
encounter.setDialogueToken("specialShinyText", `$t(${namespace}:shiny)`);
|
||||
} else {
|
||||
encounter.setDialogueToken("specialShinyText", "");
|
||||
}
|
||||
encounter.setDialogueToken("purchasePokemon", pokemon.name);
|
||||
encounter.setDialogueToken("price", pokemon.name);
|
||||
encounter.misc = {
|
||||
money: scene.getWaveMoneyAmount(priceMultiplier),
|
||||
pokemon: pokemon,
|
||||
// shiny: pokemon.shiny
|
||||
};
|
||||
|
||||
pokemon.calculateStats();
|
||||
|
||||
return true;
|
||||
})
|
||||
.withSimpleOption({
|
||||
buttonLabel: `${namespace}:option:1:label`,
|
||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:selected`,
|
||||
},
|
||||
],
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Choose Cheap Option
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const cost = encounter.misc.money;
|
||||
// const purchasedPokemon = encounter.misc.pokemon;
|
||||
|
||||
// Update money
|
||||
updatePlayerMoney(scene, -cost);
|
||||
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.withOption(
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withOptionMode(EncounterOptionMode.DEFAULT)
|
||||
.withSceneMoneyRequirement(0, 2) // Wave scaling money multiplier of 2
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option:1:label`,
|
||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.withPreOptionPhase(async (scene: BattleScene): Promise<boolean> => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const onPokemonSelected = (pokemon: PlayerPokemon) => {
|
||||
// Update money
|
||||
updatePlayerMoney(scene, -(encounter.options[0].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 getEncounterText(scene, `${namespace}:invalid_selection`);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Choose Cheap Option
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
const modifiers = encounter.misc.modifiers;
|
||||
|
||||
for (const modType of modifiers) {
|
||||
const modifier = modType.newModifier(chosenPokemon);
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
}
|
||||
scene.updateModifiers(true);
|
||||
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.withPostOptionPhase(async (scene: BattleScene) => {
|
||||
// Damage and status applied after dealer leaves (to make thematic sense)
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
|
||||
// Pokemon takes 1/3 max HP damage
|
||||
applyDamageToPokemon(scene, chosenPokemon, Math.floor(chosenPokemon.getMaxHp() / 3));
|
||||
|
||||
// Roll for poison (80%)
|
||||
if (randSeedInt(10) < 8) {
|
||||
if (chosenPokemon.trySetStatus(StatusEffect.TOXIC)) {
|
||||
// Toxic applied
|
||||
queueEncounterMessage(scene, `${namespace}:bad_poison`);
|
||||
} else {
|
||||
// Pokemon immune or something else prevents status
|
||||
queueEncounterMessage(scene, `${namespace}:damage_only`);
|
||||
}
|
||||
} else {
|
||||
queueEncounterMessage(scene, `${namespace}:damage_only`);
|
||||
}
|
||||
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withOption(
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||
.withSceneMoneyRequirement(0, 5) // Wave scaling money multiplier of 5
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}:option:2:label`,
|
||||
buttonTooltip: `${namespace}:option:2:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:selected`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.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 getEncounterText(scene, `${namespace}:invalid_selection`);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return selectPokemonForOption(scene, onPokemonSelected, null, selectableFilter);
|
||||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Choose Expensive Option
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
const modifiers = encounter.misc.modifiers;
|
||||
|
||||
for (const modType of modifiers) {
|
||||
const modifier = modType.newModifier(chosenPokemon);
|
||||
await scene.addModifier(modifier, true, false, false, true);
|
||||
}
|
||||
scene.updateModifiers(true);
|
||||
|
||||
leaveEncounterWithoutBattle(scene);
|
||||
})
|
||||
.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, `${namespace}:poison`);
|
||||
} else {
|
||||
// Pokemon immune or something else prevents status
|
||||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||
}
|
||||
} else {
|
||||
queueEncounterMessage(scene, `${namespace}:no_bad_effects`);
|
||||
}
|
||||
|
||||
setEncounterExp(scene, [chosenPokemon.id], 100);
|
||||
|
||||
chosenPokemon.updateInfo();
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.withSimpleOption(
|
||||
{
|
||||
buttonLabel: `${namespace}:option:3:label`,
|
||||
buttonTooltip: `${namespace}:option:3:tooltip`,
|
||||
},
|
||||
async (scene: BattleScene) => {
|
||||
// Leave encounter with no rewards or exp
|
||||
leaveEncounterWithoutBattle(scene, true);
|
||||
return true;
|
||||
}
|
||||
)
|
||||
.build();
|
|
@ -19,6 +19,11 @@ import { BerryType } from "#enums/berry-type";
|
|||
/** the i18n namespace for the encounter */
|
||||
const namespace = "mysteryEncounter:theStrongStuff";
|
||||
|
||||
/**
|
||||
* Pokemon Salesman encounter.
|
||||
* @see {@link https://github.com/AsdarDevelops/PokeRogue-Events/issues/54 | GitHub Issue #54}
|
||||
* @see For biome requirements check {@linkcode mysteryEncountersByBiome}
|
||||
*/
|
||||
export const TheStrongStuffEncounter: IMysteryEncounter =
|
||||
MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.THE_STRONG_STUFF)
|
||||
.withEncounterTier(MysteryEncounterTier.COMMON)
|
||||
|
@ -28,12 +33,13 @@ export const TheStrongStuffEncounter: IMysteryEncounter =
|
|||
.withIntroSpriteConfigs([
|
||||
{
|
||||
spriteKey: "berry_juice",
|
||||
fileRoot: "mystery-encounters",
|
||||
fileRoot: "items",
|
||||
hasShadow: true,
|
||||
isItem: true,
|
||||
scale: 1.5,
|
||||
x: -15,
|
||||
y: 3,
|
||||
yShadow: 0
|
||||
disableAnimation: true
|
||||
},
|
||||
{
|
||||
spriteKey: Species.SHUCKLE.toString(),
|
||||
|
|
|
@ -14,6 +14,7 @@ import IMysteryEncounter from "./mystery-encounter";
|
|||
import { SafariZoneEncounter } from "#app/data/mystery-encounters/encounters/safari-zone-encounter";
|
||||
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter";
|
||||
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter";
|
||||
import { PokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/pokemon-salesman-encounter";
|
||||
|
||||
// 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;
|
||||
|
@ -132,14 +133,14 @@ const nonExtremeBiomeEncounters: MysteryEncounterType[] = [
|
|||
|
||||
const humanTransitableBiomeEncounters: MysteryEncounterType[] = [
|
||||
MysteryEncounterType.MYSTERIOUS_CHALLENGERS,
|
||||
MysteryEncounterType.SHADY_VITAMIN_DEALER
|
||||
MysteryEncounterType.SHADY_VITAMIN_DEALER,
|
||||
MysteryEncounterType.POKEMON_SALESMAN
|
||||
];
|
||||
|
||||
const civilizationBiomeEncounters: MysteryEncounterType[] = [
|
||||
MysteryEncounterType.DEPARTMENT_STORE_SALE
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* To add an encounter to every biome possible, use this array
|
||||
*/
|
||||
|
@ -225,6 +226,7 @@ export function initMysteryEncounters() {
|
|||
allMysteryEncounters[MysteryEncounterType.LOST_AT_SEA] = LostAtSeaEncounter;
|
||||
allMysteryEncounters[MysteryEncounterType.FIERY_FALLOUT] = FieryFalloutEncounter;
|
||||
allMysteryEncounters[MysteryEncounterType.THE_STRONG_STUFF] = TheStrongStuffEncounter;
|
||||
allMysteryEncounters[MysteryEncounterType.POKEMON_SALESMAN] = PokemonSalesmanEncounter;
|
||||
|
||||
// Add extreme encounters to biome map
|
||||
extremeBiomeEncounters.forEach(encounter => {
|
||||
|
|
|
@ -17,6 +17,7 @@ import { Type } from "#app/data/type";
|
|||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
|
||||
export interface MysteryEncounterPokemonData {
|
||||
spriteScale?: number
|
||||
|
@ -204,13 +205,11 @@ export function applyHealToPokemon(scene: BattleScene, pokemon: PlayerPokemon, h
|
|||
* @param pokemon
|
||||
* @param value
|
||||
*/
|
||||
export function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: number) {
|
||||
pokemon.getSpeciesForm().baseStats = [...pokemon.getSpeciesForm().baseStats].map(v => {
|
||||
const newVal = Math.floor(v + value);
|
||||
return Math.max(newVal, 1);
|
||||
});
|
||||
export async function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: number) {
|
||||
const modType = modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE().generateType(null, [value]);
|
||||
const modifier = modType.newModifier(pokemon);
|
||||
await pokemon.scene.addModifier(modifier, false, false, false, true);
|
||||
pokemon.calculateStats();
|
||||
pokemon.updateInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -387,7 +386,7 @@ function failCatch(scene: BattleScene, pokemon: EnemyPokemon, originalY: number,
|
|||
});
|
||||
}
|
||||
|
||||
function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite, pokeballType: PokeballType): Promise<void> {
|
||||
export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, pokeball: Phaser.GameObjects.Sprite, pokeballType: PokeballType): Promise<void> {
|
||||
scene.unshiftPhase(new VictoryPhase(scene, BattlerIndex.ENEMY));
|
||||
|
||||
const speciesForm = !pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm();
|
||||
|
|
|
@ -11,5 +11,6 @@ export enum MysteryEncounterType {
|
|||
SAFARI_ZONE,
|
||||
LOST_AT_SEA, //might be generalized later on
|
||||
FIERY_FALLOUT,
|
||||
THE_STRONG_STUFF
|
||||
THE_STRONG_STUFF,
|
||||
POKEMON_SALESMAN
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as Utils from "../utils";
|
|||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
|
||||
import { getLevelTotalExp } from "../data/exp";
|
||||
import { Stat } from "../data/pokemon-stat";
|
||||
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
|
||||
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, StatBoosterModifier, TerastallizeModifier, PokemonBaseStatTotalModifier } from "../modifier/modifier";
|
||||
import { PokeballType } from "../data/pokeball";
|
||||
import { Gender } from "../data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
|
||||
|
@ -731,6 +731,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.stats = [ 0, 0, 0, 0, 0, 0 ];
|
||||
}
|
||||
const baseStats = this.getSpeciesForm().baseStats.slice(0);
|
||||
this.scene.applyModifiers(PokemonBaseStatTotalModifier, this.isPlayer(), this, baseStats);
|
||||
if (this.fusionSpecies) {
|
||||
const fusionBaseStats = this.getFusionSpeciesForm().baseStats;
|
||||
for (let s = 0; s < this.stats.length; s++) {
|
||||
|
|
|
@ -66,6 +66,16 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"PokemonBaseStatBoosterModifierType": {
|
||||
description: "Increases the holder's base {{statName}} by 10%. The higher your IVs, the higher the stack limit.",
|
||||
},
|
||||
"PokemonBaseStatTotalModifierType": {
|
||||
name: "Shuckle Juice",
|
||||
description: "{{increaseDecrease}} all of the holder's base stats by {{statValue}}. You were {{blessCurse}} by the Shuckle.",
|
||||
extra: {
|
||||
"increase": "Increases",
|
||||
"decrease": "Decreases",
|
||||
"blessed": "blessed",
|
||||
"cursed": "cursed"
|
||||
},
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
description: "Restores 100% HP for all Pokémon.",
|
||||
},
|
||||
|
@ -240,6 +250,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Full Heal Token", description: "Adds a 2.5% chance every turn to heal a status condition." },
|
||||
"ENEMY_ENDURE_CHANCE": { name: "Endure Token" },
|
||||
"ENEMY_FUSED_CHANCE": { name: "Fusion Token", description: "Adds a 1% chance that a wild Pokémon will be a fusion." },
|
||||
|
||||
"MYSTERY_ENCOUNTER_SHUCKLE_JUICE": { name: "Shuckle Juice" },
|
||||
},
|
||||
SpeciesBoosterItem: {
|
||||
"LIGHT_BALL": { name: "Light Ball", description: "It's a mysterious orb that boosts Pikachu's Attack and Sp. Atk stats." },
|
||||
|
|
|
@ -11,6 +11,7 @@ import { shadyVitaminDealerDialogue } from "#app/locales/en/mystery-encounters/s
|
|||
import { slumberingSnorlaxDialogue } from "#app/locales/en/mystery-encounters/slumbering-snorlax-dialogue";
|
||||
import { trainingSessionDialogue } from "#app/locales/en/mystery-encounters/training-session-dialogue";
|
||||
import { theStrongStuffDialogue } from "#app/locales/en/mystery-encounters/the-strong-stuff-dialogue";
|
||||
import { pokemonSalesmanDialogue } from "#app/locales/en/mystery-encounters/pokemon-salesman-dialogue";
|
||||
|
||||
/**
|
||||
* Patterns that can be used:
|
||||
|
@ -46,4 +47,5 @@ export const mysteryEncounter = {
|
|||
lostAtSea: lostAtSeaDialogue,
|
||||
fieryFallout: fieryFalloutDialogue,
|
||||
theStrongStuff: theStrongStuffDialogue,
|
||||
pokemonSalesman: pokemonSalesmanDialogue
|
||||
} as const;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
export const pokemonSalesmanDialogue = {
|
||||
intro: "A chipper elderly man approaches you.",
|
||||
speaker: "Gentleman",
|
||||
intro_dialogue: "Hello there! Have I got a deal just for YOU!{{specialShinyText}}",
|
||||
title: "The Pokémon Salesman",
|
||||
description: "\"This {{purchasePokemon}} is extremely unique, and carries an ability not normally found on its species! I'll let you have this swell {{purchasePokemon}} for just {{money, money}}!\"\n\n\"What do you say?\"",
|
||||
query: "What will you do?",
|
||||
shiny: "$I have SUPER amazing Pokémon that\nanyone would be dying to get!",
|
||||
option: {
|
||||
1: {
|
||||
label: "Accept",
|
||||
tooltip: "(-) Pay {{money, money}}\n(+) Gain a {{purchasePokemon}} with its Hidden Ability (also saved in Pokédex data)",
|
||||
selected_dialogue: `Excellent choice!
|
||||
$I can see you've a keen eye for business.`,
|
||||
selected_message: "You paid an outrageous sum and bought the {{purchasePokemon}}.",
|
||||
selected_dialogue_2: "Oh, yeah...@d{64} Returns not accepted, got that?"
|
||||
},
|
||||
2: {
|
||||
label: "Refuse",
|
||||
tooltip: "(-) No Rewards",
|
||||
selected: `No?@d{32} You say no?
|
||||
$I'm only doing this as a favor to you!`,
|
||||
},
|
||||
},
|
||||
};
|
|
@ -621,6 +621,27 @@ export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierT
|
|||
}
|
||||
}
|
||||
|
||||
export class PokemonBaseStatTotalModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType {
|
||||
private readonly statModifier: integer;
|
||||
|
||||
constructor(statModifier: integer) {
|
||||
super("modifierType:ModifierType.MYSTERY_ENCOUNTER_SHUCKLE_JUICE", "berry_juice", (_type, args) => new Modifiers.PokemonBaseStatTotalModifier(this, (args[0] as Pokemon).id, this.statModifier));
|
||||
this.statModifier = statModifier;
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.PokemonBaseStatTotalModifierType.description", {
|
||||
increaseDecrease: i18next.t(this.statModifier >= 0 ? "modifierType:ModifierType.PokemonBaseStatTotalModifierType.extra.increase" : "modifierType:ModifierType.PokemonBaseStatTotalModifierType.extra.decrease"),
|
||||
blessCurse: i18next.t(this.statModifier >= 0 ? "modifierType:ModifierType.PokemonBaseStatTotalModifierType.extra.blessed" : "modifierType:ModifierType.PokemonBaseStatTotalModifierType.extra.cursed"),
|
||||
statValue: this.statModifier,
|
||||
});
|
||||
}
|
||||
|
||||
getPregenArgs(): any[] {
|
||||
return [ this.statModifier ];
|
||||
}
|
||||
}
|
||||
|
||||
class AllPokemonFullHpRestoreModifierType extends ModifierType {
|
||||
private descriptionKey: string;
|
||||
|
||||
|
@ -1354,6 +1375,13 @@ export const modifierTypes = {
|
|||
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 2.5, 10)),
|
||||
ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2),
|
||||
ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)),
|
||||
|
||||
MYSTERY_ENCOUNTER_SHUCKLE_JUICE: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs) {
|
||||
return new PokemonBaseStatTotalModifierType(pregenArgs[0] as integer);
|
||||
}
|
||||
return new PokemonBaseStatTotalModifierType(Utils.randSeedInt(20));
|
||||
}),
|
||||
};
|
||||
|
||||
interface ModifierPool {
|
||||
|
|
|
@ -708,6 +708,55 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
|||
}
|
||||
}
|
||||
|
||||
export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier {
|
||||
private statModifier: integer;
|
||||
|
||||
constructor(type: ModifierTypes.PokemonBaseStatTotalModifierType, pokemonId: integer, statModifier: integer, stackCount?: integer) {
|
||||
super(type, pokemonId, stackCount);
|
||||
this.statModifier = statModifier;
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier): boolean {
|
||||
if (modifier instanceof PokemonBaseStatTotalModifier) {
|
||||
return (modifier as PokemonBaseStatTotalModifier).statModifier === this.statModifier;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clone(): PersistentModifier {
|
||||
return new PokemonBaseStatTotalModifier(this.type as ModifierTypes.PokemonBaseStatTotalModifierType, this.pokemonId, this.statModifier, this.stackCount);
|
||||
}
|
||||
|
||||
getArgs(): any[] {
|
||||
return super.getArgs().concat(this.statModifier);
|
||||
}
|
||||
|
||||
shouldApply(args: any[]): boolean {
|
||||
return super.shouldApply(args) && args.length === 2 && args[1] instanceof Array;
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
args[1].forEach((v, i) => {
|
||||
const newVal = Math.floor(v + this.statModifier);
|
||||
args[1][i] = Math.min(Math.max(newVal, 1), 999999);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getTransferrable(_withinParty: boolean): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
getScoreMultiplier(): number {
|
||||
return 1.2;
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier used for held items that apply {@linkcode Stat} boost(s)
|
||||
* using a multiplier.
|
||||
|
|
|
@ -117,9 +117,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
|
|||
*/
|
||||
|
||||
// 1 to 256, set to null to ignore
|
||||
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null;
|
||||
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256;
|
||||
export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
|
||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
|
||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.THE_STRONG_STUFF;
|
||||
|
||||
/**
|
||||
* MODIFIER / ITEM OVERRIDES
|
||||
|
|
Loading…
Reference in New Issue