Advertisement
Guest User

Untitled

a guest
Jul 7th, 2014
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.24 KB | None | 0 0
  1. ---- Corpse functions
  2.  
  3. -- namespaced because we have no ragdoll metatable
  4. CORPSE = {}
  5.  
  6. include("corpse_shd.lua")
  7.  
  8. --- networked data abstraction layer
  9. local dti = CORPSE.dti
  10.  
  11. function CORPSE.SetFound(rag, state)
  12. --rag:SetNWBool("found", state)
  13. rag:SetDTBool(dti.BOOL_FOUND, state)
  14. if state then --custom for recreation
  15. rag.idtime = CurTime()
  16. end
  17. end
  18.  
  19. function CORPSE.SetPlayerNick(rag, ply_or_name)
  20. -- don't have datatable strings, so use a dt entity for common case of
  21. -- still-connected player, and if the player is gone, fall back to nw string
  22. local name = ply_or_name
  23. if IsValid(ply_or_name) then
  24. name = ply_or_name:Nick()
  25. rag:SetDTEntity(dti.ENT_PLAYER, ply_or_name)
  26. end
  27.  
  28. rag:SetNWString("nick", name)
  29. end
  30.  
  31. function CORPSE.SetCredits(rag, credits)
  32. --rag:SetNWInt("credits", credits)
  33. rag:SetDTInt(dti.INT_CREDITS, credits)
  34. end
  35.  
  36.  
  37. --- ragdoll creation and search
  38.  
  39. -- If detective mode, announce when someone's body is found
  40. local bodyfound = CreateConVar("ttt_announce_body_found", "1")
  41.  
  42. --custom for auto-iding slain bodies
  43. local function IdentifySlainBody(rag, slain)
  44. if GetRoundState() == ROUND_PREP then
  45. CORPSE.SetFound(rag, true)
  46. return
  47. end
  48. local nick = CORPSE.GetPlayerNick(rag, "")
  49. local traitor = (rag.was_role == ROLE_TRAITOR)
  50.  
  51. -- Announce body
  52. if bodyfound:GetBool() and not CORPSE.GetFound(rag, false) then
  53. local roletext = nil
  54. local roletext2 = nil
  55. local role = rag.was_role
  56. if role == ROLE_TRAITOR then
  57. roletext = "body_found_t"
  58. roletext2 = "traitor"
  59. elseif role == ROLE_DETECTIVE then
  60. roletext = "body_found_d"
  61. roletext2 = "detective"
  62. else
  63. roletext = "body_found_i"
  64. roletext2 = "innocent"
  65. end
  66.  
  67. LANG.Msg("body_tslay", {victim = nick})
  68. end
  69.  
  70. if not CORPSE.GetFound(rag, false) then
  71. -- will return either false or a valid ply
  72. local deadply = player.GetByUniqueID(rag.uqid)
  73. if deadply then
  74. deadply:SetNWBool("body_found", true)
  75.  
  76. if traitor then
  77. -- update innocent's list of traitors
  78. SendConfirmedTraitors(GetInnocentFilter(false))
  79. end
  80. end
  81.  
  82. CORPSE.SetFound(rag, true)
  83. end
  84. end
  85.  
  86. local function IdentifyBody(ply, rag)
  87. if not ply:IsTerror() then return end
  88.  
  89. -- simplified case for those who die and get found during prep
  90. if GetRoundState() == ROUND_PREP then
  91. CORPSE.SetFound(rag, true)
  92. return
  93. end
  94.  
  95. local finder = ply:Nick()
  96. local nick = CORPSE.GetPlayerNick(rag, "")
  97. local traitor = (rag.was_role == ROLE_TRAITOR)
  98.  
  99. -- Announce body
  100. if bodyfound:GetBool() and not CORPSE.GetFound(rag, false) then
  101. local roletext = nil
  102. local roletext2 = nil
  103. local role = rag.was_role
  104. if role == ROLE_TRAITOR then
  105. roletext = "body_found_t"
  106. roletext2 = "traitor"
  107. elseif role == ROLE_DETECTIVE then
  108. roletext = "body_found_d"
  109. roletext2 = "detective"
  110. else
  111. roletext = "body_found_i"
  112. roletext2 = "innocent"
  113. end
  114.  
  115. LANG.Msg("body_found", {finder = finder,
  116. victim = nick,
  117. role = LANG.Param(roletext)})
  118.  
  119. if DMG_LOG then
  120. AddToDamageLog({DMG_LOG.BODY_FOUND, finder, ply:GetRoleString(), nick, roletext2, {ply:SteamID(), CORPSE.GetPlayerID(rag, "")}})
  121. end
  122. end
  123.  
  124. -- Register find
  125. if not CORPSE.GetFound(rag, false) then
  126. -- will return either false or a valid ply
  127. local deadply = player.GetByUniqueID(rag.uqid)
  128. if deadply then
  129. deadply:SetNWBool("body_found", true)
  130.  
  131. if traitor then
  132. -- update innocent's list of traitors
  133. SendConfirmedTraitors(GetInnocentFilter(false))
  134. end
  135.  
  136. SCORE:HandleBodyFound(ply, deadply)
  137. end
  138.  
  139. CORPSE.SetFound(rag, true)
  140. else
  141. -- re-set because nwvars are unreliable
  142. --CORPSE.SetFound(rag, true)
  143. --CORPSE.SetPlayerNick(rag, nick)
  144. end
  145.  
  146. -- Handle kill list
  147. for k, vicid in pairs(rag.kills) do
  148. -- filter out disconnected
  149. local vic = player.GetByUniqueID(vicid)
  150.  
  151. -- is this an unconfirmed dead?
  152. if IsValid(vic) and (not vic:GetNWBool("body_found", false)) then
  153. LANG.Msg("body_confirm", {finder = finder, victim = vic:Nick()})
  154.  
  155. -- update scoreboard status
  156. vic:SetNWBool("body_found", true)
  157.  
  158. -- however, do not mark body as found. This lets players find the
  159. -- body later and get the benefits of that
  160. --local vicrag = vic.server_ragdoll
  161. --CORPSE.SetFound(vicrag, true)
  162. end
  163. end
  164. end
  165.  
  166. -- Covert identify concommand for traitors
  167. local function IdentifyCommand(ply, cmd, args)
  168. if not IsValid(ply) then return end
  169. if #args != 2 then return end
  170.  
  171. local eidx = tonumber(args[1])
  172. local id = tonumber(args[2])
  173. if (not eidx) or (not id) then return end
  174.  
  175.  
  176. if (not ply.search_id) or ply.search_id.id != id or ply.search_id.eidx != eidx then
  177. ply.search_id = nil
  178. return
  179. end
  180.  
  181. ply.search_id = nil
  182.  
  183. local rag = Entity(eidx)
  184. if IsValid(rag) and rag:GetPos():Distance(ply:GetPos()) < 128 then
  185. if not CORPSE.GetFound(rag, false) then
  186. IdentifyBody(ply, rag)
  187. end
  188. end
  189. end
  190. concommand.Add("ttt_confirm_death", IdentifyCommand)
  191.  
  192. -- Call detectives to a corpse
  193. local function CallDetective(ply, cmd, args)
  194. if not IsValid(ply) then return end
  195. if #args != 1 then return end
  196. if not ply:IsActive() then return end
  197.  
  198. local eidx = tonumber(args[1])
  199. if not eidx then return end
  200.  
  201. local rag = Entity(eidx)
  202. if IsValid(rag) and rag:GetPos():Distance(ply:GetPos()) < 128 then
  203. if CORPSE.GetFound(rag, false) then
  204. -- show indicator to detectives
  205. SendUserMessage("corpse_call", GetDetectiveFilter(true), rag:GetPos())
  206.  
  207. LANG.Msg("body_call", {player = ply:Nick(),
  208. victim = CORPSE.GetPlayerNick(rag, "someone")})
  209.  
  210. else
  211. LANG.Msg(ply, "body_call_error")
  212. end
  213. end
  214. end
  215. concommand.Add("ttt_call_detective", CallDetective)
  216.  
  217. -- Send a usermessage to client containing search results
  218. function CORPSE.ShowSearch(ply, rag, covert, long_range)
  219. if not IsValid(ply) or not IsValid(rag) then return end
  220.  
  221. if rag:IsOnFire() then
  222. LANG.Msg(ply, "body_burning")
  223. return
  224. end
  225.  
  226. -- init a heap of data we'll be sending
  227. local nick = CORPSE.GetPlayerNick(rag)
  228. local traitor = (rag.was_role == ROLE_TRAITOR)
  229. local role = rag.was_role
  230. local eq = rag.equipment or EQUIP_NONE
  231. local c4 = rag.bomb_wire or -1
  232. local dmg = rag.dmgtype or DMG_GENERIC
  233. local wep = rag.dmgwep or ""
  234. local words = rag.last_words or ""
  235. local hshot = rag.was_headshot or false
  236. local dtime = rag.time or 0
  237.  
  238. local owner = player.GetByUniqueID(rag.uqid)
  239. owner = IsValid(owner) and owner:EntIndex() or -1
  240.  
  241. -- basic sanity check
  242. if nick == nil or eq == nil or role == nil then return end
  243.  
  244. if DetectiveMode() and not covert then
  245. IdentifyBody(ply, rag)
  246. end
  247.  
  248. local credits = CORPSE.GetCredits(rag, 0)
  249. if ply:IsActiveSpecial() and credits > 0 and (not long_range) then
  250. LANG.Msg(ply, "body_credits", {num = credits})
  251. ply:AddCredits(credits)
  252.  
  253. CORPSE.SetCredits(rag, 0)
  254.  
  255. ServerLog(ply:Nick() .. " took " .. credits .. " credits from the body of " .. nick .. "\n")
  256. if DMG_LOG then
  257. AddToDamageLog({DMG_LOG.FOUND_CREDITS, ply:Nick(), ply:GetRoleString(), nick, credits, {ply:SteamID(), CORPSE.GetPlayerID(rag, "")}})
  258. end
  259. SCORE:HandleCreditFound(ply, nick, credits)
  260. end
  261.  
  262. -- time of death relative to current time (saves bits)
  263. if dtime != 0 then
  264. dtime = math.Round(CurTime() - dtime)
  265. end
  266.  
  267. -- identifier so we know whether a ttt_confirm_death was legit
  268. ply.search_id = { eidx = rag:EntIndex(), id = rag:EntIndex() + dtime }
  269.  
  270. -- time of dna sample decay relative to current time
  271. local stime = 0
  272. if rag.killer_sample then
  273. stime = math.max(0, rag.killer_sample.t - CurTime())
  274. end
  275.  
  276. -- build list of people this traitor killed
  277. local kill_entids = {}
  278. for k, vicid in pairs(rag.kills) do
  279. -- also send disconnected players as a marker
  280. local vic = player.GetByUniqueID(vicid)
  281. table.insert(kill_entids, IsValid(vic) and vic:EntIndex() or -1)
  282. end
  283.  
  284. local lastid = -1
  285. if rag.lastid and ply:IsActiveDetective() then
  286. -- if the person this victim last id'd has since disconnected, send -1 to
  287. -- indicate this
  288. lastid = IsValid(rag.lastid.ent) and rag.lastid.ent:EntIndex() or -1
  289. end
  290.  
  291. -- If found by detective, send to all, else just the finder
  292. local receiver = ply
  293. if ply:IsActiveDetective() then receiver = nil end
  294.  
  295. -- Send a message with basic info
  296. umsg.Start("ragsrch", receiver)
  297. umsg.Short(rag:EntIndex()) -- 2 bytes
  298. umsg.Short(owner) -- 2 bytes
  299. umsg.String(nick)
  300. umsg.Short(eq) -- 2 bytes
  301. umsg.Char(role) -- 1 byte
  302. umsg.Char(c4) -- 1 byte
  303. umsg.Long(dmg) -- 4 bytes, enum goes high
  304. umsg.String(wep) -- 2 bytes(?)
  305. umsg.Bool(hshot) -- 1 byte
  306. umsg.Short(dtime) -- 2 bytes
  307. umsg.Short(stime) -- 2 bytes
  308.  
  309. umsg.Char(#kill_entids) -- 1 byte + (2 * #kills) bytes
  310. for k, idx in pairs(kill_entids) do
  311. -- might be possible to use chars here but this is safer
  312. umsg.Short(idx)
  313. end
  314.  
  315. umsg.Short(lastid)
  316.  
  317. -- Who found this, so if we get this from a detective we can decide not to
  318. -- show a window
  319. umsg.Short(ply:EntIndex())
  320.  
  321. -- Will there be a last words umsg coming up?
  322. umsg.Bool(words != "") -- 1b
  323. umsg.End()
  324.  
  325. if words != "" then
  326. -- umsgs only have 128 bytes of room, so if last words is really long we
  327. -- have to truncate
  328. if string.len(words) > 127 then
  329. words = string.sub(words, -127)
  330. end
  331.  
  332. umsg.Start("ragsrch_lw", ply)
  333. umsg.String(words)
  334. umsg.End()
  335. end
  336. end
  337.  
  338.  
  339. -- Returns a sample for use in dna scanner if the kill fits certain constraints,
  340. -- else returns nil
  341. local function GetKillerSample(victim, attacker, dmg)
  342. -- only guns and melee damage, not explosions
  343. if not (dmg:IsBulletDamage() or dmg:IsDamageType(DMG_SLASH) or dmg:IsDamageType(DMG_CLUB)) then
  344. return nil
  345. end
  346.  
  347. if not (IsValid(victim) and IsValid(attacker) and attacker:IsPlayer()) then return end
  348.  
  349. -- NPCs for which a player is damage owner (meaning despite the NPC dealing
  350. -- the damage, the attacker is a player) should not cause the player's DNA to
  351. -- end up on the corpse.
  352. local infl = dmg:GetInflictor()
  353. if IsValid(infl) and infl:IsNPC() then return end
  354.  
  355. local dist = victim:GetPos():Distance(attacker:GetPos())
  356. if dist > GetConVarNumber("ttt_killer_dna_range") then return nil end
  357.  
  358. local sample = {}
  359. sample.killer = attacker
  360. sample.killer_uid = attacker:UniqueID()
  361. sample.victim = victim
  362. sample.t = CurTime() + (-1 * (0.019 * dist)^2 + GetConVarNumber("ttt_killer_dna_basetime"))
  363.  
  364. return sample
  365. end
  366.  
  367. local crimescene_keys = {"Fraction", "HitBox", "Normal", "HitPos", "StartPos"}
  368. local poseparams = {
  369. "aim_yaw", "move_yaw", "aim_pitch",
  370. -- "spine_yaw", "head_yaw", "head_pitch"
  371. };
  372.  
  373. local function GetSceneDataFromPlayer(ply)
  374. local data = {
  375. pos = ply:GetPos(),
  376. ang = ply:GetAngles(),
  377. sequence = ply:GetSequence(),
  378. cycle = ply:GetCycle()
  379. };
  380.  
  381. for _, param in pairs(poseparams) do
  382. data[param] = ply:GetPoseParameter(param)
  383. end
  384.  
  385. return data
  386. end
  387.  
  388. local function GetSceneDataFromCorpse(rag)
  389. local data = {
  390. pos = rag:GetPos()
  391. };
  392. return data
  393. end
  394.  
  395. local function GetSceneData(victim, attacker, dmginfo)
  396. -- only for guns for now, hull traces don't work well etc
  397. if not dmginfo:IsBulletDamage() then return end
  398.  
  399. local scene = {}
  400.  
  401. if victim.hit_trace then
  402. scene.hit_trace = table.CopyKeys(victim.hit_trace, crimescene_keys)
  403. else
  404. return scene
  405. end
  406.  
  407. scene.victim = GetSceneDataFromPlayer(victim)
  408.  
  409. if IsValid(attacker) and attacker:IsPlayer() then
  410. scene.killer = GetSceneDataFromPlayer(attacker)
  411.  
  412. local att = attacker:LookupAttachment("anim_attachment_RH")
  413. local angpos = attacker:GetAttachment(att)
  414. if not angpos then
  415. scene.hit_trace.StartPos = attacker:GetShootPos()
  416. else
  417. scene.hit_trace.StartPos = angpos.Pos
  418. end
  419. end
  420.  
  421. return scene
  422. end
  423.  
  424. function GetDamageLogSceneData(victim, attacker, dmginfo)
  425. if (dmginfo:IsBulletDamage()) or (dmginfo:GetInflictor():GetClass() == "weapon_ttt_knife") then --only works on bullet or knife deaths
  426. local scene = {}
  427.  
  428. if victim.hit_trace then
  429. scene.hit_trace = table.CopyKeys(victim.hit_trace, crimescene_keys)
  430. else
  431. return scene
  432. end
  433.  
  434. scene.victim = GetSceneDataFromPlayer(victim)
  435. scene.victim["1"] = 2
  436. scene.victim["2"] = victim:Nick() .. " (" .. victim:GetRoleString() .. ")"
  437.  
  438. if IsValid(attacker) and attacker:IsPlayer() then
  439. scene.killer = GetSceneDataFromPlayer(attacker)
  440.  
  441. local att = attacker:LookupAttachment("anim_attachment_RH")
  442. local angpos = attacker:GetAttachment(att)
  443. if not angpos then
  444. scene.hit_trace.StartPos = attacker:GetShootPos()
  445. else
  446. scene.hit_trace.StartPos = angpos.Pos
  447. end
  448. scene.hit_trace.Fraction = math.Round(scene.hit_trace.Fraction, 3)
  449.  
  450. scene.killer["1"] = 1
  451. scene.killer["2"] = attacker:Nick() .. " (" .. attacker:GetRoleString() .. ")"
  452.  
  453. scene.look = attacker:EyeAngles()
  454. scene.look.p = math.Round(scene.look.p, 2)
  455. scene.look.y = math.Round(scene.look.y, 2)
  456. scene.look.r = math.Round(scene.look.r, 2)
  457.  
  458.  
  459. if dmginfo:GetInflictor():GetClass() == "weapon_ttt_knife" then scene.knife = true end
  460.  
  461. local count = 0
  462. for _,v in pairs(player.GetAll()) do
  463. if IsValid(v) and not v:IsSpec() and v != victim and v != attacker
  464. 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
  465. count = count + 1
  466. local b = GetSceneDataFromPlayer(v)
  467. b["1"] = 3
  468. b["2"] = v:Nick() .. " (" .. v:GetRoleString() .. ")"
  469. scene["b" .. count] = b
  470. end
  471. end
  472. scene.by = count
  473.  
  474. count = 0
  475. for _,v in pairs(ents.FindByClass("prop_ragdoll")) do
  476. if v.player_ragdoll and v.uqid != victim:UniqueID() and v.uqid != attacker:UniqueID()
  477. 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
  478. if (CORPSE.GetFound(v, false) and ((CurTime() - v.idtime) >= 30)) then continue end --only include id'd bodies if they were id'd recently
  479. count = count + 1
  480. local b = GetSceneDataFromCorpse(v)
  481. b["1"] = (CORPSE.GetFound(v, false) and "ID'd " or "UnID'd ") .. "Body (died " .. math.Round(CurTime() - v.time, 1) .. "s before)"
  482. local rol
  483. if v.was_role == 0 then rol = "innocent" elseif v.was_role == 1 then rol = "traitor" else rol = "detective" end
  484. b["2"] = v.pnick .. " (" .. rol .. ")"
  485. if (CORPSE.GetFound(v, false)) then
  486. b["3"] = "(identified " .. math.Round(CurTime() - v.idtime, 1) .. "s before)"
  487. end
  488. scene["c" .. count] = b
  489. end
  490. end
  491. scene.co = count
  492. end
  493.  
  494. return scene
  495. end
  496. end
  497.  
  498. local rag_collide = CreateConVar("ttt_ragdoll_collide", "0")
  499.  
  500. function DMMakeDeathRagDoll(pos, ang, mdl, skin, color, mat, dmgammount, dmgtype, dmgpos, dmgforce, onfire, npcvel, isnpc, isply, ply, attacker, vel, dmginfo)
  501. if dmgtype != 67108865 and mdl != nil then //damage type 67108865 is from a combineball (DMG_DISSOLVE)
  502. ragcont = ents.Create("dismemberment_ragdoll")//Spawn Ragdoll Controller
  503. ragcont:SetPos(pos)
  504. ragcont:Spawn()
  505.  
  506. local ragdoll = ents.Create("prop_ragdoll")
  507.  
  508. ragdoll.pnick = ply:Nick()
  509.  
  510. ragdoll.ShouldGib = true
  511. ragdoll:SetPos(pos)
  512. ragdoll:SetAngles(ang)
  513. ragdoll:SetModel(mdl)
  514. ragdoll:Spawn()
  515. ragdoll:SetSkin(skin)
  516. ragdoll:SetColor(color)
  517. ragdoll:SetMaterial(mat)
  518. ragdoll:SetNetworkedBool("IsDismemberable", true)
  519. ragdoll:SetNetworkedBool("IsLimb", false)
  520. ragcont:SetNoDraw(true)
  521. ragcont:SetNetworkedEntity("dismembermentragdoll", ragdoll)
  522. ragcont:SetParent(ragdoll)
  523. ragcont:AddEffects(EF_BONEMERGE)
  524.  
  525. ragdoll.player_ragdoll = true
  526. ragdoll.uqid = ply:UniqueID()
  527.  
  528. -- network data
  529. CORPSE.SetPlayerNick(ragdoll, ply)
  530. CORPSE.SetFound(ragdoll, false)
  531. CORPSE.SetCredits(ragdoll, ply:GetCredits())
  532.  
  533. -- if someone searches this body they can find info on the victim and the
  534. -- death circumstances
  535. ragdoll.equipment = ply:GetEquipmentItems()
  536. ragdoll.was_role = ply:GetRole()
  537. ragdoll.bomb_wire = ply.bomb_wire
  538. ragdoll.dmgtype = dmgtype
  539.  
  540. local wep = util.WeaponFromDamage(dmginfo)
  541. ragdoll.dmgwep = IsValid(wep) and wep:GetClass() or ""
  542.  
  543. ragdoll.was_headshot = (ply.was_headshot and dmginfo:IsBulletDamage())
  544. ragdoll.time = CurTime()
  545. ragdoll.kills = table.Copy(ply.kills)
  546.  
  547. ragdoll.killer_sample = GetKillerSample(ply, attacker, dmginfo)
  548.  
  549. -- crime scene data
  550. ragdoll.scene = GetSceneData(ply, attacker, dmginfo)
  551.  
  552. for bone = 0, ragdoll:GetPhysicsObjectCount() do
  553. local phys = ragdoll:GetPhysicsObjectNum(bone)
  554. local plybone = ragdoll:TranslatePhysBoneToBone(bone)
  555. local bonepos, boneang = ply:GetBonePosition(plybone)
  556.  
  557. if IsValid(phys) and IsValid(ply) then
  558. phys:SetPos(bonepos)
  559. phys:SetAngles(boneang)
  560. end
  561.  
  562. if IsValid(phys) then
  563. phys:AddVelocity(vel)
  564. end
  565. end
  566.  
  567. /*
  568. local ragdoll = ents.Create("prop_ragdoll")
  569.  
  570. ragdoll.ShouldGib = true
  571. //ragdoll.blood = {}
  572. ragdoll:SetPos(pos)
  573. ragdoll:SetAngles(ang)
  574. ragdoll:SetModel(mdl)
  575. ragdoll:Spawn()
  576. ragdoll:SetSkin(skin)
  577. ragdoll:SetColor(color)
  578. ragdoll:SetMaterial(mat)
  579. ragdoll:SetNetworkedBool("IsDismemberable", true)
  580. */
  581.  
  582. if rag_collide:GetBool() then
  583. ragdoll:SetCollisionGroup(COLLISION_GROUP_NONE)
  584. else
  585. ragdoll:SetCollisionGroup(COLLISION_GROUP_WEAPON)
  586. end
  587.  
  588. if isply then
  589. ply:SetNetworkedEntity("PlayerDeathRag" .. ply:Deaths(), ragdoll)
  590. end
  591.  
  592. //Limb Health
  593. healthmult = GetConVar("dismemberment_raghealthmult"):GetInt()
  594.  
  595. ragdoll.hHead = 50 * healthmult
  596. ragdoll.hRcalf = 50 * healthmult
  597. ragdoll.hRUcalf = 50 * healthmult --vortigaunt only middle leg bone
  598. ragdoll.hRthigh = 50 * healthmult
  599. ragdoll.hRuparm = 50 * healthmult
  600. ragdoll.hRforearm = 50 * healthmult
  601. ragdoll.hRhand = 25 * healthmult
  602. ragdoll.hRfoot = 25 * healthmult
  603. ragdoll.hLcalf = 50 * healthmult
  604. ragdoll.hLUcalf = 50 * healthmult --vortigaunt only middle leg bone
  605. ragdoll.hLthigh = 50 * healthmult
  606. ragdoll.hLuparm = 50 * healthmult
  607. ragdoll.hLforearm = 50 * healthmult
  608. ragdoll.hLhand = 25 * healthmult
  609. ragdoll.hLfoot = 25 * healthmult
  610. ragdoll.hpelvis = 50 * healthmult
  611. ragdoll.hbody = 100 * healthmult
  612.  
  613. //Body Types
  614. if mdl == "models/vortigaunt.mdl" then
  615. ragdoll.bodytype = "vortigaunt"
  616. ragdoll.goretype = 2 --Alien
  617.  
  618. ragdoll.bHead = "ValveBiped.head"
  619. ragdoll.bRcalf = "ValveBiped.leg_bone3_r"
  620. ragdoll.bRUcalf = "ValveBiped.leg_bone2_r" --vortigaunt only middle leg bone
  621. ragdoll.bRthigh = "ValveBiped.leg_bone1_r"
  622. ragdoll.bRuparm = "ValveBiped.arm1_r"
  623. ragdoll.bRforearm = "ValveBiped.arm2_r"
  624. ragdoll.bRhand = "ValveBiped.hand1_r"
  625. ragdoll.bRfoot = "ValveBiped.bip01_r_foot"
  626. ragdoll.bLcalf = "ValveBiped.leg_bone3_l"
  627. ragdoll.bLUcalf = "ValveBiped.leg_bone2_l" --vortigaunt only middle leg bone
  628. ragdoll.bLthigh = "ValveBiped.leg_bone1_l"
  629. ragdoll.bLuparm = "ValveBiped.arm1_l"
  630. ragdoll.bLforearm = "ValveBiped.arm2_l"
  631. ragdoll.bLhand = "ValveBiped.hand1_l"
  632. ragdoll.bLfoot = "ValveBiped.bip01_l_foot"
  633. ragdoll.bpelvis = "ValveBiped.hips"
  634. ragdoll.bbody = "ValveBiped.spine2"
  635. elseif mdl == "models/headcrabclassic.mdl" then
  636. ragdoll.bodytype = "generic"
  637. ragdoll.goretype = 2 --Alien
  638. ragdoll.hbody = 35 * healthmult
  639.  
  640. ragdoll.bbody = "headcrabclassic.bodycontrol"
  641. ragdoll.bRcalf = "headcrabclassic.clafr_bone"
  642. ragdoll.bRthigh = "headcrabclassic.thighr_bone"
  643. ragdoll.bRuparm = "headcrabclassic.upperarmr_bone"
  644. ragdoll.bRforearm = "headcrabclassic.forearmr_bone"
  645. ragdoll.bLcalf = "headcrabclassic.clafl_bone"
  646. ragdoll.bLthigh = "headcrabclassic.thighl_bone"
  647. ragdoll.bLuparm = "headcrabclassic.upperarml_bone"
  648. ragdoll.bLforearm = "headcrabclassic.forearml_bone"
  649. //unused
  650. ragdoll.bpelvis = "nil"
  651. ragdoll.bHead = "nil"
  652. ragdoll.bRUcalf = "nil"
  653. ragdoll.bLUcalf = "nil"
  654. ragdoll.bRhand = "nil"
  655. ragdoll.bLhand = "nil"
  656. ragdoll.bRfoot = "nil"
  657. ragdoll.bLfoot = "nil"
  658. elseif mdl == "models/headcrab.mdl" then
  659. ragdoll.bodytype = "generic"
  660. ragdoll.goretype = 2 --Alien
  661. ragdoll.hbody = 35 * healthmult
  662.  
  663. ragdoll.bbody = "hcfast.body"
  664. ragdoll.bRcalf = "hcfast.leg_bone2_r"
  665. ragdoll.bRthigh = "hcfast.leg_bone1_r"
  666. ragdoll.bRuparm = "hcfast.arm_bone1_r"
  667. ragdoll.bRforearm = "hcfast.arm_bone2_r"
  668. ragdoll.bLcalf = "hcfast.leg_bone2_l"
  669. ragdoll.bLthigh = "hcfast.leg_bone1_l"
  670. ragdoll.bLuparm = "hcfast.arm_bone1_l"
  671. ragdoll.bLforearm = "hcfast.arm_bone2_l"
  672. //unused
  673. ragdoll.bpelvis = "nil"
  674. ragdoll.bHead = "nil"
  675. ragdoll.bRUcalf = "nil"
  676. ragdoll.bLUcalf = "nil"
  677. ragdoll.bRhand = "nil"
  678. ragdoll.bLhand = "nil"
  679. ragdoll.bRfoot = "nil"
  680. ragdoll.bLfoot = "nil"
  681. elseif mdl == "models/headcrabblack.mdl" then
  682. ragdoll.bodytype = "generic"
  683. ragdoll.goretype = 2 --Alien
  684. ragdoll.hbody = 35 * healthmult
  685.  
  686. ragdoll.bbody = "hcblack.body"
  687. ragdoll.bRcalf = "hcblack.leg_bone2_r"
  688. ragdoll.bRthigh = "hcblack.leg_bone1_r"
  689. ragdoll.bRuparm = "hcblack.arm_bone1_r"
  690. ragdoll.bRforearm = "hcblack.arm_bone2_r"
  691. ragdoll.bLcalf = "hcblack.leg_bone2_l"
  692. ragdoll.bLthigh = "hcblack.leg_bone1_l"
  693. ragdoll.bLuparm = "hcblack.arm_bone1_l"
  694. ragdoll.bLforearm = "hcblack.arm_bone2_l"
  695. //unused
  696. ragdoll.bpelvis = "nil"
  697. ragdoll.bHead = "nil"
  698. ragdoll.bRUcalf = "nil"
  699. ragdoll.bLUcalf = "nil"
  700. ragdoll.bRhand = "nil"
  701. ragdoll.bLhand = "nil"
  702. ragdoll.bRfoot = "nil"
  703. ragdoll.bLfoot = "nil"
  704. else
  705. ragdoll.bodytype = "generic"
  706. ragdoll.goretype = 1 --Human
  707.  
  708. ragdoll.bHead = "ValveBiped.Bip01_Head1"
  709. ragdoll.bRcalf = "ValveBiped.Bip01_R_Calf"
  710. ragdoll.bRUcalf = "nil"
  711. ragdoll.bRthigh = "ValveBiped.Bip01_R_Thigh"
  712. ragdoll.bRuparm = "ValveBiped.Bip01_R_UpperArm"
  713. ragdoll.bRforearm = "ValveBiped.Bip01_R_Forearm"
  714. ragdoll.bRhand = "ValveBiped.Bip01_R_Hand"
  715. ragdoll.bRfoot = "ValveBiped.Bip01_R_Foot"
  716. ragdoll.bLcalf = "ValveBiped.Bip01_L_Calf"
  717. ragdoll.bLUcalf = "nil"
  718. ragdoll.bLthigh = "ValveBiped.Bip01_L_Thigh"
  719. ragdoll.bLuparm = "ValveBiped.Bip01_L_UpperArm"
  720. ragdoll.bLforearm = "ValveBiped.Bip01_L_Forearm"
  721. ragdoll.bLhand = "ValveBiped.Bip01_L_Hand"
  722. ragdoll.bLfoot = "ValveBiped.Bip01_L_Foot"
  723. ragdoll.bpelvis = "ValveBiped.Bip01_Pelvis"
  724. ragdoll.bbody = "ValveBiped.Bip01_Spine2"
  725. end
  726.  
  727. //Limbs
  728. if ragdoll:LookupBone(ragdoll.bHead) != nil then
  729. ragdoll.Head = ragdoll:LookupBone(ragdoll.bHead)
  730. else
  731. ragdoll.Head = -1
  732. end
  733.  
  734. if ragdoll:LookupBone(ragdoll.bRcalf) != nil then
  735. ragdoll.Rcalf = ragdoll:LookupBone(ragdoll.bRcalf)
  736. else
  737. ragdoll.Rcalf = -1
  738. end
  739.  
  740. if ragdoll:LookupBone(ragdoll.bRthigh) != nil then
  741. ragdoll.Rthigh = ragdoll:LookupBone(ragdoll.bRthigh)
  742. else
  743. ragdoll.Rthigh = -1
  744. end
  745.  
  746. if ragdoll:LookupBone(ragdoll.bRuparm) != nil then
  747. ragdoll.Ruparm = ragdoll:LookupBone(ragdoll.bRuparm)
  748. else
  749. ragdoll.Ruparm = -1
  750. end
  751.  
  752. if ragdoll:LookupBone(ragdoll.bRforearm) != nil then
  753. ragdoll.Rforearm = ragdoll:LookupBone(ragdoll.bRforearm)
  754. else
  755. ragdoll.Rforearm = -1
  756. end
  757.  
  758. if ragdoll:LookupBone(ragdoll.bRhand) != nil then
  759. ragdoll.Rhand = ragdoll:LookupBone(ragdoll.bRhand)
  760. else
  761. ragdoll.Rhand = -1
  762. end
  763.  
  764. if ragdoll:LookupBone(ragdoll.bRfoot) != nil then
  765. ragdoll.Rfoot = ragdoll:LookupBone(ragdoll.bRfoot)
  766. else
  767. ragdoll.Rfoot = -1
  768. end
  769.  
  770. if ragdoll:LookupBone(ragdoll.bLcalf) != nil then
  771. ragdoll.Lcalf = ragdoll:LookupBone(ragdoll.bLcalf)
  772. else
  773. ragdoll.Lcalf = -1
  774. end
  775.  
  776. if ragdoll:LookupBone(ragdoll.bLthigh) != nil then
  777. ragdoll.Lthigh = ragdoll:LookupBone(ragdoll.bLthigh)
  778. else
  779. ragdoll.Lthigh = -1
  780. end
  781.  
  782. if ragdoll:LookupBone(ragdoll.bLuparm) != nil then
  783. ragdoll.Luparm = ragdoll:LookupBone(ragdoll.bLuparm)
  784. else
  785. ragdoll.Luparm = -1
  786. end
  787.  
  788. if ragdoll:LookupBone(ragdoll.bLforearm) != nil then
  789. ragdoll.Lforearm = ragdoll:LookupBone(ragdoll.bLforearm)
  790. else
  791. ragdoll.Lforearm = -1
  792. end
  793.  
  794. if ragdoll:LookupBone(ragdoll.bLhand) != nil then
  795. ragdoll.Lhand = ragdoll:LookupBone(ragdoll.bLhand)
  796. else
  797. ragdoll.Lhand = -1
  798. end
  799.  
  800. if ragdoll:LookupBone(ragdoll.bLfoot) != nil then
  801. ragdoll.Lfoot = ragdoll:LookupBone(ragdoll.bLfoot)
  802. else
  803. ragdoll.Lfoot = -1
  804. end
  805.  
  806. if ragdoll:LookupBone(ragdoll.bpelvis) != nil then
  807. ragdoll.pelvis = ragdoll:LookupBone(ragdoll.bpelvis)
  808. else
  809. ragdoll.pelvis = -1
  810. end
  811.  
  812. if ragdoll:LookupBone(ragdoll.bRUcalf) != nil then
  813. ragdoll.RUcalf = ragdoll:LookupBone(ragdoll.bRUcalf)
  814. else
  815. ragdoll.RUcalf = -1
  816. end
  817.  
  818. if ragdoll:LookupBone(ragdoll.bLUcalf) != nil then
  819. ragdoll.LUcalf = ragdoll:LookupBone(ragdoll.bLUcalf)
  820. else
  821. ragdoll.LUcalf = -1
  822. end
  823.  
  824. //Body
  825. if ragdoll:LookupBone(ragdoll.bbody) != nil then
  826. ragdoll.body = ragdoll:LookupBone(ragdoll.bbody)
  827. else
  828. ragdoll.body = -1
  829. end
  830.  
  831. //Limb Networking (so the client knows)
  832. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Head, false)
  833. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rcalf, false)
  834. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.RUcalf, false)
  835. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rthigh, false)
  836. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Ruparm, false)
  837. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rforearm, false)
  838. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rhand, false)
  839. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Rfoot, false)
  840. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lcalf, false)
  841. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.LUcalf, false)
  842. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lthigh, false)
  843. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Luparm, false)
  844. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lforearm, false)
  845. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lhand, false)
  846. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.Lfoot, false)
  847. ragdoll:SetNWBool("clientboneisgibbed" .. ragdoll.pelvis, false)
  848. --body dosn't need to be included (these are for drip effects so when the bodys gone there wont be any)
  849.  
  850. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Head, false)
  851. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rcalf, false)
  852. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.RUcalf, false)
  853. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rthigh, false)
  854. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Ruparm, false)
  855. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rforearm, false)
  856. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rhand, false)
  857. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Rfoot, false)
  858. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lcalf, false)
  859. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.LUcalf, false)
  860. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lthigh, false)
  861. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Luparm, false)
  862. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lforearm, false)
  863. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lhand, false)
  864. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.Lfoot, false)
  865. ragdoll:SetNWBool("boneisgibbed" .. ragdoll.pelvis, false)
  866.  
  867. //Apply Kill Damage
  868. local physbone = DMGetClosestPhysBone(ragdoll, dmgpos)
  869. local bone = ragdoll:TranslatePhysBoneToBone(physbone)
  870. local phys = ragdoll:GetPhysicsObjectNum(physbone)
  871.  
  872. if dmgtype != 6144 and dmgtype != 32 then
  873. if bone != ragdoll.body and bone != ragdoll.pelvis and bone != ragdoll.Head then
  874. local dmginfo = DamageInfo()
  875. dmginfo:SetDamage(dmgammount)
  876. dmginfo:SetDamageType(dmgtype)
  877. dmginfo:SetDamagePosition(dmgpos)
  878. dmginfo:SetDamageForce(dmgforce)
  879.  
  880. ragdoll:TakeDamageInfo(dmginfo)
  881. phys:AddVelocity(dmgforce)
  882. elseif bone == ragdoll.body or bone == ragdoll.pelvis or bone == ragdoll.Head then
  883. local dmginfo = DamageInfo()
  884. dmginfo:SetDamage(dmgammount)
  885. //overides the scaled damage
  886. dmginfo:SetDamageType(dmgtype)
  887. dmginfo:SetDamagePosition(dmgpos)
  888. dmginfo:SetDamageForce(dmgforce)
  889.  
  890. ragdoll:TakeDamageInfo(dmginfo)
  891. phys:AddVelocity(dmgforce)
  892. end
  893. end
  894.  
  895. if dmgtype == 32 and dmgammount > 50 then
  896. local dmginfo = DamageInfo()
  897.  
  898. dmginfo:SetDamageType(32)
  899. dmginfo:SetDamage(1000000)
  900. dmginfo:SetDamagePosition(dmgpos)
  901. dmginfo:SetDamageForce(dmgforce)
  902.  
  903. ragdoll:TakeDamageInfo(dmginfo)
  904.  
  905. ragdoll.hHead = 0
  906. end
  907.  
  908. if onfire then
  909. ragdoll:Ignite(math.random(8, 10), 15)
  910. end
  911.  
  912. if isnpc and IsValid(ragdoll:GetPhysicsObject()) then
  913. ragdoll:GetPhysicsObject():SetVelocity(npcvel)
  914.  
  915. local bones = ragdoll:GetPhysicsObjectCount()
  916.  
  917. for i = 1, bones - 1 do
  918. local bone = ragdoll:GetPhysicsObjectNum(i)
  919. if IsValid(bone) then
  920. local bonepos, boneang = ply:GetBonePosition(ragdoll:TranslatePhysBoneToBone(i))
  921. bone:SetPos(bonepos)
  922. bone:SetAngles(boneang)
  923. bone:SetVelocity(ragdoll:GetVelocity())
  924. end
  925. end
  926. ply:Remove()
  927. end
  928. return ragdoll
  929. end
  930. end
  931.  
  932. -- Creates client or server ragdoll depending on settings
  933. function CORPSE.Create(ply, attacker, dmginfo)
  934. if not IsValid(ply) then return end
  935.  
  936. local rag = ents.Create("prop_ragdoll")
  937. if not IsValid(rag) then return nil end
  938.  
  939. rag:SetPos(ply:GetPos())
  940. rag:SetModel(ply:GetModel())
  941. rag:SetAngles(ply:GetAngles())
  942. rag:SetColor(ply:GetColor())
  943.  
  944. rag:Spawn()
  945. rag:Activate()
  946.  
  947. -- nonsolid to players, but can be picked up and shot
  948. rag:SetCollisionGroup(rag_collide:GetBool() and COLLISION_GROUP_WEAPON or COLLISION_GROUP_DEBRIS_TRIGGER)
  949.  
  950. -- flag this ragdoll as being a player's
  951. rag.player_ragdoll = true
  952. rag.uqid = ply:UniqueID()
  953.  
  954. -- network data
  955. CORPSE.SetPlayerNick(rag, ply)
  956. CORPSE.SetFound(rag, false)
  957. CORPSE.SetCredits(rag, ply:GetCredits())
  958.  
  959. --custom
  960. rag.pnick = ply:Nick()
  961.  
  962. -- if someone searches this body they can find info on the victim and the
  963. -- death circumstances
  964. rag.equipment = ply:GetEquipmentItems()
  965. rag.was_role = ply:GetRole()
  966. rag.bomb_wire = ply.bomb_wire
  967. rag.dmgtype = dmginfo:GetDamageType()
  968.  
  969. local wep = util.WeaponFromDamage(dmginfo)
  970. rag.dmgwep = IsValid(wep) and wep:GetClass() or ""
  971.  
  972. rag.was_headshot = (ply.was_headshot and dmginfo:IsBulletDamage())
  973. rag.time = CurTime()
  974. rag.kills = table.Copy(ply.kills)
  975.  
  976. rag.killer_sample = GetKillerSample(ply, attacker, dmginfo)
  977.  
  978. -- crime scene data
  979. rag.scene = GetSceneData(ply, attacker, dmginfo)
  980.  
  981.  
  982. -- position the bones
  983. local num = rag:GetPhysicsObjectCount()-1
  984. local v = ply:GetVelocity()
  985.  
  986. -- bullets have a lot of force, which feels better when shooting props,
  987. -- but makes bodies fly, so dampen that here
  988. if dmginfo:IsDamageType(DMG_BULLET) or dmginfo:IsDamageType(DMG_SLASH) then
  989. v = v / 5
  990. end
  991.  
  992. for i=0, num do
  993. local bone = rag:GetPhysicsObjectNum(i)
  994. if IsValid(bone) then
  995. local bp, ba = ply:GetBonePosition(rag:TranslatePhysBoneToBone(i))
  996. if bp and ba then
  997. bone:SetPos(bp)
  998. bone:SetAngles(ba)
  999. end
  1000.  
  1001. -- not sure if this will work:
  1002. bone:SetVelocity(v)
  1003. end
  1004. end
  1005.  
  1006. -- create advanced death effects (knives)
  1007. if ply.effect_fn then
  1008. -- next frame, after physics is happy for this ragdoll
  1009. local efn = ply.effect_fn
  1010. timer.Simple(0, function() efn(rag) end)
  1011. end
  1012.  
  1013. if ply.inactivity then
  1014. ply.inactivity = false
  1015. IdentifySlainBody(rag)
  1016. end
  1017.  
  1018. return rag -- we'll be speccing this
  1019. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement