SlonPvpru

[ARZ] J-Helper

Jun 4th, 2020
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 45.61 KB | None | 0 0
  1. -- https://vk.com/jfama
  2.  
  3. script_name('HelperLovli')
  4. script_author('#leomasker')
  5. local version = 'test-release'
  6.  
  7. local MASLOSYKA = {"Family", "Dynasty", "Corporation", "Squad", "Crew", "Empire", "Brotherhood"}
  8. local q = require 'lib.samp.events'
  9. local inicfg = require 'inicfg'
  10. local vkeys = require 'vkeys'
  11. local imgui = require 'imgui'
  12. local mem = require 'memory'
  13. local bNotf, notf = pcall(import, "imgui_notf.lua")
  14. local time = nil
  15. local captime = nil
  16. local hfind = 0
  17. local forFind = {}
  18. local houses = {}
  19. local t = 0
  20. local payday = false
  21. local captcha = ''
  22. local captchaTable = {}
  23.  
  24. local HLcfg = inicfg.load({
  25.     main = {
  26.         activation = 'helper',
  27.         nClear = false,
  28.         jtext = 'j family naxyi',
  29.         resetpd = false,
  30.         utime = false,
  31.         ptime = false,
  32.         HLmsg = false,
  33.         max5 = false,
  34.         plus3click = false,
  35.         floodN = false,
  36.         autofind = false,
  37.         onkey = false,
  38.         key = 'U',
  39.         texttime = false,
  40.         theme = 1,
  41.         autoenter = false
  42.     }
  43. }, "HelperLovli")
  44.  
  45. local encoding = require 'encoding'
  46. encoding.default = 'CP1251'
  47. u8 = encoding.UTF8
  48. local tags = imgui.ImBool(false)
  49. local main_window_state = imgui.ImBool(false)
  50. buffer = imgui.ImBuffer(tostring(HLcfg.main.jtext), 256)
  51. buffer.v = string.gsub(tostring(buffer.v), '"', '')
  52. keybuff = imgui.ImBuffer(tostring(HLcfg.main.key), 5)
  53. buffermenu = imgui.ImBuffer(tostring(HLcfg.main.activation), 256)
  54.  
  55. function apply_custom_style()
  56.     imgui.SwitchContext()
  57.     local style = imgui.GetStyle()
  58.     style.WindowTitleAlign = imgui.ImVec2(0.5, 0.5)
  59.     local Colors = style.Colors
  60.     local ImVec4 = imgui.ImVec4
  61.     local ImVec2 = imgui.ImVec2
  62.     style.Alpha = 1
  63.     style.ChildWindowRounding = 15
  64.     style.WindowRounding = 15
  65.     style.GrabRounding = 15
  66.     style.GrabMinSize = 20
  67.     style.FrameRounding = 10
  68.     Colors[imgui.Col.Text] = ImVec4(0.80, 0.80, 0.83, 1.00)
  69.     Colors[imgui.Col.TextDisabled] = ImVec4(0.24, 0.23, 0.29, 1.00)
  70.     Colors[imgui.Col.WindowBg] = ImVec4(0.06, 0.05, 0.07, 1.00)
  71.     Colors[imgui.Col.ChildWindowBg] = ImVec4(0.07, 0.07, 0.09, 1.00)
  72.     Colors[imgui.Col.PopupBg] = ImVec4(0.07, 0.07, 0.09, 1.00)
  73.     Colors[imgui.Col.Border] = ImVec4(0.80, 0.80, 0.83, 0.88)
  74.     Colors[imgui.Col.BorderShadow] = ImVec4(0.92, 0.91, 0.88, 0.00)
  75.     Colors[imgui.Col.FrameBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
  76.     Colors[imgui.Col.FrameBgHovered] = ImVec4(0.24, 0.23, 0.29, 1.00)
  77.     Colors[imgui.Col.FrameBgActive] = ImVec4(0.56, 0.56, 0.58, 1.00)
  78.     Colors[imgui.Col.TitleBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
  79.     Colors[imgui.Col.TitleBgCollapsed] = ImVec4(1.00, 0.98, 0.95, 0.75)
  80.     Colors[imgui.Col.TitleBgActive] = ImVec4(0.07, 0.07, 0.09, 1.00)
  81.     Colors[imgui.Col.MenuBarBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
  82.     Colors[imgui.Col.ScrollbarBg] = ImVec4(0.10, 0.09, 0.12, 1.00)
  83.     Colors[imgui.Col.ScrollbarGrab] = ImVec4(0.80, 0.80, 0.83, 0.31)
  84.     Colors[imgui.Col.ScrollbarGrabHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
  85.     Colors[imgui.Col.ScrollbarGrabActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
  86.     Colors[imgui.Col.ComboBg] = ImVec4(0.19, 0.18, 0.21, 1.00)
  87.     Colors[imgui.Col.CheckMark] = ImVec4(0.80, 0.80, 0.83, 0.31)
  88.     Colors[imgui.Col.SliderGrab] = ImVec4(0.80, 0.80, 0.83, 0.31)
  89.     Colors[imgui.Col.SliderGrabActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
  90.     Colors[imgui.Col.Button] = ImVec4(0.15, 0.15, 0.18, 1.00)
  91.     Colors[imgui.Col.ButtonHovered] = ImVec4(0.24, 0.23, 0.29, 1.00)
  92.     Colors[imgui.Col.ButtonActive] = ImVec4(0.56, 0.56, 0.58, 1.00)
  93.     Colors[imgui.Col.Header] = ImVec4(0.10, 0.09, 0.12, 1.00)
  94.     Colors[imgui.Col.HeaderHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
  95.     Colors[imgui.Col.HeaderActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
  96.     Colors[imgui.Col.ResizeGrip] = ImVec4(0.00, 0.00, 0.00, 0.00)
  97.     Colors[imgui.Col.ResizeGripHovered] = ImVec4(0.56, 0.56, 0.58, 1.00)
  98.     Colors[imgui.Col.ResizeGripActive] = ImVec4(0.06, 0.05, 0.07, 1.00)
  99.     Colors[imgui.Col.CloseButton] = ImVec4(0.40, 0.39, 0.38, 0.16)
  100.     Colors[imgui.Col.CloseButtonHovered] = ImVec4(0.40, 0.39, 0.38, 0.39)
  101.     Colors[imgui.Col.CloseButtonActive] = ImVec4(0.40, 0.39, 0.38, 1.00)
  102.     Colors[imgui.Col.PlotLines] = ImVec4(0.40, 0.39, 0.38, 0.63)
  103.     Colors[imgui.Col.PlotLinesHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
  104.     Colors[imgui.Col.PlotHistogram] = ImVec4(0.40, 0.39, 0.38, 0.63)
  105.     Colors[imgui.Col.PlotHistogramHovered] = ImVec4(0.25, 1.00, 0.00, 1.00)
  106.     Colors[imgui.Col.TextSelectedBg] = ImVec4(0.25, 1.00, 0.00, 0.43)
  107.     Colors[imgui.Col.ModalWindowDarkening] = ImVec4(1.00, 0.98, 0.95, 0.73)
  108. end
  109.  
  110. function lightBlue()
  111.     imgui.SwitchContext()
  112.     local style = imgui.GetStyle()
  113.     local colors = style.Colors
  114.     local clr = imgui.Col
  115.     local ImVec4 = imgui.ImVec4
  116.  
  117.     colors[clr.Text]   = ImVec4(0.00, 0.00, 0.00, 0.51)
  118.     colors[clr.TextDisabled]   = ImVec4(0.24, 0.24, 0.24, 1.00)
  119.     colors[clr.WindowBg]              = ImVec4(1.00, 1.00, 1.00, 1.00)
  120.     colors[clr.ChildWindowBg]         = ImVec4(0.96, 0.96, 0.96, 1.00)
  121.     colors[clr.PopupBg]               = ImVec4(0.92, 0.92, 0.92, 1.00)
  122.     colors[clr.Border]                = ImVec4(0.86, 0.86, 0.86, 1.00)
  123.     colors[clr.BorderShadow]          = ImVec4(0.00, 0.00, 0.00, 0.00)
  124.     colors[clr.FrameBg]               = ImVec4(0.88, 0.88, 0.88, 1.00)
  125.     colors[clr.FrameBgHovered]        = ImVec4(0.82, 0.82, 0.82, 1.00)
  126.     colors[clr.FrameBgActive]         = ImVec4(0.76, 0.76, 0.76, 1.00)
  127.     colors[clr.TitleBg]               = ImVec4(0.00, 0.45, 1.00, 0.82)
  128.     colors[clr.TitleBgCollapsed]      = ImVec4(0.00, 0.45, 1.00, 0.82)
  129.     colors[clr.TitleBgActive]         = ImVec4(0.00, 0.45, 1.00, 0.82)
  130.     colors[clr.MenuBarBg]             = ImVec4(0.00, 0.37, 0.78, 1.00)
  131.     colors[clr.ScrollbarBg]           = ImVec4(0.00, 0.00, 0.00, 0.00)
  132.     colors[clr.ScrollbarGrab]         = ImVec4(0.00, 0.35, 1.00, 0.78)
  133.     colors[clr.ScrollbarGrabHovered]  = ImVec4(0.00, 0.33, 1.00, 0.84)
  134.     colors[clr.ScrollbarGrabActive]   = ImVec4(0.00, 0.31, 1.00, 0.88)
  135.     colors[clr.ComboBg]               = ImVec4(0.92, 0.92, 0.92, 1.00)
  136.     colors[clr.CheckMark]             = ImVec4(0.00, 0.49, 1.00, 0.59)
  137.     colors[clr.SliderGrab]            = ImVec4(0.00, 0.49, 1.00, 0.59)
  138.     colors[clr.SliderGrabActive]      = ImVec4(0.00, 0.39, 1.00, 0.71)
  139.     colors[clr.Button]                = ImVec4(0.00, 0.49, 1.00, 0.59)
  140.     colors[clr.ButtonHovered]         = ImVec4(0.00, 0.49, 1.00, 0.71)
  141.     colors[clr.ButtonActive]          = ImVec4(0.00, 0.49, 1.00, 0.78)
  142.     colors[clr.Header]                = ImVec4(0.00, 0.49, 1.00, 0.78)
  143.     colors[clr.HeaderHovered]         = ImVec4(0.00, 0.49, 1.00, 0.71)
  144.     colors[clr.HeaderActive]          = ImVec4(0.00, 0.49, 1.00, 0.78)
  145.     colors[clr.ResizeGrip]            = ImVec4(0.00, 0.39, 1.00, 0.59)
  146.     colors[clr.ResizeGripHovered]     = ImVec4(0.00, 0.27, 1.00, 0.59)
  147.     colors[clr.ResizeGripActive]      = ImVec4(0.00, 0.25, 1.00, 0.63)
  148.     colors[clr.CloseButton]           = ImVec4(0.00, 0.35, 0.96, 0.71)
  149.     colors[clr.CloseButtonHovered]    = ImVec4(0.00, 0.31, 0.88, 0.69)
  150.     colors[clr.CloseButtonActive]     = ImVec4(0.00, 0.25, 0.88, 0.67)
  151.     colors[clr.PlotLines]             = ImVec4(0.00, 0.39, 1.00, 0.75)
  152.     colors[clr.PlotLinesHovered]      = ImVec4(0.00, 0.39, 1.00, 0.75)
  153.     colors[clr.PlotHistogram]         = ImVec4(0.00, 0.39, 1.00, 0.75)
  154.     colors[clr.PlotHistogramHovered]  = ImVec4(0.00, 0.35, 0.92, 0.78)
  155.     colors[clr.TextSelectedBg]        = ImVec4(0.00, 0.47, 1.00, 0.59)
  156.     colors[clr.ModalWindowDarkening]  = ImVec4(0.20, 0.20, 0.20, 0.35)
  157. end
  158.  
  159. function redTheme()
  160.     imgui.SwitchContext()
  161.     local style = imgui.GetStyle()
  162.     local colors = style.Colors
  163.     local clr = imgui.Col
  164.     local ImVec4 = imgui.ImVec4
  165.  
  166.     style.WindowRounding = 2.0
  167.     style.WindowTitleAlign = imgui.ImVec2(0.5, 0.84)
  168.     style.ChildWindowRounding = 2.0
  169.     style.FrameRounding = 2.0
  170.     style.ItemSpacing = imgui.ImVec2(5.0, 4.0)
  171.     style.ScrollbarSize = 13.0
  172.     style.ScrollbarRounding = 0
  173.     style.GrabMinSize = 8.0
  174.     style.GrabRounding = 1.0
  175.  
  176.     colors[clr.FrameBg] = ImVec4(0.48, 0.16, 0.16, 0.54)
  177.     colors[clr.FrameBgHovered] = ImVec4(0.98, 0.26, 0.26, 0.40)
  178.     colors[clr.FrameBgActive] = ImVec4(0.98, 0.26, 0.26, 0.67)
  179.     colors[clr.TitleBg] = ImVec4(0.04, 0.04, 0.04, 1.00)
  180.     colors[clr.TitleBgActive] = ImVec4(0.48, 0.16, 0.16, 1.00)
  181.     colors[clr.TitleBgCollapsed] = ImVec4(0.00, 0.00, 0.00, 0.51)
  182.     colors[clr.CheckMark] = ImVec4(0.98, 0.26, 0.26, 1.00)
  183.     colors[clr.SliderGrab] = ImVec4(0.88, 0.26, 0.24, 1.00)
  184.     colors[clr.SliderGrabActive] = ImVec4(0.98, 0.26, 0.26, 1.00)
  185.     colors[clr.Button] = ImVec4(0.98, 0.26, 0.26, 0.40)
  186.     colors[clr.ButtonHovered] = ImVec4(0.98, 0.26, 0.26, 1.00)
  187.     colors[clr.ButtonActive] = ImVec4(0.98, 0.06, 0.06, 1.00)
  188.     colors[clr.Header] = ImVec4(0.98, 0.26, 0.26, 0.31)
  189.     colors[clr.HeaderHovered] = ImVec4(0.98, 0.26, 0.26, 0.80)
  190.     colors[clr.HeaderActive] = ImVec4(0.98, 0.26, 0.26, 1.00)
  191.     colors[clr.Separator] = colors[clr.Border]
  192.     colors[clr.SeparatorHovered] = ImVec4(0.75, 0.10, 0.10, 0.78)
  193.     colors[clr.SeparatorActive] = ImVec4(0.75, 0.10, 0.10, 1.00)
  194.     colors[clr.ResizeGrip] = ImVec4(0.98, 0.26, 0.26, 0.25)
  195.     colors[clr.ResizeGripHovered] = ImVec4(0.98, 0.26, 0.26, 0.67)
  196.     colors[clr.ResizeGripActive] = ImVec4(0.98, 0.26, 0.26, 0.95)
  197.     colors[clr.TextSelectedBg] = ImVec4(0.98, 0.26, 0.26, 0.35)
  198.     colors[clr.Text] = ImVec4(1.00, 1.00, 1.00, 1.00)
  199.     colors[clr.TextDisabled] = ImVec4(0.50, 0.50, 0.50, 1.00)
  200.     colors[clr.WindowBg] = ImVec4(0.06, 0.06, 0.06, 0.94)
  201.     colors[clr.ChildWindowBg] = ImVec4(1.00, 1.00, 1.00, 0.00)
  202.     colors[clr.PopupBg] = ImVec4(0.08, 0.08, 0.08, 0.94)
  203.     colors[clr.ComboBg] = colors[clr.PopupBg]
  204.     colors[clr.Border] = ImVec4(0.43, 0.43, 0.50, 0.50)
  205.     colors[clr.BorderShadow] = ImVec4(0.00, 0.00, 0.00, 0.00)
  206.     colors[clr.MenuBarBg] = ImVec4(0.14, 0.14, 0.14, 1.00)
  207.     colors[clr.ScrollbarBg] = ImVec4(0.02, 0.02, 0.02, 0.53)
  208.     colors[clr.ScrollbarGrab] = ImVec4(0.31, 0.31, 0.31, 1.00)
  209.     colors[clr.ScrollbarGrabHovered] = ImVec4(0.41, 0.41, 0.41, 1.00)
  210.     colors[clr.ScrollbarGrabActive] = ImVec4(0.51, 0.51, 0.51, 1.00)
  211.     colors[clr.CloseButton] = ImVec4(0.41, 0.41, 0.41, 0.50)
  212.     colors[clr.CloseButtonHovered] = ImVec4(0.98, 0.39, 0.36, 1.00)
  213.     colors[clr.CloseButtonActive] = ImVec4(0.98, 0.39, 0.36, 1.00)
  214.     colors[clr.PlotLines] = ImVec4(0.61, 0.61, 0.61, 1.00)
  215.     colors[clr.PlotLinesHovered] = ImVec4(1.00, 0.43, 0.35, 1.00)
  216.     colors[clr.PlotHistogram] = ImVec4(0.90, 0.70, 0.00, 1.00)
  217.     colors[clr.PlotHistogramHovered] = ImVec4(1.00, 0.60, 0.00, 1.00)
  218.     colors[clr.ModalWindowDarkening] = ImVec4(0.80, 0.80, 0.80, 0.35)
  219. end
  220.  
  221. function ShowHelpMarker(desc)
  222.     imgui.TextDisabled('(?)')
  223.     if imgui.IsItemHovered() then
  224.         imgui.BeginTooltip()
  225.         imgui.PushTextWrapPos(450.0)
  226.         imgui.TextUnformatted(desc)
  227.         imgui.PopTextWrapPos()
  228.         imgui.EndTooltip()
  229.     end
  230. end
  231.  
  232. function GetTheme()
  233.   if HLcfg.main.theme == 1 then apply_custom_style()
  234.   elseif HLcfg.main.theme == 2 then lightBlue()
  235.   elseif HLcfg.main.theme == 3 then redTheme() end
  236. end
  237. GetTheme()
  238.  
  239. function imgui.OnDrawFrame()
  240.   if main_window_state.v then
  241.       imgui.SetNextWindowSize(imgui.ImVec2(410, 230), imgui.Cond.FirstUseEver) --низ по 25
  242.     imgui.Begin(u8'[Arizona RP] Хелпер Ловли | '..version..'##main', main_window_state, imgui.WindowFlags.NoCollapse)
  243.     imgui.SetWindowPos(u8'[Arizona RP] Хелпер Ловли | '..version..'##main', imgui.ImVec2(420, 170), imgui.Cond.FirstUseEver)
  244.     if imgui.TreeNode(u8'Общие настройки') then
  245.         imgui.Text(u8'Ваша фраза:')
  246.         if imgui.InputText('##1', buffer, imgui.SameLine()) then
  247.             HLcfg.main.jtext = string.format('%s', tostring(buffer.v))
  248.         end
  249.         ShowHelpMarker(u8'Ваша фраза после покупки имущества.', imgui.SameLine())
  250.  
  251.         imgui.Text(u8'Активация:')
  252.         if imgui.InputText('##2', buffermenu, imgui.SameLine()) then
  253.             sampUnregisterChatCommand(HLcfg.main.activation)
  254.             HLcfg.main.activation = buffermenu.v
  255.             sampRegisterChatCommand(tostring(HLcfg.main.activation), function() main_window_state.v = not main_window_state.v end)
  256.         end
  257.         ShowHelpMarker(u8'Команда для активации скрипта.', imgui.SameLine())
  258.    
  259.         if imgui.Checkbox(u8'Автонажатие Enter | Временно недоступно', imgui.ImBool(HLcfg.main.autoenter)) then HLcfg.main.autoenter = not HLcfg.main.autoenter end
  260.         ShowHelpMarker(u8'Как только в диалоге капчи будет 5 символов - ответ отправится на сервер.', imgui.SameLine())
  261.    
  262.         if imgui.Checkbox(u8'Добавлять время во фразу', imgui.ImBool(HLcfg.main.texttime)) then HLcfg.main.texttime = not HLcfg.main.texttime end
  263.         ShowHelpMarker(u8'Добавляет в вашу фразу время, за которое вы словили имущество.', imgui.SameLine())
  264.  
  265.         if imgui.Checkbox(u8'Отсчет времени в PayDay', imgui.ImBool(HLcfg.main.resetpd)) then HLcfg.main.resetpd = not HLcfg.main.resetpd end
  266.         ShowHelpMarker(u8'Если включено, то скрипт будет работать от момента пайдея.\nЕсли выключено, то скрипт будет работать от момента открытия капчи.', imgui.SameLine())
  267.  
  268.         if imgui.Checkbox(u8'Отключить ники и семьи', tags) then
  269.             pStSet = sampGetServerSettingsPtr()
  270.             if tags.v then
  271.                 mem.setint8(pStSet + 56, 0)
  272.                 for i = 1, 2048 do
  273.                     if sampIs3dTextDefined(i) then
  274.                         local text, color, posX, posY, posZ, distance, ignoreWalls, player, vehicle = sampGet3dTextInfoById(i)
  275.                         for ii = 1, #MASLOSYKA do if text:match(string.format('.+%s', MASLOSYKA[tonumber(ii)])) then sampDestroy3dText(i) end end
  276.                     end
  277.                 end
  278.             else
  279.                 mem.setint8(pStSet + 56, 1)
  280.             end
  281.         end
  282.         ShowHelpMarker(u8'Отключает ник и название семьи над игроком.\n(название семье не вернется - на доработке)', imgui.SameLine())
  283.  
  284.         if imgui.Checkbox(u8'Флуд на N', imgui.ImBool(HLcfg.main.floodN)) then HLcfg.main.floodN = not HLcfg.main.floodN end
  285.         ShowHelpMarker(u8'Если нажать на N до PayDay, то Вам не будет писать "Не флуди",\nа также не будет кд на повторное нажатие', imgui.SameLine())
  286.  
  287.         if imgui.Checkbox(u8'Поиск ближайшего дома', imgui.ImBool(HLcfg.main.autofind)) then HLcfg.main.autofind = not HLcfg.main.autofind end
  288.         ShowHelpMarker(u8'Если открыть диалог с домами - будет найдет ближайший дом в госе.\nЕсли будет только 1 дом в госе - найдет его\nЕсли домов в госе не будет - не произойдет ничего', imgui.SameLine())
  289.         imgui.TreePop()
  290.     end
  291.     imgui.Separator()
  292.     if imgui.TreeNode(u8'Диалог капчи') then
  293.         if imgui.Checkbox(u8'Удаление букв и символов с диалога капчи', imgui.ImBool(HLcfg.main.nClear)) then
  294.             HLcfg.main.nClear = not HLcfg.main.nClear
  295.         end
  296.         ShowHelpMarker(u8'В диалог с капчей будет запрещено вводить всё кроме цифр', imgui.SameLine())
  297.  
  298.         if imgui.Checkbox(u8'Ограничение в 5 символов', imgui.ImBool(HLcfg.main.max5)) then
  299.             HLcfg.main.max5 = not HLcfg.main.max5
  300.         end
  301.         ShowHelpMarker(u8'Запрещает вводить в диалог капчи больше 5 символов.', imgui.SameLine())
  302.         imgui.TreePop()
  303.     end
  304.     imgui.Separator()
  305.     if imgui.TreeNode(u8'Настройки чата') then
  306.         if imgui.Checkbox(u8'Время покупки/неверного и т.д', imgui.ImBool(HLcfg.main.utime)) then
  307.             HLcfg.main.utime = not HLcfg.main.utime
  308.         end
  309.         ShowHelpMarker(u8'Пишет в чат за сколько Вы купили дом или бизнес', imgui.SameLine())
  310.  
  311.         if imgui.Checkbox(u8'Время покупки другим человеком', imgui.ImBool(HLcfg.main.ptime)) then
  312.             HLcfg.main.ptime = not HLcfg.main.ptime
  313.         end
  314.         ShowHelpMarker(u8'Пишет в чат за сколько другой игрок купил дом или бизнес', imgui.SameLine())
  315.  
  316.         if imgui.Checkbox(u8'Сообщение в чат после покупки имущества', imgui.ImBool(HLcfg.main.HLmsg)) then
  317.             HLcfg.main.HLmsg = not HLcfg.main.HLmsg
  318.         end
  319.         ShowHelpMarker(u8'После покупки дома или бизнеса пишет в чат вашу фразу,\nкоторую можно указать во вкладке "Общие настройки"', imgui.SameLine())
  320.         imgui.TreePop()
  321.     end
  322.     imgui.Separator()
  323.     if imgui.TreeNode(u8'Тренировка капчи') then
  324.         imgui.Text(u8'Кнопка')
  325.         if imgui.InputText('##3', keybuff, imgui.SameLine()) then
  326.             HLcfg.main.key = string.format('%s', tostring(keybuff.v))
  327.         end
  328.         ShowHelpMarker(u8'Кнопка по которой будет открыватся капча.', imgui.SameLine())
  329.    
  330.         if imgui.Checkbox(u8'Открывать капчу по кнопке', imgui.ImBool(HLcfg.main.onkey)) then
  331.           HLcfg.main.onkey = not HLcfg.main.onkey
  332.         end
  333.    
  334.         if imgui.Button(u8'Открыть капчу') then showCaptcha() end
  335.         if imgui.Button(u8'Очистить текстдравы', imgui.SameLine()) then for i = 1, 400 do sampTextdrawDelete(i) end end
  336.         imgui.TreePop()
  337.     end
  338.     imgui.Separator()
  339.     if imgui.TreeNode(u8'Сменить тему') then
  340.         if HLcfg.main.theme ~= 1 then apply_custom_style() end
  341.         if imgui.Button(u8'Темная тема') then HLcfg.main.theme = 1; apply_custom_style() end
  342.         GetTheme()
  343.         if HLcfg.main.theme ~= 2 then lightBlue() end
  344.         if imgui.Button(u8'Светло-синяя тема', imgui.SameLine()) then HLcfg.main.theme = 2; lightBlue() end
  345.         GetTheme()
  346.         if HLcfg.main.theme ~= 3 then redTheme() end
  347.         if imgui.Button(u8'Красная тема', imgui.SameLine()) then HLcfg.main.theme = 3; redTheme() end
  348.         GetTheme()
  349.         imgui.TreePop()
  350.     end
  351.     imgui.End()
  352.   end
  353. end
  354.  
  355. function randomFloat(lower, greater)
  356.     return lower + math.random()  * (greater - lower);
  357. end
  358.  
  359. function showCaptcha()
  360.     removeTextdraws()
  361.     t = t + 1
  362.     sampTextdrawCreate(t, "LD_SPAC:white", 220, 120)
  363.     sampTextdrawSetLetterSizeAndColor(t, 0, 6.5, 0x80808080)
  364.     sampTextdrawSetBoxColorAndSize(t, 1, 0xFF1A2432, 380, 0.000000)
  365.        
  366.     t = t + 1
  367.     sampTextdrawCreate(t, "LD_SPAC:white", 225, 125)
  368.     sampTextdrawSetLetterSizeAndColor(t, 0, 5.5, 0x80808080)
  369.     sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, 375, 0.000000)
  370.     nextPos = -30.0;
  371.        
  372.     math.randomseed(os.time())
  373.     for i = 1, 4 do
  374.         a = math.random(0, 9)
  375.         table.insert(captchaTable, a)
  376.         captcha = captcha..a
  377.     end
  378.        
  379.     for i = 0, 4 do
  380.         nextPos = nextPos + 30
  381.         t = t + 1
  382.         sampTextdrawCreate(t, "usebox", 240 + nextPos, 130)
  383.         sampTextdrawSetLetterSizeAndColor(t, 0, 4.5, 0x80808080)
  384.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF1A2432, 30, 25.000000)
  385.         sampTextdrawSetAlign(t, 2)
  386.         if i < 4 then GenerateTextDraw(captchaTable[i + 1], 240 + nextPos, 130, 3 + i * 2)
  387.         else GenerateTextDraw(0, 240 + nextPos, 130, 3 + i * 10) end
  388.     end
  389.     captchaTable = {}
  390.     sampShowDialog(8812, '{F89168}Проверка на робота', '{FFFFFF}Введите {C6FB4A}5{FFFFFF} символов, которые\nвидно на {C6FB4A}вашем{FFFFFF} экране.', 'Принять', 'Отмена', 1)
  391.     captime = os.clock()
  392. end
  393.  
  394. function removeTextdraws()
  395.   if t > 0 then
  396.     for i = 1, t do sampTextdrawDelete(i) end
  397.     t = 0
  398.     captcha = ''
  399.     captime = nil
  400.   end
  401. end
  402.  
  403. function GenerateTextDraw(id, PosX, PosY)
  404.   if id == 0 then
  405.     t = t + 1
  406.     sampTextdrawCreate(t, "LD_SPAC:white", PosX - 5, PosY + 7)
  407.     sampTextdrawSetLetterSizeAndColor(t, 0, 3, 0x80808080)
  408.     sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX+5, 0.000000)
  409.   elseif id == 1 then
  410.     for i = 0, 1 do
  411.         t = t + 1
  412.         if i == 0 then offsetX = 3; offsetBX = 15 else offsetX = -3; offsetBX = -15; end
  413.         sampTextdrawCreate(t, "LD_SPAC:white", PosX - offsetX, PosY)
  414.         sampTextdrawSetLetterSizeAndColor(t, 0, 4.5, 0x80808080)
  415.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  416.     end
  417.   elseif id == 2 then
  418.     for i = 0, 1 do
  419.         t = t + 1
  420.         if i == 0 then offsetX = -8; offsetY = 7 offsetBX = 15 else offsetX = 6; offsetY = 25 offsetBX = -15; end
  421.         sampTextdrawCreate(t, "LD_SPAC:white", PosX - offsetX, PosY + offsetY)
  422.         sampTextdrawSetLetterSizeAndColor(t, 0, 0.8, 0x80808080)
  423.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  424.     end
  425.   elseif id == 3 then
  426.     for i = 0, 1 do
  427.         t = t + 1
  428.         if i == 0 then size = 0.8; offsetY = 7 else size = 1; offsetY = 25 end
  429.         sampTextdrawCreate(t, "LD_SPAC:white", PosX+10, PosY+offsetY)
  430.         sampTextdrawSetLetterSizeAndColor(t, 0, 1, 0x80808080)
  431.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-15, 0.000000)
  432.     end
  433.   elseif id == 4 then
  434.     for i = 0, 1 do
  435.         t = t + 1
  436.         if i == 0 then size = 1.8; offsetX = -10; offsetY = 0 offsetBX = 10 else size = 2; offsetX = -10; offsetY = 25 offsetBX = 15; end
  437.         sampTextdrawCreate(t, "LD_SPAC:white", PosX - offsetX, PosY + offsetY)
  438.         sampTextdrawSetLetterSizeAndColor(t, 0, size, 0x80808080)
  439.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  440.     end
  441.   elseif id == 5 then
  442.     for i = 0, 1 do
  443.         t = t + 1
  444.         if i == 0 then size = 0.8; offsetX = 8; offsetY = 7 offsetBX = -15 else size = 1; offsetX = -10; offsetY = 25 offsetBX = 15; end
  445.         sampTextdrawCreate(t, "LD_SPAC:white", PosX - offsetX, PosY + offsetY)
  446.         sampTextdrawSetLetterSizeAndColor(t, 0, size, 0x80808080)
  447.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  448.     end
  449.   elseif id == 6 then
  450.     for i = 0, 1 do
  451.         t = t + 1
  452.         if i == 0 then size = 0.8; offsetX = 7.5; offsetY = 7 offsetBX = -15 else size = 1; offsetX = -10; offsetY = 25 offsetBX = 10; end
  453.         sampTextdrawCreate(t, "LD_SPAC:white", PosX - offsetX, PosY + offsetY)
  454.         sampTextdrawSetLetterSizeAndColor(t, 0, size, 0x80808080)
  455.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  456.     end
  457.   elseif id == 7 then
  458.     t = t + 1
  459.     sampTextdrawCreate(t, "LD_SPAC:white", PosX - 13, PosY + 7)
  460.     sampTextdrawSetLetterSizeAndColor(t, 0, 3.75, 0x80808080)
  461.     sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX+5, 0.000000)
  462.   elseif id == 8 then
  463.     for i = 0, 1 do
  464.         t = t + 1
  465.         if i == 0 then size = 0.8; offsetY = 7 else size = 1; offsetY = 25 end
  466.         sampTextdrawCreate(t, "LD_SPAC:white", PosX+10, PosY+offsetY)
  467.         sampTextdrawSetLetterSizeAndColor(t, 0, 1, 0x80808080)
  468.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-10, 0.000000)
  469.     end
  470.   elseif id == 9 then
  471.     for i = 0, 1 do
  472.         t = t + 1
  473.         if i == 0 then size = 0.8; offsetY = 6; offsetBX = 10; else size = 1; offsetY = 25; offsetBX = 15; end
  474.         sampTextdrawCreate(t, "LD_SPAC:white", PosX+10, PosY+offsetY)
  475.         sampTextdrawSetLetterSizeAndColor(t, 0, 1, 0x80808080)
  476.         sampTextdrawSetBoxColorAndSize(t, 1, 0xFF759DA3, PosX-offsetBX, 0.000000)
  477.     end
  478.   end
  479. end
  480.  
  481. local s1xreq = {
  482.   _DESCRIPTION = 'Http s1xreq made simpler',
  483.   http_socket = http_socket,
  484.   https_socket = https_socket
  485. }
  486.  
  487. local _s1xreq = {}
  488.  
  489. function main()
  490.   if not isSampfuncsLoaded() or not isSampLoaded() then return end
  491.   while not isSampAvailable() do wait(100) end
  492.  
  493.   local ffi = require("ffi")
  494.   ffi.cdef[[
  495.     int __stdcall GetVolumeInformationA(
  496.       const char* lpRootPathName,
  497.       char* lpVolumeNameBuffer,
  498.       uint32_t nVolumeNameSize,
  499.       uint32_t* lpVolumeSerialNumber,
  500.       uint32_t* lpMaximumComponentLength,
  501.       uint32_t* lpFileSystemFlags,
  502.       char* lpFileSystemNameBuffer,
  503.       uint32_t nFileSystemNameSize
  504.     );
  505.   ]]
  506.   local serial = ffi.new("unsigned long[1]", 0)
  507.   ffi.C.GetVolumeInformationA(nil, nil, 0, serial, nil, nil, nil, 0)
  508.   serial = serial[0]
  509.  
  510.   local usdjas = ''
  511.   usdjas = string.format('%s', serial)
  512.  
  513.   local qwords = ffi.typeof("uint64_t[?]")
  514.   local dwords = ffi.typeof("uint32_t *")
  515.   local cpuid_EAX_EDX = ffi.cast("__cdecl uint64_t (*)(uint32_t)", "\x53\x0F\xA2\x5B\xC3")
  516.   local cpuid_EBX_ECX = ffi.cast("__cdecl uint64_t (*)(uint32_t)", "\x53\x0F\xA2\x91\x92\x93\x5B\xC3")
  517.  
  518.   local function cpuid(n)
  519.      local arr = ffi.cast(dwords, qwords(2, cpuid_EAX_EDX(n), cpuid_EBX_ECX(n)))
  520.      return ffi.string(arr, 4), ffi.string(arr + 2, 4), ffi.string(arr + 3, 4), ffi.string(arr + 1, 4)
  521.   end
  522.  
  523.   local s1 = ""
  524.   for n = 0x80000002, 0x80000004 do
  525.      local eax, ebx, ecx, edx = cpuid(n)
  526.      s1 = s1..eax..ebx..ecx..edx
  527.   end
  528.   s1 = s1:gsub("^%s+", ""):gsub("%z+$", "")
  529.  
  530.   local eax, ebx, ecx, edx = cpuid(0)
  531.   local s2 = ebx..edx..ecx
  532.   s2 = s2:gsub("^%s+", ""):gsub("%z+$", "")
  533.  
  534.   usdjas = string.format('%s | %s %s', usdjas, s1, s2)
  535.   usdjas = md5_tohex(usdjas)
  536.  
  537.   local ahashsahsd = {
  538.     headers = {
  539.         ['content-type']='application/x-www-form-urlencoded',
  540.         ['user-agent']='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
  541.     }
  542.   }
  543.   local mainfunci = s1xreq.get('https://saxofone.pp.ua/Helper/k_add.php?hwid='..usdjas, ahashsahsd)
  544.   if not string.find(mainfunci['text'], "SK%-TEAM POMOIKA | AZLLER'a MATb EBAL") then sampAddChatMessage('{ffff00}[Хелпер ловли] {ffffff}Код для привязки: '..usdjas, -1); thisScript():unload(); return false end
  545.   sampRegisterChatCommand(tostring(HLcfg.main.activation), function() main_window_state.v = not main_window_state.v end)
  546.   notf.addNotification('Активация: /' ..HLcfg.main.activation, 5, 1)
  547.   notf.addNotification('Скрипт успешно загружен! Текущая версия: ' ..version, 5, 1)
  548.   sampAddChatMessage('{ffff00}[Хелпер Ловли] {ffffff}by Leo_Masker for {20B2AA}J Family {ffff00}| {ffffff}Версия: '..version, -1)
  549.   while true do wait(0)
  550.     keybuff.v = string.upper(keybuff.v)
  551.     if wasKeyPressed(vkeys.name_to_id(keybuff.v, false)) and HLcfg.main.onkey and not sampIsChatInputActive() and not sampIsDialogActive() then showCaptcha() end
  552.     local result, button, list, input = sampHasDialogRespond(8812)
  553.     if result then
  554.       if button == 1 then
  555.         if input == captcha..'0' then sampAddChatMessage(string.format('{ffff00}[Хелпер ловли] {ffffff}Код верный [%.3f]', os.clock() - captime), -1)
  556.         elseif input ~= captcha..'0' then sampAddChatMessage(string.format('{ffff00}[Хелпер ловли] {ffffff}Неверный код! [%.3f] ('..captcha..'0|'..input..')', os.clock() - captime), -1) end
  557.       end
  558.       removeTextdraws()
  559.     end
  560.  
  561.     if sampIsDialogActive() and sampGetDialogCaption():find('Проверка на робота') then
  562.       if HLcfg.main.nClear then sampSetCurrentDialogEditboxText(string.gsub(sampGetCurrentDialogEditboxText(), '[^1234567890]','')) end
  563.       if HLcfg.main.max5 then
  564.         local text = sampGetCurrentDialogEditboxText()
  565.         if #text > 5 then sampSetCurrentDialogEditboxText(text:sub(1, 5)) end
  566.       end
  567.     end
  568.     imgui.Process = main_window_state.v
  569.   end
  570.   wait(-1)
  571. end
  572.  
  573. function q.onPlayerChatBubble() if tags.v then return false end end
  574.  
  575. function q.onCreate3DText(id, color, position, distance, testLOS, attachedPlayerId, attachedVehicleId, text)
  576.   if time ~= nil and HLcfg.main.ptime then
  577.     local _, pid = sampGetPlayerIdByCharHandle(playerPed)
  578.       pname = sampGetPlayerNickname(pid)
  579.     for pizda in text:gmatch('[^\n\r]+') do
  580.       pizda = pizda:match('{FFFFFF}Владелец: {AFAFAF}(.+)')
  581.       if pizda ~= nil and pizda ~= pname then return sampAddChatMessage(string.format('{ffff00}[Хелпер Ловли] {ffffff}Дом куплен игроком {20B2AA}%s {ffffff}[%.3f]', pizda, os.clock() - time), -1) end
  582.     end
  583.     for pizda in text:gmatch('[^\n\r]+') do
  584.       pizda = pizda:match('{73B461}Владелец: {FFFFFF}(.+)')
  585.       if pizda ~= nil and pizda ~= pname then return sampAddChatMessage(string.format('{ffff00}[Хелпер Ловли] {ffffff}Бизнес куплен игроком {20B2AA}%s {ffffff}[%.3f]', pizda, os.clock() - time), -1) end
  586.     end
  587.   end
  588. end
  589.  
  590. function q.onSendPlayerSync(data)
  591.   if HLcfg.main.floodN and data.weapon == 128 and not payday then return false
  592.   elseif HLcfg.main.floodN and data.weapon == 128 and payday then payday = false end
  593. end
  594.  
  595. function q.onShowDialog(dialogId, style, title, button1, button2, text)
  596.   if title:find('Проверка на робота') then
  597.     if not HLcfg.main.resetpd then
  598.       time = os.clock()
  599.       reset()
  600.     end
  601.   end
  602.   if text:find('/findihouse ID') and HLcfg.main.autofind then
  603.     for line in text:gmatch('[^\n\r]+') do
  604.       if line:find('Эта информация может быть {1EA3CC}ошибочной%.{FFFFFF}') then
  605.         if #forFind == 1 then
  606.           sampSendChat('/findihouse '..forFind[1])
  607.           table.remove(forFind, 1)
  608.           sampAddChatMessage('{ffff00}[Хелпер Ловли] {ffffff}Слетел один дом. Метка установлена!', -1)
  609.         elseif #forFind > 1 then
  610.           sampAddChatMessage('{ffff00}[Хелпер Ловли] {ffffff}Слетело {ff0000}'..#forFind..' {ffffff}домов, ищем ближайщий!', -1)
  611.           sampSendChat('/findihouse '..forFind[1])
  612.         elseif #forFind == 0 then
  613.           sampAddChatMessage('{ffff00}[Хелпер Ловли] {ffffff}Домов в госе нет!', -1)
  614.         end
  615.         return true
  616.       end
  617.       local hid = line:match('.+%. Дом        ID: {C9B931}(.+){FFFFFF}    %[{A9FF14}Слетел{FFFFFF}]')
  618.       if hid ~= nil then table.insert(forFind, hid) end
  619.     end
  620.   end
  621. end
  622.  
  623. function q.onServerMessage(color, text)
  624.   if text:find('%[Подсказка] {FFFFFF}На миникарте отмечено место где будет продаваться дом.') then
  625.     if #forFind > 0 then
  626.       local x, y, z = getCharCoordinates(playerPed)
  627.       local x1, y1, z1 = GetRedMarkerCoords()
  628.       houses[forFind[1]] = getDistanceBetweenCoords3d(x, y, z, x1, y1, z1)
  629.       table.remove(forFind, 1)
  630.       if #forFind > 0 then sampSendChat('/findihouse '..forFind[1]) end
  631.       if #forFind == 0 then hfind = 1 end
  632.     end
  633.     if #forFind == 0 and hfind == 1 then
  634.         for k,v in spairs(houses, function(t,a,b) return t[b] > t[a] end) do
  635.           hfind = 2
  636.           forFind, houses = {}, {}
  637.           sampAddChatMessage('{ffff00}[Хелпер Ловли] {ffffff}Ближайший дом - '..k..'. Метка установлена на карте!', -1)
  638.           sampSendChat('/findihouse '..k)
  639.           return
  640.         end
  641.     end
  642.     if hfind == 2 then
  643.       hfind = 0
  644.       return false
  645.     end
  646.   end
  647.  
  648.   if text:find('%[Ошибка] {FFFFFF}У вас недостаточно денег%. Вы можете пополнить свой баланс %[/donate]') and color == -10270721 and time ~= nil then
  649.     if HLcfg.main.utime then
  650.       sampAddChatMessage(string.format('{FF6347}[Ошибка] {FFFFFF}У вас недостаточно денег. [%.3f]', os.clock() - time), -1)
  651.       return false
  652.     end
  653.   end
  654.   if text:find('__________________________________') and color == 1941201407 or
  655.     text:find('Для получения PayDay вы должны отыграть минимум 20 минут.') and color == -10270721 then
  656.       if HLcfg.main.resetpd then
  657.         time = os.clock()
  658.         reset()
  659.       end
  660.       payday = true
  661.   end
  662.   if text:find('%[Информация] {FFFFFF}Поздравляю! Теперь этот бизнес ваш!') and color == 1941201407 and time ~= nil then
  663.     if HLcfg.main.HLmsg then
  664.       if HLcfg.main.texttime then sampSendChat(u8:decode(string.format('%s [%.3f]', HLcfg.main.jtext, time)))
  665.       else sampSendChat(u8:decode(HLcfg.main.jtext)) end
  666.     end
  667.     if HLcfg.main.utime then
  668.       time = os.clock() - time
  669.       sampAddChatMessage(string.format('{73B461}[Информация] {FFFFFF}Поздравляю! Теперь этот бизнес ваш! [%.3f]', time), -1)
  670.       return false
  671.     end
  672.   end
  673.   if text:find('%[Информация] {FFFFFF}Поздравляю! Теперь этот дом ваш!') and color == 1941201407 and time ~= nil then
  674.     if HLcfg.main.HLmsg then
  675.       if HLcfg.main.texttime then sampSendChat(u8:decode(string.format('%s [%.3f]', HLcfg.main.jtext, time)))
  676.       else sampSendChat(u8:decode(HLcfg.main.jtext)) end
  677.     end
  678.     if HLcfg.main.utime then
  679.       time = os.clock() - time
  680.       sampAddChatMessage(string.format('{73B461}[Информация] {FFFFFF}Поздравляю! Теперь этот дом ваш! [%.3f]', time), -1)
  681.       return false
  682.     end
  683.   end
  684.     if text:find('%[Ошибка] {FFFFFF}Ответ неверный!') and color == -10270721 and time ~= nil and HLcfg.main.utime then
  685.     sampAddChatMessage(string.format('{FF6347}[Ошибка] {FFFFFF}Ответ неверный! [%.3f]', os.clock() - time), -1)
  686.     return false
  687.   end
  688.   if text:find('%[Ошибка] {FFFFFF}Неверный код!') and color == -10270721 and time ~= nil and HLcfg.main.utime then
  689.     sampAddChatMessage(string.format('{FF6347}[Ошибка] {FFFFFF}Неверный код! [%.3f]', os.clock() - time), -1)
  690.     return false
  691.   end
  692.   if text:find('%[Ошибка] {FFFFFF}Этот дом уже куплен!') and color == -10270721 and time ~= nil and HLcfg.main.utime then
  693.     sampAddChatMessage(string.format('{FF6347}[Ошибка] {FFFFFF}Этот дом уже куплен! [%.3f]', os.clock() - time), -1)
  694.     return false
  695.   end
  696.   if text:find('%[Ошибка] {FFFFFF}Этот бизнес уже кем то куплен') and color == -10270721 and time ~= nil and HLcfg.main.utime then
  697.     sampAddChatMessage(string.format('{FF6347}[Ошибка] {FFFFFF}Этот бизнес уже кем то куплен [%.3f]', os.clock() - time), -1)
  698.     return false
  699.   end
  700.   if text:find('>> {FF6347} Местом спавна автоматически назначен ваш дом. Изменить место спавна {FFFFFF}>>{FF6347} /setspawn!') and time ~= nil and HLcfg.main.utime then time = os.clock() - time end
  701. end
  702.  
  703. function onWindowMessage(msg, wparam, lparam)
  704.   if msg == 0x100 or msg == 0x101 then
  705.     if wparam == vkeys.VK_ESCAPE and main_window_state.v and not isPauseMenuActive() then
  706.       consumeWindowMessage(true, false)
  707.       main_window_state.v = false
  708.     end
  709.   end
  710. end
  711.  
  712. function reset()
  713.   lua_thread.create(function()
  714.     wait(4000)
  715.     time = nil
  716.   end)
  717. end
  718.  
  719. function onScriptTerminate(script, quitGame)
  720.   if script == thisScript() then
  721.     inicfg.save(HLcfg, "HelperLovli")
  722.   end
  723. end
  724.  
  725. function onQuitGame()
  726.   inicfg.save(HLcfg, "HelperLovli")
  727. end
  728.  
  729. function GetRedMarkerCoords() -- snippet by SR_team, slightly modified
  730.     for i = 0, 31 do
  731.         local markerPtr = 0xC7F168 + i * 56
  732.         --local markerPtr = 0xC7DEC8 + i * 160
  733.         local x = representIntAsFloat(readMemory(markerPtr + 0, 4, false))
  734.         local y = representIntAsFloat(readMemory(markerPtr + 4, 4, false))
  735.         local z = representIntAsFloat(readMemory(markerPtr + 8, 4, false))
  736.         if x ~= 0.0 or y ~= 0.0 or z ~= 0.0 then
  737.             requestCollision(x, y); loadScene(x, y, z);
  738.             return x, y, z
  739.         end
  740.     end
  741.     return 0, 0, 0
  742. end
  743.  
  744. function spairs(t, order)
  745.     -- collect the keys
  746.     local keys = {}
  747.     for k in pairs(t) do keys[#keys+1] = k end
  748.  
  749.     -- if order function given, sort by it by passing the table and keys a, b,
  750.     -- otherwise just sort the keys
  751.     if order then
  752.         table.sort(keys, function(a,b) return order(t, a, b) end)
  753.     else
  754.         table.sort(keys)
  755.     end
  756.  
  757.     -- return the iterator function
  758.     local i = 0
  759.     return function()
  760.         i = i + 1
  761.         if keys[i] then
  762.             return keys[i], t[keys[i]]
  763.         end
  764.     end
  765. end
  766.  
  767. -- Lua s1xreq library for http ease
  768.  
  769. local http_socket = require('socket.http')
  770. local https_socket = require('ssl.https')
  771. local url_parser = require('socket.url')
  772. local ltn12 = require('ltn12')
  773. local json = require('cjson.safe')
  774. local xml = require('xml')
  775. local md5sum = require('md5') -- TODO: Make modular?
  776. local base64 = require('base64')
  777.  
  778. --User facing function the make a request use Digest Authentication
  779. --TODO: Determine what else should live in authentication
  780. function s1xreq.HTTPDigestAuth(user, password)
  781.   return { _type = 'digest', user = user, password = password}
  782. end
  783.  
  784. --User facing function the make a request use Basic Authentication
  785. --TODO: Determine what else should live in authentication
  786. function s1xreq.HTTPBasicAuth(user, password)
  787.   return { _type = 'basic', user = user, password = password}
  788. end
  789.  
  790. function s1xreq.post(url, args)
  791.   return s1xreq.request("POST", url, args)
  792. end
  793.  
  794. function s1xreq.get(url, args)
  795.   return s1xreq.request("GET", url, args)
  796. end
  797.  
  798. function s1xreq.delete(url, args)
  799.   return s1xreq.request("DELETE", url, args)
  800. end
  801.  
  802. function s1xreq.patch(url, args)
  803.   return s1xreq.request("PATCH", url, args)
  804. end
  805.  
  806. function s1xreq.put(url, args)
  807.   return s1xreq.request("PUT", url, args)
  808. end
  809.  
  810. function s1xreq.options(url, args)
  811.   return s1xreq.request("OPTIONS", url, args)
  812. end
  813.  
  814. function s1xreq.head(url, args)
  815.   return s1xreq.request("HEAD", url, args)
  816. end
  817.  
  818. function s1xreq.trace(url, args)
  819.   return s1xreq.request("TRACE", url, args)
  820. end
  821.  
  822. --Sets up all the data for a request and makes the request
  823. function s1xreq.request(method, url, args)
  824.   local request
  825.  
  826.   if type(url) == "table" then
  827.     request = url
  828.   else
  829.     request = args or {}
  830.     request.url = url
  831.   end
  832.  
  833.   request.method = method
  834.   _s1xreq.parse_args(request)
  835.  
  836.   -- TODO: Find a better way to do this
  837.   if request.auth and request.auth._type == 'digest' then
  838.     local response = _s1xreq.make_request(request)
  839.     return _s1xreq.use_digest(response, request)
  840.   else
  841.     return _s1xreq.make_request(request)
  842.   end
  843. end
  844.  
  845. --Makes a request
  846. function _s1xreq.make_request(request)
  847.   local response_body = {}
  848.   local full_request = {
  849.     method = request.method,
  850.     url = request.url,
  851.     headers = request.headers,
  852.     source = ltn12.source.string(request.data),
  853.     sink = ltn12.sink.table(response_body),
  854.     redirect = request.allow_redirects,
  855.     proxy = request.proxy
  856.   }
  857.  
  858.   local response = {}
  859.   local ok
  860.   local socket = string.find(full_request.url, '^https:') and not request.proxy and https_socket or http_socket
  861.  
  862.   ok, response.status_code, response.headers, response.status = socket.request(full_request)
  863.  
  864.   assert(ok, 'error in '..request.method..' request: '..response.status_code)
  865.   response.text = table.concat(response_body)
  866.   response.json = function () return json.decode(response.text) end
  867.   response.xml = function () return xml.load(response.text) end
  868.  
  869.   return response
  870. end
  871.  
  872. --Parses through all the possible arguments for a request
  873. function _s1xreq.parse_args(request)
  874.   _s1xreq.check_url(request)
  875.   _s1xreq.check_data(request)
  876.   _s1xreq.create_header(request)
  877.   _s1xreq.check_timeout(request.timeout)
  878.   _s1xreq.check_redirect(request.allow_redirects)
  879. end
  880.  
  881. --Format the the url based on the params argument
  882. function _s1xreq.format_params(url, params) -- TODO: Clean
  883.   if not params or next(params) == nil then return url end
  884.  
  885.   url = url..'?'
  886.   for key, value in pairs(params) do
  887.     if tostring(value) then
  888.       url = url..tostring(key)..'='
  889.  
  890.       if type(value) == 'table' then
  891.         local val_string = ''
  892.  
  893.         for _, val in ipairs(value) do
  894.           val_string = val_string..tostring(val)..','
  895.         end
  896.  
  897.         url = url..val_string:sub(0, -2)
  898.       else
  899.         url = url..tostring(value)
  900.       end
  901.  
  902.       url = url..'&'
  903.     end
  904.   end
  905.  
  906.   return url:sub(0, -2)
  907. end
  908.  
  909. --Check that there is a URL given and append to it if params are passed in.
  910. function _s1xreq.check_url(request)
  911.   assert(request.url, 'No url specified for request')
  912.   request.url = _s1xreq.format_params(request.url, request.params)
  913. end
  914.  
  915. -- Add to the HTTP header
  916. function _s1xreq.create_header(request)
  917.   request.headers = request.headers or {}
  918.   request.headers['Content-Length'] = request.data:len()
  919.  
  920.   if request.cookies then
  921.     if request.headers.cookie then
  922.       request.headers.cookie = request.headers.cookie..'; '..request.cookies
  923.     else
  924.       request.headers.cookie = request.cookies
  925.     end
  926.   end
  927.  
  928.   if request.auth then
  929.     _s1xreq.add_auth_headers(request)
  930.   end
  931. end
  932.  
  933. --Makes sure that the data is in a format that can be sent
  934. function _s1xreq.check_data(request)
  935.   request.data = request.data or ''
  936.  
  937.   if type(request.data) == "table" then
  938.     request.data = json.encode(request.data)
  939.   end
  940. end
  941.  
  942. --Set the timeout
  943. function _s1xreq.check_timeout(timeout)
  944.   http_socket.TIMEOUT = timeout or 5
  945.   https_socket.TIMEOUT = timeout or 5
  946. end
  947.  
  948. --Checks is allow_redirects parameter is set correctly
  949. function _s1xreq.check_redirect(allow_redirects)
  950.   if allow_redirects and type(allow_redirects) ~= "boolean" then
  951.     error("allow_redirects expects a boolean value. received type = "..type(allow_redirects))
  952.   end
  953. end
  954.  
  955. --Create the Authorization header for Basic Auth
  956. function _s1xreq.basic_auth_header(request)
  957.   local encoded = base64.encode(request.auth.user..':'..request.auth.password)
  958.   request.headers.Authorization = 'Basic '..encoded
  959. end
  960.  
  961. -- Create digest authorization string for request header TODO: Could be better, but it should work
  962. function _s1xreq.digest_create_header_string(auth)
  963.   local authorization = ''
  964.   authorization = 'Digest username="'..auth.user..'", realm="'..auth.realm..'", nonce="'..auth.nonce
  965.   authorization = authorization..'", uri="'..auth.uri..'", qop='..auth.qop..', nc='..auth.nc
  966.   authorization = authorization..', cnonce="'..auth.cnonce..'", response="'..auth.response..'"'
  967.  
  968.   if auth.opaque then
  969.     authorization = authorization..', opaque="'..auth.opaque..'"'
  970.   end
  971.  
  972.   return authorization
  973. end
  974.  
  975. --MD5 hash all parameters
  976. local function md5_hash(...)
  977.   return md5sum.sumhexa(table.concat({...}, ":"))
  978. end
  979.  
  980. -- Creates response hash TODO: Add functionality
  981. function _s1xreq.digest_hash_response(auth_table)
  982.   return md5_hash(
  983.     md5_hash(auth_table.user, auth_table.realm, auth_table.password),
  984.     auth_table.nonce,
  985.     auth_table.nc,
  986.     auth_table.cnonce,
  987.     auth_table.qop,
  988.     md5_hash(auth_table.method, auth_table.uri)
  989.   )
  990. end
  991.  
  992. -- Add digest authentication to the request header
  993. function _s1xreq.digest_auth_header(request)
  994.   if not request.auth.nonce then return end
  995.  
  996.   request.auth.cnonce = request.auth.cnonce or string.format("%08x", os.time())
  997.  
  998.   request.auth.nc_count = request.auth.nc_count or 0
  999.   request.auth.nc_count = request.auth.nc_count + 1
  1000.  
  1001.   request.auth.nc = string.format("%08x", request.auth.nc_count)
  1002.  
  1003.   local url = url_parser.parse(request.url)
  1004.   request.auth.uri = url_parser.build{path = url.path, query = url.query}
  1005.   request.auth.method = request.method
  1006.   request.auth.qop = 'auth'
  1007.  
  1008.   request.auth.response = _s1xreq.digest_hash_response(request.auth)
  1009.  
  1010.   request.headers.Authorization = _s1xreq.digest_create_header_string(request.auth)
  1011. end
  1012.  
  1013. --Checks the resonse code and adds additional headers for Digest Auth
  1014. -- TODO: Rename this
  1015. function _s1xreq.use_digest(response, request)
  1016.   if response.status_code == 401 then
  1017.     _s1xreq.parse_digest_response_header(response,request)
  1018.     _s1xreq.create_header(request)
  1019.     response = _s1xreq.make_request(request)
  1020.     response.auth = request.auth
  1021.     response.cookies = request.headers.cookie
  1022.     return response
  1023.   else
  1024.     response.auth = request.auth
  1025.     response.cookies = request.headers.cookie
  1026.     return response
  1027.   end
  1028. end
  1029.  
  1030. --Parse the first response from the host to make the Authorization header
  1031. function _s1xreq.parse_digest_response_header(response, request)
  1032.   for key, value in response.headers['www-authenticate']:gmatch('(%w+)="(%S+)"') do
  1033.     request.auth[key] = value
  1034.   end
  1035.  
  1036.   if request.headers.cookie then
  1037.     request.headers.cookie = request.headers.cookie..'; '..response.headers['set-cookie']
  1038.   else
  1039.     request.headers.cookie = response.headers['set-cookie']
  1040.   end
  1041.  
  1042.   request.auth.nc_count = 0
  1043. end
  1044.  
  1045. -- Call the correct authentication header function
  1046. function _s1xreq.add_auth_headers(request)
  1047.   local auth_func = {
  1048.     basic = _s1xreq.basic_auth_header,
  1049.     digest = _s1xreq.digest_auth_header
  1050.   }
  1051.  
  1052.   auth_func[request.auth._type](request)
  1053. end
  1054.  
  1055. local function str2bei(s)
  1056.   local v=0
  1057.   for i=1, #s do
  1058.     v = v * 256 + string.byte(s, i)
  1059.   end
  1060.   return v
  1061. end
  1062.  
  1063. function md5_tohex(s)
  1064.   return string.format("%08x%08x%08x%08x", str2bei(string.sub(s, 1, 4)), str2bei(string.sub(s, 5, 8)), str2bei(string.sub(s, 9, 12)), str2bei(string.sub(s, 13, 16)))
  1065. end
Add Comment
Please, Sign In to add comment