add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,494 @@
local meta = FindMetaTable( "Player" )
local lang = ConfigurationMedicMod.Language
local sentences = ConfigurationMedicMod.Sentences
function meta:MedicModDamages()
local dmg = 0
if self:IsBleeding() then
dmg = dmg + ConfigurationMedicMod.DamagePerSecsDuringBleeding * 4
end
if self:IsPoisoned() then
dmg = dmg + ConfigurationMedicMod.DamagePerSecsDuringPoisoned * 4
end
return dmg or 0
end
function meta:CreateMedicTimer()
timer.Create("MedicMod"..self:EntIndex(), 4, 0, function()
if not IsValid( self ) or not self:Alive() then return end
local world = game.GetWorld()
local d = DamageInfo()
d:SetDamage( self:MedicModDamages() )
d:SetAttacker( world )
d:SetInflictor( world )
if self:IsBleeding() then
d:SetDamageType( DMG_MEDICMODBLEEDING )
-- bleeding effect
local bone = self:GetBonePosition(math.random(1, self:GetBoneCount() - 1))
if bone then
local ef = EffectData()
ef:SetOrigin(bone)
util.Effect("BloodImpact", ef, true, true)
end
-- bleeding decals
if ConfigurationMedicMod.DecalsBleeding then
local src = self:LocalToWorld(self:OBBCenter())
for i = 1, 12 do
local dir = VectorRand() * self:GetModelRadius() * 1.4
util.Decal("Blood", src - dir, src + dir)
end
end
else
d:SetDamageType( DMG_MEDICMOD )
end
local health = self:Health()
self:TakeDamageInfo( d )
self:SetHealth(health-self:MedicModDamages())
if self:Health() <= 0 and self:Alive() then
self:Kill()
end
end)
end
function meta:SetBleeding( bool )
if self:HasGodMode() then return end
if not ConfigurationMedicMod.CanGetBleeding then return end
if table.HasValue( ConfigurationMedicMod.TeamsCantGetBleeding, self:Team() ) then return end
self:SetNWBool("Bleeding", bool )
if not bool then
if timer.Exists( "MedicMod"..self:EntIndex() ) then
if not self:IsPoisoned() then
timer.Destroy("MedicMod"..self:EntIndex())
end
end
return
end
if timer.Exists( "MedicMod"..self:EntIndex() ) then return end
hook.Run( "onPlayerStartsBleeding", self )
self:CreateMedicTimer()
end
function meta:SetMorphine( bool )
self:SetNWBool("Morphine", bool )
end
function meta:SetHeartAttack( bool )
self:SetNWBool("HeartAttack", bool )
if timer.Exists( "MedicMod"..self:EntIndex() ) then
timer.Destroy("MedicMod"..self:EntIndex())
end
end
function meta:SetPoisoned( bool )
if self:HasGodMode() then return end
if not ConfigurationMedicMod.CanGetPoisoned then return end
if table.HasValue( ConfigurationMedicMod.TeamsCantGetPoisoned, self:Team() ) then return end
self:SetNWBool("Poisoned", bool )
if not bool then
if timer.Exists( "MedicMod"..self:EntIndex() ) then
if not self:IsBleeding() then
timer.Destroy("MedicMod"..self:EntIndex())
end
end
return
end
if timer.Exists( "MedicMod"..self:EntIndex() ) then return end
hook.Run( "onPlayerPoisoned", self )
self:CreateMedicTimer()
end
local FractureHitGroups = {}
FractureHitGroups["legs"] = {
[HITGROUP_LEFTLEG] = true,
[HITGROUP_RIGHTLEG] = true,
}
FractureHitGroups["arms"] = {
[HITGROUP_LEFTARM] = true,
[HITGROUP_RIGHTARM] = true,
}
function meta:SetFracture( bool, hitgroup )
if self:HasGodMode() then return end
if not ConfigurationMedicMod.CanGetFractures then return end
if table.HasValue( ConfigurationMedicMod.TeamsCantGetFracture, self:Team() ) then return end
if bool then
self:SetNWBool("Fracture", bool )
if not self.Fractures then self.Fractures = {} end
if self.Fractures[hitgroup] then return end
self.Fractures[hitgroup] = true
if FractureHitGroups["legs"][hitgroup] then
self:MedicNotif(sentences["You broke your leg, your speed is reduced"][lang])
if self.SpeedReduced then return end
self.MMFWalkSpeed = self:GetWalkSpeed()
self.MMFRunSpeed = self:GetRunSpeed()
self:SetRunSpeed(ConfigurationMedicMod.FracturePlayerSpeed)
self:SetWalkSpeed(ConfigurationMedicMod.FracturePlayerSpeed)
self.SpeedReduced = true
elseif FractureHitGroups["arms"][hitgroup] then
self:MedicNotif(sentences["You broke your arm, you can't use any weapon"][lang])
self:SelectWeapon( "" )
self.CantSwitchWeaponMF = true
end
hook.Run( "onPlayerBreaksBone", self, hitgroup )
else
if not self.Fractures then self.Fractures = {} end
if FractureHitGroups["legs"][hitgroup] then
if self.Fractures[hitgroup] then
self.Fractures[hitgroup] = nil
end
for k, v in pairs( FractureHitGroups["legs"] ) do
if self.Fractures[k] then
return
end
end
if not self.MMFRunSpeed or not self.MMFWalkSpeed then return end
self:SetRunSpeed(self.MMFRunSpeed)
self:SetWalkSpeed(self.MMFWalkSpeed)
self.SpeedReduced = false
elseif FractureHitGroups["arms"][hitgroup] then
if self.Fractures[hitgroup] then
self.Fractures[hitgroup] = nil
end
for k, v in pairs( FractureHitGroups["arms"] ) do
if self.Fractures[k] then
return
end
end
self.CantSwitchWeaponMF = false
end
for k, v in pairs( self.Fractures ) do
if FractureHitGroups["legs"][ k ] or FractureHitGroups["arms"][ k ] then
return
end
end
self:SetNWBool("Fracture", false)
self:MedicNotif(sentences["You have no more fracture"][lang])
end
end
function meta:GetFractures()
return self.Fractures or nil
end
function meta:CreateDeathRagdoll()
-- create the ragdoll
local ragdoll = ents.Create("prop_ragdoll")
ragdoll:SetPos(self:GetPos())
ragdoll:SetAngles( self:GetAngles() )
ragdoll:SetModel(self:GetModel())
ragdoll:SetOwner( self )
ragdoll:SetDeathRagdoll( true )
-- set bones of the ragdoll at the same pos than bones of the player
local gpobc = ragdoll:GetPhysicsObjectCount() - 1
for i=0, gpobc do
local bone = self:GetPhysicsObjectNum(i)
if IsValid(bone) then
local bonepos, boneang = self:GetBonePosition(ragdoll:TranslatePhysBoneToBone(i))
if bonepos and boneang then
bone:SetPos(bonepos)
bone:SetAngles(boneang)
end
end
end
ragdoll:Spawn()
ragdoll:Activate()
ragdoll:AddEFlags( EFL_IN_SKYBOX )
-- make a prop to allow the player to pickup the ragdoll
local pickupProp = ents.Create("prop_physics")
pickupProp:SetModel("models/hunter/blocks/cube025x025x025.mdl")
pickupProp:SetPos(ragdoll:GetPos())
pickupProp:SetNoDraw(true)
pickupProp:Spawn()
pickupProp:SetCollisionGroup(COLLISION_GROUP_WORLD)
ragdoll.Prop = pickupProp
pickupProp.ragdoll = ragdoll
constraint.Weld(ragdoll, pickupProp, 0, 0, 0, false)
self.DeathRagdoll = ragdoll
if CLOTHESMOD then self:CM_ApplyRagModel( ragdoll ) end
return ragdoll
end
function meta:Stabilize( medic )
if self:IsBleeding() then return end
if self:IsPoisoned() then return end
if self:GetHeartAttack() then return end
self.NextSpawnTime = ConfigurationMedicMod.TimeBeforeRespawnIfStable + CurTime()
net.Start("MedicMod.Respawn") net.WriteInt(self.NextSpawnTime, 32) net.Send(self)
self.Stable = true
self:MedicNotif( sentences["Your condition has been stabilized"][lang], 10)
hook.Run( "onPlayerStabilized", self, medic )
if not IsValid( medic ) then return end
medic:MedicNotif( sentences["You stabilized the wounded"][lang], 10)
end
function meta:MedicalRespawn()
local pos
if not IsValid( self.DeathRagdoll ) or not self.DeathRagdoll:IsDeathRagdoll() then
pos = self:GetPos()
else
if IsValid(self.DeathRagdoll.Rope) then
self.DeathRagdoll.Rope:SetParent( nil )
if self.DeathRagdoll.Rope.Elec and IsValid( self.DeathRagdoll.Rope.Elec ) then
self.DeathRagdoll.Rope.Elec:SetPatient( nil )
end
end
pos = self.DeathRagdoll:GetPos()
end
self:MedicNotif( sentences["You have been saved"][lang], 10)
-- Save current weapons and ammo before Spawn() resets them
self.WeaponsStripped = {}
for k, v in pairs( self:GetWeapons() ) do
table.insert(self.WeaponsStripped, v:GetClass())
end
self.AmmoStripped = {}
for k, v in pairs( self:GetAmmo() ) do
self.AmmoStripped[k] = v
end
self:Spawn()
self:SetPos( pos )
local weaponsstripped = self.WeaponsStripped or {}
for k, v in pairs( weaponsstripped ) do
self:Give( v )
end
local ammostripped = self.AmmoStripped or {}
for k, v in pairs( ammostripped ) do
self:SetAmmo( v, k )
end
hook.Run( "onPlayerRevived", self )
end
function meta:StartOperation( bed )
local pos = self:GetPos()
local ang = self:GetAngles()
local hbed = ents.Create("prop_vehicle_prisoner_pod")
hbed:SetModel("models/vehicles/prisoner_pod_inner.mdl")
hbed:SetPos( bed:GetPos() + bed:GetAngles():Up() * 22 + bed:GetAngles():Right() * -30 )
hbed:SetAngles( bed:GetAngles() + Angle(-90,0,90))
hbed:SetNoDraw(true)
hbed:SetCollisionGroup(COLLISION_GROUP_WORLD)
hbed:SetSolid(SOLID_NONE)
hbed.locked = true
bed.ragdoll = hbed
self:EnterVehicle(hbed)
self:MedicNotif( sentences["You are having surgery"][lang], ConfigurationMedicMod.SurgicalOperationTime)
self:Freeze( true )
hook.Run( "onPlayerStartsOperation", self )
timer.Simple( ConfigurationMedicMod.SurgicalOperationTime, function()
if not IsValid(self) or not IsValid(bed) or not IsValid(hbed) then return end
self:Freeze( false )
self:SetHealth( self:GetMaxHealth() )
if not self.Fractures then self.Fractures = {} end
for k, v in pairs( self.Fractures ) do
self:SetFracture( false, k )
end
self:SetBleeding( false )
hbed:Remove()
timer.Simple(0.2, function()
self:SetPos( pos )
self:SetEyeAngles( ang )
end)
bed.ragdoll = nil
end)
end
function meta:HaveFractures()
local fract = false
if not self.Fractures then return false end
for k, v in pairs( self.Fractures ) do
if FractureHitGroups["legs"][ k ] or FractureHitGroups["arms"][ k ] then
fract = true
break
end
end
return fract
end
function StartMedicAnimation( ply, id )
ply:SetNWString("MedicPlayerModel", ply:GetModel())
ply:SetModel("models/medicmod/player/medic_anims.mdl")
ply:SetRenderMode(RENDERMODE_TRANSALPHA)
ply:SetColor(Color(0,0,0,0))
ply:SetNWInt("MedicActivity", id )
ply:Freeze( true )
-- network animation
net.Start("MedicMod.PlayerStartAnimation")
net.Broadcast()
end
function StopMedicAnimation( ply )
ply:SetNWInt("MedicActivity", 0 )
ply:SetModel( ply:GetNWString("MedicPlayerModel") )
ply:SetColor(Color(255,255,255,255))
ply:SetNWString("MedicPlayerModel", nil)
ply:Freeze( false )
-- network animation
net.Start("MedicMod.PlayerStopAnimation")
net.Broadcast()
end
function IsBleedingDamage( dmg )
local isdmg = false
for k, v in pairs( ConfigurationMedicMod.DamageBleeding ) do
if not v then continue end
if dmg:IsDamageType( k ) then
isdmg = true
end
end
return isdmg
end
function IsPoisonDamage( dmg )
local isdmg = false
for k, v in pairs( ConfigurationMedicMod.DamagePoisoned ) do
if dmg:IsDamageType( k ) then
isdmg = true
end
end
return isdmg
end
local ent = FindMetaTable( "Entity" )
function ent:SetDeathRagdoll( bool )
self:SetNWBool("IsDeathRagdoll", bool )
end

View File

@@ -0,0 +1,559 @@
local lang = ConfigurationMedicMod.Language
local sentences = ConfigurationMedicMod.Sentences
-- Delete the timer
hook.Add("PlayerDisconnected", "PlayerDisconnected.MedicMod", function( ply )
StopMedicAnimation( ply )
if ply.RagdollHeartMassage then
if IsValid( ply.RagdollHeartMassage ) && IsValid( ply.RagdollHeartMassage:GetOwner() ) then
ply.RagdollHeartMassage:GetOwner().NextSpawnTime = CurTime() + ply.RagdollHeartMassage:GetOwner().AddToSpawnTime
ply.RagdollHeartMassage.IsHeartMassage = false
net.Start("MedicMod.Respawn")
net.WriteInt(ply.RagdollHeartMassage:GetOwner().NextSpawnTime,32)
net.Send(ply.RagdollHeartMassage:GetOwner())
end
end
if timer.Exists( "MedicMod"..ply:EntIndex() ) then
timer.Destroy("MedicMod"..ply:EntIndex())
end
-- remove the death ragdoll
if IsValid( ply.DeathRagdoll ) then
if IsValid( ply.DeathRagdoll.Prop ) then
ply.DeathRagdoll.Prop:Remove()
end
ply.DeathRagdoll:Remove()
end
end)
-- Respawn
hook.Add("PlayerSpawn", "PlayerSpawn.MedicMod", function( ply )
ply:SetBleeding( false )
ply:SetHeartAttack( false )
ply:SetPoisoned( false )
if ply:GetFractures() then
-- cure fractures
for k, v in pairs( ply:GetFractures() ) do
ply:SetFracture(false, k)
end
end
-- remove the death ragdoll
if IsValid( ply.DeathRagdoll ) then
if IsValid( ply.DeathRagdoll.Prop ) then
ply.DeathRagdoll.Prop:Remove()
end
ply.DeathRagdoll:Remove()
if IsValid(ply.DeathRagdoll.Rope) then
ply.DeathRagdoll.Rope:SetParent( nil )
if ply.DeathRagdoll.Rope.Elec and IsValid( ply.DeathRagdoll.Rope.Elec ) then
ply.DeathRagdoll.Rope.Elec:SetPatient( nil )
end
end
end
ply:UnSpectate()
ply.NextSpawnTime = 0
end)
-- Stop death sound
hook.Add("PlayerDeathSound", "PlayerDeathSound.MedicMod", function()
return true
end)
-- Bleeding
hook.Add("EntityTakeDamage", "EntityTakeDamage.MedicMod", function( ply, dmg )
if not IsValid(ply) or not ply:IsPlayer() then return end
-- Fix for LVS/Vehicles: ignore blast/shell damage if player is in a vehicle and damage is self-inflicted
if (ply:InVehicle()) then
local vehicle = ply:GetVehicle()
local attacker = dmg:GetAttacker()
local inflictor = dmg:GetInflictor()
if (attacker == ply or attacker == vehicle or inflictor == vehicle) and (dmg:IsDamageType(DMG_BLAST) or dmg:IsDamageType(DMG_BLAST_SURFACE)) then
return
end
end
local dmgtype = dmg:GetDamageType()
-- break a bone
if dmg:IsFallDamage() then
if dmg:GetDamage() >= ConfigurationMedicMod.MinimumDamageToGetFractures then
ply:SetFracture(true, HITGROUP_RIGHTLEG)
ply:SetFracture(true, HITGROUP_LEFTLEG)
end
end
if IsBleedingDamage( dmg ) and dmg:GetDamage() >= ConfigurationMedicMod.MinimumDamageToGetBleeding then
ply:SetBleeding( true )
end
if IsPoisonDamage( dmg ) then ply:SetPoisoned( true ) end
end)
-- Set heart attack
hook.Add("DoPlayerDeath", "DoPlayerDeath.MedicMod", function( ply, att, dmg )
StopMedicAnimation( ply )
if ply.RagdollHeartMassage then
if IsValid( ply.RagdollHeartMassage ) && IsValid( ply.RagdollHeartMassage:GetOwner() ) then
ply.RagdollHeartMassage:GetOwner().NextSpawnTime = CurTime() + ply.RagdollHeartMassage:GetOwner().AddToSpawnTime
ply.RagdollHeartMassage.IsHeartMassage = false
net.Start("MedicMod.Respawn")
net.WriteInt(ply.RagdollHeartMassage:GetOwner().NextSpawnTime,32)
net.Send(ply.RagdollHeartMassage:GetOwner())
end
end
local dmgtype = dmg:GetDamageType()
local dmgimpact = dmg:GetDamage()
if IsBleedingDamage( dmg ) or ConfigurationMedicMod.DamageBurn[dmgtype] then
if dmgtype == DMG_MEDICMODBLEEDING then
ply:MedicNotif(sentences["His heart no longer beats"][lang], 10)
end
ply:SetHeartAttack( true )
ply:MedicNotif(sentences["You fell unconscious following a heart attack"][lang], 10)
else
if IsPoisonDamage(dmg) then
ply:SetPoisoned( true )
end
if IsBleedingDamage( dmg ) and dmgimpact >= ConfigurationMedicMod.MinimumDamageToGetBleeding then
ply:SetBleeding( true )
end
ply:SetHeartAttack( true )
ply:MedicNotif(sentences["You fell unconscious following a heart attack"][lang], 10)
end
end)
-- Create the death ragdoll, etc.
hook.Add("PlayerDeath", "PlayerDeath.MedicMod", function( victim, inf, att )
-- Save player weapons
victim.WeaponsStripped = {}
for k, v in pairs( victim:GetWeapons() ) do
table.insert(victim.WeaponsStripped,v:GetClass())
end
-- Save player ammo
victim.AmmoStripped = {}
for k, v in pairs( victim:GetAmmo() ) do
victim.AmmoStripped[k] = v
end
-- set the next respawn time
timer.Simple( 0, function()
local timebeforerespawn = CurTime()+ConfigurationMedicMod.TimeBeforeRespawnIfNoConnectedMedics
for k, v in pairs( player.GetAll() ) do
if table.HasValue( ConfigurationMedicMod.MedicTeams, v:Team() ) then
timebeforerespawn = CurTime()+ConfigurationMedicMod.TimeBeforeRespawn
break
end
end
victim.NextSpawnTime = timebeforerespawn
net.Start("MedicMod.Respawn")
net.WriteInt(timebeforerespawn,32)
net.Send(victim)
end )
if not IsValid( victim ) or not victim:GetHeartAttack() then return end
if victim:InVehicle() then victim:ExitVehicle() end
-- Create death ragdoll
local rag = victim:CreateDeathRagdoll()
-- Remove ragdoll ent
timer.Simple(0.01, function()
if(victim:GetRagdollEntity() != nil and victim:GetRagdollEntity():IsValid()) then
victim:GetRagdollEntity():Remove()
end
end)
-- Set the view on the ragdoll
victim:Spectate( OBS_MODE_DEATHCAM )
victim:SpectateEntity( rag )
end)
-- Determine if the player can respawn
hook.Add("PlayerDeathThink", "PlayerDeathThink.MedicMod", function( pl )
if not ( pl.NextSpawnTime ) then pl.NextSpawnTime = 0 end
if pl.NextSpawnTime == -1 then return false end
if pl.NextSpawnTime > CurTime() then return false end
if ConfigurationMedicMod.ForceRespawn then
pl:Spawn()
end
end)
hook.Add("PlayerSwitchWeapon", "PlayerSwitchWeapon.MedicMod", function( ply, old, new )
if not IsValid( old ) or not IsValid( ply ) then return end
-- prevent switch weapon if the player is doing a heart massage
if old:GetClass() == "heart_massage" && ply:GetMedicAnimation() != 0 then
return true
end
if ply.CantSwitchWeapon then
return true
end
if ply.CantSwitchWeaponMF and ConfigurationMedicMod.CanBreakArms then
return true
end
end)
-- Start animations when player join
hook.Add("PlayerInitialSpawn", "PlayerInitialSpawn.MedicMod", function( ply )
timer.Simple(10, function()
net.Start("MedicMod.PlayerStartAnimation")
net.Send( ply )
end)
end)
--[[
local function MedicMod_DropCarriedRagdoll(ply, throw)
if not IsValid(ply) then return end
local rag = ply.CarryingRagdoll
if not IsValid(rag) then
ply.CarryingRagdoll = nil
ply:SetNWBool("CarryingRagdoll", false)
return
end
rag:SetParent(nil)
rag:SetMoveType(MOVETYPE_VPHYSICS)
local phys = rag:GetPhysicsObject()
if IsValid(phys) then
phys:EnableMotion(true)
phys:Wake()
if throw then
phys:SetVelocity(ply:GetAimVector() * 450 + ply:GetVelocity() * 0.5 + Vector(0,0,125))
end
end
rag:SetNWEntity("CarriedBy", NULL)
rag:SetNWBool("IsRagdollCarried", false)
ply.CarryingRagdoll = nil
ply:SetNWBool("CarryingRagdoll", false)
ply:MedicNotif(ConfigurationMedicMod.Sentences["You dropped the corpse"][ConfigurationMedicMod.Language], 5)
end
hook.Add("PlayerButtonDown", "PlayerButtonDown.MedicMod.CarryRagdoll", function(ply, button)
if not IsValid(ply) or not ply:Alive() or button ~= KEY_E then return end
if IsValid(ply.CarryingRagdoll) then
MedicMod_DropCarriedRagdoll(ply, true)
return
end
local trace = ply:GetEyeTraceNoCursor()
local ent = trace.Entity
if not IsValid(ent) or not ent:IsDeathRagdoll() then return end
if trace.HitPos:Distance(ply:GetPos()) > 120 then return end
if ent:GetNWEntity("CarriedBy", NULL):IsValid() then return end
if ent:GetNWBool("IsRagdollCarried", false) then return end
ent:SetMoveType(MOVETYPE_NONE)
ent:SetParent(ply)
ent:SetLocalPos(Vector(10, -12, 18))
ent:SetLocalAngles(Angle(90, 0, 0))
ent:SetNWEntity("CarriedBy", ply)
ent:SetNWBool("IsRagdollCarried", true)
ply.CarryingRagdoll = ent
ply:SetNWBool("CarryingRagdoll", true)
ply:MedicNotif(ConfigurationMedicMod.Sentences["You attached the corpse on your back"][ConfigurationMedicMod.Language], 5)
end)
hook.Add("Think", "Think.MedicMod.CarryRagdoll", function()
for _, ply in ipairs(player.GetAll()) do
if not IsValid(ply) then continue end
local rag = ply.CarryingRagdoll
if not IsValid(rag) then continue end
if not ply:Alive() then
MedicMod_DropCarriedRagdoll(ply, false)
continue
end
local eye = ply:EyeAngles()
local backPos = ply:GetPos() + ply:GetForward() * -8 + ply:GetRight() * 4 + Vector(0,0,18)
rag:SetPos(backPos)
rag:SetAngles(eye + Angle(90,0,0))
end
end)
]]
-- When a player spawn an ambulance
hook.Add("PlayerSpawnedVehicle", "PlayerSpawnedVehicle.MedicMod", function( ply, ent )
if not IsValid( ent ) then return end
if ConfigurationMedicMod.Vehicles[ent:GetModel()] then
local button = ents.Create("ambulance_button_medicmod")
button:Spawn()
button:SetPos( ent:LocalToWorld(ConfigurationMedicMod.Vehicles[ent:GetModel()].buttonPos) )
button:SetAngles( ent:LocalToWorldAngles(ConfigurationMedicMod.Vehicles[ent:GetModel()].buttonAngle) )
button:SetParent( ent )
ent.Button = button
local stretcher = ents.Create("stretcher_medicmod")
stretcher:Spawn()
stretcher:SetPos(ent:LocalToWorld(ConfigurationMedicMod.Vehicles[ent:GetModel()].stretcherPos))
stretcher:SetAngles(ent:LocalToWorldAngles(ConfigurationMedicMod.Vehicles[ent:GetModel()].stretcherAngle))
stretcher:SetParent( ent )
if not ConfigurationMedicMod.Vehicles[ent:GetModel()].drawStretcher then
stretcher:SetRenderMode( RENDERMODE_TRANSALPHA )
stretcher:SetColor( Color(0,0,0,0) )
end
ent.Stretcher = stretcher
ent.SpawnedStretcher = stretcher
end
end)
-- Remove the stretcher when vehicle is removed
hook.Add("EntityRemoved", "EntityRemoved.MedicMod", function( ent )
if not IsValid( ent ) then return end
local stretch = ent.SpawnedStretcher or NULL
if not IsValid( stretch ) then return end
if stretch.ragdoll && IsValid( stretch.ragdoll ) then return end
stretch:Remove()
end)
local FractureHitGroups = {
[HITGROUP_LEFTLEG] = true,
[HITGROUP_RIGHTLEG] = true,
[HITGROUP_LEFTARM] = true,
[HITGROUP_RIGHTARM] = true,
}
-- break a bone
hook.Add("ScalePlayerDamage", "ScalePlayerDamage.MedicMod", function(ply, hitgroup, dmg)
if not FractureHitGroups[hitgroup] then return end
if dmg:GetDamage() < ConfigurationMedicMod.MinimumDamageToGetFractures then return end
ply:SetFracture( true, hitgroup )
end)
-- Save entities
local MedicModSavedEntities = {
["terminal_medicmod"] = true,
["radio_medicmod"] = true,
["npc_health_seller_medicmod"] = true,
["mural_defib_medicmod"] = true,
["electrocardiogram_medicmod"] = true,
["bed_medicmod"] = true,
}
-- Commands
hook.Add("PlayerSay", "PlayerSay.MedicMod", function(ply, text)
if text == "!save_medicmod" and ply:IsSuperAdmin() then
local MedicPos = {}
for k, v in pairs(ents.GetAll()) do
if not MedicModSavedEntities[v:GetClass()] then continue end
MedicPos[#MedicPos + 1] = {
pos = v:GetPos(),
ang = v:GetAngles(),
class = v:GetClass()
}
file.CreateDir("medicmod")
file.Write("medicmod/save_ents.txt", util.TableToJSON(MedicPos))
local filecontent = file.Read("medicmod/save_ents.txt", "DATA")
ConfigurationMedicMod.SavedEnts = util.JSONToTable(filecontent)
end
ply:MedicNotif("Entities saved!")
end
if text == "!remove_medicmod" and ply:IsSuperAdmin() then
if file.Exists("medicmod/save_ents.txt", "DATA") then
file.Delete( "medicmod/save_ents.txt" )
ply:MedicNotif("Entities removed!")
end
local filecontent = file.Read("medicmod/save_ents.txt", "DATA") or ""
ConfigurationMedicMod.SavedEnts = util.JSONToTable(filecontent) or {}
end
if text == "!reviveme" and ply:IsAdmin() and ConfigurationMedicMod.CanUseReviveMeCommand then
ply:MedicalRespawn()
end
if text == "!"..ConfigurationMedicMod.MedicCommand and table.HasValue( ConfigurationMedicMod.MedicTeams, ply:Team() ) then
net.Start("MedicMod.OpenMedicMenu")
net.Send( ply )
end
end)
-- Init the list of ents to spawn
hook.Add("Initialize", "Initialize.MedicMod", function()
if not file.Exists("medicmod/save_ents.txt", "DATA") then return end
local filecontent = file.Read("medicmod/save_ents.txt", "DATA")
ConfigurationMedicMod.SavedEnts = util.JSONToTable(filecontent)
end)
-- spawn ents
hook.Add("InitPostEntity", "InitPostEntity.MedicMod", function()
if not ConfigurationMedicMod.SavedEnts then return end
timer.Simple(1, function()
for k, v in pairs(ConfigurationMedicMod.SavedEnts) do
local ent = ents.Create(v.class)
ent:SetPos( v.pos )
ent:SetAngles( v.ang )
ent:SetPersistent( true )
ent:Spawn()
ent:SetMoveType( MOVETYPE_NONE )
end
end)
end)
hook.Add("PostCleanupMap", "PostCleanupMap.MedicMod", function()
if not ConfigurationMedicMod.SavedEnts then return end
for k, v in pairs(ConfigurationMedicMod.SavedEnts) do
local ent = ents.Create(v.class)
ent:SetPos( v.pos )
ent:SetAngles( v.ang )
ent:SetPersistent( true )
ent:Spawn()
ent:SetMoveType( MOVETYPE_NONE )
end
end)
-- Can change job?
hook.Add("playerCanChangeTeam", "playerCanChangeTeam.MedicMod", function(ply)
if ply.NextSpawnTime and ply.NextSpawnTime > CurTime() then return false end
if ply.NextSpawnTime and ply.NextSpawnTime == -1 then return false end
if ply:GetMedicAnimation() != 0 then return false end
end)
-- if someone change job
hook.Add("OnPlayerChangedTeam", "OnPlayerChangedTeam.MedicMod", function(ply, bef, after)
if ConfigurationMedicMod.HealedOnChangingJob then
ply:SetBleeding( false )
ply:SetHeartAttack( false )
ply:SetPoisoned( false )
if ply:GetFractures() then
-- cure fractures
for k, v in pairs( ply:GetFractures() ) do
ply:SetFracture(false, k)
end
end
-- remove the death ragdoll
if IsValid( ply.DeathRagdoll ) then
if IsValid( ply.DeathRagdoll.Prop ) then
ply.DeathRagdoll.Prop:Remove()
end
ply.DeathRagdoll:Remove()
end
ply:UnSpectate()
else
timer.Simple( 1, function()
if ply:GetFractures() then
for k, v in pairs( ply:GetFractures() ) do
ply:SetFracture(true, k)
end
end
end)
end
if table.HasValue( ConfigurationMedicMod.MedicTeams, ply:Team() ) then
ply:MedicNotif(sentences["You're now a medic, get help with"][lang].." !"..ConfigurationMedicMod.MedicCommand)
end
end)

View File

@@ -0,0 +1,214 @@
util.AddNetworkString("MedicMod.MedicMenu")
util.AddNetworkString("MedicMod.MedicStart")
util.AddNetworkString("MedicMod.BuyMedicEntity")
-- util.AddNetworkString("MedicMod.NotifiyPlayer")
util.AddNetworkString("MedicMod.PlayerStartAnimation")
util.AddNetworkString("MedicMod.ScanRadio")
util.AddNetworkString("MedicMod.Respawn")
util.AddNetworkString("MedicMod.TerminalMenu")
util.AddNetworkString("MedicMod.PlayerStopAnimation")
util.AddNetworkString("MedicMod.OpenMedicMenu")
util.AddNetworkString("MedicMod.BuyMedicJobEntity")
local spamCooldowns = {}
local interval = .1
local function spamCheck(pl, name)
if spamCooldowns[pl:SteamID()] then
if spamCooldowns[pl:SteamID()][name] then
if spamCooldowns[pl:SteamID()][name] > CurTime() then
return false
else
spamCooldowns[pl:SteamID()][name] = CurTime() + interval
return true
end
else
spamCooldowns[pl:SteamID()][name] = CurTime() + interval
return true
end
else
spamCooldowns[pl:SteamID()] = {}
spamCooldowns[pl:SteamID()][name] = CurTime() + interval
return true // They haven't sent shit :P
end
end
net.Receive("MedicMod.MedicStart", function( len, caller )
if not spamCheck( caller, "MedicMod.MedicStart" ) then return end
local ent = net.ReadEntity()
local health = caller:Health()
if caller:GetPos():DistToSqr(ent:GetPos()) > 22500 then return end
if health <= 0 then return end
if health >= caller:GetMaxHealth() and not caller:HaveFractures() then return end
local price = 0
if health < caller:GetMaxHealth() then
price = ( caller:GetMaxHealth() - health ) * ConfigurationMedicMod.HealthUnitPrice
end
if caller:HaveFractures() then
price = price + table.Count(caller.Fractures) * ConfigurationMedicMod.FractureRepairPrice
end
local bed = nil
local dist = -1
for k, v in pairs( ents.FindByClass("bed_medicmod") ) do
if IsValid( v.ragdoll ) then continue end
local ndist = v:GetPos():Distance( caller:GetPos() )
if dist == -1 or dist > ndist then
bed = v
dist = ndist
end
end
if not bed or not IsValid( bed ) then caller:MedicNotif(ConfigurationMedicMod.Sentences["You can't be healed because there is no free bed, retry later"][ConfigurationMedicMod.Language]) return end
if caller:getDarkRPVar("money") < price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
caller:addMoney( -price )
caller:StartOperation( bed )
end)
net.Receive("MedicMod.Respawn",function(len,ply)
if not spamCheck( ply, "MedicMod.Respawn" ) then return end
if ply.NextSpawnTime > CurTime() or ply:Alive() or ply.NextSpawnTime == -1 then return end
ply:Spawn()
end)
net.Receive("MedicMod.BuyMedicEntity", function( len, caller )
if not spamCheck( caller, "MedicMod.BuyMedicEntity" ) then return end
local key = net.ReadInt( 32 )
local ent = net.ReadEntity()
local cfg = ConfigurationMedicMod.Entities[key]
if not IsValid( ent ) then return end
if caller:GetPos():Distance(ent:GetPos()) > 200 then return end
if caller:getDarkRPVar("money") < cfg.price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
cfg.func( caller, cfg.ent, cfg.price )
end)
net.Receive("MedicMod.BuyMedicJobEntity", function( len, caller )
if not spamCheck( caller, "MedicMod.BuyMedicJobEntity" ) then return end
local key = net.ReadString()
local class = net.ReadString()
local spawnedtesttubes = caller.TestTubesSpawned or 0
local spawneddrugs = caller.DrugsSpawned or 0
local spawnedEnts = caller.spawnedEntsMedicMod or {}
if not table.HasValue( ConfigurationMedicMod.MedicTeams, caller:Team() ) then return end
if class == "test_tube_medicmod_s" and spawnedtesttubes < ConfigurationMedicMod.MaxTestTubesSpawnedWithTheShop then
if not ConfigurationMedicMod.Reagents[key] then return end
local price = ConfigurationMedicMod.Reagents[key].price
if caller:getDarkRPVar("money") < price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
caller:addMoney( -price )
local ent = ents.Create("test_tube_medicmod")
ent:SetPos(caller:GetPos() + caller:GetAngles():Forward() * 30 + caller:GetAngles():Up() * 20 )
ent:SetProduct(key)
ent:Spawn()
if CPPI then
ent:CPPISetOwner(caller)
end
undo.Create( ConfigurationMedicMod.Sentences["Test tube"][ConfigurationMedicMod.Language] )
undo.AddEntity( ent )
undo.SetPlayer( caller )
undo.Finish()
ent.TestTubeSpawner = caller
caller.TestTubesSpawned = spawnedtesttubes + 1 or 1
elseif class == "test_tube_medicmod_s" and spawnedtesttubes >= ConfigurationMedicMod.MaxTestTubesSpawnedWithTheShop then
caller:MedicNotif(ConfigurationMedicMod.Sentences["You've reached the limit of"][ConfigurationMedicMod.Language].." "..ConfigurationMedicMod.Sentences["Test tube"][ConfigurationMedicMod.Language])
elseif class == "drug_medicmod_s" and spawneddrugs < ConfigurationMedicMod.MaxDrugsSpawnedWithTheShop then
if not ConfigurationMedicMod.Drugs[key] then return end
local price = ConfigurationMedicMod.Drugs[key].price
if caller:getDarkRPVar("money") < price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
caller:addMoney( -price )
local ent = ents.Create("drug_medicmod")
ent:SetPos(caller:GetPos() + caller:GetAngles():Forward() * 30 + caller:GetAngles():Up() * 20)
ent:Spawn()
ent:SetDrug(key)
if CPPI then
ent:CPPISetOwner(caller)
end
undo.Create( ConfigurationMedicMod.Sentences["Drugs"][ConfigurationMedicMod.Language] )
undo.AddEntity( ent )
undo.SetPlayer( caller )
undo.Finish()
ent.DrugSpawner = caller
caller.DrugsSpawned = spawneddrugs + 1 or 1
elseif class == "drug_medicmod_s" and spawneddrugs >= ConfigurationMedicMod.MaxDrugsSpawnedWithTheShop then
caller:MedicNotif(ConfigurationMedicMod.Sentences["You've reached the limit of"][ConfigurationMedicMod.Language].." "..ConfigurationMedicMod.Sentences["Drugs"][ConfigurationMedicMod.Language])
elseif key == "entity" and ConfigurationMedicMod.MedicShopEntities[class] and (spawnedEnts[class] or 0) < ConfigurationMedicMod.MedicShopEntities[class].max then
local cfg = ConfigurationMedicMod.MedicShopEntities[class]
if caller:getDarkRPVar("money") < cfg.price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
caller:addMoney( -cfg.price )
local ent = ents.Create(class)
ent:SetPos(caller:GetPos() + caller:GetAngles():Forward() * 30 + caller:GetAngles():Up() * 20 )
ent:Spawn()
if CPPI then
ent:CPPISetOwner(caller)
end
undo.Create( (cfg.name or "Medic mod entity") )
undo.AddEntity( ent )
undo.SetPlayer( caller )
undo.Finish()
caller.spawnedEntsMedicMod = caller.spawnedEntsMedicMod or {}
caller.spawnedEntsMedicMod[class] = caller.spawnedEntsMedicMod[class] or 0
caller.spawnedEntsMedicMod[class] = caller.spawnedEntsMedicMod[class] + 1
elseif key == "entity" and ConfigurationMedicMod.MedicShopEntities[class] and (spawnedEnts[class] or 0) >= ConfigurationMedicMod.MedicShopEntities[class].max then
caller:MedicNotif(ConfigurationMedicMod.Sentences["You've reached the limit of"][ConfigurationMedicMod.Language].." "..ConfigurationMedicMod.MedicShopEntities[class].name)
elseif key == "weapon" and ConfigurationMedicMod.MedicShopWeapons[class] then
if caller:HasWeapon( class ) then caller:MedicNotif(ConfigurationMedicMod.Sentences["You already carry this element on you"][ConfigurationMedicMod.Language]) return end
local cfg = ConfigurationMedicMod.MedicShopWeapons[class]
if caller:getDarkRPVar("money") < cfg.price then caller:MedicNotif(ConfigurationMedicMod.Sentences["You don't have enough money"][ConfigurationMedicMod.Language]) return end
caller:addMoney( -cfg.price )
caller:Give(class)
end
end)

View File

@@ -0,0 +1,35 @@
-- local meta = FindMetaTable( "Player" )
-- function meta:MedicNotif( msg, time )
-- local ply = self
-- if not IsValid( ply ) or not ply:IsPlayer() then return end
-- msg = msg or ""
-- time = time or 5
-- net.Start("MedicMod.NotifiyPlayer")
-- net.WriteString( msg )
-- net.WriteInt( time, 32 )
-- net.Send( ply )
-- end
local meta = FindMetaTable( "Player" )
util.AddNetworkString("MedicMod:NotifyPlayer")
function meta:MedicNotif( msg, time )
local ply = self
if not IsValid( ply ) or not ply:IsPlayer() then return end
msg = msg or ""
time = time or 5
net.Start("MedicMod:NotifyPlayer")
net.WriteString( msg )
net.WriteInt( time, 32 )
net.Send( ply )
end