----------------------------------------------------- ------------------------------------- ---------------- Cuffs -------------- ------------------------------------- -- Copyright (c) 2015 Nathan Healy -- -------- All rights reserved -------- ------------------------------------- -- weapon_handcuffed.lua SHARED -- -- -- -- Handcuffed. Limits what -- -- equipping player can do. -- ------------------------------------- AddCSLuaFile() SWEP.Base = "weapon_base" SWEP.Category = "Handcuffs" SWEP.Author = "my_hat_stinks" SWEP.Instructions = "" SWEP.Spawnable = false SWEP.AdminSpawnable = false SWEP.AdminOnly = false SWEP.Slot = 4 SWEP.PrintName = "Handcuffed" SWEP.ViewModelFOV = 60 SWEP.Weight = 5 SWEP.AutoSwitchTo = false SWEP.AutoSwitchFrom = false SWEP.WorldModel = "models/weapons/w_toolgun.mdl" SWEP.ViewModel = "models/weapons/c_arms_citizen.mdl" SWEP.UseHands = true SWEP.Primary.Recoil = 1 SWEP.Primary.Damage = 5 SWEP.Primary.NumShots = 1 SWEP.Primary.Cone = 0 SWEP.Primary.Delay = 1 SWEP.Primary.ClipSize = -1 SWEP.Primary.DefaultClip = -1 SWEP.Primary.Automatic = false SWEP.Primary.Ammo = "none" SWEP.Primary.ClipMax = -1 SWEP.Secondary.ClipSize = -1 SWEP.Secondary.DefaultClip = -1 SWEP.Secondary.Automatic = false SWEP.Secondary.Ammo = "none" SWEP.Secondary.ClipMax = -1 SWEP.DeploySpeed = 1.5 SWEP.PrimaryAnim = ACT_VM_PRIMARYATTACK SWEP.ReloadAnim = ACT_VM_RELOAD SWEP.HoldType = "duel" SWEP.IsHandcuffs = true SWEP.CuffType = "" local LEASH = {} CreateConVar( "cuffs_allowbreakout", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE,FCVAR_REPLICATED,FCVAR_NOTIFY} ) // For anything that might try to drop this SWEP.CanDrop = false SWEP.PreventDrop = true -- Missing anything? // // DataTables function SWEP:SetupDataTables() self:NetworkVar( "Entity", 0, "Kidnapper" ) self:NetworkVar( "Entity", 1, "FriendBreaking" ) self:NetworkVar( "Float", 0, "RopeLength" ) self:NetworkVar( "Float", 1, "CuffBroken" ) self:NetworkVar( "Float", 2, "CuffStrength" ) self:NetworkVar( "Float", 3, "CuffRegen" ) self:NetworkVar( "String", 0, "RopeMaterial" ) self:NetworkVar( "String", 1, "CuffMaterial" ) self:NetworkVar( "Bool", 0, "CanGag" ) self:NetworkVar( "Bool", 1, "IsGagged" ) self:NetworkVar( "Bool", 2, "CanBlind" ) self:NetworkVar( "Bool", 3, "IsBlind" ) self:NetworkVar( "Bool", 4, "IsLeash" ) end // // Initialize function SWEP:Initialize() hook.Add( "canDropWeapon", self, function(self, ply, wep) if wep==self then return false end end) // Thank you DarkRP, your code is terrible if SERVER then hook.Add( "Think", self, self.BreakThink ) end if CLIENT then hook.Add( "HUDPaint", self, self.CuffsHUD ) hook.Add( "HUDPaintBackground", self, self.BlindHUDBackground ) end if self:GetCuffStrength()<=0 then self:SetCuffStrength(1) end if self:GetCuffRegen()<=0 then self:SetCuffRegen(1) end self:SetCuffBroken( 0 ) self:SetHoldType( self.HoldType ) end // // Standard SWEP functions function SWEP:PrimaryAttack() if SERVER then self:AttemptBreak() end end function SWEP:SecondaryAttack() end function SWEP:Reload() end // // Equip and Holster function SWEP:Equip( newOwner ) newOwner:SelectWeapon( self:GetClass() ) timer.Simple( 0.1, function() // Fucking FA:S if IsValid(self) and IsValid(newOwner) and newOwner:GetActiveWeapon()~=self then local wep = newOwner:GetActiveWeapon() if not IsValid(wep) then return end local oHolster = wep.Holster wep.Holster = function() return true end newOwner:SelectWeapon( self:GetClass() ) wep.Holster = oHolster end end) return true end function SWEP:Holster() return self:GetIsLeash() end // // Deploy function SWEP:Deploy() local viewModel = self.Owner:GetViewModel() viewModel:SendViewModelMatchingSequence( viewModel:LookupSequence("fists_idle_01") ) return true end function SWEP:PreDrawViewModel( viewModel ) // Fixes visible base hands viewModel:SetMaterial( "engine/occlusionproxy" ) end if CLIENT then local HadCuffs hook.Add( "PreDrawOpaqueRenderables", "Cuffs FixViewModel", function() local ply = LocalPlayer() if not IsValid(ply) then return end local HasCuffs = IsValid(ply:GetActiveWeapon()) and ply:GetActiveWeapon():GetClass()=="weapon_handcuffed" if HadCuffs and not HasCuffs then local vm = ply:GetViewModel() if IsValid(vm) then vm:SetMaterial( "" ) end end HadCuffs = HasCuffs end) end function SWEP:OnRemove() // Fixes invisible other weapons if IsValid(self.Owner) then local viewModel = self.Owner:GetViewModel() if IsValid(viewModel) then viewModel:SetMaterial("") end end if IsValid( self.cmdl_LeftCuff ) then self.cmdl_LeftCuff:Remove() end if IsValid( self.cmdl_RightCuff ) then self.cmdl_RightCuff:Remove() end return true end // // Release function SWEP:Uncuff() local ply = IsValid(self.Owner) and self.Owner self:Remove() if ply then ply:ConCommand( "lastinv" ) end end // // Breakout if SERVER then local BreakSound = Sound( "physics/metal/metal_barrel_impact_soft4.wav" ) function SWEP:Breakout() if IsValid(self.Owner) then sound.Play( BreakSound, self.Owner:GetShootPos(), 75, 100, 1 ) if IsValid( self:GetFriendBreaking() ) then hook.Call( "OnHandcuffBreak", GAMEMODE, self.Owner, self, self:GetFriendBreaking() ) else hook.Call( "OnHandcuffBreak", GAMEMODE, self.Owner, self ) end end self:Uncuff() end function SWEP:AttemptBreak() if not cvars.Bool( "cuffs_allowbreakout" ) then return end self:SetCuffBroken( self:GetCuffBroken() + math.abs(4/self:GetCuffStrength()) ) if self:GetCuffBroken()>=100 then self:Breakout() end end local function GetTrace( ply ) local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} ) if IsValid(tr.Entity) and tr.Entity:IsPlayer() then local cuffed,wep = tr.Entity:IsHandcuffed() if cuffed then return tr,wep end end end function SWEP:BreakThink() if (self.NextRegen or 0)<=CurTime() then local regen = self:GetCuffRegen() local friend = self:GetFriendBreaking() if IsValid(friend) and friend:IsPlayer() then local tr = GetTrace(friend) if tr and tr.Entity==self.Owner then regen = (regen*0.5) - (2/self:GetCuffStrength()) else self:SetFriendBreaking( nil ) end end self:SetCuffBroken( math.Approach( self:GetCuffBroken(), regen<0 and 100 or 0, math.abs(regen) ) ) self.NextRegen = CurTime()+0.05 if self:GetCuffBroken()>=100 then self:Breakout() end end if IsValid(self:GetKidnapper()) and (self:GetKidnapper():IsPlayer() and not self:GetKidnapper():Alive()) then self:SetKidnapper( nil ) end if IsValid(self.Owner) then self.Owner.KnockoutTimer = CurTime()+10 // Fucking DarkRP end end end // // UI if CLIENT then surface.CreateFont( "HandcuffsText", { font = "Arial", size = 20, weight = 700, }) local Col = { Text = Color(255,255,255), TextShadow = Color(0,0,0), BoxOutline = Color(0,0,0), BoxBackground = Color(255,255,255,20), BoxLeft = Color(255,0,0), BoxRight = Color(0,255,0), Blind = Color(0,0,0, 253), Blind2 = Color(0,0,0, 255), } local matGrad = Material( "gui/gradient" ) function SWEP:CuffsHUD() if self.Owner~=LocalPlayer() then return end local w,h = (ScrW()/2), (ScrH()/2) local TextPos = h+30 local str = string.format( "Your hands are bound%s", ((self:GetCuffStrength()>1.2) and " tightly") or ((self:GetCuffStrength()<0.8) and " loosely") or "" ) if self:GetCuffRegen()>1.2 or self:GetCuffRegen()<0.8 then str = str.. string.format( " with a %s material", ((self:GetCuffRegen()>1.2) and "sturdy") or "flimsy" ) end draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER ) draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER ) if self:GetIsBlind() then TextPos = TextPos+20 draw.SimpleText( "You have been bindfolded", "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER ) draw.SimpleText( "You have been bindfolded", "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER ) end if self:GetIsGagged() then TextPos = TextPos+20 draw.SimpleText( "You have been gagged", "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER ) draw.SimpleText( "You have been gagged", "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER ) end if cvars.Bool( "cuffs_allowbreakout" ) then TextPos = TextPos+20 if self.Owner:GetActiveWeapon()==self then str = string.format("%s to struggle", (input.LookupBinding("+attack") or "[Primary Fire]"):upper()) else str = "Switch to ".. self.PrintName .." to break out" end draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER ) draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER ) end TextPos = TextPos+25 surface.SetDrawColor( Col.BoxOutline ) surface.DrawOutlinedRect( w-101, TextPos-1, 202, 22 ) surface.SetDrawColor( Col.BoxBackground ) surface.DrawRect( w-100, TextPos, 200, 20 ) render.SetScissorRect( w-100, TextPos, (w-100)+((self:GetCuffBroken()/100)*200), TextPos+20, true ) surface.SetDrawColor( Col.BoxRight ) surface.DrawRect( w-100,TextPos, 200,20 ) surface.SetMaterial( matGrad ) surface.SetDrawColor( Col.BoxLeft ) surface.DrawTexturedRect( w-100,TextPos, 200,20 ) render.SetScissorRect( 0,0,0,0, false ) end function SWEP:BlindHUDBackground() if self.Owner~=LocalPlayer() then return end if self:GetIsBlind() then surface.SetDrawColor( Col.Blind ) surface.DrawRect( 0,0, ScrW(), ScrH() ) surface.SetDrawColor( Col.Blind2 ) for i=1,ScrH(),5 do surface.DrawRect( 0,i, ScrW(), 4 ) end for i=1,ScrW(),5 do surface.DrawRect( i,0, 4,ScrH() ) end end end end // // Rendering local renderpos = { left = {bone = "ValveBiped.Bip01_L_Wrist", pos=Vector(0.4,-0.15,-0.45), ang=Angle(90,0,0), scale = Vector(0.035,0.035,0.015)}, right = {bone = "ValveBiped.Bip01_R_Wrist", pos=Vector(0.2,-0.15,0.35), ang=Angle(100,0,0), scale = Vector(0.035,0.035,0.015)}, rope = {l = Vector(-0.2,1.3,-0.25), r = Vector(0.4,1.4,-0.2)}, } local CuffMdl = "models/hunter/tubes/tube2x2x1.mdl" local DefaultRope = "cable/cable2" local RopeCol = Color(255,255,255) function SWEP:ViewModelDrawn( vm ) if self:GetIsLeash() then self.ViewModelDrawn = LEASH.ViewModelDrawn return end if not IsValid(vm) then return end if not IsValid(self.cmdl_LeftCuff) then self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_LeftCuff ) then return end // What self.cmdl_LeftCuff:SetNoDraw( true ) self.cmdl_LeftCuff:SetParent( vm ) end if not IsValid(self.cmdl_RightCuff) then self.cmdl_RightCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_RightCuff ) then return end self.cmdl_RightCuff:SetNoDraw( true ) self.cmdl_RightCuff:SetParent( vm ) end local lpos, lang = self:GetBonePos( renderpos.left.bone, vm ) local rpos, rang = self:GetBonePos( renderpos.right.bone, vm ) if not (lpos and rpos and lang and rang) then return end // Left self.cmdl_LeftCuff:SetPos( lpos + (lang:Forward()*renderpos.left.pos.x) + (lang:Right()*renderpos.left.pos.y) + (lang:Up()*renderpos.left.pos.z) ) local u,r,f = lang:Up(), lang:Right(), lang:Forward() // Prevents moving axes lang:RotateAroundAxis( u, renderpos.left.ang.y ) lang:RotateAroundAxis( r, renderpos.left.ang.p ) lang:RotateAroundAxis( f, renderpos.left.ang.r ) self.cmdl_LeftCuff:SetAngles( lang ) local matrix = Matrix() matrix:Scale( renderpos.left.scale ) self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_LeftCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_LeftCuff:DrawModel() // Right self.cmdl_RightCuff:SetPos( rpos + (rang:Forward()*renderpos.right.pos.x) + (rang:Right()*renderpos.right.pos.y) + (rang:Up()*renderpos.right.pos.z) ) local u,r,f = rang:Up(), rang:Right(), rang:Forward() // Prevents moving axes rang:RotateAroundAxis( u, renderpos.right.ang.y ) rang:RotateAroundAxis( r, renderpos.right.ang.p ) rang:RotateAroundAxis( f, renderpos.right.ang.r ) self.cmdl_RightCuff:SetAngles( rang ) local matrix = Matrix() matrix:Scale( renderpos.right.scale ) self.cmdl_RightCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_RightCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_RightCuff:DrawModel() // Rope if self:GetRopeMaterial()~=self.LastMatStr then self.RopeMat = Material( self:GetRopeMaterial() ) self.LastMatStr = self:GetRopeMaterial() end if not self.RopeMat then self.RopeMat = Material(DefaultRope) end render.SetMaterial( self.RopeMat ) render.DrawBeam( lpos + (lang:Forward()*renderpos.rope.l.x) + (lang:Right()*renderpos.rope.l.y) + (lang:Up()*renderpos.rope.l.z), rpos + (rang:Forward()*renderpos.rope.r.x) + (rang:Right()*renderpos.rope.r.y) + (rang:Up()*renderpos.rope.r.z), 0.7, 0, 5, RopeCol ) end local wrender = { left = {bone = "ValveBiped.Bip01_L_Hand", pos=Vector(0,0,0), ang=Angle(90,0,0), scale = Vector(0.035,0.035,0.035)}, right = {bone = "ValveBiped.Bip01_R_Hand", pos=Vector(0.2,0,0), ang=Angle(90,0,0), scale = Vector(0.035,0.035,0.035)}, rope = {l = Vector(-0.2,1.3,-0.25), r = Vector(0.4,1.4,-0.2)}, } function SWEP:DrawWorldModel() if self:GetIsLeash() then -- self.DrawWorldModel = LEASH.DrawWorldModel self.DrawWorldModel = function() end hook.Add( "PostDrawOpaqueRenderables", self, LEASH.DrawWorldModel ) return end if not IsValid(self.Owner) then return end if not IsValid(self.cmdl_LeftCuff) then self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_LeftCuff ) then return end self.cmdl_LeftCuff:SetNoDraw( true ) -- self.cmdl_LeftCuff:SetParent( vm ) end if not IsValid(self.cmdl_RightCuff) then self.cmdl_RightCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_RightCuff ) then return end self.cmdl_RightCuff:SetNoDraw( true ) -- self.cmdl_RightCuff:SetParent( vm ) end local lpos, lang = self:GetBonePos( wrender.left.bone, self.Owner ) local rpos, rang = self:GetBonePos( wrender.right.bone, self.Owner ) if not (lpos and rpos and lang and rang) then return end // Left self.cmdl_LeftCuff:SetPos( lpos + (lang:Forward()*wrender.left.pos.x) + (lang:Right()*wrender.left.pos.y) + (lang:Up()*wrender.left.pos.z) ) local u,r,f = lang:Up(), lang:Right(), lang:Forward() // Prevents moving axes lang:RotateAroundAxis( u, wrender.left.ang.y ) lang:RotateAroundAxis( r, wrender.left.ang.p ) lang:RotateAroundAxis( f, wrender.left.ang.r ) self.cmdl_LeftCuff:SetAngles( lang ) local matrix = Matrix() matrix:Scale( wrender.left.scale ) self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_LeftCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_LeftCuff:DrawModel() // Right self.cmdl_RightCuff:SetPos( rpos + (rang:Forward()*wrender.right.pos.x) + (rang:Right()*wrender.right.pos.y) + (rang:Up()*wrender.right.pos.z) ) local u,r,f = rang:Up(), rang:Right(), rang:Forward() // Prevents moving axes rang:RotateAroundAxis( u, wrender.right.ang.y ) rang:RotateAroundAxis( r, wrender.right.ang.p ) rang:RotateAroundAxis( f, wrender.right.ang.r ) self.cmdl_RightCuff:SetAngles( rang ) local matrix = Matrix() matrix:Scale( wrender.right.scale ) self.cmdl_RightCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_RightCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_RightCuff:DrawModel() // Rope if (lpos.x==0 and lpos.y==0 and lpos.z==0) or (rpos.x==0 and rpos.y==0 and rpos.z==0) then return end // Rope accross half the map... if self:GetRopeMaterial()~=self.LastMatStr then self.RopeMat = Material( self:GetRopeMaterial() ) self.LastMatStr = self:GetRopeMaterial() end if not self.RopeMat then self.RopeMat = Material(DefaultRope) end render.SetMaterial( self.RopeMat ) render.DrawBeam( lpos + (lang:Forward()*wrender.rope.l.x) + (lang:Right()*wrender.rope.l.y) + (lang:Up()*wrender.rope.l.z), rpos + (rang:Forward()*wrender.rope.r.x) + (rang:Right()*wrender.rope.r.y) + (rang:Up()*wrender.rope.r.z), 0.7, 0, 5, RopeCol ) end // // Bones function SWEP:GetBonePos( bonename, vm ) local bone = vm:LookupBone( bonename ) if not bone then return end local pos,ang = Vector(0,0,0),Angle(0,0,0) local matrix = vm:GetBoneMatrix( bone ) if matrix then pos = matrix:GetTranslation() ang = matrix:GetAngles() end if self.ViewModelFlip then ang.r = -ang.r end -- if pos.x==0 and pos.y==0 and pos.z==0 then print( bonename, vm ) end return pos, ang end // // Leash LEASH.HoldType = "normal" // // Rendering local vrender = { bone = "ValveBiped.Bip01_L_Wrist", pos=Vector(0,0,-1.5), ang=Angle(0,0,0), scale = Vector(0.01,0.01,0.02), } function LEASH:ViewModelDrawn( vm ) self.UseHands = false if not (IsValid(self) and IsValid(self.Owner)) then return end if not IsValid(self.cmdl_LeftCuff) then self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_LeftCuff ) then return end self.cmdl_LeftCuff:SetNoDraw( true ) -- self.cmdl_LeftCuff:SetParent( vm ) end local lpos, lang = self:GetBonePos( vrender.bone, self.Owner ) if not (lpos and lang) then return end -- lpos = self.Owner:GetPos() + self.Owner:GetCurrentViewOffset() -- lang = Angle(0,0,0) self.cmdl_LeftCuff:SetPos( lpos + (lang:Forward()*vrender.pos.x) + (lang:Right()*vrender.pos.y) + (lang:Up()*vrender.pos.z) ) local u,r,f = lang:Up(), lang:Right(), lang:Forward() // Prevents moving axes lang:RotateAroundAxis( u, vrender.ang.y ) lang:RotateAroundAxis( r, vrender.ang.p ) lang:RotateAroundAxis( f, vrender.ang.r ) self.cmdl_LeftCuff:SetAngles( lang ) local matrix = Matrix() matrix:Scale( vrender.scale ) self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_LeftCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_LeftCuff:DrawModel() end local lrender = { normal = { bone = "ValveBiped.Bip01_Neck1", pos=Vector(2,1.8,0), ang=Angle(70,90,90), scale = Vector(0.06,0.06,0.05), }, alt = { // Eeveelotions models bone = "Neck", pos=Vector(1,0.5,-0.2), ang=Angle(100,90,90), scale = Vector(0.082,0.082,0.082), }, } function LEASH.DrawWorldModel(self) if not (IsValid(self) and IsValid(self.Owner)) then return end if self.Owner==LocalPlayer() and self.Owner:GetActiveWeapon()==self and not hook.Call("ShouldDrawLocalPlayer", GAMEMODE, self.Owner) then return end if not IsValid(self.cmdl_LeftCuff) then self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE ) if not IsValid( self.cmdl_LeftCuff ) then return end self.cmdl_LeftCuff:SetNoDraw( true ) -- self.cmdl_LeftCuff:SetParent( vm ) end local tbl = lrender.normal local lpos, lang = self:GetBonePos( tbl.bone, self.Owner ) if not (lpos) then tbl = lrender.alt lpos, lang = self:GetBonePos( tbl.bone, self.Owner ) if not (lpos) then return end end self.cmdl_LeftCuff:SetPos( lpos + (lang:Forward()*tbl.pos.x) + (lang:Right()*tbl.pos.y) + (lang:Up()*tbl.pos.z) ) local u,r,f = lang:Up(), lang:Right(), lang:Forward() // Prevents moving axes lang:RotateAroundAxis( u, tbl.ang.y ) lang:RotateAroundAxis( r, tbl.ang.p ) lang:RotateAroundAxis( f, tbl.ang.r ) self.cmdl_LeftCuff:SetAngles( lang ) local matrix = Matrix() matrix:Scale( tbl.scale ) self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix ) self.cmdl_LeftCuff:SetMaterial( self:GetCuffMaterial() or "" ) self.cmdl_LeftCuff:DrawModel() end