Add field zoom functionality and make final boss larger
parent
40d2c200a4
commit
f49a3e5127
|
@ -449,8 +449,8 @@ export class EncounterPhase extends BattlePhase {
|
|||
|
||||
doEncounter() {
|
||||
this.scene.playBgm(undefined, true);
|
||||
|
||||
this.scene.updateModifiers(false);
|
||||
this.scene.setFieldScale(1);
|
||||
|
||||
/*if (startingWave > 10) {
|
||||
for (let m = 0; m < Math.min(Math.floor(startingWave / 10), 99); m++)
|
||||
|
@ -617,6 +617,8 @@ export class NextEncounterPhase extends EncounterPhase {
|
|||
doEncounter(): void {
|
||||
this.scene.playBgm(undefined, true);
|
||||
|
||||
this.scene.arenaNextEnemy.setVisible(true);
|
||||
|
||||
const enemyField = this.scene.getEnemyField();
|
||||
this.scene.tweens.add({
|
||||
targets: [ this.scene.arenaEnemy, this.scene.arenaNextEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.lastEnemyTrainer ].flat(),
|
||||
|
@ -626,6 +628,7 @@ export class NextEncounterPhase extends EncounterPhase {
|
|||
this.scene.arenaEnemy.setX(this.scene.arenaNextEnemy.x);
|
||||
this.scene.arenaEnemy.setAlpha(1);
|
||||
this.scene.arenaNextEnemy.setX(this.scene.arenaNextEnemy.x - 300);
|
||||
this.scene.arenaNextEnemy.setVisible(false);
|
||||
if (this.scene.lastEnemyTrainer)
|
||||
this.scene.lastEnemyTrainer.destroy();
|
||||
|
||||
|
@ -836,7 +839,8 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||
this.scene.tweens.add({
|
||||
targets: this.scene.trainer,
|
||||
x: -36,
|
||||
duration: 1000
|
||||
duration: 1000,
|
||||
onComplete: () => this.scene.trainer.setVisible(false)
|
||||
});
|
||||
this.scene.time.delayedCall(750, () => this.summon());
|
||||
} else {
|
||||
|
@ -1060,6 +1064,8 @@ export class ShowTrainerPhase extends BattlePhase {
|
|||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.trainer.setVisible(true)
|
||||
|
||||
this.scene.trainer.setTexture('trainer_m');
|
||||
|
||||
this.scene.tweens.add({
|
||||
|
@ -2138,7 +2144,12 @@ export class StatChangePhase extends PokemonPhase {
|
|||
pokemon.enableMask();
|
||||
const pokemonMaskSprite = pokemon.maskSprite;
|
||||
|
||||
const statSprite = this.scene.add.tileSprite((this.player ? 106 : 236) * 6, ((this.player ? 148 : 84) + (levels.value >= 1 ? 160 : 0)) * 6, 156, 316, 'battle_stats', filteredStats.length > 1 ? 'mix' : BattleStat[filteredStats[0]].toLowerCase());
|
||||
const tileX = (this.player ? 106 : 236) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileY = ((this.player ? 148 : 84) + (levels.value >= 1 ? 160 : 0)) * pokemon.getSpriteScale() * this.scene.field.scale;
|
||||
const tileWidth = 156 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
const tileHeight = 316 * this.scene.field.scale * pokemon.getSpriteScale();
|
||||
|
||||
const statSprite = this.scene.add.tileSprite(tileX, tileY, tileWidth, tileHeight, 'battle_stats', filteredStats.length > 1 ? 'mix' : BattleStat[filteredStats[0]].toLowerCase());
|
||||
statSprite.setPipeline(this.scene.fieldSpritePipeline);
|
||||
statSprite.setAlpha(0);
|
||||
statSprite.setScale(6);
|
||||
|
@ -2388,6 +2399,7 @@ export class DamagePhase extends PokemonPhase {
|
|||
this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin, pokemon.name, null, () => {
|
||||
this.scene.addEnemyModifier(getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as PersistentModifier, false, true);
|
||||
pokemon.generateAndPopulateMoveset(1);
|
||||
this.scene.setFieldScale(0.75);
|
||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
this.scene.currentBattle.double = true;
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted());
|
||||
|
|
|
@ -48,6 +48,7 @@ import PokemonData from './system/pokemon-data';
|
|||
import { Nature } from './data/nature';
|
||||
import { SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges } from './data/pokemon-forms';
|
||||
import { FormChangePhase, QuietFormChangePhase } from './form-change-phase';
|
||||
import { BattleSpec } from './enums/battle-spec';
|
||||
|
||||
const enableAuto = true;
|
||||
const quickStart = false;
|
||||
|
@ -426,6 +427,14 @@ export default class BattleScene extends Phaser.Scene {
|
|||
}
|
||||
|
||||
launchBattle() {
|
||||
this.arenaBg = this.addFieldSprite(0, 0, 'plains_bg');
|
||||
this.arenaBgTransition = this.addFieldSprite(0, 0, `plains_bg`);
|
||||
|
||||
[ this.arenaBgTransition, this.arenaBg ].forEach(a => {
|
||||
a.setScale(6);
|
||||
a.setOrigin(0);
|
||||
});
|
||||
|
||||
const field = this.add.container(0, 0);
|
||||
field.setScale(6);
|
||||
|
||||
|
@ -494,8 +503,6 @@ export default class BattleScene extends Phaser.Scene {
|
|||
|
||||
this.quickStart = this.quickStart || this.isButtonPressed(Button.QUICK_START);
|
||||
|
||||
this.arenaBg = this.addFieldSprite(0, 0, 'plains_bg');
|
||||
this.arenaBgTransition = this.addFieldSprite(0, 0, `plains_bg`);
|
||||
this.arenaPlayer = new ArenaBase(this, true);
|
||||
this.arenaPlayerTransition = new ArenaBase(this, true);
|
||||
this.arenaEnemy = new ArenaBase(this, false);
|
||||
|
@ -503,8 +510,9 @@ export default class BattleScene extends Phaser.Scene {
|
|||
|
||||
this.arenaBgTransition.setVisible(false);
|
||||
this.arenaPlayerTransition.setVisible(false);
|
||||
this.arenaNextEnemy.setVisible(false);
|
||||
|
||||
[ this.arenaBg, this.arenaBgTransition, this.arenaPlayer, this.arenaPlayerTransition, this.arenaEnemy, this.arenaNextEnemy ].forEach(a => {
|
||||
[ this.arenaPlayer, this.arenaPlayerTransition, this.arenaEnemy, this.arenaNextEnemy ].forEach(a => {
|
||||
if (a instanceof Phaser.GameObjects.Sprite)
|
||||
a.setOrigin(0, 0);
|
||||
field.add(a);
|
||||
|
@ -722,6 +730,7 @@ export default class BattleScene extends Phaser.Scene {
|
|||
this.arenaPlayer.setPosition(300, 0);
|
||||
this.arenaPlayerTransition.setPosition(0, 0);
|
||||
[ this.arenaEnemy, this.arenaNextEnemy ].forEach(a => a.setPosition(-280, 0));
|
||||
this.arenaNextEnemy.setVisible(false);
|
||||
|
||||
this.trainer.setTexture('trainer_m');
|
||||
this.trainer.setPosition(406, 132);
|
||||
|
@ -827,7 +836,7 @@ export default class BattleScene extends Phaser.Scene {
|
|||
|
||||
if (!waveIndex && lastBattle) {
|
||||
const isNewBiome = !(lastBattle.waveIndex % 10);
|
||||
const resetArenaState = isNewBiome || this.currentBattle.battleType === BattleType.TRAINER;
|
||||
const resetArenaState = isNewBiome || this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
||||
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||
this.trySpreadPokerus();
|
||||
if (!isNewBiome && (newWaveIndex % 10) == 5)
|
||||
|
@ -876,6 +885,29 @@ export default class BattleScene extends Phaser.Scene {
|
|||
return this.arena;
|
||||
}
|
||||
|
||||
setFieldScale(scale: number, instant: boolean = false): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
scale *= 6;
|
||||
if (this.field.scale === scale)
|
||||
return resolve();
|
||||
|
||||
const defaultWidth = this.arenaBg.width * 6;
|
||||
const defaultHeight = this.arenaBg.height * 6;
|
||||
const scaledWidth = this.arenaBg.width * scale;
|
||||
const scaledHeight = this.arenaBg.height * scale;
|
||||
|
||||
this.tweens.add({
|
||||
targets: this.field,
|
||||
scale: scale,
|
||||
x: (defaultWidth - scaledWidth) / 2,
|
||||
y: defaultHeight - scaledHeight,
|
||||
duration: !instant ? Utils.fixedInt(Math.abs(this.field.scale - scale) * 200) : 0,
|
||||
ease: 'Sine.easeInOut',
|
||||
onComplete: () => resolve()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getSpeciesFormIndex(species: PokemonSpecies, gender?: Gender, nature?: Nature, ignoreArena?: boolean): integer {
|
||||
if (!species.forms?.length)
|
||||
return 0;
|
||||
|
@ -1240,9 +1272,9 @@ export default class BattleScene extends Phaser.Scene {
|
|||
duration = 500;
|
||||
if (destroy === undefined)
|
||||
destroy = true;
|
||||
const bgm = this.sound.get(this.bgm.key);
|
||||
const bgm = this.sound.getAllPlaying().find(bgm => bgm.key === this.bgm.key);
|
||||
if (bgm) {
|
||||
SoundFade.fadeOut(this, bgm, duration, destroy);
|
||||
SoundFade.fadeOut(this, this.bgm, duration, destroy);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1614,10 +1614,6 @@ export class FaintCountdownAttr extends AddBattlerTagAttr {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => super.getCondition()(user, target, move) && !target.isBossImmune();
|
||||
}
|
||||
}
|
||||
|
||||
export class HitsTagAttr extends MoveAttr {
|
||||
|
@ -2007,6 +2003,8 @@ export class DiscourageFrequentUseAttr extends MoveAttr {
|
|||
|
||||
const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY);
|
||||
|
||||
const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune();
|
||||
|
||||
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
||||
|
||||
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<void> {
|
||||
|
@ -2602,6 +2600,7 @@ export function initMoves() {
|
|||
.attr(FaintCountdownAttr)
|
||||
.ignoresProtect()
|
||||
.soundBased()
|
||||
.condition(failOnBossCondition)
|
||||
.target(MoveTarget.ALL),
|
||||
new AttackMove(Moves.ICY_WIND, "Icy Wind", Type.ICE, MoveCategory.SPECIAL, 55, 95, 15, 34, "The user attacks with a gust of chilled air. This also lowers opposing Pokémon's Speed stats.", 100, 0, 2)
|
||||
.attr(StatChangeAttr, BattleStat.SPD, -1)
|
||||
|
@ -2663,7 +2662,8 @@ export function initMoves() {
|
|||
new StatusMove(Moves.SAFEGUARD, "Safeguard (N)", Type.NORMAL, -1, 25, -1, "The user creates a protective field that prevents status conditions for five turns.", -1, 0, 2)
|
||||
.target(MoveTarget.USER_SIDE),
|
||||
new StatusMove(Moves.PAIN_SPLIT, "Pain Split", Type.NORMAL, -1, 20, -1, "The user adds its HP to the target's HP, then equally shares the combined HP with the target.", -1, 0, 2)
|
||||
.attr(HpSplitAttr),
|
||||
.attr(HpSplitAttr)
|
||||
.condition(failOnBossCondition),
|
||||
new AttackMove(Moves.SACRED_FIRE, "Sacred Fire", Type.FIRE, MoveCategory.PHYSICAL, 100, 95, 5, -1, "The target is razed with a mystical fire of great intensity. This may also leave the target with a burn.", 50, 0, 2)
|
||||
.attr(StatusEffectAttr, StatusEffect.BURN)
|
||||
.makesContact(false),
|
||||
|
@ -2796,7 +2796,8 @@ export function initMoves() {
|
|||
.condition((user, target, move) => !target.status),
|
||||
new AttackMove(Moves.KNOCK_OFF, "Knock Off (N)", Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, "The user slaps down the target's held item, and that item can't be used in that battle. The move does more damage if the target has a held item.", -1, 0, 3),
|
||||
new AttackMove(Moves.ENDEAVOR, "Endeavor", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, "This attack move cuts down the target's HP to equal the user's HP.", -1, 0, 3)
|
||||
.attr(MatchHpAttr),
|
||||
.attr(MatchHpAttr)
|
||||
.condition(failOnBossCondition),
|
||||
new AttackMove(Moves.ERUPTION, "Eruption", Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, "The user attacks opposing Pokémon with explosive fury. The lower the user's HP, the lower the move's power.", -1, 0, 3)
|
||||
.attr(HpPowerAttr)
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
|
|
|
@ -235,7 +235,7 @@ export class QuietFormChangePhase extends BattlePhase {
|
|||
this.scene.tweens.add({
|
||||
targets: pokemonFormTintSprite,
|
||||
delay: 250,
|
||||
scale: 1,
|
||||
scale: this.pokemon.getSpriteScale(),
|
||||
ease: 'Cubic.easeInOut',
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
|
|
|
@ -25,6 +25,7 @@ uniform vec3 duskTint;
|
|||
uniform vec3 nightTint;
|
||||
uniform int hasShadow;
|
||||
uniform int yCenter;
|
||||
uniform float fieldScale;
|
||||
uniform float vCutoff;
|
||||
uniform vec2 relPosition;
|
||||
uniform vec2 size;
|
||||
|
@ -115,8 +116,8 @@ void main()
|
|||
if (hasShadow == 1) {
|
||||
float width = size.x - (yOffset / 2.0);
|
||||
|
||||
float spriteX = ((floor(outPosition.x / 6.0) - relPosition.x) / width) + 0.5;
|
||||
float spriteY = ((floor(outPosition.y / 6.0) - relPosition.y) / size.y);
|
||||
float spriteX = ((floor(outPosition.x / fieldScale) - relPosition.x) / width) + 0.5;
|
||||
float spriteY = ((floor(outPosition.y / fieldScale) - relPosition.y) / size.y);
|
||||
|
||||
if (yCenter == 1) {
|
||||
spriteY += 0.5;
|
||||
|
@ -213,14 +214,19 @@ export default class SpritePipeline extends FieldSpritePipeline {
|
|||
const fusionSpriteColors = (ignoreOverride && data['fusionSpriteColorsBase']) || data['fusionSpriteColors'] || [] as number[][];
|
||||
|
||||
const isEntityObj = sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer;
|
||||
const field = isEntityObj ? sprite.parentContainer.parentContainer : sprite.parentContainer;
|
||||
const fieldScaleRatio = field.scale / 6;
|
||||
const position = isEntityObj
|
||||
? [ sprite.parentContainer.x, sprite.parentContainer.y ]
|
||||
: [ sprite.x, sprite.y ];
|
||||
position[0] += -(sprite.width - sprite.frame.width) / 2 + sprite.frame.x;
|
||||
position[0] += field.x / field.scale;
|
||||
position[1] += field.y / field.scale;
|
||||
position[0] += -(sprite.width - (sprite.frame.width)) / 2 + sprite.frame.x;
|
||||
if (sprite.originY === 0.5)
|
||||
position[1] += (sprite.height / 2) * ((isEntityObj ? sprite.parentContainer : sprite).scale - 1);
|
||||
this.set1i('hasShadow', hasShadow ? 1 : 0);
|
||||
this.set1i('yCenter', sprite.originY === 0.5 ? 1 : 0);
|
||||
this.set1f('fieldScale', field.scale);
|
||||
this.set2f('relPosition', position[0], position[1]);
|
||||
this.set2f('size', sprite.frame.width, sprite.height);
|
||||
this.set1f('yOffset', sprite.height - sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale));
|
||||
|
@ -247,14 +253,16 @@ export default class SpritePipeline extends FieldSpritePipeline {
|
|||
const hasShadow = sprite.pipelineData['hasShadow'] as boolean;
|
||||
if (hasShadow) {
|
||||
const isEntityObj = sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer;
|
||||
const field = isEntityObj ? sprite.parentContainer.parentContainer : sprite.parentContainer;
|
||||
const fieldScaleRatio = field.scale / 6;
|
||||
const baseY = (isEntityObj
|
||||
? sprite.parentContainer.y
|
||||
: sprite.y + sprite.height) * 6;
|
||||
const bottomPadding = Math.ceil(sprite.height * 0.05) * 6;
|
||||
const yDelta = (baseY - y1) / 6;
|
||||
: sprite.y + sprite.height) * 6 / fieldScaleRatio;
|
||||
const bottomPadding = Math.ceil(sprite.height * 0.05) * 6 / fieldScaleRatio;
|
||||
const yDelta = (baseY - y1) / field.scale;
|
||||
y2 = y1 = baseY + bottomPadding;
|
||||
const pixelHeight = ((v1 - v0) / (sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale)));
|
||||
v1 += (yDelta + bottomPadding / 6) * pixelHeight;
|
||||
const pixelHeight = (v1 - v0) / (sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale));
|
||||
v1 += (yDelta + bottomPadding / field.scale) * pixelHeight;
|
||||
}
|
||||
|
||||
return super.batchQuad(gameObject, x0, y0, x1, y1, x2, y2, x3, y3, u0, v0, u1, v1, tintTL, tintTR, tintBL, tintBR, tintEffect, texture, unit);
|
||||
|
|
|
@ -399,6 +399,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
getSpriteScale(): number {
|
||||
if (this.species.speciesId === Species.ETERNATUS && this.formIndex)
|
||||
return 1.5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1565,8 +1567,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (!this.maskEnabled) {
|
||||
this.maskSprite = this.getTintSprite();
|
||||
this.maskSprite.setVisible(true);
|
||||
this.maskSprite.setPosition(this.x * 6, this.y * 6);
|
||||
this.maskSprite.setScale(6 * this.getSpriteScale());
|
||||
this.maskSprite.setPosition(this.x * this.parentContainer.scale + this.parentContainer.x,
|
||||
this.y * this.parentContainer.scale + this.parentContainer.y);
|
||||
this.maskSprite.setScale(this.getSpriteScale() * this.parentContainer.scale);
|
||||
this.maskEnabled = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue