Add damage numbers feature

This commit is contained in:
Flashfyre 2024-03-01 00:27:46 -05:00
parent f48464d48d
commit 716d8853a3
7 changed files with 198 additions and 3 deletions

View File

@ -51,6 +51,7 @@ import { BattleSpec } from './enums/battle-spec';
import { getTypeRgb } from './data/type'; import { getTypeRgb } from './data/type';
import PokemonSpriteSparkleHandler from './field/pokemon-sprite-sparkle-handler'; import PokemonSpriteSparkleHandler from './field/pokemon-sprite-sparkle-handler';
import CharSprite from './ui/char-sprite'; import CharSprite from './ui/char-sprite';
import DamageNumberHandler from './field/damage-number-handler';
export const bypassLogin = false; export const bypassLogin = false;
export const startingLevel = 5; export const startingLevel = 5;
@ -92,6 +93,7 @@ export default class BattleScene extends Phaser.Scene {
public bgmVolume: number = 1; public bgmVolume: number = 1;
public seVolume: number = 1; public seVolume: number = 1;
public gameSpeed: integer = 1; public gameSpeed: integer = 1;
public damageNumbersMode: integer = 0;
public showLevelUpStats: boolean = true; public showLevelUpStats: boolean = true;
public enableTutorials: boolean = true; public enableTutorials: boolean = true;
public windowType: integer = 1; public windowType: integer = 1;
@ -141,6 +143,7 @@ export default class BattleScene extends Phaser.Scene {
public seed: string; public seed: string;
public waveSeed: string; public waveSeed: string;
public damageNumberHandler: DamageNumberHandler
private spriteSparkleHandler: PokemonSpriteSparkleHandler; private spriteSparkleHandler: PokemonSpriteSparkleHandler;
public fieldSpritePipeline: FieldSpritePipeline; public fieldSpritePipeline: FieldSpritePipeline;
@ -537,6 +540,8 @@ export default class BattleScene extends Phaser.Scene {
this.updateUIPositions(); this.updateUIPositions();
this.damageNumberHandler = new DamageNumberHandler();
this.spriteSparkleHandler = new PokemonSpriteSparkleHandler(); this.spriteSparkleHandler = new PokemonSpriteSparkleHandler();
this.spriteSparkleHandler.setup(this); this.spriteSparkleHandler.setup(this);

View File

@ -15,7 +15,7 @@ import { ArenaTagType } from "./enums/arena-tag-type";
import { Abilities, BlockRecoilDamageAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs } from "./ability"; import { Abilities, BlockRecoilDamageAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs } from "./ability";
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier } from "../modifier/modifier";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "../battle";
import { Stat, getStatName } from "./pokemon-stat"; import { Stat } from "./pokemon-stat";
export enum MoveCategory { export enum MoveCategory {
PHYSICAL, PHYSICAL,

View File

@ -0,0 +1,164 @@
import { TextStyle, addTextObject } from "../ui/text";
import Pokemon, { AttackMoveResult, HitResult } from "./pokemon";
import * as Utils from "../utils";
import { BattlerIndex } from "../battle";
export default class DamageNumberHandler {
private damageNumbers: Map<BattlerIndex, Phaser.GameObjects.Text[]>;
constructor() {
this.damageNumbers = new Map();
}
add(target: Pokemon, result: AttackMoveResult): void {
const scene = target.scene;
const battlerIndex = target.getBattlerIndex();
const baseScale = target.getSpriteScale() / 6;
const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(result.damage, true), TextStyle.SUMMARY);
damageNumber.setOrigin(0.5, 1);
damageNumber.setScale(baseScale);
let [ textColor, shadowColor ] = [ null, null ];
switch (result.result) {
case HitResult.SUPER_EFFECTIVE:
[ textColor, shadowColor ] = [ '#f8d030', '#b8a038' ];
break;
case HitResult.NOT_VERY_EFFECTIVE:
[ textColor, shadowColor ] = [ '#f08030', '#c03028' ];
break;
case HitResult.ONE_HIT_KO:
[ textColor, shadowColor ] = [ '#a040a0', '#483850' ];
break;
default:
[ textColor, shadowColor ] = [ '#ffffff', '#636363' ];
break;
}
if (textColor)
damageNumber.setColor(textColor);
if (shadowColor) {
if (result.critical) {
damageNumber.setShadowOffset(0, 0);
damageNumber.setStroke(shadowColor, 12);
} else
damageNumber.setShadowColor(shadowColor);
}
scene.fieldUI.add(damageNumber);
if (!this.damageNumbers.has(battlerIndex))
this.damageNumbers.set(battlerIndex, []);
const yOffset = this.damageNumbers.get(battlerIndex).length * -10;
if (yOffset)
damageNumber.y += yOffset;
this.damageNumbers.get(battlerIndex).push(damageNumber);
if (scene.damageNumbersMode === 1) {
scene.tweens.add({
targets: damageNumber,
duration: Utils.fixedInt(750),
alpha: 1,
y: '-=32'
});
scene.tweens.add({
delay: 375,
targets: damageNumber,
duration: Utils.fixedInt(625),
alpha: 0,
ease: 'Sine.easeIn',
onComplete: () => {
this.damageNumbers.get(battlerIndex).splice(this.damageNumbers.get(battlerIndex).indexOf(damageNumber), 1);
damageNumber.destroy(true);
}
});
return;
}
damageNumber.setAlpha(0);
scene.tweens.chain({
targets: damageNumber,
tweens: [
{
duration: Utils.fixedInt(250),
alpha: 1,
scaleX: 0.75 * baseScale,
scaleY: 1.25 * baseScale,
y: '-=16',
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(175),
alpha: 1,
scaleX: 0.875 * baseScale,
scaleY: 1.125 * baseScale,
y: '+=16',
ease: 'Cubic.easeIn'
},
{
duration: Utils.fixedInt(100),
scaleX: 1.25 * baseScale,
scaleY: 0.75 * baseScale,
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(175),
scaleX: 0.875 * baseScale,
scaleY: 1.125 * baseScale,
y: '-=8',
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(50),
scaleX: 0.925 * baseScale,
scaleY: 1.075 * baseScale,
y: '+=8',
ease: 'Cubic.easeIn'
},
{
duration: Utils.fixedInt(100),
scaleX: 1.125 * baseScale,
scaleY: 0.875 * baseScale,
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(175),
scaleX: 0.925 * baseScale,
scaleY: 1.075 * baseScale,
y: '-=4',
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(50),
scaleX: 0.975 * baseScale,
scaleY: 1.025 * baseScale,
y: '+=4',
ease: 'Cubic.easeIn'
},
{
duration: Utils.fixedInt(100),
scaleX: 1.075 * baseScale,
scaleY: 0.925 * baseScale,
ease: 'Cubic.easeOut'
},
{
duration: Utils.fixedInt(25),
scaleX: baseScale,
scaleY: baseScale,
ease: 'Cubic.easeOut'
},
{
delay: Utils.fixedInt(500),
alpha: 0,
onComplete: () => {
this.damageNumbers.get(battlerIndex).splice(this.damageNumbers.get(battlerIndex).indexOf(damageNumber), 1);
damageNumber.destroy(true);
}
}
]
});
}
}

View File

@ -38,7 +38,6 @@ export default class PokemonSpriteSparkleHandler {
const sparkle = (s.scene as BattleScene).addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), 'tera_sparkle'); const sparkle = (s.scene as BattleScene).addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), 'tera_sparkle');
sparkle.pipelineData['ignoreTimeTint'] = s.pipelineData['ignoreTimeTint']; sparkle.pipelineData['ignoreTimeTint'] = s.pipelineData['ignoreTimeTint'];
sparkle.play('tera_sparkle'); sparkle.play('tera_sparkle');
const teraColor = s.pipelineData['teraColor'] as number[];
parent.add(sparkle); parent.add(sparkle);
s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy()); s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy());
} }

View File

@ -1135,7 +1135,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
source.turnData.damageDealt += damage.value; source.turnData.damageDealt += damage.value;
this.battleData.hitCount++; this.battleData.hitCount++;
this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id }); const attackResult = { move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id };
this.turnData.attacksReceived.unshift(attackResult);
if (damage.value && this.scene.damageNumbersMode)
this.scene.damageNumberHandler.add(this, attackResult);
if (source.isPlayer() && !this.isPlayer()) if (source.isPlayer() && !this.isPlayer())
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage) this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, damage)
} }

View File

@ -36,6 +36,24 @@ export function initGameSpeed() {
config.hold = transformValue(config.hold); config.hold = transformValue(config.hold);
return originalTweensAdd.apply(this, [ config ]); return originalTweensAdd.apply(this, [ config ]);
}; };
const originalTweensChain = this.tweens.chain;
this.tweens.chain = function (config: Phaser.Types.Tweens.TweenChainBuilderConfig): Phaser.Tweens.TweenChain {
if (config.tweens) {
config.tweens.forEach(t => {
if (t.duration)
t.duration = transformValue(t.duration);
if (t.delay)
t.delay = transformValue(t.delay);
if (t.repeatDelay)
t.repeatDelay = transformValue(t.repeatDelay);
if (t.loopDelay)
t.loopDelay = transformValue(t.loopDelay);
if (t.hold)
t.hold = transformValue(t.hold);
});
}
return originalTweensChain.apply(this, [ config ]);
};
const originalAddCounter = this.tweens.addCounter; const originalAddCounter = this.tweens.addCounter;
this.tweens.addCounter = function (config: Phaser.Types.Tweens.NumberTweenBuilderConfig) { this.tweens.addCounter = function (config: Phaser.Types.Tweens.NumberTweenBuilderConfig) {
if (config.duration) if (config.duration)

View File

@ -7,6 +7,7 @@ export enum Setting {
Master_Volume = "MASTER_VOLUME", Master_Volume = "MASTER_VOLUME",
BGM_Volume = "BGM_VOLUME", BGM_Volume = "BGM_VOLUME",
SE_Volume = "SE_VOLUME", SE_Volume = "SE_VOLUME",
Damage_Numbers = "DAMAGE_NUMBERS",
Show_Stats_on_Level_Up = "SHOW_LEVEL_UP_STATS", Show_Stats_on_Level_Up = "SHOW_LEVEL_UP_STATS",
Window_Type = "WINDOW_TYPE", Window_Type = "WINDOW_TYPE",
Tutorials = "TUTORIALS", Tutorials = "TUTORIALS",
@ -29,6 +30,7 @@ export const settingOptions: SettingOptions = {
[Setting.Master_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'), [Setting.Master_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'),
[Setting.BGM_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'), [Setting.BGM_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'),
[Setting.SE_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'), [Setting.SE_Volume]: new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : 'Mute'),
[Setting.Damage_Numbers]: [ 'Off', 'Simple', 'Fancy' ],
[Setting.Show_Stats_on_Level_Up]: [ 'Off', 'On' ], [Setting.Show_Stats_on_Level_Up]: [ 'Off', 'On' ],
[Setting.Window_Type]: new Array(4).fill(null).map((_, i) => (i + 1).toString()), [Setting.Window_Type]: new Array(4).fill(null).map((_, i) => (i + 1).toString()),
[Setting.Tutorials]: [ 'Off', 'On' ], [Setting.Tutorials]: [ 'Off', 'On' ],
@ -43,6 +45,7 @@ export const settingDefaults: SettingDefaults = {
[Setting.Master_Volume]: 5, [Setting.Master_Volume]: 5,
[Setting.BGM_Volume]: 10, [Setting.BGM_Volume]: 10,
[Setting.SE_Volume]: 10, [Setting.SE_Volume]: 10,
[Setting.Damage_Numbers]: 0,
[Setting.Show_Stats_on_Level_Up]: 1, [Setting.Show_Stats_on_Level_Up]: 1,
[Setting.Window_Type]: 0, [Setting.Window_Type]: 0,
[Setting.Tutorials]: 1, [Setting.Tutorials]: 1,
@ -69,6 +72,9 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer)
scene.seVolume = value ? parseInt(settingOptions[setting][value]) * 0.01 : 0; scene.seVolume = value ? parseInt(settingOptions[setting][value]) * 0.01 : 0;
scene.updateSoundVolume(); scene.updateSoundVolume();
break; break;
case Setting.Damage_Numbers:
scene.damageNumbersMode = value;
break;
case Setting.Show_Stats_on_Level_Up: case Setting.Show_Stats_on_Level_Up:
scene.showLevelUpStats = settingOptions[setting][value] === 'On'; scene.showLevelUpStats = settingOptions[setting][value] === 'On';
break; break;