Advertisement
Exho

Untitled

Sep 9th, 2014
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.55 KB | None | 0 0
  1. if SERVER then
  2. AddCSLuaFile()
  3. util.AddNetworkString( "DisguiseDestroyed" )
  4. util.AddNetworkString( "PD_ChatPrint" )
  5. resource.AddFile("materials/vgui/ttt/exho_propdisguiser.png")
  6. end
  7.  
  8.  
  9. ---- TTT Prop Disguiser ----
  10. -- Redone by Exho - based off Jonascone's SWEP
  11. -- V: 9/7/14
  12.  
  13.  
  14. if CLIENT then
  15. SWEP.PrintName = "Prop Disguiser"
  16. SWEP.Slot = 7
  17. SWEP.DrawAmmo = false
  18. SWEP.DrawCrosshair = true
  19.  
  20. SWEP.Icon = "vgui/ttt/exho_propdisguiser.png"
  21.  
  22. SWEP.EquipMenuData = {
  23. type = "item_weapon",
  24. desc = "Allows you to disguise yourself as a Prop!\n\nReload key to select a new prop."
  25. };
  26. end
  27.  
  28. SWEP.HoldType = "normal"
  29. SWEP.Base = "weapon_tttbase"
  30. SWEP.Kind = WEAPON_EQUIP
  31. SWEP.CanBuy = { ROLE_TRAITOR }
  32. SWEP.Spawnable = true
  33. SWEP.AdminSpawnable = true
  34. SWEP.AutoSpawnable = false
  35. SWEP.ViewModel = "models/weapons/v_pistol.mdl"
  36. SWEP.WorldModel = "models/weapons/w_pistol.mdl"
  37. SWEP.ViewModelFlip = false
  38.  
  39. ------ CONFIGURATION ------
  40. SWEP.Primary.Delay = 2 -- Time limit after undisguising until next disguise
  41. SWEP.Secondary.Delay = 2 -- The exact opposite of that ^
  42.  
  43. SWEP.DisguiseProp = Model("models/props_c17/oildrum001.mdl") -- Default disguise model
  44. SWEP.DisguiseTime = 25 -- How long, seconds, for the player to be disguised
  45. SWEP.DisguiseHealth = 50 -- Health for the disguised prop to have. Works with about half the models
  46.  
  47. SWEP.MaxRadius = 100 -- Max radius of a chosen prop. If its bigger than the player cannot use it
  48. SWEP.MinRadius = 5 -- Min radius of a chosen prop
  49. ------ //END CONFIGURATION//------
  50.  
  51. SWEP.Prop = nil
  52. SWEP.Disguised = false
  53. SWEP.AllowDrop = true
  54.  
  55. -- Put the Model Names of props that pass the criteria but you dont want anyone to use. Seperate each string WITH a comma
  56. -- Example of a model path would be "models/props_junk/wood_crate001a.mdl"
  57. SWEP.Blacklist = {
  58.  
  59. }
  60.  
  61. local function PD_Msg(txt, ply)
  62. if SERVER then
  63. net.Start("PD_ChatPrint")
  64. net.WriteString(txt)
  65. net.Send(ply)
  66. end
  67. end
  68.  
  69. function SWEP:PrimaryAttack()
  70. local ply = self.Owner
  71.  
  72. if not self:GetNWBool("PD_WepDisguised") then
  73. if IsValid(self.Prop) then self.Prop:Remove() end -- Just in case the prop already exists
  74. ply:SetNWBool("PD_Disguised", true)
  75. self:SetNextPrimaryFire(CurTime()+self.Primary.Delay)
  76. self:PropDisguise() -- The main attraction, disguise
  77. else
  78. PD_Msg("You are already disguised.", ply)
  79. return
  80. end
  81. end
  82.  
  83. function SWEP:SecondaryAttack()
  84. if self:GetNWBool("PD_WepDisguised") then
  85. self.Owner:SetNWBool("PD_Disguised", false)
  86. self:SetNextSecondaryFire(CurTime()+self.Secondary.Delay)
  87. self:PropUnDisguise()
  88. end
  89. end
  90.  
  91. function SWEP:Reload()
  92. if self:GetNWBool("PD_WepDisguised") then -- If you are a prop, the trace 'hits' your entity.
  93. PD_Msg("You can't choose a new model while disguised, silly", ply)
  94. return
  95. else
  96. self:ModelHandler()
  97. end
  98. end
  99.  
  100. function SWEP:PropDisguise()
  101. local ply = self.Owner
  102. if self:GetNWBool("PD_WepDisguised") then print("HOW DID YOU GET THIS FAR??") return end -- Cant be too careful!
  103. --self.Disguised = true
  104. self:SetNWBool("PD_TimeOut", false)
  105. if not IsValid(ply) or not ply:Alive() then print("Player aint valid, yo") return end
  106.  
  107. if SERVER then
  108. -- Undisguise after the time limit
  109. timer.Create(ply:SteamID().."_DisguiseTime", self.DisguiseTime, 1, function()
  110. self:SetNWBool("PD_TimeOut", true)
  111. self:SetNextPrimaryFire(CurTime()+self.Primary.Delay + 5) -- Small delay after timer going out
  112. self:PropUnDisguise()
  113. end)
  114. self.AllowDrop = false
  115. ply:SetNWFloat("PD_TimeLeft", CurTime() + self.DisguiseTime) -- Clientside timer
  116. ply:SetNWBool("PD_Disguised", true) -- Shared - player disguised
  117. self:SetNWBool("PD_WepDisguised", true)
  118.  
  119. self.Prop = ents.Create("prop_physics") -- Create our disguise
  120. local prop = self.Prop
  121. prop:SetModel(self.DisguiseProp)
  122. local ang = ply:GetAngles()
  123. ang.x = 0 -- The Angles should always be horizontal
  124. prop:SetAngles(ang)
  125. prop:SetPos(ply:GetPos() + Vector(0,0,20))
  126. prop.fakehp = self.DisguiseHealth -- Using our own health value
  127. prop.plyhp = ply:Health()
  128. prop.hp_constant = self.DisguiseHealth
  129. ply:SetHealth(50) -- This is the prop's health but displayed as their own
  130. prop.IsADisguise = true -- Identifier for our prop
  131. prop.TiedPly = ply -- The Master
  132. prop:SetName(ply:Nick().."'s Disguised Prop") -- Prevent spectator possessing if TTT
  133. ply.DisguisedProp = prop
  134.  
  135. prop:Spawn()
  136.  
  137. local phys = prop:GetPhysicsObject()
  138. if not IsValid(phys) then return end
  139. phys:SetVelocity(ply:GetVelocity())
  140.  
  141. -- Spectate it
  142. ply:Spectate(OBS_MODE_CHASE)
  143. ply:SpectateEntity(self.Prop)
  144. ply:SelectWeapon(self:GetClass())
  145. ply:SetNoDraw(true)
  146. ply:DrawViewModel(false)
  147. ply:DrawWorldModel(false)
  148.  
  149. PD_Msg("Enabled Prop Disguise!", ply)
  150. end
  151. end
  152.  
  153. function SWEP:PropUnDisguise()
  154. local ply = self.Owner
  155. local prop = self.Prop
  156.  
  157. if IsValid(self.Prop) and IsValid(self.Owner) and self:GetNWBool("PD_WepDisguised") then
  158. prop.IsADisguise = false
  159. self.AllowDrop = true
  160. ply:SetNWFloat("PD_TimeLeft", 0)
  161. ply:SetNWBool("PD_Disguised", false)
  162. self:SetNWBool("PD_WepDisguised", false)
  163.  
  164. timer.Destroy(ply:SteamID().."_DisguiseTime")
  165.  
  166. ply:UnSpectate()
  167. ply:Spawn() -- We have to spawn before editing anything
  168.  
  169. ply:SetNoDraw(false)
  170. ply:SetAngles(prop:GetAngles())
  171. ply:SetPos(prop:GetPos())
  172. ply:SetHealth( prop.plyhp ) -- Clamp health, explanation below
  173. ply:SetVelocity(prop:GetVelocity())
  174. ply:DrawViewModel(true)
  175. ply:DrawWorldModel(true)
  176. ply:SelectWeapon(self:GetClass())
  177. prop:Remove() -- Banish our prop
  178. prop = nil
  179.  
  180. local tout = self:GetNWBool("PD_TimeOut", true)
  181. if tout then
  182. PD_Msg("Timer ran out and you were undisguised! This weapon will cooldown for 5 seconds", ply)
  183. else
  184. PD_Msg("Disabled Prop Disguise!", ply)
  185. end
  186. end
  187. end
  188.  
  189. local seen
  190. function SWEP:ModelHandler()
  191. local ply = self.Owner -- Ply is a lot easier to type
  192. local tr = ply:GetEyeTrace()
  193. local ent = tr.Entity
  194.  
  195. if seen then return end -- To prevent chat spamming of messages
  196. seen = true
  197. timer.Simple(1, function() seen = false end)
  198.  
  199. if ent:IsPlayer() or ent:IsNPC() or ent:GetClass() == "prop_ragdoll" or tr.HitWorld or ent:IsWeapon() then
  200. PD_Msg("That entity is not a prop.", ply)
  201. return
  202. elseif IsValid(ent) then -- The PROP is valid
  203. if string.sub( ent:GetClass(), 1, 5 ) ~= "prop_" then -- The last check
  204. PD_Msg("That entity is not a valid prop", ply)
  205. return
  206. end
  207. -- This entity IS a prop without a shadow of a doubt.
  208. for CANT, EVEN in pairs(self.Blacklist) do
  209. if ent:GetModel() == EVEN then
  210. print("I LITERALLY CANT EVEN")
  211. PD_Msg("That model is blacklisted, sorry.", ply)
  212. return
  213. end
  214. end
  215.  
  216. local mdl = ent:GetModel()
  217. local rad = ent:BoundingRadius()
  218. if rad < self.MinRadius then -- All self explanatory
  219. PD_Msg("That model is too small!", ply)
  220. return
  221. elseif rad > self.MaxRadius then
  222. PD_Msg("That model is too big!", ply)
  223. return
  224. else -- If its not a bad prop, choose it.
  225. self.DisguiseProp = mdl
  226. PD_Msg("Set Disguise Model to ("..mdl..")!", ply)
  227. end
  228. end
  229. end
  230.  
  231. function SWEP:DrawHUD()
  232. local ply = self.Owner
  233. local propped = ply:GetNWBool("PD_Disguised")
  234. local disguised = self:GetNWBool("PD_WepDisguised")
  235.  
  236. --print(disguised, propped)
  237. if disguised and propped then
  238. local w = ScrW()
  239. local h = ScrH()
  240. local x_axis, y_axis, width, height = 800, 98, 320, 54
  241. draw.RoundedBox(2, x_axis, y_axis, width, height, Color(10,10,10,200))
  242.  
  243. local timeleft = ply:GetNWFloat("PD_TimeLeft") - CurTime() -- Subtract (float + Cur) from Cur
  244. timeleft = math.Round(timeleft or 0, 1) -- Round for simplicity
  245. timeleft = math.Clamp(timeleft, 0, self.DisguiseTime) -- Clamp to prevent negatives
  246.  
  247. local Segments = width / self.DisguiseTime -- Divide the width into the timer
  248. local CountdownBar = timeleft * Segments -- Bar length
  249. CountdownBar = math.Clamp(CountdownBar, 3, 320)
  250.  
  251. draw.RoundedBox(2, x_axis, y_axis, CountdownBar, height, Color(52, 152, 219,200))
  252. draw.SimpleText(timeleft, "Trebuchet24", x_axis + 160, y_axis + 27, Color(255,255,255,255), 1, 1)
  253. end
  254. end
  255.  
  256. local function DeathHandler(ply, inflictor, att)
  257. if ply:GetNWBool("PD_Disguised") then
  258. if IsValid(ply.DisguisedProp) then
  259. ply.DisguisedProp:Remove() -- If the player is disguised, remove their disguise.
  260. end
  261. end
  262. end
  263.  
  264. local function DamageHandler( ent, dmginfo ) -- Entity Take Damage
  265. -- Damage method copied from my Destructible Doors and Door Locker addons
  266. if ent.IsADisguise and SERVER and IsValid(ent.TiedPly) then
  267. local ply = ent.TiedPly
  268.  
  269. local dbug_mdl = ent:GetModel()
  270. local h = ent.fakehp
  271. local dmg = dmginfo:GetDamage()
  272. ent.fakehp = h - (dmg) -- Artificially take damage for the prop
  273. ent.hp_constant = ent:Health() -- Make sure this stays updated
  274. if ent.fakehp <= 0 then
  275. net.Start("DisguiseDestroyed")
  276. net.Send(ply) -- Tell the client to draw our fancy messages
  277.  
  278. ply:Kill() -- Kill the player
  279.  
  280. local effectdata = EffectData() -- EFFECTS!
  281. effectdata:SetOrigin( ent:GetPos() + ent:OBBCenter() )
  282. effectdata:SetMagnitude( 5 )
  283. effectdata:SetScale( 2 )
  284. effectdata:SetRadius( 5 )
  285. util.Effect( "Sparks", effectdata )
  286. ent:Remove() -- Remove the disguise
  287. else
  288. -- Sometimes the Prop's defined Health is lower than what it should be, so it gets destroyed early.
  289. -- This is a fix for it
  290. timer.Simple(0.5, function() -- Wait a little bit
  291. if not IsValid(ent) and ply:GetNWBool("PD_Disguised") then
  292. -- Player is disguised but the disguise doesnt exist anymore
  293. print("[Prop Disguise Debug]")
  294. print(ply:Nick().." used wonky prop ("..dbug_mdl..") and was automatically killed!")
  295. print("Recommended you add this prop to the blacklist")
  296. ply:Kill() -- Kill the player
  297. net.Start("DisguiseDestroyed")
  298. net.Send(ply)
  299. end
  300. end)
  301. end
  302. end
  303. end
  304. hook.Add("EntityTakeDamage","CauseGodModeIsOP", DamageHandler)
  305. hook.Add("PlayerDeath","EntDestroyeronDeath", DeathHandler)
  306.  
  307. if CLIENT then
  308. local white = Color( 255, 255, 255 )
  309. local PropDisguiseCol = Color(52, 152, 219)
  310.  
  311. net.Receive( "DisguiseDestroyed", function( len, ply ) -- Recieve the message
  312. chat.AddText( PropDisguiseCol, "Prop Disguiser: ", white,
  313. "Your disguise was destroyed and you were ", Color( 170, 0, 0 ), "KILLED",white,"!!")
  314. end)
  315.  
  316. net.Receive( "PD_ChatPrint", function( len, ply ) -- Recieve the message
  317. local txt = net.ReadString()
  318. chat.AddText( PropDisguiseCol, "Prop Disguiser: ", white, txt)
  319. end)
  320. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement