В прошлом уроке вы научились основам создания аддона,теперь я научу вас созданию полноценного мода. Аддон-пример будет называться - "SandBox Player Classes" классы для игрока как в Team Fortress 2. Делаем все как в прошлом уроке - создадим папки и файлы. Итак в папке server мы создадим lua файлик. Теперь,собственно,приступим к кодингу. Впишем в lua файл: function SelectPlayerClasses( ply ) // Создадим новую функцию,которую будет использовать хук."ply" - Это игрок который подключился к игре. if engine.ActiveGamemode()=="sandbox" then // Создадим условие,чтобы этот мод работал только в игровом режиме "SandBox". local mathx = math.random(1,11) // Создадим локальную переменную которая будет с помощью кода "math.random" случайно выбирать классы. // Чтобы добавить еще классы вам нужно вместо 11 в math.random,вписать следующие числа. if mathx == 1 then // Всего у нас будет 11 классов.При желании вы можете добавить ещё,нужно только добавить следующие числа. ply:SetNWInt("ClassType",1) elseif mathx == 2 then ply:SetNWInt("ClassType",2) elseif mathx == 3 then ply:SetNWInt("ClassType",3) elseif mathx == 4 then ply:SetNWInt("ClassType",4) elseif mathx == 5 then ply:SetNWInt("ClassType",5) elseif mathx == 6 then ply:SetNWInt("ClassType",6) elseif mathx == 7 then ply:SetNWInt("ClassType",7) elseif mathx == 8 then ply:SetNWInt("ClassType",8) elseif mathx == 9 then ply:SetNWInt("ClassType",9) elseif mathx == 10 then ply:SetNWInt("ClassType",10) elseif mathx == 11 then ply:SetNWInt("ClassType",11) // Чтобы добавить больше классов,вам нужно вписать новое условие.Пример(Уберите кавычки если хотите добавить класс.): // elseif mathx == 12 then // ply:SetNWInt("ClassType",12) end timer.Simple(14,function() // Создадим таймер который через 14 секунд после подключения игрока,выведет текст в чате. if IsValid(ply) then // Условие для проверки существования игрока.Чтобы не вызывало ошибок. ply:PrintMessage(HUD_PRINTTALK,"Приветствуем " .. ply:Nick() .. "! \nВаш класс:" .. ply:GetNWString("ClassName")) // Сообщение выводимое игроку через 14 секунд. // Текст нужно вписать в кавычках,ply:Nick() - это ник игрока,ply:GetNWString("ClassName") -это название класса игрока. // Чтобы в текст вписать значения из какого-нибудь кода,вам нужно закрыть текст кавычкой и затем вписать .. затем название кода. end end) // Функция закрытия таймера.Обязательно после end вписать скобку. end end hook.Add( "PlayerInitialSpawn", "SelectPlayerClassesUniqueid", SelectPlayerClasses ) // Хук с событием "PlayerInitialSpawn" когда игрок подключается к серверу.
Далее мы будем давать класс игроку после его возрождения:
function SetPlayerClass( ply ) if engine.ActiveGamemode()=="sandbox" then timer.Simple(0.02,function() // Движок не сразу выдает оружие игроку.Поэтому нам нужно сделать таймер который активирует наш код через 0.02 секунд. if IsValid(ply) then local classtype = ply:GetNWInt("ClassType") // Находим класс игрока.Номер класса игрока мы выдали когда игрок подключился,в верхней функции. ply:RemoveAllItems() // Удаляем все оружие и патроны игрока. local name // Создадим локальную переменную которой присвоим название класса.Название класса будет выдаваться в функции класса. if classtype == 1 then name = Class.Gordon(ply) elseif classtype == 2 then name = Class.Healer(ply) elseif classtype == 3 then name = Class.Berserker(ply) elseif classtype == 4 then name = Class.Metropolice(ply) elseif classtype == 5 then name = Class.Soldier(ply) elseif classtype == 6 then name = Class.Elite(ply) elseif classtype == 7 then name = Class.Shotgunner(ply) elseif classtype == 8 then name = Class.Cowboy(ply) elseif classtype == 9 then name = Class.Demoman(ply) elseif classtype == 10 then name = Class.Rebel(ply) elseif classtype == 11 then name = Class.Trooper(ply) // Всего 11 классов по методу описанному выше,вы можете добавить еще.Надо вписать функцию класса. end ply:SetNWString("ClassName",tostring(name)) // Впишем сюда название класса.Этот код мы использовали в функции выше,где мы выводим текст. ply:PrintMessage(HUD_PRINTTALK,"Ваш класс:" .. tostring(name)) // Выводим название класса игроку после его возрождения. // tostring(name) - без него будут ошибки.Иногда переменная name будет выдаваться не в формате текста,поэтому нам нужен этот код. end end) end end hook.Add( "PlayerSpawn", "SetPlayerClassUniqueid", SetPlayerClass ) // Хук с событием "PlayerSpawn" когда игрок возрождается.
Теперь приступим к созданию самих классов:
Class = {} // Создадим таблицу Class для наглядности.
function Arsenal(ply,wep) // Создадим функцию которую будем использовать для выдачи оружия классу.ply - игрок которому выдаем оружие.wep - название оружия. ply:Give(wep) // Вот сам код выдачи оружия. end
function Ammunition(ply,num,item) // Функция для выдачи патронов игроку.num - количество патрон.item - название патрон. ply:GiveAmmo(num,item,true) end
function Class.Gordon(ply) // Теперь создадим первый класс. // И первым нашим классом будет Фриман. local name = "Гордон Фриман" // Название класса,вписать в кавычках. Arsenal(ply,"weapon_crowbar") // Вызываем функцию выдачи оружия которую мы написали выше.Название оружие вписать в кавычках. Arsenal(ply,"weapon_physcannon") Arsenal(ply,"weapon_bugbait") Arsenal(ply,"item_battery") // Это понадобиться нам для брони. Arsenal(ply,"item_battery") return name // Это нам нужно для вывода названия класса игроку. end
function Class.Healer(ply) local name = "Доктор" Arsenal(ply,"weapon_crowbar") Arsenal(ply,"weapon_pistol") Arsenal(ply,"weapon_medkit") Ammunition(ply, 40, "Pistol") // Вызываем функцию выдачи патрон.Количество вписать без кавычек.Название патрон с кавычками. return name end
function Class.Berserker(ply) local name = "Боец" Arsenal(ply,"weapon_fists") Arsenal(ply,"weapon_crowbar") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") ply:SetWalkSpeed(ply:GetWalkSpeed() + 200) // Увеличим скорость ходьбы игроку.К начальной скорости добавим 200 единиц. ply:SetRunSpeed(ply:GetWalkSpeed() + 450) // Увеличим скорость бега игроку. return name end
function Class.Metropolice(ply) local name = "Полицейский" Arsenal(ply,"weapon_stunstick") Arsenal(ply,"weapon_pistol") Arsenal(ply,"item_battery") Ammunition(ply, 100, "Pistol") // Вы также сможете указать свою модель игрока для класса.Для этого впишите в функцию класса - ply:SetModel("models/player/police.mdl") в кавычках название модели. return name end
function Class.Soldier(ply) local name = "Солдат" Arsenal(ply,"weapon_smg1") Arsenal(ply,"weapon_frag") Arsenal(ply,"weapon_frag") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Ammunition(ply, 200, "SMG1") return name end
function Class.Elite(ply) local name = "Спецназ" Arsenal(ply,"weapon_ar2") Arsenal(ply,"weapon_frag") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Ammunition(ply, 200, "AR2") Ammunition(ply, 1, "AR2AltFire") return name end
function Class.Shotgunner(ply) local name = "Охотник" Arsenal(ply,"weapon_shotgun") Arsenal(ply,"weapon_frag") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") Ammunition(ply, 40, "Buckshot") return name end
function Class.Cowboy(ply) local name = "Ковбой" Arsenal(ply,"weapon_pistol") Arsenal(ply,"weapon_357") Ammunition(ply, 60, "Pistol") Ammunition(ply, 16, "357") return name end
function Class.Demoman(ply) local name = "Подрывник" Arsenal(ply,"weapon_frag") Arsenal(ply,"weapon_slam") Arsenal(ply,"weapon_slam") Arsenal(ply,"weapon_rpg") Ammunition(ply, 2, "RPG_Round") Ammunition(ply, 2, "Grenade") return name end
function Class.Rebel(ply) local name = "Повстанец" Arsenal(ply,"weapon_crossbow") Arsenal(ply,"weapon_crowbar") Ammunition(ply, 10, "XBowBolt") return name end
function Class.Trooper(ply) local name = "Кавалерист" Arsenal(ply,"flechette_gun") Arsenal(ply,"item_battery") Arsenal(ply,"item_battery") return name end
Ну вот мы создали все 11 классов. Теперь перейдем к консольным командам. Создадим команду перевыбора классов для всех игроков,и которую будет вызывать только админ. Команда будет называться - pc_repick_classes.
function Repick(ply) // ply - игрок который использовал консольную команду. if engine.ActiveGamemode()=="sandbox" then if ply:IsAdmin() then // Проверяем игрока на права админа. for k,v in pairs(player.GetAll()) do // Находим всех игроков и перевыбираем им классы.Используем цикл.Где v - это все игроки на сервере. if IsValid(v) then local mathp = math.random(1,11) if mathp == 1 then ply:SetNWInt("ClassType",1) elseif mathp == 2 then ply:SetNWInt("ClassType",2) elseif mathp == 3 then ply:SetNWInt("ClassType",3) elseif mathp == 4 then ply:SetNWInt("ClassType",4) elseif mathp == 5 then ply:SetNWInt("ClassType",5) elseif mathp == 6 then ply:SetNWInt("ClassType",6) elseif mathp == 7 then ply:SetNWInt("ClassType",7) elseif mathp == 8 then ply:SetNWInt("ClassType",8) elseif mathp == 9 then ply:SetNWInt("ClassType",9) elseif mathp == 10 then ply:SetNWInt("ClassType",10) elseif mathp == 11 then ply:SetNWInt("ClassType",11) end v:PrintMessage(HUD_PRINTTALK, "Все классы были перевыбраны.Возродитесь чтобы применить свой класс.") // Выводим текст всем игрокам. end end ply:PrintMessage(HUD_PRINTTALK, "[Админ]Классы успешно перевыбраны!") // Выводим текст админу который ввел команду. else ply:PrintMessage(HUD_PRINTTALK, "Доступ запрещен!") // Выводим текст игроку без доступа админа. end end end concommand.Add( "pc_repick_classes", Repick, nil, nil) // Функция создания консольной команды.В кавычках вписать название команды.Затем название функции.
Теперь создадим команду для админа,которая сможет выбирать определенные классы для определенного игрока. Примерное использование команды такое - pc_class_set Hds46 2.Где Hds46 - название игрока.Где 2 - название номера класса.
function SetClassForPlayer(ply,cmd,arg,argstr) // cmd - название команды.arg - название введенных значений.argstr - название значений в форме текста. if engine.ActiveGamemode()=="sandbox" then if ply:IsAdmin() then if arg[1] != nil then // Проверяем значение ника игрока на пустоту. if arg[2] != nil then // Проверяем значение номера класса на пустоту. for k,v in pairs(player.GetAll()) do if IsValid(v) then if arg[1] == v:Nick() then // Проверка на значение ника игрока.Если такой игрок есть функция идет дальше. if IsValid(v) then if (arg[2] == "1" or arg[2] == "2" or arg[2] == "3" or arg[2] == "4" or arg[2] == "5" or arg[2] == "6" or arg[2] == "7" or arg[2] == "8" or arg[2] == "9" or arg[2] == "10" or arg[2] == "11") then // Проверка на номера классов.У нас ведь всего одиннадцать классов. v:SetNWInt("ClassType",tonumber(arg[2])) // Выдадим игроку определенный класс.tonumber(arg[2]) - выводим текст в номер. // Сообщение игроку получившего класс. v:PrintMessage(HUD_PRINTTALK,"[Админ]" .. ply:Nick() .. " поменял вам класс. \nВозродитесь чтобы получить его.") ply:PrintMessage(HUD_PRINTTALK,"[Админ]Вы успешно поменяли класс игроку " .. v:Nick() .. "!") // Вывод текста игроку который ввел команду. else ply:PrintMessage(HUD_PRINTTALK,"Номер класса не существует.") // Если номер класса определенный сверху нет,то выводим текст игроку. end end end end end else ply:PrintMessage(HUD_PRINTTALK,"Нужно ввести номер класса.") // Если игрок не ввел номер класса. end else ply:PrintMessage(HUD_PRINTTALK,"Нужно ввести имя игрока.") // Если игрок не ввел ник игрока. end else ply:PrintMessage(HUD_PRINTTALK,"Доступ запрещен!") // Если игрок не админ. end end end concommand.Add( "pc_class_set", SetClassForPlayer, nil, nil)
Ну вот.Вроде бы все,есть классы,консольные команды. Но игроки спавнят оружие через спавн меню. Тогда в папке autorun создадим папку client и там создадим lua файл. В файле прописываем это.
local function DisallowSpawnMenu( ) if not LocalPlayer():IsAdmin() then return false end end
Если игрок не админ,то он не может открыть спавнменю.
Чистый код можно скачать здесь. Этот мод хорошо подходит для deathmatch'а и coop'а. При наличии идей вы сможете создать много разнообразных классов. Не забудьте преобразовать весь код в Utf-8(Без BOM) иначе русский текст не будет отображаться.