Trainers switch out their Pokemon when at a disadvantage
parent
f49a3e5127
commit
8c4f336cd6
|
@ -967,7 +967,7 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||
if (!this.player && this.slotIndex === -1)
|
||||
this.slotIndex = this.scene.currentBattle.trainer.getNextSummonIndex();
|
||||
|
||||
if (!this.doReturn || (this.slotIndex !== -1 && !this.scene.getParty()[this.slotIndex])) {
|
||||
if (!this.doReturn || (this.slotIndex !== -1 && !(this.player ? this.scene.getParty() : this.scene.getEnemyParty())[this.slotIndex])) {
|
||||
this.switchAndSummon();
|
||||
return;
|
||||
}
|
||||
|
@ -975,7 +975,7 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||
const pokemon = this.getPokemon();
|
||||
|
||||
if (!this.batonPass)
|
||||
this.scene.getEnemyField().forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id));
|
||||
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id));
|
||||
|
||||
this.scene.ui.showText(this.player ? `Come back, ${pokemon.name}!` : `${this.scene.currentBattle.trainer.getName()}\nwithdrew ${pokemon.name}!`);
|
||||
this.scene.playSound('pb_rel');
|
||||
|
@ -996,11 +996,11 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||
}
|
||||
|
||||
switchAndSummon() {
|
||||
const party = this.getParty();
|
||||
const party = this.player ? this.getParty() : this.scene.getEnemyParty();
|
||||
const switchedPokemon = party[this.slotIndex];
|
||||
this.lastPokemon = this.getPokemon();
|
||||
if (this.batonPass && switchedPokemon) {
|
||||
this.scene.getEnemyField().forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id));
|
||||
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id));
|
||||
if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) {
|
||||
const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
|
||||
&& (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier;
|
||||
|
@ -1427,6 +1427,40 @@ export class EnemyCommandPhase extends FieldPhase {
|
|||
|
||||
const enemyPokemon = this.scene.getEnemyField()[this.fieldIndex];
|
||||
|
||||
const trainer = this.scene.currentBattle.trainer;
|
||||
|
||||
if (trainer) {
|
||||
const opponents = enemyPokemon.getOpponents();
|
||||
|
||||
const trapTag = enemyPokemon.findTag(t => t instanceof TrappedTag) as TrappedTag;
|
||||
const trapped = new Utils.BooleanHolder(false);
|
||||
opponents.forEach(playerPokemon => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, playerPokemon, trapped));
|
||||
if (enemyPokemon.moveset.find(m => m.moveId === Moves.BATON_PASS && m.isUsable(enemyPokemon)) && (enemyPokemon.summonData.battleStats.reduce((total, stat) => total += stat, 0) >= 0 || trapTag || trapped.value)) {
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] =
|
||||
{ command: Command.FIGHT, move: { move: Moves.BATON_PASS, targets: enemyPokemon.getNextTargets(Moves.BATON_PASS) } };
|
||||
|
||||
return this.end();
|
||||
} else if (!trapTag && !trapped.value) {
|
||||
const partyMemberScores = trainer.getPartyMemberMatchupScores();
|
||||
|
||||
if (partyMemberScores.length) {
|
||||
const matchupScores = opponents.map(opp => enemyPokemon.getMatchupScore(opp));
|
||||
const matchupScore = matchupScores.reduce((total, score) => total += score, 0) / matchupScores.length;
|
||||
|
||||
const sortedPartyMemberScores = trainer.getSortedPartyMemberMatchupScores(partyMemberScores);
|
||||
|
||||
if (sortedPartyMemberScores[0][1] >= matchupScore * (trainer.config.isBoss ? 2 : 3)) {
|
||||
const index = trainer.getNextSummonIndex(partyMemberScores);
|
||||
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] =
|
||||
{ command: Command.POKEMON, cursor: index, args: [ false ] };
|
||||
|
||||
return this.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nextMove = enemyPokemon.getNextMove();
|
||||
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] =
|
||||
|
@ -1527,7 +1561,7 @@ export class TurnStartPhase extends FieldPhase {
|
|||
case Command.RUN:
|
||||
const isSwitch = turnCommand.command === Command.POKEMON;
|
||||
if (isSwitch)
|
||||
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, pokemon.getFieldIndex(), turnCommand.cursor, true, turnCommand.args[0] as boolean));
|
||||
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, pokemon.getFieldIndex(), turnCommand.cursor, true, turnCommand.args[0] as boolean, pokemon.isPlayer()));
|
||||
else
|
||||
this.scene.unshiftPhase(new AttemptRunPhase(this.scene, pokemon.getFieldIndex()));
|
||||
break;
|
||||
|
|
|
@ -1737,6 +1737,10 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||
return (!player && !user.scene.currentBattle.battleType) || party.filter(p => !p.isFainted()).length > user.scene.currentBattle.getBattlerCount();
|
||||
};
|
||||
}
|
||||
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||
return -100; // Overridden in switch logic
|
||||
}
|
||||
}
|
||||
|
||||
export class CopyTypeAttr extends MoveEffectAttr {
|
||||
|
|
|
@ -902,7 +902,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (this.battleInfo.visible) {
|
||||
this.scene.tweens.add({
|
||||
targets: this.battleInfo,
|
||||
x: this.isPlayer() ? '+=150' : `-=${!this.isBoss() ? 150 : 198}`,
|
||||
x: this.isPlayer() ? '+=150' : `-=${!this.isBoss() ? 150 : 246}`,
|
||||
duration: 500,
|
||||
ease: 'Sine.easeIn',
|
||||
onComplete: () => {
|
||||
|
|
|
@ -198,21 +198,27 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
return ret;
|
||||
}
|
||||
|
||||
getNextSummonIndex(): integer {
|
||||
getPartyMemberMatchupScores(): [integer, integer][] {
|
||||
const party = this.scene.getEnemyParty();
|
||||
const nonFaintedPartyMembers = party.slice(this.scene.currentBattle.getBattlerCount()).filter(p => !p.isFainted());
|
||||
const partyMemberScores = nonFaintedPartyMembers.map(p => {
|
||||
const playerField = this.scene.getPlayerField();
|
||||
let score = 0;
|
||||
let ret: [integer, integer];
|
||||
for (let playerPokemon of playerField) {
|
||||
score += p.getMatchupScore(playerPokemon);
|
||||
if (playerPokemon.species.legendary)
|
||||
score /= 2;
|
||||
}
|
||||
score /= playerField.length;
|
||||
return [ party.indexOf(p), score ];
|
||||
ret = [ party.indexOf(p), score ];
|
||||
return ret;
|
||||
});
|
||||
|
||||
return partyMemberScores;
|
||||
}
|
||||
|
||||
getSortedPartyMemberMatchupScores(partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores()) {
|
||||
const sortedPartyMemberScores = partyMemberScores.slice(0);
|
||||
sortedPartyMemberScores.sort((a, b) => {
|
||||
const scoreA = a[1];
|
||||
|
@ -220,8 +226,21 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0;
|
||||
});
|
||||
|
||||
return sortedPartyMemberScores;
|
||||
}
|
||||
|
||||
getNextSummonIndex(partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores()): integer {
|
||||
const sortedPartyMemberScores = this.getSortedPartyMemberMatchupScores(partyMemberScores);
|
||||
|
||||
const maxScorePartyMemberIndexes = partyMemberScores.filter(pms => pms[1] === sortedPartyMemberScores[0][1]).map(pms => pms[0]);
|
||||
return maxScorePartyMemberIndexes[Utils.randSeedInt(maxScorePartyMemberIndexes.length)];
|
||||
|
||||
if (maxScorePartyMemberIndexes.length > 1) {
|
||||
let rand: integer;
|
||||
this.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(maxScorePartyMemberIndexes.length), this.scene.currentBattle.turn << 2);
|
||||
return maxScorePartyMemberIndexes[rand];
|
||||
}
|
||||
|
||||
return maxScorePartyMemberIndexes[0];
|
||||
}
|
||||
|
||||
getPartyMemberModifierChanceMultiplier(index: integer): number {
|
||||
|
|
Loading…
Reference in New Issue