script_name('grib-map')
script_author("rubin")
script_properties("work-in-pause")
script_version("21.11.2025")
require 'lib.sampfuncs'
require 'lib.moonloader'
sampev = require 'lib.samp.events'
local inicfg = require 'inicfg'
dlstatus = require("moonloader").download_status
local cook, sleep, arenda, grib, time, wh, auto = false, 400, true, {}, os.clock() * 1000, false, false
local map = {}
local pause = false

function main()
	if not isSampLoaded() or not isSampfuncsLoaded() then return end
	while not isSampAvailable() do wait(0) end
    lua_thread.create(script_update.main)
	map_ico = inicfg.load({ })
	inicfg.save(map_ico)
	local interior_coordinates = {
		{ 375.8732, -115.1052, 1001.4922 },
		{ 368.8036, -6.0194, 1001.8516 }
	}
	local font = renderCreateFont("Segoe UI",13,13)
	while true do
		wait(0)
		if save_time ~= nil and (os.time() - save_time) > 5 then
			inicfg.save(map_ico)
			save_time = nil
		end
		if getActiveInterior() ~= 0 then 
			local x, y, z = getCharCoordinates(PLAYER_PED)
			for k,v in pairs(interior_coordinates) do 
				local dist = getDistanceBetweenCoords3d(x, y, z, v[1], v[2], v[3])
				if dist < 30 then 
					local screen_x, screen_y = getScreenResolution()
					local x, y = screen_x / 2, screen_y - 25
					local text = "{6ce609}Чтобы активировать авто-готовку нажми 'G'"
					if cook then 
						text = "{6ce609}Чтобы выключить авто-готовку нажми 'G'"
					end
					x = x - (renderGetFontDrawTextLength(font,text) / 2)
					renderFontDrawText(font, text, x, y, -1)
					if not sampIsCursorActive() and not sampIsDialogActive() and not sampIsChatInputActive() then 
						if wasKeyPressed(71) then 
							cook = not cook
							if cook then 
								sendKey(1024)
							end
						end
					end
				end
			end
		end	
		if wh then
			if not isPauseMenuActive() then
				if pause then
					for key, handle in pairs(map) do
						removeBlip(handle)
					end
					map = {}
					pause = false
				end
				local ddist, x, y, z = 1111111111, 0.0, 0.0, 0.0
				for id,data in pairs(grib) do
					if data.handle == 0 then
						data.handle = addBlipForCoord(data.x, data.y, data.z)
						changeBlipScale(data.handle, 1)
						changeBlipColour(data.handle, 0xFFfff8d4)
					end
				end
			else
				if not pause then
					for id,data in pairs(grib) do
						if data.handle ~= 0 then
							removeBlip(data.handle)
							data.handle = 0
						end
					end
					pause = true
				end
				for key, coord in pairs(map_ico) do
					if map[key] == nil then
						map[key] = addBlipForCoord(coord.x, coord.y, coord.z)
						changeBlipScale(map[key], 1)
						changeBlipColour(map[key], 0xFFfff8d4)
					end
				end
			end
		end
	end
end

function sampev.onSendCommand(cmd)
	if cmd:lower() == '/grib cook' then
		cook = not cook
		if cook then
			sampAddChatMessage(' {FFFFFF}ALT {50FE96}для того чтобы начать готовить грибы. Вы должны быть в закусочной!', 0xFF50FE96)
			sampAddChatMessage(' Остановить скрипт: {FFFFFF}/grib cook{50FE96}', 0xFF50FE96)
		else
			arenda = false
			sampAddChatMessage(' Grib Cook - авто-готовка остановлена', 0xFF50FE96)
		end
		return false
	end
	if cmd:lower() == '/grib map' then
		wh = not wh
		printStringNow((wh and '~G~GRIB MAP~N~ENABLE' or '~R~GRIB MAP~N~DISABLE'), 1000)
		return false
	end
	if cmd:lower() == '/grib reload' then
		thisScript():reload()
		return false
	end
end

function sampev.onServerMessage(color, message)
	if cook and message:find(" Вы приготовили {FFFFFF}'готовые грибы'{6AB1FF}: ") then 
		lua_thread.create(function()
			wait(sleep)
			sendKey(1024)
		end)
	end	
	if cook and (message:find(" Нет места") or message:find(" У вас нет нужных ингредиентов")) then 
		sampAddChatMessage(' Grib Cook - авто-готовка остановлена', 0xFF50FE96)
		cook = false
		arenda = false
	end
end

function sampev.onShowDialog(dialogId, style, title, button1, button2, text)
	if cook and arenda and text:find('Аренда плиты') then
		sampSendDialogResponse(dialogId, 1, 0, '')
		lua_thread.create(function()
			wait(1000)
			sendKey(1024)
		end)
		sampAddChatMessage(' Арендована плита.', 0xFF50FE96)
		return false
	end
	if cook and title:find("Кухня") then 
		sampSendDialogResponse(dialogId, 1, 0, '')
		lua_thread.create(function()
			wait(1000)
			sendKey(1024)
		end)
		return false
	end
end

function sampev.onCreatePickup(id, model, pickupType, pos)
	if model == 1603 or model == 19320 then 
		grib[id] = { x = pos.x, y = pos.y, z = pos.z, handle = 0 }
		if map_ico[string.format('%d%d%d', pos.x, pos.y, pos.z)] == nil then
			map_ico[string.format('%d%d%d', pos.x, pos.y, pos.z)] = { x = pos.x, y = pos.y, z = pos.z }
			save_time = os.time()
		end
	end
end

function sampev.onSendPickedUpPickup(id)
	if grib[id] ~= nil then
		if (os.clock() * 1000 - time) > 3800 then
			time = os.clock() * 1000
		else
			return false
		end
	end
end

function sampev.onDestroyPickup(id)
	if grib[id] ~= nil then
		if grib[id].handle ~= 0 then
			removeBlip(grib[id].handle)
		end
		grib[id] = nil
	end
end

function sendKey(key)
    local _, myId = sampGetPlayerIdByCharHandle(PLAYER_PED)
    local data = allocateMemory(68)
    sampStorePlayerOnfootData(myId, data)
    setStructElement(data, 4, 2, key, false)
    sampSendOnfootData(data)
    freeMemory(data)
end

function isKeyCheckAvailable()
	if not isSampfuncsLoaded() then
		return true
	end
	return not isSampfuncsConsoleActive() and not sampIsChatInputActive() and not sampIsDialogActive()
end

function onScriptTerminate()
	for id,data in pairs(grib) do
		if data.handle ~= 0 then
			removeBlip(data.handle)
			data.handle = 0
		end
	end
end

-->> UPDATE
function openURL(url, fpath)
    local text = ""
    local file_download = false
    local download_final = false


    if doesFileExist(fpath) then
        os.remove(fpath)
    end

    downloadUrlToFile(url, fpath, function(id, status, p1, p2)
        if status == dlstatus.STATUS_ENDDOWNLOADDATA then
            file_download = true
        end
        if status == dlstatus.STATUSEX_ENDDOWNLOAD then
            download_final = true
        end
    end
    )

    repeat
        wait(1000)
    until download_final or file_download

    if file_download then
        local f = io.open(fpath, "r")
        if f then
            text = f:read("*a")
            io.close(f)
        end
        os.remove(fpath)
    end

    if (text:find("Not found") and not text:find('"Not found"')) or text == "" then
        text = ""
        addChatMessage("Не удалось скачать обновление по ссылке:")
        addChatMessage(url)
    end

    return text
end

function addChatMessage(text)
    local tag = string.format("{667dff}[%s]{FFFFFF} ", thisScript().name)
    sampAddChatMessage(tag..text, 0xFFFFFFFF)
end

script_update = {
    version_url = "http://git.deadpoo.net/rubin/grib-map/raw/branch/master/version",
    script_url = "http://git.deadpoo.net/rubin/grib-map/raw/branch/master/grib-map.lua",
    changelog_url = "http://git.deadpoo.net/rubin/grib-map/raw/branch/master/changelog",
    address_ini = string.format("rubin-mods-updates\\%s.ini", thisScript().name),
    main = function()
        if not doesDirectoryExist("moonloader\\config\\rubin-mods-updates") then
            createDirectory("moonloader\\config\\rubin-mods-updates")
        end
        local ini = inicfg.load({
            settings = {
                check_update = true,
                auto_update = true,
                server_version = ""
            }
        }, script_update.address_ini)
        ini.settings.version_url = script_update.version_url
        ini.settings.script_url = script_update.script_url
        ini.settings.changelog_url = script_update.changelog_url
        ini.settings.version = thisScript().version
        ini.settings.script_name = thisScript().name
        local command = (thisScript().name:gsub(" ", "").."-update"):lower()
        sampRegisterChatCommand(command, script_update.command)
        if ini.settings.check_update or ini.settings.auto_update then
            local fpath = os.tmpname()
            local result, text = pcall(openURL, script_update.version_url, fpath)
            if result then
                ini.settings.server_version = text
                if text ~= "" and not string.find(text, thisScript().version) then
                    addChatMessage( string.format("Вышла новая версия '%s'. Текущая: '%s'", text, thisScript().version) )
                    if ini.settings.auto_update then
                        addChatMessage( string.format("Автообновление скрипта включено. Процесс запущен!") )
                        script_update.command()
                    else
                        addChatMessage( string.format("Автообновление скрипта выключено. Обновить самому: /%s", command) )
                    end
                end
            end
        end
        inicfg.save(ini, script_update.address_ini)
        script_update.menu.init()
    end,
    command = function()
        lua_thread.create(function()
            local fpath = os.tmpname()
            local result, text = pcall(openURL, script_update.version_url, fpath)
            if result then
                if text ~= "" and not string.find(text, thisScript().version) then
                    addChatMessage( string.format("Вышла новая версия '%s'. Текущая: '%s'", text, thisScript().version) )
                    local fpath = os.tmpname()
                    local result, text = pcall(openURL, script_update.script_url, fpath)
                    if result and text ~= "" and text:find(thisScript().name:gsub("%-", "%%-")) then
                        local file, error = io.open(thisScript().path, "w")
                        if file ~= nil then
                            file:write(text)
                            file:flush()
                            io.close(file)
                            addChatMessage("Обновление завершено, скрипт перезагружен!")
                            wait(500)
                            thisScript():reload()
                        end
                    end
                else
                    addChatMessage("У Вас установлена последняя версия!")
                end
            end
        end)
    end,
    menu = {
        dialog = {},
        ini = {},
        init = function()
            if not sampIsChatCommandDefined("rubin-mods") then
                sampAddChatMessage("{667dff}[RUBIN MODS]{FFFFFF} Управление обновлениями скриптов: /rubin-mods", 0xFFFFFFFF)
                sampRegisterChatCommand("rubin-mods",script_update.menu.show)
                while true do
                    wait(0)
                    local result, button, list, input = sampHasDialogRespond(2160)
                    if result and button == 1 then
                        if script_update.menu.ini[list+1] ~= nil and script_update.menu.dialog[list+1] ~= nil then
                            script_update.menu.dialog[list+1](script_update.menu.ini[list+1])
                        end
                    end
                    local result, button, list, input = sampHasDialogRespond(2162)
                    if result then
                        if button == 1 then
                            if script_update.menu2.text[list+1] ~= nil and script_update.menu2.dialog[list+1] ~= nil then
                                script_update.menu2.dialog[list+1]()
                            end
                        else
                            script_update.menu.show()
                        end
                    end
                    local result, button, list, input = sampHasDialogRespond(2161)
                    if result then
                        script_update.menu2.show(script_update.menu2.data)
                    end
                end
            end
        end,
        show = function()
            script_update.menu.dialog = {}
            script_update.menu.ini = {}
            local text = ""
            if doesDirectoryExist("moonloader\\config\\rubin-mods-updates") then
                local FileHandle, FileName = findFirstFile("moonloader\\config\\rubin-mods-updates\\*")
                while FileName ~= nil do
                    if FileName ~= nil and FileName ~= ".." and FileName ~= "." and FileName:find("%.ini") then
                        local address = string.format("moonloader\\config\\rubin-mods-updates\\%s", FileName)
                        if doesFileExist(address) then
                            local ini = inicfg.load({}, address)
                            script_update.menu.ini[#script_update.menu.ini+1] = address
                            text = string.format("%s%s\n", text, string.format("%s\t%s%s", ini.settings.script_name, (ini.settings.version == ini.settings.server_version and "{59fc30}" or "{ff0000}"),ini.settings.version))
                            script_update.menu.dialog[#script_update.menu.dialog+1] = function(data)
                               script_update.menu2.show(data)
                            end
                        end
                    end
                    FileName = findNextFile(FileHandle)
                end
                findClose(FileHandle)
            else
                text = "Не найдена директория:\t\n    moonloader\\config\\rubin-mods-updates\t"
            end
            sampShowDialog(2160,"Обновление скриптов: Rubin Mods","Скрипт\tВерсия\n"..text,"Выбрать","Закрыть",5)
        end
    },
    menu2 = {
        data = {},
        text = {},
        dialog = {},
        show = function(data)
            script_update.menu2.data = data
            script_update.menu2.text = {}
            script_update.menu2.dialog = {}
            if doesFileExist(data) then
                local ini = inicfg.load({}, data)
                script_update.menu2.text[#script_update.menu2.text+1] = string.format("Автообновление %s", (ini.settings.auto_update and "{59fc30}ON" or "{ff0000}OFF"))
                script_update.menu2.dialog[#script_update.menu2.dialog+1] = function()
                    ini.settings.auto_update = not ini.settings.auto_update
                    inicfg.save(ini, data)
                    script_update.menu2.show(data)
                end
                if not ini.settings.auto_update then
                    script_update.menu2.text[#script_update.menu2.text+1] = string.format("Проверять обновления %s", (ini.settings.check_update and "{59fc30}ON" or "{ff0000}OFF"))
                    script_update.menu2.dialog[#script_update.menu2.dialog+1] = function()
                        ini.settings.check_update = not ini.settings.check_update
                        inicfg.save(ini, data)
                        script_update.menu2.show(data)
                    end
                end
                script_update.menu2.text[#script_update.menu2.text+1] = string.format("Последние изменения")
                script_update.menu2.dialog[#script_update.menu2.dialog+1] = function()
                    script_update.changelog(ini.settings.changelog_url, ini.settings.script_name)
                end
                script_update.menu2.text[#script_update.menu2.text+1] = string.format("Удалить из списка")
                script_update.menu2.dialog[#script_update.menu2.dialog+1] = function()
                    os.remove(data)
                    script_update.menu.show()
                end
                local text = ""
                for i = 1, #script_update.menu2.text do
                    text = text..script_update.menu2.text[i].."\n"
                end
                sampShowDialog(2162,"Настройки обновления для "..ini.settings.script_name,text,"Выбрать","Назад",2)
            end
        end
    },
    changelog = function(url, name)
        local fpath = os.tmpname()
        local result, text = pcall(openURL, url, fpath)
        if result then
            sampShowDialog(2161,"Changelog - "..name,text,"Выбрать","Назад",4)
        end
    end
}

-->> SCRIPT UTF-8
-->> utf8(table path, incoming variables encoding, outcoming variables encoding)
-->> table path example { "sampev", "onShowDialog" }
-->> encoding options nil | AnsiToUtf8 | Utf8ToAnsi
_utf8 = load([=[return function(utf8_func, in_encoding, out_encoding); if encoding == nil then; encoding = require("encoding"); encoding.default = "CP1251"; u8 = encoding.UTF8; end; if type(utf8_func) ~= "table" then; return false; end; if AnsiToUtf8 == nil or Utf8ToAnsi == nil then; AnsiToUtf8 = function(text); return u8(text); end; Utf8ToAnsi = function(text); return u8:decode(text); end; end; if _UTF8_FUNCTION_SAVE == nil then; _UTF8_FUNCTION_SAVE = {}; end; local change_var = "_G"; for s = 1, #utf8_func do; change_var = string.format('%s["%s"]', change_var, utf8_func[s]); end; if _UTF8_FUNCTION_SAVE[change_var] == nil then; _UTF8_FUNCTION = function(...); local pack = table.pack(...); readTable = function(t, enc); for k, v in next, t do; if type(v) == 'table' then; readTable(v, enc); else; if enc ~= nil and (enc == "AnsiToUtf8" or enc == "Utf8ToAnsi") then; if type(k) == "string" then; k = _G[enc](k); end; if type(v) == "string" then; t[k] = _G[enc](v); end; end; end; end; return t; end; return table.unpack(readTable({_UTF8_FUNCTION_SAVE[change_var](table.unpack(readTable(pack, in_encoding)))}, out_encoding)); end; local text = string.format("_UTF8_FUNCTION_SAVE['%s'] = %s; %s = _UTF8_FUNCTION;", change_var, change_var, change_var); load(text)(); _UTF8_FUNCTION = nil; end; return true; end]=])
function utf8(...)
    pcall(_utf8(), ...)
end

utf8({ "sampShowDialog" }, "Utf8ToAnsi")
utf8({ "sampSendChat" }, "Utf8ToAnsi")
utf8({ "sampAddChatMessage" }, "Utf8ToAnsi")
utf8({ "renderFontDrawText" }, "Utf8ToAnsi")
utf8({ "print" }, "Utf8ToAnsi")
utf8({ "sampHasDialogRespond" }, nil, "AnsiToUtf8")
utf8({ "sampev", "onShowDialog" }, "AnsiToUtf8", "Utf8ToAnsi")
utf8({ "sampev", "onServerMessage" }, "AnsiToUtf8", "Utf8ToAnsi")