add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -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)

View 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

View File

@@ -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