Compare commits

..

No commits in common. 'master' and 'test-utf-8' have entirely different histories.

  1. BIN
      TruckHUD.exe
  2. 277
      TruckHUD.lua
  3. 23
      changelog
  4. 2
      version

Binary file not shown.

@ -1,6 +1,6 @@
script_name("TruckHUD")
script_author("Serhiy_Rubin")
script_version("27.07.2026")
script_version("30.01.23")
local inicfg = require "inicfg"
local dlstatus = require("moonloader").download_status
@ -93,7 +93,7 @@ local prices_3dtext = { n1 = 0, n2 = 0, y1 = 0, y2 = 0, l1 = 0, l2 = 0, lsn = 0,
local prices_mon = { n1 = 0, n2 = 0, y1 = 0, y2 = 0, l1 = 0, l2 = 0, lsn = 0, lsy = 0, lsl = 0, sfn = 0, sfy = 0, sfl = 0 }
local prices_smon = { n1 = 0, n2 = 0, y1 = 0, y2 = 0, l1 = 0, l2 = 0, lsn = 0, lsy = 0, lsl = 0, sfn = 0, sfy = 0, sfl = 0 }
local delay, d = {chatMon = 0, chat = 0, skill = -1, mon = 0, load = 0, unload = 0, sms = 0, dir = 0, paycheck = 0, boostinfo = 0}, {[3] = ""}
local delay, d = {chatMon = 0, chat = 0, skill = -1, mon = 0, load = 0, unload = 0, sms = 0, dir = 0, paycheck = 0}, {[3] = ""}
local pickupLoad = {
[1] = {251.32167053223, 1420.3039550781, 11.5}, -- N1
[2] = {839.09020996094, 880.17510986328, 14.3515625}, -- Y1
@ -196,10 +196,7 @@ function main()
(server:find("02") and "Two" or
(server:find("Revo") and "Revolution" or
(server:find("Legacy") and "Legacy" or (server:find("Classic") and "Classic" or
(server:find("Zero Two") and "Two" or
(server:find("TEST") and "TEST" or
(server:find("Renaissance") and "Renaissance" or
(server:find("Home") and "Home" or "" ))))))))
(server:find("Zero Two") and "Two" or "")))))
if server == "" then
thisScript():unload()
end
@ -231,7 +228,7 @@ function main()
lua_thread.create(luChecker.checker)
lua_thread.create(doCruise)
platinum_check()
repeat
wait(0)
@ -260,15 +257,6 @@ function main()
end
end
maxload_int = 0
function maxload()
if maxload_int == 0 then
addChatMessage("Пересядь в фуру чтобы понять сколько груза брать!")
else
sampSendChat("/truck load "..maxload_int)
end
end
function settings_load()
wait(0)
local x1, y1 = convertGameScreenCoordsToWindowScreenCoords(14.992679595947, 274.75)
@ -348,16 +336,7 @@ function settings_load()
binder = { '/r На месте', '/r Загружаюсь', '/r Задержусь', '/r Разгружаюсь' },
binder_sms = { '/sms !ИдПары На месте', '/sms !ИдПары Загружаюсь', '/sms !ИдПары Задержусь', '/sms !ИдПары Разгружаюсь' },
blacklist = {},
version = thisScript().version,
platinum = {
status = false,
time = 0
},
boostinfo = {
pay = 1.0,
exp = 1.0,
date = 0
}
version = thisScript().version
}
if not doesFileExist(AdressJson) then
local file, error = io.open(AdressJson, "w")
@ -519,7 +498,7 @@ function doControl()
sampSendChat("/truck mon")
end
if i == 10 then
maxload()
sampSendChat("/truck load " .. GetGruz())
end
if i == 11 then
sampSendChat("/truck unload")
@ -576,7 +555,7 @@ function doSendCMD()
end
if delay.sms == 0 then
if delay.load == 1 then
maxload()
sampSendChat("/truck load " .. GetGruz())
delay.load = 2
end
if delay.load == 0 then
@ -789,11 +768,6 @@ function doDialog()
)
end
end
if str:find("Platinum VIP") then
inifiles.platinum.status = not inifiles.platinum.status
settings_save()
ShowDialog1(1)
end
if str:find("Шрифт") then
if dialogTextToList[list + 1] ~= nil then
ShowDialog1(2, dialogTextToList[list + 1], inifiles.Render.FontName, true, "Render", "FontName")
@ -1130,7 +1104,6 @@ function doCruise()
end
function doRenderStats()
boostinfo.start()
if pos[1] then
sampSetCursorMode(3)
local X, Y = getCursorPos()
@ -1161,8 +1134,7 @@ function doRenderStats()
end
end
Y = Y + height
sec_timer = (inifiles.platinum.status and 120 or 180)
timer_secc = sec_timer - os.difftime(msk_timestamp, timer)
timer_secc = 180 - os.difftime(msk_timestamp, timer)
local ost_time = 3600 - (os.date("%M", msk_timestamp) * 60) + (os.date("%S", msk_timestamp))
local greys = 0
if workload == 1 then
@ -1176,7 +1148,7 @@ function doRenderStats()
end
end
greys = greys + math.floor(ost_time / 360)
if timer_secc >= (sec_timer - 3) and workload == 0 and isTruckCar() and inifiles.Settings.Stop then
if timer_secc >= 177 and workload == 0 and isTruckCar() and inifiles.Settings.Stop then
setGameKeyState(6, 255)
end
timer_min, timer_sec = math.floor(timer_secc / 60), timer_secc % 60
@ -1222,12 +1194,12 @@ function doRenderStats()
end
if
os.difftime(msk_timestamp, timer) > sec_timer and
os.difftime(msk_timestamp, timer) > 180 and
autoh and
(not isPairModeActive() or (isPairModeActive() and os.time() - pair_afk_stop.auto_stop >= 3)) and
(not isPairModeActive() or (isPairModeActive() and (msk_timestamp - pair_timestamp) < 5)) and
(not isPairModeActive() or (isPairModeActive() and (pair_ready and player_ready))) and
not (isPairModeActive() and inifiles.Settings.auto_load_unload_kd_pair_use and base[pair_mode_name].gruz == current_load and os.difftime(msk_timestamp, base[pair_mode_name].timer) <= sec_timer)
not (isPairModeActive() and inifiles.Settings.auto_load_unload_kd_pair_use and base[pair_mode_name].gruz == current_load and os.difftime(msk_timestamp, base[pair_mode_name].timer) <= 180)
then
if workload == 1 then
if unload_location then
@ -1352,7 +1324,7 @@ function doRenderStats()
end
if inifiles.Settings.pairinfo and pair_mode and pair_status == 200 and pair_table ~= nil and pair_table["pos"] ~= nil and base[pair_mode_name] ~= nil then
local afk = msk_timestamp - pair_timestamp
local timer_d = sec_timer - (base[pair_mode_name].timer > 1000 and os.difftime(msk_timestamp, base[pair_mode_name].timer) or (sec_timer+1))
local timer_d = 180 - (base[pair_mode_name].timer > 1000 and os.difftime(msk_timestamp, base[pair_mode_name].timer) or 181)
local color = ( not player_ready and "" or (
pair_ready and "{07a817}" or "{d90b0b}"
))
@ -1863,7 +1835,6 @@ end
function ShowDialog1(int, dtext, dinput, string_or_number, ini1, ini2)
d[1], d[2], d[3], d[4], d[5], d[6] = int, dtext, dinput, string_or_number, ini1, ini2
if int == 1 then
local new = "{59fc30}[NEW]{ffffff} "
dialogLine, dialogTextToList, iniName = {}, {}, {}
dialogLine[#dialogLine + 1] = (script_run and "TruckHUD\t{59fc30}ON" or "TruckHUD\t{ff0000}OFF")
@ -1966,8 +1937,6 @@ function ShowDialog1(int, dtext, dinput, string_or_number, ini1, ini2)
dialogTextToList[#dialogLine] =
"{FFFFFF}Введите новый цвет в HEX\nПодобрать цвет можно через браузер\nЧтобы скопировать ссылку введите /truck url"
dialogLine[#dialogLine + 1] = new.."Platinum VIP (2 мин кд)\t" .. (inifiles.platinum.status == true and "{59fc30}ON" or "{ff0000}OFF")
dialogLine[#dialogLine + 1] = "Шрифт\t" .. inifiles.Render.FontName -- 7
dialogTextToList[#dialogLine] = "{FFFFFF}Введите название шрифта"
@ -2270,28 +2239,6 @@ function loadEvents()
end
function sampev.onServerMessage(color, message)
if message:find("У вас .E5E4E2.PLATINUM VIP.EAC700. до %d+/%d+/%d+ %d+:%d+") then
local year, mounth, day, hour, min = message:match("У вас .E5E4E2.PLATINUM VIP.EAC700. до (%d+)/(%d+)/(%d+) (%d+):(%d+)")
datetime = {
year = tonumber(year),
month = tonumber(mounth),
day = tonumber(day),
hour = tonumber(hour),
min = tonumber(min),
sec = 5
}
if os.time(datetime) ~= inifiles.platinum.time then
inifiles.platinum.time = os.time(datetime)
settings_save()
end
if not inifiles.platinum.status then
inifiles.platinum.status = true
settings_save()
end
end
if string.find(message, " Нефть: %d+ / (%d+)$") then
maxload_int = tonumber(string.match(message, " Нефть: %d+ / (%d+)$"))
end
if message == " У вас бан чата!" then
delay.chatMon = 0
delay.chat = 0
@ -2553,7 +2500,8 @@ function loadEvents()
if string.find(message, "Вы заработали (%d+) вирт, из которых (%d+) вирт будет добавлено к вашей зарплате") and isTruckCar() then
pttModule()
timer = msk_timestamp
local Z1, Z2 = string.match(message, " Вы заработали (%d+) вирт, из которых (%d+) вирт будет добавлено к вашей зарплате")
local Z1, Z2 =
string.match(message, " Вы заработали (%d+) вирт, из которых (%d+) вирт будет добавлено к вашей зарплате")
if texts_of_reports[current_warehouse] ~= nil and gruzLOAD ~= nil then
local cena = Z1 / (gruzLOAD / 1000)
local sklad = texts_of_reports[current_warehouse]
@ -2567,11 +2515,6 @@ function loadEvents()
delay.sms = 1
end
end
if inifiles.boostinfo.pay > 1.0 then
local cena_gruz = tonumber(Z1) - tonumber(Z2)
Z2 = tonumber(Z2) * inifiles.boostinfo.pay
Z1 = cena_gruz + Z2
end
if inifiles.Trucker.MaxZP > tonumber(inifiles.log[os.date("%d.%m.%Y", msk_timestamp)].hour[os.date("%H", msk_timestamp)].zp + Z2) then
write_table_log('razgruzka', {Z1, Z2, (Z1 - Z2)}, 2)
else
@ -2597,10 +2540,6 @@ function loadEvents()
auto = false
end
delay.paycheck = 1
if inifiles.boostinfo.pay > 1.0 then
text = string.format(" Вы заработали %d вирт, из которых %d вирт будет добавлено к вашей зарплате", Z1, Z2)
return {color, text}
end
end
if message == " Не флуди!" then
if delay.skill == 2 then
@ -2655,10 +2594,6 @@ function loadEvents()
local Z1 = string.match(message, " Вы купили канистру с 50 литрами бензина за (%d+) вирт")
write_table_log('kanistr', {Z1}, 8)
end
if boostinfo.onServerMessage(color, message) then
return false
end
end
function sampev.onShowDialog(DdialogId, Dstyle, Dtitle, Dbutton1, Dbutton2, Dtext)
@ -2675,20 +2610,12 @@ function loadEvents()
local S1 = gruzs / 100 * (1.1 ^ (50 - inifiles.Trucker.Skill))
local S2 = 10000 * (1.1 ^ inifiles.Trucker.Skill)
local S3 = (S1 * 100) / S2
inifiles.Trucker.ReysSkill = math.ceil((100.0 - SkillP) / S3) / inifiles.boostinfo.exp
inifiles.Trucker.ReysSkill = math.ceil((100.0 - SkillP) / S3)
inifiles.Trucker.ProcSkill = SkillP
-- if inifiles.Trucker.ProcRank ~= RankP then
-- inifiles.Trucker.ReysRank = math.ceil((100.0 - RankP) / (RankP - inifiles.Trucker.ProcRank))
-- inifiles.Trucker.ProcRank = RankP
-- end
local currentRankExp = gruzs * (1.1 ^ Rank) -- Сколько опыта нужно всего для текущего ранга
local expPerTrip = 10000 / 100 * (1.1 ^ (50 - Rank)) -- Опыта в ранг дает один рейс
local percentPerTrip = expPerTrip / currentRankExp * 100 -- В процентах один рейс
-- 0.27 0.135
local trips = (100 - RankP) / percentPerTrip -- Кол-во рейсов осталось до нового ранга
inifiles.Trucker.ReysRank = math.ceil(trips / inifiles.boostinfo.exp)
inifiles.Trucker.ProcRank = RankP
if inifiles.Trucker.ProcRank ~= RankP then
inifiles.Trucker.ReysRank = math.ceil((100.0 - RankP) / (RankP - inifiles.Trucker.ProcRank))
inifiles.Trucker.ProcRank = RankP
end
inifiles.Trucker.Skill = Skill
inifiles.Trucker.Rank = Rank
inifiles.Trucker.MaxZP = math.ceil( 50000 + (2500 * (1.1 ^ Skill)) + (2500 * (1.1 ^ Rank)) )
@ -2755,50 +2682,32 @@ function loadEvents()
end
if delay.dir ~= 0 then
if string.find(Dtitle, "справочник") and delay.dir == 2 then
sampSendDialogResponse(DdialogId, 1, 1, "Работы")
if string.find(Dtitle, "Тел.справочник") and delay.dir == 2 then
sampSendDialogResponse(DdialogId, 1, 1, "")
delay.dir = 3
return false
end
if string.find(Dtitle, "Работы") and delay.dir == 3 then
if Dtext:find("Дальнобойщик") then
local arr = split(Dtext, "\n")
dir_list = 0
dir_list_text = ""
for i = 1, #arr do
if arr[i]:find("Дальнобойщик") then
dir_list = i
dir_list_text = arr[i]
break
end
lua_thread.create(
function()
repeat
wait(0)
until delay.dir == 4
wait(150)
sampSendDialogResponse(DdialogId, 1, 9, "[9] Дальнобойщик")
end
lua_thread.create(
function()
repeat
wait(0)
until delay.dir == 4
wait(550)
sampSendDialogResponse(DdialogId, 1, dir_list - 1, "Дальнобойщик")
end
)
else
sampShowDialog(0,"Дальнобойщик","{ffffff}Список пуст","Закрыть","",0)
end
)
delay.dir = 4
return false
end
if string.find(Dtitle, "Дальнобойщик") and string.find(Dtext, "AFK секунд") and delay.dir == 4 then
if string.find(Dtitle, "Меню") and string.find(Dtext, "AFK секунд") and delay.dir == 4 then
delay.dir = 0
sampShowDialog(222, Dtitle, Dtext, Dbutton1, Dbutton2, Dstyle)
return false
end
end
if boostinfo.dialog(DdialogId, Dstyle, Dtitle, Dbutton1, Dbutton2, Dtext) then
return false
end
end
function sampev.onCreate3DText(id, color, position, distance, testLOS, attachedPlayerId, attachedVehicleId, text)
@ -3058,6 +2967,34 @@ function isTruckCar()
end
end
function GetGruz()
local gruz = 0
if isCharInModel(PLAYER_PED, 514) then
local Vehicle = storeCarCharIsInNoSave(PLAYER_PED)
local Color1, Color2 = getCarColours(Vehicle)
gruz = 10000
end
if isCharInModel(PLAYER_PED, 403) then
local Vehicle = storeCarCharIsInNoSave(PLAYER_PED)
local Color1, Color2 = getCarColours(Vehicle)
if Color1 == 36 and Color2 == 36 then
gruz = 30000
else
gruz = 20000
end
end
if isCharInModel(PLAYER_PED, 515) then
local Vehicle = storeCarCharIsInNoSave(PLAYER_PED)
local Color1, Color2 = getCarColours(Vehicle)
if Color1 == 34 and Color2 == 36 then
gruz = 50000
else
gruz = 40000
end
end
return gruz
end
function ChangeCena(st)
if st > 0 then
if workload == 1 then
@ -3188,8 +3125,7 @@ function transponder()
paraid = pair_mode_id,
timer = timer,
tmonitor = inifiles.tmonitor,
version = inifiles.version,
platinum = inifiles.platinum.status
version = inifiles.version
},
solo_message = solo_message_send
}
@ -3651,11 +3587,7 @@ function showTruckers()
if (sampIsPlayerConnected(v.id) or myid == v.id) and sampGetPlayerNickname(v.id) == k then
trucker_count = trucker_count + 1
local afk = math.ceil(msk_timestamp - v.timestamp)
local platinum = ""
if v.platinum then
platinum = "[VIP] "
end
dialogText = string.format('%s%s%s[%s] %s\t%s / %s\t%s\t%s\n', dialogText, platinum, k, v.id, (afk > 10 and '[AFK: '..afk..']' or ''), v.skill, v.rank, ( (v.is_truck and 'Да ' or 'Нет ')..(v.gruz == 0 and '/ Нет' or (v.gruz == 1 and '/ Нефть' or (v.gruz == 2 and '/ Уголь' or (v.gruz == 3 and '/ Дерево' or '/ Нет')))) ), ( v.pair_mode_name == '____' and 'Нет' or v.pair_mode_name..'['..v.paraid..']'))
dialogText = string.format('%s%s[%s] %s\t%s / %s\t%s\t%s\n', dialogText, k, v.id, (afk > 10 and '[AFK: '..afk..']' or ''), v.skill, v.rank, ( (v.is_truck and 'Да ' or 'Нет ')..(v.gruz == 0 and '/ Нет' or (v.gruz == 1 and '/ Нефть' or (v.gruz == 2 and '/ Уголь' or (v.gruz == 3 and '/ Дерево' or '/ Нет')))) ), ( v.pair_mode_name == '____' and 'Нет' or v.pair_mode_name..'['..v.paraid..']'))
end
end
end
@ -3675,14 +3607,13 @@ function renderTruckers()
local stream, ped = sampGetCharHandleBySampPlayerId(id)
if stream then
if (isCharInModel(ped, 403) or isCharInModel(ped, 514) or isCharInModel(ped, 515)) then
sec_timer = (base[nickname].platinum and 120 or 180)
local car = storeCarCharIsInNoSave(ped)
local result, idcar = sampGetVehicleIdByCarHandle(car)
if _3dTextplayers[id] == nil and result then
_3dTextplayers[id] = sampCreate3dText(' ', -1, 0.0, 0.0, 0.0, 30.0, false, -1, idcar)
end
if _3dTextplayers[id] ~= nil and result then
local timer_player = sec_timer - (base[nickname].timer > 1000 and os.difftime(msk_timestamp, base[nickname].timer) or (sec_timer+1))
local timer_player = 180 - (base[nickname].timer > 1000 and os.difftime(msk_timestamp, base[nickname].timer) or 181)
local color = (timer_player <= 0 and inifiles.Render.Color2 or (timer_player <= 10 and 'b50000' or inifiles.Render.Color2))
local kd_player = (timer_player > 0
and
@ -3698,7 +3629,7 @@ function renderTruckers()
)
local pair_kd = ''
if base[nickname].pair_mode_name ~= '____' and base[base[nickname].pair_mode_name] ~= nil then
local timer_d = sec_timer - (base[base[nickname].pair_mode_name].timer > 1000 and os.difftime(msk_timestamp, base[base[nickname].pair_mode_name].timer) or (sec_timer+1))
local timer_d = 180 - (base[base[nickname].pair_mode_name].timer > 1000 and os.difftime(msk_timestamp, base[base[nickname].pair_mode_name].timer) or 181)
local color = (timer_d <= 0 and inifiles.Render.Color2 or (timer_d <= 10 and 'b50000' or inifiles.Render.Color2))
pair_kd = string.format('(%s{%s})', (timer_d > 0 and string.format('{%s}%d:%02d', color, math.floor(timer_d / 60), timer_d % 60) or string.format('{%s}0:00', inifiles.Render.Color2)), inifiles.Render.Color2)
end
@ -4000,80 +3931,6 @@ function pttModule()
end
end
-->> boostinfo checker
boostinfo = {}
boostinfo.wait = 0
boostinfo.start = function()
if delay.boostinfo == 1 then
if os.clock() * 1000 - antiflood > 3000 then
boostinfo.wait = os.time()
sampSendChat("/boostinfo")
end
end
if delay.boostinfo == 0 then
delay.boostinfo = 1
end
if inifiles.boostinfo.date ~= 0 then
if os.time() > inifiles.boostinfo.date then
inifiles.boostinfo.pay = 1.0
inifiles.boostinfo.exp = 1.0
inifiles.boostinfo.date = 0
settings_save()
end
end
end
boostinfo.dialog = function(DdialogId, Dstyle, Dtitle, Dbutton1, Dbutton2, Dtext)
if delay.boostinfo > 0 then
if Dtitle:find("Бонусы") then
sampSendDialogResponse(DdialogId,(delay.boostinfo == 1 and 1 or 0),0,"[0] Общие бонусы")
delay.boostinfo = 2
return true
end
if Dtitle:find("Общие бонусы") then
local arr = split(Dtext, "\n")
for k,v in pairs(arr) do
if v:find("Зарплаты") then
inifiles.boostinfo.pay = tonumber(v:match("(%d+%.%d+)"))
end
if v:find("Дальнобойщика") then
inifiles.boostinfo.exp = tonumber(v:match("(%d+%.%d+)"))
end
end
settings_save()
sampSendDialogResponse(DdialogId,0,0,"[0] Общие бонусы")
return true
end
end
if os.time() - boostinfo.wait < 4 and Dtitle:find("онусы") then
sampSendDialogResponse(DdialogId,0,0,"[0] Общие бонусы")
return true
end
end
boostinfo.onServerMessage = function(color, message)
if delay.boostinfo > 0 then
if message:find("Действует до: (....)/(..)/(..) (..):(..):(..)") then
local year, month, day, hour, min, sec = message:match("Действует до: (....)/(..)/(..) (..):(..):(..)")
datetime = { year = year, month = month, day = day, hour = hour, min = min, sec = sec }
inifiles.boostinfo.date = os.time(datetime)
settings_save()
delay.boostinfo = -1
return true
end
if message:find("Бонусы отключены") then
inifiles.boostinfo.pay = 1.0
inifiles.boostinfo.exp = 1.0
inifiles.boostinfo.date = 0
settings_save()
delay.boostinfo = -1
return true
end
end
if os.time() - boostinfo.wait < 4 and (message:find("Действует до: (....)/(..)/(..) (..):(..):(..)") or message:find("Бонусы отключены")) then
return true
end
end
--> LOAD & UNLOAD CHECKER
luChecker = {
@ -4255,15 +4112,6 @@ function luChecker.checker()
end
end
-- platinum
function platinum_check()
if inifiles.platinum.status and inifiles.platinum.time < os.time() then
addChatMessage("'Platinum VIP' закончился. Теперь у Вас кд сново 3 минуты")
inifiles.platinum.status = false
settings_save()
end
end
function getLocalPlayerId()
return select(2,sampGetPlayerIdByCharHandle(PLAYER_PED))
end
@ -4622,4 +4470,3 @@ utf8({ "sampSet3dTextString" }, "Utf8ToAnsi")
utf8({ "sampGetDialogText" }, nil, "AnsiToUtf8")
utf8({ "sampGetDialogCaption" }, nil, "AnsiToUtf8")
utf8({ "sampHasDialogRespond" }, nil, "AnsiToUtf8")
utf8({ "sampSendDialogResponse" }, "Utf8ToAnsi")

@ -19,26 +19,3 @@
Версия от 30.01.2023
Фикс вылета скрипта из-за /truck hud
Версия от 14.02.2023
Теперь макс. количество груза берется из чата во время посадки в фуру
Версия от 18.02.2023
Исправлен баг когда скрипт постоянно пишет что нужно пересесть в фуру
Версия от 14.03.2023
Исправлен баг не работало 'Дальнобойщики онлайн'
Версия от 30.06.2023
Добавлена поддержка нового сервера Underground
Версия от 24.11.2023
Добавлен таймер 2 минуты для VIP
Версия от 28.06.2026
Добавлен новый сервер Home
Версия от 27.07.2026
Обновлен подсчет рейсов до нового скилла/ранга
Теперь учитываются бусты на опыт дальнобойщика и зарплату
Восстановлена работа функции "Дальнобойщики онлайн" (новый /dir)

@ -1 +1 @@
27.07.2026
30.01.23
Loading…
Cancel
Save