add sborka
This commit is contained in:
667
garrysmod/gamemodes/militaryrp/plugins/f4menu/sv_plugin.lua
Normal file
667
garrysmod/gamemodes/militaryrp/plugins/f4menu/sv_plugin.lua
Normal file
@@ -0,0 +1,667 @@
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
util.AddNetworkString("ix.F4_RequestInfo")
|
||||
util.AddNetworkString("ix.F4_SendInfo")
|
||||
util.AddNetworkString("ix.F4_DonatePurchase")
|
||||
util.AddNetworkString("ix.F4_DonatePurchaseResult")
|
||||
util.AddNetworkString("ixChangeName")
|
||||
util.AddNetworkString("ixF4UpdateName")
|
||||
|
||||
local function GetFactionCounters(factionID, podIndex, specIndex)
|
||||
local factionOnline, samePod, sameSpec = 0, 0, 0
|
||||
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if not IsValid(ply) then continue end
|
||||
if ply:Team() ~= factionID then continue end
|
||||
|
||||
factionOnline = factionOnline + 1
|
||||
|
||||
local char = ply:GetCharacter()
|
||||
if not char then continue end
|
||||
|
||||
if char:GetPodr() == podIndex then
|
||||
samePod = samePod + 1
|
||||
end
|
||||
|
||||
if char:GetSpec() == specIndex then
|
||||
sameSpec = sameSpec + 1
|
||||
end
|
||||
end
|
||||
|
||||
return factionOnline, samePod, sameSpec
|
||||
end
|
||||
|
||||
local function BuildInfoPayload(client)
|
||||
local char = client:GetCharacter()
|
||||
if not char then return end
|
||||
|
||||
local factionID = char:GetFaction()
|
||||
local factionTable = ix.faction.Get(factionID)
|
||||
local podIndex = char:GetPodr()
|
||||
local specIndex = char:GetSpec()
|
||||
local rankIndex = char:GetRank() or 1
|
||||
|
||||
local factionOnline, samePod, sameSpec = GetFactionCounters(factionID, podIndex, specIndex)
|
||||
|
||||
local vehiclesPlugin = ix.plugin.Get("vehicles")
|
||||
local arsenalPlugin = ix.plugin.Get("arsenal")
|
||||
|
||||
local techPoints = 0
|
||||
if vehiclesPlugin and vehiclesPlugin.GetFactionPoints then
|
||||
techPoints = vehiclesPlugin:GetFactionPoints(factionID) or 0
|
||||
end
|
||||
|
||||
local supplyPoints = 0
|
||||
if arsenalPlugin and arsenalPlugin.GetFactionSupply then
|
||||
supplyPoints = arsenalPlugin:GetFactionSupply(factionID) or 0
|
||||
end
|
||||
|
||||
local activeVehicles = 0
|
||||
if vehiclesPlugin and vehiclesPlugin.activeVehicles then
|
||||
for _, data in pairs(vehiclesPlugin.activeVehicles) do
|
||||
if not istable(data) then continue end
|
||||
if data.faction == factionID then
|
||||
activeVehicles = activeVehicles + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local subdivisionData = {
|
||||
index = podIndex,
|
||||
name = "Не назначено",
|
||||
preset = {},
|
||||
specDefault = 1,
|
||||
members = samePod,
|
||||
model = "",
|
||||
skin = 0,
|
||||
bodygroups = {}
|
||||
}
|
||||
|
||||
local specData = {
|
||||
index = specIndex,
|
||||
name = "Не назначено",
|
||||
weapons = {},
|
||||
members = sameSpec,
|
||||
podr = 0
|
||||
}
|
||||
|
||||
local rankData = {
|
||||
index = rankIndex,
|
||||
name = "Без звания"
|
||||
}
|
||||
|
||||
if factionTable then
|
||||
if factionTable.Podr and factionTable.Podr[podIndex] then
|
||||
local unit = factionTable.Podr[podIndex]
|
||||
subdivisionData.name = unit.name or subdivisionData.name
|
||||
subdivisionData.preset = unit.preset or subdivisionData.preset
|
||||
subdivisionData.specDefault = unit.spec_def or subdivisionData.specDefault
|
||||
subdivisionData.model = unit.model or subdivisionData.model
|
||||
subdivisionData.skin = unit.skin or subdivisionData.skin
|
||||
subdivisionData.bodygroups = unit.bodygroups or subdivisionData.bodygroups
|
||||
end
|
||||
|
||||
if factionTable.Spec and factionTable.Spec[specIndex] then
|
||||
local spec = factionTable.Spec[specIndex]
|
||||
specData.name = spec.name or specData.name
|
||||
specData.weapons = spec.weapons or specData.weapons
|
||||
specData.podr = spec.podr or specData.podr
|
||||
end
|
||||
|
||||
if factionTable.Ranks and factionTable.Ranks[rankIndex] then
|
||||
local rank = factionTable.Ranks[rankIndex]
|
||||
rankData.name = rank[1] or rankData.name
|
||||
end
|
||||
end
|
||||
|
||||
local factionColor = nil
|
||||
if factionTable and factionTable.color then
|
||||
factionColor = { r = factionTable.color.r, g = factionTable.color.g, b = factionTable.color.b }
|
||||
end
|
||||
|
||||
local supplyStatus = "Стабильно"
|
||||
local minSupply = 0
|
||||
if arsenalPlugin and arsenalPlugin.config then
|
||||
minSupply = arsenalPlugin.config.minSupply or 0
|
||||
end
|
||||
|
||||
if supplyPoints <= minSupply then
|
||||
supplyStatus = "Критически низко"
|
||||
elseif supplyPoints <= minSupply * 2 and minSupply > 0 then
|
||||
supplyStatus = "Низко"
|
||||
end
|
||||
|
||||
return {
|
||||
timestamp = os.time(),
|
||||
faction = {
|
||||
id = factionID,
|
||||
name = factionTable and factionTable.name or "Неизвестно",
|
||||
description = factionTable and factionTable.description or "",
|
||||
color = factionColor,
|
||||
online = factionOnline,
|
||||
techPoints = techPoints,
|
||||
supplyPoints = supplyPoints,
|
||||
supplyStatus = supplyStatus,
|
||||
activeVehicles = activeVehicles
|
||||
},
|
||||
character = {
|
||||
name = char:GetName(),
|
||||
money = char:GetMoney(),
|
||||
id = char:GetID() or 0,
|
||||
rank = rankData,
|
||||
subdivision = subdivisionData,
|
||||
spec = specData
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
net.Receive("ix.F4_RequestInfo", function(_, client)
|
||||
if not IsValid(client) then return end
|
||||
local payload = BuildInfoPayload(client)
|
||||
if not payload then return end
|
||||
|
||||
net.Start("ix.F4_SendInfo")
|
||||
net.WriteTable(payload)
|
||||
net.Send(client)
|
||||
end)
|
||||
|
||||
local DONATE_PURCHASE_COOLDOWN = 2
|
||||
PLUGIN.donatePurchaseCooldowns = PLUGIN.donatePurchaseCooldowns or {}
|
||||
|
||||
local function GetCooldownKey(client)
|
||||
return client:SteamID64() or client:SteamID() or client:EntIndex()
|
||||
end
|
||||
|
||||
function PLUGIN:GetIGSBalance(client)
|
||||
if not IsValid(client) then return 0 end
|
||||
|
||||
if client.IGSFunds then
|
||||
local ok, funds = pcall(client.IGSFunds, client)
|
||||
if ok and isnumber(funds) then
|
||||
return math.max(math.floor(funds), 0)
|
||||
end
|
||||
end
|
||||
|
||||
if client.GetNetVar then
|
||||
local funds = client:GetNetVar("igsFunds", 0)
|
||||
if isnumber(funds) then
|
||||
return math.max(math.floor(funds), 0)
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
function PLUGIN:AdjustIGSBalance(client, amount)
|
||||
if not IsValid(client) then return false, "Игрок недоступен" end
|
||||
amount = tonumber(amount) or 0
|
||||
if amount == 0 then return true end
|
||||
|
||||
if not client.AddIGSFunds then
|
||||
return false, "IGS недоступен"
|
||||
end
|
||||
|
||||
local ok, err = pcall(client.AddIGSFunds, client, amount)
|
||||
if ok then
|
||||
return true
|
||||
end
|
||||
|
||||
return false, err or "Ошибка IGS"
|
||||
end
|
||||
|
||||
function PLUGIN:IsDonateOnCooldown(client)
|
||||
local key = GetCooldownKey(client)
|
||||
local expires = self.donatePurchaseCooldowns[key] or 0
|
||||
if CurTime() < expires then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:ArmDonateCooldown(client)
|
||||
local key = GetCooldownKey(client)
|
||||
self.donatePurchaseCooldowns[key] = CurTime() + DONATE_PURCHASE_COOLDOWN
|
||||
end
|
||||
|
||||
function PLUGIN:CanPurchaseDonateProduct(client, entry)
|
||||
local char = client:GetCharacter()
|
||||
if not char then
|
||||
return false, "Нет активного персонажа"
|
||||
end
|
||||
|
||||
if not entry then
|
||||
return false, "Предложение не найдено"
|
||||
end
|
||||
|
||||
if entry.oneTime then
|
||||
local history = char:GetData("donate_purchases", {})
|
||||
if history[entry.id] then
|
||||
return false, "Этот набор уже был приобретен"
|
||||
end
|
||||
end
|
||||
|
||||
local hookResult, hookMessage = hook.Run("CanPlayerBuyDonateProduct", client, entry)
|
||||
if hookResult == false then
|
||||
return false, hookMessage or "Покупка отклонена"
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function PLUGIN:GrantDonateItems(client, grantData)
|
||||
if not grantData then return end
|
||||
local char = client:GetCharacter()
|
||||
if not char then return end
|
||||
|
||||
if istable(grantData.weapons) and #grantData.weapons > 0 then
|
||||
local owned = char:GetData("donate_weapons", {})
|
||||
local changed
|
||||
for _, class in ipairs(grantData.weapons) do
|
||||
if isstring(class) and not table.HasValue(owned, class) then
|
||||
table.insert(owned, class)
|
||||
changed = true
|
||||
end
|
||||
end
|
||||
if changed then
|
||||
char:SetData("donate_weapons", owned)
|
||||
end
|
||||
end
|
||||
|
||||
if istable(grantData.cosmetics) and #grantData.cosmetics > 0 then
|
||||
local cosmetics = char:GetData("donate_cosmetics", {})
|
||||
for _, cosmeticID in ipairs(grantData.cosmetics) do
|
||||
if isstring(cosmeticID) then
|
||||
cosmetics[cosmeticID] = true
|
||||
end
|
||||
end
|
||||
char:SetData("donate_cosmetics", cosmetics)
|
||||
end
|
||||
|
||||
if istable(grantData.vehicles) and #grantData.vehicles > 0 then
|
||||
local vehicles = char:GetData("donate_vehicles", {})
|
||||
for _, certificate in ipairs(grantData.vehicles) do
|
||||
if isstring(certificate) then
|
||||
vehicles[#vehicles + 1] = certificate
|
||||
end
|
||||
end
|
||||
char:SetData("donate_vehicles", vehicles)
|
||||
end
|
||||
|
||||
if istable(grantData.boosts) and #grantData.boosts > 0 then
|
||||
local calls = char:GetData("donate_support_calls", {})
|
||||
for _, callID in ipairs(grantData.boosts) do
|
||||
calls[#calls + 1] = callID
|
||||
end
|
||||
char:SetData("donate_support_calls", calls)
|
||||
end
|
||||
|
||||
if istable(grantData.items) and #grantData.items > 0 then
|
||||
local pending = char:GetData("donate_items", {})
|
||||
for _, itemID in ipairs(grantData.items) do
|
||||
pending[#pending + 1] = { id = itemID, ts = os.time() }
|
||||
end
|
||||
char:SetData("donate_items", pending)
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:ApplyDonateReward(client, entry, mode)
|
||||
local char = client:GetCharacter()
|
||||
if not char then
|
||||
return false, "Нет активного персонажа"
|
||||
end
|
||||
|
||||
local reward = entry.reward
|
||||
if not reward then
|
||||
local hookResult, hookMessage = hook.Run("OnDonateReward", client, entry, mode)
|
||||
if hookResult ~= nil then
|
||||
return hookResult, hookMessage
|
||||
end
|
||||
return false, "Награда не настроена"
|
||||
end
|
||||
|
||||
local rewardType = reward.type
|
||||
|
||||
if rewardType == "privilege" then
|
||||
local tier = reward.tier or entry.id
|
||||
local duration = nil
|
||||
|
||||
if mode == "3month" then
|
||||
duration = os.time() + (90 * 86400) -- 90 дней
|
||||
else
|
||||
duration = os.time() + (30 * 86400) -- 30 дней (1 месяц)
|
||||
end
|
||||
|
||||
local privileges = char:GetData("donate_privileges", {})
|
||||
privileges[tier] = {
|
||||
tier = tier,
|
||||
expires = duration,
|
||||
granted = os.time(),
|
||||
mode = mode or "month"
|
||||
}
|
||||
char:SetData("donate_privileges", privileges)
|
||||
|
||||
-- Применяем группу через SAM если доступно
|
||||
if sam then
|
||||
local groupMap = {
|
||||
vip = "vip",
|
||||
vip_plus = "vip_plus",
|
||||
premium = "premium",
|
||||
sponsor = "sponsor"
|
||||
}
|
||||
local rank = groupMap[tier]
|
||||
if rank then
|
||||
local expireTime = mode == "3month" and os.time() + (90 * 86400) or os.time() + (30 * 86400)
|
||||
sam.player.set_rank(client, rank, expireTime)
|
||||
end
|
||||
end
|
||||
|
||||
local modeText = mode == "3month" and "на 3 месяца" or "на 1 месяц"
|
||||
return true, reward.successMessage or ("Привилегия " .. tier .. " активирована " .. modeText)
|
||||
|
||||
elseif rewardType == "weapon" then
|
||||
local weaponClass = reward.weaponClass or reward.class
|
||||
if not weaponClass then
|
||||
return false, "Класс оружия не указан"
|
||||
end
|
||||
|
||||
-- Добавляем оружие в список донат-оружия персонажа со сроком действия
|
||||
local donateWeapons = char:GetData("donate_weapons_timed", {})
|
||||
if not istable(donateWeapons) then donateWeapons = {} end
|
||||
|
||||
-- Вычисляем срок действия
|
||||
local expireTime
|
||||
if mode == "3month" then
|
||||
expireTime = os.time() + (90 * 86400) -- 90 дней
|
||||
else
|
||||
expireTime = os.time() + (30 * 86400) -- 30 дней
|
||||
end
|
||||
|
||||
-- Добавляем или обновляем срок
|
||||
donateWeapons[weaponClass] = {
|
||||
expires = expireTime,
|
||||
granted = os.time(),
|
||||
mode = mode or "1month"
|
||||
}
|
||||
char:SetData("donate_weapons_timed", donateWeapons)
|
||||
|
||||
local modeText = mode == "3month" and "на 3 месяца" or "на 1 месяц"
|
||||
return true, reward.successMessage or ("Донат-оружие " .. (reward.name or weaponClass) .. " добавлено в ваш арсенал " .. modeText)
|
||||
|
||||
elseif rewardType == "money" then
|
||||
local amount = reward.amount or 0
|
||||
if amount > 0 and char.GiveMoney then
|
||||
char:GiveMoney(math.floor(amount))
|
||||
return true, reward.successMessage or ("Вам начислено " .. amount .. " ₽")
|
||||
end
|
||||
return false, "Ошибка начисления денег"
|
||||
|
||||
elseif rewardType == "voice_chat" then
|
||||
-- Разблокировка голосового чата
|
||||
char:SetData("voice_chat_unlocked", true)
|
||||
|
||||
-- Если есть система SAM, можно добавить флаг
|
||||
if sam then
|
||||
-- Можно добавить специальную группу или флаг для голосового чата
|
||||
end
|
||||
|
||||
return true, reward.successMessage or "Голосовой чат разблокирован!"
|
||||
|
||||
elseif rewardType == "bundle" then
|
||||
if reward.money and reward.money > 0 and char.GiveMoney then
|
||||
char:GiveMoney(math.floor(reward.money))
|
||||
end
|
||||
|
||||
if reward.supply and reward.supply ~= 0 then
|
||||
local arsenal = ix.plugin.Get("arsenal")
|
||||
if arsenal and arsenal.AddFactionSupply then
|
||||
arsenal:AddFactionSupply(client:Team(), reward.supply)
|
||||
end
|
||||
end
|
||||
|
||||
if reward.techPoints and reward.techPoints ~= 0 then
|
||||
local vehicles = ix.plugin.Get("vehicles")
|
||||
if vehicles and vehicles.AddFactionPoints then
|
||||
vehicles:AddFactionPoints(client:Team(), reward.techPoints)
|
||||
end
|
||||
end
|
||||
|
||||
if reward.grantedItems then
|
||||
self:GrantDonateItems(client, reward.grantedItems)
|
||||
end
|
||||
|
||||
return true, reward.successMessage or "Комплект успешно выдан"
|
||||
|
||||
elseif rewardType == "pass" then
|
||||
local tier = reward.tier or entry.id
|
||||
local duration = math.max(1, tonumber(reward.durationDays) or 30) * 86400
|
||||
local passes = char:GetData("donate_passes", {})
|
||||
passes[tier] = {
|
||||
tier = tier,
|
||||
expires = os.time() + duration,
|
||||
bonuses = reward.bonuses or {}
|
||||
}
|
||||
char:SetData("donate_passes", passes)
|
||||
return true, reward.successMessage or "Подписка активирована"
|
||||
elseif rewardType == "booster" then
|
||||
local boosterID = reward.boosterID or entry.id
|
||||
local duration = math.max(1, tonumber(reward.durationHours) or 24) * 3600
|
||||
local boosters = char:GetData("donate_boosters", {})
|
||||
boosters[boosterID] = {
|
||||
expires = os.time() + duration,
|
||||
multiplier = reward.multiplier or 1.0
|
||||
}
|
||||
char:SetData("donate_boosters", boosters)
|
||||
return true, reward.successMessage or "Бустер активирован"
|
||||
elseif rewardType == "case" then
|
||||
local caseID = reward.caseID or entry.id
|
||||
local cases = char:GetData("donate_cases", {})
|
||||
cases[caseID] = (cases[caseID] or 0) + 1
|
||||
char:SetData("donate_cases", cases)
|
||||
return true, reward.successMessage or "Кейс добавлен в коллекцию"
|
||||
elseif rewardType == "cosmetic" then
|
||||
local unlockID = reward.unlockID or entry.id
|
||||
local cosmetics = char:GetData("donate_cosmetics", {})
|
||||
cosmetics[unlockID] = true
|
||||
char:SetData("donate_cosmetics", cosmetics)
|
||||
return true, reward.successMessage or "Косметика разблокирована"
|
||||
end
|
||||
|
||||
local hookResult, hookMessage = hook.Run("OnDonateReward", client, entry)
|
||||
if hookResult ~= nil then
|
||||
return hookResult, hookMessage
|
||||
end
|
||||
|
||||
return false, "Тип награды не поддерживается"
|
||||
end
|
||||
|
||||
function PLUGIN:MarkDonatePurchase(client, entry)
|
||||
local char = client:GetCharacter()
|
||||
if not char then return end
|
||||
|
||||
local history = char:GetData("donate_purchases", {})
|
||||
history[entry.id] = (history[entry.id] or 0) + 1
|
||||
char:SetData("donate_purchases", history)
|
||||
end
|
||||
|
||||
function PLUGIN:SendDonateResult(client, success, message, productID)
|
||||
if not IsValid(client) then return end
|
||||
|
||||
net.Start("ix.F4_DonatePurchaseResult")
|
||||
net.WriteBool(success and true or false)
|
||||
net.WriteString(message or "")
|
||||
net.WriteString(productID or "")
|
||||
net.Send(client)
|
||||
end
|
||||
|
||||
function PLUGIN:HandleDonatePurchase(client, productID, price, mode)
|
||||
local entry = self:GetDonateProduct(productID)
|
||||
local ok, msg = self:CanPurchaseDonateProduct(client, entry)
|
||||
if not ok then
|
||||
return false, msg, entry
|
||||
end
|
||||
|
||||
local actualPrice = price or tonumber(entry and entry.price) or 0
|
||||
if actualPrice <= 0 then
|
||||
return false, "Цена предложения не настроена", entry
|
||||
end
|
||||
|
||||
local funds = self:GetIGSBalance(client)
|
||||
if funds < actualPrice then
|
||||
return false, "Недостаточно средств на балансе", entry
|
||||
end
|
||||
|
||||
local debited, debitError = self:AdjustIGSBalance(client, -actualPrice)
|
||||
if not debited then
|
||||
return false, debitError or "Не удалось списать средства", entry
|
||||
end
|
||||
|
||||
local success, rewardMessage = self:ApplyDonateReward(client, entry, mode)
|
||||
if not success then
|
||||
self:AdjustIGSBalance(client, actualPrice)
|
||||
return false, rewardMessage or "Ошибка выдачи награды", entry
|
||||
end
|
||||
|
||||
self:MarkDonatePurchase(client, entry, mode)
|
||||
hook.Run("PostDonatePurchase", client, entry, actualPrice, mode)
|
||||
|
||||
return true, rewardMessage or "Покупка завершена", entry
|
||||
end
|
||||
|
||||
net.Receive("ix.F4_DonatePurchase", function(_, client)
|
||||
if not IsValid(client) or not client:IsPlayer() then return end
|
||||
|
||||
local productID = net.ReadString() or ""
|
||||
local price = net.ReadUInt(32) or 0
|
||||
local mode = net.ReadString() or "month"
|
||||
|
||||
if productID == "" then return end
|
||||
|
||||
if PLUGIN:IsDonateOnCooldown(client) then
|
||||
PLUGIN:SendDonateResult(client, false, "Слишком частые запросы", productID)
|
||||
return
|
||||
end
|
||||
|
||||
PLUGIN:ArmDonateCooldown(client)
|
||||
local success, message, entry = PLUGIN:HandleDonatePurchase(client, productID, price, mode)
|
||||
|
||||
local entryID = entry and entry.id or productID
|
||||
if success then
|
||||
local priceText = tostring(price)
|
||||
local modeText = mode == "forever" and " (навсегда)" or " (на месяц)"
|
||||
print(string.format("[F4 Donate] %s (%s) купил %s%s за %s", client:Name(), client:SteamID(), entryID, modeText, priceText))
|
||||
else
|
||||
print(string.format("[F4 Donate] Ошибка покупки %s игроком %s: %s", entryID, client:Name(), tostring(message)))
|
||||
end
|
||||
|
||||
PLUGIN:SendDonateResult(client, success, message, entryID)
|
||||
end)
|
||||
-- Admin command to add IGS funds
|
||||
ix.command.Add("GiveIGS", {
|
||||
description = "Выдать IGS средства игроку",
|
||||
CanRun = function(self, client)
|
||||
local userGroup = string.lower(client:GetUserGroup() or "user")
|
||||
return client:IsAdmin() or AdminPrivs[userGroup]
|
||||
end,
|
||||
arguments = {
|
||||
ix.type.player,
|
||||
ix.type.number
|
||||
},
|
||||
OnRun = function(self, client, target, amount)
|
||||
if not IsValid(target) then
|
||||
return "@invalidTarget"
|
||||
end
|
||||
|
||||
amount = math.floor(tonumber(amount) or 0)
|
||||
if amount == 0 then
|
||||
return "Укажите корректную сумму"
|
||||
end
|
||||
|
||||
local success, err = PLUGIN:AdjustIGSBalance(target, amount)
|
||||
if success then
|
||||
local action = amount > 0 and "выдал" or "снял"
|
||||
client:Notify(string.format("Вы %s %d IGS для %s", action, math.abs(amount), target:Name()))
|
||||
target:Notify(string.format("Администратор %s вам %d IGS", action == "выдал" and "выдал" or "снял у вас", math.abs(amount)))
|
||||
|
||||
print(string.format("[IGS Admin] %s (%s) %s %d IGS для %s (%s)",
|
||||
client:Name(), client:SteamID(), action, math.abs(amount), target:Name(), target:SteamID()))
|
||||
return ""
|
||||
else
|
||||
return err or "Ошибка при изменении баланса"
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- Admin command to check IGS balance
|
||||
ix.command.Add("CheckIGS", {
|
||||
description = "Проверить IGS баланс игрока",
|
||||
CanRun = function(self, client)
|
||||
local userGroup = string.lower(client:GetUserGroup() or "user")
|
||||
return client:IsAdmin() or AdminPrivs[userGroup]
|
||||
end,
|
||||
arguments = {
|
||||
ix.type.player
|
||||
},
|
||||
OnRun = function(self, client, target)
|
||||
if not IsValid(target) then
|
||||
return "@invalidTarget"
|
||||
end
|
||||
|
||||
local balance = PLUGIN:GetIGSBalance(target)
|
||||
return string.format("Баланс IGS игрока %s: %d руб.", target:Name(), balance)
|
||||
end
|
||||
})
|
||||
|
||||
net.Receive("ixChangeName", function(len, client)
|
||||
if not IsValid(client) then return end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
if not character then return end
|
||||
|
||||
local newName = net.ReadString()
|
||||
if not newName or newName == "" then return end
|
||||
|
||||
if #newName < 3 or #newName > 50 then
|
||||
client:Notify("Имя должно содержать от 3 до 50 символов")
|
||||
return
|
||||
end
|
||||
|
||||
if newName:find("[<>\"\\/]") then
|
||||
client:Notify("Имя содержит недопустимые символы")
|
||||
return
|
||||
end
|
||||
|
||||
local oldName = character:GetName()
|
||||
character:SetName(newName)
|
||||
client:Notify("Ваше имя успешно изменено на: " .. newName)
|
||||
|
||||
net.Start("ixF4UpdateName")
|
||||
net.WriteString(newName)
|
||||
net.Send(client)
|
||||
|
||||
hook.Run("OnCharacterVarChanged", character, "name", oldName, newName)
|
||||
end)
|
||||
|
||||
-- Фикс выдачи донат-оружия IGS в Helix
|
||||
hook.Add("PostPlayerLoadout", "IGS_Helix_WeaponLoadoutFix", function(client)
|
||||
if not IsValid(client) or not IGS then return end
|
||||
|
||||
timer.Simple(1.5, function()
|
||||
if not IsValid(client) or not client:GetCharacter() then return end
|
||||
|
||||
if isfunction(IGS.PlayerLoadout) then
|
||||
IGS.PlayerLoadout(client)
|
||||
end
|
||||
|
||||
if isfunction(IGS.GetItems) and IsValid(client) and client.HasPurchase then
|
||||
for _, ITEM in pairs(IGS.GetItems()) do
|
||||
if not ITEM or not isfunction(ITEM.GetUID) then continue end
|
||||
|
||||
local weaponClass = (isfunction(ITEM.GetWeapon) and ITEM:GetWeapon()) or ITEM.weapon
|
||||
if weaponClass and client:HasPurchase(ITEM:GetUID()) then
|
||||
if not client:HasWeapon(weaponClass) then
|
||||
client:Give(weaponClass)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user