Untitled diff

Created Diff never expires
39 removals
503 lines
46 additions
509 lines
-- Body search popup
-- Body search popup


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


local is_dmg = util.BitSet
local is_dmg = util.BitSet


local dtt = { search_dmg_crush = DMG_CRUSH, search_dmg_bullet = DMG_BULLET, search_dmg_fall = DMG_FALL,
search_dmg_boom = DMG_BLAST, search_dmg_club = DMG_CLUB, search_dmg_drown = DMG_DROWN, search_dmg_stab = DMG_SLASH,
search_dmg_burn = DMG_BURN, search_dmg_tele = DMG_SONIC, search_dmg_car = DMG_VEHICLE }

-- "From his body you can tell XXX"
-- "From his body you can tell XXX"
local function DmgToText(d)
local function DmgToText(d)
for k, v in pairs(dtt) do
if is_dmg(d, DMG_CRUSH) then
if is_dmg(d, v) then
return T("search_dmg_crush")
return T(k)
elseif is_dmg(d, DMG_BULLET) then
end
return T("search_dmg_bullet")
end
elseif is_dmg(d, DMG_FALL) then
if is_dmg(d, DMG_DIRECT) 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")
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
return T("search_dmg_other")
end
end


-- Info type to icon mapping
-- Info type to icon mapping


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


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


local dtm = { bullet = DMG_BULLET, rock = DMG_CRUSH, splode = DMG_BLAST, fall = DMG_FALL, fire = DMG_BURN }

local function DmgToMat(d)
local function DmgToMat(d)
for k, v in pairs(dtm) do
if is_dmg(d, DMG_BULLET) then
if is_dmg(d, v) then
return "bullet"
return k
elseif is_dmg(d, DMG_CRUSH) then
end
return "rock"
end
elseif is_dmg(d, DMG_BLAST) then
if is_dmg(d, DMG_DIRECT) 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"
return "fire"
else
else
return "skull"
return "skull"
end
end
end
end


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


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


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


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


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


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




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


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


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


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


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


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


search[t].text_icon = ftime
search[t].text_icon = ftime


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


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


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


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


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


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


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


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


hook.Call("TTTBodySearchPopulate", nil, search, raw)

return search
return search
end
end




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


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


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


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


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


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


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


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


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


ry = ry + desch + m
ry = ry + desch + m


local butx, buty = rx, ry
local butx, buty = rx, ry


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


dframe.OnKeyCodePressed = util.BasicKeyHandler
dframe.OnKeyCodePressed = util.BasicKeyHandler


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


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


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


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


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


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


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


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


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


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


RunConsoleCommand("ttt_call_detective", search_raw.eidx)
RunConsoleCommand("ttt_call_detective", search_raw.eidx)
end
end


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


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




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


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


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


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


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


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


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


ic.info_type = t
ic.info_type = t


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


dlist:SelectPanel(start_icon)
dlist:SelectPanel(start_icon)


dframe:MakePopup()
dframe:MakePopup()
end
end


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


ply.search_result = search
ply.search_result = search


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


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


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


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


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


search.nick = net.ReadString()
search.nick = net.ReadString()


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


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


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


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


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


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


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


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


--
--
-- last words
-- last words
--
--
local words = net.ReadString()
local words = net.ReadString()
search.words = (words ~= "") and words or nil
search.words = (words ~= "") and words or nil
hook.Call("TTTBodySearchEquipment", nil, search, eq)


if search.show then
if search.show then
ShowSearchScreen(search)
ShowSearchScreen(search)
end
end


StoreSearchResult(search)
StoreSearchResult(search)


search = nil
search = nil
end
end


net.Receive("TTT_RagdollSearch", ReceiveRagdollSearch)
net.Receive("TTT_RagdollSearch", ReceiveRagdollSearch)