import { Hooks, RpgCommonPlayer } from '@rpgjs/common'; import { Trigger } from 'canvasengine'; import { RpgClientEngine } from '../RpgClientEngine'; type Frame = { x: number; y: number; ts: number; }; type AnimationRestoreOptions = { /** Optional duration in milliseconds of each animation cycle. */ durationMs?: number; restoreAnimationName?: string; restoreGraphics?: any[]; timeoutMs?: number; }; type FlashType = 'alpha' | 'tint' | 'both'; type FlashOptions = { type?: FlashType; duration?: number; cycles?: number; alpha?: number; tint?: number | string; }; type FlashTriggerOptions = Omit & { tint: number; }; type ConfigurableTrigger = Omit, "start"> & { start(config?: T): Promise; }; export declare const multiplyGraphicDisplayScale: (baseScale: unknown, instanceScale: unknown) => [number, number]; export declare const withGraphicDisplayScale: (spritesheet: any, scale: unknown) => any; export declare const appendFramePayload: (current: unknown, items: unknown) => Frame[]; export declare const getFrameTimestamp: (frame: Frame) => number; /** * Largest movement backlog replayed frame by frame. One frame is consumed per * render tick, so a longer queue (a hidden or frozen tab keeps receiving * positions while the render loop is paused) would never drain and the object * would replay old positions long after the tab is visible again. */ export declare const MAX_FRAME_BACKLOG = 10; export declare const mergeFreshFramePayload: (current: unknown, items: unknown, lastAppliedFrameTs?: number) => Frame[]; export declare abstract class RpgClientObject extends RpgCommonPlayer { abstract _type: string; emitParticleTrigger: Trigger; particleName: import('canvasengine').WritableSignal; animationCurrentIndex: import('canvasengine').WritableSignal; animationIsPlaying: import('canvasengine').WritableSignal; _param: import('canvasengine').WritableObjectSignal<{}>; frames: Frame[]; graphicsSignals: import('canvasengine').WritableArraySignal; flashTrigger: ConfigurableTrigger; private lastAppliedFrameTs; private animationRestoreState?; constructor(); private getFrameTimestamp; /** * Access the shared client hook registry. * * @returns The hook service used to register and trigger client-side hooks. */ get hooks(): Hooks; /** * Access the current client engine instance. * * @returns The active {@link RpgClientEngine} instance. */ get engine(): RpgClientEngine; setHitbox(width: number, height: number): void; private animationSubscription?; private animationResetTimeout?; private animationWaitResolve?; private clearAnimationControls; private resolveAnimationWait; private finishTemporaryAnimation; /** * Trigger a flash animation on this sprite * * This method triggers a flash effect using CanvasEngine's flash directive. * The flash can be configured with various options including type (alpha, tint, or both), * duration, cycles, and color. * * ## Design * * The flash uses a trigger system that is connected to the flash directive in the * character component. This allows for flexible configuration and can be triggered * from both server events and client-side code. * * @param options - Flash configuration options * @param options.type - Type of flash effect: 'alpha' (opacity), 'tint' (color), or 'both' (default: 'alpha') * @param options.duration - Duration of the flash animation in milliseconds (default: 300) * @param options.cycles - Number of flash cycles (flash on/off) (default: 1) * @param options.alpha - Alpha value when flashing, from 0 to 1 (default: 0.3) * @param options.tint - Tint color when flashing as hex value or color name (default: 0xffffff - white) * * @example * ```ts * // Simple flash with default settings (alpha flash) * player.flash(); * * // Flash with red tint * player.flash({ type: 'tint', tint: 0xff0000 }); * * // Flash with both alpha and tint * player.flash({ * type: 'both', * alpha: 0.5, * tint: 0xff0000, * duration: 200, * cycles: 2 * }); * * // Quick damage flash * player.flash({ * type: 'tint', * tint: 0xff0000, * duration: 150, * cycles: 1 * }); * ``` */ flash(options?: FlashOptions): void; /** * Reset animation state when animation changes externally * * This method should be called when the animation changes due to movement * or other external factors to ensure the animation system doesn't get stuck * * @example * ```ts * // Reset when player starts moving * player.resetAnimationState(); * ``` */ resetAnimationState(): void; /** * Set a custom animation for a specific number of times * * Plays a custom animation for the specified number of repetitions. * The animation system prevents overlapping animations and automatically * returns to the previous animation when complete. * * @param animationName - Name of the animation to play * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous) * @param options - Restore, timeout and optional per-cycle durationMs options * @returns A promise resolved when a finite animation finishes, is interrupted, or times out * * @example * ```ts * // Play attack animation 3 times * await player.setAnimation('attack', 3); * * // Play continuous spell animation * player.setAnimation('spell'); * ``` */ setAnimation(animationName: string, nbTimes?: number, options?: AnimationRestoreOptions): Promise; /** * Set a custom animation with temporary graphic change * * Plays a custom animation for the specified number of repetitions and temporarily * changes the player's graphic (sprite sheet) during the animation. The graphic * is automatically reset when the animation finishes. * * @param animationName - Name of the animation to play * @param graphic - The graphic(s) to temporarily use during the animation * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous) * @param options - Restore, timeout and optional per-cycle durationMs options * @returns A promise resolved when a finite animation finishes, is interrupted, or times out * * @example * ```ts * // Play attack animation with temporary graphic change * await player.setAnimation('attack', 'hero_attack', 3); * ``` */ setAnimation(animationName: string, graphic?: string | string[], nbTimes?: number, options?: AnimationRestoreOptions): Promise; /** * Display a registered component animation effect on this object. * * @param id - Identifier of the component animation to play. * @param params - Parameters forwarded to the animation effect. * @returns A promise resolved when the animation component calls `onFinish`. */ showComponentAnimation(id: string, params: any): Promise; /** * Display a registered spritesheet animation effect on this object. * * @param graphic - Identifier of the spritesheet to use. * @param animationName - Name of the animation inside the spritesheet. * @returns A promise resolved when the animation component calls `onFinish`. */ showAnimation(graphic: string, animationName?: string): Promise; /** * Check whether this client object represents an event. * * @returns `true` if the object type is `event`, otherwise `false`. */ isEvent(): boolean; /** * Check whether this client object represents a player. * * @returns `true` if the object type is `player`, otherwise `false`. */ isPlayer(): boolean; } export {};