Guest User

Untitled

a guest
Feb 6th, 2014
98
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ---- Traitor equipment menu
  2. local GetTranslation = LANG.GetTranslation
  3. local GetPTranslation = LANG.GetParamTranslation
  4.  
  5. -- Buyable weapons are loaded automatically. Buyable items are defined in
  6. -- equip_items_shd.lua
  7.  
  8. local Equipment = nil
  9. function GetEquipmentForRole(role)
  10. -- need to build equipment cache?
  11. if not Equipment then
  12. -- start with all the non-weapon goodies
  13. local tbl = table.Copy(EquipmentItems)
  14.  
  15. -- find buyable weapons to load info from
  16. for k, v in pairs(weapons.GetList()) do
  17. if v and v.CanBuy then
  18. local data = v.EquipMenuData or {}
  19. local base = {
  20. id = WEPS.GetClass(v),
  21. name = v.PrintName or "Unnamed",
  22. limited = v.LimitedStock,
  23. kind = v.Kind or WEAPON_NONE,
  24. slot = (v.Slot or 0) + 1,
  25. material = v.Icon or "VGUI/ttt/icon_id",
  26. -- the below should be specified in EquipMenuData, in which case
  27. -- these values are overwritten
  28. type = "Type not specified",
  29. model = "models/weapons/w_bugbait.mdl",
  30. desc = "No description specified."
  31. };
  32.  
  33. -- Force material to nil so that model key is used when we are
  34. -- explicitly told to do so (ie. material is false rather than nil).
  35. if data.modelicon then
  36. base.material = nil
  37. end
  38.  
  39. table.Merge(base, data)
  40.  
  41. -- add this buyable weapon to all relevant equipment tables
  42. for _, r in pairs(v.CanBuy) do
  43. table.insert(tbl[r], base)
  44. end
  45. end
  46. end
  47.  
  48. -- mark custom items
  49. for r, is in pairs(tbl) do
  50. for _, i in pairs(is) do
  51. if i and i.id then
  52. i.custom = not table.HasValue(DefaultEquipment[r], i.id)
  53. end
  54. end
  55. end
  56.  
  57. Equipment = tbl
  58. end
  59.  
  60. return Equipment and Equipment[role] or {}
  61. end
  62.  
  63.  
  64. local function ItemIsWeapon(item) return not tonumber(item.id) end
  65. local function CanCarryWeapon(item) return LocalPlayer():CanCarryType(item.kind) end
  66.  
  67. local color_bad = Color(220, 60, 60, 255)
  68. local color_good = Color(0, 200, 0, 255)
  69.  
  70. -- Creates tabel of labels showing the status of ordering prerequisites
  71. local function PreqLabels(parent, x, y)
  72. local tbl = {}
  73.  
  74. tbl.credits = vgui.Create("DLabel", parent)
  75. tbl.credits:SetToolTip(GetTranslation("equip_help_cost"))
  76. tbl.credits:SetPos(x, y)
  77. tbl.credits.Check = function(s, sel)
  78. local credits = LocalPlayer():GetCredits()
  79. return credits > 0, GetPTranslation("equip_cost", {num = credits})
  80. end
  81.  
  82. tbl.owned = vgui.Create("DLabel", parent)
  83. tbl.owned:SetToolTip(GetTranslation("equip_help_carry"))
  84. tbl.owned:CopyPos(tbl.credits)
  85. tbl.owned:MoveBelow(tbl.credits, y)
  86. tbl.owned.Check = function(s, sel)
  87. if ItemIsWeapon(sel) and (not CanCarryWeapon(sel)) then
  88. return false, GetPTranslation("equip_carry_slot", {slot = sel.slot})
  89. elseif (not ItemIsWeapon(sel)) and LocalPlayer():HasEquipmentItem(sel.id) then
  90. return false, GetTranslation("equip_carry_own")
  91. else
  92. return true, GetTranslation("equip_carry")
  93. end
  94. end
  95.  
  96. tbl.bought = vgui.Create("DLabel", parent)
  97. tbl.bought:SetToolTip(GetTranslation("equip_help_stock"))
  98. tbl.bought:CopyPos(tbl.owned)
  99. tbl.bought:MoveBelow(tbl.owned, y)
  100. tbl.bought.Check = function(s, sel)
  101. if sel.limited and LocalPlayer():HasBought(tostring(sel.id)) then
  102. return false, GetTranslation("equip_stock_deny")
  103. else
  104. return true, GetTranslation("equip_stock_ok")
  105. end
  106. end
  107.  
  108. for k, pnl in pairs(tbl) do
  109. pnl:SetFont("TabLarge")
  110. end
  111.  
  112. return function(selected)
  113. local allow = true
  114. for k, pnl in pairs(tbl) do
  115. local result, text = pnl:Check(selected)
  116. pnl:SetTextColor(result and color_good or color_bad)
  117. pnl:SetText(text)
  118. pnl:SizeToContents()
  119.  
  120. allow = allow and result
  121. end
  122. return allow
  123. end
  124. end
  125.  
  126. -- quick, very basic override of DPanelSelect
  127. local PANEL = {}
  128. local function DrawSelectedEquipment(pnl)
  129. surface.SetDrawColor( tttreskin.tdmitemselect )
  130. surface.DrawOutlinedRect(0, 0, pnl:GetWide(), pnl:GetTall())
  131. end
  132.  
  133. function PANEL:SelectPanel(pnl)
  134. self.BaseClass.SelectPanel(self, pnl)
  135. if pnl then
  136. pnl.PaintOver = DrawSelectedEquipment
  137. end
  138. end
  139. vgui.Register("EquipSelect", PANEL, "DPanelSelect")
  140.  
  141.  
  142. local SafeTranslate = LANG.TryTranslation
  143.  
  144. local color_darkened = Color(255,255,255, 80)
  145. -- TODO: make set of global role colour defs, these are same as wepswitch
  146. local color_slot = {
  147. [ROLE_TRAITOR] = Color(180, 50, 40, 255),
  148. [ROLE_DETECTIVE] = Color(50, 60, 180, 255)
  149. };
  150.  
  151. local eqframe = nil
  152. local function TraitorMenuPopup()
  153. local ply = LocalPlayer()
  154. if not IsValid(ply) or not ply:IsActiveSpecial() then
  155. return
  156. end
  157.  
  158. -- Close any existing traitor menu
  159. if eqframe and ValidPanel(eqframe) then eqframe:Close() end
  160.  
  161. local credits = ply:GetCredits()
  162. local can_order = credits > 0
  163. local dframe = vgui.Create("DFrame")
  164. local w, h = 505, 350
  165. dframe:SetSize(w, h)
  166. dframe:Center()
  167. dframe:SetTitle(GetTranslation("equip_title"))
  168. dframe:SetVisible(true)
  169. dframe:ShowCloseButton(true)
  170. dframe:SetMouseInputEnabled(true)
  171. dframe:SetDeleteOnClose(true)
  172. dframe.Paint = function(self, w, h)
  173. draw.RoundedBox( 0, 0, 0, w, h, tttreskin.hsbg )
  174. draw.RoundedBox( 0, 0, 0, w, 25, tttreskin.hsbgtop )
  175. end
  176.  
  177. local m = 5
  178.  
  179. local dsheet = vgui.Create("DPropertySheet", dframe)
  180.  
  181. -- Add a callback when switching tabs
  182. local oldfunc = dsheet.SetActiveTab
  183. dsheet.SetActiveTab = function(self, new)
  184. if self.m_pActiveTab != new and self.OnTabChanged then
  185. self:OnTabChanged(self.m_pActiveTab, new)
  186. end
  187. oldfunc(self, new)
  188. end
  189.  
  190. dsheet:SetPos(0,0)
  191. dsheet:StretchToParent(m,m + 25,m,m)
  192. dsheet.Paint = function(self, w, h)
  193. draw.RoundedBox( 0, 0, 0, w, h, tttreskin.tdmbody )
  194. end
  195. local padding = dsheet:GetPadding()
  196.  
  197. local dequip = vgui.Create("DPanel", dsheet)
  198. dequip:SetPaintBackground(false)
  199. dequip:StretchToParent(padding,padding,padding,padding)
  200.  
  201. -- Determine if we already have equipment
  202. local owned_ids = {}
  203. for _, wep in pairs(ply:GetWeapons()) do
  204. if IsValid(wep) and wep:IsEquipment() then
  205. table.insert(owned_ids, wep:GetClass())
  206. end
  207. end
  208.  
  209. -- Stick to one value for no equipment
  210. if #owned_ids == 0 then
  211. owned_ids = nil
  212. end
  213.  
  214. --- Construct icon listing
  215. local dlist = vgui.Create("EquipSelect", dequip)
  216. dlist:SetPos(0, m)
  217. dlist:SetSize(w - 27, 137)
  218. dlist:EnableHorizontal(true)
  219. dlist:SetPadding(3)
  220. dlist:EnableVerticalScrollbar(true)
  221. dlist.VBar.Paint = function( s, w, h )
  222. surface.SetDrawColor( tttreskin.tdmitemscrollmainbg )
  223. surface.DrawRect( 0, 0, w, h )
  224. end
  225. dlist.VBar.btnUp.Paint = function( s, w, h )
  226. surface.SetDrawColor( tttreskin.tdmitemscrollborder )
  227. surface.DrawRect( 0, 0, w-1, h )
  228. surface.SetDrawColor( tttreskin.tdmitemscrollbg )
  229. surface.DrawRect( 1, 1, w-3, h-2 )
  230. end
  231. dlist.VBar.btnDown.Paint = function( s, w, h )
  232. surface.SetDrawColor( tttreskin.tdmitemscrollborder )
  233. surface.DrawRect( 0, 0, w-1, h )
  234. surface.SetDrawColor( tttreskin.tdmitemscrollbg )
  235. surface.DrawRect( 1, 1, w-3, h-2 )
  236. end
  237. dlist.VBar.btnGrip.Paint = function( s, w, h )
  238. surface.SetDrawColor( tttreskin.tdmitemscrollborder )
  239. surface.DrawRect( 0, 0, w-1, h )
  240. surface.SetDrawColor( tttreskin.tdmitemscrollbg )
  241. surface.DrawRect( 1, 1, w-3, h-2 )
  242. end
  243.  
  244. dlist.Paint = function(self, w, h)
  245. draw.RoundedBox(0, 0, 0, w, h, tttreskin.tdmitembg)
  246. end
  247.  
  248. local items = GetEquipmentForRole(ply:GetRole())
  249.  
  250. local to_select = nil
  251. for k, item in pairs(items) do
  252. local ic = nil
  253.  
  254. -- Create icon panel
  255. if item.material then
  256. if item.custom then
  257. -- Custom marker icon
  258. ic = vgui.Create("LayeredIcon", dlist)
  259.  
  260. local marker = vgui.Create("DImage")
  261. marker:SetImage("VGUI/ttt/custom_marker")
  262. marker.PerformLayout = function(s)
  263. s:AlignBottom(2)
  264. s:AlignRight(2)
  265. s:SetSize(16, 16)
  266. end
  267. marker:SetTooltip(GetTranslation("equip_custom"))
  268.  
  269. ic:AddLayer(marker)
  270.  
  271. ic:EnableMousePassthrough(marker)
  272. elseif not ItemIsWeapon(item) then
  273. ic = vgui.Create("SimpleIcon", dlist)
  274. else
  275. ic = vgui.Create("LayeredIcon", dlist)
  276. end
  277.  
  278. -- Slot marker icon
  279. if ItemIsWeapon(item) then
  280. local slot = vgui.Create("SimpleIconLabelled")
  281. slot:SetIcon("VGUI/ttt/slotcap")
  282. slot:SetIconColor(color_slot[ply:GetRole()] or COLOR_GREY)
  283. slot:SetIconSize(16)
  284.  
  285. slot:SetIconText(item.slot)
  286.  
  287. slot:SetIconProperties(COLOR_WHITE,
  288. "DefaultBold",
  289. {opacity=220, offset=1},
  290. {10, 8})
  291.  
  292. ic:AddLayer(slot)
  293. ic:EnableMousePassthrough(slot)
  294. end
  295.  
  296. ic:SetIconSize(64)
  297. ic:SetIcon(item.material)
  298. elseif item.model then
  299. ic = vgui.Create("SpawnIcon", dlist)
  300. ic:SetModel(item.model)
  301. else
  302. ErrorNoHalt("Equipment item does not have model or material specified: " .. tostring(item) .. "\n")
  303. end
  304.  
  305. ic.item = item
  306.  
  307. local tip = SafeTranslate(item.name) .. " (" .. SafeTranslate(item.type) .. ")"
  308. ic:SetTooltip(tip)
  309.  
  310. -- If we cannot order this item, darken it
  311. if ((not can_order) or
  312. -- already owned
  313. table.HasValue(owned_ids, item.id) or
  314. (tonumber(item.id) and ply:HasEquipmentItem(tonumber(item.id))) or
  315. -- already carrying a weapon for this slot
  316. (ItemIsWeapon(item) and (not CanCarryWeapon(item))) or
  317. -- already bought the item before
  318. (item.limited and ply:HasBought(tostring(item.id)))) then
  319.  
  320. ic:SetIconColor(color_darkened)
  321. end
  322.  
  323. dlist:AddPanel(ic)
  324. end
  325.  
  326. local dlistw = 154
  327.  
  328. local bw, bh = 100, 25
  329.  
  330. local dih = (h - 5*m - 73)/2
  331. local diw = w - dlistw - m*6 - 72
  332. local dinfobg = vgui.Create("DPanel", dequip)
  333. dinfobg:SetPaintBackground(false)
  334. dinfobg:SetSize(w, dih + 10)
  335. dinfobg:SetPos(0, 150)
  336.  
  337. local dinfo = vgui.Create("ColoredBox", dinfobg)
  338. dinfo:SetColor( tttreskin.tdmiteminfotop )
  339. dinfo:SetPos(0, 0)
  340. dinfo:SetSize(diw, dih)
  341.  
  342. local dfields = {}
  343. for _, k in pairs({"name", "type", "desc"}) do
  344. dfields[k] = vgui.Create("DLabel", dinfo)
  345. dfields[k]:SetTooltip(GetTranslation("equip_spec_" .. k))
  346. dfields[k]:SetPos(m*3, m*2)
  347. end
  348.  
  349. dfields.name:SetFont("TabLarge")
  350.  
  351. dfields.type:SetFont("DermaDefault")
  352. dfields.type:MoveBelow(dfields.name)
  353.  
  354. dfields.desc:SetFont("DermaDefaultBold")
  355. dfields.desc:SetContentAlignment(7)
  356. dfields.desc:MoveBelow(dfields.type, 1)
  357.  
  358. local iw, ih = dinfo:GetSize()
  359.  
  360. local dhelp = vgui.Create("ColoredBox", dinfobg)
  361. dhelp:SetColor( tttreskin.tdmiteminfo )
  362. dhelp:SetSize(diw - 25, dih - m - bh)
  363. dhelp:SetPos(diw + 5, 0)
  364.  
  365. local update_preqs = PreqLabels(dhelp, m*3, m*2)
  366.  
  367. dhelp:SizeToContents()
  368.  
  369. local dconfirm = vgui.Create("DButton", dinfobg)
  370. dconfirm:SetPos(diw + 5, dih - bh)
  371. dconfirm:SetSize(bw, bh)
  372. dconfirm:SetDisabled(true)
  373. dconfirm:SetText(GetTranslation("equip_confirm"))
  374. dconfirm:SetTextColor( tttreskin.tdmbuybtntexat )
  375. dconfirm.OnCursorEntered = function(self)
  376. self:SetTextColor( tttreskin.tdmbuybtntexthover )
  377. end
  378. dconfirm.OnCursorExited = function(self)
  379. self:SetTextColor( tttreskin.tdmbuybtntext )
  380. end
  381. dconfirm.Paint = function(self,w,h)
  382. draw.RoundedBox( 0, 0, 0, w, h, tttreskin.tdmbuybtnborder )
  383. draw.RoundedBox( 0, 1, 1, w-2, h-2, tttreskin.tdmbuybtngrdtop )
  384.  
  385. surface.SetDrawColor( tttreskin.tdmbuybtngrdbtm )
  386. surface.SetTexture( surface.GetTextureID( "gui/gradient" ) )
  387. surface.DrawTexturedRectRotated( w/2, h/2, h-1, w-2, 90 )
  388.  
  389. draw.RoundedBox( 0, 1, 1, w-2, 1, tttreskin.tdmbuybtnshine )
  390. end
  391.  
  392.  
  393. dsheet:AddSheet(GetTranslation("equip_tabtitle"), dequip, "icon16/bomb.png", false, false, "Traitor equipment menu")
  394.  
  395. -- Item control
  396. if ply:HasEquipmentItem(EQUIP_RADAR) then
  397. local dradar = RADAR.CreateMenu(dsheet, dframe)
  398. dsheet:AddSheet(GetTranslation("radar_name"), dradar, "icon16/magnifier.png", false,false, "Radar control")
  399. end
  400.  
  401. if ply:HasEquipmentItem(EQUIP_DISGUISE) then
  402. local ddisguise = DISGUISE.CreateMenu(dsheet)
  403. dsheet:AddSheet(GetTranslation("disg_name"), ddisguise, "icon16/user.png", false,false, "Disguise control")
  404. end
  405.  
  406. -- Weapon/item control
  407. if IsValid(ply.radio) or ply:HasWeapon("weapon_ttt_radio") then
  408. local dradio = TRADIO.CreateMenu(dsheet)
  409. dsheet:AddSheet(GetTranslation("radio_name"), dradio, "icon16/transmit.png", false,false, "Radio control")
  410. end
  411.  
  412. -- Credit transferring
  413. if credits > 0 then
  414. local dtransfer = CreateTransferMenu(dsheet)
  415. dsheet:AddSheet(GetTranslation("xfer_name"), dtransfer, "icon16/group_gear.png", false,false, "Transfer credits")
  416. end
  417.  
  418.  
  419. -- couple panelselect with info
  420. dlist.OnActivePanelChanged = function(self, _, new)
  421. for k,v in pairs(new.item) do
  422. if dfields[k] then
  423. dfields[k]:SetText(SafeTranslate(v))
  424. dfields[k]:SizeToContents()
  425. end
  426. end
  427.  
  428. -- Trying to force everything to update to
  429. -- the right size is a giant pain, so just
  430. -- force a good size.
  431. dfields.desc:SetTall(70)
  432.  
  433. can_order = update_preqs(new.item)
  434.  
  435. dconfirm:SetDisabled(not can_order)
  436. end
  437.  
  438. -- select first
  439. dlist:SelectPanel(to_select or dlist:GetItems()[1])
  440.  
  441. -- prep confirm action
  442. dconfirm.DoClick = function()
  443. local pnl = dlist.SelectedPanel
  444. if not pnl or not pnl.item then return end
  445. local choice = pnl.item
  446. RunConsoleCommand("ttt_order_equipment", choice.id)
  447. dframe:Close()
  448. end
  449.  
  450. -- update some basic info, may have changed in another tab
  451. -- specifically the number of credits in the preq list
  452. dsheet.OnTabChanged = function(s, old, new)
  453. if not IsValid(new) then return end
  454.  
  455. if new:GetPanel() == dequip then
  456. can_order = update_preqs(dlist.SelectedPanel.item)
  457. dconfirm:SetDisabled(not can_order)
  458. end
  459. end
  460. for k, v in pairs(dsheet.Items) do
  461. if (!v.Tab) then continue end
  462.  
  463. v.Tab.Paint = function(self,w,h)
  464. if v.Tab == dsheet:GetActiveTab() then
  465. draw.RoundedBox(0, 0, 0, w, h, tttreskin.tdmbodytabselected)
  466. else
  467. draw.RoundedBox(0, 0, 0, w, h, tttreskin.tdmbodytab)
  468. end
  469. end
  470. end
  471.  
  472. local dcancel = vgui.Create("DButton", dframe)
  473. dcancel:SetPos(w - 13 - bw, h - bh - 16)
  474. dcancel:SetSize(bw, bh)
  475. dcancel:SetDisabled(false)
  476. dcancel:SetText(GetTranslation("close"))
  477. dcancel:SetTextColor( tttreskin.tdmclosebtntext )
  478. dcancel.OnCursorEntered = function(self)
  479. self:SetTextColor( tttreskin.tdmclosebtntexthover )
  480. end
  481. dcancel.OnCursorExited = function(self)
  482. self:SetTextColor( tttreskin.tdmclosebtntext )
  483. end
  484. dcancel.Paint = function(self,w,h)
  485. draw.RoundedBox( 0, 0, 0, w, h, tttreskin.tdmclosebtnborder )
  486. draw.RoundedBox( 0, 1, 1, w-2, h-2, tttreskin.tdmclosebtngrdtop )
  487.  
  488. surface.SetDrawColor( tttreskin.tdmclosebtngrdbtm )
  489. surface.SetTexture( surface.GetTextureID( "gui/gradient" ) )
  490. surface.DrawTexturedRectRotated( w/2, h/2, h-1, w-2, 90 )
  491.  
  492. draw.RoundedBox( 0, 1, 1, w-2, 1, tttreskin.tdmclosebtnshine )
  493. end
  494. dcancel.DoClick = function() dframe:Close() end
  495.  
  496. dframe:MakePopup()
  497. dframe:SetKeyboardInputEnabled(false)
  498.  
  499. eqframe = dframe
  500. end
  501. concommand.Add("ttt_cl_traitorpopup", TraitorMenuPopup)
  502.  
  503. local function ForceCloseTraitorMenu(ply, cmd, args)
  504. if ValidPanel(eqframe) then
  505. eqframe:Close()
  506. end
  507. end
  508. concommand.Add("ttt_cl_traitorpopup_close", ForceCloseTraitorMenu)
  509.  
  510. function GM:OnContextMenuOpen()
  511. local r = GetRoundState()
  512. if r == ROUND_ACTIVE and not (LocalPlayer():GetTraitor() or LocalPlayer():GetDetective()) then
  513. return
  514. elseif r == ROUND_POST or r == ROUND_PREP then
  515. CLSCORE:Reopen()
  516. return
  517. end
  518.  
  519. RunConsoleCommand("ttt_cl_traitorpopup")
  520. end
  521.  
  522. local function ReceiveEquipment(um)
  523. local ply = LocalPlayer()
  524. if not IsValid(ply) then return end
  525.  
  526. ply.equipment_items = um:ReadShort()
  527. end
  528. usermessage.Hook("equipment", ReceiveEquipment)
  529.  
  530. local function ReceiveCredits(um)
  531. local ply = LocalPlayer()
  532. if not IsValid(ply) then return end
  533.  
  534. ply.equipment_credits = um:ReadChar()
  535. end
  536. usermessage.Hook("credits", ReceiveCredits)
  537.  
  538. local r = 0
  539. local function ReceiveBought(um)
  540. local ply = LocalPlayer()
  541. if not IsValid(ply) then return end
  542.  
  543. ply.bought = {}
  544. local num = um:ReadShort()
  545. for i=1,num do
  546. local s = um:ReadString()
  547. if s != "" then
  548. table.insert(ply.bought, s)
  549. end
  550. end
  551.  
  552. -- This usermessage sometimes fails to contain the last weapon that was
  553. -- bought, even though resending then works perfectly. Possibly a bug in
  554. -- bf_read. Anyway, this hack is a workaround: we just request a new umsg.
  555. if num != #ply.bought and r < 10 then -- r is an infinite loop guard
  556. RunConsoleCommand("ttt_resend_bought")
  557. r = r + 1
  558. else
  559. r = 0
  560. end
  561. end
  562. usermessage.Hook("bought", ReceiveBought)
  563.  
  564. -- Player received the item he has just bought, so run clientside init
  565. local function ReceiveBoughtItem(um)
  566. local is_item = um:ReadBool()
  567. local id = is_item and um:ReadShort() or um:ReadString()
  568.  
  569. -- I can imagine custom equipment wanting this, so making a hook
  570. hook.Run("TTTBoughtItem", is_item, id)
  571. end
  572. usermessage.Hook("bought_item", ReceiveBoughtItem)
RAW Paste Data