|
|
|
@ -4,6 +4,8 @@ import type {
|
|
|
|
EnemyState,
|
|
|
|
EnemyState,
|
|
|
|
HeroState,
|
|
|
|
HeroState,
|
|
|
|
FloatingDamageData,
|
|
|
|
FloatingDamageData,
|
|
|
|
|
|
|
|
FloatingDamageKind,
|
|
|
|
|
|
|
|
FloatingDamageTarget,
|
|
|
|
LootDrop,
|
|
|
|
LootDrop,
|
|
|
|
TownData,
|
|
|
|
TownData,
|
|
|
|
NearbyHeroData,
|
|
|
|
NearbyHeroData,
|
|
|
|
@ -420,6 +422,7 @@ export class GameEngine {
|
|
|
|
isCrit: boolean,
|
|
|
|
isCrit: boolean,
|
|
|
|
heroHp: number,
|
|
|
|
heroHp: number,
|
|
|
|
enemyHp: number,
|
|
|
|
enemyHp: number,
|
|
|
|
|
|
|
|
outcome?: 'hit' | 'dodge' | 'block' | 'stun',
|
|
|
|
): void {
|
|
|
|
): void {
|
|
|
|
if (this._gameState.hero) {
|
|
|
|
if (this._gameState.hero) {
|
|
|
|
this._gameState.hero.hp = heroHp;
|
|
|
|
this._gameState.hero.hp = heroHp;
|
|
|
|
@ -430,25 +433,53 @@ export class GameEngine {
|
|
|
|
|
|
|
|
|
|
|
|
// Emit floating damage at appropriate screen position
|
|
|
|
// Emit floating damage at appropriate screen position
|
|
|
|
const viewport = getViewport();
|
|
|
|
const viewport = getViewport();
|
|
|
|
if (source === 'hero') {
|
|
|
|
const isBlocked = outcome === 'block';
|
|
|
|
// Damage on enemy (right side of screen)
|
|
|
|
const isEvaded = outcome === 'dodge';
|
|
|
|
|
|
|
|
const defender: FloatingDamageTarget = source === 'enemy' ? 'hero' : 'enemy';
|
|
|
|
|
|
|
|
if (source === 'hero' || source === 'enemy') {
|
|
|
|
|
|
|
|
if (isBlocked || isEvaded) {
|
|
|
|
|
|
|
|
this._emitDamage(
|
|
|
|
|
|
|
|
0,
|
|
|
|
|
|
|
|
defender === 'enemy' ? viewport.width / 2 + 60 : viewport.width / 2 - 60,
|
|
|
|
|
|
|
|
viewport.height / 2 - 30,
|
|
|
|
|
|
|
|
false,
|
|
|
|
|
|
|
|
isBlocked ? 'blocked' : 'evaded',
|
|
|
|
|
|
|
|
defender,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this._emitDamage(
|
|
|
|
|
|
|
|
damage,
|
|
|
|
|
|
|
|
defender === 'enemy' ? viewport.width / 2 + 60 : viewport.width / 2 - 60,
|
|
|
|
|
|
|
|
viewport.height / 2 - 30,
|
|
|
|
|
|
|
|
source === 'hero' ? isCrit : false,
|
|
|
|
|
|
|
|
'damage',
|
|
|
|
|
|
|
|
defender,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// potion source: no floating damage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._notifyStateChange();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Called when server sends enemy_regen.
|
|
|
|
|
|
|
|
* Updates enemy HP and emits floating regen numbers.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
applyEnemyRegen(amount: number, enemyHp: number): void {
|
|
|
|
|
|
|
|
if (!this._gameState.enemy) return;
|
|
|
|
|
|
|
|
this._gameState.enemy.hp = enemyHp;
|
|
|
|
|
|
|
|
if (amount > 0) {
|
|
|
|
|
|
|
|
const viewport = getViewport();
|
|
|
|
this._emitDamage(
|
|
|
|
this._emitDamage(
|
|
|
|
damage,
|
|
|
|
amount,
|
|
|
|
viewport.width / 2 + 60,
|
|
|
|
viewport.width / 2 + 60,
|
|
|
|
viewport.height / 2 - 30,
|
|
|
|
viewport.height / 2 - 30,
|
|
|
|
isCrit,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else if (source === 'enemy') {
|
|
|
|
|
|
|
|
// Damage on hero (left side of screen)
|
|
|
|
|
|
|
|
this._emitDamage(
|
|
|
|
|
|
|
|
damage,
|
|
|
|
|
|
|
|
viewport.width / 2 - 60,
|
|
|
|
|
|
|
|
viewport.height / 2 - 30,
|
|
|
|
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
|
|
|
|
'regen',
|
|
|
|
|
|
|
|
'enemy',
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// potion source: no floating damage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._notifyStateChange();
|
|
|
|
this._notifyStateChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -914,6 +945,8 @@ export class GameEngine {
|
|
|
|
x: number,
|
|
|
|
x: number,
|
|
|
|
y: number,
|
|
|
|
y: number,
|
|
|
|
isCrit: boolean,
|
|
|
|
isCrit: boolean,
|
|
|
|
|
|
|
|
kind: FloatingDamageKind,
|
|
|
|
|
|
|
|
target: FloatingDamageTarget,
|
|
|
|
): void {
|
|
|
|
): void {
|
|
|
|
if (!this._onDamage) return;
|
|
|
|
if (!this._onDamage) return;
|
|
|
|
this._onDamage({
|
|
|
|
this._onDamage({
|
|
|
|
@ -923,6 +956,8 @@ export class GameEngine {
|
|
|
|
y,
|
|
|
|
y,
|
|
|
|
isCrit,
|
|
|
|
isCrit,
|
|
|
|
createdAt: performance.now(),
|
|
|
|
createdAt: performance.now(),
|
|
|
|
|
|
|
|
kind,
|
|
|
|
|
|
|
|
target,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|