|
|
|
@ -25,8 +25,10 @@ import type {
|
|
|
|
EnemyState,
|
|
|
|
EnemyState,
|
|
|
|
LootDrop,
|
|
|
|
LootDrop,
|
|
|
|
MerchantLootPayload,
|
|
|
|
MerchantLootPayload,
|
|
|
|
|
|
|
|
DebuffAppliedPayload,
|
|
|
|
} from './types';
|
|
|
|
} from './types';
|
|
|
|
import { EnemyType, Rarity } from './types';
|
|
|
|
import { DebuffType, EnemyType, Rarity } from './types';
|
|
|
|
|
|
|
|
import { DEBUFF_DURATION_DEFAULTS } from '../shared/constants';
|
|
|
|
|
|
|
|
|
|
|
|
// ---- Callback types for UI layer (App.tsx) ----
|
|
|
|
// ---- Callback types for UI layer (App.tsx) ----
|
|
|
|
|
|
|
|
|
|
|
|
@ -64,6 +66,9 @@ export function wireWSHandler(
|
|
|
|
engine: GameEngine,
|
|
|
|
engine: GameEngine,
|
|
|
|
callbacks: WSHandlerCallbacks,
|
|
|
|
callbacks: WSHandlerCallbacks,
|
|
|
|
): void {
|
|
|
|
): void {
|
|
|
|
|
|
|
|
const isDebuffType = (value: string): value is DebuffType => (
|
|
|
|
|
|
|
|
Object.values(DebuffType).includes(value as DebuffType)
|
|
|
|
|
|
|
|
);
|
|
|
|
// ---- Server -> Client: Movement ----
|
|
|
|
// ---- Server -> Client: Movement ----
|
|
|
|
|
|
|
|
|
|
|
|
ws.on('hero_move', (msg: ServerMessage) => {
|
|
|
|
ws.on('hero_move', (msg: ServerMessage) => {
|
|
|
|
@ -111,6 +116,16 @@ export function wireWSHandler(
|
|
|
|
engine.applyAttack(p.source, p.damage, p.isCrit, p.heroHp, p.enemyHp);
|
|
|
|
engine.applyAttack(p.source, p.damage, p.isCrit, p.heroHp, p.enemyHp);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ws.on('debuff_applied', (msg: ServerMessage) => {
|
|
|
|
|
|
|
|
const p = msg.payload as DebuffAppliedPayload;
|
|
|
|
|
|
|
|
if (!p?.debuffType || !isDebuffType(p.debuffType)) return;
|
|
|
|
|
|
|
|
const nowMs = Date.now();
|
|
|
|
|
|
|
|
const fallbackMs = DEBUFF_DURATION_DEFAULTS[p.debuffType] ?? 0;
|
|
|
|
|
|
|
|
const durationMs = Number.isFinite(p.durationMs) ? Math.max(0, p.durationMs as number) : fallbackMs;
|
|
|
|
|
|
|
|
const expiresAtMs = p.expiresAt ? Date.parse(p.expiresAt) : nowMs + durationMs;
|
|
|
|
|
|
|
|
engine.applyDebuffApplied(p.debuffType, durationMs, expiresAtMs);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ws.on('combat_end', (msg: ServerMessage) => {
|
|
|
|
ws.on('combat_end', (msg: ServerMessage) => {
|
|
|
|
const p = msg.payload as CombatEndPayload;
|
|
|
|
const p = msg.payload as CombatEndPayload;
|
|
|
|
engine.applyCombatEnd();
|
|
|
|
engine.applyCombatEnd();
|
|
|
|
|