local PLUGIN = PLUGIN PLUGIN.name = "Spawns" PLUGIN.description = "Spawn points for factions and classes." PLUGIN.author = "Chessnut" PLUGIN.spawns = PLUGIN.spawns or {} local function IsSpawnPointClear(pos) local mins = Vector(-16, -16, 0) local maxs = Vector(16, 16, 72) for _, ply in ipairs(player.GetAll()) do if ply:Alive() and ply:GetPos():Distance(pos) < 50 then return false end end local ents = ents.FindInBox(pos + mins, pos + maxs) for _, ent in ipairs(ents) do if IsValid(ent) and not ent:IsPlayer() and ent:GetSolid() ~= SOLID_NONE then return false end end return true end function PLUGIN:PlayerLoadout(client) local character = client:GetCharacter() if (self.spawns and !table.IsEmpty(self.spawns) and character) then local class = character:GetClass() local points local className = "default" for k, v in ipairs(ix.faction.indices) do if (k == client:Team()) then points = self.spawns[v.uniqueID] or {} break end end if (points) then local factionTable = ix.faction.indices[client:Team()] local podr = character:GetPodr() if (podr and factionTable and factionTable.Podr and factionTable.Podr[podr]) then className = factionTable.Podr[podr].name:lower() else for _, v in ipairs(ix.class.list) do if (class == v.index) then className = v.uniqueID break end end end points = points[className] or points["default"] if (points and !table.IsEmpty(points)) then local tries = 0 local position repeat position = table.Random(points) tries = tries + 1 until IsSpawnPointClear(position) or tries > 10 client:SetPos(position) end end end end function PLUGIN:LoadData() self.spawns = self:GetData() or {} end function PLUGIN:SaveSpawns() self:SetData(self.spawns) end ix.command.Add("SpawnAdd", { description = "@cmdSpawnAdd", privilege = "Manage Spawn Points", adminOnly = true, arguments = { ix.type.string, bit.bor(ix.type.text, ix.type.optional) }, OnRun = function(self, client, name, class) local full = (name .. " " .. (class or "")):Trim() local words = string.Explode(" ", full) local info, info2, faction, className -- Перебираем возможные разбиения строки на фракцию и класс for i = 1, #words do local fName = table.concat(words, " ", 1, i) local cName = table.concat(words, " ", i + 1) for _, v in ipairs(ix.faction.indices) do -- Проверяем совпадение фракции if (ix.util.StringMatches(v.uniqueID, fName) or ix.util.StringMatches(L(v.name, client), fName)) then local potentialInfo = v local potentialFaction = v.uniqueID local potentialClassName, potentialInfo2 if (cName == "") then potentialClassName = "default" else -- Ищем класс for _, c in ipairs(ix.class.list) do if (c.faction == v.index and (c.uniqueID:lower() == cName:lower() or ix.util.StringMatches(L(c.name, client), cName))) then potentialInfo2 = c potentialClassName = c.uniqueID break end end -- Ищем подразделение (Podr) if (!potentialClassName and v.Podr) then for _, p in pairs(v.Podr) do local pName = p.name:lower() local qName = cName:lower() -- Сравнение с запасом на окончания (по первым 4-5 символам) или по вхождению if (ix.util.StringMatches(pName, qName) or ix.util.StringMatches(qName, pName) or pName:find(qName, 1, true) or qName:find(pName, 1, true) or (pName:sub(1, 8) == qName:sub(1, 8))) then -- 8 байт = ~4 русских символа potentialInfo2 = p potentialClassName = p.name:lower() break end end end end if (potentialClassName) then info = potentialInfo faction = potentialFaction className = potentialClassName info2 = potentialInfo2 break end end end if (className) then break end end if (info) then if (!className) then return "@invalidClass" end PLUGIN.spawns[faction] = PLUGIN.spawns[faction] or {} PLUGIN.spawns[faction][className] = PLUGIN.spawns[faction][className] or {} table.insert(PLUGIN.spawns[faction][className], client:GetPos()) PLUGIN:SaveSpawns() local logName = L(info.name, client) if (info2) then logName = logName .. " (" .. L(info2.name, client) .. ")" end return "@spawnAdded", logName else return "@invalidFaction" end end }) ix.command.Add("SpawnRemove", { description = "@cmdSpawnRemove", privilege = "Manage Spawn Points", adminOnly = true, arguments = bit.bor(ix.type.number, ix.type.optional), OnRun = function(self, client, radius) radius = radius or 120 local position = client:GetPos() local i = 0 for _, v in pairs(PLUGIN.spawns) do for _, v2 in pairs(v) do for k3, v3 in pairs(v2) do if (v3:Distance(position) <= radius) then v2[k3] = nil i = i + 1 end end end end if (i > 0) then PLUGIN:SaveSpawns() end return "@spawnDeleted", i end })