Physgun Wiki

Система смерти

Модуль death/ отвечает за всё, что происходит между гибелью игрока и его возрождением: труп, потеря денег, отсчёт и камера от первого лица на трупе.

Порядок событий

GM:DoPlayerDeath в sv_player.lua вызывает roleplay.Death.Handle(ply), который делает четыре вещи по порядку: создаёт реглолл через ply:CreateRagdoll(), если его ещё нет; пишет время возрождения в сетевую переменную respawn_at; списывает деньги через ply:DropDeathMoney(); сбрасывает профессию через ply:DemoteOnDeath(), если у неё есть нужный флаг.

Порядок последних двух шагов важен. Деньги списываются до смены профессии, иначе разрешающий хук спросит уже гражданского, а не ту работу, на которой игрок погиб.

Потеря денег

Списывается DeathMoneyPercent от кошелька с потолком DeathMoneyMax, деньги падают сущностью money на месте гибели и достаются любому, кто подберёт.

Профессия может вмешаться своими методами:

function JOB:CanDropDeathMoney(amount) return true, math.floor(amount * 0.5) end

Возврат false отменяет потерю, второе значение задаёт свою сумму. Как и везде, отсутствие return означает «не вмешиваюсь».

Возрождение

Базовый геймод возрождает игрока сам, по атаке или прыжку. Это поведение выключено пустым переопределением:

function GM:PlayerDeathThink(ply) end

Функция выглядит мёртвым кодом, но именно она держит всю систему: если её удалить, базовый геймод начнёт возрождать игроков мимо отсчёта.

Само возрождение идёт из GM:PlayerButtonDown — по любой клавише в диапазоне KEY_NONE..KEY_LAST, то есть с клавиатуры, без кнопок мыши.

function roleplay.Death.TryRespawn(ply) if (ply:Alive()) then return end if (CurTime() < ply:GetNetVar('respawn_at', 0)) then return end ... ply:Spawn() end

Функция сама проверяет и состояние игрока, и отсчёт, поэтому дёргать её можно свободно. Реглолл удаляется в момент возрождения.

Камера на трупе

Камера цепляется за аттачмент eyes, а не за кость — у аттачмента сразу есть и позиция, и угол:

local attachment = ragdoll:GetAttachment(ragdoll:LookupAttachment('eyes'))

Кость, в имени которой есть head, схлопывается в нулевой масштаб. Без этого камера стоит внутри головы и в кадр попадают её полигоны изнутри. Делается это один раз, после InvalidateBoneCache() и SetupBones().

Таблица вида объявлена на уровне файла и переиспользуется: CalcView выполняется каждый кадр, создавать в нём таблицу нельзя.

Приём взят из модуля deathpov оригинального DarkRP.

Флаг потери профессии

JOB_FLAG_DEMOTE_ON_DEATH сбрасывает работу на дефолтную:

JOB.Flags = { JOB_FLAG_DEMOTE_ON_DEATH }

Класс при этом ставится напрямую через player_manager.SetPlayerClass, а не через PLAYER:SetJob. Последний внутри вызывает Spawn() и возродил бы игрока мгновенно, мимо отсчёта.

Настройки

Ключ Config.Defaults Значение Смысл
RespawnDelay 10 секунд до возможности возродиться
DeathMoneyPercent 0.3 доля кошелька, которая выпадает
DeathMoneyMax 10000 потолок потери за одну смерть

HUD

Отсчёт рисует roleplay.Death.Draw(), вызываемая из GM:HUDPaint. Вывод намеренно отладочный, шрифтом DebugOverlay, как и основной HUD — это заглушка до нормального интерфейса.