about summary refs log tree commit diff stats
path: root/html/plains
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-12-14 21:46:04 -0500
committerelioat <elioat@tilde.institute>2024-12-14 21:46:04 -0500
commit4aeabc4d6194e49884a83a3fe8b7e0809a9ac166 (patch)
tree041481b5419025a58517790144fac7fe5567d1c0 /html/plains
parentaef4513c844a5779b63bcbe6d68592de5ea47103 (diff)
downloadtour-4aeabc4d6194e49884a83a3fe8b7e0809a9ac166.tar.gz
*
Diffstat (limited to 'html/plains')
-rw-r--r--html/plains/game.js88
1 files changed, 76 insertions, 12 deletions
diff --git a/html/plains/game.js b/html/plains/game.js
index ad7b8c3..43b4446 100644
--- a/html/plains/game.js
+++ b/html/plains/game.js
@@ -152,6 +152,15 @@ const CONFIG = {
             startDelay: 1500,    // Start idle animation after 1.5 seconds
             lookSpeed: 0.001,    // Speed of the looking animation
             lookRadius: 0.4      // How far to look around (in radians)
+        },
+        equipment: {
+            swordUnlockCount: 3,  // Number of rescues needed to unlock sword
+            unlockAnimation: {
+                duration: 6000,    // Duration of unlock animation in ms
+                glowColor: 'rgba(255, 215, 0, 0.6)',  // Golden glow
+                messageText: 'Sword Unlocked!',
+                messageColor: '#FFD700'  // Gold color for text
+            }
         }
     },
     sword: {
@@ -304,7 +313,7 @@ const createInitialState = () => ({
         direction: { x: 0, y: -1 },
         swordAngle: 0,
         isSwinging: false,
-        equipment: 'sword',
+        equipment: 'unarmed',  // Start without sword
         bubbles: [],
         bubbleParticles: [],
         lastBubbleTime: 0,
@@ -313,7 +322,9 @@ const createInitialState = () => ({
         dashExhausted: false, // Is dash on cooldown?
         lastInputTime: 0, // Track when the last input occurred
         baseDirection: { x: 0, y: -1 },
-        lastDashEnd: 0
+        lastDashEnd: 0,
+        swordUnlocked: false,
+        rescuedCount: 0
     },
     particles: [],
     footprints: [],
@@ -395,15 +406,18 @@ const inputHandlers = {
     handleAttack: (state, animationTime) => {
         if (state.player.isDefending) return state;
         
-        if (state.player.equipment === 'sword' && !state.player.isSwinging) {
-            return {
-                ...state,
-                player: {
-                    ...state.player,
-                    isSwinging: true,
-                    swordAngle: Math.atan2(state.player.direction.y, state.player.direction.x) - Math.PI / 2
-                }
-            };
+        if (state.player.equipment === 'sword') {
+            if (!state.player.swordUnlocked) return state; // Prevent sword usage if not unlocked
+            if (!state.player.isSwinging) {
+                return {
+                    ...state,
+                    player: {
+                        ...state.player,
+                        isSwinging: true,
+                        swordAngle: Math.atan2(state.player.direction.y, state.player.direction.x) - Math.PI / 2
+                    }
+                };
+            }
         } else if (state.player.equipment === 'unarmed') {
             return createBubbleAttack(state, animationTime);
         }
@@ -411,6 +425,8 @@ const inputHandlers = {
     },
 
     handleEquipmentSwitch: (state) => {
+        if (!state.player.swordUnlocked) return state; // Can't switch if sword isn't unlocked
+        
         const equipment = ['sword', 'unarmed'];
         const currentIndex = equipment.indexOf(state.player.equipment);
         return {
@@ -1393,10 +1409,18 @@ const updatePlayer = () => {
         
         if (distance < (CONFIG.player.size + CONFIG.world.villagers.size) / 2) {
             villager.status = 'rescued';
+            state.player.rescuedCount++;
+            
+            // Check for sword unlock
+            if (state.player.rescuedCount >= CONFIG.player.equipment.swordUnlockCount && !state.player.swordUnlocked) {
+                state.player.swordUnlocked = true;
+                state.player.equipment = 'sword';  // Auto-equip sword
+                showSwordUnlockAnimation();
+            }
             
             // Assign new position in village when rescued
             const villageSize = CONFIG.world.village.size * CONFIG.display.grid.size;
-            const margin = CONFIG.world.villagers.size; // Keep villagers away from village edges
+            const margin = CONFIG.world.villagers.size;
             
             villager.x = margin + Math.random() * (villageSize - margin * 2);
             villager.y = margin + Math.random() * (villageSize - margin * 2);
@@ -1632,4 +1656,44 @@ const getCellInfo = (x, y) => {
             grass: !hasTree && !hasMushrooms && !hasFlowers && hasGrass
         }
     };
+};
+
+const showSwordUnlockAnimation = () => {
+    // Create container for animation
+    const container = document.createElement('div');
+    container.style.position = 'fixed';
+    container.style.top = '50%';
+    container.style.left = '50%';
+    container.style.transform = 'translate(-50%, -50%)';
+    container.style.padding = '20px';
+    container.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
+    container.style.borderRadius = '10px';
+    container.style.animation = 'glow 2s ease-in-out';
+    container.style.zIndex = '1000';
+
+    // Add CSS animation
+    const style = document.createElement('style');
+    style.textContent = `
+        @keyframes glow {
+            0% { box-shadow: 0 0 0 0 ${CONFIG.player.equipment.unlockAnimation.glowColor}; opacity: 0; }
+            50% { box-shadow: 0 0 30px 10px ${CONFIG.player.equipment.unlockAnimation.glowColor}; opacity: 1; }
+            100% { box-shadow: 0 0 0 0 ${CONFIG.player.equipment.unlockAnimation.glowColor}; opacity: 0; }
+        }
+    `;
+    document.head.appendChild(style);
+
+    // Add message text
+    const message = document.createElement('div');
+    message.textContent = CONFIG.player.equipment.unlockAnimation.messageText;
+    message.style.color = CONFIG.player.equipment.unlockAnimation.messageColor;
+    message.style.fontSize = '24px';
+    message.style.textAlign = 'center';
+    container.appendChild(message);
+
+    // Add to document and remove after animation
+    document.body.appendChild(container);
+    setTimeout(() => {
+        document.body.removeChild(container);
+        document.head.removeChild(style);
+    }, CONFIG.player.equipment.unlockAnimation.duration);
 };
\ No newline at end of file