Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---- Corpse functions
- -- namespaced because we have no ragdoll metatable
- CORPSE = {}
- include("corpse_shd.lua")
- --- networked data abstraction layer
- local dti = CORPSE.dti
- function CORPSE.SetFound(rag, state)
- --rag:SetNWBool("found", state)
- rag:SetDTBool(dti.BOOL_FOUND, state)
- if state then --custom for recreation
- rag.idtime = CurTime()
- end
- end
- function CORPSE.SetPlayerNick(rag, ply_or_name)
- -- don't have datatable strings, so use a dt entity for common case of
- -- still-connected player, and if the player is gone, fall back to nw string
- local name = ply_or_name
- if IsValid(ply_or_name) then
- name = ply_or_name:Nick()
- rag:SetDTEntity(dti.ENT_PLAYER, ply_or_name)
- end
- rag:SetNWString("nick", name)
- end
- function CORPSE.SetCredits(rag, credits)
- --rag:SetNWInt("credits", credits)
- rag:SetDTInt(dti.INT_CREDITS, credits)
- end
- --- ragdoll creation and search
- -- If detective mode, announce when someone's body is found
- local bodyfound = CreateConVar("ttt_announce_body_found", "1")
- --custom for auto-iding slain bodies
- local function IdentifySlainBody(rag, slain)
- if GetRoundState() == ROUND_PREP then
- CORPSE.SetFound(rag, true)
- return
- end
- local nick = CORPSE.GetPlayerNick(rag, "")
- local traitor = (rag.was_role == ROLE_TRAITOR)
- -- Announce body
- if bodyfound:GetBool() and not CORPSE.GetFound(rag, false) then
- local roletext = nil
- local roletext2 = nil
- local role = rag.was_role
- if role == ROLE_TRAITOR then
- roletext = "body_found_t"
- roletext2 = "traitor"
- elseif role == ROLE_DETECTIVE then
- roletext = "body_found_d"
- roletext2 = "detective"
- else
- roletext = "body_found_i"
- roletext2 = "innocent"
- end
- LANG.Msg("body_tslay", {victim = nick})
- end
- if not CORPSE.GetFound(rag, false) then
- -- will return either false or a valid ply
- local deadply = player.GetByUniqueID(rag.uqid)
- if deadply then
- deadply:SetNWBool("body_found", true)
- if traitor then
- -- update innocent's list of traitors
- SendConfirmedTraitors(GetInnocentFilter(false))
- end
- end
- CORPSE.SetFound(rag, true)
- end
- end
- local function IdentifyBody(ply, rag)
- if not ply:IsTerror() then return end
- -- simplified case for those who die and get found during prep
- if GetRoundState() == ROUND_PREP then
- CORPSE.SetFound(rag, true)
- return
- end
- local finder = ply:Nick()
- local nick = CORPSE.GetPlayerNick(rag, "")
- local traitor = (rag.was_role == ROLE_TRAITOR)
- -- Announce body
- if bodyfound:GetBool() and not CORPSE.GetFound(rag, false) then
- local roletext = nil
- local roletext2 = nil
- local role = rag.was_role
- if role == ROLE_TRAITOR then
- roletext = "body_found_t"
- roletext2 = "traitor"
- elseif role == ROLE_DETECTIVE then
- roletext = "body_found_d"
- roletext2 = "detective"
- else
- roletext = "body_found_i"
- roletext2 = "innocent"
- end
- LANG.Msg("body_found", {finder = finder,
- victim = nick,
- role = LANG.Param(roletext)})
- if DMG_LOG then
- AddToDamageLog({DMG_LOG.BODY_FOUND, finder, ply:GetRoleString(), nick, roletext2, {ply:SteamID(), CORPSE.GetPlayerID(rag, "")}})
- end
- end
- -- Register find
- if not CORPSE.GetFound(rag, false) then
- -- will return either false or a valid ply
- local deadply = player.GetByUniqueID(rag.uqid)
- if deadply then
- deadply:SetNWBool("body_found", true)
- if traitor then
- -- update innocent's list of traitors
- SendConfirmedTraitors(GetInnocentFilter(false))
- end
- SCORE:HandleBodyFound(ply, deadply)
- end
- CORPSE.SetFound(rag, true)
- else
- -- re-set because nwvars are unreliable
- --CORPSE.SetFound(rag, true)
- --CORPSE.SetPlayerNick(rag, nick)
- end
- -- Handle kill list
- for k, vicid in pairs(rag.kills) do
- -- filter out disconnected
- local vic = player.GetByUniqueID(vicid)
- -- is this an unconfirmed dead?
- if IsValid(vic) and (not vic:GetNWBool("body_found", false)) then
- LANG.Msg("body_confirm", {finder = finder, victim = vic:Nick()})
- -- update scoreboard status
- vic:SetNWBool("body_found", true)
- -- however, do not mark body as found. This lets players find the
- -- body later and get the benefits of that
- --local vicrag = vic.server_ragdoll
- --CORPSE.SetFound(vicrag, true)
- end
- end
- end
- -- Covert identify concommand for traitors
- local function IdentifyCommand(ply, cmd, args)
- if not IsValid(ply) then return end
- if #args != 2 then return end
- local eidx = tonumber(args[1])
- local id = tonumber(args[2])
- if (not eidx) or (not id) then return end
- if (not ply.search_id) or ply.search_id.id != id or ply.search_id.eidx != eidx then
- ply.search_id = nil
- return
- end
- ply.search_id = nil
- local rag = Entity(eidx)
- if IsValid(rag) and rag:GetPos():Distance(ply:GetPos()) < 128 then
- if not CORPSE.GetFound(rag, false) then
- IdentifyBody(ply, rag)
- end
- end
- end
- concommand.Add("ttt_confirm_death", IdentifyCommand)
- -- Call detectives to a corpse
- local function CallDetective(ply, cmd, args)
- if not IsValid(ply) then return end
- if #args != 1 then return end
- if not ply:IsActive() then return end
- local eidx = tonumber(args[1])
- if not eidx then return end
- local rag = Entity(eidx)
- if IsValid(rag) and rag:GetPos():Distance(ply:GetPos()) < 128 then
- if CORPSE.GetFound(rag, false) then
- -- show indicator to detectives
- SendUserMessage("corpse_call", GetDetectiveFilter(true), rag:GetPos())
- LANG.Msg("body_call", {player = ply:Nick(),
- victim = CORPSE.GetPlayerNick(rag, "someone")})
- else
- LANG.Msg(ply, "body_call_error")
- end
- end
- end
- concommand.Add("ttt_call_detective", CallDetective)
- -- Send a usermessage to client containing search results
- function CORPSE.ShowSearch(ply, rag, covert, long_range)
- if not IsValid(ply) or not IsValid(rag) then return end
- if rag:IsOnFire() then
- LANG.Msg(ply, "body_burning")
- return
- end
- -- init a heap of data we'll be sending
- local nick = CORPSE.GetPlayerNick(rag)
- local traitor = (rag.was_role == ROLE_TRAITOR)
- local role = rag.was_role
- local eq = rag.equipment or EQUIP_NONE
- local c4 = rag.bomb_wire or -1
- local dmg = rag.dmgtype or DMG_GENERIC
- local wep = rag.dmgwep or ""
- local words = rag.last_words or ""
- local hshot = rag.was_headshot or false
- local dtime = rag.time or 0
- local owner = player.GetByUniqueID(rag.uqid)
- owner = IsValid(owner) and owner:EntIndex() or -1
- -- basic sanity check
- if nick == nil or eq == nil or role == nil then return end
- if DetectiveMode() and not covert then
- IdentifyBody(ply, rag)
- end
- local credits = CORPSE.GetCredits(rag, 0)
- if ply:IsActiveSpecial() and credits > 0 and (not long_range) then
- LANG.Msg(ply, "body_credits", {num = credits})
- ply:AddCredits(credits)
- CORPSE.SetCredits(rag, 0)
- ServerLog(ply:Nick() .. " took " .. credits .. " credits from the body of " .. nick .. "\n")
- if DMG_LOG then
- AddToDamageLog({DMG_LOG.FOUND_CREDITS, ply:Nick(), ply:GetRoleString(), nick, credits, {ply:SteamID(), CORPSE.GetPlayerID(rag, "")}})
- end
- SCORE:HandleCreditFound(ply, nick, credits)
- end
- -- time of death relative to current time (saves bits)
- if dtime != 0 then
- dtime = math.Round(CurTime() - dtime)
- end
- -- identifier so we know whether a ttt_confirm_death was legit
- ply.search_id = { eidx = rag:EntIndex(), id = rag:EntIndex() + dtime }
- -- time of dna sample decay relative to current time
- local stime = 0
- if rag.killer_sample then
- stime = math.max(0, rag.killer_sample.t - CurTime())
- end
- -- build list of people this traitor killed
- local kill_entids = {}
- for k, vicid in pairs(rag.kills) do
- -- also send disconnected players as a marker
- local vic = player.GetByUniqueID(vicid)
- table.insert(kill_entids, IsValid(vic) and vic:EntIndex() or -1)
- end
- local lastid = -1
- if rag.lastid and ply:IsActiveDetective() then
- -- if the person this victim last id'd has since disconnected, send -1 to
- -- indicate this
- lastid = IsValid(rag.lastid.ent) and rag.lastid.ent:EntIndex() or -1
- end
- -- If found by detective, send to all, else just the finder
- local receiver = ply
- if ply:IsActiveDetective() then receiver = nil end
- -- Send a message with basic info
- umsg.Start("ragsrch", receiver)
- umsg.Short(rag:EntIndex()) -- 2 bytes
- umsg.Short(owner) -- 2 bytes
- umsg.String(nick)
- umsg.Short(eq) -- 2 bytes
- umsg.Char(role) -- 1 byte
- umsg.Char(c4) -- 1 byte
- umsg.Long(dmg) -- 4 bytes, enum goes high
- umsg.String(wep) -- 2 bytes(?)
- umsg.Bool(hshot) -- 1 byte
- umsg.Short(dtime) -- 2 bytes
- umsg.Short(stime) -- 2 bytes
- umsg.Char(#kill_entids) -- 1 byte + (2 * #kills) bytes
- for k, idx in pairs(kill_entids) do
- -- might be possible to use chars here but this is safer
- umsg.Short(idx)
- end
- umsg.Short(lastid)
- -- Who found this, so if we get this from a detective we can decide not to
- -- show a window
- umsg.Short(ply:EntIndex())
- -- Will there be a last words umsg coming up?
- umsg.Bool(words != "") -- 1b
- umsg.End()
- if words != "" then
- -- umsgs only have 128 bytes of room, so if last words is really long we
- -- have to truncate
- if string.len(words) > 127 then
- words = string.sub(words, -127)
- end
- umsg.Start("ragsrch_lw", ply)
- umsg.String(words)
- umsg.End()
- end
- end
- -- Returns a sample for use in dna scanner if the kill fits certain constraints,
- -- else returns nil
- local function GetKillerSample(victim, attacker, dmg)
- -- only guns and melee damage, not explosions
- if not (dmg:IsBulletDamage() or dmg:IsDamageType(DMG_SLASH) or dmg:IsDamageType(DMG_CLUB)) then
- return nil
- end
- if not (IsValid(victim) and IsValid(attacker) and attacker:IsPlayer()) then return end
- -- NPCs for which a player is damage owner (meaning despite the NPC dealing
- -- the damage, the attacker is a player) should not cause the player's DNA to
- -- end up on the corpse.
- local infl = dmg:GetInflictor()
- if IsValid(infl) and infl:IsNPC() then return end
- local dist = victim:GetPos():Distance(attacker:GetPos())
- if dist > GetConVarNumber("ttt_killer_dna_range") then return nil end
- local sample = {}
- sample.killer = attacker
- sample.killer_uid = attacker:UniqueID()
- sample.victim = victim
- sample.t = CurTime() + (-1 * (0.019 * dist)^2 + GetConVarNumber("ttt_killer_dna_basetime"))
- return sample
- end
- local crimescene_keys = {"Fraction", "HitBox", "Normal", "HitPos", "StartPos"}
- local poseparams = {
- "aim_yaw", "move_yaw", "aim_pitch",
- -- "spine_yaw", "head_yaw", "head_pitch"
- };
- local function GetSceneDataFromPlayer(ply)
- local data = {
- pos = ply:GetPos(),
- ang = ply:GetAngles(),
- sequence = ply:GetSequence(),
- cycle = ply:GetCycle()
- };
- for _, param in pairs(poseparams) do
- data[param] = ply:GetPoseParameter(param)
- end
- return data
- end
- local function GetSceneDataFromCorpse(rag)
- local data = {
- pos = rag:GetPos()
- };
- return data
- end
- local function GetSceneData(victim, attacker, dmginfo)
- -- only for guns for now, hull traces don't work well etc
- if not dmginfo:IsBulletDamage() then return end
- local scene = {}
- if victim.hit_trace then
- scene.hit_trace = table.CopyKeys(victim.hit_trace, crimescene_keys)
- else
- return scene
- end
- scene.victim = GetSceneDataFromPlayer(victim)
- if IsValid(attacker) and attacker:IsPlayer() then
- scene.killer = GetSceneDataFromPlayer(attacker)
- local att = attacker:LookupAttachment("anim_attachment_RH")
- local angpos = attacker:GetAttachment(att)
- if not angpos then
- scene.hit_trace.StartPos = attacker:GetShootPos()
- else
- scene.hit_trace.StartPos = angpos.Pos
- end
- end
- return scene
- end
- function GetDamageLogSceneData(victim, attacker, dmginfo)
- if (dmginfo:IsBulletDamage()) or (dmginfo:GetInflictor():GetClass() == "weapon_ttt_knife") then --only works on bullet or knife deaths
- local scene = {}
- if victim.hit_trace then
- scene.hit_trace = table.CopyKeys(victim.hit_trace, crimescene_keys)
- else
- return scene
- end
- scene.victim = GetSceneDataFromPlayer(victim)
- scene.victim["1"] = 2
- scene.victim["2"] = victim:Nick() .. " (" .. victim:GetRoleString() .. ")"
- if IsValid(attacker) and attacker:IsPlayer() then
- scene.killer = GetSceneDataFromPlayer(attacker)
- local att = attacker:LookupAttachment("anim_attachment_RH")
- local angpos = attacker:GetAttachment(att)
- if not angpos then
- scene.hit_trace.StartPos = attacker:GetShootPos()
- else
- scene.hit_trace.StartPos = angpos.Pos
- end
- scene.hit_trace.Fraction = math.Round(scene.hit_trace.Fraction, 3)
- scene.killer["1"] = 1
- scene.killer["2"] = attacker:Nick() .. " (" .. attacker:GetRoleString() .. ")"
- scene.look = attacker:EyeAngles()
- scene.look.p = math.Round(scene.look.p, 2)
- scene.look.y = math.Round(scene.look.y, 2)
- scene.look.r = math.Round(scene.look.r, 2)
- if dmginfo:GetInflictor():GetClass() == "weapon_ttt_knife" then scene.knife = true end
- local count = 0
- for _,v in pairs(player.GetAll()) do
- if IsValid(v) and not v:IsSpec() and v != victim and v != attacker
- and (v:GetPos():Distance(victim:GetPos()) <= 700 or v:GetPos():Distance(attacker:GetPos()) <= 700) then --is within 700 units of either the victim or attacker
- count = count + 1
- local b = GetSceneDataFromPlayer(v)
- b["1"] = 3
- b["2"] = v:Nick() .. " (" .. v:GetRoleString() .. ")"
- scene["b" .. count] = b
- end
- end
- scene.by = count
- count = 0
- for _,v in pairs(ents.FindByClass("prop_ragdoll")) do
- if v.player_ragdoll and v.uqid != victim:UniqueID() and v.uqid != attacker:UniqueID()
- and (v:GetPos():Distance(victim:GetPos()) <= 500 or v:GetPos():Distance(attacker:GetPos()) <= 500) then --is within 500 units of either the victim or attacker
- if (CORPSE.GetFound(v, false) and ((CurTime() - v.idtime) >= 30)) then continue end --only include id'd bodies if they were id'd recently
- count = count + 1
- local b = GetSceneDataFromCorpse(v)
- b["1"] = (CORPSE.GetFound(v, false) and "ID'd " or "UnID'd ") .. "Body (died " .. math.Round(CurTime() - v.time, 1) .. "s before)"
- local rol
- if v.was_role == 0 then rol = "innocent" elseif v.was_role == 1 then rol = "traitor" else rol = "detective" end
- b["2"] = v.pnick .. " (" .. rol .. ")"
- if (CORPSE.GetFound(v, false)) then
- b["3"] = "(identified " .. math.Round(CurTime() - v.idtime, 1) .. "s before)"
- end
- scene["c" .. count] = b
- end
- end
- scene.co = count
- end
- return scene
- end
- end
- local rag_collide = CreateConVar("ttt_ragdoll_collide", "0")
- function DMMakeDeathRagDoll(pos, ang, mdl, skin, color, mat, dmgammount, dmgtype, dmgpos, dmgforce, onfire, npcvel, isnpc, isply, ply, attacker, vel, dmginfo)
- if dmgtype != 67108865 and mdl != nil then //damage type 67108865 is from a combineball (DMG_DISSOLVE)
- ragcont = ents.Create("dismemberment_ragdoll")//Spawn Ragdoll Controller
- ragcont:SetPos(pos)
- ragcont:Spawn()
- local ragdoll = ents.Create("prop_ragdoll")
- ragdoll.pnick = ply:Nick()
- ragdoll.ShouldGib = true
- ragdoll:SetPos(pos)
- ragdoll:SetAngles(ang)
- ragdoll:SetModel(mdl)
- ragdoll:Spawn()
- ragdoll:SetSkin(skin)
- ragdoll:SetColor(color)
- ragdoll:SetMaterial(mat)
- ragdoll:SetNetworkedBool("IsDismemberable", true)
- ragdoll:SetNetworkedBool("IsLimb", false)
- ragcont:SetNoDraw(true)
- ragcont:SetNetworkedEntity("dismembermentragdoll", ragdoll)
- ragcont:SetParent(ragdoll)
- ragcont:AddEffects(EF_BONEMERGE)
- ragdoll.player_ragdoll = true
- ragdoll.uqid = ply:UniqueID()
- -- network data
- CORPSE.SetPlayerNick(ragdoll, ply)
- CORPSE.SetFound(ragdoll, false)
- CORPSE.SetCredits(ragdoll, ply:GetCredits())
- -- if someone searches this body they can find info on the victim and the
- -- death circumstances
- ragdoll.equipment = ply:GetEquipmentItems()
- ragdoll.was_role = ply:GetRole()
- ragdoll.bomb_wire = ply.bomb_wire
- ragdoll.dmgtype = dmgtype
- local wep = util.WeaponFromDamage(dmginfo)
- ragdoll.dmgwep = IsValid(wep) and wep:GetClass() or ""
- ragdoll.was_headshot = (ply.was_headshot and dmginfo:IsBulletDamage())
- ragdoll.time = CurTime()
- ragdoll.kills = table.Copy(ply.kills)
- ragdoll.killer_sample = GetKillerSample(ply, attacker, dmginfo)
- -- crime scene data
- ragdoll.scene = GetSceneData(ply, attacker, dmginfo)
- for bone = 0, ragdoll:GetPhysicsObjectCount() do
- local phys = ragdoll:GetPhysicsObjectNum(bone)
- local plybone = ragdoll:TranslatePhysBoneToBone(bone)
- local bonepos, boneang = ply:GetBonePosition(plybone)
- if IsValid(phys) and IsValid(ply) then
- phys:SetPos(bonepos)
- phys:SetAngles(boneang)
- end
- if IsValid(phys) then
- phys:AddVelocity(vel)
- end
- end
- /*
- local ragdoll = ents.Create("prop_ragdoll")
- ragdoll.ShouldGib = true
- //ragdoll.blood = {}
- ragdoll:SetPos(pos)
- ragdoll:SetAngles(ang)
- ragdoll:SetModel(mdl)
- ragdoll:Spawn()
- ragdoll:SetSkin(skin)
- ragdoll:SetColor(color)
- ragdoll:SetMaterial(mat)
- ragdoll:SetNetworkedBool("IsDismemberable", true)
- */
- if rag_collide:GetBool() then
- ragdoll:SetCollisionGroup(COLLISION_GROUP_NONE)
- else
- ragdoll:SetCollisionGroup(COLLISION_GROUP_WEAPON)
- end
- if isply then
- ply:SetNetworkedEntity("PlayerDeathRag" .. ply:Deaths(), ragdoll)
- end
- //Limb Health
- healthmult = GetConVar("dismemberment_raghealthmult"):GetInt()
- ragdoll.hHead = 50 * healthmult
- ragdoll.hRcalf = 50 * healthmult
- ragdoll.hRUcalf = 50 * healthmult --vortigaunt only middle leg bone
- ragdoll.hRthigh = 50 * healthmult
- ragdoll.hRuparm = 50 * healthmult
- ragdoll.hRforearm = 50 * healthmult
- ragdoll.hRhand = 25 * healthmult
- ragdoll.hRfoot = 25 * healthmult
- ragdoll.hLcalf = 50 * healthmult
- ragdoll.hLUcalf = 50 * healthmult --vortigaunt only middle leg bone
- ragdoll.hLthigh = 50 * healthmult
- ragdoll.hLuparm = 50 * healthmult
- ragdoll.hLforearm = 50 * healthmult
- ragdoll.hLhand = 25 * healthmult
- ragdoll.hLfoot = 25 * healthmult
- ragdoll.hpelvis = 50 * healthmult
- ragdoll.hbody = 100 * healthmult
- //Body Types
- if mdl == "models/vortigaunt.mdl" then
- ragdoll.bodytype = "vortigaunt"
- ragdoll.goretype = 2 --Alien
- ragdoll.bHead = "ValveBiped.head"
- ragdoll.bRcalf = "ValveBiped.leg_bone3_r"
- ragdoll.bRUcalf = "ValveBiped.leg_bone2_r" --vortigaunt only middle leg bone
- ragdoll.bRthigh = "ValveBiped.leg_bone1_r"
- ragdoll.bRuparm = "ValveBiped.arm1_r"
- ragdoll.bRforearm = "ValveBiped.arm2_r"
- ragdoll.bRhand = "ValveBiped.hand1_r"
- ragdoll.bRfoot = "ValveBiped.bip01_r_foot"
- ragdoll.bLcalf = "ValveBiped.leg_bone3_l"
- ragdoll.bLUcalf = "ValveBiped.leg_bone2_l" --vortigaunt only middle leg bone
- ragdoll.bLthigh = "ValveBiped.leg_bone1_l"
- ragdoll.bLuparm = "ValveBiped.arm1_l"
- ragdoll.bLforearm = "ValveBiped.arm2_l"
- ragdoll.bLhand = "ValveBiped.hand1_l"
- ragdoll.bLfoot = "ValveBiped.bip01_l_foot"
- ragdoll.bpelvis = "ValveBiped.hips"
- ragdoll.bbody = "ValveBiped.spine2"
- elseif mdl == "models/headcrabclassic.mdl" then
- ragdoll.bodytype = "generic"
- ragdoll.goretype = 2 --Alien
- ragdoll.hbody = 35 * healthmult
- ragdoll.bbody = "headcrabclassic.bodycontrol"
- ragdoll.bRcalf = "headcrabclassic.clafr_bone"
- ragdoll.bRthigh = "headcrabclassic.thighr_bone"
- ragdoll.bRuparm = "headcrabclassic.upperarmr_bone"
- ragdoll.bRforearm = "headcrabclassic.forearmr_bone"
- ragdoll.bLcalf = "headcrabclassic.clafl_bone"
- ragdoll.bLthigh = "headcrabclassic.thighl_bone"
- ragdoll.bLuparm = "headcrabclassic.upperarml_bone"
- ragdoll.bLforearm = "headcrabclassic.forearml_bone"
- //unused
- ragdoll.bpelvis = "nil"
- ragdoll.bHead = "nil"
- ragdoll.bRUcalf = "nil"
- ragdoll.bLUcalf = "nil"
- ragdoll.bRhand = "nil"
- ragdoll.bLhand = "nil"
- ragdoll.bRfoot = "nil"
- ragdoll.bLfoot = "nil"
- elseif mdl == "models/headcrab.mdl" then
- ragdoll.bodytype = "generic"
- ragdoll.goretype = 2 --Alien
- ragdoll.hbody = 35 * healthmult
- ragdoll.bbody = "hcfast.body"
- ragdoll.bRcalf = "hcfast.leg_bone2_r"
- ragdoll.bRthigh = "hcfast.leg_bone1_r"
- ragdoll.bRuparm = "hcfast.arm_bone1_r"
- ragdoll.bRforearm = "hcfast.arm_bone2_r"
- ragdoll.bLcalf = "hcfast.leg_bone2_l"
- ragdoll.bLthigh = "hcfast.leg_bone1_l"
- ragdoll.bLuparm = "hcfast.arm_bone1_l"
- ragdoll.bLforearm = "hcfast.arm_bone2_l"
- //unused
- ragdoll.bpelvis = "nil"
- ragdoll.bHead = "nil"
- ragdoll.bRUcalf = "nil"
- ragdoll.bLUcalf = "nil"
- ragdoll.bRhand = "nil"
- ragdoll.bLhand = "nil"
- ragdoll.bRfoot = "nil"
- ragdoll.bLfoot = "nil"
- elseif mdl == "models/headcrabblack.mdl" then
- ragdoll.bodytype = "generic"
- ragdoll.goretype = 2 --Alien
- ragdoll.hbody = 35 * healthmult
- ragdoll.bbody = "hcblack.body"
- ragdoll.bRcalf = "hcblack.leg_bone2_r"
- ragdoll.bRthigh = "hcblack.leg_bone1_r"
- ragdoll.bRuparm = "hcblack.arm_bone1_r"
- ragdoll.bRforearm = "hcblack.arm_bone2_r"
- ragdoll.bLcalf = "hcblack.leg_bone2_l"
- ragdoll.bLthigh = "hcblack.leg_bone1_l"
- ragdoll.bLuparm = "hcblack.arm_bone1_l"
- ragdoll.bLforearm = "hcblack.arm_bone2_l"
- //unused
- ragdoll.bpelvis = "nil"
- ragdoll.bHead = "nil"
- ragdoll.bRUcalf = "nil"
- ragdoll.bLUcalf = "nil"
- ragdoll.bRhand = "nil"
- ragdoll.bLhand = "nil"
- ragdoll.bRfoot = "nil"
- ragdoll.bLfoot = "nil"
- else
- ragdoll.bodytype = "generic"
- ragdoll.goretype = 1 --Human
- ragdoll.bHead = "ValveBiped.Bip01_Head1"
- ragdoll.bRcalf = "ValveBiped.Bip01_R_Calf"
- ragdoll.bRUcalf = "nil"
- ragdoll.bRthigh = "ValveBiped.Bip01_R_Thigh"
- ragdoll.bRuparm = "ValveBiped.Bip01_R_UpperArm"
- ragdoll.bRforearm = "ValveBiped.Bip01_R_Forearm"
- ragdoll.bRhand = "ValveBiped.Bip01_R_Hand"
- ragdoll.bRfoot = "ValveBiped.Bip01_R_Foot"
- ragdoll.bLcalf = "ValveBiped.Bip01_L_Calf"
- ragdoll.bLUcalf = "nil"
- ragdoll.bLthigh = "ValveBiped.Bip01_L_Thigh"
- ragdoll.bLuparm = "ValveBiped.Bip01_L_UpperArm"
- ragdoll.bLforearm = "ValveBiped.Bip01_L_Forearm"
- ragdoll.bLhand = "ValveBiped.Bip01_L_Hand"
- ragdoll.bLfoot = "ValveBiped.Bip01_L_Foot"
- ragdoll.bpelvis = "ValveBiped.Bip01_Pelvis"
- ragdoll.bbody = "ValveBiped.Bip01_Spine2"
- end
- //Limbs
- if ragdoll:LookupBone(ragdoll.bHead) != nil then
- ragdoll.Head = ragdoll:LookupBone(ragdoll.bHead)
- else
- ragdoll.Head = -1
- end
- if ragdoll:LookupBone(ragdoll.bRcalf) != nil then
- ragdoll.Rcalf = ragdoll:LookupBone(ragdoll.bRcalf)
- else
- ragdoll.Rcalf = -1
- end
- if ragdoll:LookupBone(ragdoll.bRthigh) != nil then
- ragdoll.Rthigh = ragdoll:LookupBone(ragdoll.bRthigh)
- else
- ragdoll.Rthigh = -1
- end
- if ragdoll:LookupBone(ragdoll.bRuparm) != nil then
- ragdoll.Ruparm = ragdoll:LookupBone(ragdoll.bRuparm)
- else
- ragdoll.Ruparm = -1
- end
- if ragdoll:LookupBone(ragdoll.bRforearm) != nil then
- ragdoll.Rforearm = ragdoll:LookupBone(ragdoll.bRforearm)
- else
- ragdoll.Rforearm = -1
- end
- if ragdoll:LookupBone(ragdoll.bRhand) != nil then
- ragdoll.Rhand = ragdoll:LookupBone(ragdoll.bRhand)
- else
- ragdoll.Rhand = -1
- end
- if ragdoll:LookupBone(ragdoll.bRfoot) != nil then
- ragdoll.Rfoot = ragdoll:LookupBone(ragdoll.bRfoot)
- else
- ragdoll.Rfoot = -1
- end
- if ragdoll:LookupBone(ragdoll.bLcalf) != nil then
- ragdoll.Lcalf = ragdoll:LookupBone(ragdoll.bLcalf)
- else
- ragdoll.Lcalf = -1
- end
- if ragdoll:LookupBone(ragdoll.bLthigh) != nil then
- ragdoll.Lthigh = ragdoll:LookupBone(ragdoll.bLthigh)
- else
- ragdoll.Lthigh = -1
- end
- if ragdoll:LookupBone(ragdoll.bLuparm) != nil then
- ragdoll.Luparm = ragdoll:LookupBone(ragdoll.bLuparm)
- else
- ragdoll.Luparm = -1
- end
- if ragdoll:LookupBone(ragdoll.bLforearm) != nil then
- ragdoll.Lforearm = ragdoll:LookupBone(ragdoll.bLforearm)
- else
- ragdoll.Lforearm = -1
- end
- if ragdoll:LookupBone(ragdoll.bLhand) != nil then
- ragdoll.Lhand = ragdoll:LookupBone(ragdoll.bLhand)
- else
- ragdoll.Lhand = -1
- end
- if ragdoll:LookupBone(ragdoll.bLfoot) != nil then
- ragdoll.Lfoot = ragdoll:LookupBone(ragdoll.bLfoot)
- else
- ragdoll.Lfoot = -1
- end
- if ragdoll:LookupBone(ragdoll.bpelvis) != nil then
- ragdoll.pelvis = ragdoll:LookupBone(ragdoll.bpelvis)
- else
- ragdoll.pelvis = -1
- end
- if ragdoll:LookupBone(ragdoll.bRUcalf) != nil then
- ragdoll.RUcalf = ragdoll:LookupBone(ragdoll.bRUcalf)
- else
- ragdoll.RUcalf = -1
- end
- if ragdoll:LookupBone(ragdoll.bLUcalf) != nil then
- ragdoll.LUcalf = ragdoll:LookupBone(ragdoll.bLUcalf)
- else
- ragdoll.LUcalf = -1
- end
- //Body
- if ragdoll:LookupBone(ragdoll.bbody) != nil then
- ragdoll.body = ragdoll:LookupBone(ragdoll.bbody)
- else
- ragdoll.body = -1
- end
- //Limb Networking (so the client knows)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Head, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rcalf, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.RUcalf, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rthigh, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Ruparm, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rforearm, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rhand, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rfoot, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lcalf, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.LUcalf, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lthigh, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Luparm, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lforearm, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lhand, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lfoot, false)
- ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.pelvis, false)
- --body dosn't need to be included (these are for drip effects so when the bodys gone there wont be any)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Head, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rcalf, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.RUcalf, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rthigh, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Ruparm, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rforearm, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rhand, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rfoot, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lcalf, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.LUcalf, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lthigh, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Luparm, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lforearm, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lhand, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lfoot, false)
- ragdoll:SetNWBool("boneisgibbed" .. ragdoll.pelvis, false)
- //Apply Kill Damage
- local physbone = DMGetClosestPhysBone(ragdoll, dmgpos)
- local bone = ragdoll:TranslatePhysBoneToBone(physbone)
- local phys = ragdoll:GetPhysicsObjectNum(physbone)
- if dmgtype != 6144 and dmgtype != 32 then
- if bone != ragdoll.body and bone != ragdoll.pelvis and bone != ragdoll.Head then
- local dmginfo = DamageInfo()
- dmginfo:SetDamage(dmgammount)
- dmginfo:SetDamageType(dmgtype)
- dmginfo:SetDamagePosition(dmgpos)
- dmginfo:SetDamageForce(dmgforce)
- ragdoll:TakeDamageInfo(dmginfo)
- phys:AddVelocity(dmgforce)
- elseif bone == ragdoll.body or bone == ragdoll.pelvis or bone == ragdoll.Head then
- local dmginfo = DamageInfo()
- dmginfo:SetDamage(dmgammount)
- //overides the scaled damage
- dmginfo:SetDamageType(dmgtype)
- dmginfo:SetDamagePosition(dmgpos)
- dmginfo:SetDamageForce(dmgforce)
- ragdoll:TakeDamageInfo(dmginfo)
- phys:AddVelocity(dmgforce)
- end
- end
- if dmgtype == 32 and dmgammount > 50 then
- local dmginfo = DamageInfo()
- dmginfo:SetDamageType(32)
- dmginfo:SetDamage(1000000)
- dmginfo:SetDamagePosition(dmgpos)
- dmginfo:SetDamageForce(dmgforce)
- ragdoll:TakeDamageInfo(dmginfo)
- ragdoll.hHead = 0
- end
- if onfire then
- ragdoll:Ignite(math.random(8, 10), 15)
- end
- if isnpc and IsValid(ragdoll:GetPhysicsObject()) then
- ragdoll:GetPhysicsObject():SetVelocity(npcvel)
- local bones = ragdoll:GetPhysicsObjectCount()
- for i = 1, bones - 1 do
- local bone = ragdoll:GetPhysicsObjectNum(i)
- if IsValid(bone) then
- local bonepos, boneang = ply:GetBonePosition(ragdoll:TranslatePhysBoneToBone(i))
- bone:SetPos(bonepos)
- bone:SetAngles(boneang)
- bone:SetVelocity(ragdoll:GetVelocity())
- end
- end
- ply:Remove()
- end
- return ragdoll
- end
- end
- -- Creates client or server ragdoll depending on settings
- function CORPSE.Create(ply, attacker, dmginfo)
- if not IsValid(ply) then return end
- local rag = ents.Create("prop_ragdoll")
- if not IsValid(rag) then return nil end
- rag:SetPos(ply:GetPos())
- rag:SetModel(ply:GetModel())
- rag:SetAngles(ply:GetAngles())
- rag:SetColor(ply:GetColor())
- rag:Spawn()
- rag:Activate()
- -- nonsolid to players, but can be picked up and shot
- rag:SetCollisionGroup(rag_collide:GetBool() and COLLISION_GROUP_WEAPON or COLLISION_GROUP_DEBRIS_TRIGGER)
- -- flag this ragdoll as being a player's
- rag.player_ragdoll = true
- rag.uqid = ply:UniqueID()
- -- network data
- CORPSE.SetPlayerNick(rag, ply)
- CORPSE.SetFound(rag, false)
- CORPSE.SetCredits(rag, ply:GetCredits())
- --custom
- rag.pnick = ply:Nick()
- -- if someone searches this body they can find info on the victim and the
- -- death circumstances
- rag.equipment = ply:GetEquipmentItems()
- rag.was_role = ply:GetRole()
- rag.bomb_wire = ply.bomb_wire
- rag.dmgtype = dmginfo:GetDamageType()
- local wep = util.WeaponFromDamage(dmginfo)
- rag.dmgwep = IsValid(wep) and wep:GetClass() or ""
- rag.was_headshot = (ply.was_headshot and dmginfo:IsBulletDamage())
- rag.time = CurTime()
- rag.kills = table.Copy(ply.kills)
- rag.killer_sample = GetKillerSample(ply, attacker, dmginfo)
- -- crime scene data
- rag.scene = GetSceneData(ply, attacker, dmginfo)
- -- position the bones
- local num = rag:GetPhysicsObjectCount()-1
- local v = ply:GetVelocity()
- -- bullets have a lot of force, which feels better when shooting props,
- -- but makes bodies fly, so dampen that here
- if dmginfo:IsDamageType(DMG_BULLET) or dmginfo:IsDamageType(DMG_SLASH) then
- v = v / 5
- end
- for i=0, num do
- local bone = rag:GetPhysicsObjectNum(i)
- if IsValid(bone) then
- local bp, ba = ply:GetBonePosition(rag:TranslatePhysBoneToBone(i))
- if bp and ba then
- bone:SetPos(bp)
- bone:SetAngles(ba)
- end
- -- not sure if this will work:
- bone:SetVelocity(v)
- end
- end
- -- create advanced death effects (knives)
- if ply.effect_fn then
- -- next frame, after physics is happy for this ragdoll
- local efn = ply.effect_fn
- timer.Simple(0, function() efn(rag) end)
- end
- if ply.inactivity then
- ply.inactivity = false
- IdentifySlainBody(rag)
- end
- return rag -- we'll be speccing this
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement