104 lines
3.4 KiB
Lua
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)
|