fix initial scan failed
failed to find enemy position
failed to find enemy position. retrying in 1 second
starting intial unkown scan for enemy x position
Error: first scan failed --[[
    Final Lua Script for Cheat Engine
    Purpose: Memory Scanning and Manipulation for Enemy and Player Aim Positions
    Author: [Your Name]
    Date: [Today's Date]
--]]

-- ==================== Configuration ====================

-- Define scan options if not already defined
-- These constants are typically predefined in Cheat Engine, but defining them ensures compatibility
if soUnknownInitialValue == nil then soUnknownInitialValue = 0 end -- "Unknown initial value" scan option
if soUnknownValueChanged == nil then soUnknownValueChanged = 6 end -- "Unknown value changed" scan option

-- Define value types
-- Adjust based on how the game represents position data
-- Common types: vtFloat = 0, vtDouble = 1, vtByte = 2, vtWord = 3, vtDword = 4
if vtFloat == nil then vtFloat = 0 end
if vtDword == nil then vtDword = 4 end

-- Select the value type you need (commonly vtFloat for positions)
local VALUE_TYPE = vtFloat

-- ==================== Utility Functions ====================

-- Function to read a 32-bit integer or float from memory
function readValue(address, valueType)
    if valueType == vtDword then
        local value = readInteger(address)
        if value == nil then
            print(string.format("Error: Failed to read integer from address 0x%X", address))
            return nil
        end
        return tonumber(value)
    elseif valueType == vtFloat then
        local value = readFloat(address)
        if value == nil then
            print(string.format("Error: Failed to read float from address 0x%X", address))
            return nil
        end
        return tonumber(value)
    else
        print("Error: Unsupported value type.")
        return nil
    end
end

-- Function to write a 32-bit integer or float to memory
function writeValue(address, value, valueType)
    local success
    if valueType == vtDword then
        success = writeInteger(address, value)
    elseif valueType == vtFloat then
        success = writeFloat(address, value)
    else
        print("Error: Unsupported value type.")
        return
    end

    if not success then
        print(string.format("Error: Failed to write value to address 0x%X", address))
    end
end

-- Function to perform an initial unknown value scan
function initialScanUnknown(scanOption)
    local memscan = createMemScan()
    if not memscan then
        print("Error: Failed to create memscan object.")
        return false, nil
    end

    -- Start the initial scan with the correct scan option
    local scanSuccess = memscan.FirstScan(scanOption, VALUE_TYPE, "", 0, 0, "", "", "")
    if not scanSuccess then
        print("Error: FirstScan failed.")
        memscan.destroy()
        return false, nil
    end

    local foundlist = memscan.FoundList
    if not foundlist then
        print("Error: FoundList is nil after FirstScan.")
        memscan.destroy()
        return false, nil
    end

    -- Initialize the found list
    local initSuccess, initError = pcall(function() foundlist.Initialize() end)
    if not initSuccess then
        print("Error: Failed to initialize FoundList. Details:", initError)
        memscan.destroy()
        return false, nil
    end

    -- Check if foundlist is valid
    if not foundlist or foundlist.Count == nil then
        print("Error: FoundList is invalid after initialization.")
        memscan.destroy()
        return false, nil
    end

    memscan.destroy()

    if foundlist.Count > 0 then
        print(string.format("Initial scan successful. %d results found.", foundlist.Count))
        return true, foundlist
    else
        print("No results found in FoundList after initial scan.")
        return false, nil
    end
end

-- Function to perform a narrow down unknown value changed scan
function narrowDownScanUnknown(foundlist, scanOption)
    if not foundlist then
        print("Error: Provided foundlist is nil.")
        return false, nil
    end

    local memscan = createMemScan()
    if not memscan then
        print("Error: Failed to create memscan object.")
        return false, nil
    end

    -- Begin the narrow down scan with the correct scan option
    local beginSuccess = memscan.BeginScan(foundlist, scanOption, VALUE_TYPE, "", 0, 0, "", "", "")
    if not beginSuccess then
        print("Error: BeginScan failed.")
        memscan.destroy()
        return false, nil
    end

    local updateSuccess = memscan.UpdateScan()
    if not updateSuccess then
        print("Error: UpdateScan failed.")
        memscan.destroy()
        return false, nil
    end

    local newFoundList = memscan.FoundList
    if not newFoundList then
        print("Error: FoundList is nil after narrow down scan.")
        memscan.destroy()
        return false, nil
    end

    -- Initialize the new found list
    local initSuccess, initError = pcall(function() newFoundList.Initialize() end)
    if not initSuccess then
        print("Error: Failed to initialize new FoundList. Details:", initError)
        memscan.destroy()
        return false, nil
    end

    memscan.destroy()

    if newFoundList.Count > 0 then
        print(string.format("Narrow down scan successful. %d results found.", newFoundList.Count))
        return true, newFoundList
    else
        print("No results found in new FoundList after narrow down scan.")
        return false, nil
    end
end

-- Function to find a unique address by repeatedly narrowing down the scan
function findUniqueAddress(initialScanOption, narrowScanOption, promptMessage)
    -- Perform initial scan
    local success, foundlist = initialScanUnknown(initialScanOption)
    if not success then
        print("Initial scan failed.")
        return nil
    end

    -- Repeat narrowing down until one address is found or no results remain
    while foundlist.Count > 1 do
        print(promptMessage)
        -- Wait for user input to proceed (manual change in game state)
        io.read()

        -- Perform narrow down scan
        local successNarrow, newFoundList = narrowDownScanUnknown(foundlist, narrowScanOption)
        if not successNarrow then
            print("Narrow down scan failed.")
            foundlist.destroy()
            return nil
        end

        -- Destroy previous found list and update to new one
        foundlist.destroy()
        foundlist = newFoundList
    end

    -- Check if exactly one result is found
    if foundlist.Count == 1 then
        local addressList = foundlist.Address
        if addressList and addressList[0] then
            local address = addressList[0]
            foundlist.destroy()
            print(string.format("Unique address found: 0x%X", address))
            return address
        else
            print("Error: Address list is invalid.")
            foundlist.destroy()
            return nil
        end
    else
        print("Failed to uniquely identify the address.")
        foundlist.destroy()
        return nil
    end
end

-- Function to find the enemy's position
function findEnemyPosition()
    print("Starting initial unknown scan for enemy X position...")
    local enemyXAddress = findUniqueAddress(
        soUnknownInitialValue,
        soUnknownValueChanged,
        "Change the enemy's position in-game and press Enter..."
    )
    if not enemyXAddress then
        print("Failed to find enemy position.")
        return nil, nil, nil, nil
    end

    print(string.format("Enemy X Address Found: 0x%X", enemyXAddress))

    -- Read Y and Z positions based on known offsets
    local enemyYAddress = enemyXAddress + 4  -- Assuming 4 bytes per coordinate
    local enemyZAddress = enemyXAddress + 8

    local enemyX = readValue(enemyXAddress, VALUE_TYPE)
    local enemyY = readValue(enemyYAddress, VALUE_TYPE)
    local enemyZ = readValue(enemyZAddress, VALUE_TYPE)

    if enemyX == nil or enemyY == nil or enemyZ == nil then
        print("Error: Failed to read one or more enemy position values.")
        return nil, nil, nil, nil
    end

    print(string.format("Enemy Position: X=%.2f, Y=%.2f, Z=%.2f", enemyX, enemyY, enemyZ))
    return enemyX, enemyY, enemyZ, enemyXAddress
end

-- Function to find the player's aim position
function findPlayerAimPosition()
    print("Starting initial unknown scan for player aim X position...")
    local playerAimXAddress = findUniqueAddress(
        soUnknownInitialValue,
        soUnknownValueChanged,
        "Change the player's aim in-game and press Enter..."
    )
    if not playerAimXAddress then
        print("Failed to find player aim position.")
        return nil, nil, nil, nil
    end

    print(string.format("Player Aim X Address Found: 0x%X", playerAimXAddress))

    -- Read Y and Z positions based on known offsets
    local playerAimYAddress = playerAimXAddress + 4  -- Assuming 4 bytes per coordinate
    local playerAimZAddress = playerAimXAddress + 8

    local playerAimX = readValue(playerAimXAddress, VALUE_TYPE)
    local playerAimY = readValue(playerAimYAddress, VALUE_TYPE)
    local playerAimZ = readValue(playerAimZAddress, VALUE_TYPE)

    if playerAimX == nil or playerAimY == nil or playerAimZ == nil then
        print("Error: Failed to read one or more player aim position values.")
        return nil, nil, nil, nil
    end

    print(string.format("Player Aim Position: X=%.2f, Y=%.2f, Z=%.2f", playerAimX, playerAimY, playerAimZ))
    return playerAimX, playerAimY, playerAimZ, playerAimXAddress
end

-- Function to calculate the aim offset
function calculateAimOffset(enemyX, enemyY, enemyZ, playerAimX, playerAimY, playerAimZ)
    -- Calculate the offset to aim at the enemy's head
    local offsetX = enemyX - playerAimX
    local offsetY = enemyY - playerAimY
    local offsetZ = enemyZ - playerAimZ

    -- Adjust the aim (this is a simple example, you may need to fine-tune the values)
    local newAimX = playerAimX + offsetX
    local newAimY = playerAimY + offsetY
    local newAimZ = playerAimZ + offsetZ

    return newAimX, newAimY, newAimZ
end

-- ==================== Main Loop ====================

-- Function to safely destroy foundlist
function safeDestroy(foundlist)
    if foundlist and foundlist.destroy then
        foundlist:destroy()
    end
end

-- Main loop
while true do
    ::continue:: -- Label moved to the beginning of the loop

    -- Find the enemy's position
    local enemyX, enemyY, enemyZ, enemyXAddress = findEnemyPosition()
    if not enemyX or not enemyY or not enemyZ then
        print("Failed to find enemy position. Retrying in 1 second...")
        sleep(1000) -- Sleep for 1 second
        goto continue
    end

    -- Find the player's aim position
    local playerAimX, playerAimY, playerAimZ, playerAimXAddress = findPlayerAimPosition()
    if not playerAimX or not playerAimY or not playerAimZ then
        print("Failed to find player aim position. Retrying in 1 second...")
        sleep(1000) -- Sleep for 1 second
        goto continue
    end

    -- Calculate the aim offset
    local newAimX, newAimY, newAimZ = calculateAimOffset(
        enemyX, enemyY, enemyZ,
        playerAimX, playerAimY, playerAimZ
    )

    -- Write the new aim position back to memory
    writeValue(playerAimXAddress, newAimX, VALUE_TYPE)
    writeValue(playerAimXAddress + 4, newAimY, VALUE_TYPE)
    writeValue(playerAimXAddress + 8, newAimZ, VALUE_TYPE)

    print(string.format("Aim adjusted to X=%.2f, Y=%.2f, Z=%.2f", newAimX, newAimY, newAimZ))

    -- Sleep to avoid high CPU usage
    sleep(10) -- Sleep for 10 milliseconds
end