Files
wnsrc/lua/autorun/rb655_make_animatable.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

196 lines
6.0 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
AddCSLuaFile()
properties.Add( "rb655_make_animatable", {
MenuLabel = "#tool.rb655_easy_animation.property",
Order = 654,
MenuIcon = "icon16/tick.png",
Filter = function( self, ent, ply )
if ( !IsValid( ent ) or !gamemode.Call( "CanProperty", ply, "rb655_make_animatable", ent ) ) then return false end
if ( ent:GetClass() == "prop_animatable" ) then return false end
if ( ent:IsPlayer() or !ent:GetModel() or ent:GetModel():StartWith( "*" ) ) then return false end
--if ( string.find( ent:GetClass(), "prop_physics" ) or string.find( ent:GetClass(), "prop_ragdoll" ) ) then return true end
return true
end,
Action = function( self, ent )
self:MsgStart()
net.WriteEntity( ent )
self:MsgEnd()
end,
Receive = function( self, len, ply )
local ent = net.ReadEntity()
if ( !IsValid( ply ) or !IsValid( ent ) or !self:Filter( ent, ply ) ) then return false end
local entActual = ent
if ( IsValid( ent.AttachedEntity ) ) then
ent = ent.AttachedEntity
end
local ragPos = ent:GetPos()
-- Try to not make entity fly
if ( ent:IsRagdoll() ) then
for i = 0, ent:GetPhysicsObjectCount() - 1 do
local bone = ent:GetPhysicsObjectNum( i )
if ( IsValid( bone ) ) then
local pos = bone:GetPos()
-- Yes I like my pyramids
if ( pos.z < ragPos.z ) then
ragPos.z = pos.z
end
end
end
end
local prop_animatable = ents.Create( "prop_animatable" )
prop_animatable:SetModel( ent:GetModel() )
prop_animatable:SetPos( ragPos )
prop_animatable:SetAngles( ent:GetAngles() )
prop_animatable:SetSequence( ent:GetSequence() )
prop_animatable:SetCycle( ent:GetCycle() )
--prop_animatable:SetPlaybackRate( ent:GetPlaybackRate() )
if ( IsValid( ply ) ) then
ply:AddCount( "prop_animatable", prop_animatable )
ply:AddCleanup( "prop_animatable", prop_animatable )
prop_animatable:SetPlayer( ply )
end
prop_animatable:SetSkin( ent:GetSkin() or 0 )
prop_animatable:SetFlexScale( ent:GetFlexScale() )
for i = 0, ent:GetFlexNum() - 1 do prop_animatable:SetFlexWeight( i, ent:GetFlexWeight( i ) ) end
for i = 0, ( ent:GetNumBodyGroups() or 0 ) - 1 do prop_animatable:SetBodygroup( i, ent:GetBodygroup( i ) ) end
for i = 0, ent:GetNumPoseParameters() - 1 do prop_animatable:SetPoseParameter( ent:GetPoseParameterName( i ) , ent:GetPoseParameter( i ) ) end
for i = 0, ent:GetBoneCount() do
prop_animatable:ManipulateBoneScale( i, ent:GetManipulateBoneScale( i ) )
prop_animatable:ManipulateBoneAngles( i, ent:GetManipulateBoneAngles( i ) )
prop_animatable:ManipulateBonePosition( i, ent:GetManipulateBonePosition( i ) )
prop_animatable:ManipulateBoneJiggle( i, ent:GetManipulateBoneJiggle( i ) )
end
-- prop_animatable:InvalidateBoneCache()
prop_animatable:Spawn()
prop_animatable:Activate()
prop_animatable.EntityMods = ent.EntityMods
prop_animatable.BoneMods = ent.BoneMods
duplicator.ApplyEntityModifiers( ply, prop_animatable )
duplicator.ApplyBoneModifiers( ply, prop_animatable )
-- We use string find because there are might be subclasses, like prop_ragdoll_multiplayer or something
if ( string.find( entActual:GetClass(), "prop_ragdoll" ) or entActual:IsNPC() ) then
prop_animatable:FixRagdoll() -- This WILL have false-positives, but it will have to do for now
end
undo.ReplaceEntity( entActual, prop_animatable )
cleanup.ReplaceEntity( entActual, prop_animatable )
constraint.RemoveAll( entActual ) -- Remove all constraints ( this stops ropes from hanging around )
entActual:Remove()
end
} )
properties.Add( "rb655_make_ragdoll", {
MenuLabel = "#tool.rb655_easy_animation.property_ragdoll",
Order = 653,
MenuIcon = "icon16/tick.png",
Filter = function( self, ent, ply )
if ( !IsValid( ent ) or !gamemode.Call( "CanProperty", ply, "rb655_make_ragdoll", ent ) ) then return false end
if ( ent:GetClass() != "prop_animatable" ) then return false end
if ( !ent.GetIsRagdoll or !ent:GetIsRagdoll() ) then return false end
return true
end,
Action = function( self, ent )
self:MsgStart()
net.WriteEntity( ent )
self:MsgEnd()
end,
Receive = function( self, len, ply )
local ent = net.ReadEntity()
if ( !IsValid( ply ) or !IsValid( ent ) or !self:Filter( ent, ply ) ) then return false end
ent:BecomeRagdollLua()
end
} )
local function MakeDTVarToggleProperty( class, tab )
local origTab = {
Type = "toggle",
Filter = function( self, ent, ply )
if ( !IsValid( ent ) ) then return false end
if ( !gamemode.Call( "CanProperty", ply, class, ent ) ) then return false end
if ( self.ClassRestrict and ent:GetClass() != self.ClassRestrict ) then return false end
return true
end,
Checked = function( self, ent, ply )
-- This should never happen
if ( !isfunction( ent[ "Get" .. self.DTVariable ] ) ) then return false end
return ent[ "Get" .. self.DTVariable ]( ent )
end,
Action = function( self, ent )
self:MsgStart()
net.WriteEntity( ent )
self:MsgEnd()
end,
Receive = function( self, length, ply )
local ent = net.ReadEntity()
if ( !properties.CanBeTargeted( ent, ply ) ) then return end
if ( !self:Filter( ent, ply ) ) then return end
if ( !isfunction( ent[ "Get" .. self.DTVariable ] ) ) then return end
if ( !isfunction( ent[ "Set" .. self.DTVariable ] ) ) then return end
ent[ "Set" .. self.DTVariable ]( ent, !ent[ "Get" .. self.DTVariable ]( ent ) )
end
}
properties.Add( class, table.Merge( origTab, tab ) )
end
MakeDTVarToggleProperty( "rb655_animatable_body_xy", {
MenuLabel = "#tool.rb655_easy_animation.property_bodyxy",
Order = 600,
ClassRestrict = "prop_animatable",
DTVariable = "AnimateBodyXY"
} )
MakeDTVarToggleProperty( "rb655_animatable_ragdoll_on_dmg", {
MenuLabel = "#tool.rb655_easy_animation.property_damageragdoll",
Order = 601,
ClassRestrict = "prop_animatable",
DTVariable = "BecomeRagdoll"
} )