Simple Script: Grabbing

Good afternoon, Facepunch!

I have been wondering if someone were up to the task of coding a grab-function of sorts.

I would like an Oblivion/Fallout style grab where it hangs from the point you grab it at.

It must be a script, not a weapon. I am looking for an auxilliary gravity gun, one that can throw (Small) objects a small ways.

Also, if it is feasible, I would appreciate it if there were a concommand to enable/disable weapon hiding/drawing when picking up objects as well as a concommand to enable/disable throwing objects.

-=EXAMPLE =-
I have a SWEP out. This SWEP doesn’t have a pick up props code. Then, I press a bind to a command which is, let’s say, “grabprop.” Then, a prop I was looking at is now hanging from the point I looked at just like in Oblivion/Fallout.

Thank you in advance.

Your’s truly,
Xavier Studios

Wizzy has gotta see this.

Well, it’s basically just spawning some help entity, then ‘weld’ the target entity to it and no-collide them etc.

[lua]

---- Carry weapon SWEP
if SERVER then
AddCSLuaFile(“shared.lua”)
end

SWEP.HoldType = “pistol”

if CLIENT then
SWEP.PrintName = “Magneto-stick”
SWEP.Instructions = “Pick things up with this.”
SWEP.Slot = 4
SWEP.SlotPos = 1

–SWEP.ViewModelFOV = 54
end

SWEP.Base = “weapon_tttbase”
SWEP.Spawnable = true
SWEP.AdminSpawnable = true
SWEP.AutoSpawnable = false
SWEP.ViewModel = “models/weapons/v_stunbaton.mdl”
SWEP.WorldModel = “models/weapons/w_stunbaton.mdl”
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.DrawCrosshair = false
SWEP.ViewModelFlip = false
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = “none”
SWEP.Primary.Delay = 0.1

SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = true
SWEP.Secondary.Ammo = “none”
SWEP.Secondary.Delay = 0.1

SWEP.Kind = WEAPON_CARRY

SWEP.AllowDelete = false
SWEP.AllowDrop = false

SWEP.NoSights = true

SWEP.EntHolding = nil
SWEP.CarryHack = nil
SWEP.Constr = nil
SWEP.PrevOwner = nil

local allow_rag = CreateConVar(“ttt_ragdoll_carrying”, “1”)
local rag_force = CreateConVar(“ttt_ragdoll_carrying_force”, “8000”)

– Allowing weapon pickups can allow players to cause a crash in the physics
– system (ie. not fixable). Tuning the range seems to make this more
– difficult. Not sure why. It’s that kind of crash.
local allow_wep = CreateConVar(“ttt_weapon_carrying”, “1”)
local wep_range = CreateConVar(“ttt_weapon_carrying_range”, “50”)

– not customizable via convars as some objects rely on not being carryable for
– gameplay purposes
CARRY_WEIGHT_LIMIT = 45

function SWEP:reset()
– debug
–print(“called reset with carryhack/constr/entholding:”, self.CarryHack, self.Constr, self.EntHolding)

if ValidEntity(self.CarryHack) then
self.CarryHack:Remove()
end

if ValidEntity(self.Constr) then
self.Constr:Remove()
end

if ValidEntity(self.EntHolding) then
if not IsValid(self.PrevOwner) then
–print(“resetting entholding owner to nil”)
self.EntHolding:SetOwner(nil)
else
–print(“resetting entholding owner to previous”)
self.EntHolding:SetOwner(self.PrevOwner)
end

  local phys = self.EntHolding:GetPhysicsObject()
  if ValidEntity(phys) then
     --print("clearing physobj flags")
     phys:ClearGameFlag(FVPHYSICS_PLAYER_HELD)
     phys:EnableCollisions(true)
  end

end

self.EntHolding = nil
self.CarryHack = nil
self.Constr = nil
end

function SWEP:CheckValidity()

if not ValidEntity(self.EntHolding) or not ValidEntity(self.CarryHack) or not ValidEntity(self.Constr) then

  -- if one of them is not valid but another is non-nil...
  if (self.EntHolding or self.CarryHack or self.Constr) then
     --print("checkvalidity found badness, resetting...")
     self:reset()
  end

  return false

else
return true
end
end

local ent_diff = Vector()
local ent_diff_time = CurTime()
function SWEP:Think()
if SERVER then
if not self:CheckValidity() then return end

  -- If we are too far from our object, force a drop. To avoid doing this
  -- vector math extremely often (esp. when everyone is carrying something)
  -- even though the occurrence is very rare, limited to once per
  -- second. This should be plenty to catch the rare glitcher.
  if CurTime() > ent_diff_time then
     ent_diff = self:GetPos() - self.EntHolding:GetPos()
     if ent_diff:Dot(ent_diff) > 20000 then
        self:reset()
        return
     end
     
     ent_diff_time = CurTime() + 1
  end

  self.CarryHack:SetPos(self.Owner:EyePos() + self.Owner:GetAimVector() * 70)
  self.CarryHack:SetAngles(self.Owner:GetAngles())

  self.EntHolding:PhysWake()

end
end

function SWEP:PrimaryAttack()
self:DoAttack(false)
end

function SWEP:SecondaryAttack()
self:DoAttack(true)
end

function SWEP:MoveObject(phys, pdir, maxforce, is_ragdoll)
if not ValidEntity(phys) then return end
local speed = phys:GetVelocity():Length()

– remap speed from 0 -> 125 to force 1 -> 4000
local force = maxforce + (1 - maxforce) * (speed / 125)

if is_ragdoll then
force = force * 4
end

pdir = pdir * force

local mass = phys:GetMass()
– scale more for light objects
if mass < 50 then
pdir = pdir * (mass + 0.5) * (1 / 50)
end

phys:ApplyForceCenter(pdir)
end

function SWEP:GetRange(target)
if IsValid(target) and target:IsWeapon() and allow_wep:GetBool() then
return wep_range:GetFloat()
else
return 100
end
end

function SWEP:AllowPickup(target)
local phys = target:GetPhysicsObject()
local ply = self:GetOwner()

return (IsValid(phys) and IsValid(ply) and
phys:GetMass() < CARRY_WEIGHT_LIMIT and
ply:GetGroundEntity() != target and
(target:GetClass() != “prop_ragdoll” or allow_rag:GetBool()) and
((not target:IsWeapon()) or allow_wep:GetBool()))
end

function SWEP:DoAttack(pickup)
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )

if ValidEntity(self.EntHolding) then
–print(“attacking with held item; dropping”)
self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER )
self:Drop()
self.Weapon:SetNextSecondaryFire(CurTime() + 0.3)
return
end

local ply = self.Owner

local trace = ply:GetEyeTrace()
if ValidEntity(trace.Entity) then
local ent = trace.Entity
local phys = trace.Entity:GetPhysicsObject()

  if not ValidEntity(phys) or not phys:IsMoveable() or phys:HasGameFlag(FVPHYSICS_PLAYER_HELD) then
     return
  end

  -- if we let the client mess with physics, desync ensues
  if CLIENT then return end

  if pickup then
     --print("attempting pickup")
     if (ply:EyePos() - trace.HitPos):Length() &lt; self:GetRange(ent) then
        --print("target is in range")

        if self:AllowPickup(ent) then
           self:Pickup()
           self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER )
           
           -- make the refire slower to avoid immediately dropping
           self.Weapon:SetNextSecondaryFire(CurTime() + 0.4)
           return
        else
           local is_ragdoll = trace.Entity:GetClass() == "prop_ragdoll"
           
           -- pull heavy stuff
           local ent = trace.Entity
           local phys = ent:GetPhysicsObject()
           local pdir = trace.Normal * -1

           if is_ragdoll then

              if ValidEntity(phys) then
                 self:MoveObject(phys, pdir, 3000, is_ragdoll)   
              end

              phys = ent:GetPhysicsObjectNum(trace.PhysicsBone)

              -- increase refire to make rags easier to drag
              self.Weapon:SetNextSecondaryFire(CurTime() + 0.04)
           end

           if ValidEntity(phys) then
              self:MoveObject(phys, pdir, 6000, is_ragdoll)
              return
           end
        end
     end
  else
     if (ply:EyePos() - trace.HitPos):Length() &lt; 125 then
        local phys = trace.Entity:GetPhysicsObject()
        if ValidEntity(phys) then
           if ValidEntity(phys) then
              local pdir = trace.Normal
              self:MoveObject(phys, pdir, 6000, (trace.Entity:GetClass() == "prop_ragdoll"))

              self.Weapon:SetNextPrimaryFire(CurTime() + 0.03)
              return
           end
        end
        return
     end
  end

end
end

– Perform a pickup
function SWEP:Pickup()
if CLIENT or ValidEntity(self.EntHolding) then return end

local ply = self.Owner
local trace = ply:GetEyeTrace()
local ent = trace.Entity
self.EntHolding = ent
local entphys = ent:GetPhysicsObject()

–print(“picking up”, ent)

if ValidEntity(ent) and ValidEntity(entphys) then

  --print("creating carry hack ent")

  self.CarryHack = ents.Create("prop_physics")
  if ValidEntity(self.CarryHack) then
     self.CarryHack:SetPos(self.EntHolding:GetPos())
     self.CarryHack:SetModel("models/weapons/w_bugbait.mdl")
     self.CarryHack:SetHealth(999)
     self.CarryHack:SetOwner(ply)
     self.CarryHack:SetCollisionGroup(COLLISION_GROUP_NONE)
     self.CarryHack:SetSolid(SOLID_NONE)
     self.CarryHack:SetNoDraw(true)
     self.CarryHack:Spawn()

     -- if we already are owner before pickup, we will not want to disown
     -- this entity when we drop it
     self.PrevOwner = self.EntHolding:GetOwner()

     --print("entholding had owner", self.PrevOwner)

     self.EntHolding:SetOwner(ply)

     local phys = self.CarryHack:GetPhysicsObject()
     if ValidEntity(phys) then
        phys:SetMass(200)
        phys:SetDamping(0, 1000)
        phys:AddGameFlag(FVPHYSICS_PLAYER_HELD)
     end

     entphys:AddGameFlag(FVPHYSICS_PLAYER_HELD)
     local bone = math.Clamp(trace.PhysicsBone, 0, 1)

     if ent:GetClass() == "prop_ragdoll" then
        self.Constr = constraint.Weld(self.CarryHack, self.EntHolding, 0, trace.PhysicsBone, rag_force:GetInt(), true)

     else
        --print("creating constraint between", self.CarryHack, self.EntHolding)

        self.Constr = constraint.Weld(self.CarryHack, self.EntHolding, 0, bone, 0, true)
     end

     --print("pickup complete, carry/constr/held", self.CarryHack, self.Constr, self.EntHolding)

     --entphys:EnableCollisions(false)
     --timer.Simple(0, entphys.EnableCollisions, entphys, true)
  end
  --      end

end

end

local down = Vector(0, 0, -1)
function SWEP:AllowEntityDrop()
local ply = self.Owner
local ent = self.CarryHack
if not ValidEntity(ply) or not ValidEntity(ent) then return false end

local ground = ply:GetGroundEntity()
if ground and (ground:IsWorld() or ValidEntity(ground)) then return true end

local diff = (ent:GetPos() - ply:GetShootPos()):Normalize()

if down:Dot(diff) > 0.75 then
return false
else
return true
end
end

– Drop it
function SWEP:Drop()
if not self:CheckValidity() then return end

if not self:AllowEntityDrop() then return end

if SERVER then
–print(“going to drop, carry/constr/holding”, self.CarryHack, self.Constr, self.EntHolding)

  self.Constr:Remove()
  self.CarryHack:Remove()
  
  
  local phys = self.EntHolding:GetPhysicsObject()
  if ValidEntity(phys) then
     phys:EnableCollisions(true)
     phys:EnableGravity(true)
     phys:EnableDrag(true)
     phys:EnableMotion(true)
     phys:Wake()
     phys:ApplyForceCenter(self.Owner:GetAimVector() * 500)

     phys:ClearGameFlag(FVPHYSICS_PLAYER_HELD)
     --phys:SetMass(self.OldMass)
  end

  -- Try to limit ragdoll slinging
  if self.EntHolding:GetClass() == "prop_ragdoll" then
     for i=0, self.EntHolding:GetPhysicsObjectCount()-1 do
        local subphys = self.EntHolding:GetPhysicsObjectNum(i)
        if IsValid(subphys) then
           subphys:SetVelocity(vector_origin)
           subphys:SetVelocityInstantaneous(vector_origin)

           subphys:AddAngleVelocity(-1 * subphys:GetAngleVelocity())
        end
     end

     self.EntHolding:SetVelocity(vector_origin)
  end

  -- this is already done in reset()
  --self.EntHolding:SetOwner(nil)

end

self:reset()
end

function SWEP:OnRemove()
self:reset()
end

function SWEP:Deploy()
self:reset()
return self.BaseClass:Deploy()
end

function SWEP:Holster()
self:Drop()
return self.BaseClass:Holster()
end

function SWEP:ShouldDropOnDie()
return false
end

function SWEP:OnDrop()
self:Remove()
end

function SWEP:GetClass()
return “weapon_zm_carry”
end
[/lua]

Check that code out.

Thank you, iRzilla, but that is not what I’m looking for. I suppose I wasn’t as clear as I thought I was.

I am not looking for a weapon to pick stuff up, but a script to where I can press a bind and pick up an object.

Thank you for your contribution as I might end up using this if Zoey doesn’t fly in and code the hell out of what I want.

[Updating OP to accomodate for my lack of intelligence.]

>.> That IS what he gave you, you can edit it into a command so you can bind it >.>

I must be missing something because that looks like weapon code. I don’t know how one would make a concommand to do what I asked.

[Updating OP because of lack of intelligence on OTHER PEOPLE’S parts.]

grabbing peelz

You want the hl2 grabbing function?

Sorry for the late reply, but yes. Almost exactly like it is in Half-life 2, only with the hanging feature, provided it’s possible in some way, shape, or form.