Revision Difference
Entity:GetAttachment#528276
<function name="GetAttachment" parent="Entity" type="classfunc">
<description>
Gets the orientation and position of the attachment by its ID, returns nothing if the attachment does not exist.
<note>The update rate of this function is limited by the setting of ENT.AutomaticFrameAdvance for <page>Scripted Entities</page>!</note>
<bug issue="1255">This will return improper values for viewmodels if used in <page>GM:CalcView</page>.</bug>
</description>
<realm>Shared</realm>
<args>
<arg name="attachmentId" type="number">The internal ID of the attachment.</arg>
</args>
<rets>
<ret name="" type="table">The angle and position of the attachment. See the <page>Structures/AngPos</page>. Most notably, the table contains the keys "Ang" and "Pos".</ret>
</rets>
</function>
<example>
<description>Grabs the muzzle position of a player's view model.</description>
<code>
local vm = ply:GetViewModel()
local obj = vm:LookupAttachment( "muzzle" )
if (obj < 1) then
local muzzle = vm:GetAttachment( obj )
print( muzzle.Pos, muzzle.Ang )
end
</code>
</example>
<example>
<description>Draws a green cube at the player's view model muzzle if the model has a "muzzle" attachment. This properly translates the attachment into the view model projection space.</description>
<code>
-- FIXME: The nFOV parameter should be replaced with ViewModelFOV() when it's binded
local function FormatViewModelAttachment(nFOV, vOrigin, bInverse --[[= false]])
local function FormatViewModelAttachment(nFOV, vOrigin, bFrom --[[= false]])
local vEyePos = EyePos()
local aEyesRot = EyeAngles()
local vOffset = vOrigin - vEyePos
local vForward = aEyesRot:Forward()
local nViewX = math.tan(nFOV * math.pi / 360)
if (nViewX == 0) then
vForward:Mul(vForward:Dot(vOffset))
vEyePos:Add(vForward)
return vEyePos
end
-- FIXME: LocalPlayer():GetFOV() should be replaced with EyeFOV() when it's binded
local nWorldX = math.tan(LocalPlayer():GetFOV() * math.pi / 360)
if (nWorldX == 0) then
vForward:Mul(vForward:Dot(vOffset))
vEyePos:Add(vForward)
return vEyePos
end
local nFactor = nWorldX / nViewX⤶
local vRight = aEyesRot:Right()⤶
local vRight = aEyesRot:Right()⤶
local vUp = aEyesRot:Up()
if (bInverse) then
vRight:Mul(vRight:Dot(vOffset) / nFactor)⤶
vUp:Mul(vUp:Dot(vOffset) / nFactor)
if (bFrom) then
local nFactor = nWorldX / nViewX⤶
vRight:Mul(vRight:Dot(vOffset) * nFactor)
vUp:Mul(vUp:Dot(vOffset) * nFactor)⤶
else
local nFactor = nViewX / nWorldX⤶
vRight:Mul(vRight:Dot(vOffset) * nFactor)
vUp:Mul(vUp:Dot(vOffset) * nFactor)
end
vForward:Mul(vForward:Dot(vOffset))
vEyePos:Add(vRight)
vEyePos:Add(vUp)
vEyePos:Add(vForward)
return vEyePos
end
SWEP.BoxAttachment = "muzzle"
SWEP.BoxMins = Vector(-2, -2, -2)
SWEP.BoxMaxs = Vector(2, 2, 2)
SWEP.BoxColor = Color(0, 255, 0)
function SWEP:ViewModelDrawn()
local pOwner = self:GetOwner()
if (not pOwner:IsValid()) then return end
local pViewModel = pOwner:GetViewModel()
if (not pViewModel:IsValid()) then return end
local uAttachment = pViewModel:LookupAttachment(self.BoxAttachment)
if (uAttachment < 1) then return end
local tAttachment = pViewModel:GetAttachment(uAttachment)
if (tAttachment == nil) then return end
-- FIXME: This should be removed when ViewModelFOV() is binded
local nFOV = self.ViewModelFOV
if (not isnumber(nFOV)) then nFOV = 62 end
render.DrawWireframeBox(FormatViewModelAttachment(nFOV, tAttachment.Pos, true), tAttachment.Ang, self.BoxMins, self.BoxMaxs, self.BoxColor, true)
render.DrawWireframeBox(FormatViewModelAttachment(nFOV, tAttachment.Pos, false), tAttachment.Ang, self.BoxMins, self.BoxMaxs, self.BoxColor, true)
end
</code>
</example>