Add field zoom functionality and make final boss larger

This commit is contained in:
Flashfyre 2024-01-14 20:47:08 -05:00
parent 40d2c200a4
commit f49a3e5127
6 changed files with 82 additions and 26 deletions

View File

@ -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());

View File

@ -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;
}

View File

@ -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),

View File

@ -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: () => {

View File

@ -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);

View File

@ -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;
}
}