Files
wnsrc/gamemodes/helix/plugins/medical/sv_plugin.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

351 lines
12 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
local IsValid = IsValid
local ix = ix
local math = math
util.AddNetworkString("ixHealingData")
ix.log.AddType("medicalBleedoutKO", function(client)
return string.format("%s a été assommé et saigne abondamment.", client:GetName())
end, FLAG_DANGER)
ix.log.AddType("medicalBleedoutKilled", function(client)
return string.format("%s est mort alors qu'il saignait abondamment.", client:GetName())
end, FLAG_DANGER)
ix.log.AddType("medicalBleedoutStop", function(client)
return string.format("%s n'est plus inconscient en raison de blessures critiques.", client:GetName())
end)
ix.log.AddType("medicalBleedout", function(client)
return string.format("%s a saigné jusqu'à en mourir.", client:GetName())
end, FLAG_DANGER)
ix.log.AddType("medicalFullyHealed", function(client)
return string.format("%s est complètement guéri.", client:GetName())
end)
ix.log.AddType("medicalPainkillersNoHP", function(client)
return string.format("%s n'a plus de points de vie.", client:GetName())
end, FLAG_DANGER)
ix.log.AddType("medicalPainkillersTooMany", function(client)
return string.format("%s a pris trop d'analgésiques.", client:GetName())
end, FLAG_DANGER)
ix.log.AddType("medicalBleedoutStoppedBy", function(client, givenBy)
return string.format("%s a arrêté l'hémorragie de %s.", givenBy:GetPlayer():Name(), client:Name())
end)
ix.log.AddType("medicalBandagedBy", function(client, givenBy, amount)
return string.format("%s a été bandé par %s pour %d points de vie.", client:Name(), givenBy:GetPlayer():Name(), amount)
end)
ix.log.AddType("medicalDisinfectedBy", function(client, givenBy, amount)
if (amount) then
return string.format("%s a été désinfecté par %s pendant %d secondes.", client:Name(), givenBy:GetPlayer():Name(), amount)
else
return string.format("%s a essayé de désinfecter %s mais la plaie était déjà propre.", givenBy:GetPlayer():Name(), client:Name())
end
end)
function PLUGIN:MedicalPlayerTick(client, ticks)
local character = client:GetCharacter()
if (!character) then return end
if (!client:Alive()) then
return
end
local health = client:Health()
local maxHealth = client:GetMaxHealth()
local bMaxHealth = health >= maxHealth
if (!bMaxHealth or character:GetHealing("fakeHealth") > 0) then
local factor = 1
if (character:GetHealing("disinfectant") > 0) then
factor = ix.config.Get("HealingRegenBoostFactor") * 5
end
character:SetHealing("passive", ticks * factor * maxHealth / (ix.config.Get("HealthRegenTime") * 3600))
end
if (IsValid(client.ixRagdoll) and client:Alive() and client.ixRagdoll.bleedoutGetup and
(health * 100 / maxHealth) >= ix.config.Get("WakeupTreshold")) then
client:SetRagdolled(false)
netstream.Start("BleedoutScreen", false)
ix.log.Add(client, "medicalBleedoutStop")
end
-- Do bleedout stuff
local bleedout = character:GetBleedout()
if (bleedout > 0) then
bleedout = bleedout - ticks
if (bleedout <= 0) then
if (IsValid(client.ixRagdoll)) then
client.ixRagdoll.ixNoReset = true
end
character:SetBleedout(-1)
client:SetNetVar("deathTime", nil)
client:Kill()
ix.log.Add(client, "medicalBleedout")
return
else
self:BleedoutPainSound(client)
character:SetBleedout(bleedout)
end
end
local healingData = character:GetHealing()
if (!healingData) then
return
end
-- Apply healing from bandages
if (healingData.bandage > 0) then
local healingAmount = ticks * ix.config.Get("HealingRegenRate") / 60
if (healingData.disinfectant > 0) then -- Boost if disinfected
healingAmount = healingAmount * ix.config.Get("HealingRegenBoostFactor")
healingData.disinfectant = math.max(healingData.disinfectant - ticks, 0)
end
-- Give healRate or whatever is left
if (healingData.bandage > healingAmount) then
healingData.healingAmount = math.Round(healingData.healingAmount + healingAmount, self.HEALING_PRECISION)
healingData.bandage = math.Round(healingData.bandage - healingAmount, self.HEALING_PRECISION)
else
healingData.healingAmount = math.Round(healingData.healingAmount + healingData.bandage, self.HEALING_PRECISION)
healingData.bandage = 0
end
elseif (healingData.disinfectant and healingData.disinfectant > 0) then
healingData.disinfectant = math.max(healingData.disinfectant - ticks * 2, 0)
end
-- Apply fake healing from painkillers
if (healingData.painkillers > 0) then
local fakeAmount = ticks * ix.config.Get("HealingPainkillerRate") / 60
if (healingData.painkillers > fakeAmount) then
if (!bMaxHealth) then -- Only actually kill pain if not at max health
healingData.fakeHealth = math.Round(healingData.fakeHealth + fakeAmount, self.HEALING_PRECISION)
healingData.healingAmount = math.Round(healingData.healingAmount + fakeAmount, self.HEALING_PRECISION)
end
healingData.painkillers = math.Round(healingData.painkillers - fakeAmount, self.HEALING_PRECISION)
else
if (!bMaxHealth) then -- Only actually kill pain if not at max health
healingData.healingAmount = math.Round(healingData.healingAmount + healingData.painkillers, self.HEALING_PRECISION)
healingData.fakeHealth = math.Round(healingData.fakeHealth + healingData.painkillers, self.HEALING_PRECISION)
end
healingData.painkillers = 0
end
end
-- Check if painkillers are still working
if (healingData.painkillersDuration > 0) then
-- Reduce duration
healingData.painkillersDuration = math.max(healingData.painkillersDuration - ticks, 0)
end
-- At max health?
if (bMaxHealth) then
-- Check if there is any fake health we can heal
if (healingData.fakeHealth > 0 and healingData.healingAmount > 0) then
if (healingData.fakeHealth > healingData.healingAmount) then
healingData.fakeHealth = healingData.fakeHealth - healingData.healingAmount
healingData.healingAmount = 0
else
healingData.healingAmount = healingData.healingAmount - healingData.fakeHealth
healingData.fakeHealth = 0
end
end
-- At max health and no full health point of fake healing left
if (healingData.fakeHealth - healingData.healingAmount < 1) then
character:SetHealing("table", nil) -- Stop healing!
ix.log.Add(client, "medicalFullyHealed")
return
end
end
-- Uh oh, the painkillers ran out... time to bring back the pain
if (healingData.painkillersDuration == 0 and healingData.fakeHealth > 0) then
local fakeAmount = ticks * ix.config.Get("HealingPainkillerDecayRate") / 60
if (healingData.fakeHealth > fakeAmount) then
healingData.healingAmount = math.Round(healingData.healingAmount - fakeAmount, self.HEALING_PRECISION)
healingData.fakeHealth = math.Round(healingData.fakeHealth - fakeAmount, self.HEALING_PRECISION)
else
healingData.healingAmount = math.Round(healingData.healingAmount - healingData.fakeHealth, self.HEALING_PRECISION)
healingData.fakeHealth = 0
end
end
-- Check if we can heal/damage for at least one point of HP
if ((!bMaxHealth and healingData.healingAmount >= 1) or healingData.healingAmount <= -1) then
if (healingData.healingAmount >= 1 or healingData.healingAmount <= -1) then
-- Source engine can only handle integer values for HP so...
-- Heal as many integer points of HP as we can and save the fraction left for the future
local totalHealing = math.min(math.Truncate(healingData.healingAmount), maxHealth - health)
healingData.healingAmount = healingData.healingAmount - totalHealing
client:SetHealth(math.min(health + totalHealing, maxHealth))
if (client:Health() <= 0) then
client:Kill()
ix.log.Add(client, "medicalPainkillersNoHP")
character:SetHealing("table", nil)
return
end
end
end
if (healingData.fakeHealth - client:Health() > maxHealth * 1.1) then
client:Kill()
ix.log.Add(client, "medicalPainkillersTooMany")
character:SetHealing("table", nil)
return
end
character:SetHealing("table", healingData)
end
function PLUGIN.OnSetHealing(character, healType, value, givenBy)
if (!healType) then
ErrorNoHalt("Tentative de définir la guérison mais aucun type n'a été fourni !")
return
end
if (healType == "table") then
character.vars.healing = value
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
if (character.vars.healing) then
net.WriteUInt(0, 2)
net.WriteUInt(value.bandage, 16)
net.WriteUInt(value.disinfectant, 16)
net.WriteUInt(value.painkillers, 16)
net.WriteUInt(value.painkillersDuration, 16)
net.WriteFloat(value.healingAmount)
net.WriteFloat(value.fakeHealth)
end
net.Broadcast()
else
if (!value or value <= 0) then
ErrorNoHalt("Tentative de soignement '"..healType.."' sans valeurs ("..(value or "nil")..")!")
return
end
local healingData = character:GetHealing()
if (!healingData or !healingData.bandage) then
healingData = {
bandage = 0,
disinfectant = 0,
painkillers = 0,
painkillersDuration = 0,
healingAmount = 0,
fakeHealth = 0
}
end
if (healType == "bandage") then
value = value * (givenBy and (1 + givenBy:GetSkillScale("bandage_skill")) or 1)
healingData.bandage = healingData.bandage + value
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(1, 2)
net.WriteUInt(healingData.bandage, 16)
net.Broadcast()
if (character:GetBleedout() > 0) then
character:SetBleedout(-1)
ix.log.Add(character:GetPlayer(), "medicalBleedoutStoppedBy", givenBy)
end
if (givenBy) then
ix.log.Add(character:GetPlayer(), "medicalBandagedBy", givenBy, value)
end
elseif (healType == "bandage_damage") then
healingData.bandage = math.max(healingData.bandage - value, 0)
healingData.painkillers = 0
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(1, 2)
net.WriteUInt(healingData.bandage, 16)
net.Broadcast()
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(3, 2)
net.WriteUInt(healingData.painkillers, 16)
net.Broadcast()
elseif (healType == "disinfectant") then
value = value * (1 + givenBy:GetSkillScale("disinfectant_skill")) * 60 /
(ix.config.Get("HealingRegenRate") * ix.config.Get("HealingRegenBoostFactor"))
healingData.disinfectant = math.max(healingData.disinfectant, value)
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(2, 2)
net.WriteUInt(healingData.disinfectant, 16)
net.Broadcast()
if (givenBy) then
ix.log.Add(character:GetPlayer(), "medicalDisinfectedBy", givenBy, healingData.disinfectant == value and value)
end
elseif (healType == "painkillers") then
healingData.painkillers = healingData.painkillers + value
healingData.painkillersDuration = ix.config.Get("HealingPainkillerDuration") * 60
net.Start("ixHealingData")
net.WriteUInt(character:GetID(), 32)
net.WriteUInt(3, 2)
net.WriteUInt(healingData.painkillers, 16)
net.Broadcast()
elseif (healType == "passive") then
healingData.healingAmount = math.Round(healingData.healingAmount + value, PLUGIN.HEALING_PRECISION)
end
character.vars.healing = healingData
end
end
local painSounds = {
Sound("vo/npc/male01/pain01.wav"),
Sound("vo/npc/male01/pain02.wav"),
Sound("vo/npc/male01/pain03.wav"),
Sound("vo/npc/male01/pain04.wav"),
Sound("vo/npc/male01/pain05.wav"),
Sound("vo/npc/male01/pain06.wav")
}
function PLUGIN:BleedoutPainSound(client)
if ((client.ixNextPain or 0) < CurTime() and math.random() < 0.1) then
local painSound = hook.Run("GetPlayerPainSound", client) or painSounds[math.random(1, #painSounds)]
if (client:IsFemale() and !painSound:find("female")) then
painSound = painSound:gsub("male", "female")
end
client:EmitSound(painSound)
client.ixNextPain = CurTime() + 5
end
end
netstream.Hook("ixConfirmRespawn", function(client)
client.confirmRespawn = true
end)
netstream.Hook("ixAcceptDeath", function(client)
if (IsValid(client.ixRagdoll)) then
client.ixRagdoll.ixNoReset = true
end
if (!client:GetCharacter()) then return end
client:GetCharacter():SetBleedout(-1)
client:SetNetVar("deathTime", nil)
client:Kill()
ix.log.Add(client, "qolDeathLog", "accepting their death")
end)