// HikeMap Animation Definitions // This file defines all available animations for monster and player icons // Edit the keyframes to customize how animations look // Player-specific animations (defaults used when no skill override is set) const PLAYER_ANIMATIONS = { // Default attack animation - lunge forward towards enemies attack: { name: 'Attack', description: 'Lunge forward towards enemy', duration: 500, loop: false, easing: 'ease-out', keyframes: ` 0% { transform: translateX(0); } 20% { transform: translateX(-20px) scale(0.9); } 50% { transform: translateX(30px) scale(1.15); } 70% { transform: translateX(5px) scale(1.05); } 100% { transform: translateX(0) scale(1); } ` }, // Default skill animation - quick pulse/glow effect skill: { name: 'Skill', description: 'Quick pulse effect for skills', duration: 400, loop: false, easing: 'ease-in-out', keyframes: ` 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } ` }, // Miss animation - attack motion then fall clockwise, hold, recover (mirrors monster miss) miss: { name: 'Miss', description: 'Attack then fall over clockwise and recover', duration: 2000, loop: false, easing: 'ease-out', keyframes: ` 0% { transform: translateX(0) rotate(0deg); } 10% { transform: translateX(-20px) scale(0.9) rotate(0deg); } 20% { transform: translateX(30px) scale(1.15) rotate(0deg); } 30% { transform: translateX(15px) rotate(90deg); } 70% { transform: translateX(15px) rotate(90deg); } 85% { transform: translateX(5px) rotate(30deg); } 100% { transform: translateX(0) rotate(0deg); } ` }, // Death animation - fall over death: { name: 'Death', description: 'Fall over permanently', duration: 800, loop: false, easing: 'ease-out', fillMode: 'forwards', keyframes: ` 0% { transform: rotate(0deg); opacity: 1; } 100% { transform: rotate(90deg); opacity: 0.5; } ` } }; const MONSTER_ANIMATIONS = { // Default attack animation - rubber band snap towards player attack: { name: 'Attack', description: 'Rubber band snap towards player', duration: 500, loop: false, easing: 'ease-out', keyframes: ` 0% { transform: translateX(0); } 20% { transform: translateX(20px) scale(0.9); } 50% { transform: translateX(-30px) scale(1.15); } 70% { transform: translateX(-5px) scale(1.05); } 100% { transform: translateX(0) scale(1); } ` }, // Default skill animation - quick shake back and forth skill: { name: 'Skill', description: 'Quick shake back and forth', duration: 400, loop: false, easing: 'ease-in-out', keyframes: ` 0%, 100% { transform: translateX(0); } 10%, 30%, 50%, 70%, 90% { transform: translateX(-8px); } 20%, 40%, 60%, 80% { transform: translateX(8px); } ` }, // Default miss animation - attack motion then fall counter-clockwise, hold, recover miss: { name: 'Miss', description: 'Attack then fall over counter-clockwise and recover', duration: 2000, loop: false, easing: 'ease-out', keyframes: ` 0% { transform: translateX(0) rotate(0deg); } 10% { transform: translateX(20px) scale(0.9) rotate(0deg); } 20% { transform: translateX(-30px) scale(1.15) rotate(0deg); } 30% { transform: translateX(-15px) rotate(-90deg); } 70% { transform: translateX(-15px) rotate(-90deg); } 85% { transform: translateX(-5px) rotate(-30deg); } 100% { transform: translateX(0) rotate(0deg); } ` }, // Default death animation - fall over counter-clockwise permanently death: { name: 'Death', description: 'Fall over permanently', duration: 600, loop: false, easing: 'ease-out', fillMode: 'forwards', keyframes: ` 0% { transform: rotate(0deg); opacity: 1; } 100% { transform: rotate(-90deg); opacity: 0.6; } ` }, // Default idle animation - gentle dance/bob idle: { name: 'Idle', description: 'Gentle dance/bob animation', duration: 2000, loop: true, easing: 'ease-in-out', keyframes: ` 0%, 100% { transform: rotate(-3deg) scale(1); } 50% { transform: rotate(3deg) scale(0.95); } ` }, // Bouncy dance - faster, more energetic idle bouncy: { name: 'Bouncy Dance', description: 'Fast energetic bouncing dance', duration: 600, loop: true, easing: 'ease-in-out', keyframes: ` 0%, 100% { transform: translateY(0) rotate(-5deg) scale(1); } 25% { transform: translateY(-8px) rotate(5deg) scale(1.1); } 50% { transform: translateY(0) rotate(-5deg) scale(0.9); } 75% { transform: translateY(-8px) rotate(5deg) scale(1.1); } ` }, // Flip Y animation - spin 360 degrees around vertical axis (like opening a door) flipy: { name: 'Flip Y', description: 'Horizontal flip around vertical axis', duration: 600, loop: false, easing: 'ease-in-out', keyframes: ` 0% { transform: rotateY(0deg); } 100% { transform: rotateY(360deg); } ` }, // Flip XY animation - tumbling diagonal flip (somersault + spin) flipxy: { name: 'Flip XY', description: 'Tumbling diagonal flip', duration: 800, loop: false, easing: 'ease-in-out', keyframes: ` 0% { transform: rotateX(0deg) rotateY(0deg); } 100% { transform: rotateX(360deg) rotateY(360deg); } ` }, // Flip Z animation - spin like a top viewed from above flipz: { name: 'Flip Z', description: 'Spin like a top', duration: 600, loop: false, easing: 'ease-in-out', keyframes: ` 0% { transform: rotateZ(0deg); } 100% { transform: rotateZ(360deg); } ` }, // Shrink and grow animation shrink_grow: { name: 'Shrink & Grow', description: 'Shrink to 50% then grow back', duration: 1000, loop: false, easing: 'ease-in-out', keyframes: ` 0%, 100% { transform: scale(1); } 50% { transform: scale(0.5); } ` }, // Slow spinning with grow/shrink - loopable, smooth like a rotating plant spin_grow: { name: 'Spin & Grow', description: 'Smooth slow spin with pulsing size', duration: 4000, loop: true, easing: 'linear', keyframes: ` 0% { transform: rotateZ(0deg) scale(1); } 50% { transform: rotateZ(-180deg) scale(1.15); } 100% { transform: rotateZ(-360deg) scale(1); } ` } }; // Helper function to get animation list for dropdowns function getAnimationList() { return Object.entries(MONSTER_ANIMATIONS).map(([id, anim]) => ({ id, name: anim.name, description: anim.description })); } // Helper function to get player animation list for dropdowns function getPlayerAnimationList() { // Player can use both player-specific and monster animations const playerAnims = Object.entries(PLAYER_ANIMATIONS).map(([id, anim]) => ({ id, name: anim.name, description: anim.description, source: 'player' })); const monsterAnims = Object.entries(MONSTER_ANIMATIONS).map(([id, anim]) => ({ id, name: anim.name, description: anim.description, source: 'monster' })); return [...playerAnims, ...monsterAnims]; } // Get an animation by ID, checking both player and monster animations function getAnimation(animationId) { if (PLAYER_ANIMATIONS[animationId]) { return PLAYER_ANIMATIONS[animationId]; } if (MONSTER_ANIMATIONS[animationId]) { return MONSTER_ANIMATIONS[animationId]; } return null; } // Export for use in browser if (typeof window !== 'undefined') { window.MONSTER_ANIMATIONS = MONSTER_ANIMATIONS; window.PLAYER_ANIMATIONS = PLAYER_ANIMATIONS; window.getAnimationList = getAnimationList; window.getPlayerAnimationList = getPlayerAnimationList; window.getAnimation = getAnimation; }