Files
garrysmod-coop/gamemode/chargersystem.lua
T
2026-09-06 16:36:58 +02:00

104 lines
3.4 KiB
Lua

local healthRechargeTime = CreateConVar(
"gc_healthchargerrechargetime",
"60",
FCVAR_ARCHIVE,
"Seconds before an emptied wall health charger refills; 0 disables automatic refills"
)
local suitRechargeTime = CreateConVar(
"gc_suitchargerrechargetime",
"30",
FCVAR_ARCHIVE,
"Seconds before an emptied wall suit charger refills; 0 disables automatic refills"
)
local chargerClasses = {
item_healthcharger = healthRechargeTime,
item_suitcharger = suitRechargeTime
}
local chargerStates = {}
local function GetChargerJuice(charger)
local juice = charger:GetInternalVariable("m_iJuice")
return tonumber(juice)
end
local function GetChargerCapacity(charger, juice)
local maxJuice = charger:GetInternalVariable("m_iMaxJuice")
local displayedJuice = charger:GetInternalVariable("m_flJuice")
return math.max(
juice or 0,
tonumber(maxJuice) or 0,
tonumber(displayedJuice) or 0
)
end
local function RefillCharger(charger, state)
charger:Fire("Recharge")
-- GMod's suit charger implements Recharge, but item_healthcharger does not
-- on all engine branches. Give the native input a frame to run, then use
-- its internal Source charge fields as a compatibility fallback.
timer.Simple(0.1, function()
if not IsValid(charger) or (GetChargerJuice(charger) or 0) > 0 then return end
if not state.capacity or state.capacity <= 0 then return end
charger:SetSaveValue("m_iJuice", state.capacity)
if charger:GetInternalVariable("m_flJuice") ~= nil then
charger:SetSaveValue("m_flJuice", state.capacity)
end
charger:SetCycle(0)
charger:EmitSound("items/medshot4.wav", 60, 100, 0.5)
end)
end
timer.Create("CustomCoopRechargeWallChargers", 1, 0, function()
local now = CurTime()
local seen = {}
for className, rechargeTime in pairs(chargerClasses) do
local delay = math.max(rechargeTime:GetFloat(), 0)
for _, charger in ipairs(ents.FindByClass(className)) do
seen[charger] = true
local juice = GetChargerJuice(charger)
if juice == nil then continue end
local state = chargerStates[charger]
if not state then
-- A mapper may deliberately place a charger with zero charge.
-- Only chargers observed being drained during play are refilled.
state = {
lastJuice = juice,
capacity = GetChargerCapacity(charger, juice)
}
chargerStates[charger] = state
elseif juice > 0 or delay == 0 then
state.refillAt = nil
elseif state.lastJuice > 0 and juice <= 0 then
state.refillAt = now + delay
elseif state.refillAt and now >= state.refillAt then
-- Use the native Source input rather than replacing the entity,
-- preserving its name, Hammer I/O, animation and sounds.
RefillCharger(charger, state)
state.refillAt = nil
end
state.lastJuice = juice
end
end
for charger in pairs(chargerStates) do
if not seen[charger] or not IsValid(charger) then
chargerStates[charger] = nil
end
end
end)
hook.Add("PostCleanupMap", "CustomCoopResetWallChargerTracking", function()
chargerStates = {}
end)