Advertisement
Purfect

try

Aug 28th, 2016
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.00 KB | None | 0 0
  1. DisModels = {
  2. "models/player/pyroteknik/link_hw.mdl", -- Example models
  3. "models/player/pyroteknik/link_hw.mdl",
  4. "models/player/pyroteknik/link_hw.mdl"
  5. }
  6.  
  7. local DisguiseModel = ""
  8. local OriginDisguiseModel = ""
  9.  
  10. include("weaponry_shd.lua") -- inits WEPS tbl
  11.  
  12. ---- Weapon system, pickup limits, etc
  13.  
  14. local IsEquipment = WEPS.IsEquipment
  15.  
  16. -- Prevent players from picking up multiple weapons of the same type etc
  17. function GM:PlayerCanPickupWeapon(ply, wep)
  18. if not IsValid(wep) or not IsValid(ply) then return end
  19. if ply:IsSpec() then return false end
  20.  
  21. -- Disallow picking up for ammo
  22. if ply:HasWeapon(wep:GetClass()) then
  23. return false
  24. elseif not ply:CanCarryWeapon(wep) then
  25. return false
  26. elseif IsEquipment(wep) and wep.IsDropped and (not ply:KeyDown(IN_USE)) then
  27. return false
  28. end
  29.  
  30. local tr = util.TraceEntity({start=wep:GetPos(), endpos=ply:GetShootPos(), mask=MASK_SOLID}, wep)
  31. if tr.Fraction == 1.0 or tr.Entity == ply then
  32. wep:SetPos(ply:GetShootPos())
  33. end
  34.  
  35. return true
  36. end
  37.  
  38. -- Cache role -> default-weapons table
  39. local loadout_weapons = nil
  40. local function GetLoadoutWeapons(r)
  41. if not loadout_weapons then
  42. local tbl = {
  43. [ROLE_INNOCENT] = {},
  44. [ROLE_TRAITOR] = {},
  45. [ROLE_DETECTIVE]= {}
  46. };
  47.  
  48. for k, w in pairs(weapons.GetList()) do
  49. if w and type(w.InLoadoutFor) == "table" then
  50. for _, wrole in pairs(w.InLoadoutFor) do
  51. table.insert(tbl[wrole], WEPS.GetClass(w))
  52. end
  53. end
  54. end
  55.  
  56. loadout_weapons = tbl
  57. end
  58.  
  59. return loadout_weapons[r]
  60. end
  61.  
  62. -- Give player loadout weapons he should have for his role that he does not have
  63. -- yet
  64. local function GiveLoadoutWeapons(ply)
  65. local r = GetRoundState() == ROUND_PREP and ROLE_INNOCENT or ply:GetRole()
  66. local weps = GetLoadoutWeapons(r)
  67. if not weps then return end
  68.  
  69. for _, cls in pairs(weps) do
  70. if not ply:HasWeapon(cls) then
  71. ply:Give(cls)
  72. end
  73. end
  74. end
  75.  
  76. local function HasLoadoutWeapons(ply)
  77. if ply:IsSpec() then return true end
  78.  
  79. local r = GetRoundState() == ROUND_PREP and ROLE_INNOCENT or ply:GetRole()
  80. local weps = GetLoadoutWeapons(r)
  81. if not weps then return true end
  82.  
  83.  
  84. for _, cls in pairs(weps) do
  85. if not ply:HasWeapon(cls) then
  86. return false
  87. end
  88. end
  89.  
  90. return true
  91. end
  92.  
  93. -- Give loadout items.
  94. local function GiveLoadoutItems(ply)
  95. local items = EquipmentItems[ply:GetRole()]
  96. if items then
  97. for _, item in pairs(items) do
  98. if item.loadout and item.id then
  99. ply:GiveEquipmentItem(item.id)
  100. end
  101. end
  102. end
  103. end
  104.  
  105. -- Quick hack to limit hats to models that fit them well
  106. local Hattables = { "phoenix.mdl", "arctic.mdl", "Group01", "monk.mdl" }
  107. local function CanWearHat(ply)
  108. local path = string.Explode("/", ply:GetModel())
  109. if #path == 1 then path = string.Explode("\\", path) end
  110.  
  111. return table.HasValue(Hattables, path[3])
  112. end
  113.  
  114. CreateConVar("ttt_detective_hats", "0")
  115. -- Just hats right now
  116. local function GiveLoadoutSpecial(ply)
  117. if ply:IsDetective() and GetConVar("ttt_detective_hats"):GetBool() and CanWearHat(ply) then
  118.  
  119. if not IsValid(ply.hat) then
  120. local hat = ents.Create("ttt_hat_deerstalker")
  121. if not IsValid(hat) then return end
  122.  
  123. hat:SetPos(ply:GetPos() + Vector(0,0,70))
  124. hat:SetAngles(ply:GetAngles())
  125.  
  126. hat:SetParent(ply)
  127.  
  128. ply.hat = hat
  129.  
  130. hat:Spawn()
  131. end
  132. else
  133. SafeRemoveEntity(ply.hat)
  134.  
  135. ply.hat = nil
  136. end
  137. end
  138.  
  139. -- Sometimes, in cramped map locations, giving players weapons fails. A timer
  140. -- calling this function is used to get them the weapons anyway as soon as
  141. -- possible.
  142. local function LateLoadout(id)
  143. local ply = player.GetByID(id)
  144. if not IsValid(ply) then
  145. timer.Remove("lateloadout" .. id)
  146. return
  147. end
  148.  
  149. if not HasLoadoutWeapons(ply) then
  150. GiveLoadoutWeapons(ply)
  151.  
  152. if HasLoadoutWeapons(ply) then
  153. timer.Remove("lateloadout" .. id)
  154. end
  155. end
  156. end
  157.  
  158. -- Note that this is called both when a player spawns and when a round starts
  159. function GM:PlayerLoadout( ply )
  160. if IsValid(ply) and (not ply:IsSpec()) then
  161. -- clear out equipment flags
  162. ply:ResetEquipment()
  163.  
  164. -- give default items
  165. GiveLoadoutItems(ply)
  166.  
  167. -- hand out weaponry
  168. GiveLoadoutWeapons(ply)
  169.  
  170. GiveLoadoutSpecial(ply)
  171.  
  172. if not HasLoadoutWeapons(ply) then
  173. MsgN("Could not spawn all loadout weapons for " .. ply:Nick() .. ", will retry.")
  174. timer.Create("lateloadout" .. ply:EntIndex(), 1, 0,
  175. function() LateLoadout(ply:EntIndex()) end)
  176. end
  177. end
  178. end
  179.  
  180. function GM:UpdatePlayerLoadouts()
  181. for k, v in pairs(player.GetAll()) do
  182. GAMEMODE:PlayerLoadout(v)
  183. end
  184. end
  185.  
  186. ---- Weapon switching
  187. local function ForceWeaponSwitch(ply, cmd, args)
  188. if not ply:IsPlayer() or not args[1] then return end
  189. -- Turns out even SelectWeapon refuses to switch to empty guns, gah.
  190. -- Worked around it by giving every weapon a single Clip2 round.
  191. -- Works because no weapon uses those.
  192. local wepname = args[1]
  193. local wep = ply:GetWeapon(wepname)
  194. if IsValid(wep) then
  195. -- Weapons apparently not guaranteed to have this
  196. if wep.SetClip2 then
  197. wep:SetClip2(1)
  198. end
  199. ply:SelectWeapon(wepname)
  200. end
  201. end
  202. concommand.Add("wepswitch", ForceWeaponSwitch)
  203.  
  204. ---- Weapon dropping
  205.  
  206. function WEPS.DropNotifiedWeapon(ply, wep, death_drop)
  207. if IsValid(ply) and IsValid(wep) then
  208. -- Hack to tell the weapon it's about to be dropped and should do what it
  209. -- must right now
  210. if wep.PreDrop then
  211. wep:PreDrop(death_drop)
  212. end
  213.  
  214. -- PreDrop might destroy weapon
  215. if not IsValid(wep) then return end
  216.  
  217. -- Tag this weapon as dropped, so that if it's a special weapon we do not
  218. -- auto-pickup when nearby.
  219. wep.IsDropped = true
  220.  
  221. ply:DropWeapon(wep)
  222.  
  223. wep:PhysWake()
  224.  
  225. -- After dropping a weapon, always switch to holstered, so that traitors
  226. -- will never accidentally pull out a traitor weapon
  227. ply:SelectWeapon("weapon_ttt_unarmed")
  228. end
  229. end
  230.  
  231. local function DropActiveWeapon(ply)
  232. if not IsValid(ply) then return end
  233.  
  234. local wep = ply:GetActiveWeapon()
  235.  
  236. if not IsValid(wep) then return end
  237.  
  238. if wep.AllowDrop == false then
  239. return
  240. end
  241.  
  242. local tr = util.QuickTrace(ply:GetShootPos(), ply:GetAimVector() * 32, ply)
  243.  
  244. if tr.HitWorld then
  245. LANG.Msg(ply, "drop_no_room")
  246. return
  247. end
  248.  
  249. ply:AnimPerformGesture(ACT_ITEM_PLACE)
  250.  
  251. WEPS.DropNotifiedWeapon(ply, wep)
  252. end
  253. concommand.Add("ttt_dropweapon", DropActiveWeapon)
  254.  
  255. local function DropActiveAmmo(ply)
  256. if not IsValid(ply) then return end
  257.  
  258. local wep = ply:GetActiveWeapon()
  259. if not IsValid(wep) then return end
  260.  
  261. if not wep.AmmoEnt then return end
  262.  
  263. local amt = wep:Clip1()
  264. if amt < 1 or amt <= (wep.Primary.ClipSize * 0.25) then
  265. LANG.Msg(ply, "drop_no_ammo")
  266. return
  267. end
  268.  
  269. local pos, ang = ply:GetShootPos(), ply:EyeAngles()
  270. local dir = (ang:Forward() * 32) + (ang:Right() * 6) + (ang:Up() * -5)
  271.  
  272. local tr = util.QuickTrace(pos, dir, ply)
  273. if tr.HitWorld then return end
  274.  
  275. wep:SetClip1(0)
  276.  
  277. ply:AnimPerformGesture(ACT_ITEM_GIVE)
  278.  
  279. local box = ents.Create(wep.AmmoEnt)
  280. if not IsValid(box) then box:Remove() end
  281.  
  282. box:SetPos(pos + dir)
  283. box:SetOwner(ply)
  284. box:Spawn()
  285.  
  286. box:PhysWake()
  287.  
  288. local phys = box:GetPhysicsObject()
  289. if IsValid(phys) then
  290. phys:ApplyForceCenter(ang:Forward() * 1000)
  291. phys:ApplyForceOffset(VectorRand(), vector_origin)
  292. end
  293.  
  294. box.AmmoAmount = amt
  295.  
  296. timer.Simple(2, function()
  297. if IsValid(box) then
  298. box:SetOwner(nil)
  299. end
  300. end)
  301. end
  302. concommand.Add("ttt_dropammo", DropActiveAmmo)
  303.  
  304.  
  305. -- Give a weapon to a player. If the initial attempt fails due to heisenbugs in
  306. -- the map, keep trying until the player has moved to a better spot where it
  307. -- does work.
  308. local function GiveEquipmentWeapon(sid, cls)
  309. -- Referring to players by SteamID because a player may disconnect while his
  310. -- unique timer still runs, in which case we want to be able to stop it. For
  311. -- that we need its name, and hence his SteamID.
  312. local ply = player.GetBySteamID(sid)
  313. local tmr = "give_equipment" .. sid
  314.  
  315. if (not IsValid(ply)) or (not ply:IsActiveSpecial()) then
  316. timer.Remove(tmr)
  317. return
  318. end
  319.  
  320. -- giving attempt, will fail if we're in a crazy spot in the map or perhaps
  321. -- other glitchy cases
  322. local w = ply:Give(cls)
  323.  
  324. if (not IsValid(w)) or (not ply:HasWeapon(cls)) then
  325. if not timer.Exists(tmr) then
  326. timer.Create(tmr, 1, 0, function() GiveEquipmentWeapon(sid, cls) end)
  327. end
  328.  
  329. -- we will be retrying
  330. else
  331. -- can stop retrying, if we were
  332. timer.Remove(tmr)
  333.  
  334. if w.WasBought then
  335. -- some weapons give extra ammo after being bought, etc
  336. w:WasBought(ply)
  337. end
  338. end
  339. end
  340.  
  341. local function HasPendingOrder(ply)
  342. return timer.Exists("give_equipment" .. tostring(ply:SteamID()))
  343. end
  344.  
  345. -- Equipment buying
  346. local function OrderEquipment(ply, cmd, args)
  347. if not IsValid(ply) or #args != 1 then return end
  348.  
  349. if not (ply:IsActiveTraitor() or ply:IsActiveDetective()) then return end
  350.  
  351. -- no credits, can't happen when buying through menu as button will be off
  352. if ply:GetCredits() < 1 then return end
  353.  
  354. -- it's an item if the arg is an id instead of an ent name
  355. local id = args[1]
  356. local is_item = tonumber(id)
  357.  
  358. -- we use weapons.GetStored to save time on an unnecessary copy, we will not
  359. -- be modifying it
  360. local swep_table = (not is_item) and weapons.GetStored(id) or nil
  361.  
  362. -- some weapons can only be bought once per player per round, this used to be
  363. -- defined in a table here, but is now in the SWEP's table
  364. if swep_table and swep_table.LimitedStock and ply:HasBought(id) then
  365. LANG.Msg(ply, "buy_no_stock")
  366. return
  367. end
  368.  
  369. local received = false
  370.  
  371. if is_item then
  372. id = tonumber(id)
  373.  
  374. -- item whitelist check
  375. local allowed = GetEquipmentItem(ply:GetRole(), id)
  376.  
  377. if not allowed then
  378. print(ply, "tried to buy item not buyable for his class:", id)
  379. return
  380. end
  381.  
  382. -- ownership check and finalise
  383. if id and EQUIP_NONE < id then
  384. if not ply:HasEquipmentItem(id) then
  385. ply:GiveEquipmentItem(id)
  386. received = true
  387. end
  388. end
  389. elseif swep_table then
  390. -- weapon whitelist check
  391. if not table.HasValue(swep_table.CanBuy, ply:GetRole()) then
  392. print(ply, "tried to buy weapon his role is not permitted to buy")
  393. return
  394. end
  395.  
  396. -- if we have a pending order because we are in a confined space, don't
  397. -- start a new one
  398. if HasPendingOrder(ply) then
  399. LANG.Msg(ply, "buy_pending")
  400. return
  401. end
  402.  
  403. -- no longer restricted to only WEAPON_EQUIP weapons, just anything that
  404. -- is whitelisted and carryable
  405. if ply:CanCarryWeapon(swep_table) then
  406. GiveEquipmentWeapon(ply:SteamID(), id)
  407.  
  408. received = true
  409. end
  410. end
  411.  
  412. if received then
  413. ply:SubtractCredits(1)
  414. LANG.Msg(ply, "buy_received")
  415.  
  416. ply:AddBought(id)
  417.  
  418. timer.Simple(0.5,
  419. function()
  420. if not IsValid(ply) then return end
  421. net.Start("TTT_BoughtItem")
  422. net.WriteBit(is_item)
  423. if is_item then
  424. net.WriteUInt(id, 16)
  425. else
  426. net.WriteString(id)
  427. end
  428. net.Send(ply)
  429. end)
  430.  
  431. hook.Call("TTTOrderedEquipment", GAMEMODE, ply, id, is_item)
  432. end
  433. end
  434. concommand.Add("ttt_order_equipment", OrderEquipment)
  435.  
  436. local function SetDisguise(ply, cmd, args)
  437. if not IsValid(ply) or not ply:IsActiveTraitor() then return end
  438.  
  439. if ply:HasEquipmentItem(EQUIP_DISGUISE) then
  440. local state = #args == 1 and tobool(args[1])
  441.  
  442. ply:SetNWBool("disguised", state)
  443. if (!table.HasValue(DisModels,DisguiseModel)) then
  444. OriginDisguiseModel = ply:GetModel()
  445. DisguiseModel = table.Random(DisModels)
  446. ply:SetModel(table.Random(DisModels))
  447. table.insert(DisguisedPlayers,table.Count(DisguisedPlayers) + 1,ply)
  448. else
  449. ply:SetModel(DisguiseModel)
  450. end
  451. LANG.Msg(ply, state and "disg_turned_on" or "disg_turned_off")
  452. end
  453. end
  454. concommand.Add("ttt_set_disguise", SetDisguise)
  455.  
  456. local function RevertModel(ply, inf, attacker)
  457. local mdl = GAMEMODE.playermodel or "models/player/phoenix.mdl"
  458. ply:SetModel(mdl)
  459. OriginDisguiseModel = ""
  460. DisguiseModel = ""
  461. end
  462. hook.Add("PlayerDeath","RevertModel",RevertModel)
  463.  
  464. local function CheatCredits(ply)
  465. if cvars.Bool("sv_cheats", false) and IsValid(ply) then
  466. ply:AddCredits(10)
  467. end
  468. end
  469. concommand.Add("ttt_cheat_credits", CheatCredits)
  470.  
  471. local function TransferCredits(ply, cmd, args)
  472. if (not IsValid(ply)) or (not ply:IsActiveSpecial()) then return end
  473. if #args != 2 then return end
  474.  
  475. local sid = tostring(args[1])
  476. local credits = tonumber(args[2])
  477. if sid and credits then
  478. local target = player.GetBySteamID(sid)
  479. if (not IsValid(target)) or (not target:IsActiveSpecial()) or (target:GetRole() ~= ply:GetRole()) or (target == ply) then
  480. LANG.Msg(ply, "xfer_no_recip")
  481. return
  482. end
  483.  
  484. if ply:GetCredits() < credits then
  485. LANG.Msg(ply, "xfer_no_credits")
  486. return
  487. end
  488.  
  489. credits = math.Clamp(credits, 0, ply:GetCredits())
  490. if credits == 0 then return end
  491.  
  492. ply:SubtractCredits(credits)
  493. target:AddCredits(credits)
  494.  
  495. LANG.Msg(ply, "xfer_success", {player=target:Nick()})
  496. LANG.Msg(target, "xfer_received", {player = ply:Nick(), num = credits})
  497. end
  498. end
  499. concommand.Add("ttt_transfer_credits", TransferCredits)
  500.  
  501. -- Protect against non-TTT weapons that may break the HUD
  502. function GM:WeaponEquip(wep)
  503. if IsValid(wep) then
  504. -- only remove if they lack critical stuff
  505. if not wep.Kind then
  506. wep:Remove()
  507. ErrorNoHalt("Equipped weapon " .. wep:GetClass() .. " is not compatible with TTT\n")
  508. end
  509. end
  510. end
  511.  
  512. -- non-cheat developer commands can reveal precaching the first time equipment
  513. -- is bought, so trigger it at the start of a round instead
  514. function WEPS.ForcePrecache()
  515. for k, w in ipairs(weapons.GetList()) do
  516. if w.WorldModel then
  517. util.PrecacheModel(w.WorldModel)
  518. end
  519. if w.ViewModel then
  520. util.PrecacheModel(w.ViewModel)
  521. end
  522. end
  523. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement