This commit is contained in:
xDasone 2023-10-28 14:37:17 -07:00
commit 95f645dd23
38 changed files with 2304 additions and 1694 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

View File

@ -49024,7 +49024,7 @@
} }
}, },
{ {
"filename": "555standard_01.png", "filename": "555_01.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49045,7 +49045,7 @@
} }
}, },
{ {
"filename": "555standard_02.png", "filename": "555_02.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49066,7 +49066,7 @@
} }
}, },
{ {
"filename": "555standard_03.png", "filename": "555_03.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49087,7 +49087,7 @@
} }
}, },
{ {
"filename": "555standard_04.png", "filename": "555_04.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49108,7 +49108,7 @@
} }
}, },
{ {
"filename": "555standard_05.png", "filename": "555_05.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49129,7 +49129,7 @@
} }
}, },
{ {
"filename": "555standard_06.png", "filename": "555_06.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49150,7 +49150,7 @@
} }
}, },
{ {
"filename": "555standard_07.png", "filename": "555_07.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49171,7 +49171,7 @@
} }
}, },
{ {
"filename": "555standard_08.png", "filename": "555_08.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49192,7 +49192,7 @@
} }
}, },
{ {
"filename": "555standard_09.png", "filename": "555_09.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49213,7 +49213,7 @@
} }
}, },
{ {
"filename": "555standard_10.png", "filename": "555_10.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49234,7 +49234,7 @@
} }
}, },
{ {
"filename": "555standard_11.png", "filename": "555_11.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49255,7 +49255,7 @@
} }
}, },
{ {
"filename": "555standard_12.png", "filename": "555_12.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49276,7 +49276,7 @@
} }
}, },
{ {
"filename": "555standard_13.png", "filename": "555_13.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49297,7 +49297,7 @@
} }
}, },
{ {
"filename": "555standard_14.png", "filename": "555_14.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49318,7 +49318,7 @@
} }
}, },
{ {
"filename": "555standard_15.png", "filename": "555_15.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49339,7 +49339,7 @@
} }
}, },
{ {
"filename": "555standard_16.png", "filename": "555_16.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -49360,7 +49360,7 @@
} }
}, },
{ {
"filename": "555standard_17.png", "filename": "555_17.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50809,7 +50809,7 @@
} }
}, },
{ {
"filename": "555standard_18.png", "filename": "555_18.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50830,7 +50830,7 @@
} }
}, },
{ {
"filename": "555standard_19.png", "filename": "555_19.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50851,7 +50851,7 @@
} }
}, },
{ {
"filename": "555standard_20.png", "filename": "555_20.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50872,7 +50872,7 @@
} }
}, },
{ {
"filename": "555standard_21.png", "filename": "555_21.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50893,7 +50893,7 @@
} }
}, },
{ {
"filename": "555standard_22.png", "filename": "555_22.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50914,7 +50914,7 @@
} }
}, },
{ {
"filename": "555standard_23.png", "filename": "555_23.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50935,7 +50935,7 @@
} }
}, },
{ {
"filename": "555standard_24.png", "filename": "555_24.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50956,7 +50956,7 @@
} }
}, },
{ {
"filename": "555standard_25.png", "filename": "555_25.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50977,7 +50977,7 @@
} }
}, },
{ {
"filename": "555standard_26.png", "filename": "555_26.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -50998,7 +50998,7 @@
} }
}, },
{ {
"filename": "555standard_27.png", "filename": "555_27.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51019,7 +51019,7 @@
} }
}, },
{ {
"filename": "555standard_28.png", "filename": "555_28.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51040,7 +51040,7 @@
} }
}, },
{ {
"filename": "555standard_29.png", "filename": "555_29.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51061,7 +51061,7 @@
} }
}, },
{ {
"filename": "555standard_30.png", "filename": "555_30.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51082,7 +51082,7 @@
} }
}, },
{ {
"filename": "555standard_31.png", "filename": "555_31.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51103,7 +51103,7 @@
} }
}, },
{ {
"filename": "555standard_32.png", "filename": "555_32.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51124,7 +51124,7 @@
} }
}, },
{ {
"filename": "555standard_33.png", "filename": "555_33.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {
@ -51145,7 +51145,7 @@
} }
}, },
{ {
"filename": "555standard_34.png", "filename": "555_34.png",
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"sourceSize": { "sourceSize": {

View File

@ -119,7 +119,18 @@ export class Arena {
getFormIndex(species: PokemonSpecies) { getFormIndex(species: PokemonSpecies) {
if (!species.canChangeForm && species.forms?.length) if (!species.canChangeForm && species.forms?.length)
return Utils.randSeedInt(species.forms.length); // TODO: Base on biome return Utils.randSeedInt(species.forms.length);
switch (species.speciesId) {
case Species.BURMY:
case Species.WORMADAM:
switch (this.biomeType) {
case Biome.BEACH:
return 1;
case Biome.CITY:
return 2;
}
break;
}
return 0; return 0;
} }

View File

@ -16,7 +16,7 @@ import { EvolutionPhase } from "./evolution-phase";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "./battle-phase";
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat"; import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./data/battle-stat";
import { Biome, biomeLinks } from "./data/biome"; import { Biome, biomeLinks } from "./data/biome";
import { ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import { ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, TmModifierType, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag"; import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag";
import { getPokemonMessage } from "./messages"; import { getPokemonMessage } from "./messages";
@ -246,7 +246,7 @@ export class EncounterPhase extends BattlePhase {
battle.enemyParty[e] = battle.trainer.genPartyMember(e); battle.enemyParty[e] = battle.trainer.genPartyMember(e);
else { else {
const enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, null, true); const enemySpecies = this.scene.randomSpecies(battle.waveIndex, level, null, true);
battle.enemyParty[e] = new EnemyPokemon(this.scene, enemySpecies, level); battle.enemyParty[e] = new EnemyPokemon(this.scene, enemySpecies, level, false);
} }
} }
const enemyPokemon = this.scene.getEnemyParty()[e]; const enemyPokemon = this.scene.getEnemyParty()[e];
@ -256,7 +256,7 @@ export class EncounterPhase extends BattlePhase {
this.scene.gameData.setPokemonSeen(enemyPokemon); this.scene.gameData.setPokemonSeen(enemyPokemon);
} }
if (this.scene.gameMode === GameMode.CLASSIC && battle.waveIndex === 200 && enemyPokemon.species.speciesId === Species.ETERNATUS) if (this.scene.gameMode === GameMode.CLASSIC && (battle.waveIndex === 200 || !(battle.waveIndex % 250)) && enemyPokemon.species.speciesId === Species.ETERNATUS)
enemyPokemon.formIndex = 1; enemyPokemon.formIndex = 1;
loadEnemyAssets.push(enemyPokemon.loadAssets()); loadEnemyAssets.push(enemyPokemon.loadAssets());
@ -635,7 +635,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
this.scene.field.add(pokemon); this.scene.field.add(pokemon);
if (!this.player) { if (!this.player) {
const playerPokemon = this.scene.getPlayerPokemon() as Pokemon; const playerPokemon = this.scene.getPlayerPokemon() as Pokemon;
if (playerPokemon.visible) if (playerPokemon?.visible)
this.scene.field.moveBelow(pokemon, playerPokemon); this.scene.field.moveBelow(pokemon, playerPokemon);
this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id); this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id);
this.scene.updateModifiers(false); this.scene.updateModifiers(false);
@ -937,6 +937,15 @@ export class CommandPhase extends FieldPhase {
start() { start() {
super.start(); super.start();
if (this.fieldIndex) {
const allyCommand = this.scene.currentBattle.turnCommands[this.fieldIndex - 1];
if (allyCommand.command === Command.BALL || allyCommand.command === Command.RUN)
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: allyCommand.command, skip: true };
}
if (this.scene.currentBattle.turnCommands[this.fieldIndex]?.skip)
return this.end();
const playerPokemon = this.scene.getPlayerField()[this.fieldIndex]; const playerPokemon = this.scene.getPlayerField()[this.fieldIndex];
const moveQueue = playerPokemon.getMoveQueue(); const moveQueue = playerPokemon.getMoveQueue();
@ -968,10 +977,12 @@ export class CommandPhase extends FieldPhase {
switch (command) { switch (command) {
case Command.FIGHT: case Command.FIGHT:
if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean)) { let useStruggle = false;
if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) {
const moveId = !useStruggle ? playerPokemon.moveset[cursor].moveId : Moves.STRUGGLE;
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor,
move: cursor > -1 ? { move: playerPokemon.moveset[cursor].moveId, targets: [] } : null, args: args }; // TODO: Struggle logic move: cursor > -1 ? { move: moveId, targets: [] } : null, args: args };
const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, cursor > -1 ? playerPokemon.moveset[cursor].moveId : Moves.NONE) : args[2]; const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, cursor > -1 ? moveId : Moves.NONE) : args[2];
console.log(moveTargets, playerPokemon.name); console.log(moveTargets, playerPokemon.name);
if (moveTargets.targets.length <= 1 || moveTargets.multiple) if (moveTargets.targets.length <= 1 || moveTargets.multiple)
turnCommand.move.targets = moveTargets.targets; turnCommand.move.targets = moveTargets.targets;
@ -989,13 +1000,12 @@ export class CommandPhase extends FieldPhase {
}, null, true); }, null, true);
} }
} }
break; break;
case Command.BALL: case Command.BALL:
if (this.scene.arena.biomeType === Biome.END) { if (this.scene.arena.biomeType === Biome.END) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`A strange force\nprevents using Poké Balls.`, null, () => { this.scene.ui.showText(`An unseen force\nprevents using Poké Balls.`, null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
@ -1006,21 +1016,39 @@ export class CommandPhase extends FieldPhase {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else if (cursor < 4) { } else {
const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex()); const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex());
if (targets.length > 1) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`You can only throw a Poké Ball\nwhen there is one Pokémon remaining!`, null, () => {
this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else if (cursor < 4) {
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor }; this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor };
this.scene.currentBattle.turnPokeballCounts[cursor as PokeballType]--;
if (targets.length > 1) if (targets.length > 1)
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
else else {
this.scene.currentBattle.turnCommands[this.fieldIndex].targets = targets; this.scene.currentBattle.turnCommands[this.fieldIndex].targets = targets;
if (this.fieldIndex)
this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true;
}
success = true; success = true;
} }
}
break; break;
case Command.POKEMON: case Command.POKEMON:
case Command.RUN: case Command.RUN:
const isSwitch = command === Command.POKEMON; const isSwitch = command === Command.POKEMON;
if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) { if (!isSwitch && this.scene.arena.biomeType === Biome.END) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`An unseen force\nprevents escape.`, null, () => {
this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true);
} else if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`You can't run\nfrom a trainer battle!`, null, () => { this.scene.ui.showText(`You can't run\nfrom a trainer battle!`, null, () => {
@ -1038,6 +1066,8 @@ export class CommandPhase extends FieldPhase {
? { command: Command.POKEMON, cursor: cursor, args: args } ? { command: Command.POKEMON, cursor: cursor, args: args }
: { command: Command.RUN }; : { command: Command.RUN };
success = true; success = true;
if (this.fieldIndex)
this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true;
} else if (trapTag) { } else if (trapTag) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
@ -1058,9 +1088,6 @@ export class CommandPhase extends FieldPhase {
cancel() { cancel() {
if (this.fieldIndex) { if (this.fieldIndex) {
const lastCommand = this.scene.currentBattle.turnCommands[0];
if (lastCommand.command === Command.BALL)
this.scene.currentBattle.turnPokeballCounts[lastCommand.cursor]++;
this.scene.unshiftPhase(new CommandPhase(this.scene, 0)); this.scene.unshiftPhase(new CommandPhase(this.scene, 0));
this.scene.unshiftPhase(new CommandPhase(this.scene, 1)); this.scene.unshiftPhase(new CommandPhase(this.scene, 1));
this.end(); this.end();
@ -1116,12 +1143,12 @@ export class SelectTargetPhase extends PokemonPhase {
this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (cursor: integer) => { this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (cursor: integer) => {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
if (cursor === -1) { if (cursor === -1) {
if (turnCommand.command === Command.BALL)
this.scene.currentBattle.turnPokeballCounts[turnCommand.cursor]++;
this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.currentBattle.turnCommands[this.fieldIndex] = null;
this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex)); this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex));
} else } else
turnCommand.targets = [ cursor ]; turnCommand.targets = [ cursor ];
if (turnCommand.command === Command.BALL && this.fieldIndex)
this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true;
this.end(); this.end();
}); });
} }
@ -1168,6 +1195,9 @@ export class TurnStartPhase extends FieldPhase {
const pokemon = field[o]; const pokemon = field[o];
const turnCommand = this.scene.currentBattle.turnCommands[o]; const turnCommand = this.scene.currentBattle.turnCommands[o];
if (turnCommand.skip)
continue;
switch (turnCommand.command) { switch (turnCommand.command) {
case Command.FIGHT: case Command.FIGHT:
const queuedMove = turnCommand.move; const queuedMove = turnCommand.move;
@ -1263,7 +1293,7 @@ export class BattleEndPhase extends BattlePhase {
pokemon.resetBattleSummonData(); pokemon.resetBattleSummonData();
} }
this.scene.clearEnemyModifiers(); this.scene.clearEnemyHeldItemModifiers();
const lapsingModifiers = this.scene.findModifiers(m => m instanceof LapsingPersistentModifier) as LapsingPersistentModifier[]; const lapsingModifiers = this.scene.findModifiers(m => m instanceof LapsingPersistentModifier) as LapsingPersistentModifier[];
for (let m of lapsingModifiers) { for (let m of lapsingModifiers) {
@ -2141,9 +2171,7 @@ export class ModifierRewardPhase extends BattlePhase {
constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc) { constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc) {
super(scene); super(scene);
this.modifierType = modifierTypeFunc(); this.modifierType = getModifierType(modifierTypeFunc);
if (!this.modifierType.id)
this.modifierType.id = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifierTypeFunc);
} }
start() { start() {
@ -2664,7 +2692,7 @@ export class AttemptCapturePhase extends PokemonPhase {
this.scene.getPlayerField().filter(p => p.isActive()).forEach(playerPokemon => playerPokemon.removeTagsBySourceId(pokemon.id)); this.scene.getPlayerField().filter(p => p.isActive()).forEach(playerPokemon => playerPokemon.removeTagsBySourceId(pokemon.id));
pokemon.hp = 0; pokemon.hp = 0;
pokemon.trySetStatus(StatusEffect.FAINT); pokemon.trySetStatus(StatusEffect.FAINT);
this.scene.clearEnemyModifiers(); this.scene.clearEnemyHeldItemModifiers();
this.scene.field.remove(pokemon, true); this.scene.field.remove(pokemon, true);
}; };
const addToParty = () => { const addToParty = () => {

View File

@ -16,7 +16,7 @@ import { GameData } from './system/game-data';
import StarterSelectUiHandler from './ui/starter-select-ui-handler'; import StarterSelectUiHandler from './ui/starter-select-ui-handler';
import { TextStyle, addTextObject } from './ui/text'; import { TextStyle, addTextObject } from './ui/text';
import { Moves, initMoves } from './data/move'; import { Moves, initMoves } from './data/move';
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type'; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getModifierType, modifierTypes } from './modifier/modifier-type';
import AbilityBar from './ui/ability-bar'; import AbilityBar from './ui/ability-bar';
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability';
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
@ -104,7 +104,7 @@ export default class BattleScene extends Phaser.Scene {
private modifierBar: ModifierBar; private modifierBar: ModifierBar;
private enemyModifierBar: ModifierBar; private enemyModifierBar: ModifierBar;
private modifiers: PersistentModifier[]; private modifiers: PersistentModifier[];
private enemyModifiers: PokemonHeldItemModifier[]; private enemyModifiers: PersistentModifier[];
public uiContainer: Phaser.GameObjects.Container; public uiContainer: Phaser.GameObjects.Container;
public ui: UI; public ui: UI;
@ -1148,7 +1148,7 @@ export default class BattleScene extends Phaser.Scene {
}); });
} }
addEnemyModifier(itemModifier: PokemonHeldItemModifier): Promise<void> { addEnemyModifier(itemModifier: PersistentModifier): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
itemModifier.add(this.enemyModifiers, false); itemModifier.add(this.enemyModifiers, false);
this.updateModifiers(false).then(() => resolve()); this.updateModifiers(false).then(() => resolve());
@ -1206,7 +1206,7 @@ export default class BattleScene extends Phaser.Scene {
removePartyMemberModifiers(partyMemberIndex: integer): Promise<void> { removePartyMemberModifiers(partyMemberIndex: integer): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
const pokemonId = this.getParty()[partyMemberIndex].id; const pokemonId = this.getParty()[partyMemberIndex].id;
const modifiersToRemove = this.modifiers.filter(m => (m instanceof PokemonHeldItemModifier) && (m as PokemonHeldItemModifier).pokemonId === pokemonId); const modifiersToRemove = this.modifiers.filter(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === pokemonId);
for (let m of modifiersToRemove) for (let m of modifiersToRemove)
this.modifiers.splice(this.modifiers.indexOf(m), 1); this.modifiers.splice(this.modifiers.indexOf(m), 1);
this.updateModifiers().then(() => resolve()); this.updateModifiers().then(() => resolve());
@ -1233,12 +1233,10 @@ export default class BattleScene extends Phaser.Scene {
for (let c = 0; c < chances; c++) { for (let c = 0; c < chances; c++) {
if (!Utils.randSeedInt(modifierChance)) if (!Utils.randSeedInt(modifierChance))
count++; count++;
if (count === 12)
break;
} }
if (isBoss) if (isBoss)
count = Math.max(count, Math.floor(chances / 2)); count = Math.max(count, Math.floor(chances / 2));
getEnemyModifierTypesForWave(waveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD) getEnemyModifierTypesForWave(waveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, this.gameMode)
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false)); .map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false));
}); });
@ -1246,8 +1244,17 @@ export default class BattleScene extends Phaser.Scene {
}); });
} }
clearEnemyModifiers(): void { generateEnemyBuffModifier(): void{
this.enemyModifiers.splice(0, this.enemyModifiers.length); const enemyBuffModifierTypes = [ modifierTypes.ENEMY_DAMAGE_BOOSTER, modifierTypes.ENEMY_DAMAGE_REDUCTION ];
this.executeWithSeedOffset(() => {
(getModifierType(Phaser.Math.RND.pick(enemyBuffModifierTypes)).newModifier() as PersistentModifier).add(this.enemyModifiers, false);
}, Math.floor(this.currentBattle.waveIndex / 50));
}
clearEnemyHeldItemModifiers(): void {
const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier);
for (let m of modifiersToRemove)
this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1);
this.updateModifiers(false).then(() => this.updateUIPositions()); this.updateModifiers(false).then(() => this.updateUIPositions());
} }

View File

@ -24,6 +24,7 @@ export interface TurnCommand {
cursor?: integer; cursor?: integer;
move?: QueuedMove; move?: QueuedMove;
targets?: BattlerIndex[]; targets?: BattlerIndex[];
skip?: boolean;
args?: any[]; args?: any[];
}; };
@ -42,7 +43,6 @@ export default class Battle {
public started: boolean; public started: boolean;
public turn: integer; public turn: integer;
public turnCommands: TurnCommands; public turnCommands: TurnCommands;
public turnPokeballCounts: PokeballCounts;
public playerParticipantIds: Set<integer> = new Set<integer>(); public playerParticipantIds: Set<integer> = new Set<integer>();
public escapeAttempts: integer = 0; public escapeAttempts: integer = 0;
public lastMove: Moves; public lastMove: Moves;
@ -94,7 +94,6 @@ export default class Battle {
incrementTurn(scene: BattleScene): void { incrementTurn(scene: BattleScene): void {
this.turn++; this.turn++;
this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ])); this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ]));
this.turnPokeballCounts = Object.assign({}, scene.pokeballCounts);
} }
addParticipant(playerPokemon: PlayerPokemon): void { addParticipant(playerPokemon: PlayerPokemon): void {

View File

@ -2,7 +2,7 @@ import Pokemon, { HitResult, PokemonMove } from "../pokemon";
import { Type } from "./type"; import { Type } from "./type";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { BattleStat, getBattleStatName } from "./battle-stat"; import { BattleStat, getBattleStatName } from "./battle-stat";
import { DamagePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../battle-phases"; import { DamagePhase, ObtainStatusEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../battle-phases";
import { getPokemonMessage } from "../messages"; import { getPokemonMessage } from "../messages";
import { Weather, WeatherType } from "./weather"; import { Weather, WeatherType } from "./weather";
import { BattlerTag, BattlerTagType } from "./battler-tag"; import { BattlerTag, BattlerTagType } from "./battler-tag";
@ -290,9 +290,9 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
} }
applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (move.getMove().hasFlag(MoveFlags.MAKES_CONTACT) && Utils.randInt(100) < this.chance) { if (move.getMove().hasFlag(MoveFlags.MAKES_CONTACT) && Utils.randInt(100) < this.chance && !pokemon.status) {
const effect = this.effects.length === 1 ? this.effects[0] : this.effects[Utils.randInt(this.effects.length)]; const effect = this.effects.length === 1 ? this.effects[0] : this.effects[Utils.randInt(this.effects.length)];
return attacker.trySetStatus(effect); pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, attacker.getBattlerIndex(), effect));
} }
return false; return false;

View File

@ -13,6 +13,7 @@ import { BlockRecoilDamageAttr, applyAbAttrs } from "./ability";
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier } from "../modifier/modifier";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "../battle";
import { Stat } from "./pokemon-stat"; import { Stat } from "./pokemon-stat";
import { Species } from "./species";
export enum MoveCategory { export enum MoveCategory {
PHYSICAL, PHYSICAL,
@ -977,7 +978,7 @@ export class RandomLevelDamageAttr extends FixedDamageAttr {
} }
getDamage(user: Pokemon, target: Pokemon, move: Move): number { getDamage(user: Pokemon, target: Pokemon, move: Move): number {
return user.level * (Utils.randIntRange(50, 150) * 0.01); return Math.max(Math.floor(user.level * (Utils.randIntRange(50, 150) * 0.01)), 1);
} }
} }
@ -1155,18 +1156,22 @@ export class MultiHitAttr extends MoveAttr {
export class StatusEffectAttr extends MoveEffectAttr { export class StatusEffectAttr extends MoveEffectAttr {
public effect: StatusEffect; public effect: StatusEffect;
public cureTurn: integer; public cureTurn: integer;
public overrideStatus: boolean;
constructor(effect: StatusEffect, selfTarget?: boolean, cureTurn?: integer) { constructor(effect: StatusEffect, selfTarget?: boolean, cureTurn?: integer, overrideStatus?: boolean) {
super(selfTarget, MoveEffectTrigger.HIT); super(selfTarget, MoveEffectTrigger.HIT);
this.effect = effect; this.effect = effect;
this.cureTurn = cureTurn; this.cureTurn = cureTurn;
this.overrideStatus = !!overrideStatus;
} }
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const statusCheck = move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance; const statusCheck = move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance;
if (statusCheck) { if (statusCheck) {
const pokemon = this.selfTarget ? user : target; const pokemon = this.selfTarget ? user : target;
if (pokemon.status)
pokemon.resetStatus();
if (!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) { if (!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) {
user.scene.unshiftPhase(new ObtainStatusEffectPhase(user.scene, pokemon.getBattlerIndex(), this.effect, this.cureTurn)); user.scene.unshiftPhase(new ObtainStatusEffectPhase(user.scene, pokemon.getBattlerIndex(), this.effect, this.cureTurn));
return true; return true;
@ -1296,6 +1301,8 @@ export class OneHitKOAttr extends MoveEffectAttr {
} }
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (target.species.speciesId === Species.ETERNATUS && target.formIndex === 1)
return false;
target.damage(target.hp, true); target.damage(target.hp, true);
user.scene.queueMessage('It\'s a one-hit KO!'); user.scene.queueMessage('It\'s a one-hit KO!');
return true; return true;
@ -2299,7 +2306,7 @@ export function initMoves() {
.attr(StatusEffectAttr, StatusEffect.PARALYSIS), .attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new AttackMove(Moves.SCRATCH, "Scratch", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 0, 1), new AttackMove(Moves.SCRATCH, "Scratch", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 0, 1),
new AttackMove(Moves.VISE_GRIP, "Vise Grip", Type.NORMAL, MoveCategory.PHYSICAL, 55, 100, 30, -1, "", -1, 0, 1), new AttackMove(Moves.VISE_GRIP, "Vise Grip", Type.NORMAL, MoveCategory.PHYSICAL, 55, 100, 30, -1, "", -1, 0, 1),
new AttackMove(Moves.GUILLOTINE, "Guillotine", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1) new AttackMove(Moves.GUILLOTINE, "Guillotine", Type.NORMAL, MoveCategory.PHYSICAL, 250, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1)
.attr(OneHitKOAttr), .attr(OneHitKOAttr),
new AttackMove(Moves.RAZOR_WIND, "Razor Wind", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "Charges on first turn, attacks on second. High critical hit ratio.", -1, 0, 1) new AttackMove(Moves.RAZOR_WIND, "Razor Wind", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "Charges on first turn, attacks on second. High critical hit ratio.", -1, 0, 1)
.attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, 'whipped\nup a whirlwind!') .attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, 'whipped\nup a whirlwind!')
@ -2340,7 +2347,7 @@ export function initMoves() {
new AttackMove(Moves.HORN_ATTACK, "Horn Attack", Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 25, -1, "", -1, 0, 1), new AttackMove(Moves.HORN_ATTACK, "Horn Attack", Type.NORMAL, MoveCategory.PHYSICAL, 65, 100, 25, -1, "", -1, 0, 1),
new AttackMove(Moves.FURY_ATTACK, "Fury Attack", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 1) new AttackMove(Moves.FURY_ATTACK, "Fury Attack", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 1)
.attr(MultiHitAttr), .attr(MultiHitAttr),
new AttackMove(Moves.HORN_DRILL, "Horn Drill", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1) new AttackMove(Moves.HORN_DRILL, "Horn Drill", Type.NORMAL, MoveCategory.PHYSICAL, 250, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1)
.attr(OneHitKOAttr), .attr(OneHitKOAttr),
new AttackMove(Moves.TACKLE, "Tackle", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 0, 1), new AttackMove(Moves.TACKLE, "Tackle", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 0, 1),
new AttackMove(Moves.BODY_SLAM, "Body Slam", Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 66, "May paralyze opponent.", 30, 0, 1) new AttackMove(Moves.BODY_SLAM, "Body Slam", Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 66, "May paralyze opponent.", 30, 0, 1)
@ -2478,7 +2485,7 @@ export function initMoves() {
.attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true) .attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true)
.makesContact(false) .makesContact(false)
.target(MoveTarget.ALL_NEAR_OTHERS), .target(MoveTarget.ALL_NEAR_OTHERS),
new AttackMove(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1) new AttackMove(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, 250, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1)
.attr(OneHitKOAttr) .attr(OneHitKOAttr)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, 55, "Digs underground on first turn, attacks on second. Can also escape from caves.", -1, 0, 1) new AttackMove(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, 55, "Digs underground on first turn, attacks on second. Can also escape from caves.", -1, 0, 1)
@ -2632,7 +2639,7 @@ export function initMoves() {
.attr(MultiHitAttr, MultiHitType._2) .attr(MultiHitAttr, MultiHitType._2)
.makesContact(false), .makesContact(false),
new SelfStatusMove(Moves.REST, "Rest", Type.PSYCHIC, -1, 5, 85, "User sleeps for 2 turns, but user is fully healed.", -1, 0, 1) new SelfStatusMove(Moves.REST, "Rest", Type.PSYCHIC, -1, 5, 85, "User sleeps for 2 turns, but user is fully healed.", -1, 0, 1)
.attr(StatusEffectAttr, StatusEffect.SLEEP, true, 3) .attr(StatusEffectAttr, StatusEffect.SLEEP, true, 3, true)
.attr(HealAttr, 1, true) .attr(HealAttr, 1, true)
.condition((user: Pokemon, target: Pokemon, move: Move) => user.status?.effect !== StatusEffect.SLEEP), .condition((user: Pokemon, target: Pokemon, move: Move) => user.status?.effect !== StatusEffect.SLEEP),
new AttackMove(Moves.ROCK_SLIDE, "Rock Slide", Type.ROCK, MoveCategory.PHYSICAL, 75, 90, 10, 86, "May cause flinching.", 30, 0, 1) new AttackMove(Moves.ROCK_SLIDE, "Rock Slide", Type.ROCK, MoveCategory.PHYSICAL, 75, 90, 10, 86, "May cause flinching.", 30, 0, 1)
@ -2744,9 +2751,9 @@ export function initMoves() {
new StatusMove(Moves.SANDSTORM, "Sandstorm", Type.ROCK, -1, 10, 51, "Creates a sandstorm for 5 turns.", -1, 0, 2) new StatusMove(Moves.SANDSTORM, "Sandstorm", Type.ROCK, -1, 10, 51, "Creates a sandstorm for 5 turns.", -1, 0, 2)
.attr(WeatherChangeAttr, WeatherType.SANDSTORM) .attr(WeatherChangeAttr, WeatherType.SANDSTORM)
.target(MoveTarget.BOTH_SIDES), .target(MoveTarget.BOTH_SIDES),
new AttackMove(Moves.GIGA_DRAIN, "Giga Drain", Type.GRASS, MoveCategory.SPECIAL, 75, 100, 10, 111, "User recovers half the HP inflicted on opponent.", -1, 4, 2) new AttackMove(Moves.GIGA_DRAIN, "Giga Drain", Type.GRASS, MoveCategory.SPECIAL, 75, 100, 10, 111, "User recovers half the HP inflicted on opponent.", -1, 0, 2)
.attr(HitHealAttr), .attr(HitHealAttr),
new SelfStatusMove(Moves.ENDURE, "Endure (N)", Type.NORMAL, -1, 10, 47, "Always left with at least 1 HP, but may fail if used consecutively.", -1, 0, 2), new SelfStatusMove(Moves.ENDURE, "Endure (N)", Type.NORMAL, -1, 10, 47, "Always left with at least 1 HP, but may fail if used consecutively.", -1, 4, 2),
new StatusMove(Moves.CHARM, "Charm", Type.FAIRY, 100, 20, 2, "Sharply lowers opponent's Attack.", -1, 0, 2) new StatusMove(Moves.CHARM, "Charm", Type.FAIRY, 100, 20, 2, "Sharply lowers opponent's Attack.", -1, 0, 2)
.attr(StatChangeAttr, BattleStat.ATK, -2), .attr(StatChangeAttr, BattleStat.ATK, -2),
new AttackMove(Moves.ROLLOUT, "Rollout", Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, "Doubles in power each turn for 5 turns.", -1, 0, 2) new AttackMove(Moves.ROLLOUT, "Rollout", Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, "Doubles in power each turn for 5 turns.", -1, 0, 2)
@ -2919,7 +2926,7 @@ export function initMoves() {
new AttackMove(Moves.SECRET_POWER, "Secret Power (N)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Effects of the attack vary with the location.", 30, 0, 3) new AttackMove(Moves.SECRET_POWER, "Secret Power (N)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Effects of the attack vary with the location.", 30, 0, 3)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, "Dives underwater on first turn, attacks on second turn.", -1, 0, 3) new AttackMove(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, "Dives underwater on first turn, attacks on second turn.", -1, 0, 3)
.attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!') .attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!', BattlerTagType.UNDERGROUND)
.ignoresVirtual(), .ignoresVirtual(),
new AttackMove(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 3) new AttackMove(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 3)
.attr(MultiHitAttr), .attr(MultiHitAttr),
@ -3000,7 +3007,7 @@ export function initMoves() {
new AttackMove(Moves.SAND_TOMB, "Sand Tomb", Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 3) new AttackMove(Moves.SAND_TOMB, "Sand Tomb", Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 3)
.attr(TrapAttr, BattlerTagType.SAND_TOMB) .attr(TrapAttr, BattlerTagType.SAND_TOMB)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 3) new AttackMove(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, 250, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 3)
.attr(OneHitKOAttr), .attr(OneHitKOAttr),
new AttackMove(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "May lower opponent's Accuracy.", 30, 0, 3) new AttackMove(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "May lower opponent's Accuracy.", 30, 0, 3)
.attr(StatChangeAttr, BattleStat.ACC, -1) .attr(StatChangeAttr, BattleStat.ACC, -1)

View File

@ -521,7 +521,7 @@ function getGymLeaderPartyTemplate(scene: BattleScene) {
function getRandomPartyMemberFunc(speciesPool: Species[], postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc { function getRandomPartyMemberFunc(speciesPool: Species[], postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc {
return (scene: BattleScene, level: integer) => { return (scene: BattleScene, level: integer) => {
const species = getPokemonSpecies(Phaser.Math.RND.pick(speciesPool)).getSpeciesForLevel(level, true); const species = getPokemonSpecies(Phaser.Math.RND.pick(speciesPool)).getSpeciesForLevel(level, true);
const ret = new EnemyPokemon(scene, getPokemonSpecies(species), level); const ret = new EnemyPokemon(scene, getPokemonSpecies(species), level, true);
if (postProcess) if (postProcess)
postProcess(ret); postProcess(ret);
return ret; return ret;
@ -532,7 +532,7 @@ function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilt
const originalSpeciesFilter = speciesFilter; const originalSpeciesFilter = speciesFilter;
speciesFilter = (species: PokemonSpecies) => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical) && originalSpeciesFilter(species); speciesFilter = (species: PokemonSpecies) => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical) && originalSpeciesFilter(species);
return (scene: BattleScene, level: integer) => { return (scene: BattleScene, level: integer) => {
const ret = new EnemyPokemon(scene, scene.randomSpecies(scene.currentBattle.waveIndex, level, speciesFilter), level); const ret = new EnemyPokemon(scene, scene.randomSpecies(scene.currentBattle.waveIndex, level, speciesFilter), level, true);
if (postProcess) if (postProcess)
postProcess(ret); postProcess(ret);
return ret; return ret;
@ -735,7 +735,7 @@ export const trainerConfigs: TrainerConfigs = {
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540) .setSpeciesFilter(species => species.baseTotal >= 540)
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ])), .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], p => p.formIndex = 0)),
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setBoss().setStaticParty().setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6) [TrainerType.RIVAL_6]: new TrainerConfig(++t).setBoss().setStaticParty().setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ])) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))

View File

@ -660,6 +660,9 @@ export const modifierTypes = {
GOLDEN_POKEBALL: () => new ModifierType(`Golden ${getPokeballName(PokeballType.POKEBALL)}`, 'Adds 1 extra item option at the end of every battle', GOLDEN_POKEBALL: () => new ModifierType(`Golden ${getPokeballName(PokeballType.POKEBALL)}`, 'Adds 1 extra item option at the end of every battle',
(type, _args) => new Modifiers.ExtraModifierModifier(type), 'pb_gold', null, 'pb_bounce_1'), (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')
}; };
const modifierPool = { const modifierPool = {
@ -797,6 +800,13 @@ const trainerModifierPool = {
].map(m => { m.setTier(ModifierTier.MASTER); return m; }) ].map(m => { m.setTier(ModifierTier.MASTER); return m; })
}; };
export function getModifierType(modifierTypeFunc: ModifierTypeFunc): ModifierType {
const modifierType = modifierTypeFunc();
if (!modifierType.id)
modifierType.id = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifierTypeFunc);
return modifierType;
}
let modifierPoolThresholds = {}; let modifierPoolThresholds = {};
let ignoredPoolIndexes = {}; let ignoredPoolIndexes = {};
@ -813,8 +823,8 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
let i = 0; let i = 0;
pool[t].reduce((total: integer, modifierType: WeightedModifierType) => { pool[t].reduce((total: integer, modifierType: WeightedModifierType) => {
const weightedModifierType = modifierType as WeightedModifierType; const weightedModifierType = modifierType as WeightedModifierType;
const existingModifier = party[0].scene.findModifier(m => (m.type.generatorId || m.type.id) === weightedModifierType.modifierType.id); const existingModifiers = party[0].scene.findModifiers(m => (m.type.generatorId || m.type.id) === weightedModifierType.modifierType.id, player);
const weight = !existingModifier || existingModifier.stackCount < existingModifier.getMaxStackCount() const weight = !existingModifiers.length || existingModifiers.filter(m => m.stackCount < m.getMaxStackCount())
? weightedModifierType.weight instanceof Function ? weightedModifierType.weight instanceof Function
? (weightedModifierType.weight as Function)(party) ? (weightedModifierType.weight as Function)(party)
: weightedModifierType.weight as integer : weightedModifierType.weight as integer
@ -858,13 +868,10 @@ export function getPlayerModifierTypeOptionsForWave(waveIndex: integer, count: i
return options; return options;
} }
export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER): PokemonHeldItemModifierType[] { 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); const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType).type as PokemonHeldItemModifierType);
if (waveIndex === 200) { if ((gameMode === GameMode.CLASSIC && waveIndex === 200) || !(waveIndex % 1000))
const miniBlackHole = modifierTypes.MINI_BLACK_HOLE(); ret.push(getModifierType(modifierTypes.MINI_BLACK_HOLE) as PokemonHeldItemModifierType);
miniBlackHole.id = 'MINI_BLACK_HOLE';
ret.push(miniBlackHole);
}
return ret; return ret;
} }

View File

@ -1,5 +1,5 @@
import * as ModifierTypes from './modifier-type'; import * as ModifierTypes from './modifier-type';
import { LearnMovePhase, LevelUpPhase, PokemonHealPhase } from "../battle-phases"; import { LearnMovePhase, LevelUpPhase, ObtainStatusEffectPhase, PokemonHealPhase } from "../battle-phases";
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { getLevelTotalExp } from "../data/exp"; import { getLevelTotalExp } from "../data/exp";
import { PokeballType } from "../data/pokeball"; import { PokeballType } from "../data/pokeball";
@ -15,6 +15,7 @@ import { TempBattleStat } from '../data/temp-battle-stat';
import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry'; import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
import { Species } from '../data/species'; import { Species } from '../data/species';
import { BattleType } from '../battle'; import { BattleType } from '../battle';
import { StatusEffect } from '../data/status-effect';
type ModifierType = ModifierTypes.ModifierType; type ModifierType = ModifierTypes.ModifierType;
export type ModifierPredicate = (modifier: Modifier) => boolean; export type ModifierPredicate = (modifier: Modifier) => boolean;
@ -671,13 +672,13 @@ export class PreserveBerryModifier extends PersistentModifier {
apply(args: any[]): boolean { apply(args: any[]): boolean {
if (!(args[0] as Utils.BooleanHolder).value) if (!(args[0] as Utils.BooleanHolder).value)
(args[0] as Utils.BooleanHolder).value = this.getStackCount() === this.getMaxStackCount() || Utils.randInt(this.getMaxStackCount()) < this.getStackCount(); (args[0] as Utils.BooleanHolder).value = Utils.randInt(this.getMaxStackCount()) < this.getStackCount();
return true; return true;
} }
getMaxStackCount(): integer { getMaxStackCount(): integer {
return 4; return 3;
} }
} }
@ -1225,3 +1226,87 @@ export class ExtraModifierModifier extends PersistentModifier {
return 3; return 3;
} }
} }
export abstract class EnemyPersistentModifer extends PersistentModifier {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);
}
}
export class EnemyDamageBoosterModifier extends EnemyPersistentModifer {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);
}
match(modifier: Modifier): boolean {
return modifier instanceof EnemyDamageBoosterModifier;
}
clone(): EnemyDamageBoosterModifier {
return new EnemyDamageBoosterModifier(this.type, this.stackCount);
}
apply(args: any[]): boolean {
(args[0] as Utils.NumberHolder).value = Math.floor((args[0] as Utils.NumberHolder).value * (1 + 0.2 * this.getStackCount()));
return true;
}
getMaxStackCount(): number {
return 5;
}
}
export class EnemyDamageReducerModifier extends EnemyPersistentModifer {
constructor(type: ModifierType, stackCount?: integer) {
super(type, stackCount);
}
match(modifier: Modifier): boolean {
return modifier instanceof EnemyDamageReducerModifier;
}
clone(): EnemyDamageReducerModifier {
return new EnemyDamageReducerModifier(this.type, this.stackCount);
}
apply(args: any[]): boolean {
(args[0] as Utils.NumberHolder).value = Math.floor((args[0] as Utils.NumberHolder).value * (1 - 0.2 * this.getStackCount()));
return true;
}
getMaxStackCount(): number {
return 5;
}
}
export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifer {
public effect: StatusEffect;
constructor(type: ModifierType, effect: StatusEffect, stackCount?: integer) {
super(type, stackCount);
this.effect = effect;
}
match(modifier: Modifier): boolean {
return modifier instanceof EnemyAttackStatusEffectChanceModifier && modifier.effect === this.effect;
}
clone(): EnemyDamageReducerModifier {
return new EnemyAttackStatusEffectChanceModifier(this.type, this.effect, this.stackCount);
}
apply(args: any[]): boolean {
const target = (args[0] as Pokemon);
if (Utils.randInt(10) < this.getStackCount())
target.scene.unshiftPhase(new ObtainStatusEffectPhase(target.scene, target.getBattlerIndex(), this.effect));
return true;
}
getMaxStackCount(): number {
return 5;
}
}

View File

@ -8,7 +8,7 @@ import * as Utils from './utils';
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier } from './data/type'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier } from './data/type';
import { getLevelTotalExp } from './data/exp'; import { getLevelTotalExp } from './data/exp';
import { Stat } from './data/pokemon-stat'; import { Stat } from './data/pokemon-stat';
import { AttackTypeBoosterModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier } from './modifier/modifier'; import { AttackTypeBoosterModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier } from './modifier/modifier';
import { PokeballType } from './data/pokeball'; import { PokeballType } from './data/pokeball';
import { Gender } from './data/gender'; import { Gender } from './data/gender';
import { initMoveAnim, loadMoveAnimAssets } from './data/battle-anims'; import { initMoveAnim, loadMoveAnimAssets } from './data/battle-anims';
@ -125,23 +125,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16)); if (this.shiny === undefined)
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32)); this.trySetShiny();
const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId;
const F = rand1 ^ rand2;
if (this.shiny === undefined) {
let shinyThreshold = new Utils.IntegerHolder(32);
this.scene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold);
console.log(shinyThreshold.value);
this.shiny = (E ^ F) < shinyThreshold.value;
if ((E ^ F) < 32)
console.log('REAL SHINY!!');
if (this.shiny)
console.log((E ^ F), shinyThreshold.value);
}
this.winCount = 0; this.winCount = 0;
this.pokerus = false; this.pokerus = false;
@ -207,6 +192,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
abstract isPlayer(): boolean; abstract isPlayer(): boolean;
abstract hasTrainer(): boolean;
abstract getFieldIndex(): integer; abstract getFieldIndex(): integer;
abstract getBattlerIndex(): BattlerIndex; abstract getBattlerIndex(): BattlerIndex;
@ -507,6 +494,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.summonData.moveset[moveIndex] = move; this.summonData.moveset[moveIndex] = move;
} }
trySetShiny(): boolean {
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16));
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32));
const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId;
const F = rand1 ^ rand2;
let shinyThreshold = new Utils.IntegerHolder(32);
if (!this.hasTrainer()) {
this.scene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold);
console.log(shinyThreshold.value);
}
this.shiny = (E ^ F) < shinyThreshold.value;
if ((E ^ F) < 32)
console.log('REAL SHINY!!');
return this.shiny;
}
generateAndPopulateMoveset(): void { generateAndPopulateMoveset(): void {
this.moveset = []; this.moveset = [];
const movePool = []; const movePool = [];
@ -629,7 +636,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let result: HitResult; let result: HitResult;
const move = battlerMove.getMove(); const move = battlerMove.getMove();
const moveCategory = move.category; const moveCategory = move.category;
let damage = 0; let damage = new Utils.NumberHolder(0);
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
const typeless = !!move.getAttrs(TypelessAttr).length const typeless = !!move.getAttrs(TypelessAttr).length
@ -683,19 +690,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyAbAttrs(StabBoostAbAttr, source, null, stabMultiplier); applyAbAttrs(StabBoostAbAttr, source, null, stabMultiplier);
if (!isTypeImmune) { if (!isTypeImmune) {
damage = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk / targetDef) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * weatherTypeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier; damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk / targetDef) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * weatherTypeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier;
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) if (isPhysical && source.status && source.status.effect === StatusEffect.BURN)
damage = Math.floor(damage / 2); damage.value = Math.floor(damage.value / 2);
move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => { move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => {
if (this.getTag(hta.tagType)) if (this.getTag(hta.tagType))
damage *= 2; damage.value *= 2;
}); });
} }
const fixedDamage = new Utils.IntegerHolder(0); const fixedDamage = new Utils.IntegerHolder(0);
applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage); applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage);
if (!isTypeImmune && fixedDamage.value) { if (!isTypeImmune && fixedDamage.value) {
damage = fixedDamage.value; damage.value = fixedDamage.value;
isCritical = false; isCritical = false;
result = HitResult.EFFECTIVE; result = HitResult.EFFECTIVE;
} }
@ -713,15 +720,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
result = HitResult.NO_EFFECT; result = HitResult.NO_EFFECT;
} }
if (!source.isPlayer())
this.scene.applyModifiers(EnemyDamageBoosterModifier, false, damage);
if (!this.isPlayer())
this.scene.applyModifiers(EnemyDamageReducerModifier, false, damage);
if (damage) { if (damage) {
this.scene.unshiftPhase(new DamagePhase(this.scene, this.getBattlerIndex(), result as DamageResult)); this.scene.unshiftPhase(new DamagePhase(this.scene, this.getBattlerIndex(), result as DamageResult));
if (isCritical) if (isCritical)
this.scene.queueMessage('A critical hit!'); this.scene.queueMessage('A critical hit!');
this.scene.setPhaseQueueSplice(); this.scene.setPhaseQueueSplice();
damage = Math.min(damage, this.hp); damage.value = Math.min(damage.value, this.hp);
this.damage(damage); this.damage(damage.value);
source.turnData.damageDealt += damage; source.turnData.damageDealt += damage.value;
this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage, critical: isCritical, sourceId: source.id }); this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id });
} }
switch (result) { switch (result) {
@ -1097,6 +1110,10 @@ export class PlayerPokemon extends Pokemon {
return true; return true;
} }
hasTrainer(): boolean {
return true;
}
getFieldIndex(): integer { getFieldIndex(): integer {
return this.scene.getPlayerField().indexOf(this); return this.scene.getPlayerField().indexOf(this);
} }
@ -1165,12 +1182,15 @@ export class PlayerPokemon extends Pokemon {
} }
export class EnemyPokemon extends Pokemon { export class EnemyPokemon extends Pokemon {
public trainer: boolean;
public aiType: AiType; public aiType: AiType;
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, dataSource?: PokemonData) { constructor(scene: BattleScene, species: PokemonSpecies, level: integer, trainer: boolean, dataSource?: PokemonData) {
super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource ? dataSource.formIndex : scene.arena.getFormIndex(species), super(scene, 236, 84, species, level, dataSource?.abilityIndex, dataSource ? dataSource.formIndex : scene.arena.getFormIndex(species),
dataSource?.gender, dataSource?.shiny, dataSource); dataSource?.gender, dataSource?.shiny, dataSource);
this.trainer = trainer;
if (!dataSource) { if (!dataSource) {
let prevolution: Species; let prevolution: Species;
let speciesId = species.speciesId; let speciesId = species.speciesId;
@ -1323,6 +1343,10 @@ export class EnemyPokemon extends Pokemon {
return false; return false;
} }
hasTrainer(): boolean {
return this.trainer;
}
getFieldIndex(): integer { getFieldIndex(): integer {
return this.scene.getEnemyField().indexOf(this); return this.scene.getEnemyField().indexOf(this);
} }

View File

@ -253,7 +253,7 @@ export class GameData {
scene.newArena(sessionData.arena.biome, true); scene.newArena(sessionData.arena.biome, true);
sessionData.enemyParty.forEach((enemyData, e) => { sessionData.enemyParty.forEach((enemyData, e) => {
const enemyPokemon = enemyData.toPokemon(scene) as EnemyPokemon; const enemyPokemon = enemyData.toPokemon(scene, battleType) as EnemyPokemon;
battle.enemyParty[e] = enemyPokemon; battle.enemyParty[e] = enemyPokemon;
if (battleType === BattleType.WILD) if (battleType === BattleType.WILD)
battle.seenEnemyPartyMemberIds.add(enemyPokemon.id); battle.seenEnemyPartyMemberIds.add(enemyPokemon.id);
@ -274,7 +274,7 @@ export class GameData {
} }
for (let enemyModifierData of sessionData.enemyModifiers) { for (let enemyModifierData of sessionData.enemyModifiers) {
const modifier = enemyModifierData.toModifier(scene, modifiersModule[enemyModifierData.className]) as PokemonHeldItemModifier; const modifier = enemyModifierData.toModifier(scene, modifiersModule[enemyModifierData.className]);
if (modifier) if (modifier)
scene.addEnemyModifier(modifier); scene.addEnemyModifier(modifier);
} }

View File

@ -1,3 +1,4 @@
import { BattleType } from "../battle";
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { Gender } from "../data/gender"; import { Gender } from "../data/gender";
import { PokeballType } from "../data/pokeball"; import { PokeballType } from "../data/pokeball";
@ -69,10 +70,10 @@ export default class PokemonData {
} }
} }
toPokemon(scene: BattleScene): Pokemon { toPokemon(scene: BattleScene, battleType?: BattleType): Pokemon {
const species = getPokemonSpecies(this.species); const species = getPokemonSpecies(this.species);
if (this.player) if (this.player)
return new PlayerPokemon(scene, species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this); return new PlayerPokemon(scene, species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this);
return new EnemyPokemon(scene, species, this.level, this); return new EnemyPokemon(scene, species, this.level, battleType === BattleType.TRAINER, this);
} }
} }

View File

@ -131,7 +131,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
? getPokemonSpecies(battle.enemyParty[offset].species.getSpeciesForLevel(level)) ? getPokemonSpecies(battle.enemyParty[offset].species.getSpeciesForLevel(level))
: this.genNewPartyMemberSpecies(level); : this.genNewPartyMemberSpecies(level);
ret = new EnemyPokemon(this.scene, species, level); ret = new EnemyPokemon(this.scene, species, level, true);
}, this.config.hasStaticParty ? this.config.getDerivedType() + ((index + 1) << 8) : this.scene.currentBattle.waveIndex + (this.config.getDerivedType() << 10) + ((index + 1) << 8)); }, this.config.hasStaticParty ? this.config.getDerivedType() + ((index + 1) << 8) : this.scene.currentBattle.waveIndex + (this.config.getDerivedType() << 10) + ((index + 1) << 8));
return ret; return ret;
@ -151,7 +151,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
tier--; tier--;
} }
const tierPool = this.config.speciesPools[tier]; const tierPool = this.config.speciesPools[tier];
ret = getPokemonSpecies(getPokemonSpecies(Phaser.Math.RND.pick(tierPool)).getSpeciesForLevel(level)); ret = getPokemonSpecies(getPokemonSpecies(Phaser.Math.RND.pick(tierPool)).getSpeciesForLevel(level, true));
} else } else
ret = getPokemonSpecies(this.scene.randomSpecies(battle.waveIndex, level, this.config.speciesFilter).getSpeciesForLevel(level)); ret = getPokemonSpecies(this.scene.randomSpecies(battle.waveIndex, level, this.config.speciesFilter).getSpeciesForLevel(level));

View File

@ -60,13 +60,13 @@ export default class BallUiHandler extends UiHandler {
let success = false; let success = false;
const pokeballTypeCount = Object.keys(this.scene.currentBattle.turnPokeballCounts).length; const pokeballTypeCount = Object.keys(this.scene.pokeballCounts).length;
if (button === Button.ACTION || button === Button.CANCEL) { if (button === Button.ACTION || button === Button.CANCEL) {
const commandPhase = this.scene.getCurrentPhase() as CommandPhase; const commandPhase = this.scene.getCurrentPhase() as CommandPhase;
success = true; success = true;
if (button === Button.ACTION && this.cursor < pokeballTypeCount) { if (button === Button.ACTION && this.cursor < pokeballTypeCount) {
if (this.scene.currentBattle.turnPokeballCounts[this.cursor]) { if (this.scene.pokeballCounts[this.cursor]) {
if (commandPhase.handleCommand(Command.BALL, this.cursor)) { if (commandPhase.handleCommand(Command.BALL, this.cursor)) {
this.scene.ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex()); this.scene.ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
@ -94,7 +94,7 @@ export default class BallUiHandler extends UiHandler {
} }
updateCounts() { updateCounts() {
this.countsText.setText(Object.values(this.scene.currentBattle.turnPokeballCounts).map(c => `x${c}`).join('\n')); this.countsText.setText(Object.values(this.scene.pokeballCounts).map(c => `x${c}`).join('\n'));
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {