script_name('map renderer')
script_author('[RAF]Pavel')
script_description('lets you view the map without the pause menu by pressing M, as well as teleport to any point on the map by clickng on it with left mouse button with chat open')
local SE = require 'lib.samp.events'
local key = require 'lib.vkeys'
local font_flag = require('moonloader').font_flag
local arial = renderCreateFont('Arial', 15, font_flag.BOLD + font_flag.BORDER)
local is_map_being_rendered = false
local map_texture = false
local marker_table = {}
function main()
    if not doesDirectoryExist("moonloader/map") then
        createDirectory("moonloader/map")
    end
    while true do
        wait(40)
        if isKeyDown(key.VK_NUMPAD0) and not sampIsChatInputActive() and not sampIsDialogActive() and not sampIsScoreboardOpen() then
            while isKeyDown(key.VK_NUMPAD0) do wait(80) end
            renderMap()
        end
    end
    repeat wait(0) until isSampAvailable()
    while true do
        wait(0)
    end
end
function onScriptTerminate(s, quitGame)
    if not quitGame and s == thisScript() then
        for _, marker in ipairs(marker_table) do
            marker = nil
        end
        marker_table = nil
        map_texture = nil
        is_map_being_rendered = nil
    end
end
function SE.onMarkersSync(markers)
    for _, marker in ipairs(marker_table) do
        marker.active = false
    end
    for i, marker in ipairs(markers) do
        marker_table[i] = {playerId = marker.playerId, active = marker.active, coords = marker.coords}
    end
    return markers
end
function renderMap(mode)
    if not is_map_being_rendered then
        is_map_being_rendered = true
        lua_thread.create(function()
            if not map_texture then
                if not doesFileExist("moonloader/map/map.png") then
                    sampAddChatMessage("please add a map image file named 'map.png' to moonloader/map", 0xFF0000)
                    is_map_being_rendered = false
                    return
                end
                map_texture = renderLoadTextureFromFile("moonloader/map/map.png")
            end
            local sx, sy, map_size, multiplier, top_x, bottom_x, top_y, bottom_y, posx, posy, posz, world_x, world_y, x, y, color
            local cursor_x, cursor_y, cursor_world_x, cursor_world_y, cursor_world_z, player_max_id
            local closest_player, closest_distance, closest_x, closest_y, closest_z, distance
            while is_map_being_rendered do
                if not sampIsDialogActive() and not sampIsScoreboardOpen() then
                    posx, posy, posz = getCharCoordinates(playerPed)
                    sx, sy = getScreenResolution()
                    map_size = math.floor(sy * 0.8)
                    multiplier = map_size / 6000
                    top_x = sx / 2 - map_size / 2
                    bottom_x = top_x + map_size
                    top_y = sy * 0.1
                    bottom_y = top_y + map_size
                    renderDrawTexture(map_texture, top_x, top_y, map_size, map_size, 0, 0xFFFFFFFF)
                    closest_player = -1
                    closest_distance = math.huge
                    if sampIsCursorActive() then
                        cursor_x, cursor_y = getCursorPos()
                    end
                    player_max_id = sampGetMaxPlayerId(false)
                    for _, marker in ipairs(marker_table) do
                        if marker.active == true and sampIsPlayerConnected(marker.playerId) then
                            world_x, world_y = limitToMap(unsignedToSigned(marker.coords.x), unsignedToSigned(marker.coords.y))
                            x = top_x + (world_x + 3000) * multiplier
                            y = top_y + map_size - (world_y + 3000) * multiplier
                            color = 0xFF000000 + sampGetPlayerColor(marker.playerId) % 0x1000000
                            distance = getDistanceBetweenCoords2d(x, y, cursor_x, cursor_y)
                            if distance < 500 then
                                closest_distance = distance
                                closest_player = marker.playerId
                                closest_x, closest_y, closest_z = unsignedToSigned(marker.coords.x), unsignedToSigned(marker.coords.y), unsignedToSigned(marker.coords.z)
                            end
                            if unsignedToSigned(marker.coords.z) > posz + 5 then
                                renderDrawPolygon(x, y, 21, 21, 3, 0, 0xFF000000)
                                renderDrawPolygon(x, y, 15, 15, 3, 0, color)
                            elseif unsignedToSigned(marker.coords.z) < posz - 5 then
                                renderDrawPolygon(x, y, 21, 21, 3, 180, 0xFF000000)
                                renderDrawPolygon(x, y, 15, 15, 3, 180, color)
                            else
                                renderDrawBox(x - 6, y - 6, 12, 12, 0xFF000000)
                                renderDrawBox(x - 5, y - 5, 10, 10, color)
                            end
                        end
                    end
                    posx, posy = limitToMap(posx, posy)
                    x = top_x + (posx + 3000) * multiplier
                    y = top_y + map_size - (posy + 3000) * multiplier
                    renderDrawLine(x + 5, top_y, x + 5, bottom_y, 5, 0xFF000000)
                    renderDrawLine(top_x, y, bottom_x, y, 5, 0xFF000000)
                    renderDrawLine(x + 2, top_y - 2, x + 2, bottom_y - 2, 2, 0xFF00FF00)
                    renderDrawLine(top_x - 2, y, bottom_x - 2, y, 2, 0xFF00FF00)
                    
                    if sampIsCursorActive() then
                        cursor_world_x, cursor_world_y, cursor_world_z = (cursor_x - top_x) / multiplier - 3000, (top_y + map_size - cursor_y) / multiplier - 3000, getGroundZFor3dCoord(cursor_world_x, cursor_world_y, 600) + 1
                        if closest_distance < 10 then
                            cursor_world_x, cursor_world_y, cursor_world_z = closest_x, closest_y + 2, closest_z + 1
                            renderFontDrawText(arial, '[' .. closest_player .. '] ' .. sampGetPlayerNickname(closest_player), cursor_x, cursor_y - 25, 0xFF000000 + sampGetPlayerColor(closest_player) % 0x1000000)
                        end
                        if isKeyDown(key.VK_LBUTTON) then
                            setCharCoordinates(playerPed, cursor_world_x, cursor_world_y, cursor_world_z)
                        end
                    end
                end
                wait(0)
            end
        end)
    else
        is_map_being_rendered = false
    end
end
function unsignedToSigned(x)
    if x > 32767 then
        return x - 65536
    end
    return x
end
function limitToMap(x, y)
    if x > 3000 then
        x = 3000
    elseif x < -3000 then
        x = -3000
    end
    if y > 3000 then
        y = 3000
    elseif y < -3000 then
        y = -3000
    end
    return x, y
end