TTT adding avatar to corpse.

Hello! I have a weapon that allows traitor’s to fake their death. However when you check the fake corpse it shows a blue question mark instead of the steam avatar. Anyone know how to fix this so the fake body will show the avatar? Code Below:



////////////////////
//Dead Ringer Swep//
///////Update///////
////by NECROSSIN////
////////////////////
///TTT Convert by///
///////PORTER///////
////////////////////

--Updated: 24 January 2010
--Converted : 01 May 2014

----------------------------
--////////////////////////--
local REDUCEDAMAGE = 1
--////////////////////////--
----------------------------

--was -- this SWEP uses models, textures and sounds from TF2, so be sure that you have it if you dont want to see an ERROR instead of swep model and etc...
--now -- included models, textures and sounds from TF2, so u don't need to install TeamFortress2...

resource.AddFile( "materials/vgui/ttt/weapon_dead_ringer.vmt" )
resource.AddFile( "materials/vgui/ttt/weapon_dead_ringer.vtf" )
resource.AddFile( "sound/ttt/recharged.wav" )
resource.AddFile( "sound/ttt/spy_uncloak_feigndeath.wav" )
resource.AddFile( "models/ttt/v_models/v_watch_pocket_spy.mdl" )
resource.AddFile( "models/ttt/v_models/v_watch_pocket_spy.sw.vtx" )
resource.AddFile( "models/ttt/c_models/c_pocket_watch.mdl" )
resource.AddFile( "models/ttt/c_models/c_pocket_watch.sw.vtx" )
resource.AddFile( "materials/vgui/ttt/misc_ammo_area_red.vmt" )
resource.AddFile( "materials/vgui/ttt/gradient_red.vtf" )
resource.AddFile( "materials/vgui/ttt/misc_ammo_area_mask.vtf" )
resource.AddFile( "materials/models/ttt/c_pocket_watch/c_pocket_watch.vtf" )
resource.AddFile( "materials/models/ttt/c_pocket_watch/c_pocket_watch.vmt" )
resource.AddFile( "materials/models/player/pyro/pyro_lightwarp.vtf" )
resource.AddFile( "materials/models/player/spy/spy_exponent.vtf" )
resource.AddFile( "materials/models/player/spy/spy_hands_blue.vmt" )
resource.AddFile( "materials/models/player/spy/spy_hands_blue.vtf" )
resource.AddFile( "materials/models/player/spy/spy_hands_normal.vtf" )
resource.AddFile( "materials/models/player/spy/spy_hands_red.vmt" )
resource.AddFile( "materials/models/player/spy/spy_hands_red.vtf" )
resource.AddFile( "materials/models/weapons/c_items/c_pocket_watch.vmt" )
resource.AddFile( "materials/models/weapons/c_items/c_pocket_watch.vtf" )
resource.AddFile( "materials/models/weapons/c_items/c_pocket_watch_lightwarp" )
resource.AddFile( "materials/models/weapons/c_items/c_pocket_watch_phongwarp.vtf" )
resource.AddFile( "sound/ttt/walk_to_sprint.wav" )
resource.AddFile( "sound/ttt/sprint_to_walk.wav" )
if SERVER then util.AddNetworkString("FakePlayerDeathrun")
end

if SERVER then util.AddNetworkString("FakePlayerDeathwalk")
end

--------------------------------------------------------------------------
if (SERVER) then

	AddCSLuaFile( "shared.lua" )
	SWEP.Weight				= 5
	SWEP.AutoSwitchTo			= false
	SWEP.AutoSwitchFrom		= false
	SWEP.HoldType			= "normal"
	
end

--------------------------------------------------------------------------

if ( CLIENT ) then
	SWEP.PrintName			= "Dead Ringer"	
	SWEP.Slot = 6

	SWEP.EquipMenuData = {
   	   type = "item_weapon",
           desc = "Left click enables the dead ringer
Fakes death when damaged + 3 second Speed boost
Cloak lasts for 14 seconds max
Dead Ringer takes 28 seconds max to recharge
CANNOT BE DROPPED!!"
        };
                                                                                                                                                                    
	SWEP.Icon = "vgui/ttt/weapon_dead_ringer"

	SWEP.Author				= "NECROSSIN (fixed by Niandra Lades / Converted by Porter)"
	SWEP.DrawAmmo 			= false
	SWEP.DrawCrosshair 		= false
	SWEP.ViewModelFOV			= 55
	SWEP.ViewModelFlip		= false
	SWEP.CSMuzzleFlashes		= false
	SWEP.WepSelectIcon = surface.GetTextureID("models/ttt/c_pocket_watch/c_pocket_watch.vtf") -- texture from TF2
	
	SWEP.IconLetter			= "G"
	
	surface.CreateFont( "DRfont", {
	font = "coolvertica",
	size = 13,
	weight = 500,
	blursize = 0,
	scanlines = 0,
	antialias = true,
	underline = false,
} )

function drawdr()
--here goes the new HUD
if LocalPlayer():GetNWBool("Status") == 1 or LocalPlayer():GetNWBool("Status") == 3 or LocalPlayer():GetNWBool("Status") == 4 and LocalPlayer():Alive() then
local background = surface.GetTextureID("vgui/ttt/misc_ammo_area_red")
local w,h = surface.GetTextureSize(surface.GetTextureID("vgui/ttt/misc_ammo_area_red"))
	surface.SetTexture(background)
	surface.SetDrawColor(255,255,255,255)
	surface.DrawTexturedRect(13, ScrH() - h - 200, w*5, h*5 )

local energy = math.max(LocalPlayer():GetNWInt("drcharge"), 0)
draw.RoundedBox(2,44, ScrH() - h - 168, (energy / 8) * 77, 15, Color(255,222,255,255))
surface.SetDrawColor(255,255,255,255)
surface.DrawOutlinedRect(44, ScrH() - h - 168, 77, 15)
draw.DrawText("CLOAK", "DRfont",65, ScrH() - h - 150, Color(255,255,255,255))
end

end
hook.Add("HUDPaint", "drawdr", drawdr)

local function DRReady(um)
surface.PlaySound( "ttt/recharged.wav" )
end
usermessage.Hook("DRReady", DRReady)
end 

-------------------------------------------------------------------

SWEP.Category				= "Spy"

SWEP.Spawnable				= false
SWEP.AdminSpawnable			= true

SWEP.Purpose        	= "Fake your death!"

SWEP.Instructions   	= "Primary - turn on.
Secondary - turn off or drop cloak."

SWEP.ViewModel 				= "models/ttt/v_models/v_watch_pocket_spy.mdl"
SWEP.WorldModel 			= "" 

SWEP.Weight					= 5 
SWEP.AutoSwitchTo				= false
SWEP.AutoSwitchFrom			= false
SWEP.Category = "Dead Ringer"
SWEP.Kind = WEAPON_EQUIP
SWEP.CanBuy = {ROLE_TRAITOR}
SWEP.WeaponID = AMMO_DEADRING
SWEP.LimitedStock = true
SWEP.Base = "weapon_tttbase"
SWEP.AllowDrop = false
SWEP.NoSights = true

SWEP.Primary.ClipSize			= -1
SWEP.Primary.DefaultClip		= -1
SWEP.Primary.Ammo				= ""

SWEP.Secondary.ClipSize			= -1
SWEP.Secondary.DefaultClip		= -1
SWEP.Secondary.Ammo			= "none" 
------------------------------------------
NPCs = { -- if you have custom NPC-enemies, you can add them here
"npc_zombie",
"npc_fastzombie",
"npc_zombie_torso",
"npc_poisonzombie",
"npc_antlion",
"npc_antlionguard",
"npc_hunter",
"npc_antlion_worker",
"npc_headcrab_black",
"npc_headcrab",
"npc_headcrab_fast",
"npc_combine_s",
"npc_zombine",
"npc_fastzombie_torso",
"npc_rollermine",
"npc_turret_floor",
"npc_cscanner",
"npc_clawscanner",
"npc_manhack",
"npc_tripmine",
"npc_barnacle",
"npc_strider",
"npc_metropolice",
}

-----------------------------------------------------------------------

-- disable dead rnger on spawn
if SERVER then
	function dringerspawn( p )
if p:GetNWBool("Dead") == true then
p:SetNWBool(	"Status",			0)
p:GetViewModel():SetMaterial("")
p:SetMaterial("")
p:SetColor(255,255,255,255)
end
p:SetNWBool(	"Status",			0)
p:SetNWBool(	"Dead",			false)
p:SetNWBool(	"CanAttack",			true)
p:SetNWInt("drcharge", 8 )

	end
	hook.Add( "PlayerSpawn", "DRingerspawn", dringerspawn );
end
-----------------------------------
function SWEP:Initialize()
	self:SetWeaponHoldType("normal")
        util.PrecacheSound ( "sound/ttt/sprint_to_walk.wav" )
        util.PrecacheSound ( "sound/ttt/walk_to_sprint.wav" )
end
-----------------------------------
function SWEP:Deploy()
if SERVER then
		self.Owner:DrawWorldModel(false)
		self.Owner:DrawWorldModel(false)

local ent = ents.Create("deadringer")			
ent:SetOwner(self.Owner) 
ent:SetParent(self.Owner)
ent:SetPos(self.Owner:GetPos())
ent:SetColor(self.Owner:GetColor())
ent:SetMaterial(self.Owner:GetMaterial())
ent:Spawn()	
end

self.Weapon:SendWeaponAnim( ACT_VM_DRAW )
if !self.Owner:GetNWBool("Status") == 3 or !self.Owner:GetNWBool("Status") == 4 or !self.Owner:GetNWBool("Status") == 1 then
self.Owner:SetNWBool(	"Status",			2)
end
return true
end
-----------------------------------
function SWEP:Think()
end

function SWEP:Holster()
	local worldmodel = ents.FindInSphere(self.Owner:GetPos(),0.6)
	for k, v in pairs(worldmodel) do 
if v:GetClass() == "deadringer" and v:GetOwner() == self.Owner then
if ( SERVER) then v:Remove()
end
end
end
return true
end

-----------------------------------
--------View Model material--------
-----------------------------------

if CLIENT then
function drvm()

if LocalPlayer():GetNWBool("Dead") == true and LocalPlayer():Alive() then 
LocalPlayer():GetViewModel():SetMaterial( "models/props_c17/fisheyelens")

elseif LocalPlayer():GetNWBool("Dead") == false and LocalPlayer():Alive() then
LocalPlayer():GetViewModel():SetMaterial("models/weapons/v_crowbar.mdl")
end
end
hook.Add( "Think", "DRVM", drvm )
end


-----------------------------------------------------------

---------------------------------
---------hooks--------
---------------------------------
if SERVER then

function checkifwehaveourdr(ent,dmginfo)
local attacker = dmginfo:GetAttacker()
local getdmg = dmginfo:GetDamage()
local reducedmg = getdmg * REDUCEDAMAGE
	if ent:IsPlayer() then
	local p = ent
	local infl
		if attacker:GetClass() == "trigger_hurt" or attacker:GetClass() == "func_rotating" or attacker:GetClass() == "func_physbox" then
			if p:GetNWBool("CanAttack") == true and p:GetNWBool("Dead") == false and p:GetNWBool("Status") == 1 then
			dmginfo:SetDamage(math.random(5,15))
			p:fakedeath()
			elseif p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
			dmginfo:SetDamage(math.random(0,1))
			end
		elseif attacker:IsPlayer() then
			if p:GetNWBool("CanAttack") == true and p:GetNWBool("Dead") == false and p:GetNWBool("Status") == 1 then
			dmginfo:SetDamage(getdmg - reducedmg )
			p:fakedeath()
			elseif p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
			dmginfo:SetDamage(getdmg - reducedmg )
			end
		elseif attacker:IsNPC() then
			if p:GetNWBool("CanAttack") == true and p:GetNWBool("Dead") == false and p:GetNWBool("Status") == 1 then
			dmginfo:SetDamage(getdmg - reducedmg )
			p:fakedeath()
			-- if npc has weapon (eg: metrocop with stunstick) then inflictor = npc's weapon
			if IsValid(attacker:GetActiveWeapon()) then
			infl = attacker:GetActiveWeapon():GetClass()
			-- else  (eg: zombie or hunter) then inflictor = attacker
			else
			infl = attacker:GetClass()
			end
			elseif p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
			dmginfo:SetDamage(getdmg - reducedmg )
			end
		else
			if p:GetNWBool("CanAttack") == true and p:GetNWBool("Dead") == false and p:GetNWBool("Status") == 1 then
			dmginfo:SetDamage(getdmg - reducedmg )
			p:fakedeath()
			elseif p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
			dmginfo:SetDamage(getdmg - reducedmg )
			end
		end
	end
end
hook.Add("EntityTakeDamage", "CheckIfWeHaveDeadRinger", checkifwehaveourdr)
end
if SERVER then
function disablefakecorpseondeath(p, attacker)
if p:IsValid() and p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
p:uncloak()
end
end
hook.Add("DoPlayerDeath", "RemoveFakeCorpse", disablefakecorpseondeath)

-- here goes the dead ringer charge/regenerating system
function drthink()
	for _, p in pairs(player.GetAll()) do
		if p:IsValid() and p:GetNWBool("Dead") == false and p:GetNWBool("Status") == 4 then
			if p:GetNWInt("drcharge") < 8 then
			p.drtimer = p.drtimer or CurTime() + 0.1
				if CurTime() > p.drtimer then
				p.drtimer = CurTime() + 4
				p:SetNWInt("drcharge", p:GetNWInt("drcharge") + 1)
				end
			elseif 	p:GetNWInt("drcharge") == 8 then
			p:SetNWBool("Status", 1)
			umsg.Start( "DRReady", p )
			umsg.End()
			end
		elseif p:IsValid() and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then
			for _, v in pairs(p:GetWeapons()) do
			v:SetNextPrimaryFire(CurTime() + 0.2)
			v:SetNextSecondaryFire(CurTime() +0.2)
			end
			p:DrawWorldModel(false)
			for _,npc in pairs(ents.GetAll()) do 
				if npc:IsNPC() then 
					for _,v in pairs(NPCs) do
						if npc:GetClass() == v then
						npc:AddEntityRelationship(p,D_NU,99)
						end
					end
				end
			end
			if p:KeyPressed( IN_ATTACK2 ) then
			p:uncloak()
			p:SetNWInt("drcharge", 2 )
			end
			if p:GetNWInt("drcharge") <= 8 and p:GetNWInt("drcharge") > 0 then
			p.cltimer = p.cltimer or CurTime() + 2
				if CurTime() > p.cltimer then
				p.cltimer = CurTime() + 2
				p:SetNWInt("drcharge", p:GetNWInt("drcharge") - 1)
				end
			elseif p:GetNWInt("drcharge") == 0 then
				p:uncloak()
			end
		end
	end
end
hook.Add( "Think", "DR_ENERGY", drthink )



end

function DRFootsteps( p, vPos, iFoot, strSoundName, fVolume, pFilter )

if p:Alive() and p:IsValid() then

if p:GetNWBool("CanAttack") == false and p:GetNWBool("Dead") == true and p:GetNWBool("Status") == 3 then

if CLIENT then
return true
end
end
end
end

hook.Add("PlayerFootstep","DeadRingerFootsteps",DRFootsteps)


-------------------------------------------------------------------------------

function SWEP:PrimaryAttack()



if self.Owner:GetNWBool("CanAttack") == true and self.Owner:GetNWBool("Dead") == false and self.Owner:GetNWBool("Status") != 4 then

self.Owner:SetNWBool(	"Status",			1)

if CLIENT then
   surface.PlaySound("buttons/blip1.wav")
end

else
return
end
end

function SWEP:SecondaryAttack()



if self.Owner:GetNWBool("CanAttack") == true and self.Owner:GetNWBool("Dead") == false and self.Owner:GetNWBool("Status") != 4 then
self.Owner:SetNWBool(	"Status",			2)

if CLIENT then
   surface.PlaySound("buttons/blip1.wav")
end
else
return
end
end
-------------------------------------------------------------------------------------

-- this has to go out of everything. Not inside any function nor anything else.

if CLIENT then net.Receive("FakePlayerDeathrun", function(len, ply)
     surface.PlaySound("ttt/walk_to_sprint.wav")
end)
end

-- this has to go out of everything. Not inside any function nor anything else.
if CLIENT then net.Receive("FakePlayerDeathwalk", function(len, ply)
     surface.PlaySound("ttt/sprint_to_walk.wav")
end)
end

local plymeta = FindMetaTable( "Player" );

function plymeta:fakedeath()

timer.Simple(0.1, function()
    if IsValid(self) then
      self.DringerSpeed = 1.5
       -- you have to call this function when you want to play the sound
       net.Start("FakePlayerDeathrun")
       net.Send(self) -- here has to go the player you want to hear that sound.
       -- and if you want all players to hear it use instead net.Broadcast()
    end
end)


timer.Simple(3.1, function()
    if IsValid(self) then
        self.DringerSpeed = 1
        -- you have to call this function when you want to play the sound
        net.Start("FakePlayerDeathwalk")
        net.Send(self) -- here has to go the player you want to hear that sound.
        -- and if you want all players to hear it use instead net.Broadcast()
    end
end)

self:SetNWBool("Dead", true)
self:SetNWBool("CanAttack", false)
self:SetNWBool("Status", 3)
self:SetColor(Color(255,255,255,0))
self:SetNoDraw(true)
self:SetNWBool("disguised", true)


---------------------------
--------"corpse"-------
---------------------------
-- this is time to make our corpse

	local weapons = {"weapon_zm_pistol","weapon_ttt_m16","weapon_zm_revolver","weapon_zm_shotgun","weapon_ttt_glock","weapon_zm_mac10","weapon_zm_revolver","weapon_zm_sledge"}

	local dmginfo = DamageInfo()  
	dmginfo:SetDamage( math.random(10,100) )
	dmginfo:SetDamageType( DMG_BULLET )

-- create the ragdoll
	local rag = ents.Create("prop_ragdoll", dmginfo)

	rag:SetPos(self:GetPos())
	rag:SetModel(self:GetModel())
	rag:SetAngles(self:GetAngles())
	rag:SetColor(self:GetColor())
	rag.SetOwner(self)
	self:SetCollisionGroup( COLLISION_GROUP_PASSABLE_DOOR )

	rag:Spawn(self)
	rag:Activate(self)

	-- flag this ragdoll as being a player's
	rag.player_ragdoll = self
	rag.uqid = self:UniqueID()
  
	self:SetNWBool("is_pretending", true)
	self:SetNWString("nick", self:Nick())

	-- network data
	CORPSE.SetPlayerNick(rag, self)
	CORPSE.SetCredits(rag, 0)

	-- if someone searches this body they can find info on the victim and the
	-- death circumstances
	rag.equipment = self:GetEquipmentItems()
 	rag.was_role = ROLE_INNOCENT
	rag.bomb_wire = false
	rag.dmgtype = ( DMG_BULLET )

	rag.dmgwep  = table.Random(weapons)

    rag.was_headshot = table.Random({true, false}) -- Random chance of dying from a headshot
	rag.time = CurTime()
	rag.kills = {}
    rag:EmitSound("vo/npc/male01/pain07.wav")
        if rag.was_headshot == true then
        rag:EmitSound("")
        else
        rag:EmitSound("vo/npc/male01/pain07.wav")
        end
	rag.killer_sample = nil

	-- position the bones
	local num = rag:GetPhysicsObjectCount()-1
	local v = self:GetVelocity()

	for i=0, num do
	local bone = rag:GetPhysicsObjectNum(i)
		
		if IsValid(bone) then
		local bp, ba = self:GetBonePosition(rag:TranslatePhysBoneToBone(i))
			if bp and ba then
				bone:SetPos(bp)
				bone:SetAngles(ba)
			end
		end
	end
end

-- here goes the uncloak function
function plymeta:uncloak()

	for _, rag in pairs(ents.GetAll()) do
		if rag:GetClass() == "prop_ragdoll" and rag.player_ragdoll == self then
		if (SERVER) then rag:Remove()
                      end
		end
	end
	
	for _,npc in pairs(ents.GetAll()) do 
		if npc:IsNPC() then 
			for k,v in pairs(NPCs) do 
				if npc:GetClass() == v then
				npc:AddEntityRelationship(self,D_HT,99) 
				end
			end
		end
	end
	
	self:SetNWBool(	"Dead",			false)
	self:SetNWBool(	"CanAttack",			true)
	self:SetNWBool(	"Status",			4)
	self:GetViewModel():SetMaterial("")
	self:SetMaterial("")
	self:SetColor(Color(255,255,255,255))
	self:SetNoDraw(false)
	self:SetNWBool("is_pretending", false)
	self:SetNWBool("disguised", false)

	
	self:DrawWorldModel(true)

	self:SetMaterial("")

	self:EmitSound(Sound( "ttt/spy_uncloak_feigndeath.wav" ))

	local effectdata = EffectData()
	effectdata:SetOrigin( self:GetPos() )
	effectdata:SetEntity( self )
	util.Effect( "uncloak", effectdata )

end

function DRinger_Speed(self,slowed)
if self.DringerSpeed != nil then
return self.DringerSpeed
else
return 1
end
end
hook.Add( "TTTPlayerSpeed", "Dead Ringer Speed Change", DRinger_Speed )

function SWEP:ShouldDropOnDie()
	return false
end


Replace:



rag.uqid = self:UniqueID()


With:



rag.sid = self:SteamID()


Still didn’t work :\

Do you have replaced the cl_search.lua file with the cl_search.lua file from the dead ringer?
If I’m not wrong then this file is outdated.

Avatar images use Steam64ID’s instead of UniqueID’s or SteamID’s. That might be the issue.

Edit: The code you’re using is out of date or you have a custom cl_search. There are a few other issues, but if you’d like to only fix the avatar, replace: rag.uqid = self:UniqueID() with rag.owner = self

I have the Dead Ringer addon with the cl_search.lua file that came with it. I tried removing it and then tried keeping it, both had no luck.

[editline]10th August 2016[/editline]

Here is the cl_search.lua that came with the Dead Ringer.



-- Body search popup

local T = LANG.GetTranslation
local PT = LANG.GetParamTranslation

local is_dmg = util.BitSet

-- "From his body you can tell XXX"
local function DmgToText(d)
   if is_dmg(d, DMG_CRUSH) then
      return T("search_dmg_crush")
   elseif is_dmg(d, DMG_BULLET) then
      return T("search_dmg_bullet")
   elseif is_dmg(d, DMG_FALL) then
      return T("search_dmg_fall")
   elseif is_dmg(d, DMG_BLAST) then
      return T("search_dmg_boom")
   elseif is_dmg(d, DMG_CLUB) then
      return T("search_dmg_club")
   elseif is_dmg(d, DMG_DROWN) then
      return T("search_dmg_drown")
   elseif is_dmg(d, DMG_SLASH) then
      return T("search_dmg_stab")
   elseif is_dmg(d, DMG_BURN) or is_dmg(d, DMG_DIRECT) then
      return T("search_dmg_burn")
   elseif is_dmg(d, DMG_SONIC) then
      return T("search_dmg_tele")
   elseif is_dmg(d, DMG_VEHICLE) then
      return T("search_dmg_car")
   else
      return T("search_dmg_other")
   end
end

-- Info type to icon mapping

-- Some icons have different appearances based on the data value. These have a
-- separate table inside the TypeToMat table.

-- Those that have a lot of possible data values are defined separately, either
-- as a function or a table.

local function DmgToMat(d)
   if is_dmg(d, DMG_BULLET) then
      return "bullet"
   elseif is_dmg(d, DMG_CRUSH) then
      return "rock"
   elseif is_dmg(d, DMG_BLAST) then
      return "splode"
   elseif is_dmg(d, DMG_FALL) then
      return "fall"
   elseif is_dmg(d, DMG_BURN) or is_dmg(d, DMG_DIRECT) then
      return "fire"
   else
      return "skull"
   end
end

local function WeaponToIcon(d)
   local wep = util.WeaponForClass(d)
   return wep and wep.Icon or "VGUI/ttt/icon_nades"
end

local TypeToMat = {
   nick="id",
   words="halp",
   eq_armor="armor",
   eq_radar="radar",
   eq_disg="disguise",
   role={[ROLE_TRAITOR]="traitor", [ROLE_DETECTIVE]="det", [ROLE_INNOCENT]="inno"},
   c4="code",
   dmg=DmgToMat,
   wep=WeaponToIcon,
   head="head",
   dtime="time",
   stime="wtester",
   lastid="lastid",
   kills="list"
};

-- Accessor for better fail handling
local function IconForInfoType(t, data)
   local base = "VGUI/ttt/icon_"
   local mat = TypeToMat[t]

   if type(mat) == "table" then
      mat = mat[data]
   elseif type(mat) == "function" then
      mat = mat(data)
   end

   if not mat then
      mat = TypeToMat["nick"]
   end

   -- ugly special casing for weapons, because they are more likely to be
   -- customized and hence need more freedom in their icon filename
   if t != "wep" then
      return base .. mat
   else
      return mat
   end
end


function PreprocSearch(raw)
   local search = {}
   for t, d in pairs(raw) do
      search[t] = {img=nil, text="", p=10}

      if t == "nick" then
         search[t].text = PT("search_nick", {player = d})
         search[t].p = 1
         search[t].nick = d
      elseif t == "role" then
         if d == ROLE_TRAITOR then
            search[t].text = T("search_role_t")
         elseif d == ROLE_DETECTIVE then
            search[t].text = T("search_role_d")
         else
            search[t].text = T("search_role_i")
         end

         search[t].p = 2
      elseif t == "words" then
         if d != "" then
            -- only append "--" if there's no ending interpunction
            local final = string.match(d, "[\\.\\!\\?]$") != nil

            search[t].text = PT("search_words", {lastwords = d .. (final and "" or "--.")})
         end
      elseif t == "eq_armor" then
         if d then
            search[t].text = T("search_armor")
            search[t].p = 17
         end
      elseif t == "eq_disg" then
         if d then
            search[t].text = T("search_disg")
            search[t].p = 18
         end
      elseif t == "eq_radar" then
         if d then
            search[t].text = T("search_radar")

            search[t].p = 19
         end
      elseif t == "c4" then
         if d > 0 then
            search[t].text= PT("search_c4", {num = d})
         end
      elseif t == "dmg" then
         search[t].text = DmgToText(d)
         search[t].p = 12
      elseif t == "wep" then
         local wep = util.WeaponForClass(d)
         local wname = wep and LANG.TryTranslation(wep.PrintName)

         if wname then
            search[t].text = PT("search_weapon", {weapon = wname})
         end
      elseif t == "head" then
         if d then
            search[t].text = T("search_head")
         end
         search[t].p = 15
      elseif t == "dtime" then
         if d != 0 then
            local ftime = util.SimpleTime(d, "%02i:%02i")
            search[t].text = PT("search_time", {time = ftime})

            search[t].text_icon = ftime

            search[t].p = 8
         end
      elseif t == "stime" then
         if d > 0 then
            local ftime = util.SimpleTime(d, "%02i:%02i")
            search[t].text = PT("search_dna", {time = ftime})

            search[t].text_icon = ftime
         end
      elseif t == "kills" then
         local num = table.Count(d)
         if num == 1 then
            local vic = Entity(d[1])
            local dc = d[1] == -1 -- disconnected
            if dc or (IsValid(vic) and vic:IsPlayer()) then
               search[t].text = PT("search_kills1", {player = (dc and "<Disconnected>" or vic:Nick())})
            end
         elseif num > 1 then
            local txt = T("search_kills2") .. "
"

            local nicks = {}
            for k, idx in pairs(d) do
               local vic = Entity(idx)
               local dc = idx == -1
               if dc or (IsValid(vic) and vic:IsPlayer()) then
                  table.insert(nicks, (dc and "<Disconnected>" or vic:Nick()))
               end
            end

            local last = #nicks
            txt = txt .. table.concat(nicks, "
", 1, last)
            search[t].text = txt
         end

         search[t].p = 30
      elseif t == "lastid" then
         if d and d.idx != -1 then
            local ent = Entity(d.idx)
            if IsValid(ent) and ent:IsPlayer() then
               search[t].text = PT("search_eyes", {player = ent:Nick()})

               search[t].ply = ent
            end
         end
      else
         -- Not matching a type, so don't display
         search[t] = nil
      end

      -- anything matching a type but not given a text should be removed
      if search[t] and search[t].text == "" then
         search[t] = nil
      end

      -- if there's still something here, we'll be showing it, so find an icon
      if search[t] then
         search[t].img = IconForInfoType(t, d)
      end
   end

   return search
end


-- Returns a function meant to override OnActivePanelChanged, which modifies
-- dactive and dtext based on the search information that is associated with the
-- newly selected panel
local function SearchInfoController(search, dactive, dtext)
   return function(s, pold, pnew)
             local t = pnew.info_type
             local data = search[t]
             if not data then
                ErrorNoHalt("Search: data not found", t, data,"
")
                return
             end

             -- If wrapping is on, the Label's SizeToContentsY misbehaves for
             -- text that does not need wrapping. I long ago stopped wondering
             -- "why" when it comes to VGUI. Apply hack, move on.
             dtext:GetLabel():SetWrap(#data.text > 50)

             dtext:SetText(data.text)
             dactive:SetImage(data.img)
          end
end

local function ShowSearchScreen(search_raw)
   local client = LocalPlayer()
   if not IsValid(client) then return end

   local m = 8
   local bw, bh = 100, 25
   local w, h = 410, 260

   local rw, rh = (w - m*2), (h - 25 - m*2)
   local rx, ry = 0, 0

   local rows = 1
   local listw, listh = rw, (64 * rows + 6)
   local listx, listy = rx, ry

   ry = ry + listh + m*2
   rx = m

   local descw, desch = rw - m*2, 80
   local descx, descy = rx, ry

   ry = ry + desch + m

   local butx, buty = rx, ry

   local dframe = vgui.Create("DFrame")
   dframe:SetSize(w, h)
   dframe:Center()
   dframe:SetTitle(T("search_title") .. " - " .. search_raw.nick or "???")
   dframe:SetVisible(true)
   dframe:ShowCloseButton(true)
   dframe:SetMouseInputEnabled(true)
   dframe:SetKeyboardInputEnabled(true)
   dframe:SetDeleteOnClose(true)

   dframe.OnKeyCodePressed = util.BasicKeyHandler

   -- contents wrapper
   local dcont = vgui.Create("DPanel", dframe)
   dcont:SetPaintBackground(false)
   dcont:SetSize(rw, rh)
   dcont:SetPos(m, 25 + m)

   -- icon list
   local dlist = vgui.Create("DPanelSelect", dcont)
   dlist:SetPos(listx, listy)
   dlist:SetSize(listw, listh)
   dlist:EnableHorizontal(true)
   dlist:SetSpacing(1)
   dlist:SetPadding(2)

   if dlist.VBar then
      dlist.VBar:Remove()
      dlist.VBar = nil
   end

   -- description area
   local dscroll = vgui.Create("DHorizontalScroller", dlist)
   dscroll:StretchToParent(3,3,3,3)

   local ddesc = vgui.Create("ColoredBox", dcont)
   ddesc:SetColor(Color(50, 50, 50))
   ddesc:SetName(T("search_info"))
   ddesc:SetPos(descx, descy)
   ddesc:SetSize(descw, desch)

   local dactive = vgui.Create("DImage", ddesc)
   dactive:SetImage("VGUI/ttt/icon_id")
   dactive:SetPos(m, m)
   dactive:SetSize(64, 64)

   local dtext = vgui.Create("ScrollLabel", ddesc)
   dtext:SetSize(descw - 120, desch - m*2)
   dtext:MoveRightOf(dactive, m*2)
   dtext:AlignTop(m)
   dtext:SetText("...")

   -- buttons
   local by = rh - bh - (m/2)

   local dident = vgui.Create("DButton", dcont)
   dident:SetPos(m, by)
   dident:SetSize(bw,bh)
   dident:SetText(T("search_confirm"))
   local id = search_raw.eidx + search_raw.dtime
   dident.DoClick = function() RunConsoleCommand("ttt_confirm_death", search_raw.eidx, id) end
   dident:SetDisabled(client:IsSpec() or (not client:KeyDownLast(IN_WALK)))

   local dcall = vgui.Create("DButton", dcont)
   dcall:SetPos(m*2 + bw, by)
   dcall:SetSize(bw, bh)
   dcall:SetText(T("search_call"))
   dcall.DoClick = function(s)
                      client.called_corpses = client.called_corpses or {}
                      table.insert(client.called_corpses, search_raw.eidx)
                      s:SetDisabled(true)

                      RunConsoleCommand("ttt_call_detective", search_raw.eidx)
                   end

   dcall:SetDisabled(client:IsSpec() or table.HasValue(client.called_corpses or {}, search_raw.eidx))

   local dconfirm = vgui.Create("DButton", dcont)
   dconfirm:SetPos(rw - m - bw, by)
   dconfirm:SetSize(bw, bh)
   dconfirm:SetText(T("close"))
   dconfirm.DoClick = function() dframe:Close() end


   -- Finalize search data, prune stuff that won't be shown etc
   -- search is a table of tables that have an img and text key
   local search = PreprocSearch(search_raw)

   -- Install info controller that will link up the icons to the text etc
   dlist.OnActivePanelChanged = SearchInfoController(search, dactive, dtext)

   -- Create table of SimpleIcons, each standing for a piece of search
   -- information.
   local start_icon = nil
   for t, info in SortedPairsByMemberValue(search, "p") do
      local ic = nil

      -- Certain items need a special icon conveying additional information
      if t == "nick" then
         local name = info.nick
         local avply = IsValid(search_raw.owner) and search_raw.owner or nil

         ic = vgui.Create("SimpleIcon", dlist)
         ic:SetPlayer(avply)

         start_icon = ic
      elseif t == "lastid" then
         ic = vgui.Create("SimpleIconAvatar", dlist)
         ic:SetPlayer(info.ply)
         ic:SetAvatarSize(24)
      elseif info.text_icon then
         ic = vgui.Create("SimpleIconLabelled", dlist)
         ic:SetIconText(info.text_icon)
      else
         ic = vgui.Create("SimpleIcon", dlist)
      end

      ic:SetIconSize(64)
      ic:SetIcon(info.img)

      ic.info_type = t

      dlist:AddPanel(ic)
      dscroll:AddPanel(ic)
   end

   dlist:SelectPanel(start_icon)

   dframe:MakePopup()
end

local function StoreSearchResult(search)
   if search.owner then
      -- if existing result was not ours, it was detective's, and should not
      -- be overwritten
      local ply = search.owner
      if (not ply.search_result) or ply.search_result.show then

         ply.search_result = search

         -- this is useful for targetid
         local rag = Entity(search.eidx)
         if IsValid(rag) then
            rag.search_result = search
         end
      end
   end
end

local function bitsRequired(num)
   local bits, max = 0, 1
   while max <= num do
      bits = bits + 1
      max = max + max
   end
   return bits
end

local search = {}
local function ReceiveRagdollSearch()
   search = {}

   -- Basic info
   search.eidx = net.ReadUInt(16)

   search.owner = Entity(net.ReadUInt(8))
   if not (IsValid(search.owner) and search.owner:IsPlayer() and (not search.owner:Alive())) then
      search.owner = nil
   end

   search.nick = net.ReadString()

   -- Equipment
   local eq = net.ReadUInt(16)

   -- All equipment pieces get their own icon
   search.eq_armor = util.BitSet(eq, EQUIP_ARMOR)
   search.eq_radar = util.BitSet(eq, EQUIP_RADAR)
   search.eq_disg = util.BitSet(eq, EQUIP_DISGUISE)

   -- Traitor things
   search.role = net.ReadUInt(2)
   search.c4 = net.ReadInt(bitsRequired(C4_WIRE_COUNT) + 1)

   -- Kill info
   search.dmg = net.ReadUInt(30)
   search.wep = net.ReadString()
   search.head = net.ReadBit() == 1
   search.dtime = net.ReadInt(16)
   search.stime = net.ReadInt(16)

   -- Players killed
   local num_kills = net.ReadUInt(8)
   if num_kills > 0 then
      search.kills = {}
      for i=1,num_kills do
         table.insert(search.kills, net.ReadUInt(8))
      end
   else
      search.kills = nil
   end

   search.lastid = {idx=net.ReadUInt(8)}

   -- should we show a menu for this result?
   search.finder = net.ReadUInt(8)

   search.show = (LocalPlayer():EntIndex() == search.finder)

   --
   -- last words
   --
   local words = net.ReadString()
   search.words = (words ~= "") and words or nil

   if search.show then
      ShowSearchScreen(search)
   end

   StoreSearchResult(search)

   search = nil
end

net.Receive("TTT_RagdollSearch", ReceiveRagdollSearch)


[editline]10th August 2016[/editline]

This may help people who are looking for differences in the code.
Left is vanilla TTT and right is DeadRinger version

Check difference between cl_search
https://www.diffchecker.com/r9ia3llz

difference in sb_main
https://www.diffchecker.com/djgbsuj4

difference in sb_team
https://www.diffchecker.com/0cqlwb3x

[editline]10th August 2016[/editline]

Anyone have any idea? Right now it shows up as ID where the avatar should be. it’s really annoying.

No one have any ideas or an updated cl_search file?

You can copy these three files from your client.
(Navigate to your gmod folder, then to garrysmod/terrortown/gamemode/.)
Or you use the one from GitHub.
These three files have no changes for years.
So they can easily be copied.

But be aware.
Updating the files can break some other things from the dead ringer.

Edit:
Updating cl_search.lua shouldn’t break something from the dead ringer.
But I’m not sure.

It broke it when I removed the files from the addon (So it can use the default TTT one). Searching a ringer’s body will have the question mark still while normal bodies show up fine.

Totally forgotten.

search.owner is made to nil because you’re alive.
See:



search.owner = Entity(net.ReadUInt(8))
if not (IsValid(search.owner) and search.owner:IsPlayer() and (not search.owner:Alive())) then
   search.owner = nil
end


It seems like that you have to make a ugly work around.
You can use for example the “TTTBodySearchEquipment”-Hook.