Advertisement
Guest User

Untitled

a guest
Jun 11th, 2014
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 43.04 KB | None | 0 0
  1. --[[
  2.     Title: Adv. Duplicator 2 Module
  3.    
  4.     Desc: Provides advanced duplication functionality for the Adv. Dupe 2 tool.
  5.    
  6.     Author: TB
  7.    
  8.     Version: 1.0
  9. ]]
  10.  
  11. require "duplicator"
  12.  
  13. AdvDupe2.duplicator = {}
  14.  
  15. AdvDupe2.JobManager = {}
  16. AdvDupe2.JobManager.PastingHook = false
  17. AdvDupe2.JobManager.Queue = {}
  18.  
  19. local constraints = {Weld=true,  Axis=true, Ballsocket=true, Elastic=true, Hydraulic=true, Motor=true, Muscle=true, Pulley=true, Rope=true, Slider=true, Winch=true}
  20.  
  21. local function FilterEntityTable(tab)
  22.     local varType
  23.     for k,v in pairs(tab)do
  24.         varType=TypeID(v)
  25.         if(varType==5)then
  26.             tab[k] = FilterEntityTable(tab[k])
  27.         elseif(varType==6 or varType==9)then
  28.             tab[k]=nil
  29.         end
  30.     end
  31.     return tab
  32. end
  33.  
  34. --[[
  35.     Name: CopyEntTable
  36.     Desc: Returns a copy of the passed entity's table
  37.     Params: <entity> Ent
  38.     Returns: <table> enttable
  39. ]]
  40.  
  41. /*---------------------------------------------------------
  42.     Returns a copy of the passed entity's table
  43. ---------------------------------------------------------*/
  44. local function CopyEntTable( Ent, Offset )
  45.    
  46.     if(not IsValid(Ent:GetPhysicsObject()))then return nil end
  47.  
  48.     local Tab = {}
  49.  
  50.     if Ent.PreEntityCopy then
  51.         local status, valid = pcall(Ent.PreEntityCopy, Ent)
  52.         if(not status)then
  53.             print("AD2 PreEntityCopy Error: "..tostring(valid))
  54.         end
  55.     end
  56.  
  57.     local EntityClass = duplicator.FindEntityClass( Ent:GetClass() )
  58.    
  59.     local EntTable = table.Copy(Ent:GetTable())
  60.    
  61.     if EntityClass then
  62.         local varType
  63.         for iNumber, Key in pairs( EntityClass.Args ) do
  64.             -- Translate keys from old system
  65.             if(Key=="Pos" or Key=="Model" or Key=="Ang" or Key=="Angle" or Key=="ang" or Key=="angle" or Key=="pos" or Key=="position" or Key=="model")then
  66.                 continue
  67.             end
  68.            
  69.             varType=TypeID(EntTable[Key])
  70.             if(varType==5)then
  71.                 Tab[ Key ] = FilterEntityTable(EntTable[Key])
  72.                 continue
  73.             elseif(varType==9 || varType==6)then
  74.                 continue
  75.             end
  76.  
  77.             Tab[ Key ] = EntTable[ Key ]
  78.         end
  79.        
  80.     end  
  81.  
  82.     Tab.BoneMods = table.Copy( Ent.BoneMods )
  83.     if(Ent.EntityMods)then
  84.         Tab.EntityMods = table.Copy(Ent.EntityMods)
  85.     end
  86.  
  87.     if Ent.PostEntityCopy then
  88.         local status, valid = pcall(Ent.PostEntityCopy, Ent)
  89.         if(not status)then
  90.             print("AD2 PostEntityCopy Error: "..tostring(valid))
  91.         end
  92.     end
  93.  
  94.     Tab.Pos             = Ent:GetPos()
  95.     Tab.Class           = Ent:GetClass()
  96.     Tab.Model           = Ent:GetModel()
  97.     Tab.Skin            = Ent:GetSkin()
  98.     Tab.CollisionGroup  = Ent:GetCollisionGroup()
  99.     Tab.ModelScale      = Ent:GetModelScale()
  100.    
  101.     if(Tab.Skin==0)then Tab.Skin = nil end
  102.     if(Tab.ModelScale == 1)then Tab.ModelScale = nil end
  103.  
  104.     if(Tab.Class == "gmod_cameraprop")then
  105.         Tab.key = Ent:GetNetworkedInt("key")
  106.     end
  107.     -- Allow the entity to override the class
  108.     -- This is a hack for the jeep, since it's real class is different from the one it reports as
  109.     -- (It reports a different class to avoid compatibility problems)
  110.     if Ent.ClassOverride then Tab.Class = Ent.ClassOverride end
  111.  
  112.     Tab.PhysicsObjects = {}
  113.  
  114.     -- Physics Objects
  115.     local PhysObj
  116.     for Bone = 0, Ent:GetPhysicsObjectCount()-1 do
  117.         PhysObj = Ent:GetPhysicsObjectNum( Bone )
  118.         if IsValid(PhysObj) then
  119.             Tab.PhysicsObjects[ Bone ] = Tab.PhysicsObjects[ Bone ] or {}
  120.             if(PhysObj:IsMoveable())then Tab.PhysicsObjects[ Bone ].Frozen = true end
  121.             PhysObj:EnableMotion(false)
  122.             Tab.PhysicsObjects[ Bone ].Pos = PhysObj:GetPos() - Tab.Pos
  123.             Tab.PhysicsObjects[ Bone ].Angle = PhysObj:GetAngles()
  124.         end
  125.     end
  126.  
  127.     Tab.PhysicsObjects[0].Pos = Tab.Pos - Offset
  128.  
  129.     Tab.Pos = nil
  130.     if(Tab.Class~="prop_physics")then
  131.         if(not Tab.BuildDupeInfo)then Tab.BuildDupeInfo = {} end
  132.         Tab.BuildDupeInfo.IsNPC = Ent:IsNPC()
  133.         Tab.BuildDupeInfo.IsVehicle = Ent:IsVehicle()
  134.     end
  135.     if( IsValid(Ent:GetParent()) ) then
  136.         if(not Tab.BuildDupeInfo)then Tab.BuildDupeInfo = {} end
  137.         Tab.PhysicsObjects[ 0 ].Angle = Ent:GetAngles()
  138.         Tab.BuildDupeInfo.DupeParentID = Ent:GetParent():EntIndex()
  139.     end
  140.  
  141.     -- Flexes
  142.     local FlexNum = Ent:GetFlexNum()
  143.     Tab.Flex = Tab.Flex or {}
  144.     local weight
  145.     local flexes
  146.     for i = 0, FlexNum do
  147.         weight = Ent:GetFlexWeight( i )
  148.         if(weight~=0)then
  149.             Tab.Flex[ i ] = weight
  150.             flexes = true
  151.         end
  152.     end
  153.     if(flexes or Ent:GetFlexScale()~=1)then
  154.         Tab.FlexScale = Ent:GetFlexScale()
  155.     else
  156.         Tab.Flex = nil
  157.     end
  158.    
  159.     -- Body Groups
  160.     Tab.BodyG = {}
  161.     for k, v in pairs(Ent:GetBodyGroups()) do
  162.         if ( Ent:GetBodygroup( v.id ) > 0 ) then
  163.             Tab.BodyG[ v.id ] = Ent:GetBodygroup( v.id )
  164.         end
  165.     end
  166.    
  167.     if(table.Count(Tab.BodyG)==0)then
  168.         Tab.BodyG = nil
  169.     end
  170.    
  171.     -- Bone Manipulator
  172.     if ( Ent:HasBoneManipulations() ) then
  173.    
  174.         Tab.BoneManip = {}
  175.         local t
  176.         local s
  177.         local a
  178.         local p
  179.         for i=0, Ent:GetBoneCount() do
  180.             t={}
  181.             s = Ent:GetManipulateBoneScale( i )
  182.             a = Ent:GetManipulateBoneAngles( i )
  183.             p = Ent:GetManipulateBonePosition( i )
  184.            
  185.             if ( s != Vector( 1, 1, 1 ) ) then  t[ 's' ] = s end
  186.             if ( a != Angle( 0, 0, 0 ) ) then   t[ 'a' ] = a end
  187.             if ( p != Vector( 0, 0, 0 ) ) then  t[ 'p' ] = p end
  188.        
  189.             if ( t['s'] or t['a'] or t['p'] ) then
  190.                 Tab.BoneManip[ i ] = t
  191.             end
  192.        
  193.         end
  194.    
  195.     end
  196.  
  197.     if Ent.GetNetworkVars then
  198.         Tab.DT = Ent:GetNetworkVars()
  199.     end
  200.  
  201.     // Make this function on your SENT if you want to modify the
  202.     //  returned table specifically for your entity.
  203.     if Ent.OnEntityCopyTableFinish then
  204.         local status, valid = pcall(Ent.OnEntityCopyTableFinish, Ent, Tab)
  205.         if(not status)then
  206.             print("AD2 OnEntityCopyTableFinish Error: "..tostring(valid))
  207.         end
  208.     end
  209.  
  210.     return Tab
  211.  
  212. end
  213.  
  214.  
  215. --[[
  216.     Name: CopyConstraintTable
  217.     Desc: Create a table for constraints
  218.     Params: <table> Constraints
  219.     Returns: <table> Constraints, <table> Entities
  220. ]]
  221. local function CopyConstraintTable( Const, Offset )
  222.  
  223.     if(Const==nil)then return nil, {} end
  224.     local Type = duplicator.ConstraintType[ Const.Type ]
  225.     if(not Type)then return nil, {} end
  226.     local Constraint = {}
  227.     local Entities = {}
  228.  
  229.     Const.Constraint = nil
  230.     Const.OnDieFunctions=nil
  231.     Constraint.Entity={}
  232.     for k, key in pairs( Type.Args ) do
  233.         if(key~="pl" and not string.find(key, "Ent") and not string.find(key, "Bone"))then
  234.             Constraint[key] = Const[ key ]
  235.         end
  236.     end
  237.  
  238.     if((Const["Ent"] and Const["Ent"]:IsWorld()) or IsValid(Const["Ent"]))then
  239.         Constraint.Entity[ 1 ] = {}
  240.         Constraint.Entity[ 1 ].Index = Const["Ent"]:EntIndex()
  241.         if(not Const["Ent"]:IsWorld())then table.insert( Entities, Const["Ent"] ) end
  242.         Constraint.Type = Const.Type
  243.         if(Const.BuildDupeInfo)then Constraint.BuildDupeInfo = table.Copy(Const.BuildDupeInfo) end
  244.     else
  245.         local ent
  246.         for i=1,4 do
  247.             ent = "Ent"..i
  248.  
  249.             if((Const[ent] and Const[ent]:IsWorld()) or IsValid(Const[ent]))then
  250.                 Constraint.Entity[ i ]              = {}
  251.                 Constraint.Entity[ i ].Index        = Const[ent]:EntIndex()
  252.                 Constraint.Entity[ i ].Bone         = Const[ "Bone"..i ]
  253.                 Constraint.Entity[ i ].Length       = Const[ "Length"..i ]
  254.                 Constraint.Entity[ i ].World        = Const[ "World"..i ]
  255.  
  256.                 if Const[ ent ]:IsWorld() then
  257.                     Constraint.Entity[ i ].World = true
  258.                     if ( Const[ "LPos"..i ] ) then
  259.                         if(i~= 4 and i~=2)then
  260.                             if(Const["Ent2"])then
  261.                                 Constraint.Entity[ i ].LPos = Const[ "LPos"..i ] - Const["Ent2"]:GetPos()
  262.                                 Constraint[ "LPos"..i ] = Const[ "LPos"..i ] - Const["Ent2"]:GetPos()
  263.                             elseif(Const["Ent4"])then
  264.                                 Constraint.Entity[ i ].LPos = Const[ "LPos"..i ] - Const["Ent4"]:GetPos()
  265.                                 Constraint[ "LPos"..i ] = Const[ "LPos"..i ] - Const["Ent4"]:GetPos()
  266.                             end
  267.                         elseif(Const["Ent1"])then
  268.                             Constraint.Entity[ i ].LPos = Const[ "LPos"..i ] - Const["Ent1"]:GetPos()
  269.                             Constraint[ "LPos"..i ] = Const[ "LPos"..i ] - Const["Ent1"]:GetPos()
  270.                         end
  271.                     else
  272.                         Constraint.Entity[ i ].LPos = Offset
  273.                         Constraint[ "LPos"..i ] = Offset
  274.                     end
  275.                 else
  276.                     Constraint.Entity[ i ].LPos = Const[ "LPos"..i ]
  277.                     Constraint.Entity[ i ].WPos = Const[ "WPos"..i ]
  278.                 end
  279.  
  280.                 if(not Const[ent]:IsWorld())then table.insert( Entities, Const[ent] ) end
  281.             end
  282.  
  283.             if(Const["WPos"..i])then
  284.                 if(not Const["Ent1"]:IsWorld())then
  285.                     Constraint["WPos"..i] = Const[ "WPos"..i ] - Const["Ent1"]:GetPos()
  286.                 else
  287.                     Constraint["WPos"..i] = Const[ "WPos"..i ] - Const["Ent4"]:GetPos()
  288.                 end
  289.             end
  290.         end
  291.  
  292.         Constraint.Type = Const.Type
  293.         if(Const.BuildDupeInfo)then Constraint.BuildDupeInfo = table.Copy(Const.BuildDupeInfo) end
  294.     end    
  295.     return Constraint, Entities
  296. end
  297.  
  298. --[[
  299.     Name: Copy
  300.     Desc: Copy an entity and all entities constrained
  301.     Params: <entity> Entity
  302.     Returns: <table> Entities, <table> Constraints
  303. ]]
  304. local function Copy( Ent, EntTable, ConstraintTable, Offset )
  305.  
  306.     local index = Ent:EntIndex()
  307.     if(EntTable[index])then return EntTable, ConstraintTable end
  308.  
  309.     EntTable[index] = CopyEntTable(Ent, Offset)
  310.     if(EntTable[index]==nil)then return EntTable, ConstraintTable end
  311.  
  312.     if ( not constraint.HasConstraints( Ent ) ) then
  313.         for k,v in pairs(EntTable[Ent:EntIndex()].PhysicsObjects)do
  314.             Ent:GetPhysicsObjectNum(k):EnableMotion(v.Frozen)
  315.         end
  316.         return EntTable, ConstraintTable
  317.     end
  318.  
  319.     local ConstTable, EntTab
  320.     for k, Constraint in pairs( Ent.Constraints ) do
  321.         index = Constraint:GetCreationID()
  322.         if(index and not ConstraintTable[index])then
  323.             Constraint.Identity = index
  324.             ConstTable, EntTab = CopyConstraintTable( table.Copy(Constraint:GetTable()), Offset )
  325.             ConstraintTable[index] = ConstTable
  326.             for j,e in pairs(EntTab) do
  327.                 if ( e and ( e:IsWorld() or e:IsValid() ) ) and ( not EntTable[e:EntIndex()] ) then
  328.                     Copy( e, EntTable, ConstraintTable, Offset )
  329.                 end
  330.             end
  331.         end
  332.     end
  333.  
  334.     for k,v in pairs(EntTable[Ent:EntIndex()].PhysicsObjects)do
  335.         Ent:GetPhysicsObjectNum(k):EnableMotion(v.Frozen)
  336.     end
  337.  
  338.     return EntTable, ConstraintTable
  339. end
  340. AdvDupe2.duplicator.Copy = Copy
  341.  
  342. --[[
  343.     Name: AreaCopy
  344.     Desc: Copy based on a box
  345.     Params: <entity> Entity
  346.     Returns: <table> Entities, <table> Constraints
  347. ]]
  348. function AdvDupe2.duplicator.AreaCopy( Entities, Offset, CopyOutside )
  349.     local Constraints, EntTable, ConstraintTable = {}, {}, {}
  350.     local index, add, AddEnts, AddConstrs, ConstTable, EntTab
  351.    
  352.     for _,Ent in pairs(Entities)do
  353.  
  354.         index = Ent:EntIndex()
  355.         EntTable[index] = CopyEntTable(Ent, Offset)
  356.         if(EntTable[index]~=nil)then
  357.        
  358.             if ( not constraint.HasConstraints( Ent ) ) then
  359.                 for k,v in pairs(EntTable[Ent:EntIndex()].PhysicsObjects)do
  360.                     Ent:GetPhysicsObjectNum(k):EnableMotion(v.Frozen)
  361.                 end
  362.             else
  363.                 for k,v in pairs(Ent.Constraints)do
  364.                     index = v:GetCreationID()
  365.                     if(index and not Constraints[index])then
  366.                         v.Identity = v:GetCreationID()
  367.                         Constraints[index] = v
  368.                     end
  369.                 end
  370.                
  371.                 for k,v in pairs(EntTable[Ent:EntIndex()].PhysicsObjects)do
  372.                     Ent:GetPhysicsObjectNum(k):EnableMotion(v.Frozen)
  373.                 end
  374.             end
  375.         end
  376.     end
  377.  
  378.     for _, Constraint in pairs( Constraints ) do
  379.         ConstTable, EntTab = CopyConstraintTable( table.Copy(Constraint:GetTable()), Offset )
  380.         //If the entity is constrained to an entity outside of the area box, don't copy the constraint.
  381.         if(not CopyOutside)then
  382.             add = true
  383.             for k,v in pairs(EntTab)do
  384.                 if(not Entities[v:EntIndex()])then add=false end
  385.             end
  386.             if(add)then ConstraintTable[_] = ConstTable  end
  387.         else    //Copy entities and constraints outside of the box that are constrained to entities inside the box
  388.             ConstraintTable[_] = ConstTable
  389.             for k,v in pairs(EntTab)do
  390.                 Copy(v, EntTable, ConstraintTable, Offset)
  391.             end
  392.         end
  393.     end
  394.  
  395.     return EntTable, ConstraintTable
  396. end
  397.  
  398. --[[
  399.     Name: CreateConstraintFromTable
  400.     Desc: Creates a constraint from a given table
  401.     Params: <table>Constraint, <table> EntityList, <table> EntityTable
  402.     Returns: <entity> CreatedConstraint
  403. ]]
  404. local function CreateConstraintFromTable(Constraint, EntityList, EntityTable, Player, DontEnable)
  405.  
  406.     local Factory = duplicator.ConstraintType[ Constraint.Type ]
  407.     if not Factory then return end
  408.  
  409.     local first --Ent1 or Ent in the constraint's table
  410.     local second --Any other Ent that is not Ent1 or Ent
  411.    
  412.     -- Build the argument list for the Constraint's spawn function
  413.     local Args = {}
  414.     local Val
  415.     for k, Key in pairs( Factory.Args ) do
  416.  
  417.         Val = Constraint[ Key ]
  418.  
  419.         if Key == "pl" or Key == "ply" then
  420.             Val = Player
  421.         end
  422.  
  423.         for i=1, 4 do
  424.             if ( Constraint.Entity and Constraint.Entity[ i ] ) then
  425.                 if Key == "Ent"..i or Key == "Ent" then
  426.                     if ( Constraint.Entity[ i ].World ) then
  427.                         Val = game.GetWorld()
  428.                     else               
  429.                         Val = EntityList[ Constraint.Entity[ i ].Index ]
  430.  
  431.                         if not IsValid(Val) then
  432.                             if(Player)then
  433.                                 Player:ChatPrint("DUPLICATOR: ERROR, "..Constraint.Type.." Constraint could not find an entity!")
  434.                             else
  435.                                 print("DUPLICATOR: ERROR, "..Constraint.Type.." Constraint could not find an entity!")
  436.                             end    
  437.                             return
  438.                         else   
  439.                             if(IsValid(Val:GetPhysicsObject()))then
  440.                                 Val:GetPhysicsObject():EnableMotion(false)
  441.                             end
  442.                             --Important for perfect duplication
  443.                             --Get which entity is which so we can reposition them before constraining
  444.                             if(Key== "Ent" or Key == "Ent1")then
  445.                                 first=Val
  446.                                 firstindex = Constraint.Entity[ i ].Index
  447.                             else
  448.                                 second=Val
  449.                                 secondindex = Constraint.Entity[ i ].Index
  450.                             end
  451.                                    
  452.                         end    
  453.                     end
  454.  
  455.                 end
  456.  
  457.                 if Key == "Bone"..i or Key == "Bone" then Val = Constraint.Entity[ i ].Bone end
  458.  
  459.                 if Key == "LPos"..i then
  460.                     if (Constraint.Entity[i].World and Constraint.Entity[i].LPos)then
  461.                         if(i==2 or i==4)then
  462.                             Val = Constraint.Entity[i].LPos + EntityList[Constraint.Entity[1].Index]:GetPos()
  463.                         elseif(i==1)then
  464.                             if(Constraint.Entity[2])then
  465.                                 Val = Constraint.Entity[i].LPos + EntityList[Constraint.Entity[2].Index]:GetPos()
  466.                             else
  467.                                 Val = Constraint.Entity[i].LPos + EntityList[Constraint.Entity[4].Index]:GetPos()
  468.                             end
  469.                         end
  470.                     elseif( Constraint.Entity[i].LPos ) then
  471.                         Val = Constraint.Entity[ i ].LPos
  472.                     end
  473.                 end
  474.  
  475.                 if Key == "Length"..i then Val = Constraint.Entity[ i ].Length end
  476.             end
  477.             if Key == "WPos"..i then
  478.                 if(not Constraint.Entity[1].World)then
  479.                     Val = Constraint["WPos"..i] + EntityList[Constraint.Entity[1].Index]:GetPos()
  480.                 else
  481.                     Val = Constraint["WPos"..i] + EntityList[Constraint.Entity[4].Index]:GetPos()
  482.                 end
  483.             end
  484.  
  485.         end
  486.         -- If there's a missing argument then unpack will stop sending at that argument
  487.         Val = Val or false
  488.         table.insert( Args, Val )
  489.  
  490.     end
  491.  
  492.     local Bone1
  493.     local Bone1Index
  494.     local ReEnableFirst
  495.     local Bone2
  496.     local Bone2Index
  497.     local ReEnableSecond
  498.     if(Constraint.BuildDupeInfo)then
  499.  
  500.         if second ~= nil and not second:IsWorld() and Constraint.BuildDupeInfo.EntityPos ~= nil then
  501.             if(not DontEnable)then ReEnableSecond = second:GetPhysicsObject():IsMoveable() end
  502.             second:GetPhysicsObject():EnableMotion(false)
  503.             second:SetPos(first:GetPos()-Constraint.BuildDupeInfo.EntityPos)
  504.             if(Constraint.BuildDupeInfo.Bone2) then
  505.                 Bone2Index = Constraint.BuildDupeInfo.Bone2
  506.                 Bone2 = second:GetPhysicsObjectNum(Bone2Index)
  507.                 Bone2:EnableMotion(false)
  508.                 Bone2:SetPos(second:GetPos() + Constraint.BuildDupeInfo.Bone2Pos)
  509.                 Bone2:SetAngles(Constraint.BuildDupeInfo.Bone2Angle)
  510.             end
  511.         end
  512.  
  513.         if first ~= nil and Constraint.BuildDupeInfo.Ent1Ang ~= nil then
  514.             if(not DontEnable)then ReEnableFirst = first:GetPhysicsObject():IsMoveable() end
  515.             first:GetPhysicsObject():EnableMotion(false)
  516.             first:SetAngles(Constraint.BuildDupeInfo.Ent1Ang)
  517.             if(Constraint.BuildDupeInfo.Bone1) then
  518.                 Bone1Index = Constraint.BuildDupeInfo.Bone1
  519.                 Bone1 = first:GetPhysicsObjectNum(Bone1Index)
  520.                 Bone1:EnableMotion(false)
  521.                 Bone1:SetPos(first:GetPos() + Constraint.BuildDupeInfo.Bone1Pos)
  522.                 Bone1:SetAngles(Constraint.BuildDupeInfo.Bone1Angle)
  523.             end
  524.         end
  525.  
  526.         if second ~= nil and Constraint.BuildDupeInfo.Ent2Ang ~= nil then
  527.             second:SetAngles(Constraint.BuildDupeInfo.Ent2Ang)
  528.         end
  529.  
  530.         if second ~= nil and Constraint.BuildDupeInfo.Ent4Ang ~= nil then
  531.             second:SetAngles(Constraint.BuildDupeInfo.Ent4Ang)
  532.         end
  533.     end
  534.  
  535.     local status, Ent = pcall( Factory.Func, unpack(Args))
  536.  
  537.     if not status or not Ent then
  538.         if(Player)then
  539.             AdvDupe2.Notify(Player, "ERROR, Failed to create "..Constraint.Type.." Constraint!", NOTIFY_ERROR)
  540.         else
  541.             print("DUPLICATOR: ERROR, Failed to create "..Constraint.Type.." Constraint!")
  542.         end
  543.         return
  544.     end
  545.  
  546.     Ent.BuildDupeInfo = table.Copy(Constraint.BuildDupeInfo)
  547.  
  548.     //Move the entities back after constraining them
  549.     if(EntityTable)then
  550.         if(first~=nil)then
  551.             first:SetPos(EntityTable[firstindex].BuildDupeInfo.PosReset)
  552.             first:SetAngles(EntityTable[firstindex].BuildDupeInfo.AngleReset)
  553.             if(Bone1 and Bone1Index~=0)then
  554.                 Bone1:SetPos(EntityTable[firstindex].BuildDupeInfo.PosReset + EntityTable[firstindex].BuildDupeInfo.PhysicsObjects[Bone1Index].Pos)
  555.                 Bone1:SetAngles(EntityTable[firstindex].PhysicsObjects[Bone1Index].Angle)
  556.             end
  557.             if(ReEnableFirst)then first:GetPhysicsObject():EnableMotion(true) end
  558.         end
  559.         if(second~=nil)then
  560.             second:SetPos(EntityTable[secondindex].BuildDupeInfo.PosReset)
  561.             second:SetAngles(EntityTable[secondindex].BuildDupeInfo.AngleReset)
  562.             if(Bone2 and Bone2Index~=0)then
  563.                 Bone2:SetPos(EntityTable[secondindex].BuildDupeInfo.PosReset + EntityTable[secondindex].BuildDupeInfo.PhysicsObjects[Bone2Index].Pos)
  564.                 Bone2:SetAngles(EntityTable[secondindex].PhysicsObjects[Bone2Index].Angle)
  565.             end
  566.             if(ReEnableSecond)then second:GetPhysicsObject():EnableMotion(true) end
  567.         end
  568.     end
  569.  
  570.     if(Ent and Ent.length)then Ent.length = Constraint["length"] end //Fix for weird bug with ropes
  571.  
  572.     return Ent
  573. end
  574.  
  575. local function ApplyEntityModifiers( Player, Ent )
  576.     if(not Ent.EntityMods)then return end
  577.     local status, error
  578.     for Type, ModFunction in pairs( duplicator.EntityModifiers ) do
  579.         if ( Ent.EntityMods[ Type ] ) then
  580.             status, error = pcall(ModFunction, Player, Ent, Ent.EntityMods[ Type ] )
  581.             if(not status)then
  582.                 if(Player)then
  583.                     Player:ChatPrint('Error applying entity modifer, "'..tostring(Type)..'". ERROR: '..error)
  584.                 else
  585.                     print('Error applying entity modifer, "'..tostring(Type)..'". ERROR: '..error)
  586.                 end
  587.             end
  588.         end
  589.     end
  590.     if(Ent.EntityMods["mass"] and duplicator.EntityModifiers["mass"])then
  591.         status, error = pcall(duplicator.EntityModifiers["mass"], Player, Ent, Ent.EntityMods["mass"] )
  592.         if(not status)then
  593.             if(Player)then
  594.                 Player:ChatPrint('Error applying entity modifer, "mass". ERROR: '..error)
  595.             else
  596.                 print('Error applying entity modifer, "'..tostring(Type)..'". ERROR: '..error)
  597.             end
  598.         end
  599.     end
  600.  
  601. end
  602.  
  603. local function ApplyBoneModifiers( Player, Ent )
  604.     if(not Ent.BoneMods or not Ent.PhysicsObjects)then return end
  605.  
  606.     local status, error, PhysObject
  607.     for Type, ModFunction in pairs( duplicator.BoneModifiers ) do
  608.         for Bone, Args in pairs( Ent.PhysicsObjects ) do
  609.             if ( Ent.BoneMods[ Bone ] and Ent.BoneMods[ Bone ][ Type ] ) then
  610.                 PhysObject = Ent:GetPhysicsObjectNum( Bone )
  611.                 if ( Ent.PhysicsObjects[ Bone ] ) then
  612.                     status, error = pcall(ModFunction, Player, Ent, Bone, PhysObject, Ent.BoneMods[ Bone ][ Type ] )
  613.                     if(not status)then
  614.                         Player:ChatPrint('Error applying bone modifer, "'..tostring(Type)..'". ERROR: '..error)
  615.                     end
  616.                 end
  617.             end
  618.         end
  619.     end
  620. end
  621.  
  622. --[[
  623.     Name: DoGenericPhysics
  624.     Desc: Applies bone data, generically.
  625.     Params: <player> Player, <table> data
  626.     Returns: <entity> Entity, <table> data
  627. ]]
  628. local function DoGenericPhysics( Entity, data, Player )
  629.  
  630.     if (not data) then return end
  631.     if (not data.PhysicsObjects) then return end
  632.     local Phys
  633.     if(Player)then
  634.         for Bone, Args in pairs( data.PhysicsObjects ) do
  635.             Phys = Entity:GetPhysicsObjectNum(Bone)
  636.             if ( IsValid(Phys) ) then  
  637.                 Phys:SetPos( Args.Pos )
  638.                 Phys:SetAngles( Args.Angle )
  639.                 Phys:EnableMotion( false )  
  640.                 Player:AddFrozenPhysicsObject( Entity, Phys )
  641.             end
  642.         end
  643.     else
  644.         for Bone, Args in pairs( data.PhysicsObjects ) do
  645.             Phys = Entity:GetPhysicsObjectNum(Bone)
  646.             if ( IsValid(Phys) ) then  
  647.                 Phys:SetPos( Args.Pos )
  648.                 Phys:SetAngles( Args.Angle )
  649.                 Phys:EnableMotion( false )  
  650.             end
  651.         end
  652.     end
  653. end
  654.  
  655. local function reportclass(ply,class)
  656.     umsg.Start("AdvDupe2_ReportClass", ply)
  657.         umsg.String(class)
  658.     umsg.End()
  659. end
  660.  
  661. local function reportmodel(ply,model)
  662.     umsg.Start("AdvDupe2_ReportModel", ply)
  663.         umsg.String(model)
  664.     umsg.End()
  665. end
  666.  
  667. --[[
  668.     Name: GenericDuplicatorFunction
  669.     Desc: Override the default duplicator's GenericDuplicatorFunction function
  670.     Params: <player> Player, <table> data
  671.     Returns: <entity> Entity
  672. ]]
  673. local function GenericDuplicatorFunction( data, Player )
  674.  
  675.     local Entity = ents.Create( data.Class )
  676.     if ( not IsValid(Entity) ) then
  677.         if(Player)then
  678.             reportclass(Player,data.Class)
  679.         else
  680.              print("Advanced Duplicator 2 Invalid Class: "..data.Class)
  681.         end
  682.         return nil
  683.     end
  684.  
  685.     if( not util.IsValidModel(data.Model) and not file.Exists( data.Model, "GAME" ) )then
  686.         if(Player)then
  687.             reportmodel(Player,data.Model)
  688.         else
  689.             print("Advanced Duplicator 2 Invalid Model: "..data.Model)
  690.         end
  691.         return nil
  692.     end
  693.  
  694.     duplicator.DoGeneric( Entity, data )
  695.     Entity:Spawn()
  696.     Entity:Activate()
  697.     DoGenericPhysics( Entity, data, Player )   
  698.  
  699.     table.Add( Entity:GetTable(), data )
  700.     return Entity
  701. end
  702.  
  703. --[[
  704.     Name: MakeProp
  705.     Desc: Make prop without spawn effects
  706.     Params: <player> Player, <vector> Pos, <angle> Ang, <string> Model, <table> PhysicsObject, <table> Data
  707.     Returns: <entity> Prop
  708. ]]
  709. local function MakeProp(Player, Pos, Ang, Model, PhysicsObject, Data)
  710.  
  711.     if( not util.IsValidModel(Model) and not file.Exists( Data.Model, "GAME" ) )then
  712.         if(Player)then
  713.             reportmodel(Player,Data.Model)
  714.         else
  715.             print("Advanced Duplicator 2 Invalid Model: "..Model)
  716.         end
  717.         return nil
  718.     end
  719.  
  720.     Data.Pos = Pos
  721.     Data.Angle = Ang
  722.     Data.Model = Model
  723.     Data.Frozen = true
  724.     // Make sure this is allowed
  725.     if( Player )then
  726.         if ( not gamemode.Call( "PlayerSpawnProp", Player, Model ) ) then return false end
  727.     end
  728.  
  729.     local Prop = ents.Create( "prop_physics" )
  730.     if not IsValid(Prop) then return false end
  731.  
  732.     duplicator.DoGeneric( Prop, Data )
  733.     Prop:Spawn()
  734.     Prop:Activate()
  735.     DoGenericPhysics( Prop, Data, Player )
  736.     if(Data.Flex)then duplicator.DoFlex( Prop, Data.Flex, Data.FlexScale ) end
  737.  
  738.     return Prop
  739. end
  740.  
  741. local function RestoreBodyGroups( ent, BodyG )
  742.     for k, v in pairs( BodyG ) do
  743.         ent:SetBodygroup( k, v )
  744.     end
  745. end
  746.  
  747. --[[
  748.     Name: CreateEntityFromTable
  749.     Desc: Creates an entity from a given table
  750.     Params: <table> EntTable, <player> Player
  751.     Returns: nil
  752. ]]
  753. local function CreateEntityFromTable(EntTable, Player)
  754.  
  755.     local EntityClass = duplicator.FindEntityClass( EntTable.Class )
  756.     if ( Player and not Player:IsAdmin( ) and not Player:IsSuperAdmin() and not game.SinglePlayer())then
  757.         if(not AdvDupe2.duplicator.EntityList[EntTable.Class])then
  758.             Player:ChatPrint([[Entity Class Black listed, "]]..EntTable.Class..[["]])
  759.             return nil
  760.         end
  761.     end
  762.  
  763.     local sent = false
  764.     local status, valid
  765.     local GENERIC = false
  766.  
  767.     // This class is unregistered. Instead of failing try using a generic
  768.     // Duplication function to make a new copy.
  769.     if (not EntityClass) then
  770.         GENERIC = true
  771.         sent = true
  772.  
  773.         /*if(EntTable.Class=="prop_effect")then
  774.             sent = gamemode.Call( "PlayerSpawnEffect", Player, EntTable.Model)
  775.         else
  776.             sent = gamemode.Call( "PlayerSpawnSENT", Player, EntTable.Class)
  777.         end
  778.         */
  779.  
  780.         sent = hook.Call("PlayerSpawnEntity", nil, Player, EntTable)
  781.         if(sent==false)then
  782.             print("Advanced Duplicator 2: Creation rejected for class, : "..EntTable.Class)
  783.             return nil
  784.         else
  785.             sent = true
  786.         end
  787.  
  788.         if duplicator.IsAllowed(EntTable.Class) then
  789.             status, valid = pcall(GenericDuplicatorFunction, EntTable, Player )
  790.         else
  791.             print("Advanced Duplicator 2: ENTITY CLASS IS BLACKLISTED, CLASS NAME: "..EntTable.Class)
  792.             return nil
  793.         end
  794.     end
  795.  
  796.     if(not GENERIC)then
  797.  
  798.         // Build the argument list for the Entitie's spawn function
  799.         local ArgList = {}
  800.         local Arg
  801.         for iNumber, Key in pairs( EntityClass.Args ) do
  802.  
  803.             Arg = nil
  804.             // Translate keys from old system
  805.             if ( Key == "pos" or Key == "position" ) then Key = "Pos" end
  806.             if ( Key == "ang" or Key == "Ang" or Key == "angle" ) then Key = "Angle" end
  807.             if ( Key == "model" ) then Key = "Model" end
  808.             if ( Key == "VehicleTable" and EntTable[Key] and EntTable[Key].KeyValues)then
  809.                 EntTable[Key].KeyValues = {vehiclescript=EntTable[Key].KeyValues.vehiclescript, limitview=EntTable[Key].KeyValues.limitview}
  810.             end
  811.  
  812.             Arg = EntTable[ Key ]
  813.  
  814.             // Special keys
  815.             if ( Key == "Data" ) then Arg = EntTable end
  816.  
  817.             // If there's a missing argument then unpack will stop sending at that argument
  818.             ArgList[ iNumber ] = Arg or false
  819.  
  820.         end
  821.        
  822.         // Create and return the entity
  823.         if(EntTable.Class=="prop_physics")then
  824.             valid = MakeProp(Player, unpack(ArgList)) //Create prop_physics like this because if the model doesn't exist it will cause
  825.         elseif duplicator.IsAllowed(EntTable.Class) then
  826.             //Create sents using their spawn function with the arguments we stored earlier
  827.             sent = true
  828.  
  829.             /*if(not EntTable.BuildDupeInfo.IsVehicle or not EntTable.BuildDupeInfo.IsNPC or EntTable.Class~="prop_ragdoll")then    //These three are auto done
  830.                 sent = gamemode.Call( "PlayerSpawnSENT", Player, EntTable.Class)
  831.             end
  832.             */
  833.             sent = hook.Call("PlayerSpawnEntity", nil, Player, EntTable)
  834.             if(sent==false)then
  835.                 print("Advanced Duplicator 2: Creation rejected for class, : "..EntTable.Class)
  836.                 return nil
  837.             else
  838.                 sent = true
  839.             end    
  840.            
  841.             status,valid = pcall(  EntityClass.Func, Player, unpack(ArgList) )
  842.         else
  843.             print("Advanced Duplicator 2: ENTITY CLASS IS BLACKLISTED, CLASS NAME: "..EntTable.Class)
  844.             return nil
  845.         end
  846.     end
  847.  
  848.     //If its a valid entity send it back to the entities list so we can constrain it
  849.     if( status~=false and IsValid(valid) )then
  850.         if(sent)then
  851.             local iNumPhysObjects = valid:GetPhysicsObjectCount()
  852.             local PhysObj
  853.             if(Player)then
  854.                 for Bone = 0, iNumPhysObjects-1 do
  855.                     PhysObj = valid:GetPhysicsObjectNum( Bone )
  856.                     if IsValid(PhysObj) then
  857.                         PhysObj:EnableMotion(false)
  858.                         Player:AddFrozenPhysicsObject( valid, PhysObj )
  859.                     end
  860.                 end
  861.             else
  862.                 for Bone = 0, iNumPhysObjects-1 do
  863.                     PhysObj = valid:GetPhysicsObjectNum( Bone )
  864.                     if IsValid(PhysObj) then
  865.                         PhysObj:EnableMotion(false)
  866.                     end
  867.                 end
  868.             end
  869.             if(EntTable.Skin)then valid:SetSkin(EntTable.Skin) end
  870.             if ( EntTable.BodyG ) then RestoreBodyGroups( valid, EntTable.BodyG ) end
  871.  
  872.             if valid.RestoreNetworkVars then
  873.                 valid:RestoreNetworkVars(EntTable.DT)
  874.             end
  875.  
  876.             /*if(Player)then
  877.                 if(not valid:IsVehicle() and EntTable.Class~="prop_ragdoll" and not valid:IsNPC())then  //These three get called automatically
  878.                     if(EntTable.Class=="prop_effect")then
  879.                         gamemode.Call("PlayerSpawnedEffect", Player, valid:GetModel(), valid)
  880.                     else
  881.                         gamemode.Call("PlayerSpawnedSENT", Player, valid)
  882.                     end
  883.                 end
  884.             end*/
  885.         elseif(Player)then
  886.             gamemode.Call( "PlayerSpawnedProp", Player, valid:GetModel(), valid )
  887.         end
  888.  
  889.         return valid
  890.     else
  891.         if(valid==false)then
  892.             return false
  893.         else
  894.             return nil
  895.         end
  896.     end
  897. end
  898.  
  899. --[[
  900.     Name: Paste
  901.     Desc: Override the default duplicator's paste function
  902.     Params: <player> Player, <table> Entities, <table> Constraints
  903.     Returns: <table> Entities, <table> Constraints
  904. ]]
  905. function AdvDupe2.duplicator.Paste( Player, EntityList, ConstraintList, Position, AngleOffset, OrigPos, Parenting )
  906.  
  907.     local CreatedEntities = {}
  908.     --
  909.     -- Create entities
  910.     --
  911.     local proppos
  912.     DisablePropCreateEffect = true
  913.     for k, v in pairs( EntityList ) do
  914.         if(not v.BuildDupeInfo)then v.BuildDupeInfo={} end
  915.         v.BuildDupeInfo.PhysicsObjects = table.Copy(v.PhysicsObjects)
  916.         proppos = v.PhysicsObjects[0].Pos
  917.         v.BuildDupeInfo.PhysicsObjects[0].Pos = Vector(0,0,0)
  918.         if( OrigPos )then
  919.             for i,p in pairs(v.BuildDupeInfo.PhysicsObjects) do
  920.                 v.PhysicsObjects[i].Pos = p.Pos + proppos + OrigPos
  921.                 v.PhysicsObjects[i].Frozen = true
  922.             end
  923.             v.Pos = v.PhysicsObjects[0].Pos
  924.             v.Angle = v.PhysicsObjects[0].Angle
  925.             v.BuildDupeInfo.PosReset = v.Pos
  926.             v.BuildDupeInfo.AngleReset = v.Angle
  927.         else
  928.             for i,p in pairs(v.BuildDupeInfo.PhysicsObjects)do
  929.                 v.PhysicsObjects[i].Pos, v.PhysicsObjects[i].Angle = LocalToWorld(p.Pos + proppos, p.Angle, Position, AngleOffset)
  930.                 v.PhysicsObjects[i].Frozen = true
  931.             end
  932.             v.Pos = v.PhysicsObjects[0].Pos
  933.             v.BuildDupeInfo.PosReset = v.Pos
  934.             v.Angle = v.PhysicsObjects[0].Angle
  935.             v.BuildDupeInfo.AngleReset = v.Angle
  936.         end
  937.  
  938.         local Ent = CreateEntityFromTable(v, Player)
  939.  
  940.         if Ent then
  941.             if(Player)then Player:AddCleanup( "AdvDupe2", Ent ) end
  942.             Ent.BoneMods = table.Copy( v.BoneMods )
  943.             Ent.EntityMods = table.Copy( v.EntityMods )
  944.             Ent.PhysicsObjects = table.Copy( v.PhysicsObjects )
  945.             if(v.CollisionGroup)then Ent:SetCollisionGroup(v.CollisionGroup) end
  946.             ApplyEntityModifiers( Player, Ent )
  947.             ApplyBoneModifiers( Player, Ent )
  948.             Ent:SetNotSolid(true)
  949.         elseif(Ent==false)then
  950.             Ent = nil
  951.             ConstraintList = {}
  952.             break
  953.         else
  954.             Ent = nil
  955.         end
  956.         CreatedEntities[k] = Ent
  957.     end
  958.  
  959.     local CreatedConstraints = {}
  960.     local Entity
  961.     --
  962.     -- Create constraints
  963.     --
  964.     for k, Constraint in pairs( ConstraintList ) do
  965.         Entity = CreateConstraintFromTable( Constraint, CreatedEntities, EntityList, Player )
  966.         if(IsValid(Entity))then
  967.             table.insert( CreatedConstraints, Entity )
  968.         end
  969.     end
  970.  
  971.     if(Player)then
  972.  
  973.         undo.Create "AdvDupe2_Paste"
  974.             for _,v in pairs( CreatedEntities ) do
  975.                 --If the entity has a PostEntityPaste function tell it to use it now
  976.                 if v.PostEntityPaste then
  977.                     local status, valid = pcall(v.PostEntityPaste, v, Player, v, CreatedEntities)
  978.                     if(not status)then
  979.                         print("AD2 PostEntityPaste Error: "..tostring(valid))
  980.                     end
  981.                 end
  982.                 v:GetPhysicsObject():EnableMotion(false)
  983.  
  984.                 if(EntityList[_].BuildDupeInfo.DupeParentID and Parenting)then
  985.                     v:SetParent(CreatedEntities[EntityList[_].BuildDupeInfo.DupeParentID])
  986.                 end
  987.                 v:SetNotSolid(false)
  988.                 undo.AddEntity( v )
  989.             end
  990.             undo.SetPlayer( Player )
  991.         undo.Finish()
  992.  
  993.         //if(Tool)then AdvDupe2.FinishPasting(Player, true) end
  994.     else
  995.  
  996.         for _,v in pairs( CreatedEntities ) do
  997.                 --If the entity has a PostEntityPaste function tell it to use it now
  998.             if v.PostEntityPaste then
  999.                 local status, valid = pcall(v.PostEntityPaste, v, Player, v, CreatedEntities)
  1000.                 if(not status)then
  1001.                     print("AD2 PostEntityPaste Error: "..tostring(valid))
  1002.                 end
  1003.             end
  1004.             v:GetPhysicsObject():EnableMotion(false)
  1005.  
  1006.             if(EntityList[_].BuildDupeInfo.DupeParentID and Parenting)then
  1007.                 v:SetParent(CreatedEntities[EntityList[_].BuildDupeInfo.DupeParentID])
  1008.             end
  1009.  
  1010.             v:SetNotSolid(false)
  1011.         end
  1012.     end
  1013.     DisablePropCreateEffect = nil
  1014.     hook.Call("AdvDupe_FinishPasting", nil, {{EntityList=EntityList, CreatedEntities=CreatedEntities, ConstraintList=ConstraintList, CreatedConstraints=CreatedConstraints, HitPos=OrigPos or Position}}, 1)
  1015.    
  1016.     return CreatedEntities, CreatedConstraints
  1017. end
  1018.  
  1019. local ticktotal = 0
  1020. local function AdvDupe2_Spawn()
  1021.    
  1022.     ticktotal = ticktotal + AdvDupe2.SpawnRate
  1023.     if(ticktotal<1)then
  1024.         return
  1025.     end
  1026.    
  1027.     ticktotal = ticktotal - 1
  1028.        
  1029.    
  1030.     local Queue = AdvDupe2.JobManager.Queue[AdvDupe2.JobManager.CurrentPlayer]
  1031.  
  1032.     if(not IsValid(Queue.Player))then
  1033.         table.remove(AdvDupe2.JobManager.Queue, AdvDupe2.JobManager.CurrentPlayer)
  1034.         if(#AdvDupe2.JobManager.Queue==0)then
  1035.             hook.Remove("Tick", "AdvDupe2_Spawning")
  1036.             DisablePropCreateEffect = nil
  1037.             AdvDupe2.JobManager.PastingHook = false
  1038.         end
  1039.         return
  1040.     end
  1041.  
  1042.     if(Queue.Entity)then
  1043.         if(Queue.Current==1)then
  1044.             AdvDupe2.InitProgressBar(Queue.Player,"Pasting:")
  1045.             Queue.Player.AdvDupe2.Queued = false
  1046.         end
  1047.         local newpos
  1048.         if(Queue.Current>#Queue.SortedEntities)then
  1049.             Queue.Entity = false
  1050.             Queue.Constraint = true
  1051.             Queue.Current = 1
  1052.             return
  1053.         end
  1054.         if(not Queue.SortedEntities[Queue.Current])then Queue.Current = Queue.Current+1 return end
  1055.  
  1056.         local k = Queue.SortedEntities[Queue.Current]
  1057.         local v = Queue.EntityList[k]
  1058.  
  1059.         if(not v.BuildDupeInfo)then v.BuildDupeInfo={} end
  1060.         if(v.LocalPos)then
  1061.             for i,p in pairs(v.PhysicsObjects) do
  1062.                 v.PhysicsObjects[i] = {Pos=v.LocalPos, Angle=v.LocalAngle}
  1063.             end
  1064.         end
  1065.  
  1066.         v.BuildDupeInfo.PhysicsObjects = table.Copy(v.PhysicsObjects)
  1067.         proppos = v.PhysicsObjects[0].Pos
  1068.         v.BuildDupeInfo.PhysicsObjects[0].Pos = Vector(0,0,0)
  1069.         if( Queue.OrigPos )then
  1070.             for i,p in pairs(v.BuildDupeInfo.PhysicsObjects) do
  1071.                 v.PhysicsObjects[i].Pos = p.Pos + proppos + Queue.OrigPos
  1072.                 v.PhysicsObjects[i].Frozen = true
  1073.             end
  1074.             v.Pos = v.PhysicsObjects[0].Pos
  1075.             v.Angle = v.PhysicsObjects[0].Angle
  1076.             v.BuildDupeInfo.PosReset = v.Pos
  1077.             v.BuildDupeInfo.AngleReset = v.Angle
  1078.         else
  1079.             for i,p in pairs(v.BuildDupeInfo.PhysicsObjects)do
  1080.                 v.PhysicsObjects[i].Pos, v.PhysicsObjects[i].Angle = LocalToWorld(p.Pos + proppos, p.Angle, Queue.PositionOffset, Queue.AngleOffset)
  1081.                 v.PhysicsObjects[i].Frozen = true
  1082.             end
  1083.             v.Pos = v.PhysicsObjects[0].Pos
  1084.             v.BuildDupeInfo.PosReset = v.Pos
  1085.             v.Angle = v.PhysicsObjects[0].Angle
  1086.             v.BuildDupeInfo.AngleReset = v.Angle
  1087.         end
  1088.  
  1089.         local Ent = CreateEntityFromTable(v, Queue.Player)
  1090.         if Ent then
  1091.             Queue.Player:AddCleanup( "AdvDupe2", Ent )
  1092.             Ent.BoneMods = table.Copy( v.BoneMods )
  1093.             Ent.EntityMods = table.Copy( v.EntityMods )
  1094.             Ent.PhysicsObjects = table.Copy( v.PhysicsObjects )
  1095.  
  1096.             local Phys = Ent:GetPhysicsObject()
  1097.             if(IsValid(Phys))then Phys:EnableMotion(false) end
  1098.             if(not Queue.DisableProtection)then Ent:SetNotSolid(true) end
  1099.             if(v.CollisionGroup)then Ent:SetCollisionGroup(v.CollisionGroup) end
  1100.         elseif(Ent==false)then
  1101.             Ent = nil
  1102.             Queue.Entity = false
  1103.             Queue.Constraint = true
  1104.             Queue.Current = 1
  1105.             Queue.ConstraintList = {}
  1106.         else
  1107.             Ent = nil
  1108.         end
  1109.         Queue.CreatedEntities[ k ] = Ent
  1110.        
  1111.         AdvDupe2.UpdateProgressBar(Queue.Player, math.floor((Queue.Percent*Queue.Current)*100))
  1112.         Queue.Current = Queue.Current+1
  1113.         if(Queue.Current>#Queue.SortedEntities)then
  1114.            
  1115.             for _,Ent in pairs(Queue.CreatedEntities)do
  1116.                 ApplyEntityModifiers( Queue.Player, Ent )
  1117.                 ApplyBoneModifiers( Queue.Player, Ent )
  1118.            
  1119.                 --If the entity has a PostEntityPaste function tell it to use it now
  1120.                 if Ent.PostEntityPaste then
  1121.                     local status, valid = pcall(Ent.PostEntityPaste, Ent, Queue.Player, Ent, Queue.CreatedEntities)
  1122.                     if(not status)then
  1123.                         print("AD2 PostEntityPaste Error: "..tostring(valid))
  1124.                     end
  1125.                 end
  1126.             end
  1127.        
  1128.             Queue.Entity = false
  1129.             Queue.Constraint = true
  1130.             Queue.Current = 1
  1131.         end
  1132.  
  1133.         if(#AdvDupe2.JobManager.Queue>=AdvDupe2.JobManager.CurrentPlayer+1)then  
  1134.             AdvDupe2.JobManager.CurrentPlayer = AdvDupe2.JobManager.CurrentPlayer+1
  1135.         else  
  1136.             AdvDupe2.JobManager.CurrentPlayer = 1
  1137.         end
  1138.     else
  1139.         if(#Queue.ConstraintList>0)then
  1140.  
  1141.             if(#AdvDupe2.JobManager.Queue==0)then
  1142.                 hook.Remove("Tick", "AdvDupe2_Spawning")
  1143.                 DisablePropCreateEffect = nil
  1144.                 AdvDupe2.JobManager.PastingHook = false
  1145.             end
  1146.             if(not Queue.ConstraintList[Queue.Current])then Queue.Current = Queue.Current+1 return end
  1147.  
  1148.             local Entity = CreateConstraintFromTable( Queue.ConstraintList[Queue.Current], Queue.CreatedEntities, Queue.EntityList, Queue.Player, true )
  1149.             if IsValid(Entity) then
  1150.                 table.insert( Queue.CreatedConstraints, Entity )
  1151.             end
  1152.         elseif(table.Count(Queue.ConstraintList)>0)then
  1153.             local tbl = {}
  1154.             for k,v in pairs(Queue.ConstraintList)do
  1155.                 table.insert(tbl, v)
  1156.             end
  1157.             Queue.ConstraintList = tbl
  1158.             Queue.Current=0
  1159.         end
  1160.  
  1161.         AdvDupe2.UpdateProgressBar(Queue.Player, math.floor((Queue.Percent*(Queue.Current+Queue.Plus))*100))
  1162.         Queue.Current = Queue.Current+1
  1163.  
  1164.         if(Queue.Current>#Queue.ConstraintList)then
  1165.  
  1166.             local unfreeze = tobool(Queue.Player:GetInfo("advdupe2_paste_unfreeze")) or false
  1167.             local preservefrozenstate = tobool(Queue.Player:GetInfo("advdupe2_preserve_freeze")) or false
  1168.  
  1169.             //Remove the undo for stopping pasting
  1170.             local undos = undo.GetTable()[Queue.Player:UniqueID()]
  1171.             local str = "AdvDupe2_"..Queue.Player:UniqueID()
  1172.             for i=#undos, 1, -1 do
  1173.                 if(undos[i] and undos[i].Name == str)then
  1174.                     undos[i] = nil
  1175.                     umsg.Start( "Undone", Queue.Player )
  1176.                         umsg.Long( i )
  1177.                     umsg.End()
  1178.                     break
  1179.                 end
  1180.             end
  1181.  
  1182.             undo.Create "AdvDupe2"
  1183.                 local phys
  1184.                 local edit
  1185.                 local mass
  1186.                 for _,v in pairs( Queue.CreatedEntities ) do
  1187.                     if(not IsValid(v))then
  1188.                         v = nil
  1189.                     else
  1190.                         edit = true
  1191.                         if(Queue.EntityList[_].BuildDupeInfo.DupeParentID~=nil and Queue.Parenting)then
  1192.                             v:SetParent(Queue.CreatedEntities[Queue.EntityList[_].BuildDupeInfo.DupeParentID])
  1193.                             if(v.Constraints~=nil)then
  1194.                                 for i,c in pairs(v.Constraints)do
  1195.                                     if(c and constraints[c.Type])then
  1196.                                         edit=false
  1197.                                         break
  1198.                                     end
  1199.                                 end
  1200.                             end
  1201.                             if(edit and IsValid(v:GetPhysicsObject()))then
  1202.                                 mass = v:GetPhysicsObject():GetMass()
  1203.                                 v:PhysicsInitShadow(false, false)
  1204.                                 v:SetCollisionGroup(COLLISION_GROUP_WORLD)
  1205.                                 v:GetPhysicsObject():EnableMotion(false)
  1206.                                 v:GetPhysicsObject():Sleep()
  1207.                                 v:GetPhysicsObject():SetMass(mass)
  1208.                             end
  1209.                         else
  1210.                             edit=false
  1211.                         end
  1212.  
  1213.                         if(unfreeze)then
  1214.                             for i=0, v:GetPhysicsObjectCount() do
  1215.                                 phys = v:GetPhysicsObjectNum(i)
  1216.                                 if(IsValid(phys))then
  1217.                                     phys:EnableMotion(true) //Unfreeze the entitiy and all of its objects
  1218.                                     phys:Wake()
  1219.                                 end
  1220.                             end
  1221.                         elseif(preservefrozenstate)then
  1222.                             for i=0, v:GetPhysicsObjectCount() do
  1223.                                 phys = v:GetPhysicsObjectNum(i)
  1224.                                 if(IsValid(phys))then
  1225.                                     if(Queue.EntityList[_].BuildDupeInfo.PhysicsObjects[i].Frozen)then
  1226.                                         phys:EnableMotion(true) //Restore the entity and all of its objects to their original frozen state
  1227.                                         phys:Wake()
  1228.                                     else
  1229.                                         Queue.Player:AddFrozenPhysicsObject( v, phys )
  1230.                                     end
  1231.                                 end
  1232.                             end
  1233.                         else
  1234.                             for i=0, v:GetPhysicsObjectCount() do
  1235.                                 phys = v:GetPhysicsObjectNum(i)
  1236.                                 if(IsValid(phys))then
  1237.                                     if(phys:IsMoveable())then
  1238.                                         phys:EnableMotion(false)    //Freeze the entitiy and all of its objects
  1239.                                         Queue.Player:AddFrozenPhysicsObject( v, phys )
  1240.                                     end
  1241.                                 end
  1242.                             end
  1243.                         end
  1244.  
  1245.                         if(not edit or not Queue.DisableParents)then
  1246.                             v:SetNotSolid(false)
  1247.                         end
  1248.  
  1249.                         undo.AddEntity( v )
  1250.                     end
  1251.                 end
  1252.                 undo.SetCustomUndoText("Undone "..(Queue.Name or "Advanced Duplication"))
  1253.                 undo.SetPlayer( Queue.Player )
  1254.             undo.Finish()
  1255.  
  1256.             hook.Call("AdvDupe_FinishPasting", nil, {{EntityList=Queue.EntityList, CreatedEntities=Queue.CreatedEntities, ConstraintList=Queue.ConstraintList, CreatedConstraints=Queue.CreatedConstraints, HitPos=Queue.PositionOffset}}, 1)
  1257.             AdvDupe2.FinishPasting(Queue.Player, true)
  1258.  
  1259.             table.remove(AdvDupe2.JobManager.Queue, AdvDupe2.JobManager.CurrentPlayer)
  1260.             if(#AdvDupe2.JobManager.Queue==0)then
  1261.                 hook.Remove("Tick", "AdvDupe2_Spawning")
  1262.                 DisablePropCreateEffect = nil
  1263.                 AdvDupe2.JobManager.PastingHook = false
  1264.             end
  1265.         end
  1266.         if(#AdvDupe2.JobManager.Queue>=AdvDupe2.JobManager.CurrentPlayer+1)then  
  1267.             AdvDupe2.JobManager.CurrentPlayer = AdvDupe2.JobManager.CurrentPlayer+1
  1268.         else  
  1269.             AdvDupe2.JobManager.CurrentPlayer = 1
  1270.         end
  1271.     end
  1272. end
  1273.  
  1274. local function ErrorCatchSpawning()
  1275.  
  1276.     local status, error = pcall(AdvDupe2_Spawn)
  1277.  
  1278.     if(not status)then
  1279.         //PUT ERROR LOGGING HERE
  1280.        
  1281.         if(not AdvDupe2.JobManager.Queue)then
  1282.             print("[AdvDupe2Notify]\t"..error)
  1283.             AdvDupe2.JobManager.Queue = {}
  1284.             return
  1285.         end
  1286.        
  1287.         local Queue = AdvDupe2.JobManager.Queue[AdvDupe2.JobManager.CurrentPlayer]
  1288.         if(not Queue)then
  1289.             print("[AdvDupe2Notify]\t"..error)
  1290.             return
  1291.         end
  1292.        
  1293.         if(IsValid(Queue.Player))then
  1294.             AdvDupe2.Notify(Queue.Player, error)
  1295.            
  1296.             local undos = undo.GetTable()[Queue.Player:UniqueID()]
  1297.             local str = "AdvDupe2_"..Queue.Player:UniqueID()
  1298.             for i=#undos, 1, -1 do
  1299.                 if(undos[i] and undos[i].Name == str)then
  1300.                     undos[i] = nil
  1301.                     umsg.Start( "Undone", Queue.Player )
  1302.                         umsg.Long( i )
  1303.                     umsg.End()
  1304.                     break
  1305.                 end
  1306.             end
  1307.         else
  1308.             print("[AdvDupe2Notify]\t"..error)
  1309.         end
  1310.  
  1311.         for k,v in pairs(Queue.CreatedEntities)do
  1312.             if(IsValid(v))then v:Remove() end
  1313.         end
  1314.  
  1315.         if(IsValid(Queue.Player))then
  1316.             AdvDupe2.FinishPasting(Queue.Player, true)
  1317.         end
  1318.  
  1319.         table.remove(AdvDupe2.JobManager.Queue, AdvDupe2.JobManager.CurrentPlayer)
  1320.  
  1321.         if(#AdvDupe2.JobManager.Queue==0)then
  1322.             hook.Remove("Tick", "AdvDupe2_Spawning")
  1323.             DisablePropCreateEffect = nil
  1324.             AdvDupe2.JobManager.PastingHook = false
  1325.         else
  1326.             if(#Queue<AdvDupe2.JobManager.CurrentPlayer)then    
  1327.                 AdvDupe2.JobManager.CurrentPlayer = 1
  1328.             end
  1329.         end
  1330.  
  1331.     end
  1332. end
  1333.  
  1334. local function RemoveSpawnedEntities(tbl, i)
  1335.     if(not AdvDupe2.JobManager.Queue[i])then return end //Without this some errors come up, double check the errors without this line
  1336.  
  1337.     for k,v in pairs(AdvDupe2.JobManager.Queue[i].CreatedEntities)do
  1338.         if(IsValid(v))then
  1339.             v:Remove()
  1340.         end
  1341.     end
  1342.  
  1343.     AdvDupe2.FinishPasting(AdvDupe2.JobManager.Queue[i].Player, false)
  1344.     table.remove(AdvDupe2.JobManager.Queue, i)
  1345.     if(#AdvDupe2.JobManager.Queue==0)then
  1346.         hook.Remove("Tick", "AdvDupe2_Spawning")
  1347.         DisablePropCreateEffect = nil
  1348.         AdvDupe2.JobManager.PastingHook = false
  1349.     end
  1350. end
  1351.  
  1352. function AdvDupe2.InitPastingQueue(Player, PositionOffset, AngleOffset, OrigPos, Constrs, Parenting, DisableParents, DisableProtection)
  1353.    
  1354.     local i = #AdvDupe2.JobManager.Queue+1
  1355.     AdvDupe2.JobManager.Queue[i] = {}
  1356.     local Queue = AdvDupe2.JobManager.Queue[i]
  1357.     Queue.Player = Player
  1358.     Queue.SortedEntities = {}
  1359.     Queue.EntityList = table.Copy(Player.AdvDupe2.Entities)
  1360.     if(Constrs)then
  1361.         Queue.ConstraintList = table.Copy(Player.AdvDupe2.Constraints)
  1362.     else
  1363.         Queue.ConstraintList = {}
  1364.     end
  1365.     Queue.OrigPos = OrigPos
  1366.     for k,v in pairs(Player.AdvDupe2.Entities)do
  1367.         table.insert(Queue.SortedEntities, k)
  1368.     end
  1369.  
  1370.     if(Player.AdvDupe2.Name)then
  1371.         print("[AdvDupe2NotifyPaste]\t Player: "..Player:Nick().." Pasted File, "..Player.AdvDupe2.Name.." with, "..#Queue.SortedEntities.." Entities and "..#Player.AdvDupe2.Constraints.." Constraints.")
  1372.     else
  1373.         print("[AdvDupe2NotifyPaste]\t Player: "..Player:Nick().." Pasted, "..#Queue.SortedEntities.." Entities and "..#Player.AdvDupe2.Constraints.." Constraints.")
  1374.     end
  1375.    
  1376.     Queue.Current = 1
  1377.     Queue.Name = Player.AdvDupe2.Name
  1378.     Queue.Entity = true
  1379.     Queue.Constraint = false
  1380.     Queue.Parenting = Parenting
  1381.     Queue.DisableParents = DisableParents
  1382.     Queue.DisableProtection = DisableProtection
  1383.     Queue.CreatedEntities = {}
  1384.     Queue.CreatedConstraints = {}
  1385.     Queue.PositionOffset = PositionOffset or Vector(0,0,0)
  1386.     Queue.AngleOffset = AngleOffset or Angle(0,0,0)
  1387.     Queue.Plus = #Queue.SortedEntities
  1388.     Queue.Percent = 1/(#Queue.SortedEntities+#Queue.ConstraintList)
  1389.     AdvDupe2.InitProgressBar(Player,"Queued:")
  1390.     Player.AdvDupe2.Queued = true
  1391.     if(not AdvDupe2.JobManager.PastingHook)then
  1392.         DisablePropCreateEffect = true
  1393.         hook.Add("Tick", "AdvDupe2_Spawning", ErrorCatchSpawning)
  1394.         AdvDupe2.JobManager.PastingHook = true
  1395.         AdvDupe2.JobManager.CurrentPlayer = 1
  1396.     end
  1397.  
  1398.     undo.Create("AdvDupe2_"..Player:UniqueID())
  1399.         undo.SetPlayer(Player)
  1400.         undo.SetCustomUndoText(string.format("Undone Advanced Duplication \"%s\"",Player.AdvDupe2.Name or ""))
  1401.         undo.AddFunction(RemoveSpawnedEntities, i)
  1402.     undo.Finish()
  1403. end
  1404.  
  1405. --make sure we have ent lists when reloading
  1406. LoadSents()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement