add sborka
This commit is contained in:
306
garrysmod/addons/handcuffs/lua/autorun/server/sv_handcuffs.lua
Normal file
306
garrysmod/addons/handcuffs/lua/autorun/server/sv_handcuffs.lua
Normal file
@@ -0,0 +1,306 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- sv_handcuffs.lua SERVER --
|
||||
-- --
|
||||
-- Server-side handcuff stuff. --
|
||||
-------------------------------------
|
||||
|
||||
if CLIENT then return end
|
||||
|
||||
util.AddNetworkString( "Cuffs_GagPlayer" )
|
||||
util.AddNetworkString( "Cuffs_BlindPlayer" )
|
||||
util.AddNetworkString( "Cuffs_FreePlayer" )
|
||||
util.AddNetworkString( "Cuffs_DragPlayer" )
|
||||
|
||||
util.AddNetworkString( "Cuffs_TiePlayers" )
|
||||
util.AddNetworkString( "Cuffs_UntiePlayers" )
|
||||
|
||||
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
|
||||
|
||||
//
|
||||
// Standard hooks
|
||||
CreateConVar( "cuffs_restrictsuicide", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "CanPlayerSuicide", "Cuffs RestrictSuicide", function( ply )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictarrest") then return false end
|
||||
end)
|
||||
CreateConVar( "cuffs_restrictteams", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "PlayerCanJoinTeam", "Cuffs RestrictTeam", function( ply )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictteams") then return false end
|
||||
end)
|
||||
hook.Add( "PlayerCanSeePlayersChat", "Cuffs ChatGag", function( _,_,_, ply )
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local cuffed,wep = ply:IsHandcuffed()
|
||||
if cuffed and wep:GetIsGagged() then return false end
|
||||
end)
|
||||
hook.Add( "PlayerCanHearPlayersVoice", "Cuffs VoiceGag", function( _, ply )
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local cuffed,wep = ply:IsHandcuffed()
|
||||
if cuffed and wep:GetIsGagged() then return false end
|
||||
end)
|
||||
|
||||
//
|
||||
// DarkRP
|
||||
CreateConVar( "cuffs_restrictwarrant", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE,FCVAR_REPLICATED} )
|
||||
hook.Add( "canRequestWarrant", "Cuffs PreventWarrant", function( crim, cop, reason ) if cvars.Bool("cuffs_restrictwarrant") and cop:IsHandcuffed() then return false,"You can issue warrants when cuffed!" end end)
|
||||
hook.Add( "canWanted", "Cuffs PreventWarrant", function( crim, cop, reason ) if cvars.Bool("cuffs_restrictwarrant") and cop:IsHandcuffed() then return false,"You can issue warrants when cuffed!" end end)
|
||||
|
||||
CreateConVar( "cuffs_autoarrest", 0, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
CreateConVar( "cuffs_restrictarrest", 0, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "canArrest", "Cuffs RestrictArrest", function( cop, crim ) // DarkRP Arrest hook
|
||||
if IsValid(crim) and cvars.Bool("cuffs_restrictarrest") and not crim:IsHandcuffed() then return false,"You must handcuff a suspect to arrest them!" end
|
||||
end)
|
||||
hook.Add( "playerCanChangeTeam", "Cuffs RestrictTeam", function( ply, tm, force )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictteams") and not force then return false,"You can't change jobs when cuffed!" end
|
||||
end)
|
||||
hook.Add( "CanChangeRPName", "Cuffs RestrictName", function( ply )
|
||||
if ply:IsHandcuffed() then return false,"You can't change your name when cuffed!" end
|
||||
end)
|
||||
|
||||
//
|
||||
// Think
|
||||
local NextTieHookCleanup
|
||||
hook.Add( "Think", "Cuffs ForceJump CleanupTieHooks", function()
|
||||
for _,v in pairs(player.GetAll()) do
|
||||
if v.Cuff_ForceJump then
|
||||
if not v:OnGround() then return end
|
||||
|
||||
local tr = util.TraceLine( {start = v:GetPos(), endpos = v:GetPos()+Vector(0,0,20), filter = v} )
|
||||
if tr.Hit then return end
|
||||
|
||||
v:SetPos(v:GetPos()+Vector(0,0,5) )
|
||||
|
||||
v.Cuff_ForceJump = nil
|
||||
end
|
||||
end
|
||||
|
||||
if CurTime()>=(NextTieHookCleanup or 0) then
|
||||
for _,v in pairs(ents.GetAll()) do
|
||||
if v.IsHandcuffHook and v.TiedHandcuffs then
|
||||
for i=#v.TiedHandcuffs,0,-1 do
|
||||
if not IsValid(v.TiedHandcuffs[i]) then
|
||||
table.remove( v.TiedHandcuffs, i )
|
||||
end
|
||||
end
|
||||
if #v.TiedHandcuffs<=0 then
|
||||
v:Remove()
|
||||
continue
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Cuffed player interaction
|
||||
net.Receive( "Cuffs_GagPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetCanGag()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldGag = net.ReadBit()==1
|
||||
cuffs:SetIsGagged( shouldGag )
|
||||
hook.Call( shouldGag and "OnHandcuffGag" or "OnHandcuffUnGag", GAMEMODE, ply, target, cuffs )
|
||||
end)
|
||||
net.Receive( "Cuffs_BlindPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetCanBlind()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldBlind = net.ReadBit()==1
|
||||
cuffs:SetIsBlind( shouldBlind )
|
||||
hook.Call( shouldBlind and "OnHandcuffBlindfold" or "OnHandcuffUnBlindfold", GAMEMODE, ply, target, cuffs )
|
||||
end)
|
||||
net.Receive( "Cuffs_FreePlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs)) then return end
|
||||
if IsValid(cuffs:GetFriendBreaking()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
cuffs:SetFriendBreaking( ply )
|
||||
end)
|
||||
net.Receive( "Cuffs_DragPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetRopeLength()>0) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldDrag = net.ReadBit()==1
|
||||
if shouldDrag then
|
||||
if not (IsValid(cuffs:GetKidnapper())) then
|
||||
cuffs:SetKidnapper( ply )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, ply, target, cuffs )
|
||||
end
|
||||
else
|
||||
if ply==cuffs:GetKidnapper() then
|
||||
cuffs:SetKidnapper( nil )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, target, cuffs )
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local HookModel = Model("models/props_c17/TrapPropeller_Lever.mdl")
|
||||
net.Receive( "Cuffs_TiePlayers", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local DraggedCuffs = {}
|
||||
for _,c in pairs(ents.FindByClass("weapon_handcuffed")) do
|
||||
if c:GetRopeLength()>0 and c:GetKidnapper()==ply then
|
||||
table.insert( DraggedCuffs, c )
|
||||
end
|
||||
end
|
||||
if #DraggedCuffs<=0 then return end
|
||||
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if not tr.Hit then return end
|
||||
|
||||
if IsValid(tr.Entity) then // Pass to another player
|
||||
if tr.Entity:IsPlayer() then
|
||||
for i=1,#DraggedCuffs do
|
||||
if DraggedCuffs[i].Owner==tr.Entity then
|
||||
DraggedCuffs[i]:SetKidnapper(nil)
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
else
|
||||
DraggedCuffs[i]:SetKidnapper(tr.Entity)
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, tr.Entity, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
end
|
||||
end
|
||||
return
|
||||
elseif tr.Entity.IsHandcuffHook and tr.Entity.TiedHandcuffs then
|
||||
for i=1,#DraggedCuffs do
|
||||
DraggedCuffs[i]:SetKidnapper(tr.Entity)
|
||||
table.insert( tr.Entity.TiedHandcuffs, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffTied", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i], tr.Entity )
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local hk = ents.Create("prop_physics")
|
||||
hk:SetPos( tr.HitPos + tr.HitNormal )
|
||||
local ang = tr.HitNormal:Angle()
|
||||
ang:RotateAroundAxis( ang:Up(), -90 )
|
||||
hk:SetAngles( ang )
|
||||
hk:SetModel( HookModel )
|
||||
hk:Spawn()
|
||||
|
||||
-- hk:SetMoveType( MOVETYPE_NONE )
|
||||
if IsValid(tr.Entity) then
|
||||
hk:SetParent( tr.Entity )
|
||||
hk:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
else
|
||||
hk:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
hk:SetCollisionGroup( COLLISION_GROUP_WEAPON )
|
||||
|
||||
hk:SetNWBool("Cuffs_TieHook", true)
|
||||
hk.IsHandcuffHook = true
|
||||
hk.TiedHandcuffs = {}
|
||||
|
||||
for i=1,#DraggedCuffs do
|
||||
DraggedCuffs[i]:SetKidnapper( hk )
|
||||
table.insert( hk.TiedHandcuffs, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffTied", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i], hk )
|
||||
end
|
||||
end)
|
||||
|
||||
local function DoUntie( ply, ent )
|
||||
for i=1,#ent.TiedHandcuffs do
|
||||
if not IsValid(ent.TiedHandcuffs[i]) then continue end
|
||||
|
||||
ent.TiedHandcuffs[i]:SetKidnapper( ply )
|
||||
hook.Call( "OnHandcuffUnTied", GAMEMODE, ply, ent.TiedHandcuffs[i].Owner, ent.TiedHandcuffs[i], ent )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, ply, ent.TiedHandcuffs[i].Owner, ent.TiedHandcuffs[i] )
|
||||
end
|
||||
|
||||
ent:Remove()
|
||||
end
|
||||
net.Receive( "Cuffs_UntiePlayers", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if IsValid(tr.Entity) and tr.Entity.IsHandcuffHook and tr.Entity.TiedHandcuffs then
|
||||
DoUntie( ply, tr.Entity )
|
||||
end
|
||||
end)
|
||||
hook.Add( "AllowPlayerPickup", "Cuffs UntieHook", function(ply,ent)
|
||||
if IsValid(ent) and ent.IsHandcuffHook and ent.TiedHandcuffs then
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
DoUntie( ply, ent )
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// GmodDayZ support
|
||||
// Created by and added with permission of Phoenix129 ( http://steamcommunity.com/profiles/76561198039440140/ )
|
||||
hook.Add("OnHandcuffed", "DayZCuffs RemoveInventoryItem", function(ply, cuffedply, handcuffs)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
ply:TakeCharItem( handcuffs.CuffType )
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("OnHandcuffBreak", "DayZCuffs GiveInventoryItemIfFriend", function(cuffedply, handcuffs, friend)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if IsValid(friend) and handcuffs.CuffType and handcuffs.CuffType~="" then
|
||||
friend:GiveItem(handcuffs.CuffType, 1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add( "CuffsCanHandcuff", "DayZCuffs SafezoneProtectCuffs", function( ply, target )
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if target.SafeZone or target.SafeZoneEdge or target.Loading or !target.Ready then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end)
|
||||
hook.Add("PlayerDisconnected", "DayZCuffs DieHandcuffs", function(ply)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if ply:IsHandcuffed() then ply:Kill() end
|
||||
end
|
||||
end)
|
||||
403
garrysmod/addons/handcuffs/lua/autorun/sh_handcuffs.lua
Normal file
403
garrysmod/addons/handcuffs/lua/autorun/sh_handcuffs.lua
Normal file
@@ -0,0 +1,403 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- sh_handcuffs.lua SHARED --
|
||||
-- --
|
||||
-- Shared handcuff stuff. --
|
||||
-------------------------------------
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
//
|
||||
// Config
|
||||
local ProtectedJobs = {
|
||||
"TEAM_PLAYER", "TEAM_MOD", "TEAM_PLAYER",
|
||||
}
|
||||
|
||||
//
|
||||
// Utility
|
||||
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
|
||||
|
||||
//
|
||||
// PLAYER extensions
|
||||
local PLAYER = FindMetaTable( "Player" )
|
||||
function PLAYER:IsHandcuffed()
|
||||
local wep = self:GetWeapon( "weapon_handcuffed" )
|
||||
if IsValid(wep) and wep.IsHandcuffs then
|
||||
return true,wep
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
//
|
||||
// Override Movement
|
||||
hook.Add( "SetupMove", "Cuffs Move Penalty", function(ply, mv, cmd)
|
||||
local cuffed, cuffs = ply:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs)) then return end
|
||||
|
||||
mv:SetMaxClientSpeed( mv:GetMaxClientSpeed()*0.6 )
|
||||
|
||||
if cuffs:GetRopeLength()<=0 then return end // No forced movement
|
||||
if not IsValid(cuffs:GetKidnapper()) then return end // Nowhere to move to
|
||||
|
||||
local kidnapper = cuffs:GetKidnapper()
|
||||
if kidnapper==ply then return end
|
||||
|
||||
local TargetPoint = (kidnapper:IsPlayer() and kidnapper:GetShootPos()) or kidnapper:GetPos()
|
||||
local MoveDir = (TargetPoint - ply:GetPos()):GetNormal()
|
||||
local ShootPos = ply:GetShootPos() + (Vector(0,0, (ply:Crouching() and 0)))
|
||||
local Distance = cuffs:GetRopeLength()
|
||||
|
||||
local distFromTarget = ShootPos:Distance( TargetPoint )
|
||||
if distFromTarget<=(Distance+5) then return end
|
||||
if ply:InVehicle() then
|
||||
if SERVER and (distFromTarget>(Distance*3)) then
|
||||
ply:ExitVehicle()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local TargetPos = TargetPoint - (MoveDir*Distance)
|
||||
|
||||
local xDif = math.abs(ShootPos[1] - TargetPos[1])
|
||||
local yDif = math.abs(ShootPos[2] - TargetPos[2])
|
||||
local zDif = math.abs(ShootPos[3] - TargetPos[3])
|
||||
|
||||
local speedMult = 3+ ( (xDif + yDif)*0.5)^1.01
|
||||
local vertMult = math.max((math.Max(300-(xDif + yDif), -10)*0.08)^1.01 + (zDif/2),0)
|
||||
|
||||
if kidnapper:GetGroundEntity()==ply then vertMult = -vertMult end
|
||||
|
||||
local TargetVel = (TargetPos - ShootPos):GetNormal() * 10
|
||||
TargetVel[1] = TargetVel[1]*speedMult
|
||||
TargetVel[2] = TargetVel[2]*speedMult
|
||||
TargetVel[3] = TargetVel[3]*vertMult
|
||||
local dir = mv:GetVelocity()
|
||||
|
||||
local clamp = 50
|
||||
local vclamp = 20
|
||||
local accel = 200
|
||||
local vaccel = 30*(vertMult/50)
|
||||
|
||||
dir[1] = (dir[1]>TargetVel[1]-clamp or dir[1]<TargetVel[1]+clamp) and math.Approach(dir[1], TargetVel[1], accel) or dir[1]
|
||||
dir[2] = (dir[2]>TargetVel[2]-clamp or dir[2]<TargetVel[2]+clamp) and math.Approach(dir[2], TargetVel[2], accel) or dir[2]
|
||||
|
||||
if ShootPos[3]<TargetPos[3] then
|
||||
dir[3] = (dir[3]>TargetVel[3]-vclamp or dir[3]<TargetVel[3]+vclamp) and math.Approach(dir[3], TargetVel[3], vaccel) or dir[3]
|
||||
|
||||
if vertMult>0 then ply.Cuff_ForceJump=ply end
|
||||
end
|
||||
|
||||
mv:SetVelocity( dir )
|
||||
|
||||
if SERVER and mv:GetVelocity():Length()>=(mv:GetMaxClientSpeed()*10) and ply:IsOnGround() and CurTime()>(ply.Cuff_NextDragDamage or 0) then
|
||||
ply:SetHealth( ply:Health()-1 )
|
||||
if ply:Health()<=0 then ply:Kill() end
|
||||
|
||||
ply.Cuff_NextDragDamage = CurTime()+0.1
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Vehicles
|
||||
hook.Add( "CanPlayerEnterVehicle", "Cuffs PreventVehicle", function( ply )
|
||||
-- if ply:IsHandcuffed() then return false end
|
||||
end)
|
||||
|
||||
//
|
||||
// Internal Cuffs hooks
|
||||
hook.Add( "CuffsCanHandcuff", "Cuff ProtectAdmin", function( ply, target )
|
||||
if IsValid(target) and target:IsPlayer() and ProtectedJobs then
|
||||
for i=1,#ProtectedJobs do
|
||||
if ProtectedJobs[i] and _G[ ProtectedJobs[i] ] and target:Team()==_G[ ProtectedJobs[i] ] then return false end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if CLIENT then
|
||||
local CuffsTable = {}
|
||||
local function UpdateCuffsTable()
|
||||
CuffsTable = {}
|
||||
for _,v in pairs(ents.GetAll()) do
|
||||
if IsValid(v) and v.IsHandcuffs then table.insert( CuffsTable, v ) end
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// HUD
|
||||
local Col = {
|
||||
Text = Color(255,255,255), TextShadow=Color(0,0,0), Rope = Color(255,255,255),
|
||||
|
||||
BoxOutline = Color(0,0,0), BoxBackground = Color(255,255,255,20), BoxLeft = Color(255,0,0), BoxRight = Color(0,255,0),
|
||||
}
|
||||
local matGrad = Material( "gui/gradient" )
|
||||
local NextCuffsTableUpdate = 0
|
||||
hook.Add( "HUDPaint", "Cuffs CuffedInteractPrompt", function()
|
||||
local ply = LocalPlayer()
|
||||
if ply:IsHandcuffed() then return end
|
||||
|
||||
local w,h = (ScrW()/2), (ScrH()/2)
|
||||
local TextPos = h-40
|
||||
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if tr.Hit then
|
||||
if CurTime()>NextCuffsTableUpdate then
|
||||
UpdateCuffsTable()
|
||||
NextCuffsTableUpdate = CurTime()+5
|
||||
end
|
||||
|
||||
for _,v in pairs(CuffsTable) do
|
||||
if IsValid(v) and v:GetKidnapper()==ply and v:GetRopeLength()>0 then
|
||||
local str = string.format( "%s + %s to %s",
|
||||
(input.LookupBinding("+use") or "[use]"):upper(),
|
||||
(input.LookupBinding("+attack") or "[Primary Fire]"):upper(),
|
||||
(IsValid(tr.Entity) and tr.Entity:IsPlayer()) and "hand over captive" or "tie captive"
|
||||
)
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-30
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tr,cuff = GetTrace( ply )
|
||||
if not (tr and IsValid(cuff)) then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
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)+((cuff: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 )
|
||||
TextPos = TextPos-25
|
||||
|
||||
if IsValid(cuff:GetFriendBreaking()) then
|
||||
if cuff:GetFriendBreaking()==ply then
|
||||
draw.SimpleText( "Releasing player...", "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( "Releasing player...", "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
else
|
||||
local str = string.format( "%s to release", (input.LookupBinding("+use") or "[USE]"):upper() )
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
|
||||
if cuff:GetRopeLength()>0 then
|
||||
if IsValid(cuff:GetKidnapper()) then
|
||||
if cuff:GetKidnapper()==ply then
|
||||
local str = string.format( "%s to stop dragging", (input.LookupBinding("+reload") or "[Reload]"):upper() )
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
else
|
||||
local str = string.format( "%s to drag player", (input.LookupBinding("+reload") or "[Reload]"):upper() )
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
end
|
||||
|
||||
if cuff:GetCanBlind() then
|
||||
local str = string.format( "%s to %sblindfold", (input.LookupBinding("+attack2") or "[PRIMARY FIRE]"):upper(), cuff:GetIsBlind() and "remove " or "" )
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
|
||||
if cuff:GetCanGag() then
|
||||
local str = string.format( "%s to %sgag", (input.LookupBinding("+attack") or "[PRIMARY FIRE]"):upper(), cuff:GetIsGagged() and "un" or "" )
|
||||
draw.SimpleText( str, "HandcuffsText", w+1, TextPos+1, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( str, "HandcuffsText", w, TextPos, Col.Text, TEXT_ALIGN_CENTER )
|
||||
TextPos = TextPos-20
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Bind hooks
|
||||
hook.Add( "PlayerBindPress", "Cuffs CuffedInteract", function(ply, bind, pressed)
|
||||
if ply~=LocalPlayer() then return end
|
||||
|
||||
if bind:lower()=="+attack" and pressed then
|
||||
if ply:KeyDown( IN_USE ) then
|
||||
local isDragging = false
|
||||
for _,c in pairs(ents.FindByClass("weapon_handcuffed")) do
|
||||
if c.GetRopeLength and c.GetKidnapper and c:GetRopeLength()>0 and c:GetKidnapper()==ply then
|
||||
isDragging=true
|
||||
break
|
||||
end
|
||||
end
|
||||
if isDragging then
|
||||
net.Start("Cuffs_TiePlayers") net.SendToServer()
|
||||
return true
|
||||
end
|
||||
end
|
||||
local tr,cuffs = GetTrace( ply )
|
||||
if tr and cuffs:GetCanGag() then
|
||||
net.Start( "Cuffs_GagPlayer" )
|
||||
net.WriteEntity( tr.Entity )
|
||||
net.WriteBit( not cuffs:GetIsGagged() )
|
||||
net.SendToServer()
|
||||
return true
|
||||
end
|
||||
elseif bind:lower()=="+attack2" and pressed then
|
||||
local tr,cuffs = GetTrace( ply )
|
||||
if tr and cuffs:GetCanBlind() then
|
||||
net.Start( "Cuffs_BlindPlayer" )
|
||||
net.WriteEntity( tr.Entity )
|
||||
net.WriteBit( not cuffs:GetIsBlind() )
|
||||
net.SendToServer()
|
||||
return true
|
||||
end
|
||||
elseif bind:lower()=="+reload" and pressed then
|
||||
local tr,cuffs = GetTrace( ply )
|
||||
if tr and cuffs:GetRopeLength()>0 then
|
||||
net.Start( "Cuffs_DragPlayer" )
|
||||
net.WriteEntity( tr.Entity )
|
||||
net.WriteBit( LocalPlayer()~=cuffs:GetKidnapper() )
|
||||
net.SendToServer()
|
||||
return true
|
||||
end
|
||||
elseif bind:lower()=="+use" and pressed then
|
||||
local tr,cuffs = GetTrace( ply )
|
||||
if tr then
|
||||
net.Start( "Cuffs_FreePlayer" )
|
||||
net.WriteEntity( tr.Entity )
|
||||
net.SendToServer()
|
||||
return true
|
||||
else
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if IsValid(tr.Entity) and tr.Entity:GetNWBool("Cuffs_TieHook") then
|
||||
net.Start("Cuffs_UntiePlayers") net.SendToServer()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Render
|
||||
local DragBone = "ValveBiped.Bip01_R_Hand"
|
||||
local LeashBone = "ValveBiped.Bip01_Neck1"
|
||||
local LeashAltBone = "Neck"
|
||||
local LeashHolder = "ValveBiped.Bip01_R_Hand"
|
||||
local DefaultRope = Material("cable/rope")
|
||||
hook.Add( "PostDrawOpaqueRenderables", "Cuffs DragRope", function()
|
||||
local allCuffs = ents.FindByClass( "weapon_handcuffed" )
|
||||
for i=1,#allCuffs do
|
||||
local cuff = allCuffs[i]
|
||||
if not (IsValid(cuff) and IsValid(cuff.Owner) and cuff.GetRopeLength and cuff:GetRopeLength()>0 and cuff.GetKidnapper and IsValid(cuff:GetKidnapper())) then continue end
|
||||
|
||||
local kidnapper = cuff:GetKidnapper()
|
||||
local kidPos = (kidnapper:IsPlayer() and kidnapper:GetPos() + Vector(0,0,37)) or kidnapper:GetPos()
|
||||
|
||||
local pos = cuff.Owner:GetPos()
|
||||
if cuff:GetIsLeash() then
|
||||
local bone = cuff.Owner:LookupBone( LeashBone )
|
||||
if not bone then
|
||||
bone = cuff.Owner:LookupBone( LeashAltBone )
|
||||
end
|
||||
if bone then
|
||||
pos = cuff.Owner:GetBonePosition( bone )
|
||||
if (pos.x==0 and pos.y==0 and pos.z==0) then pos = cuff.Owner:GetPos() end
|
||||
end
|
||||
|
||||
if kidnapper~=LocalPlayer() or (hook.Call("ShouldDrawLocalPlayer", GAMEMODE, LocalPlayer())) then // Looks weird first-person
|
||||
local lBone = kidnapper:LookupBone(LeashHolder)
|
||||
if lBone then
|
||||
local newPos = kidnapper:GetBonePosition( lBone )
|
||||
if newPos and (newPos.x~=0 and newPos.y~=0 and newPos.z~=0) then
|
||||
kidPos = newPos
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local bone = cuff.Owner:LookupBone( DragBone )
|
||||
if bone then
|
||||
pos = cuff.Owner:GetBonePosition( bone )
|
||||
if (pos.x==0 and pos.y==0 and pos.z==0) then pos = cuff.Owner:GetPos() end
|
||||
end
|
||||
end
|
||||
-- print(bone)
|
||||
|
||||
if not cuff.RopeMat then cuff.RopeMat = DefaultRope end
|
||||
render.SetMaterial( cuff.RopeMat )
|
||||
render.DrawBeam( kidPos, pos, 0.7, 0, 5, Col.Rope )
|
||||
render.DrawBeam( pos, kidPos, -0.7, 0, 5, Col.Rope )
|
||||
end
|
||||
end)
|
||||
|
||||
local HeadBone = "ValveBiped.Bip01_Head1"
|
||||
local RenderPos = {
|
||||
Blind = {Vector(3.5,3,2.6), Vector(3.8,4.8,0), Vector(3.5,3,-2.8), Vector(2.4,-2,-3.8), Vector(1.5,-4.5,0), Vector(2.4,-2,3.8)},
|
||||
Gag = {Vector(1.0,4.2,2), Vector(1.0,5.5,-0.1), Vector(1.0,4.5,-2), Vector(0,0,-3.4), Vector(-0.8,-3,0), Vector(0,0,3.4)},
|
||||
}
|
||||
hook.Add( "PostPlayerDraw", "Cuffs DrawGag", function( ply )
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local cuffed, cuff = ply:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuff)) then return end
|
||||
|
||||
render.SetMaterial( DefaultRope )
|
||||
if cuff:GetIsBlind() then
|
||||
local pos,ang
|
||||
local bone = cuff.Owner:LookupBone( HeadBone )
|
||||
if bone then
|
||||
pos, ang = cuff.Owner:GetBonePosition( bone )
|
||||
end
|
||||
if pos and ang then
|
||||
local firstpos = pos + (ang:Forward()*RenderPos.Blind[1].x) + (ang:Right()*RenderPos.Blind[1].y) + (ang:Up()*RenderPos.Blind[1].z)
|
||||
local lastpos = firstpos
|
||||
for i=2,#RenderPos.Blind do
|
||||
local newPos = pos + (ang:Forward()*RenderPos.Blind[i].x) + (ang:Right()*RenderPos.Blind[i].y) + (ang:Up()*RenderPos.Blind[i].z)
|
||||
render.DrawBeam( newPos, lastpos, 1.5, 0, 1, Col.Rope )
|
||||
lastpos = newPos
|
||||
end
|
||||
render.DrawBeam( lastpos, firstpos, 1.5, 0, 1, Col.Rope )
|
||||
end
|
||||
end
|
||||
if cuff:GetIsGagged() then
|
||||
local pos,ang
|
||||
local bone = cuff.Owner:LookupBone( HeadBone )
|
||||
if bone then
|
||||
pos, ang = cuff.Owner:GetBonePosition( bone )
|
||||
end
|
||||
if pos and ang then
|
||||
local firstpos = pos + (ang:Forward()*RenderPos.Gag[1].x) + (ang:Right()*RenderPos.Gag[1].y) + (ang:Up()*RenderPos.Gag[1].z)
|
||||
local lastpos = firstpos
|
||||
for i=2,#RenderPos.Gag do
|
||||
local newPos = pos + (ang:Forward()*RenderPos.Gag[i].x) + (ang:Right()*RenderPos.Gag[i].y) + (ang:Up()*RenderPos.Gag[i].z)
|
||||
render.DrawBeam( newPos, lastpos, 1.5, 0, 1, Col.Rope )
|
||||
lastpos = newPos
|
||||
end
|
||||
render.DrawBeam( lastpos, firstpos, 1.5, 0, 1, Col.Rope )
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
306
garrysmod/addons/handcuffs/lua/autorun/sv_handcuffs.lua
Normal file
306
garrysmod/addons/handcuffs/lua/autorun/sv_handcuffs.lua
Normal file
@@ -0,0 +1,306 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- sv_handcuffs.lua SERVER --
|
||||
-- --
|
||||
-- Server-side handcuff stuff. --
|
||||
-------------------------------------
|
||||
|
||||
if CLIENT then return end
|
||||
|
||||
util.AddNetworkString( "Cuffs_GagPlayer" )
|
||||
util.AddNetworkString( "Cuffs_BlindPlayer" )
|
||||
util.AddNetworkString( "Cuffs_FreePlayer" )
|
||||
util.AddNetworkString( "Cuffs_DragPlayer" )
|
||||
|
||||
util.AddNetworkString( "Cuffs_TiePlayers" )
|
||||
util.AddNetworkString( "Cuffs_UntiePlayers" )
|
||||
|
||||
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
|
||||
|
||||
//
|
||||
// Standard hooks
|
||||
CreateConVar( "cuffs_restrictsuicide", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "CanPlayerSuicide", "Cuffs RestrictSuicide", function( ply )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictarrest") then return false end
|
||||
end)
|
||||
CreateConVar( "cuffs_restrictteams", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "PlayerCanJoinTeam", "Cuffs RestrictTeam", function( ply )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictteams") then return false end
|
||||
end)
|
||||
hook.Add( "PlayerCanSeePlayersChat", "Cuffs ChatGag", function( _,_,_, ply )
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local cuffed,wep = ply:IsHandcuffed()
|
||||
if cuffed and wep:GetIsGagged() then return false end
|
||||
end)
|
||||
hook.Add( "PlayerCanHearPlayersVoice", "Cuffs VoiceGag", function( _, ply )
|
||||
if not IsValid(ply) then return end
|
||||
|
||||
local cuffed,wep = ply:IsHandcuffed()
|
||||
if cuffed and wep:GetIsGagged() then return false end
|
||||
end)
|
||||
|
||||
//
|
||||
// DarkRP
|
||||
CreateConVar( "cuffs_restrictwarrant", 1, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE,FCVAR_REPLICATED} )
|
||||
hook.Add( "canRequestWarrant", "Cuffs PreventWarrant", function( crim, cop, reason ) if cvars.Bool("cuffs_restrictwarrant") and cop:IsHandcuffed() then return false,"You can issue warrants when cuffed!" end end)
|
||||
hook.Add( "canWanted", "Cuffs PreventWarrant", function( crim, cop, reason ) if cvars.Bool("cuffs_restrictwarrant") and cop:IsHandcuffed() then return false,"You can issue warrants when cuffed!" end end)
|
||||
|
||||
CreateConVar( "cuffs_autoarrest", 0, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
CreateConVar( "cuffs_restrictarrest", 0, {FCVAR_ARCHIVE,FCVAR_SERVER_CAN_EXECUTE} )
|
||||
hook.Add( "canArrest", "Cuffs RestrictArrest", function( cop, crim ) // DarkRP Arrest hook
|
||||
if IsValid(crim) and cvars.Bool("cuffs_restrictarrest") and not crim:IsHandcuffed() then return false,"You must handcuff a suspect to arrest them!" end
|
||||
end)
|
||||
hook.Add( "playerCanChangeTeam", "Cuffs RestrictTeam", function( ply, tm, force )
|
||||
if ply:IsHandcuffed() and cvars.Bool("cuffs_restrictteams") and not force then return false,"You can't change jobs when cuffed!" end
|
||||
end)
|
||||
hook.Add( "CanChangeRPName", "Cuffs RestrictName", function( ply )
|
||||
if ply:IsHandcuffed() then return false,"You can't change your name when cuffed!" end
|
||||
end)
|
||||
|
||||
//
|
||||
// Think
|
||||
local NextTieHookCleanup
|
||||
hook.Add( "Think", "Cuffs ForceJump CleanupTieHooks", function()
|
||||
for _,v in pairs(player.GetAll()) do
|
||||
if v.Cuff_ForceJump then
|
||||
if not v:OnGround() then return end
|
||||
|
||||
local tr = util.TraceLine( {start = v:GetPos(), endpos = v:GetPos()+Vector(0,0,20), filter = v} )
|
||||
if tr.Hit then return end
|
||||
|
||||
v:SetPos(v:GetPos()+Vector(0,0,5) )
|
||||
|
||||
v.Cuff_ForceJump = nil
|
||||
end
|
||||
end
|
||||
|
||||
if CurTime()>=(NextTieHookCleanup or 0) then
|
||||
for _,v in pairs(ents.GetAll()) do
|
||||
if v.IsHandcuffHook and v.TiedHandcuffs then
|
||||
for i=#v.TiedHandcuffs,0,-1 do
|
||||
if not IsValid(v.TiedHandcuffs[i]) then
|
||||
table.remove( v.TiedHandcuffs, i )
|
||||
end
|
||||
end
|
||||
if #v.TiedHandcuffs<=0 then
|
||||
v:Remove()
|
||||
continue
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Cuffed player interaction
|
||||
net.Receive( "Cuffs_GagPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetCanGag()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldGag = net.ReadBit()==1
|
||||
cuffs:SetIsGagged( shouldGag )
|
||||
hook.Call( shouldGag and "OnHandcuffGag" or "OnHandcuffUnGag", GAMEMODE, ply, target, cuffs )
|
||||
end)
|
||||
net.Receive( "Cuffs_BlindPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetCanBlind()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldBlind = net.ReadBit()==1
|
||||
cuffs:SetIsBlind( shouldBlind )
|
||||
hook.Call( shouldBlind and "OnHandcuffBlindfold" or "OnHandcuffUnBlindfold", GAMEMODE, ply, target, cuffs )
|
||||
end)
|
||||
net.Receive( "Cuffs_FreePlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs)) then return end
|
||||
if IsValid(cuffs:GetFriendBreaking()) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
cuffs:SetFriendBreaking( ply )
|
||||
end)
|
||||
net.Receive( "Cuffs_DragPlayer", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local target = net.ReadEntity()
|
||||
if (not IsValid(target)) or target==ply then return end
|
||||
|
||||
local cuffed, cuffs = target:IsHandcuffed()
|
||||
if not (cuffed and IsValid(cuffs) and cuffs:GetRopeLength()>0) then return end
|
||||
|
||||
local tr = GetTrace(ply)
|
||||
if not (tr and tr.Entity==target) then return end
|
||||
|
||||
local shouldDrag = net.ReadBit()==1
|
||||
if shouldDrag then
|
||||
if not (IsValid(cuffs:GetKidnapper())) then
|
||||
cuffs:SetKidnapper( ply )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, ply, target, cuffs )
|
||||
end
|
||||
else
|
||||
if ply==cuffs:GetKidnapper() then
|
||||
cuffs:SetKidnapper( nil )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, target, cuffs )
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local HookModel = Model("models/props_c17/TrapPropeller_Lever.mdl")
|
||||
net.Receive( "Cuffs_TiePlayers", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local DraggedCuffs = {}
|
||||
for _,c in pairs(ents.FindByClass("weapon_handcuffed")) do
|
||||
if c:GetRopeLength()>0 and c:GetKidnapper()==ply then
|
||||
table.insert( DraggedCuffs, c )
|
||||
end
|
||||
end
|
||||
if #DraggedCuffs<=0 then return end
|
||||
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if not tr.Hit then return end
|
||||
|
||||
if IsValid(tr.Entity) then // Pass to another player
|
||||
if tr.Entity:IsPlayer() then
|
||||
for i=1,#DraggedCuffs do
|
||||
if DraggedCuffs[i].Owner==tr.Entity then
|
||||
DraggedCuffs[i]:SetKidnapper(nil)
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
else
|
||||
DraggedCuffs[i]:SetKidnapper(tr.Entity)
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, tr.Entity, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
end
|
||||
end
|
||||
return
|
||||
elseif tr.Entity.IsHandcuffHook and tr.Entity.TiedHandcuffs then
|
||||
for i=1,#DraggedCuffs do
|
||||
DraggedCuffs[i]:SetKidnapper(tr.Entity)
|
||||
table.insert( tr.Entity.TiedHandcuffs, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffTied", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i], tr.Entity )
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local hk = ents.Create("prop_physics")
|
||||
hk:SetPos( tr.HitPos + tr.HitNormal )
|
||||
local ang = tr.HitNormal:Angle()
|
||||
ang:RotateAroundAxis( ang:Up(), -90 )
|
||||
hk:SetAngles( ang )
|
||||
hk:SetModel( HookModel )
|
||||
hk:Spawn()
|
||||
|
||||
-- hk:SetMoveType( MOVETYPE_NONE )
|
||||
if IsValid(tr.Entity) then
|
||||
hk:SetParent( tr.Entity )
|
||||
hk:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
else
|
||||
hk:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
hk:SetCollisionGroup( COLLISION_GROUP_WEAPON )
|
||||
|
||||
hk:SetNWBool("Cuffs_TieHook", true)
|
||||
hk.IsHandcuffHook = true
|
||||
hk.TiedHandcuffs = {}
|
||||
|
||||
for i=1,#DraggedCuffs do
|
||||
DraggedCuffs[i]:SetKidnapper( hk )
|
||||
table.insert( hk.TiedHandcuffs, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffStopDragging", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i] )
|
||||
hook.Call( "OnHandcuffTied", GAMEMODE, ply, DraggedCuffs[i].Owner, DraggedCuffs[i], hk )
|
||||
end
|
||||
end)
|
||||
|
||||
local function DoUntie( ply, ent )
|
||||
for i=1,#ent.TiedHandcuffs do
|
||||
if not IsValid(ent.TiedHandcuffs[i]) then continue end
|
||||
|
||||
ent.TiedHandcuffs[i]:SetKidnapper( ply )
|
||||
hook.Call( "OnHandcuffUnTied", GAMEMODE, ply, ent.TiedHandcuffs[i].Owner, ent.TiedHandcuffs[i], ent )
|
||||
hook.Call( "OnHandcuffStartDragging", GAMEMODE, ply, ent.TiedHandcuffs[i].Owner, ent.TiedHandcuffs[i] )
|
||||
end
|
||||
|
||||
ent:Remove()
|
||||
end
|
||||
net.Receive( "Cuffs_UntiePlayers", function(_,ply)
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
local tr = util.TraceLine( {start=ply:EyePos(), endpos=ply:EyePos()+(ply:GetAimVector()*100), filter=ply} )
|
||||
if IsValid(tr.Entity) and tr.Entity.IsHandcuffHook and tr.Entity.TiedHandcuffs then
|
||||
DoUntie( ply, tr.Entity )
|
||||
end
|
||||
end)
|
||||
hook.Add( "AllowPlayerPickup", "Cuffs UntieHook", function(ply,ent)
|
||||
if IsValid(ent) and ent.IsHandcuffHook and ent.TiedHandcuffs then
|
||||
if (not IsValid(ply)) or ply:IsHandcuffed() then return end
|
||||
|
||||
DoUntie( ply, ent )
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// GmodDayZ support
|
||||
// Created by and added with permission of Phoenix129 ( http://steamcommunity.com/profiles/76561198039440140/ )
|
||||
hook.Add("OnHandcuffed", "DayZCuffs RemoveInventoryItem", function(ply, cuffedply, handcuffs)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
ply:TakeCharItem( handcuffs.CuffType )
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("OnHandcuffBreak", "DayZCuffs GiveInventoryItemIfFriend", function(cuffedply, handcuffs, friend)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if IsValid(friend) and handcuffs.CuffType and handcuffs.CuffType~="" then
|
||||
friend:GiveItem(handcuffs.CuffType, 1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add( "CuffsCanHandcuff", "DayZCuffs SafezoneProtectCuffs", function( ply, target )
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if target.SafeZone or target.SafeZoneEdge or target.Loading or !target.Ready then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end)
|
||||
hook.Add("PlayerDisconnected", "DayZCuffs DieHandcuffs", function(ply)
|
||||
if engine.ActiveGamemode() == "dayz" then
|
||||
if ply:IsHandcuffed() then ply:Kill() end
|
||||
end
|
||||
end)
|
||||
467
garrysmod/addons/handcuffs/lua/weapons/weapon_cuff_base.lua
Normal file
467
garrysmod/addons/handcuffs/lua/weapons/weapon_cuff_base.lua
Normal file
@@ -0,0 +1,467 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- weapon_cuff_base.lua SHARED --
|
||||
-- --
|
||||
-- Base swep for handcuffs. --
|
||||
-------------------------------------
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.Base = "weapon_base"
|
||||
|
||||
SWEP.Category = "Handcuffs"
|
||||
SWEP.Author = "my_hat_stinks"
|
||||
SWEP.Instructions = ""
|
||||
|
||||
SWEP.Spawnable = false
|
||||
SWEP.AdminOnly = false
|
||||
SWEP.AdminSpawnable = false
|
||||
|
||||
SWEP.Slot = 3
|
||||
SWEP.PrintName = "UnnamedHandcuff"
|
||||
|
||||
SWEP.ViewModelFOV = 60
|
||||
SWEP.Weight = 5
|
||||
SWEP.AutoSwitchTo = false
|
||||
SWEP.AutoSwitchFrom = false
|
||||
|
||||
SWEP.WorldModel = "models/weapons/w_toolgun.mdl"
|
||||
SWEP.ViewModel = "models/weapons/c_bugbait.mdl"
|
||||
SWEP.UseHands = true
|
||||
|
||||
SWEP.Primary.Recoil = 1
|
||||
SWEP.Primary.Damage = 5
|
||||
SWEP.Primary.NumShots = 1
|
||||
SWEP.Primary.Cone = 0
|
||||
SWEP.Primary.Delay = 0.25
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = true
|
||||
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.Spawnable = false
|
||||
SWEP.AdminSpawnable = false
|
||||
SWEP.AdminOnly = false
|
||||
|
||||
SWEP.PrimaryAnim = ACT_VM_PRIMARYATTACK
|
||||
SWEP.ReloadAnim = ACT_VM_RELOAD
|
||||
SWEP.HoldType = "slam"
|
||||
|
||||
SWEP.Spawnable = false
|
||||
SWEP.AdminSpawnable = false
|
||||
SWEP.AdminOnly = false
|
||||
|
||||
//
|
||||
// Handcuff Vars
|
||||
SWEP.CuffTime = 1.0 // Seconds to handcuff
|
||||
SWEP.CuffSound = Sound( "buttons/lever7.wav" )
|
||||
|
||||
SWEP.CuffMaterial = "phoenix_storms/metalfloor_2-3"
|
||||
SWEP.CuffRope = "cable/cable2"
|
||||
|
||||
SWEP.CuffStrength = 1
|
||||
SWEP.CuffRegen = 1
|
||||
SWEP.RopeLength = 0
|
||||
|
||||
SWEP.CuffReusable = false // Can reuse (ie, not removed on use)
|
||||
SWEP.CuffRecharge = 30 // Time before re-use
|
||||
|
||||
SWEP.CuffBlindfold = false
|
||||
SWEP.CuffGag = false
|
||||
|
||||
SWEP.CuffStrengthVariance = 0 // Randomise strangth
|
||||
SWEP.CuffRegenVariance = 0 // Randomise regen
|
||||
|
||||
//
|
||||
// Network Vars
|
||||
function SWEP:SetupDataTables()
|
||||
self:NetworkVar( "Bool", 0, "IsCuffing" )
|
||||
self:NetworkVar( "Entity", 0, "Cuffing" )
|
||||
self:NetworkVar( "Float", 0, "CuffTime" )
|
||||
end
|
||||
|
||||
//
|
||||
// Standard SWEP functions
|
||||
function SWEP:PrimaryAttack()
|
||||
if self:GetIsCuffing() then return end
|
||||
|
||||
self:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
|
||||
self:SetNextSecondaryFire( CurTime() + self.Primary.Delay )
|
||||
|
||||
if CLIENT then return end
|
||||
if self:GetCuffTime()>CurTime() then return end // On cooldown
|
||||
|
||||
local tr = self:TargetTrace()
|
||||
if not tr then return end
|
||||
|
||||
self:SetCuffTime( CurTime() + self.CuffTime )
|
||||
self:SetIsCuffing( true )
|
||||
self:SetCuffing( tr.Entity )
|
||||
|
||||
sound.Play( self.CuffSound, self.Owner:GetShootPos(), 75, 100, 1 )
|
||||
end
|
||||
function SWEP:SecondaryAttack()
|
||||
end
|
||||
function SWEP:Reload()
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType( self.HoldType )
|
||||
|
||||
if engine.ActiveGamemode()=="dayz" then self.CuffReusable = false end
|
||||
end
|
||||
function SWEP:Holster()
|
||||
if CLIENT and IsValid(self.Owner) and self.Owner==LocalPlayer() then
|
||||
local vm = self.Owner:GetViewModel()
|
||||
if not IsValid(vm) then return end
|
||||
|
||||
vm:SetMaterial( "" )
|
||||
end
|
||||
if IsValid(self.cmdl_RightCuff) then self.cmdl_RightCuff:Remove() end
|
||||
if IsValid(self.cmdl_LeftCuff) then self.cmdl_LeftCuff:Remove() end
|
||||
|
||||
return true
|
||||
end
|
||||
SWEP.OnRemove = SWEP.Holster
|
||||
|
||||
//
|
||||
// Handcuff
|
||||
function SWEP:DoHandcuff( target )
|
||||
if not (target and IsValid(target)) then return end
|
||||
if target:IsHandcuffed() then return end
|
||||
if not IsValid(self.Owner) then return end
|
||||
|
||||
local cuff = target:Give( "weapon_handcuffed" )
|
||||
cuff:SetCuffStrength( self.CuffStrength + (math.Rand(-self.CuffStrengthVariance,self.CuffStrengthVariance)) )
|
||||
cuff:SetCuffRegen( self.CuffRegen + (math.Rand(-self.CuffRegenVariance,self.CuffRegenVariance)) )
|
||||
|
||||
cuff:SetCuffMaterial( self.CuffMaterial )
|
||||
cuff:SetRopeMaterial( self.CuffRope )
|
||||
|
||||
cuff:SetKidnapper( self.Owner )
|
||||
cuff:SetRopeLength( self.RopeLength )
|
||||
|
||||
cuff:SetCanBlind( self.CuffBlindfold )
|
||||
cuff:SetCanGag( self.CuffGag )
|
||||
|
||||
cuff.CuffType = self:GetClass() or ""
|
||||
|
||||
if self.IsLeash then
|
||||
cuff:SetIsLeash( true )
|
||||
timer.Simple( 0, function()
|
||||
if IsValid(cuff) then
|
||||
cuff:SetHoldType( "normal" )
|
||||
cuff.HoldType = "normal"
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
PrintMessage( HUD_PRINTCONSOLE, "[Cuffs] "..tostring(self.Owner:Nick()).." has handcuffed "..tostring(target:Nick()).." with "..tostring(self.PrintName) )
|
||||
hook.Call( "OnHandcuffed", GAMEMODE, self.Owner, target, cuff )
|
||||
|
||||
if self.Owner.isCP and target.arrest and self.Owner:isCP() and cvars.Bool("cuffs_autoarrest") then
|
||||
target:arrest( nil, self.Owner)
|
||||
end
|
||||
|
||||
if not self.CuffReusable then
|
||||
if IsValid(self.Owner) then self.Owner:ConCommand( "lastinv" ) end
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// Think
|
||||
function SWEP:Think()
|
||||
if SERVER then
|
||||
if self:GetIsCuffing() then
|
||||
local tr = self:TargetTrace()
|
||||
if (not tr) or tr.Entity~=self:GetCuffing() then
|
||||
self:SetIsCuffing(false)
|
||||
self:SetCuffTime( 0 )
|
||||
return
|
||||
end
|
||||
|
||||
if CurTime()>self:GetCuffTime() then
|
||||
self:SetIsCuffing( false )
|
||||
self:SetCuffTime( CurTime() + self.CuffRecharge )
|
||||
self:DoHandcuff( self:GetCuffing() )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// Get Target
|
||||
function SWEP:TargetTrace()
|
||||
if not IsValid(self.Owner) then return end
|
||||
|
||||
local tr = util.TraceLine( {start=self.Owner:GetShootPos(), endpos=(self.Owner:GetShootPos() + (self.Owner:GetAimVector()*50)), filter={self, self.Owner}} )
|
||||
if IsValid(tr.Entity) and tr.Entity:IsPlayer() and tr.Entity~=self.Owner and not tr.Entity:IsHandcuffed() then
|
||||
if hook.Run( "CuffsCanHandcuff", self.Owner, tr.Entity )==false then return end
|
||||
return tr
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// HUD
|
||||
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),
|
||||
}
|
||||
local matGrad = Material( "gui/gradient" )
|
||||
function SWEP:DrawHUD()
|
||||
if not self:GetIsCuffing() then
|
||||
if self:GetCuffTime()<=CurTime() then return end
|
||||
|
||||
local w,h = (ScrW()/2), (ScrH()/2)
|
||||
|
||||
surface.SetDrawColor( Col.BoxOutline )
|
||||
surface.DrawOutlinedRect( w-101, h+54, 202, 22 )
|
||||
surface.SetDrawColor( Col.BoxBackground )
|
||||
surface.DrawRect( w-100, h+55, 200, 20 )
|
||||
|
||||
local CuffingPercent = math.Clamp( ((self:GetCuffTime()-CurTime())/self.CuffRecharge), 0, 1 )
|
||||
render.SetScissorRect( w-100, h+55, (w-100)+(CuffingPercent*200), h+75, true )
|
||||
surface.SetDrawColor( Col.BoxRight )
|
||||
surface.DrawRect( w-100,h+55, 200,20 )
|
||||
|
||||
surface.SetMaterial( matGrad )
|
||||
surface.SetDrawColor( Col.BoxLeft )
|
||||
surface.DrawTexturedRect( w-100,h+55, 200,20 )
|
||||
render.SetScissorRect( 0,0,0,0, false )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local w,h = (ScrW()/2), (ScrH()/2)
|
||||
|
||||
draw.SimpleText( "Restraining target...", "HandcuffsText", w+1, h+31, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( "Restraining target...", "HandcuffsText", w, h+30, Col.Text, TEXT_ALIGN_CENTER )
|
||||
|
||||
surface.SetDrawColor( Col.BoxOutline )
|
||||
surface.DrawOutlinedRect( w-101, h+54, 202, 22 )
|
||||
surface.SetDrawColor( Col.BoxBackground )
|
||||
surface.DrawRect( w-100, h+55, 200, 20 )
|
||||
|
||||
local CuffingPercent = math.Clamp( 1-((self:GetCuffTime()-CurTime())/self.CuffTime), 0, 1 )
|
||||
|
||||
render.SetScissorRect( w-100, h+55, (w-100)+(CuffingPercent*200), h+75, true )
|
||||
surface.SetDrawColor( Col.BoxRight )
|
||||
surface.DrawRect( w-100,h+55, 200,20 )
|
||||
|
||||
surface.SetMaterial( matGrad )
|
||||
surface.SetDrawColor( Col.BoxLeft )
|
||||
surface.DrawTexturedRect( w-100,h+55, 200,20 )
|
||||
render.SetScissorRect( 0,0,0,0, false )
|
||||
end
|
||||
|
||||
//
|
||||
// Rendering
|
||||
local renderpos = {
|
||||
left = {pos=Vector(0,0,0), vel=Vector(0,0,0), gravity=1, ang=Angle(0,30,90)},
|
||||
right = {bone = "ValveBiped.Bip01_R_Hand", pos=Vector(3.2,2.1,0.4), ang=Angle(-2,0,80), scale = Vector(0.045,0.045,0.03)},
|
||||
rope = {l = Vector(0,0,2.0), r = Vector(2.3,-1.9,2.7)},
|
||||
}
|
||||
local CuffMdl = "models/hunter/tubes/tube2x2x1.mdl"
|
||||
local RopeCol = Color(255,255,255)
|
||||
function SWEP:ViewModelDrawn( vm )
|
||||
if not IsValid(vm) then return end
|
||||
|
||||
vm:SetMaterial( "engine/occlusionproxy" )
|
||||
|
||||
if not IsValid(self.cmdl_LeftCuff) then
|
||||
self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
self.cmdl_LeftCuff:SetNoDraw( true )
|
||||
self.cmdl_LeftCuff:SetParent( vm )
|
||||
|
||||
renderpos.left.pos = self.Owner:GetPos()
|
||||
end
|
||||
if not IsValid(self.cmdl_RightCuff) then
|
||||
self.cmdl_RightCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
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 (rpos and rang) then return end
|
||||
|
||||
// Right
|
||||
local fixed_rpos = rpos + (rang:Forward()*renderpos.right.pos.x) + (rang:Right()*renderpos.right.pos.y) + (rang:Up()*renderpos.right.pos.z)
|
||||
self.cmdl_RightCuff:SetPos( fixed_rpos )
|
||||
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.CuffMaterial )
|
||||
self.cmdl_RightCuff:DrawModel()
|
||||
|
||||
// Left
|
||||
if CurTime()>(renderpos.left.NextThink or 0) then
|
||||
local dist = renderpos.left.pos:Distance( fixed_rpos )
|
||||
if dist>100 then
|
||||
renderpos.left.pos = fixed_rpos
|
||||
renderpos.left.vel = Vector(0,0,0)
|
||||
elseif dist > 10 then
|
||||
local target = (fixed_rpos - renderpos.left.pos)*0.3
|
||||
renderpos.left.vel.x = math.Approach( renderpos.left.vel.x, target.x, 1 )
|
||||
renderpos.left.vel.y = math.Approach( renderpos.left.vel.y, target.y, 1 )
|
||||
renderpos.left.vel.z = math.Approach( renderpos.left.vel.z, target.z, 3 )
|
||||
end
|
||||
|
||||
renderpos.left.vel.x = math.Approach( renderpos.left.vel.x, 0, 0.5 )
|
||||
renderpos.left.vel.y = math.Approach( renderpos.left.vel.y, 0, 0.5 )
|
||||
renderpos.left.vel.z = math.Approach( renderpos.left.vel.z, 0, 0.5 )
|
||||
-- if renderpos.left.vel:Length()>10 then renderpos.left.vel:Mul(0.1) end
|
||||
|
||||
local targetZ = ((fixed_rpos.z - 10) - renderpos.left.pos.z) * renderpos.left.gravity
|
||||
renderpos.left.vel.z = math.Approach( renderpos.left.vel.z, targetZ, 3 )
|
||||
|
||||
renderpos.left.pos:Add( renderpos.left.vel )
|
||||
|
||||
-- renderpos.left.NextThink = CurTime()+0.01
|
||||
end
|
||||
|
||||
self.cmdl_LeftCuff:SetPos( renderpos.left.pos )
|
||||
self.cmdl_LeftCuff:SetAngles( renderpos.left.ang )
|
||||
|
||||
-- self.cmdl_LeftCuff:SetAngles( rang )
|
||||
local matrix = Matrix()
|
||||
matrix:Scale( renderpos.right.scale )
|
||||
self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix )
|
||||
|
||||
self.cmdl_LeftCuff:SetMaterial( self.CuffMaterial )
|
||||
self.cmdl_LeftCuff:DrawModel()
|
||||
|
||||
// Rope
|
||||
if not self.RopeMat then self.RopeMat = Material(self.CuffRope) end
|
||||
|
||||
render.SetMaterial( self.RopeMat )
|
||||
render.DrawBeam( renderpos.left.pos + renderpos.rope.l,
|
||||
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
|
||||
|
||||
SWEP.wrender = {
|
||||
left = {pos=Vector(0,0,0), vel=Vector(0,0,0), gravity=1, ang=Angle(0,30,90)},
|
||||
right = {bone = "ValveBiped.Bip01_R_Hand", pos=Vector(2.95,2.5,-0.2), ang=Angle(30,0,90), scale = Vector(0.044,0.044,0.044)},
|
||||
rope = {l = Vector(0,0,2), r = Vector(3,-1.65,1)},
|
||||
}
|
||||
function SWEP:DrawWorldModel()
|
||||
if not IsValid(self.Owner) then return end
|
||||
local wrender = self.wrender
|
||||
|
||||
if not IsValid(self.cmdl_LeftCuff) then
|
||||
self.cmdl_LeftCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
self.cmdl_LeftCuff:SetNoDraw( true )
|
||||
end
|
||||
if not IsValid(self.cmdl_RightCuff) then
|
||||
self.cmdl_RightCuff = ClientsideModel( CuffMdl, RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
self.cmdl_RightCuff:SetNoDraw( true )
|
||||
end
|
||||
|
||||
local rpos, rang = self:GetBonePos( wrender.right.bone, self.Owner )
|
||||
if not (rpos and rang) then return end
|
||||
|
||||
// Right
|
||||
local fixed_rpos = rpos + (rang:Forward()*wrender.right.pos.x) + (rang:Right()*wrender.right.pos.y) + (rang:Up()*wrender.right.pos.z)
|
||||
self.cmdl_RightCuff:SetPos( fixed_rpos )
|
||||
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.CuffMaterial )
|
||||
self.cmdl_RightCuff:DrawModel()
|
||||
|
||||
// Left
|
||||
if CurTime()>(wrender.left.NextThink or 0) then
|
||||
local dist = wrender.left.pos:Distance( fixed_rpos )
|
||||
if dist>100 then
|
||||
wrender.left.pos = fixed_rpos
|
||||
wrender.left.vel = Vector(0,0,0)
|
||||
elseif dist > 10 then
|
||||
local target = (fixed_rpos - wrender.left.pos)*0.3
|
||||
wrender.left.vel.x = math.Approach( wrender.left.vel.x, target.x, 1 )
|
||||
wrender.left.vel.y = math.Approach( wrender.left.vel.y, target.y, 1 )
|
||||
wrender.left.vel.z = math.Approach( wrender.left.vel.z, target.z, 3 )
|
||||
end
|
||||
|
||||
wrender.left.vel.x = math.Approach( wrender.left.vel.x, 0, 0.5 )
|
||||
wrender.left.vel.y = math.Approach( wrender.left.vel.y, 0, 0.5 )
|
||||
wrender.left.vel.z = math.Approach( wrender.left.vel.z, 0, 0.5 )
|
||||
-- if wrender.left.vel:Length()>10 then wrender.left.vel:Mul(0.1) end
|
||||
|
||||
local targetZ = ((fixed_rpos.z - 10) - wrender.left.pos.z) * wrender.left.gravity
|
||||
wrender.left.vel.z = math.Approach( wrender.left.vel.z, targetZ, 3 )
|
||||
|
||||
wrender.left.pos:Add( wrender.left.vel )
|
||||
|
||||
-- wrender.left.NextThink = CurTime()+0
|
||||
end
|
||||
|
||||
self.cmdl_LeftCuff:SetPos( wrender.left.pos )
|
||||
self.cmdl_LeftCuff:SetAngles( wrender.left.ang )
|
||||
|
||||
local matrix = Matrix()
|
||||
matrix:Scale( wrender.right.scale )
|
||||
self.cmdl_LeftCuff:EnableMatrix( "RenderMultiply", matrix )
|
||||
|
||||
self.cmdl_LeftCuff:SetMaterial( self.CuffMaterial )
|
||||
self.cmdl_LeftCuff:DrawModel()
|
||||
|
||||
// Rope
|
||||
if not self.RopeMat then self.RopeMat = Material(self.CuffRope) end
|
||||
|
||||
render.SetMaterial( self.RopeMat )
|
||||
render.DrawBeam( wrender.left.pos + wrender.rope.l,
|
||||
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
|
||||
45
garrysmod/addons/handcuffs/lua/weapons/weapon_cuff_rope.lua
Normal file
45
garrysmod/addons/handcuffs/lua/weapons/weapon_cuff_rope.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- weapon_cuff_standard.lua SHARED --
|
||||
-- --
|
||||
-- Rope handcuffs. --
|
||||
-------------------------------------
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.Base = "weapon_cuff_base"
|
||||
|
||||
SWEP.Category = "[RP] Система полиции"
|
||||
SWEP.Author = "my_hat_stinks"
|
||||
SWEP.Instructions = "A weak restraint."
|
||||
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminOnly = false
|
||||
SWEP.AdminSpawnable = false
|
||||
|
||||
SWEP.Slot = 3
|
||||
SWEP.PrintName = "Наручники"
|
||||
|
||||
//
|
||||
// Handcuff Vars
|
||||
SWEP.CuffTime = 1.0 // Seconds to handcuff
|
||||
SWEP.CuffSound = Sound( "buttons/lever7.wav" )
|
||||
|
||||
SWEP.CuffMaterial = "phoenix_storms/gear"
|
||||
SWEP.CuffRope = "cable/cable2"
|
||||
SWEP.CuffStrength = 1.4
|
||||
SWEP.CuffRegen = 1.4
|
||||
SWEP.RopeLength = 0
|
||||
SWEP.CuffReusable = false
|
||||
|
||||
SWEP.CuffBlindfold = true
|
||||
SWEP.CuffGag = true
|
||||
|
||||
SWEP.CuffStrengthVariance = 0.1 // Randomise strangth
|
||||
SWEP.CuffRegenVariance = 0.1 // Randomise regen
|
||||
601
garrysmod/addons/handcuffs/lua/weapons/weapon_handcuffed.lua
Normal file
601
garrysmod/addons/handcuffs/lua/weapons/weapon_handcuffed.lua
Normal file
@@ -0,0 +1,601 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- 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
|
||||
77
garrysmod/addons/handcuffs/lua/weapons/weapon_leash_base.lua
Normal file
77
garrysmod/addons/handcuffs/lua/weapons/weapon_leash_base.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- weapon_cuff_base.lua SHARED --
|
||||
-- --
|
||||
-- Base swep for handcuffs. --
|
||||
-------------------------------------
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.Base = "weapon_cuff_base"
|
||||
|
||||
SWEP.Category = "Handcuffs"
|
||||
SWEP.Author = "my_hat_stinks"
|
||||
SWEP.Instructions = ""
|
||||
|
||||
SWEP.Slot = 3
|
||||
SWEP.PrintName = "Unnamed"
|
||||
|
||||
SWEP.IsLeash = true
|
||||
|
||||
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),
|
||||
}
|
||||
local matGrad = Material( "gui/gradient" )
|
||||
function SWEP:DrawHUD()
|
||||
if not self:GetIsCuffing() then
|
||||
if self:GetCuffTime()<=CurTime() then return end
|
||||
|
||||
local w,h = (ScrW()/2), (ScrH()/2)
|
||||
|
||||
surface.SetDrawColor( Col.BoxOutline )
|
||||
surface.DrawOutlinedRect( w-101, h+54, 202, 22 )
|
||||
surface.SetDrawColor( Col.BoxBackground )
|
||||
surface.DrawRect( w-100, h+55, 200, 20 )
|
||||
|
||||
local CuffingPercent = math.Clamp( ((self:GetCuffTime()-CurTime())/self.CuffRecharge), 0, 1 )
|
||||
render.SetScissorRect( w-100, h+55, (w-100)+(CuffingPercent*200), h+75, true )
|
||||
surface.SetDrawColor( Col.BoxRight )
|
||||
surface.DrawRect( w-100,h+55, 200,20 )
|
||||
|
||||
surface.SetMaterial( matGrad )
|
||||
surface.SetDrawColor( Col.BoxLeft )
|
||||
surface.DrawTexturedRect( w-100,h+55, 200,20 )
|
||||
render.SetScissorRect( 0,0,0,0, false )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local w,h = (ScrW()/2), (ScrH()/2)
|
||||
|
||||
draw.SimpleText( "Leashing target...", "HandcuffsText", w+1, h+31, Col.TextShadow, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( "Leashing target...", "HandcuffsText", w, h+30, Col.Text, TEXT_ALIGN_CENTER )
|
||||
|
||||
surface.SetDrawColor( Col.BoxOutline )
|
||||
surface.DrawOutlinedRect( w-101, h+54, 202, 22 )
|
||||
surface.SetDrawColor( Col.BoxBackground )
|
||||
surface.DrawRect( w-100, h+55, 200, 20 )
|
||||
|
||||
local CuffingPercent = math.Clamp( 1-((self:GetCuffTime()-CurTime())/self.CuffTime), 0, 1 )
|
||||
|
||||
render.SetScissorRect( w-100, h+55, (w-100)+(CuffingPercent*200), h+75, true )
|
||||
surface.SetDrawColor( Col.BoxRight )
|
||||
surface.DrawRect( w-100,h+55, 200,20 )
|
||||
|
||||
surface.SetMaterial( matGrad )
|
||||
surface.SetDrawColor( Col.BoxLeft )
|
||||
surface.DrawTexturedRect( w-100,h+55, 200,20 )
|
||||
render.SetScissorRect( 0,0,0,0, false )
|
||||
end
|
||||
45
garrysmod/addons/handcuffs/lua/weapons/weapon_leash_rope.lua
Normal file
45
garrysmod/addons/handcuffs/lua/weapons/weapon_leash_rope.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
-----------------------------------------------------
|
||||
-------------------------------------
|
||||
---------------- Cuffs --------------
|
||||
-------------------------------------
|
||||
-- Copyright (c) 2015 Nathan Healy --
|
||||
-------- All rights reserved --------
|
||||
-------------------------------------
|
||||
-- weapon_cuff_standard.lua SHARED --
|
||||
-- --
|
||||
-- Rope handcuffs. --
|
||||
-------------------------------------
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.Base = "weapon_leash_base"
|
||||
|
||||
SWEP.Category = "Handcuffs"
|
||||
SWEP.Author = "my_hat_stinks"
|
||||
SWEP.Instructions = "A weak leash."
|
||||
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminOnly = false
|
||||
SWEP.AdminSpawnable = false
|
||||
|
||||
SWEP.Slot = 3
|
||||
SWEP.PrintName = "Rope Leash"
|
||||
|
||||
//
|
||||
// Handcuff Vars
|
||||
SWEP.CuffTime = 0.8 // Seconds to handcuff
|
||||
SWEP.CuffSound = Sound( "buttons/lever7.wav" )
|
||||
|
||||
SWEP.CuffMaterial = "models/props_foliage/tree_deciduous_01a_trunk"
|
||||
SWEP.CuffRope = "cable/rope"
|
||||
SWEP.CuffStrength = 0.85
|
||||
SWEP.CuffRegen = 0.8
|
||||
SWEP.RopeLength = 100
|
||||
SWEP.CuffReusable = false
|
||||
|
||||
SWEP.CuffBlindfold = false
|
||||
SWEP.CuffGag = false
|
||||
|
||||
SWEP.CuffStrengthVariance = 0.1 // Randomise strangth
|
||||
SWEP.CuffRegenVariance = 0.2 // Randomise regen
|
||||
Reference in New Issue
Block a user