new post | browse code | authors | help | about

LuaBin 2.0

Viewing file root / lua / includes / modules / duplicator.lua

  1.  
  2.  
  3.  
  4. /*---------------------------------------------------------
  5.    Duplicator module,
  6.    to add new constraints or entity classes use...
  7.    
  8.    duplicator.RegisterConstraint( "name", funct, ... )
  9.    duplicator.RegisterEntityClass( "class", funct, ... )
  10.    
  11. ---------------------------------------------------------*/
  12.  
  13. module( "duplicator", package.seeall )
  14.  
  15. ConstraintType  = ConstraintType or {}
  16.        
  17. /*---------------------------------------------------------
  18.    Register a constraint to be duplicated
  19. ---------------------------------------------------------*/
  20. function RegisterConstraint( _name_ , _function_, ... )
  21.  
  22.         ConstraintType[ _name_ ]        = {}
  23.        
  24.         ConstraintType[ _name_ ].Func = _function_;
  25.         ConstraintType[ _name_ ].Args = {...}
  26.        
  27. end
  28.  
  29.  
  30. EntityClasses   = EntityClasses or {}
  31.  
  32. /*---------------------------------------------------------
  33.    Register an entity's class, to allow it to be duplicated
  34. ---------------------------------------------------------*/
  35. function RegisterEntityClass( _name_ , _function_, ... )
  36.  
  37.         EntityClasses[ _name_ ]                 = {}
  38.        
  39.         EntityClasses[ _name_ ].Func    = _function_
  40.         EntityClasses[ _name_ ].Args    = {...}
  41.        
  42. end
  43.  
  44. /*---------------------------------------------------------
  45.    Returns an entity class factory
  46. ---------------------------------------------------------*/
  47. function FindEntityClass( _name_ )
  48.  
  49.         if ( !_name_ ) then return end
  50.         return EntityClasses[ _name_ ]
  51.  
  52. end
  53.  
  54. /*---------------------------------------------------------
  55.  
  56. ---------------------------------------------------------*/
  57. BoneModifiers                           = BoneModifiers or {}
  58. EntityModifiers                         = EntityModifiers or {}
  59.  
  60. function RegisterBoneModifier( _name_, _function_ )             BoneModifiers[ _name_ ]                         = _function_ end
  61. function RegisterEntityModifier( _name_, _function_ )   EntityModifiers[ _name_ ]                       = _function_ end
  62.  
  63. if (!SERVER) then return end
  64.  
  65. /*---------------------------------------------------------
  66.    Applies generic every-day entity stuff for ent from table data.
  67. ---------------------------------------------------------*/
  68. function DoGeneric( ent, data )
  69.  
  70.         if ( !data ) then return end
  71.         if ( data.Model ) then ent:SetModel( data.Model ) end
  72.         if ( data.Angle ) then ent:SetAngles( data.Angle ) end
  73.         if ( data.Pos ) then ent:SetPos( data.Pos ) end
  74.         if ( data.Skin ) then ent:SetSkin( data.Skin ) end
  75.  
  76. end
  77.  
  78.  
  79. /*---------------------------------------------------------
  80.    Applies bone data, generically.
  81. ---------------------------------------------------------*/
  82. function DoGenericPhysics( Entity, Player, data )
  83.  
  84.         if (!data) then return end
  85.         if (!data.PhysicsObjects) then return end
  86.        
  87.         for Bone, Args in pairs( data.PhysicsObjects ) do
  88.        
  89.                 local Phys = Entity:GetPhysicsObjectNum(Bone)
  90.                
  91.                 if ( Phys && Phys:IsValid() ) then     
  92.  
  93.                         Phys:SetPos( Args.Pos )
  94.                         Phys:SetAngle( Args.Angle )
  95.  
  96.                         if ( Args.Frozen == true ) then
  97.                                 Phys:EnableMotion( false )
  98.                                 Player:AddFrozenPhysicsObject( Entity, Phys )
  99.                         end
  100.                                                        
  101.                 end
  102.                
  103.         end
  104.  
  105. end
  106.  
  107. /*---------------------------------------------------------
  108.    Restore's the face data
  109. ---------------------------------------------------------*/
  110. function DoFlex( ent, Flex, Scale )
  111.  
  112.         if (!Flex) then return end
  113.         if (!ent) then return end
  114.  
  115.         for k, v in pairs( Flex ) do
  116.                 ent:SetFlexWeight( k, v )
  117.         end
  118.        
  119.         if ( Scale ) then
  120.                 ent:SetFlexScale( Scale )
  121.         end
  122.  
  123. end
  124.  
  125. /*---------------------------------------------------------
  126.    Generic function for duplicating stuff
  127. ---------------------------------------------------------*/
  128. function GenericDuplicatorFunction( Player, data )
  129.  
  130.         local Entity = ents.Create( data.Class )
  131.                 DoGeneric( Entity, data )
  132.         Entity:Spawn()
  133.         Entity:Activate()
  134.        
  135.         DoGenericPhysics( Entity, Player, data )       
  136.        
  137.         table.Add( Entity:GetTable(), data )
  138.        
  139.         return Entity
  140.        
  141. end
  142.  
  143. /*---------------------------------------------------------
  144.         Automates the process of adding crap the EntityMods table
  145. ---------------------------------------------------------*/
  146. function StoreEntityModifier( Entity, Type, Data )
  147.  
  148.         if (!Entity) then return end
  149.         if (!Entity:IsValid()) then return end
  150.  
  151.         Entity.EntityMods = Entity.EntityMods or {}
  152.        
  153.         // Copy the data
  154.         local NewData = Entity.EntityMods[ Type ] or {}
  155.         table.Merge( NewData, Data )
  156.        
  157.         Entity.EntityMods[ Type ] = NewData
  158.  
  159. end
  160.  
  161. /*---------------------------------------------------------
  162.         Clear entity modification
  163. ---------------------------------------------------------*/
  164. function ClearEntityModifier( Entity, Type )
  165.  
  166.         if (!Entity) then return end
  167.         if (!Entity:IsValid()) then return end
  168.        
  169.         Entity.EntityMods = Entity.EntityMods or {}
  170.         Entity.EntityMods[ Type ] = nil
  171.  
  172. end
  173.  
  174. /*---------------------------------------------------------
  175.         Automates the process of adding crap the BoneMods table
  176. ---------------------------------------------------------*/
  177. function StoreBoneModifier( Entity, BoneID, Type, Data )
  178.  
  179.         if (!Entity) then return end
  180.         if (!Entity:IsValid()) then return end
  181.  
  182.         // Copy the data
  183.         NewData = {}
  184.         table.Merge( NewData , Data )
  185.        
  186.         // Add it to the entity
  187.         Entity.BoneMods = Entity.BoneMods or {}
  188.         Entity.BoneMods[ BoneID ] = Entity.BoneMods[ BoneID ] or {}
  189.        
  190.         Entity.BoneMods[ BoneID ][ Type ] = NewData
  191.  
  192. end
  193.  
  194. /*---------------------------------------------------------
  195.         Returns a copy of the passed entity's table
  196. ---------------------------------------------------------*/
  197. function CopyEntTable( Ent )
  198.  
  199.         local Tab = {}
  200.  
  201.         if ( Ent.PreEntityCopy ) then
  202.                 Ent:PreEntityCopy()
  203.         end
  204.        
  205.         table.Merge( Tab, Ent:GetTable() )
  206.        
  207.         if ( Ent.PostEntityCopy ) then
  208.                 Ent:PostEntityCopy()
  209.         end
  210.        
  211.         Tab.Pos = Ent:GetPos()
  212.         Tab.Angle = Ent:GetAngles()
  213.         Tab.Class = Ent:GetClass()
  214.         Tab.Model = Ent:GetModel()
  215.         Tab.Skin = Ent:GetSkin()
  216.        
  217.         // Allow the entity to override the class
  218.         // This is a hack for the jeep, since it's real class is different from the one it reports as
  219.         // (It reports a different class to avoid compatibility problems)
  220.         if ( Ent.ClassOverride ) then Tab.Class = Ent.ClassOverride end
  221.        
  222.         Tab.PhysicsObjects = Tab.PhysicsObjects or {}
  223.        
  224.         // Physics Objects
  225.         local iNumPhysObjects = Ent:GetPhysicsObjectCount()
  226.         for Bone = 0, iNumPhysObjects-1 do
  227.        
  228.                 local PhysObj = Ent:GetPhysicsObjectNum( Bone )
  229.                 if ( PhysObj:IsValid() ) then
  230.                
  231.                         Tab.PhysicsObjects[ Bone ] = Tab.PhysicsObjects[ Bone ] or {}
  232.                         Tab.PhysicsObjects[ Bone ].Pos = PhysObj:GetPos()
  233.                         Tab.PhysicsObjects[ Bone ].Angle = PhysObj:GetAngle()
  234.                         Tab.PhysicsObjects[ Bone ].Frozen = !PhysObj:IsMoveable()
  235.                        
  236.                 end
  237.        
  238.         end
  239.        
  240.         // Flexes
  241.         local FlexNum = Ent:GetFlexNum()
  242.         for i = 0, FlexNum do
  243.        
  244.                 Tab.Flex = Tab.Flex or {}
  245.                 Tab.Flex[ i ] = Ent:GetFlexWeight( i )
  246.        
  247.         end
  248.        
  249.         Tab.FlexScale = Ent:GetFlexScale()
  250.        
  251.         // Make this function on your SENT if you want to modify the
  252.         //  returned table specifically for your entity.
  253.         if ( Ent.OnEntityCopyTableFinish ) then
  254.                 Ent:OnEntityCopyTableFinish( Tab )
  255.         end
  256.  
  257.         return Tab
  258.  
  259. end
  260.  
  261. /*---------------------------------------------------------
  262.    Copy this entity, and all of its constraints and entities
  263.    and put them in a table.
  264. ---------------------------------------------------------*/
  265. function Copy( Ent )
  266.  
  267.         local Ents = {}
  268.         local Constraints = {}
  269.        
  270.         GetAllConstrainedEntitiesAndConstraints( Ent, Ents, Constraints )
  271.        
  272.         local EntTables = {}
  273.         for k, v in pairs(Ents) do
  274.                 EntTables[ k ] = CopyEntTable( v )
  275.         end
  276.        
  277.         local ConstraintTables = {}
  278.         for k, v in pairs(Constraints) do
  279.                 table.insert( ConstraintTables, v )
  280.         end
  281.        
  282.         return EntTables, ConstraintTables
  283.  
  284. end
  285.  
  286.  
  287. /*---------------------------------------------------------
  288.    Create an entity from a table.
  289. ---------------------------------------------------------*/
  290. function CreateEntityFromTable( Player, EntTable )
  291.  
  292.         local EntityClass = FindEntityClass( EntTable.Class )
  293.        
  294.         // This class is unregistered. Instead of failing try using a generic
  295.         // Duplication function to make a new copy..
  296.         if (!EntityClass) then
  297.        
  298.                 return GenericDuplicatorFunction( Player, EntTable )
  299.        
  300.         end
  301.                
  302.         // Build the argument list
  303.         local ArgList = {}
  304.                
  305.         for iNumber, Key in pairs( EntityClass.Args ) do
  306.  
  307.                 local Arg = nil
  308.        
  309.                 // Translate keys from old system
  310.                 if ( Key == "pos" || Key == "position" ) then Key = "Pos" end
  311.                 if ( Key == "ang" || Key == "Ang" || Key == "angle" ) then Key = "Angle" end
  312.                 if ( Key == "model" ) then Key = "Model" end
  313.                
  314.                 Arg = EntTable[ Key ]
  315.                
  316.                 // Special keys
  317.                 if ( Key == "Data" ) then Arg = EntTable end
  318.                
  319.                 // If there's a missing argument then unpack will stop sending at that argument
  320.                 if ( Arg == nil ) then Arg = false end
  321.                
  322.                 ArgList[ iNumber ] = Arg
  323.                
  324.         end
  325.                
  326.        
  327.         // Create and return the entity
  328.         return EntityClass.Func( Player, unpack(ArgList) )
  329.        
  330. end
  331.  
  332.  
  333. /*---------------------------------------------------------
  334.   Make a constraint from a constraint table
  335. ---------------------------------------------------------*/
  336. function CreateConstraintFromTable( Constraint, EntityList )
  337.  
  338.         local Factory = ConstraintType[ Constraint.Type ]
  339.         if ( !Factory ) then return end
  340.        
  341.         local Args = {}
  342.         for k, Key in pairs( Factory.Args ) do
  343.        
  344.                 local Val = Constraint[ Key ]
  345.                
  346.                 for i=1, 6 do
  347.                         if ( Constraint.Entity[ i ] ) then
  348.                                 if ( Key == "Ent"..i ) then    
  349.                                         Val = EntityList[ Constraint.Entity[ i ].Index ]
  350.                                         if ( Constraint.Entity[ i ].World ) then
  351.                                                 Val = GetWorldEntity()
  352.                                         end
  353.                                 end
  354.                                 if ( Key == "Bone"..i ) then Val = Constraint.Entity[ i ].Bone end
  355.                                 if ( Key == "LPos"..i ) then Val = Constraint.Entity[ i ].LPos end
  356.                                 if ( Key == "WPos"..i ) then Val = Constraint.Entity[ i ].WPos end
  357.                                 if ( Key == "Length"..i ) then Val = Constraint.Entity[ i ].Length end
  358.                         end
  359.                 end
  360.                
  361.                 // If there's a missing argument then unpack will stop sending at that argument
  362.                 if ( Val == nil ) then Val = false end
  363.                
  364.                 table.insert( Args, Val )
  365.        
  366.         end
  367.        
  368.         local Entity = Factory.Func( unpack(Args) )
  369.        
  370.         return Entity
  371.  
  372. end
  373.  
  374. /*---------------------------------------------------------
  375.    Given entity list and constranit list, create all entities
  376.    and return their tables
  377. ---------------------------------------------------------*/
  378. function Paste( Player, EntityList, ConstraintList )
  379.  
  380.         local CreatedEntities = {}
  381.        
  382.         //
  383.         // Create the Entities
  384.         //
  385.         for k, v in pairs( EntityList ) do
  386.        
  387.                 CreatedEntities[ k ] = CreateEntityFromTable( Player, v )
  388.                
  389.                 if ( CreatedEntities[ k ] ) then
  390.                
  391.                         CreatedEntities[ k ].BoneMods = table.Copy( v.BoneMods )
  392.                         CreatedEntities[ k ].EntityMods = table.Copy( v.EntityMods )
  393.                         CreatedEntities[ k ].PhysicsObjects = table.Copy( v.PhysicsObjects )
  394.                        
  395.                 else
  396.                
  397.                         CreatedEntities[ k ] = nil
  398.                
  399.                 end
  400.                
  401.         end
  402.        
  403.         //
  404.         // Apply modifiers to the created entities
  405.         //
  406.         for EntID, Ent in pairs( CreatedEntities ) do  
  407.        
  408.                 ApplyEntityModifiers ( Player, Ent )
  409.                 ApplyBoneModifiers ( Player, Ent )
  410.        
  411.                 if ( Ent.PostEntityPaste ) then
  412.                         Ent:PostEntityPaste( Player, Ent, CreatedEntities )
  413.                 end
  414.        
  415.         end
  416.        
  417.        
  418.         local CreatedConstraints = {}
  419.        
  420.         //
  421.         // Create constraints
  422.         //
  423.         for k, Constraint in pairs( ConstraintList ) do
  424.        
  425.                 local Entity = CreateConstraintFromTable( Constraint, CreatedEntities )
  426.                
  427.                 if ( Entity && Entity:IsValid() ) then
  428.                         table.insert( CreatedConstraints, Entity )
  429.                 end
  430.        
  431.         end
  432.  
  433.  
  434.         return CreatedEntities, CreatedConstraints
  435.        
  436. end
  437.  
  438.  
  439. /*---------------------------------------------------------
  440.   Applies entity modifiers
  441. ---------------------------------------------------------*/
  442. function ApplyEntityModifiers( Player, Ent )
  443.  
  444.         if ( !Ent ) then return end
  445.         if ( !Ent.EntityMods ) then return end
  446.  
  447.         for Type, ModFunction in pairs( EntityModifiers ) do
  448.        
  449.                 if ( Ent.EntityMods[ Type ] ) then
  450.        
  451.                         ModFunction( Player, Ent, Ent.EntityMods[ Type ] )
  452.                        
  453.                 end
  454.         end
  455.  
  456. end
  457.  
  458.  
  459. /*---------------------------------------------------------
  460.   Applies Bone Modifiers
  461. ---------------------------------------------------------*/
  462. function ApplyBoneModifiers( Player, Ent )
  463.  
  464.         if ( !Ent ) then return end
  465.         if ( !Ent.PhysicsObjects ) then return end
  466.         if ( !Ent.BoneMods ) then return end
  467.        
  468.         // For each modifier
  469.         for Type, ModFunction in pairs( BoneModifiers ) do
  470.                
  471.                 // For each of the entity's bones
  472.                 for Bone, Args in pairs( Ent.PhysicsObjects ) do
  473.                
  474.                         if ( Ent.BoneMods[ Bone ] && Ent.BoneMods[ Bone ][ Type ] ) then
  475.                        
  476.                                 local PhysObject = Ent:GetPhysicsObjectNum( Bone )
  477.                        
  478.                                 if ( Ent.PhysicsObjects[ Bone ] ) then
  479.                                         ModFunction( Player, Ent, Bone, PhysObject, Ent.BoneMods[ Bone ][ Type ] )
  480.                                 end
  481.                        
  482.                         end
  483.                
  484.                 end
  485.                
  486.         end
  487.  
  488. end
  489.  
  490.  
  491. /*---------------------------------------------------------
  492.   Returns all constrained Entities and constraints
  493.   This is kind of in the wrong place. No not call this
  494.   from outside of this code. It will probably get moved to
  495.   constraint.lua soon.
  496. ---------------------------------------------------------*/
  497. function GetAllConstrainedEntitiesAndConstraints( ent, EntTable, ConstraintTable )
  498.  
  499.         if ( !ent:IsValid() ) then return end
  500.  
  501.         EntTable[ ent:EntIndex() ] = ent
  502.        
  503.         if ( !constraint.HasConstraints( ent ) ) then return end
  504.        
  505.         local ConTable = constraint.GetTable( ent )
  506.        
  507.         for key, constraint in pairs( ConTable ) do
  508.  
  509.                 local index = constraint.Constraint
  510.                
  511.                 if ( !ConstraintTable[ index ] ) then
  512.  
  513.                         // Add constraint to the constraints table
  514.                         ConstraintTable[ index ] = constraint
  515.  
  516.                         // Run the Function for any ents attached to this constraint
  517.                         for key, ConstrainedEnt in pairs( constraint.Entity ) do
  518.  
  519.                                 GetAllConstrainedEntitiesAndConstraints( ConstrainedEnt.Entity, EntTable, ConstraintTable )
  520.                                        
  521.                         end
  522.                        
  523.                 end
  524.         end
  525.  
  526.         return EntTable, ConstraintTable
  527.        
  528. end
  529.  
  530.