local PLUGIN = PLUGIN util.AddNetworkString("ixAdminShopOpen") util.AddNetworkString("ixAdminShopBuy") util.AddNetworkString("ixAdminShopRetrieve") util.AddNetworkString("ixAdminShopAdminSync") util.AddNetworkString("ixAdminShopAdminAction") util.AddNetworkString("ixAdminShopPanelOpen") util.AddNetworkString("ixAdminShopPanelData") util.AddNetworkString("ixAdminShopPanelGivePoints") util.AddNetworkString("ixAdminShopPanelTakePoints") local adminRanks = { ["super admin"] = true, ["superadmin"] = true, ["projectteam"] = true, ["teh.admin"] = true, ["curator"] = true, ["sudo-curator"] = true, ["asist-sudo"] = true, ["admin"] = true, ["st.admin"] = true, ["ivent"] = true, ["st.event"] = true, ["event"] = true, ["disp"] = true, ["assistant"] = true, ["prem"] = true, ["dsmoder"] = true } local function IsAdminRank(rank) if not rank or rank == "user" then return false end local lowerRank = string.lower(rank) -- Check exact match in the provided list if adminRanks[lowerRank] then return true end -- Keep generic string searches just in case if lowerRank == "founder" or lowerRank == "owner" or lowerRank == "manager" then return true end return false end PLUGIN.IsAdminRank = IsAdminRank function PLUGIN:Initialize() self.shopData = ix.data.Get("adminShop", {}) end function PLUGIN:SaveShopData() ix.data.Set("adminShop", self.shopData) end function PLUGIN:PlayerLoaded(client) local steamID = client:SteamID() self.shopData[steamID] = self.shopData[steamID] or {points = 0, inventory = {}} client:SetNetVar("adminPoints", self.shopData[steamID].points) client:SetNetVar("adminInventory", self.shopData[steamID].inventory) end local playerMeta = debug.getregistry().Player function playerMeta:SetAdminPoints(amount) amount = math.max(0, amount) self:SetNetVar("adminPoints", amount) local steamID = self:SteamID() PLUGIN.shopData[steamID] = PLUGIN.shopData[steamID] or {points = 0, inventory = {}} PLUGIN.shopData[steamID].points = amount PLUGIN:SaveShopData() end function playerMeta:GiveAdminPoints(amount) self:SetAdminPoints(self:GetAdminPoints() + amount) end function playerMeta:TakeAdminPoints(amount) self:SetAdminPoints(self:GetAdminPoints() - amount) end function playerMeta:SetAdminInventory(data) self:SetNetVar("adminInventory", data) local steamID = self:SteamID() PLUGIN.shopData[steamID] = PLUGIN.shopData[steamID] or {points = 0, inventory = {}} PLUGIN.shopData[steamID].inventory = data PLUGIN:SaveShopData() end ix.command.Add("AdminShop", { description = "Открыть магазин администратора.", OnRun = function(self, client) if (!client:IsAdmin() and !client:IsSuperAdmin() and !IsAdminRank(client:GetUserGroup())) then client:Notify("Эта команда доступна только администраторам.") return end net.Start("ixAdminShopOpen") net.Send(client) end }) net.Receive("ixAdminShopBuy", function(len, client) local itemID = net.ReadString() local item = PLUGIN.Items[itemID] if (!item) then return end local points = client:GetAdminPoints() if (points < item.price) then client:Notify("У вас недостаточно очков!") return end if (itemID == "remove_warn") then local warnPlugin = ix.plugin.Get("warn") if (warnPlugin) then local steamID = client:SteamID() local warns = ix.data.Get("warns", {}) local targetData = warns[steamID] if (targetData and targetData.count > 0) then targetData.count = targetData.count - 1 table.insert(targetData.history, { admin = "Admin Shop", adminSteamID = "STEAM_0:0:0", reason = "Покупка в магазине", time = os.time(), type = "remove" }) ix.data.Set("warns", warns) warnPlugin.warns = warns client:TakeAdminPoints(item.price) client:Notify("Вы успешно сняли выговор!") else client:Notify("У вас нет активных выговоров для снятия!") end else client:Notify("Система выговоров не найдена!") end else -- Immediate delivery if class exists if (item.class) then client:GiveItem(item.class) client:TakeAdminPoints(item.price) client:Notify("Вы купили " .. item.name .. ". Предмет выдан!") else -- Fallback to inventory just in case (hidden) local inv = client:GetAdminInventory() local expireTime = 0 if (item.duration) then expireTime = os.time() + (item.duration * 24 * 60 * 60) end table.insert(inv, { id = itemID, buyTime = os.time(), expireTime = expireTime, name = item.name, class = item.class }) client:SetAdminInventory(inv) client:TakeAdminPoints(item.price) client:Notify("Вы купили " .. item.name .. ". Предмет добавлен в инвентарь (скрыто).") end end end) net.Receive("ixAdminShopRetrieve", function(len, client) local index = net.ReadUInt(16) local inv = client:GetAdminInventory() local itemData = inv[index] if (!itemData) then return end if (itemData.expireTime > 0 and os.time() > itemData.expireTime) then client:Notify("Срок действия предмета истек!") table.remove(inv, index) client:SetAdminInventory(inv) return end if (itemData.class) then client:GiveItem(itemData.class) client:Notify("Вы получили: " .. itemData.name) end end) -- Сбор данных игроков с доступом к магазину function PLUGIN:CollectPanelData() local playersData = {} for _, ply in ipairs(player.GetAll()) do local rank = ply:GetUserGroup() if IsAdminRank(rank) then table.insert(playersData, { name = ply:Nick(), steamID = ply:SteamID(), rank = rank, points = ply:GetAdminPoints() }) end end return playersData end -- Открытие панели (только superadmin) net.Receive("ixAdminShopPanelOpen", function(len, client) if not client:IsSuperAdmin() then client:Notify("Доступ к панели только у суперадминистраторов!") return end local data = PLUGIN:CollectPanelData() net.Start("ixAdminShopPanelData") net.WriteTable(data) net.Send(client) end) -- Выдача очков (только superadmin) net.Receive("ixAdminShopPanelGivePoints", function(len, client) if not client:IsSuperAdmin() then client:Notify("Доступ только у суперадминистраторов!") return end local targetSID = net.ReadString() local amount = net.ReadUInt(32) local target = player.GetBySteamID(targetSID) if not IsValid(target) then client:Notify("Игрок не найден на сервере!") return end if amount < 1 then client:Notify("Некорректная сумма!") return end target:GiveAdminPoints(amount) client:Notify("Выдано " .. amount .. " очков игроку " .. target:Nick()) -- Обновить панель local data = PLUGIN:CollectPanelData() net.Start("ixAdminShopPanelData") net.WriteTable(data) net.Send(client) end) -- Забрать очки (только superadmin) net.Receive("ixAdminShopPanelTakePoints", function(len, client) if not client:IsSuperAdmin() then client:Notify("Доступ только у суперадминистраторов!") return end local targetSID = net.ReadString() local amount = net.ReadUInt(32) local target = player.GetBySteamID(targetSID) if not IsValid(target) then client:Notify("Игрок не найден на сервере!") return end if amount < 1 then client:Notify("Некорректная сумма!") return end local current = target:GetAdminPoints() if current < amount then client:Notify("У игрока недостаточно очков! (Текущий баланс: " .. current .. ")") return end target:TakeAdminPoints(amount) client:Notify("Забрано " .. amount .. " очков у игрока " .. target:Nick()) -- Обновить панель local data = PLUGIN:CollectPanelData() net.Start("ixAdminShopPanelData") net.WriteTable(data) net.Send(client) end)