Advertisement
Guest User

Untitled

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