Как добавить профессию
Профессии не регистрируются кодом напрямую: sh_registrator.lua при старте сканирует папку jobs/ и сам вызывает player_manager.RegisterPlayerClass для каждого найденного файла. Чтобы добавить профессию, достаточно создать один файл.
1. Файл профессии
gamemodes/darkrp/jobs/police.lua. ID профессии берётся из имени файла (police), сам файл выполняется через include с глобальной таблицей JOB, а не return:
JOB.Team обязателен и должен быть объявлен раньше в teams.lua. JOB.Model — таблица моделей, rp_player:SetModel выберет случайную при спавне.
Team, Model, MaxPlayers, Salary, DisplayName, Color, Flags и SWEPs реально применяются (см. таблицу ниже). Description, MaxHealth, StartHealth, StartArmor пока только хранятся на классе: rp_player:Spawn() не вызывает SetMaxHealth/SetHealth/SetArmor.
2. Выдаваемое оружие
JOB.SWEPs выдаётся при спавне в rp_player:Loadout вместе со стандартным набором (Default_SWEPs: физпушка, тулган, ключи):
GM:PlayerLoadout перед этим полностью снимает оружие и патроны (StripWeapons/RemoveAllAmmo), так что предыдущий набор не накапливается при респавне или смене профессии.
3. Флаги
JOB.Flags — массив констант из sh_jobs.lua:
| Флаг | Значение | Где используется |
|---|---|---|
JOB_FLAG_CANT_BUY_DOOR |
4 | OnPlayerBuyDoor и OnPlayerAddDoorOwner: нельзя покупать двери и становиться совладельцем. |
JOB_FLAG_NEED_VOTE |
2 | Команда /become (sv_jobs.lua): устройство на профессию проходит через голосование сервера. |
JOB_FLAG_UNDISMISSABLE |
1 | Команда /demote: с такой профессии нельзя уволить. |
JOB_FLAG_NONRP |
3 | Объявлен, но пока нигде не читается. |
JOB_FLAG_DEMOTE_ON_DEATH |
5 | PLAYER:DemoteOnDeath: после смерти профессия сбрасывается на дефолтную. |
4. Переопределение поведения геймода
Базовый класс rp_player (sh_jobs.lua) объявляет пустые методы-перехватчики, которые дёргает player_manager.RunClass из соответствующих GM-хуков до дефолтной логики геймода: CanBuyDoor/OnBoughtDoor, CanSellDoor/OnSoldDoor, OnRenamedDoor, CanAddDoorOwner/OnAddedDoorOwner, OnRemovedDoorOwner, CanOpenDoor, OnLeftDoor, CanDropMoney/OnDroppedMoney, CanDropDeathMoney/OnDroppedDeathMoney, CanTransferMoney/OnTransferedMoney, CheckBuildLimit, OnSpawnedProp, OnSalary, CanJoin, OnJoined. Профессия может переопределить любой из них прямо в своём файле:
Если метод вернул не-nil, это решение побеждает; вернул nil (или не определён) — используется дефолт геймода. Полный список хуков и их дефолтов — в разделах справочника «Двери», «Экономика» и «Профессии» в боковом меню.
5. Смена профессии игроком
Игрок меняет профессию командой /become <id> (sv_jobs.lua), которая ищет id среди player_manager.GetPlayerClasses(). Если у профессии флаг JOB_FLAG_NEED_VOTE — сервер голосует 20 секунд (Config.Defaults.JobVoteSeconds), иначе смена происходит сразу через PLAYER:SetJob. Между сменами действует кулдаун Config.Defaults.NextJobChange.
Уволить другого игрока может команда /demote <id> <причина> — тоже через голосование (Config.Defaults.DemoteVoteSeconds), недоступна для профессий с JOB_FLAG_UNDISMISSABLE и требует минимум Config.Defaults.MinPlayersToDemote игроков на сервере.
6. Двери для профессии
Привязка двери к профессии по её ID, один раз при настройке карты, через SetDoorJob:
Игроки профессии police получат доступ к замку двери через CanBeOpenedBy без покупки: двери с назначенной профессией нельзя купить (см. PLAYER:BuyDoor).
