Add enemy buffs to balance endless mode
parent
cb62d79280
commit
5567b39f20
|
@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov
|
|||
import { Mode } from './ui/ui';
|
||||
import { Command } from "./ui/command-ui-handler";
|
||||
import { Stat } from "./data/pokemon-stat";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
||||
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyInstantReviveChanceModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
|
||||
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
|
||||
|
@ -16,7 +16,7 @@ import { EvolutionPhase } from "./evolution-phase";
|
|||
import { BattlePhase } from "./battle-phase";
|
||||
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat";
|
||||
import { Biome, biomeLinks } from "./data/biome";
|
||||
import { ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
|
||||
import { ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getEnemyBuffModifierTypeOptionsForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag";
|
||||
import { getPokemonMessage } from "./messages";
|
||||
|
@ -1561,8 +1561,11 @@ class MoveEffectPhase extends PokemonPhase {
|
|||
if (!isProtected && !chargeEffect) {
|
||||
applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT,
|
||||
user, target, this.move.getMove());
|
||||
if (!target.isFainted())
|
||||
if (!target.isFainted()) {
|
||||
applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult);
|
||||
if (!user.isPlayer())
|
||||
user.scene.applyModifiers(EnemyAttackStatusEffectChanceModifier, false, target);
|
||||
}
|
||||
if (this.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT))
|
||||
this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex());
|
||||
}
|
||||
|
@ -1987,8 +1990,15 @@ export class FaintPhase extends PokemonPhase {
|
|||
if (!--instantReviveModifier.stackCount)
|
||||
this.scene.removeModifier(instantReviveModifier);
|
||||
this.scene.updateModifiers(this.player);
|
||||
this.end();
|
||||
return;
|
||||
return this.end();
|
||||
}
|
||||
|
||||
if (!pokemon.isPlayer()) {
|
||||
const enemyInstantReviveModifiers = this.scene.findModifiers(m => m instanceof EnemyInstantReviveChanceModifier);
|
||||
for (let modifier of enemyInstantReviveModifiers) {
|
||||
if (modifier.shouldApply([ pokemon ]) && modifier.apply([ pokemon ]))
|
||||
return this.end();
|
||||
}
|
||||
}
|
||||
|
||||
this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true);
|
||||
|
@ -2113,9 +2123,11 @@ export class VictoryPhase extends PokemonPhase {
|
|||
if (this.scene.currentBattle.battleType === BattleType.TRAINER)
|
||||
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
|
||||
if (this.scene.gameMode === GameMode.ENDLESS || this.scene.currentBattle.waveIndex < this.scene.finalWave) {
|
||||
if (this.scene.currentBattle.waveIndex > 30 || this.scene.currentBattle.waveIndex % 10)
|
||||
if (this.scene.currentBattle.waveIndex > 30 || this.scene.currentBattle.waveIndex % 10) {
|
||||
this.scene.pushPhase(new SelectModifierPhase(this.scene));
|
||||
else
|
||||
if (this.scene.gameMode === GameMode.ENDLESS && !(this.scene.currentBattle.waveIndex % 50))
|
||||
this.scene.pushPhase(new SelectEnemyBuffModifierPhase(this.scene));
|
||||
} else
|
||||
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.GOLDEN_EXP_CHARM))
|
||||
this.scene.pushPhase(new NewBattlePhase(this.scene));
|
||||
} else
|
||||
|
@ -2794,13 +2806,13 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.resetSeed();
|
||||
this.updateSeed();
|
||||
|
||||
const party = this.scene.getParty();
|
||||
regenerateModifierPoolThresholds(party, ModifierPoolType.PLAYER);
|
||||
regenerateModifierPoolThresholds(party, this.getPoolType());
|
||||
const modifierCount = new Utils.IntegerHolder(3);
|
||||
this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount);
|
||||
const typeOptions: Array<ModifierTypeOption> = getPlayerModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, modifierCount.value, party);
|
||||
const typeOptions: ModifierTypeOption[] = this.getModifierTypeOptions(modifierCount.value);
|
||||
|
||||
const modifierSelectCallback = (cursor: integer) => {
|
||||
if (cursor < 0) {
|
||||
|
@ -2810,7 +2822,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
} else if (cursor >= typeOptions.length) {
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, toSlotIndex: integer) => {
|
||||
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT).then(() => {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
|
||||
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
|
||||
const itemModifier = itemModifiers[itemIndex];
|
||||
|
@ -2820,11 +2832,11 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
super.end();
|
||||
} else
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, typeOptions, modifierSelectCallback);
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback);
|
||||
});
|
||||
});
|
||||
} else
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, typeOptions, modifierSelectCallback);
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback);
|
||||
}, PartyUiHandler.FilterItemMaxStacks);
|
||||
return;
|
||||
}
|
||||
|
@ -2841,7 +2853,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
: undefined;
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, partyUiMode, -1, (slotIndex: integer, option: PartyOption) => {
|
||||
if (slotIndex < 6) {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT).then(() => {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer()).then(() => {
|
||||
const modifierType = typeOptions[cursor].type;
|
||||
const modifier = !isMoveModifier
|
||||
? modifierType.newModifier(party[slotIndex])
|
||||
|
@ -2851,15 +2863,63 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.addModifier(modifier, true).then(() => super.end());
|
||||
});
|
||||
} else
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, typeOptions, modifierSelectCallback);
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, );
|
||||
}, pokemonModifierType.selectFilter, modifierType instanceof PokemonMoveModifierType ? (modifierType as PokemonMoveModifierType).moveSelectFilter : undefined, tmMoveId);
|
||||
} else {
|
||||
this.scene.addModifier(typeOptions[cursor].type.newModifier(), true).then(() => super.end());
|
||||
this.addModifier(typeOptions[cursor].type.newModifier()).then(() => super.end());
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
}
|
||||
};
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, typeOptions, modifierSelectCallback);
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback);
|
||||
}
|
||||
|
||||
updateSeed(): void {
|
||||
this.scene.resetSeed();
|
||||
}
|
||||
|
||||
isPlayer(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
getPoolType(): ModifierPoolType {
|
||||
return ModifierPoolType.PLAYER;
|
||||
}
|
||||
|
||||
getModifierTypeOptions(modifierCount: integer): ModifierTypeOption[] {
|
||||
return getPlayerModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, modifierCount, this.scene.getParty());
|
||||
}
|
||||
|
||||
addModifier(modifier: Modifier): Promise<void> {
|
||||
return this.scene.addModifier(modifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectEnemyBuffModifierPhase extends SelectModifierPhase {
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
}
|
||||
|
||||
start() {
|
||||
this.scene.time.delayedCall(500, () => super.start());
|
||||
}
|
||||
|
||||
updateSeed(): void { }
|
||||
|
||||
isPlayer(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
getPoolType(): ModifierPoolType {
|
||||
return ModifierPoolType.ENEMY_BUFF;
|
||||
}
|
||||
|
||||
getModifierTypeOptions(modifierCount: integer): ModifierTypeOption[] {
|
||||
return getEnemyBuffModifierTypeOptionsForWave(modifierCount);
|
||||
}
|
||||
|
||||
addModifier(modifier: Modifier): Promise<void> {
|
||||
return this.scene.addEnemyModifier(modifier as PersistentModifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,28 +63,18 @@ export default class Battle {
|
|||
|
||||
private getLevelForWave(): integer {
|
||||
let baseLevel = 1 + this.waveIndex / 2 + Math.pow(this.waveIndex / 25, 2);
|
||||
let bossMultiplier = this.waveIndex <= 250 ? 1.2 : Math.pow(1.2, this.waveIndex / 250);
|
||||
const bossMultiplier = 1.2;
|
||||
|
||||
if (!(this.waveIndex % 10)) {
|
||||
const ret = Math.floor(baseLevel * bossMultiplier);
|
||||
if (this.waveIndex === 200 || !(this.waveIndex % 250))
|
||||
return Math.ceil(ret / 25) * 25;
|
||||
return ret;
|
||||
return ret + Math.round(Phaser.Math.RND.realInRange(-1, 1) * Math.floor(this.waveIndex / 10));
|
||||
}
|
||||
|
||||
const deviation = 10 / this.waveIndex;
|
||||
|
||||
const randLevel = Math.max(Math.round(baseLevel + Math.abs(Utils.randSeedGauss(deviation))), 1);
|
||||
|
||||
if (this.waveIndex <= 250)
|
||||
return randLevel;
|
||||
|
||||
const waveRatio = Math.min(this.waveIndex - 250 / 250, 1);
|
||||
|
||||
const easeInFunc = Phaser.Tweens.Builders.GetEaseFunction('Sine.easeIn');
|
||||
const easeOutFunc = Phaser.Tweens.Builders.GetEaseFunction('Sine.easeOut');
|
||||
|
||||
return Math.ceil(easeInFunc(waveRatio) * Math.floor(baseLevel * bossMultiplier) + easeOutFunc(1 - waveRatio) * randLevel);
|
||||
return Math.max(Math.round(baseLevel + Math.abs(Utils.randSeedGauss(deviation))), 1);
|
||||
}
|
||||
|
||||
getBattlerCount(): integer {
|
||||
|
|
|
@ -2635,7 +2635,8 @@ export function initMoves() {
|
|||
.ignoresVirtual()
|
||||
.target(MoveTarget.OTHER),
|
||||
new StatusMove(Moves.TRANSFORM, "Transform", Type.NORMAL, -1, 10, -1, "User takes on the form and attacks of the opponent.", -1, 0, 1)
|
||||
.attr(TransformAttr),
|
||||
.attr(TransformAttr)
|
||||
.ignoresProtect(),
|
||||
new AttackMove(Moves.BUBBLE, "Bubble", Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Speed.", 10, 0, 1)
|
||||
.attr(StatChangeAttr, BattleStat.SPD, -1)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
|
|
|
@ -12,6 +12,7 @@ import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName
|
|||
import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry';
|
||||
import { Unlockables } from '../system/unlockables';
|
||||
import { GameMode } from '../game-mode';
|
||||
import { StatusEffect, getStatusEffectDescriptor } from '../data/status-effect';
|
||||
|
||||
type Modifier = Modifiers.Modifier;
|
||||
|
||||
|
@ -26,7 +27,8 @@ export enum ModifierTier {
|
|||
export enum ModifierPoolType {
|
||||
PLAYER,
|
||||
WILD,
|
||||
TRAINER
|
||||
TRAINER,
|
||||
ENEMY_BUFF
|
||||
}
|
||||
|
||||
type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier;
|
||||
|
@ -524,6 +526,18 @@ export class TurnHeldItemTransferModifierType extends PokemonHeldItemModifierTyp
|
|||
}
|
||||
}
|
||||
|
||||
export class EnemyAttackStatusEffectChanceModifierType extends ModifierType {
|
||||
constructor(name: string, chancePercent: integer, effect: StatusEffect, iconImage?: string) {
|
||||
super(name, `Adds a ${chancePercent}% chance on hit to inflict ${getStatusEffectDescriptor(effect)}`, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent), iconImage, 'enemy_status_chance')
|
||||
}
|
||||
}
|
||||
|
||||
export class EnemyInstantReviveChanceModifierType extends ModifierType {
|
||||
constructor(name: string, chancePercent: integer, fullHeal: boolean, iconImage?: string) {
|
||||
super(name, `Adds a ${chancePercent}% chance of reviving with ${fullHeal ? '100' : '50'}% HP`, (type, _args) => new Modifiers.EnemyInstantReviveChanceModifier(type, fullHeal, chancePercent), iconImage, 'enemy_revive');
|
||||
}
|
||||
}
|
||||
|
||||
export type ModifierTypeFunc = () => ModifierType;
|
||||
type WeightedModifierTypeWeightFunc = (party: Pokemon[]) => integer;
|
||||
|
||||
|
@ -662,7 +676,14 @@ export const modifierTypes = {
|
|||
(type, _args) => new Modifiers.ExtraModifierModifier(type), 'pb_gold', null, 'pb_bounce_1'),
|
||||
|
||||
ENEMY_DAMAGE_BOOSTER: () => new ModifierType('Damage Booster', 'Increases damage by 20%', (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type), 'wl_item_drop'),
|
||||
ENEMY_DAMAGE_REDUCTION: () => new ModifierType('Damage Reducer', 'Reduces incoming damage by 10%', (type, _args) => new Modifiers.EnemyDamageReducerModifier(type), 'wl_guard_spec')
|
||||
ENEMY_DAMAGE_REDUCTION: () => new ModifierType('Damage Reducer', 'Reduces incoming damage by 10%', (type, _args) => new Modifiers.EnemyDamageReducerModifier(type), 'wl_guard_spec'),
|
||||
ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Poison Hit', 10, StatusEffect.POISON, 'wl_antidote'),
|
||||
ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Paralyze Hit', 10, StatusEffect.PARALYSIS, 'wl_paralyze_heal'),
|
||||
ENEMY_ATTACK_SLEEP_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Sleep Hit', 10, StatusEffect.SLEEP, 'wl_awakening'),
|
||||
ENEMY_ATTACK_FREEZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Freeze Hit', 10, StatusEffect.FREEZE, 'wl_ice_heal'),
|
||||
ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType('Burn Hit', 10, StatusEffect.BURN, 'wl_burn_heal'),
|
||||
ENEMY_INSTANT_REVIVE_CHANCE: () => new EnemyInstantReviveChanceModifierType('Reviver', 5, false, 'wl_revive'),
|
||||
ENEMY_INSTANT_MAX_REVIVE_CHANCE: () => new EnemyInstantReviveChanceModifierType('Reviver', 2, true, 'wl_max_revive'),
|
||||
};
|
||||
|
||||
const modifierPool = {
|
||||
|
@ -800,6 +821,23 @@ const trainerModifierPool = {
|
|||
].map(m => { m.setTier(ModifierTier.MASTER); return m; })
|
||||
};
|
||||
|
||||
const enemyBuffModifierPool = {
|
||||
[ModifierTier.COMMON]: [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 8),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 8),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_SLEEP_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_FREEZE_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_INSTANT_REVIVE_CHANCE, 8),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_INSTANT_MAX_REVIVE_CHANCE, 8)
|
||||
].map(m => { m.setTier(ModifierTier.COMMON); return m; }),
|
||||
[ModifierTier.GREAT]: [ ].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
|
||||
[ModifierTier.ULTRA]: [ ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
|
||||
[ModifierTier.MASTER]: [ ].map(m => { m.setTier(ModifierTier.MASTER); return m; })
|
||||
};
|
||||
|
||||
export function getModifierType(modifierTypeFunc: ModifierTypeFunc): ModifierType {
|
||||
const modifierType = modifierTypeFunc();
|
||||
if (!modifierType.id)
|
||||
|
@ -813,9 +851,12 @@ let ignoredPoolIndexes = {};
|
|||
let enemyModifierPoolThresholds = {};
|
||||
let enemyIgnoredPoolIndexes = {};
|
||||
|
||||
let enemyBuffModifierPoolThresholds = {};
|
||||
let enemyBuffIgnoredPoolIndexes = {};
|
||||
|
||||
export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType) {
|
||||
const player = !poolType;
|
||||
const pool = player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : trainerModifierPool;
|
||||
const pool = player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : poolType === ModifierPoolType.TRAINER ? trainerModifierPool : enemyBuffModifierPool;
|
||||
const ignoredIndexes = {};
|
||||
const thresholds = Object.fromEntries(new Map(Object.keys(pool).map(t => {
|
||||
ignoredIndexes[t] = [];
|
||||
|
@ -843,9 +884,12 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
|
|||
if (player) {
|
||||
modifierPoolThresholds = thresholds;
|
||||
ignoredPoolIndexes = ignoredIndexes;
|
||||
} else {
|
||||
} else if (poolType !== ModifierPoolType.ENEMY_BUFF) {
|
||||
enemyModifierPoolThresholds = thresholds;
|
||||
enemyIgnoredPoolIndexes = ignoredIndexes;
|
||||
} else {
|
||||
enemyBuffModifierPoolThresholds = thresholds;
|
||||
enemyBuffIgnoredPoolIndexes = ignoredIndexes;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -868,6 +912,19 @@ export function getPlayerModifierTypeOptionsForWave(waveIndex: integer, count: i
|
|||
return options;
|
||||
}
|
||||
|
||||
export function getEnemyBuffModifierTypeOptionsForWave(count: integer): ModifierTypeOption[] {
|
||||
const options: ModifierTypeOption[] = [];
|
||||
const retryCount = Math.min(count * 5, 50);
|
||||
new Array(count).fill(0).map(() => {
|
||||
let candidate = getNewModifierTypeOption(null, ModifierPoolType.ENEMY_BUFF, ModifierTier.COMMON);
|
||||
let r = 0;
|
||||
while (options.length && ++r < retryCount && options.filter(o => o.type.name === candidate.type.name || o.type.group === candidate.type.group).length)
|
||||
candidate = getNewModifierTypeOption(null, ModifierPoolType.ENEMY_BUFF, candidate.type.tier);
|
||||
options.push(candidate);
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER, gameMode: GameMode): PokemonHeldItemModifierType[] {
|
||||
const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType).type as PokemonHeldItemModifierType);
|
||||
if ((gameMode === GameMode.CLASSIC && waveIndex === 200) || !(waveIndex % 1000))
|
||||
|
@ -877,6 +934,7 @@ export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer,
|
|||
|
||||
function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, tier?: ModifierTier, upgrade?: boolean): ModifierTypeOption {
|
||||
const player = !poolType;
|
||||
const pool = player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : poolType === ModifierPoolType.TRAINER ? trainerModifierPool : enemyBuffModifierPool;
|
||||
if (tier === undefined) {
|
||||
const tierValue = Utils.randSeedInt(256);
|
||||
if (player && tierValue) {
|
||||
|
@ -886,23 +944,26 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
|||
} else
|
||||
upgrade = false;
|
||||
tier = (tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER) + (upgrade ? 1 : 0);
|
||||
while (tier && !modifierPool[tier].length)
|
||||
tier--;
|
||||
}
|
||||
|
||||
const thresholds = Object.keys((player ? modifierPoolThresholds : enemyModifierPoolThresholds)[tier]);
|
||||
const totalWeight = parseInt(thresholds[thresholds.length - 1]);
|
||||
const thresholds = player ? modifierPoolThresholds : pool !== enemyBuffModifierPool ? enemyModifierPoolThresholds : enemyBuffModifierPoolThresholds;
|
||||
const tierThresholds = Object.keys(thresholds[tier]);
|
||||
const totalWeight = parseInt(tierThresholds[tierThresholds.length - 1]);
|
||||
const value = Utils.randSeedInt(totalWeight);
|
||||
let index: integer;
|
||||
for (let t of thresholds) {
|
||||
for (let t of tierThresholds) {
|
||||
let threshold = parseInt(t);
|
||||
if (value < threshold) {
|
||||
index = (player ? modifierPoolThresholds : enemyModifierPoolThresholds)[tier][threshold];
|
||||
index = thresholds[tier][threshold];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (player)
|
||||
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
|
||||
let modifierType: ModifierType = ((player ? modifierPool : poolType === ModifierPoolType.WILD ? wildModifierPool : trainerModifierPool)[tier][index]).modifierType;
|
||||
let modifierType: ModifierType = (pool[tier][index]).modifierType;
|
||||
if (modifierType instanceof ModifierTypeGenerator) {
|
||||
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
|
||||
if (modifierType === null) {
|
||||
|
|
|
@ -1231,6 +1231,10 @@ export abstract class EnemyPersistentModifer extends PersistentModifier {
|
|||
constructor(type: ModifierType, stackCount?: integer) {
|
||||
super(type, stackCount);
|
||||
}
|
||||
|
||||
getMaxStackCount(): number {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
export class EnemyDamageBoosterModifier extends EnemyPersistentModifer {
|
||||
|
@ -1251,10 +1255,6 @@ export class EnemyDamageBoosterModifier extends EnemyPersistentModifer {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
getMaxStackCount(): number {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
export class EnemyDamageReducerModifier extends EnemyPersistentModifer {
|
||||
|
@ -1275,19 +1275,17 @@ export class EnemyDamageReducerModifier extends EnemyPersistentModifer {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
getMaxStackCount(): number {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifer {
|
||||
public effect: StatusEffect;
|
||||
private chance: number;
|
||||
|
||||
constructor(type: ModifierType, effect: StatusEffect, stackCount?: integer) {
|
||||
constructor(type: ModifierType, effect: StatusEffect, chancePercent: integer, stackCount?: integer) {
|
||||
super(type, stackCount);
|
||||
|
||||
this.effect = effect;
|
||||
this.chance = chancePercent / 100;
|
||||
}
|
||||
|
||||
match(modifier: Modifier): boolean {
|
||||
|
@ -1300,13 +1298,45 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModife
|
|||
|
||||
apply(args: any[]): boolean {
|
||||
const target = (args[0] as Pokemon);
|
||||
if (Utils.randInt(10) < this.getStackCount())
|
||||
if (Utils.randIntRange(0, 1) < this.chance * this.getStackCount()) {
|
||||
target.scene.unshiftPhase(new ObtainStatusEffectPhase(target.scene, target.getBattlerIndex(), this.effect));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getMaxStackCount(): number {
|
||||
return 5;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class EnemyInstantReviveChanceModifier extends EnemyPersistentModifer {
|
||||
public fullHeal: boolean;
|
||||
private chance: number;
|
||||
|
||||
constructor(type: ModifierType, healFull: boolean, chancePercent: integer, stackCount?: integer) {
|
||||
super(type, stackCount);
|
||||
|
||||
this.fullHeal = healFull;
|
||||
this.chance = chancePercent / 100;
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier) {
|
||||
return modifier instanceof EnemyInstantReviveChanceModifier && modifier.fullHeal === this.fullHeal;
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new EnemyInstantReviveChanceModifier(this.type, this.fullHeal, this.chance, this.stackCount);
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
if (Utils.randIntRange(0, 1) >= this.chance * this.getStackCount())
|
||||
return false;
|
||||
|
||||
const pokemon = args[0] as Pokemon;
|
||||
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
|
||||
Math.max(Math.floor(pokemon.getMaxHp() / (this.fullHeal ? 1 : 2)), 1), getPokemonMessage(pokemon, ` was revived\nby its ${this.type.name}!`), false, false, true));
|
||||
|
||||
pokemon.resetStatus();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -116,7 +116,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
|||
}
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
clear() {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
private transferButtonContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private lastCursor: integer = 0;
|
||||
private player: boolean;
|
||||
|
||||
public options: ModifierOption[];
|
||||
|
||||
|
@ -47,26 +48,28 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
|
||||
show(args: any[]) {
|
||||
if (this.active) {
|
||||
if (args.length === 2) {
|
||||
if (args.length === 3) {
|
||||
this.awaitingActionInput = true;
|
||||
this.onActionInput = args[1];
|
||||
this.onActionInput = args[2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length !== 2 || !(args[0] instanceof Array) || !args[0].length || !(args[1] instanceof Function))
|
||||
if (args.length !== 3 || !(args[1] instanceof Array) || !args[1].length || !(args[2] instanceof Function))
|
||||
return;
|
||||
|
||||
super.show(args);
|
||||
|
||||
this.getUi().clearText();
|
||||
|
||||
const partyHasHeldItem = !!this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).getTransferrable(true)).length;
|
||||
this.player = args[0];
|
||||
|
||||
const partyHasHeldItem = this.player && !!this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).getTransferrable(true)).length;
|
||||
|
||||
this.transferButtonContainer.setVisible(false);
|
||||
this.transferButtonContainer.setAlpha(0);
|
||||
|
||||
const typeOptions = args[0] as ModifierTypeOption[];
|
||||
const typeOptions = args[1] as ModifierTypeOption[];
|
||||
for (let m = 0; m < typeOptions.length; m++) {
|
||||
const sliceWidth = (this.scene.game.canvas.width / 6) / (typeOptions.length + 2);
|
||||
const option = new ModifierOption(this.scene, sliceWidth * (m + 1) + (sliceWidth * 0.5), -this.scene.game.canvas.height / 12 - 24, typeOptions[m]);
|
||||
|
@ -113,7 +116,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
|
||||
this.setCursor(0);
|
||||
this.awaitingActionInput = true;
|
||||
this.onActionInput = args[1];
|
||||
this.onActionInput = args[2];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -134,6 +137,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
originalOnActionInput(this.cursor);
|
||||
}
|
||||
} else if (button === Button.CANCEL) {
|
||||
if (this.player) {
|
||||
success = true;
|
||||
if (this.onActionInput) {
|
||||
const originalOnActionInput = this.onActionInput;
|
||||
|
@ -141,6 +145,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
this.onActionInput = null;
|
||||
originalOnActionInput(-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
|
|
Loading…
Reference in New Issue