add sborka
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
local HOUR = 60 * 60
|
||||
local REWARD_AFTER = HOUR * 2
|
||||
local REWARD_SIZE = 150
|
||||
|
||||
local startTime = os.time()
|
||||
local animatedProgress = 0
|
||||
|
||||
CreateClientConVar("cl_igs_session_ui_hide", "0", true, false)
|
||||
|
||||
surface.CreateFont("IGS_SessionTitle", {
|
||||
font = "Roboto",
|
||||
size = 17,
|
||||
weight = 600
|
||||
})
|
||||
|
||||
surface.CreateFont("IGS_SessionSub", {
|
||||
font = "Roboto",
|
||||
size = 14,
|
||||
weight = 400
|
||||
})
|
||||
|
||||
surface.CreateFont("IGS_Tooltip", {
|
||||
font = "Roboto",
|
||||
size = 12,
|
||||
weight = 400
|
||||
})
|
||||
|
||||
local coinMat = Material("icon16/coins.png")
|
||||
local gearMat = Material("icon16/cog.png") -- ⚙ значок настроек (скрыть)
|
||||
|
||||
net.Receive("igs_session_start", function()
|
||||
startTime = net.ReadInt(32)
|
||||
end)
|
||||
|
||||
local function GetMinutesLeft()
|
||||
local elapsed = os.time() - startTime
|
||||
local left = math.max(0, REWARD_AFTER - elapsed)
|
||||
return math.ceil(left / 60)
|
||||
end
|
||||
|
||||
-- 🔥 Toggle по клавише F6
|
||||
hook.Add("Think", "igs_session_ui_toggle", function()
|
||||
if input.IsKeyDown(KEY_F2) and not _igsKeyPressed then
|
||||
_igsKeyPressed = true
|
||||
RunConsoleCommand("cl_igs_session_ui_hide",
|
||||
GetConVar("cl_igs_session_ui_hide"):GetInt() == 1 and "0" or "1")
|
||||
elseif not input.IsKeyDown(KEY_F2) then
|
||||
_igsKeyPressed = false
|
||||
end
|
||||
end)
|
||||
|
||||
local width, height = 300, 98
|
||||
|
||||
hook.Add("HUDPaint", "igs_session_ui", function()
|
||||
local pl = LocalPlayer()
|
||||
if not IsValid(pl) then return end
|
||||
|
||||
local hidden = GetConVar("cl_igs_session_ui_hide"):GetInt() == 1
|
||||
local minutesLeft = GetMinutesLeft()
|
||||
if minutesLeft <= 0 then return end
|
||||
if hidden then
|
||||
-- Показываем только маленький tooltip внизу
|
||||
local tx = ScrW() - 130
|
||||
local ty = 20
|
||||
draw.SimpleText("Нажмите F2 — показать", "IGS_Tooltip",
|
||||
tx, ty, Color(200,200,200))
|
||||
return
|
||||
end
|
||||
|
||||
local x = ScrW() - width - 20
|
||||
local y = 20
|
||||
|
||||
draw.RoundedBox(8, x, y, width, height, Color(0,0,0,190))
|
||||
|
||||
local realProgress = 1 - (minutesLeft * 60) / REWARD_AFTER
|
||||
animatedProgress = Lerp(FrameTime() * 3, animatedProgress, realProgress)
|
||||
|
||||
surface.SetDrawColor(255,255,255)
|
||||
surface.SetMaterial(coinMat)
|
||||
surface.DrawTexturedRect(x + 10, y + 10, 18, 18)
|
||||
|
||||
draw.SimpleText("Бонус за игру! " .. REWARD_SIZE .. " руб",
|
||||
"IGS_SessionTitle", x + 32, y + 11, Color(255,255,255))
|
||||
|
||||
draw.RoundedBox(5, x + 10, y + 35,
|
||||
(width - 20) * animatedProgress, 15,
|
||||
Color(72,92,44))
|
||||
|
||||
draw.SimpleText("Осталось: " .. minutesLeft .. " мин",
|
||||
"IGS_SessionSub", x + 10, y + 60, Color(220,220,220))
|
||||
|
||||
-- ⚙ Кнопка скрытия
|
||||
surface.SetMaterial(gearMat)
|
||||
surface.DrawTexturedRect(x + width - 27, y + 10, 16, 16)
|
||||
|
||||
-- Проверка клика по кнопке
|
||||
if input.IsMouseDown(MOUSE_LEFT) then
|
||||
local mx, my = gui.MousePos()
|
||||
if mx >= x + width - 27 and mx <= x + width - 11
|
||||
and my >= y + 10 and my <= y + 26 then
|
||||
RunConsoleCommand("cl_igs_session_ui_hide", "1")
|
||||
end
|
||||
end
|
||||
|
||||
-- Tooltip внизу панели
|
||||
draw.SimpleText("Нажмите F2 — скрыть", "IGS_Tooltip",
|
||||
x + 10, y + height - 18, Color(200, 200, 200, 180))
|
||||
end)
|
||||
121
garrysmod/addons/igsmodification/lua/autorun/l_ingameshopmod.lua
Normal file
121
garrysmod/addons/igsmodification/lua/autorun/l_ingameshopmod.lua
Normal file
@@ -0,0 +1,121 @@
|
||||
file.CreateDir("igs")
|
||||
|
||||
-- Вы можете сделать форк основного репозитория, сделать там изменения и указать его имя здесь
|
||||
-- Таким образом IGS будет грузиться у всех с вашего репозитория
|
||||
IGS_REPO = "GM-DONATE/IGS" -- "AMD-NICK/IGS-1"
|
||||
if not IGS_REPO or file.Exists("autorun/l_ingameshop.lua", "LUA") then return end -- force lua
|
||||
|
||||
|
||||
local function checkRunString()
|
||||
RunString("IGS_Test_RS = true", "IGS_Test_RS")
|
||||
assert(IGS_Test_RS, "RunString не работает: https://forum.gm-donate.net/t/1663")
|
||||
IGS_Test_RS = nil
|
||||
end
|
||||
|
||||
checkRunString() -- сразу может быть, а потом пропасть
|
||||
|
||||
-- http либа работает не сразу
|
||||
local fetchDelayed = function(delay, url, fOk, fErr, tHeaders)
|
||||
timer.Simple(delay, function()
|
||||
http.Fetch(url, fOk, fErr, tHeaders)
|
||||
end)
|
||||
end
|
||||
|
||||
local replaceGithubUrl = function(original)
|
||||
return original
|
||||
:gsub("^https://api.github.com", "https://gh.gm-donate.net/api")
|
||||
:gsub("^https://github.com", "https://gh.gm-donate.net")
|
||||
end
|
||||
|
||||
local function wrapFetch(url, cb, retry_)
|
||||
local retry3Times = function()
|
||||
retry_ = retry_ or 1
|
||||
if retry_ < 3 then
|
||||
wrapFetch(url, cb, retry_ + 1)
|
||||
elseif retry_ == 3 then -- last chance
|
||||
local newurl = replaceGithubUrl(url)
|
||||
wrapFetch(newurl or url, cb, retry_ + 1)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local patt = "IGS Не может выполнить HTTP запрос и загрузить скрипт\nURL: %s\nError: %s\n"
|
||||
fetchDelayed((retry_ or 0) * 5, url, cb, function(err) -- timeout, unsuccessful
|
||||
local fault = retry3Times()
|
||||
if not fault then return end -- пытается дальше
|
||||
-- попытки исчерпались
|
||||
|
||||
error(patt:format(url, err))
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local function downloadSuperfile(version, cb, _failure)
|
||||
local url = "https://github.com/" .. IGS_REPO .. "/releases/download/" .. version .. "/superfile.json"
|
||||
if _failure then ErrorNoHalt("[IGS] #" .. _failure .. " повторение загрузки", url) end
|
||||
|
||||
wrapFetch(url, function(superfile)
|
||||
local dat = util.JSONToTable(superfile)
|
||||
if not dat and (_failure or 0) < 3 then
|
||||
downloadSuperfile(version, cb, (_failure or 0) + 1)
|
||||
return
|
||||
end
|
||||
|
||||
local err =
|
||||
not dat and "superfile.json получен не в правильном формате"
|
||||
or dat.error and ("Ошибка от GitHub: " .. dat.error)
|
||||
|
||||
assert(not err, (err or "") .. "\n" .. url .. "\nПопробуйте снова или почитайте тут https://forum.gm-donate.net/t/1663")
|
||||
|
||||
file.Write("igs/superfile.txt", superfile)
|
||||
cb(superfile)
|
||||
end)
|
||||
end
|
||||
|
||||
local function loadFromFile(superfile)
|
||||
checkRunString()
|
||||
|
||||
local path = "autorun/l_ingameshop.lua"
|
||||
IGS_MOUNT = util.JSONToTable(superfile)
|
||||
|
||||
RunString(IGS_MOUNT[path], path)
|
||||
end
|
||||
|
||||
local function findFreshestVersion(cb)
|
||||
wrapFetch("https://api.github.com/repos/" .. IGS_REPO .. "/releases", function(json)
|
||||
local releases = util.JSONToTable(json)
|
||||
table.sort(releases, function(a, b) -- свежайшие версии сначала
|
||||
return tonumber(a.tag_name) > tonumber(b.tag_name)
|
||||
end)
|
||||
|
||||
local freshest_version = releases[1]
|
||||
assert(freshest_version, "Релизов нет. Нужно запустить CI: https://forum.gm-donate.net/t/1663")
|
||||
|
||||
cb(freshest_version.tag_name)
|
||||
end)
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
local superfile = file.Read("igs/superfile.txt")
|
||||
local version = cookie.GetString("igs_version")
|
||||
|
||||
if superfile and version then -- 2 может не быть, если сервер перенесли без sv.db
|
||||
loadFromFile(superfile)
|
||||
|
||||
elseif not version then
|
||||
findFreshestVersion(function(freshest_version)
|
||||
cookie.Set("igs_version", freshest_version)
|
||||
downloadSuperfile(freshest_version, loadFromFile)
|
||||
end)
|
||||
|
||||
else -- version
|
||||
downloadSuperfile(version, loadFromFile)
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
CreateConVar("igs_version", "", {FCVAR_REPLICATED})
|
||||
local version = GetConVar("igs_version"):GetString()
|
||||
assert(tonumber(version), "cvar igs_version не передался клиенту. " .. version .. ": https://forum.gm-donate.net/t/1663")
|
||||
downloadSuperfile(version, loadFromFile)
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
if SERVER then
|
||||
util.AddNetworkString("igs_session_start")
|
||||
util.AddNetworkString("igs_session_reward_given")
|
||||
|
||||
local HOUR = 60 * 60
|
||||
local REWARD_AFTER = HOUR * 2 -- 2 часа
|
||||
local REWARD_SIZE = 150 -- 150 рублей (изменено по просьбе пользователя)
|
||||
|
||||
-- Таблица для отслеживания времени начала сессии игроков
|
||||
local playerSessionStart = {}
|
||||
local playerRewardGiven = {}
|
||||
|
||||
-- Отправка времени начала сессии при спавне
|
||||
hook.Add("PlayerInitialSpawn", "igs.session_reward_ui", function(pl)
|
||||
playerSessionStart[pl:SteamID()] = os.time()
|
||||
|
||||
local lastRewardDate = pl:GetPData("igs_playtime_bonus_date", "")
|
||||
local currentDate = os.date("%d-%m-%Y")
|
||||
|
||||
playerRewardGiven[pl:SteamID()] = (lastRewardDate == currentDate)
|
||||
|
||||
net.Start("igs_session_start")
|
||||
net.WriteInt(os.time(), 32)
|
||||
net.Send(pl)
|
||||
end)
|
||||
|
||||
-- Очистка данных при отключении игрока
|
||||
hook.Add("PlayerDisconnected", "igs.session_cleanup", function(pl)
|
||||
playerSessionStart[pl:SteamID()] = nil
|
||||
playerRewardGiven[pl:SteamID()] = nil
|
||||
end)
|
||||
|
||||
-- Проверка и выдача награды каждые 60 секунд
|
||||
timer.Create("igs.check_session_rewards", 60, 0, function()
|
||||
for _, pl in pairs(player.GetAll()) do
|
||||
local steamID = pl:SteamID()
|
||||
local startTime = playerSessionStart[steamID]
|
||||
local rewardGiven = playerRewardGiven[steamID]
|
||||
|
||||
if startTime and not rewardGiven then
|
||||
local elapsed = os.time() - startTime
|
||||
|
||||
-- Если прошло 2 часа - выдаем награду
|
||||
if elapsed >= REWARD_AFTER then
|
||||
-- Проверяем, что игрок не AFK (опционально)
|
||||
if IsValid(pl) and pl:Alive() then
|
||||
-- Выдаем рубли на баланс IGS
|
||||
pl:AddIGSFunds(REWARD_SIZE, "Бонус за 2 часа игры")
|
||||
|
||||
-- Уведомление игроку
|
||||
IGS.Notify(pl, "Вы получили " .. REWARD_SIZE .. " руб за 2 часа игры!")
|
||||
|
||||
-- Помечаем, что награда выдана
|
||||
playerRewardGiven[steamID] = true
|
||||
pl:SetPData("igs_playtime_bonus_date", os.date("%d-%m-%Y"))
|
||||
|
||||
-- Логирование
|
||||
print("[IGS Session Reward] " .. pl:Nick() .. " (" .. steamID .. ") получил " .. REWARD_SIZE .. " руб за 2 часа игры")
|
||||
|
||||
-- Отправляем клиенту сигнал об успешной выдаче
|
||||
net.Start("igs_session_reward_given")
|
||||
net.Send(pl)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user