The dirt paths aren't perfectly flush with the ground. Can you remove the current ones and adjust the terrain generation logic to draw them ON the terrain itself instead of above it? Output the entire code please.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D Environment with Goblins, Merchant, Golden Orb, and Dirt Paths</title>
    <style>
        body { margin: 0; overflow: hidden; }
        canvas { display: block; }

        /* HUD Container */
        #hud {
            position: absolute;
            top: 10px;
            left: 10px;
            color: white;
            font-family: Arial, sans-serif;
            font-size: 20px;
            z-index: 1;
        }

        /* Health Bar Container */
        #healthBarContainer {
            width: 200px;
            height: 25px;
            background-color: #555; /* Dark gray background */
            border: 2px solid #fff; /* White border */
            border-radius: 5px;
            overflow: hidden;
            margin-bottom: 10px; /* Spacing below the health bar */
        }

        /* Health Bar (Foreground) */
        #healthBar {
            width: 100%; /* Full width initially */
            height: 100%;
            background-color: green; /* Initial color based on health */
            transition: width 0.2s ease, background-color 0.2s ease; /* Smooth transitions */
        }

        /* Time Display */
        #timeDisplay {
            margin-top: 10px; /* Spacing above the time display */
        }

        /* Gold Display */
        #goldDisplay {
            color: gold;
            font-family: Arial, sans-serif;
            font-size: 20px;
            margin-top: 10px; /* Spacing above the gold display */
        }

        #goldDisplay .coin-icon {
            display: inline-block;
            width: 20px;
            height: 20px;
            background-color: gold; /* Gold color for the coin */
            border-radius: 50%; /* Make it a circle */
            vertical-align: middle;
            margin-right: 5px; /* Spacing between the coin and amount */
        }

        /* Game Over screen */
        #gameOver {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: red;
            font-family: Arial, sans-serif;
            font-size: 50px;
            display: none;
            z-index: 2;
        }

        /* Merchant Dialog */
        #merchantDialog {
            position: absolute;
            bottom: 20%;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 20px;
            border-radius: 10px;
            display: none;
            z-index: 3;
            font-family: Arial, sans-serif;
            font-size: 20px;
            text-align: center;
        }

        /* Shop UI */
        #shopUI {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(50, 50, 50, 0.9);
            color: white;
            padding: 20px;
            border-radius: 10px;
            display: none;
            z-index: 4;
            font-family: Arial, sans-serif;
            font-size: 20px;
            text-align: center;
        }

        #shopUI h2 {
            margin-top: 0;
        }

        #shopUI .item {
            margin: 10px 0;
        }

        #shopUI button {
            padding: 10px 20px;
            font-size: 16px;
            margin-top: 10px;
        }

        /* YOU WIN screen */
        #youWin {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: #000033; /* Dark blue background */
            display: none;
            z-index: 5;
            overflow: hidden;
        }

        #winText {
            position: absolute;
            top: 20%;
            width: 100%;
            text-align: center;
            color: #FF00FF; /* Magenta */
            font-family: 'Comic Sans MS', cursive, sans-serif;
            font-size: 80px;
            text-shadow: 2px 2px #00FFFF; /* Cyan shadow */
        }
    </style>
</head>
<body>
    <!-- HUD Elements -->
    <div id="hud">
        <!-- Health Bar -->
        <div id="healthBarContainer">
            <div id="healthBar"></div>
        </div>
        <!-- Time Display -->
        <div id="timeDisplay">Time: 06:00 AM</div>
        <!-- Gold Display -->
        <div id="goldDisplay">
            <div class="coin-icon"></div>
            <span id="goldAmount">0</span>
        </div>
    </div>
    <!-- Game Over Screen -->
    <div id="gameOver">Game Over</div>
    <!-- Merchant Dialog -->
    <div id="merchantDialog">
        Press E to talk to the Merchant
    </div>
    <!-- Shop UI -->
    <div id="shopUI">
        <h2>Merchant's Shop</h2>
        <div class="item">
            <span>Sword Upgrade - 10 Gold</span><br>
            <button onclick="buyItem('swordUpgrade', 10)">Buy</button>
        </div>
        <div class="item">
            <span>Health Potion - 5 Gold</span><br>
            <button onclick="buyItem('healthPotion', 5)">Buy</button>
        </div>
        <button onclick="closeShop()">Close</button>
    </div>
    <!-- YOU WIN Screen -->
    <div id="youWin">
        <div id="winText">YOU WIN!</div>
        <canvas id="winCanvas"></canvas>
    </div>
    <!-- Three.js and Controls Libraries -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/PointerLockControls.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/objects/Sky.js"></script>
    <script>
        // Set up scene, camera, and renderer
        const scene = new THREE.Scene();

        // Declare 'controls' before using it
        let controls;

        const camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );

        // Adjust the player's starting position
        camera.position.set(0, 1.6, 5);

        // Initialize 'controls' after declaring it
        controls = new THREE.PointerLockControls(camera, document.body);

        const renderer = new THREE.WebGLRenderer({ antialias: true });
        const collisionBoxes = []; // Array to hold bounding boxes for collision
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // HUD Elements
        const healthBar = document.getElementById('healthBar');
        const timeDisplay = document.getElementById('timeDisplay');
        const goldDisplay = document.getElementById('goldAmount');
        const gameOverScreen = document.getElementById('gameOver');
        const merchantDialog = document.getElementById('merchantDialog');
        const shopUI = document.getElementById('shopUI');
        const youWinScreen = document.getElementById('youWin');

        // Player Health
        let playerHealth = 100;

        // Player Gold
        let playerGold = 0;

        // Update Gold Display
        function updateGoldDisplay() {
            goldDisplay.innerText = playerGold;
        }

        // Add ambient light and directional light
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
        scene.add(ambientLight);
        const sunLight = new THREE.DirectionalLight(0xffffff, 1);
        sunLight.position.set(100, 100, 100);
        scene.add(sunLight);

        // Add Sky Shader
        const sky = new THREE.Sky();
        sky.scale.setScalar(450000); // Scale the sky to cover a large area
        scene.add(sky);

        const sun = new THREE.Vector3();

        // Skybox parameters
        const skyUniforms = sky.material.uniforms;
        skyUniforms['turbidity'].value = 10;
        skyUniforms['rayleigh'].value = 2;
        skyUniforms['mieCoefficient'].value = 0.005;
        skyUniforms['mieDirectionalG'].value = 0.8;

        // Set the initial sun position
        const thetaInitial = Math.PI * 0.25; // Elevation angle in radians for midday
        const phiInitial = 2 * Math.PI * 0.25; // Azimuthal angle in radians
        sun.setFromSphericalCoords(1, thetaInitial, phiInitial);
        sky.material.uniforms['sunPosition'].value.copy(sun);
        sunLight.position.copy(sun);

        // Add ground with rolling hills
        const terrainGeometry = new THREE.PlaneBufferGeometry(
            1000,
            1000,
            128,
            128
        );
        const terrainMaterial = new THREE.MeshLambertMaterial({
            color: 0x228b22,
        });
        const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
        terrain.rotation.x = -Math.PI / 2;

        const positionAttr = terrainGeometry.attributes.position;
        for (let i = 0; i < positionAttr.count; i++) {
            const x = positionAttr.getX(i);
            const y = positionAttr.getY(i);
            const z = Math.sin(x / 20) * 5 + Math.cos(y / 20) * 5;
            positionAttr.setZ(i, z);
        }
        terrainGeometry.computeVertexNormals();
        scene.add(terrain);

        // Function to get the height of the terrain at a given (x, z) position
        function getTerrainHeightAt(x, z) {
            const terrainPosition = terrainGeometry.attributes.position;
            const terrainWidth = terrainGeometry.parameters.width;
            const terrainSegments = terrainGeometry.parameters.widthSegments;

            const xNormalized = (x + terrainWidth / 2) / terrainWidth;
            const zNormalized = (z + terrainWidth / 2) / terrainWidth;

            const xIndex = xNormalized * terrainSegments;
            const zIndex = zNormalized * terrainSegments;

            const x0 = Math.floor(xIndex);
            const x1 = Math.min(x0 + 1, terrainSegments);
            const z0 = Math.floor(zIndex);
            const z1 = Math.min(z0 + 1, terrainSegments);

            const s1 = xIndex - x0;
            const s0 = 1 - s1;
            const t1 = zIndex - z0;
            const t0 = 1 - t1;

            const index00 = z0 * (terrainSegments + 1) + x0;
            const index01 = z1 * (terrainSegments + 1) + x0;
            const index10 = z0 * (terrainSegments + 1) + x1;
            const index11 = z1 * (terrainSegments + 1) + x1;

            const height00 = terrainPosition.getZ(index00);
            const height01 = terrainPosition.getZ(index01);
            const height10 = terrainPosition.getZ(index10);
            const height11 = terrainPosition.getZ(index11);

            const height =
                s0 * t0 * height00 +
                s1 * t0 * height10 +
                s0 * t1 * height01 +
                s1 * t1 * height11;
            return height;
        }

        // Bilinear interpolation for smoother terrain height detection
        function getInterpolatedHeightAt(x, z) {
            // Same as getTerrainHeightAt
            return getTerrainHeightAt(x, z);
        }

        // Add dirt paths to the terrain
        function addDirtPaths() {
            // Paths are created as dynamic geometries conforming to the terrain
            const pathMaterial = new THREE.MeshLambertMaterial({
                color: 0x8b4513, // Brown color for dirt
                side: THREE.DoubleSide,
            });

            // Define path points (you can adjust coordinates as needed)
            const paths = [
                // Path from player's starting position to merchant
                [
                    { x: 0, z: 5 },
                    { x: 0, z: -15 },
                    { x: 0, z: -30 }, // Merchant position
                ],
                // Path from merchant to orb
                [
                    { x: 0, z: -30 },
                    { x: 25, z: -15 },
                    { x: 50, z: 0 },
                    { x: 75, z: 15 },
                    { x: 100, z: 30 }, // Orb position
                ],
            ];

            paths.forEach((pathPoints) => {
                const pathGeometry = new THREE.BufferGeometry();
                const positions = [];
                const indices = [];
                const width = 1.5; // Width of the path

                const numSegments = pathPoints.length - 1;
                const subdivisions = 20; // Number of subdivisions per segment

                for (let i = 0; i < numSegments; i++) {
                    const start = pathPoints[i];
                    const end = pathPoints[i + 1];

                    for (let j = 0; j <= subdivisions; j++) {
                        const t = j / subdivisions;
                        const x = start.x + (end.x - start.x) * t;
                        const z = start.z + (end.z - start.z) * t;
                        const y = getTerrainHeightAt(x, z) + 0.02; // Slightly above ground to prevent z-fighting

                        // Calculate left and right positions for the width of the path
                        const nextT = Math.min((j + 1) / subdivisions, 1);
                        const nextX = start.x + (end.x - start.x) * nextT;
                        const nextZ = start.z + (end.z - start.z) * nextT;

                        const dx = nextX - x;
                        const dz = nextZ - z;
                        const length = Math.hypot(dx, dz);
                        const nx = dz / length;
                        const nz = -dx / length;

                        // Left point
                        positions.push(
                            x + nx * width,
                            y,
                            z + nz * width
                        );

                        // Right point
                        positions.push(
                            x - nx * width,
                            y,
                            z - nz * width
                        );
                    }
                }

                // Generate indices
                const vertexCount = (subdivisions * numSegments + 1) * 2;
                for (let i = 0; i < vertexCount - 2; i += 2) {
                    indices.push(i, i + 1, i + 2);
                    indices.push(i + 1, i + 3, i + 2);
                }

                pathGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
                pathGeometry.setIndex(indices);
                pathGeometry.computeVertexNormals();

                const pathMesh = new THREE.Mesh(pathGeometry, pathMaterial);
                scene.add(pathMesh);
            });
        }

        addDirtPaths(); // Call the function to add dirt paths

        // Add trees
        for (let i = 0; i < 100; i++) {
            // Generate random position for the tree
            const treeX = Math.random() * 500 - 250;
            const treeZ = Math.random() * 500 - 250;
            const treeY = getTerrainHeightAt(treeX, treeZ);

            // Create tree trunk
            const trunkGeometry = new THREE.CylinderGeometry(0.5, 0.5, 10, 8);
            const trunkMaterial = new THREE.MeshLambertMaterial({
                color: 0x8b4513,
            });
            const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
            trunk.position.set(treeX, treeY + 5, treeZ);

            // Create evergreen leaves as stacked cones
            const leavesMaterial = new THREE.MeshLambertMaterial({
                color: 0x228b22,
            });
            for (let j = 0; j < 3; j++) {
                const leavesGeometry = new THREE.ConeGeometry(
                    3 + j * 1.5,
                    8,
                    16
                ); // Biggest on bottom, smallest on top
                const leaves = new THREE.Mesh(leavesGeometry, leavesMaterial);
                leaves.position.set(0, 10 - j * 3, 0);
                trunk.add(leaves);
            }

            scene.add(trunk);
        }

        // Create a sword with blade, crossbar, and hilt
        const swordGroup = new THREE.Group();

        // Blade
        const bladeGeometry = new THREE.ConeGeometry(0.1, 1.5, 4);
        const bladeMaterial = new THREE.MeshLambertMaterial({ color: 0xc0c0c0 });
        const blade = new THREE.Mesh(bladeGeometry, bladeMaterial);
        blade.position.set(0, 0.75, 0);
        swordGroup.add(blade);

        // Crossbar
        const crossbarGeometry = new THREE.BoxGeometry(0.4, 0.05, 0.1);
        const crossbarMaterial = new THREE.MeshLambertMaterial({
            color: 0x808080,
        });
        const crossbar = new THREE.Mesh(crossbarGeometry, crossbarMaterial);
        crossbar.position.set(0, 0, 0);
        swordGroup.add(crossbar);

        // Extra crossbar (vertical and perpendicular to the current one)
        const extraCrossbarGeometry = new THREE.BoxGeometry(0.4, 0.05, 0.1);
        const extraCrossbarMaterial = new THREE.MeshLambertMaterial({
            color: 0x808080,
        });
        const extraCrossbar = new THREE.Mesh(
            extraCrossbarGeometry,
            extraCrossbarMaterial
        );
        extraCrossbar.rotation.y = Math.PI / 2;
        extraCrossbar.position.set(0, 0, 0);
        swordGroup.add(extraCrossbar);

        // Hilt
        const hiltGeometry = new THREE.CylinderGeometry(0.05, 0.05, 0.5, 8);
        const hiltMaterial = new THREE.MeshLambertMaterial({
            color: 0x8b4513,
        });
        const hilt = new THREE.Mesh(hiltGeometry, hiltMaterial);
        hilt.position.set(0, -0.25, 0);
        swordGroup.add(hilt);

        // Position the sword relative to the camera
        swordGroup.position.set(0.5, -0.5, -1);
        camera.add(swordGroup);
        scene.add(camera);

        // Add event listener for locking controls
        document.body.addEventListener('click', () => {
            controls.lock();
        });

        // WASD movement controls for the player
        const movement = {
            forward: false,
            backward: false,
            left: false,
            right: false,
            jump: false,
            running: false,
        };
        document.addEventListener('keydown', (event) => {
            switch (event.code) {
                case 'KeyW':
                    movement.forward = true;
                    break;
                case 'KeyS':
                    movement.backward = true;
                    break;
                case 'KeyA':
                    movement.left = true;
                    break;
                case 'KeyD':
                    movement.right = true;
                    break;
                case 'Space':
                    if (!movement.jump) {
                        velocity.y = 0.6;
                        movement.jump = true;
                    }
                    break;
                case 'ShiftLeft':
                    movement.running = true;
                    break;
                case 'Digit1':
                    incrementTimeByOneHour();
                    break; // Handle "1" key press
                case 'KeyE':
                    if (canTalkToMerchant) {
                        openShop();
                    }
                    break;
            }
        });
        document.addEventListener('keyup', (event) => {
            switch (event.code) {
                case 'KeyW':
                    movement.forward = false;
                    break;
                case 'KeyS':
                    movement.backward = false;
                    break;
                case 'KeyA':
                    movement.left = false;
                    break;
                case 'KeyD':
                    movement.right = false;
                    break;
                case 'Space':
                    movement.jump = false;
                    break;
                case 'ShiftLeft':
                    movement.running = false;
                    break;
            }
        });

        // Gravity and velocity setup
        let velocity = new THREE.Vector3();
        const gravity = -0.05;

        // Goblin collision radius
        const goblinCollisionRadius = 1.0;

        // Array to hold all goblins
        const goblins = [];

        // Coins Array
        const coins = [];

        // Sword swing variables
        let isSwinging = false;
        let isBlocking = false; // Variable to track blocking state
        let swordDamage = 25; // Damage per swing

        // Sword rotation targets
        let swordRotationTargetZ = 0; // Target rotation for Z axis (roll)
        let swordRotationTargetX = 0; // Target rotation for X axis (swing)

        // Prevent context menu on right-click
        document.addEventListener('contextmenu', (event) => {
            event.preventDefault();
        });

        document.addEventListener('mousedown', (event) => {
            if (event.button === 0 && !isSwinging && !isBlocking && !shopUIOpen) {
                // Left mouse button click
                isSwinging = true;
                const swingDuration = 200; // Swing duration in ms
                const swingSteps = swingDuration / 10;
                let currentStep = 0;
                const maxSwingAngle = Math.PI / 2; // 90 degrees

                const swingInterval = setInterval(() => {
                    currentStep++;
                    const swingProgress = currentStep / swingSteps;
                    const swingAngle = swingProgress * maxSwingAngle;

                    // Rotate the sword for swinging effect
                    swordGroup.rotation.x = -swingAngle;

                    // Detect hits during the swing
                    if (swingProgress > 0.3 && swingProgress < 0.7) {
                        // Active swing window
                        const swordWorldPosition = new THREE.Vector3();
                        swordGroup.getWorldPosition(swordWorldPosition);

                        // Check for collisions with goblins
                        goblins.forEach((goblin) => {
                            if (!goblin.isHit) {
                                // Prevent multiple hits per swing
                                const distance = swordWorldPosition.distanceTo(
                                    goblin.mesh.position
                                );
                                if (distance < 3) {
                                    // Increased collision distance for easier hits
                                    goblin.takeDamage(swordDamage);
                                    goblin.isHit = true;
                                }
                            }
                        });
                    }

                    if (currentStep >= swingSteps) {
                        // End of swing
                        clearInterval(swingInterval);
                        swordGroup.rotation.x = 0;
                        isSwinging = false;

                        // Reset goblins' hit status after swing
                        goblins.forEach((goblin) => (goblin.isHit = false));
                    }
                }, 10);
            } else if (event.button === 2) {
                // Right mouse button click for blocking
                isBlocking = true;
                swordRotationTargetZ = Math.PI / 4; // Set target rotation for blocking
            }
        });

        document.addEventListener('mouseup', (event) => {
            if (event.button === 2) {
                // Right mouse button released
                isBlocking = false;
                swordRotationTargetZ = 0; // Reset target rotation
            }
        });

        // Function to check collision for player and goblins
        function checkCollision(x, z, radius) {
            const collisionPosition = new THREE.Vector3(x, 0, z); // y is irrelevant for horizontal collision

            for (let i = 0; i < collisionBoxes.length; i++) {
                const wallBox = collisionBoxes[i];
                if (wallBox.containsPoint(collisionPosition)) {
                    return true;
                }

                // Additional circle-box collision
                const closestPoint = wallBox.clampPoint(
                    collisionPosition,
                    new THREE.Vector3()
                );
                const distance = collisionPosition.distanceTo(closestPoint);
                if (distance < radius) {
                    return true;
                }
            }

            return false;
        }

        // Goblin Class Definition with Orbiting Logic
        class Goblin {
            constructor(x, z) {
                // Create goblin mesh
                this.mesh = new THREE.Group();

                // Body
                const bodyGeometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 8);
                const bodyMaterial = new THREE.MeshLambertMaterial({
                    color: 0xff0000,
                }); // Red color
                this.body = new THREE.Mesh(bodyGeometry, bodyMaterial);
                this.body.position.y = 1;
                this.mesh.add(this.body);

                // Head
                const headGeometry = new THREE.SphereGeometry(0.6, 16, 16);
                const headMaterial = new THREE.MeshLambertMaterial({
                    color: 0xff0000,
                }); // Red color
                this.head = new THREE.Mesh(headGeometry, headMaterial);
                this.head.position.y = 2.5;
                this.mesh.add(this.head);

                // Arms
                const armGeometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    1,
                    8
                );
                const armMaterial = new THREE.MeshLambertMaterial({
                    color: 0xff0000,
                });
                // Left Arm
                this.leftArm = new THREE.Mesh(armGeometry, armMaterial);
                this.leftArm.position.set(-0.6, 1.5, 0);
                this.leftArm.rotation.z = Math.PI / 4;
                this.mesh.add(this.leftArm);
                // Right Arm
                this.rightArm = new THREE.Mesh(armGeometry, armMaterial);
                this.rightArm.position.set(0.6, 1.5, 0);
                this.rightArm.rotation.z = -Math.PI / 4;
                this.mesh.add(this.rightArm);

                // Legs
                const legGeometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    1,
                    8
                );
                const legMaterial = new THREE.MeshLambertMaterial({
                    color: 0xff0000,
                });
                // Left Leg
                this.leftLeg = new THREE.Mesh(legGeometry, legMaterial);
                this.leftLeg.position.set(-0.3, -0.5, 0);
                this.mesh.add(this.leftLeg);
                // Right Leg
                this.rightLeg = new THREE.Mesh(legGeometry, legMaterial);
                this.rightLeg.position.set(0.3, -0.5, 0);
                this.mesh.add(this.rightLeg);

                // Weapon (e.g., club)
                const weaponGeometry = new THREE.BoxGeometry(0.2, 1, 0.2);
                const weaponMaterial = new THREE.MeshLambertMaterial({
                    color: 0x654321,
                });
                this.weapon = new THREE.Mesh(
                    weaponGeometry,
                    weaponMaterial
                );
                this.weapon.position.set(0, 1, -0.6);
                this.mesh.add(this.weapon);

                // Position goblin on terrain
                this.mesh.position.set(
                    x,
                    getTerrainHeightAt(x, z) + 1,
                    z
                );

                // Add to scene
                scene.add(this.mesh);

                // Health
                this.health = 100;

                // Movement speed
                this.speed = 0.12;

                // Vertical velocity for gravity
                this.velocityY = 0;

                // Flag to prevent multiple hits per swing
                this.isHit = false;

                // Attack cooldown
                this.attackCooldown = 0;

                // Animation phase for walking
                this.walkPhase = Math.random() * Math.PI * 2; // Random initial phase
                this.walkSpeed = 0.05; // Speed of walking animation

                // Target position for wandering
                this.targetPosition = null;

                // Random movement cooldown
                this.wanderCooldown = 0;

                // State management
                this.state = 'wandering'; // 'wandering', 'approaching_orbit', 'orbiting', 'rearing_back', 'charging', 'pausing'
                this.orbitStartTime = null;
                this.orbitDuration = 2000; // Duration to orbit in milliseconds
                this.angularSpeed = 0.0008; // Radians per millisecond (slower orbit)
                this.orbitRadius = 5; // Orbit radius
                this.orbitAngle = 0;

                this.orbitingClock = new THREE.Clock(false); // Clock to manage orbit duration

                // Variables for smooth transition to orbit
                this.approachSpeed = 0.08; // Speed when approaching orbit position
                this.hasReachedOrbit = false; // Flag to indicate if goblin has reached orbit path

                // Variables for pausing state
                this.pauseStartTime = 0;
                this.pauseDuration = 1000; // Pause duration in milliseconds

                // Variables for rearing back state
                this.rearStartTime = 0;
                this.rearDuration = 1000; // Time in milliseconds to rear back

                // Initial rotation for rearing back animation
                this.originalBodyRotationX = this.body.rotation.x;

                // Charge behavior variables
                this.chargeStopDistance = 3; // Distance at which the goblin stops before the player during charge
            }

            // Method to apply damage to goblin
            takeDamage(amount) {
                this.health -= amount;
                console.log('Goblin hit! Health:', this.health);
                if (this.health <= 0) {
                    this.die();
                }
            }

            // Method to handle goblin death
            die() {
                scene.remove(this.mesh);
                const index = goblins.indexOf(this);
                if (index > -1) {
                    goblins.splice(index, 1);
                }
                console.log('Goblin died!');
                // Drop a coin at goblin's position
                const coinPosition = this.mesh.position.clone();
                coins.push(new Coin(coinPosition));
            }

            // Method to check if goblin can attack the player
            canAttackPlayer() {
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);
                const distance = playerPosition.distanceTo(this.mesh.position);
                return distance < 2; // Attack range
            }

            // Method to attack the player
            attackPlayer() {
                if (this.attackCooldown <= 0) {
                    if (!isBlocking) {
                        playerHealth -= 10; // Damage per attack
                        updateHealthBar();
                        console.log('Player hit! Health:', playerHealth);
                        if (playerHealth <= 0) {
                            gameOver();
                        }
                    } else {
                        console.log('Attack blocked!');
                        // You can add visual or sound effects here
                    }
                    this.attackCooldown = 1000; // Cooldown in milliseconds
                }
            }

            // Apply gravity
            applyGravity(deltaTimeMs) {
                const gravityPerMs = gravity / (1000 / 60); // gravity per millisecond
                this.velocityY += gravityPerMs * deltaTimeMs;
                this.mesh.position.y += this.velocityY * deltaTimeMs;

                // Collision detection with terrain
                const terrainHeight = getInterpolatedHeightAt(this.mesh.position.x, this.mesh.position.z) + 1;
                if (this.mesh.position.y < terrainHeight) {
                    this.mesh.position.y = terrainHeight;
                    this.velocityY = 0;
                }
            }

            // Update method for goblin behavior and animations
            update(deltaTimeMs) {
                const currentTime = performance.now();
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);
                const distanceToPlayer = playerPosition.distanceTo(this.mesh.position);

                if (this.state === 'wandering') {
                    if (distanceToPlayer < 20) {
                        // Begin approaching orbit path
                        this.state = 'approaching_orbit';
                        this.hasReachedOrbit = false;
                        // Compute initial orbit angle based on current position relative to player
                        const vectorToPlayer = new THREE.Vector3().subVectors(this.mesh.position, playerPosition);
                        this.orbitAngle = Math.atan2(vectorToPlayer.z, vectorToPlayer.x);
                    } else {
                        this.wander(deltaTimeMs);
                    }
                } else if (this.state === 'approaching_orbit') {
                    this.approachOrbit(deltaTimeMs);
                    if (this.hasReachedOrbit) {
                        this.state = 'orbiting';
                        this.orbitingClock.start();
                    }
                } else if (this.state === 'orbiting') {
                    this.orbitPlayer(deltaTimeMs);
                    if (this.orbitingClock.getElapsedTime() * 1000 > this.orbitDuration) {
                        this.state = 'rearing_back';
                        this.rearStartTime = currentTime;
                    }
                } else if (this.state === 'rearing_back') {
                    this.rearBack(deltaTimeMs);
                    if (currentTime - this.rearStartTime >= this.rearDuration) {
                        this.state = 'charging';
                        // Reset body rotation after rearing back
                        this.body.rotation.x = this.originalBodyRotationX;
                    }
                } else if (this.state === 'charging') {
                    this.chargeTowardsPlayer(deltaTimeMs);
                    // Check if goblin has reached the stopping distance
                    const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);
                    if (distanceToPlayer <= this.chargeStopDistance) {
                        this.state = 'pausing'; // Switch to pausing state
                        this.pauseStartTime = currentTime;
                        this.pauseDuration = 1000; // Pause for 1 second
                    }
                } else if (this.state === 'pausing') {
                    // Face the player
                    this.facePlayer();

                    // Attack the player if cooldown permits and within attack range
                    if (this.canAttackPlayer()) {
                        this.attackPlayer();
                    }

                    // Check if pause duration has elapsed
                    if (currentTime - this.pauseStartTime >= this.pauseDuration) {
                        this.state = 'orbiting';
                        this.hasReachedOrbit = false; // Reset for next orbit
                        this.orbitingClock.start();
                    }
                }

                // Apply gravity
                this.applyGravity(deltaTimeMs);

                // Update walking animation
                this.updateAnimations(deltaTimeMs);

                if (this.attackCooldown > 0) {
                    this.attackCooldown -= deltaTimeMs;
                }
            }

            // Move towards orbit path smoothly
            approachOrbit(deltaTimeMs) {
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);

                // Desired position on orbit path
                const desiredX = playerPosition.x + Math.cos(this.orbitAngle) * this.orbitRadius;
                const desiredZ = playerPosition.z + Math.sin(this.orbitAngle) * this.orbitRadius;

                const desiredPosition = new THREE.Vector3(desiredX, this.mesh.position.y, desiredZ);

                // Move towards desired position
                const direction = new THREE.Vector3().subVectors(desiredPosition, this.mesh.position);
                const distance = direction.length();
                if (distance < 0.1) {
                    this.hasReachedOrbit = true;
                } else {
                    direction.normalize();
                    const moveDistance = Math.min(this.approachSpeed * deltaTimeMs * 0.06, distance);
                    const moveStep = direction.multiplyScalar(moveDistance);

                    // Check collision before moving
                    if (!checkCollision(this.mesh.position.x + moveStep.x, this.mesh.position.z + moveStep.z, goblinCollisionRadius)) {
                        this.mesh.position.add(moveStep);
                    }

                    // Rotate to face the player
                    const angle = Math.atan2((playerPosition.x - this.mesh.position.x), (playerPosition.z - this.mesh.position.z));
                    this.mesh.rotation.y = angle;
                }
            }

            // Orbiting around the player
            orbitPlayer(deltaTimeMs) {
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);

                // Update orbit angle
                this.orbitAngle += this.angularSpeed * deltaTimeMs;

                const offsetX = Math.cos(this.orbitAngle) * this.orbitRadius;
                const offsetZ = Math.sin(this.orbitAngle) * this.orbitRadius;

                // Assign new position
                this.mesh.position.x = playerPosition.x + offsetX;
                this.mesh.position.z = playerPosition.z + offsetZ;

                // Adjust Y position according to terrain
                this.mesh.position.y = getInterpolatedHeightAt(this.mesh.position.x, this.mesh.position.z) + 1;

                // Face the player
                const direction = new THREE.Vector3().subVectors(playerPosition, this.mesh.position).normalize();
                const angle = Math.atan2(direction.x, direction.z);
                this.mesh.rotation.y = angle;
            }

            // Rearing back before charging
            rearBack(deltaTimeMs) {
                // Animate rearing back by tilting the body backward over time
                const currentTime = performance.now();
                const progress = (currentTime - this.rearStartTime) / this.rearDuration;
                const maxTiltAngle = -Math.PI / 6; // Tilt back up to 30 degrees

                this.body.rotation.x = this.originalBodyRotationX + maxTiltAngle * progress;

                // Optional: Move slightly backward while rearing back
                const backwardStep = 0.02 * deltaTimeMs * 0.06; // Adjust speed as needed
                const backwardDirection = new THREE.Vector3(Math.sin(this.mesh.rotation.y), 0, Math.cos(this.mesh.rotation.y));
                this.mesh.position.sub(backwardDirection.multiplyScalar(backwardStep));
            }

            // Charging towards the player
            chargeTowardsPlayer(deltaTimeMs) {
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);
                const direction = new THREE.Vector3().subVectors(playerPosition, this.mesh.position).normalize();
                const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);

                // If the goblin is within stopping distance, stop moving
                if (distanceToPlayer <= this.chargeStopDistance) {
                    // Stop moving
                    return;
                }

                const chargeSpeed = 0.2; // Faster than normal speed
                const moveStep = direction.multiplyScalar(chargeSpeed * deltaTimeMs * 0.06); // Adjust for deltaTime

                // Check collision before moving
                if (!checkCollision(this.mesh.position.x + moveStep.x, this.mesh.position.z + moveStep.z, goblinCollisionRadius)) {
                    this.mesh.position.add(moveStep);
                }

                // Rotate to face the player
                const angle = Math.atan2(direction.x, direction.z);
                this.mesh.rotation.y = angle;
            }

            // Face the player
            facePlayer() {
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);
                const direction = new THREE.Vector3().subVectors(playerPosition, this.mesh.position).normalize();
                const angle = Math.atan2(direction.x, direction.z);
                this.mesh.rotation.y = angle;
            }

            // Update animations
            updateAnimations(deltaTimeMs) {
                // Only animate walking when moving
                if (this.state === 'wandering' || this.state === 'approaching_orbit' || this.state === 'orbiting' || this.state === 'charging') {
                    this.walkPhase += this.walkSpeed;
                    const armSwing = Math.sin(this.walkPhase) * 0.5; // Swing angle for arms
                    const legSwing = Math.cos(this.walkPhase) * 0.5; // Swing angle for legs

                    // Animate arms
                    this.leftArm.rotation.z = Math.PI / 4 + armSwing;
                    this.rightArm.rotation.z = -Math.PI / 4 - armSwing;

                    // Animate legs
                    this.leftLeg.rotation.x = legSwing;
                    this.rightLeg.rotation.x = -legSwing;
                } else {
                    // Reset animations when not moving
                    this.leftArm.rotation.z = Math.PI / 4;
                    this.rightArm.rotation.z = -Math.PI / 4;
                    this.leftLeg.rotation.x = 0;
                    this.rightLeg.rotation.x = 0;
                }
            }

            // Method to move goblin randomly
            wander(deltaTimeMs) {
                if (!this.targetPosition || this.wanderCooldown <= 0) {
                    // Choose a new random direction
                    const angle = Math.random() * Math.PI * 2;
                    const distance = 5 + Math.random() * 10;
                    this.targetPosition = new THREE.Vector3(
                        this.mesh.position.x + Math.cos(angle) * distance,
                        this.mesh.position.y,
                        this.mesh.position.z + Math.sin(angle) * distance
                    );
                    this.wanderCooldown = 100 + Math.random() * 100;
                } else {
                    const direction = new THREE.Vector3();
                    direction.subVectors(this.targetPosition, this.mesh.position).normalize();
                    const moveStep = direction.multiplyScalar(this.speed * deltaTimeMs * 0.06); // Adjust for deltaTime

                    // Check collision before moving
                    if (!checkCollision(this.mesh.position.x + moveStep.x, this.mesh.position.z + moveStep.z, goblinCollisionRadius)) {
                        this.mesh.position.add(moveStep);
                    }

                    // Rotate to face movement direction
                    const angle = Math.atan2(direction.x, direction.z);
                    this.mesh.rotation.y = angle;

                    // If reached target position
                    if (this.mesh.position.distanceTo(this.targetPosition) < 1) {
                        this.targetPosition = null;
                    }

                    this.wanderCooldown--;
                }
            }
        }

        // Merchant Class Definition
        class Merchant {
            constructor(x, z) {
                this.mesh = new THREE.Group();

                // Body
                const bodyGeometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 8);
                const bodyMaterial = new THREE.MeshLambertMaterial({
                    color: 0x8b4513,
                }); // Brown color
                this.body = new THREE.Mesh(bodyGeometry, bodyMaterial);
                this.body.position.y = 1;
                this.mesh.add(this.body);

                // Head
                const headGeometry = new THREE.SphereGeometry(0.6, 16, 16);
                const headMaterial = new THREE.MeshLambertMaterial({
                    color: 0xffe0bd,
                }); // Skin color
                this.head = new THREE.Mesh(headGeometry, headMaterial);
                this.head.position.y = 2.5;
                this.mesh.add(this.head);

                // Arms
                const armGeometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    1,
                    8
                );
                const armMaterial = new THREE.MeshLambertMaterial({
                    color: 0x8b4513,
                });
                // Left Arm
                this.leftArm = new THREE.Mesh(armGeometry, armMaterial);
                this.leftArm.position.set(-0.6, 1.5, 0);
                this.leftArm.rotation.z = Math.PI / 4;
                this.mesh.add(this.leftArm);
                // Right Arm
                this.rightArm = new THREE.Mesh(armGeometry, armMaterial);
                this.rightArm.position.set(0.6, 1.5, 0);
                this.rightArm.rotation.z = -Math.PI / 4;
                this.mesh.add(this.rightArm);

                // Legs
                const legGeometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    1,
                    8
                );
                const legMaterial = new THREE.MeshLambertMaterial({
                    color: 0x000000,
                }); // Black color for pants
                // Left Leg
                this.leftLeg = new THREE.Mesh(legGeometry, legMaterial);
                this.leftLeg.position.set(-0.3, -0.5, 0);
                this.mesh.add(this.leftLeg);
                // Right Leg
                this.rightLeg = new THREE.Mesh(legGeometry, legMaterial);
                this.rightLeg.position.set(0.3, -0.5, 0);
                this.mesh.add(this.rightLeg);

                // Lantern
                const lanternGeometry = new THREE.SphereGeometry(0.2, 8, 8);
                const lanternMaterial = new THREE.MeshLambertMaterial({ color: 0xffff00 }); // Yellow color for light
                this.lantern = new THREE.Mesh(lanternGeometry, lanternMaterial);
                this.lantern.position.set(0.6, 1, -0.6);
                this.mesh.add(this.lantern);

                // Lantern Light
                this.lanternLight = new THREE.PointLight(0xffffaa, 1, 15);
                this.lanternLight.position.copy(this.lantern.position);
                this.mesh.add(this.lanternLight);

                // Position merchant on terrain
                this.mesh.position.set(x, getTerrainHeightAt(x, z) + 1, z);

                // Add to scene
                scene.add(this.mesh);
            }

            update() {
                // Face the player
                const playerPosition = new THREE.Vector3();
                camera.getWorldPosition(playerPosition);
                const direction = new THREE.Vector3().subVectors(playerPosition, this.mesh.position).normalize();
                const angle = Math.atan2(direction.x, direction.z);
                this.mesh.rotation.y = angle;
            }
        }

        // Coin Class Definition
        class Coin {
            constructor(position) {
                // Create coin mesh
                const coinGeometry = new THREE.CylinderGeometry(0.5, 0.5, 0.1, 32);
                const coinMaterial = new THREE.MeshLambertMaterial({ color: 0xFFD700 });
                this.mesh = new THREE.Mesh(coinGeometry, coinMaterial);
                this.mesh.position.copy(position);
                this.mesh.rotation.x = Math.PI / 2; // Lay the coin flat

                // Animation variables
                this.rotationSpeed = 0.05;
                this.bounceHeight = 0.5;
                this.bounceSpeed = 2;
                this.initialY = position.y;

                scene.add(this.mesh);
            }

            update(deltaTime) {
                // Rotate the coin
                this.mesh.rotation.z += this.rotationSpeed;

                // Bounce the coin up and down
                this.mesh.position.y = this.initialY + Math.sin(performance.now() * 0.002 * this.bounceSpeed) * this.bounceHeight;
            }
        }

        // Variables to manage merchant interaction
        let merchant;
        let canTalkToMerchant = false;
        let shopUIOpen = false;

        // Spawn the merchant at a fixed location
        const merchantX = 0;
        const merchantZ = -30;
        merchant = new Merchant(merchantX, merchantZ);

        // Spawn goblins at random positions
        function spawnGoblins(number) {
            for (let i = 0; i < number; i++) {
                let spawnX, spawnZ;
                // Spawn outside the immediate vicinity of the merchant
                do {
                    spawnX = Math.random() * 400 - 200;
                    spawnZ = Math.random() * 400 - 200;
                } while (Math.hypot(spawnX - merchantX, spawnZ - merchantZ) < 10);
                // Ensure goblin spawns on terrain
                const spawnY = getTerrainHeightAt(spawnX, spawnZ) + 1;
                goblins.push(new Goblin(spawnX, spawnZ));
            }
        }

        spawnGoblins(20); // Spawn 20 goblins

        // In-game time management: Start at 6 AM
        let inGameTime = 6;
        let inGameMinutes = 0;

        // Function to update the sky and lighting based on in-game time
        function updateDayNightCycle(deltaTime) {
            // Increment in-game time
            inGameMinutes += deltaTime;
            if (inGameMinutes >= 60) {
                // Each minute represents an hour
                inGameMinutes = 0;
                inGameTime += 1;
                if (inGameTime >= 24) {
                    inGameTime = 0;
                }
            }

            // Calculate sun position based on in-game time
            const timeFraction = (inGameTime + inGameMinutes / 60) / 24; // 0 to 1
            const theta = Math.PI * (timeFraction - 0.25); // Adjusted to start at sunrise
            const phi = 2 * Math.PI * 0.25; // Fixed azimuthal angle for simplicity

            sun.setFromSphericalCoords(1, theta, phi);
            sky.material.uniforms['sunPosition'].value.copy(sun);
            sunLight.position.copy(sun);

            // Adjust lighting based on time of day
            if (inGameTime >= 6 && inGameTime < 18) {
                // Daytime
                ambientLight.intensity = 0.7;
                sunLight.intensity = 1;
                sunLight.color.set(0xffffff);
            } else {
                // Nighttime
                ambientLight.intensity = 0.2;
                sunLight.intensity = 0.2;
                sunLight.color.set(0x555577); // Dim bluish light
            }

            // Update HUD with current time
            updateTimeDisplay();
        }

        // Update Health Bar
        function updateHealthBar() {
            const healthPercentage = Math.max(playerHealth, 0) / 100; // Ensure non-negative
            healthBar.style.width = `${healthPercentage * 100}%`;
            if (healthPercentage > 0.6) {
                healthBar.style.backgroundColor = 'green';
            } else if (healthPercentage > 0.3) {
                healthBar.style.backgroundColor = 'yellow';
            } else {
                healthBar.style.backgroundColor = 'red';
            }
        }

        // Update Time Display
        function updateTimeDisplay() {
            // Format in-game time to HH:MM AM/PM
            let displayHour = inGameTime;
            let period = 'AM';
            if (displayHour >= 12) {
                period = 'PM';
                if (displayHour > 12) displayHour -= 12;
            }
            if (displayHour === 0) {
                displayHour = 12;
            }
            const displayMinutes = inGameMinutes
                .toString()
                .padStart(2, '0');
            timeDisplay.innerText = `Time: ${displayHour}:${displayMinutes} ${period}`;
        }

        // Increment in-game time by one hour
        function incrementTimeByOneHour() {
            inGameTime += 1;
            if (inGameTime >= 24) {
                inGameTime = 0;
            }
            inGameMinutes = 0;
            // Update sun position and lighting immediately
            updateDayNightCycle(0);
            console.log(
                `Time increased by 1 hour. Current time: ${inGameTime}:00`
            );
        }

        // Handle game over
        function gameOver() {
            gameOverScreen.style.display = 'block';
            // Stop the animation loop
            cancelAnimationFrame(animate.id);
        }

        // Handle game win
        function gameWin() {
            youWinScreen.style.display = 'block';
            // Stop the main animation loop
            cancelAnimationFrame(animate.id);
            // Start the YOU WIN animation
            startWinAnimation();
        }

        // Variables for the YOU WIN screen
        let winScene, winCamera, winRenderer, winObjects = [];

        function startWinAnimation() {
            // Set up the YOU WIN scene
            winScene = new THREE.Scene();
            winCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            winCamera.position.z = 5;

            // Create renderer for the YOU WIN screen
            winRenderer = new THREE.WebGLRenderer({ canvas: document.getElementById('winCanvas'), alpha: true });
            winRenderer.setSize(window.innerWidth, window.innerHeight);

            // Add colorful 3D objects (90s themed)
            const colors = [0xFF00FF, 0x00FFFF, 0xFFFF00, 0xFF0000, 0x00FF00];
            const geometries = [
                new THREE.TorusGeometry(1, 0.4, 16, 100),
                new THREE.SphereGeometry(1, 32, 32),
                new THREE.ConeGeometry(1, 2, 32),
                new THREE.BoxGeometry(1, 1, 1),
                new THREE.DodecahedronGeometry(1)
            ];

            for (let i = 0; i < 20; i++) {
                const material = new THREE.MeshBasicMaterial({ color: colors[i % colors.length], wireframe: true });
                const geometry = geometries[i % geometries.length];
                const mesh = new THREE.Mesh(geometry, material);
                mesh.position.set(
                    Math.random() * 10 - 5,
                    Math.random() * 10 - 5,
                    Math.random() * -10
                );
                mesh.rotationSpeed = Math.random() * 0.05;
                winScene.add(mesh);
                winObjects.push(mesh);
            }

            // Animate the YOU WIN screen
            animateWinScreen();
        }

        function animateWinScreen() {
            requestAnimationFrame(animateWinScreen);

            // Rotate objects
            winObjects.forEach(obj => {
                obj.rotation.x += obj.rotationSpeed;
                obj.rotation.y += obj.rotationSpeed;
            });

            winRenderer.render(winScene, winCamera);
        }

        // Handle window resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);

            if (winCamera && winRenderer) {
                winCamera.aspect = window.innerWidth / window.innerHeight;
                winCamera.updateProjectionMatrix();
                winRenderer.setSize(window.innerWidth, window.innerHeight);
            }
        });

        // Shop functions
        function openShop() {
            shopUI.style.display = 'block';
            shopUIOpen = true;
            controls.unlock();
        }

        function closeShop() {
            shopUI.style.display = 'none';
            shopUIOpen = false;
            controls.lock();
        }

        function buyItem(item, cost) {
            if (playerGold >= cost) {
                playerGold -= cost;
                updateGoldDisplay();
                switch (item) {
                    case 'swordUpgrade':
                        swordDamage += 10;
                        alert('Sword upgraded! Damage increased.');
                        break;
                    case 'healthPotion':
                        playerHealth = Math.min(playerHealth + 50, 100);
                        updateHealthBar();
                        alert('Health restored!');
                        break;
                }
            } else {
                alert('Not enough gold!');
            }
        }

        // Add the Orb (Initially Gray with Purple Light and Aura)
        let orb;
        let orbLight;
        let orbAura;
        let orbActivated = false; // Flag to check if orb is activated

        function createOrb() {
            const orbX = 100; // Orb X position
            const orbZ = 30;  // Orb Z position
            const orbY = getTerrainHeightAt(orbX, orbZ) + 2.5; // Slightly above ground

            // Orb geometry and material (Gray orb)
            const orbGeometry = new THREE.SphereGeometry(1, 32, 32);
            const orbMaterial = new THREE.MeshStandardMaterial({
                color: 0x555555, // Gray color
                emissive: 0x555555,
                emissiveIntensity: 1,
                roughness: 0.5,
                metalness: 0.5,
            });
            orb = new THREE.Mesh(orbGeometry, orbMaterial);
            orb.position.set(orbX, orbY, orbZ);
            scene.add(orb);

            // Purple light
            orbLight = new THREE.PointLight(0x800080, 2, 50); // Purple color
            orbLight.position.set(orbX, orbY, orbZ);
            orbLight.castShadow = true;
            scene.add(orbLight);

            // Purple Aura
            const auraGeometry = new THREE.SphereGeometry(1.5, 32, 32);
            const auraMaterial = new THREE.MeshBasicMaterial({
                color: 0x800080, // Purple color
                transparent: true,
                opacity: 0.5,
            });
            orbAura = new THREE.Mesh(auraGeometry, auraMaterial);
            orbAura.position.copy(orb.position);
            scene.add(orbAura);
        }

        createOrb(); // Call the function to create the orb

        // Check if all goblins are destroyed to activate the orb
        function checkGoblinCount() {
            if (!orbActivated && goblins.length === 0) {
                activateOrb();
            }
        }

        // Activate the orb (change to golden orb)
        function activateOrb() {
            orbActivated = true;
            // Update orb material to golden
            orb.material.color.set(0xFFD700);
            orb.material.emissive.set(0xFFD700);
            orb.material.roughness = 0.3;
            orb.material.metalness = 0.7;

            // Update orb light to golden
            orbLight.color.set(0xFFD700);
            orbLight.intensity = 2;

            // Update aura to golden
            orbAura.material.color.set(0xFFD700);

            console.log('Orb activated!');
        }

        // Animation loop to render the scene
        let lastTime = performance.now();
        function animate() {
            animate.id = requestAnimationFrame(animate);

            const currentTime = performance.now();
            const deltaTimeMs = currentTime - lastTime;
            const deltaTime =
                (deltaTimeMs / 1000) * 60; // Convert to in-game minutes
            lastTime = currentTime;

            // Update day/night cycle
            updateDayNightCycle(deltaTime / 60); // Adjust deltaTime for smoother increment

            let speed = movement.running ? 0.2 : 0.1;
            if (movement.forward) controls.moveForward(speed);
            if (movement.backward) controls.moveForward(-speed);
            if (movement.left) controls.moveRight(-speed);
            if (movement.right) controls.moveRight(speed);

            // Apply gravity to the player
            velocity.y += gravity;
            camera.position.y += velocity.y;

            // Collision detection with terrain for the player
            const terrainHeight =
                getInterpolatedHeightAt(camera.position.x, camera.position.z) +
                1.6; // Adjusted player height for better collision
            if (camera.position.y < terrainHeight) {
                camera.position.y = terrainHeight;
                velocity.y = 0;
            }

            // Update goblins
            goblins.forEach((goblin) => goblin.update(deltaTimeMs));

            // Check if all goblins are destroyed to activate the orb
            checkGoblinCount();

            // Update merchant
            merchant.update();

            // Check if player can talk to merchant
            const distanceToMerchant = camera.position.distanceTo(merchant.mesh.position);
            if (distanceToMerchant < 5 && !shopUIOpen) {
                canTalkToMerchant = true;
                merchantDialog.style.display = 'block';
            } else {
                canTalkToMerchant = false;
                merchantDialog.style.display = 'none';
            }

            // Update coins
            for (let i = coins.length - 1; i >= 0; i--) {
                const coin = coins[i];
                coin.update(deltaTimeMs);

                // Check if player is close enough to pick up the coin
                const playerPosition = camera.position;
                const distance = coin.mesh.position.distanceTo(playerPosition);
                if (distance < 2) {
                    // Remove coin from scene
                    scene.remove(coin.mesh);
                    coins.splice(i, 1);

                    // Increase player gold
                    playerGold += 1;
                    updateGoldDisplay();
                }
            }

            // Animate the orb
            const pulseSpeed = 2; // Pulses per second
            const pulseScale = 0.1; // Scale variation
            orb.scale.set(
                1 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale,
                1 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale,
                1 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale
            );

            // Animate the orb aura
            orbAura.scale.set(
                1.5 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale,
                1.5 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale,
                1.5 + Math.sin(performance.now() * 0.002 * pulseSpeed) * pulseScale
            );

            // Check for collision with the orb when activated
            if (orbActivated) {
                const orbDistance = camera.position.distanceTo(orb.position);
                if (orbDistance < 2) {
                    gameWin();
                }
            }

            // Smoothly interpolate sword rotation for blocking
            const rotationSpeed = 0.1; // Adjust rotation speed (higher is faster)
            swordGroup.rotation.z +=
                (swordRotationTargetZ - swordGroup.rotation.z) * rotationSpeed;

            // Render the scene
            renderer.render(scene, camera);
        }
        animate();

    </script>
</body>
</html>