Guest User

Time Bomb Entity Code

a guest
Apr 17th, 2023
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 39.11 KB | None | 0 0
  1. AddCSLuaFile( "cl_init.lua" )
  2. AddCSLuaFile( "shared.lua" )
  3. include( "shared.lua" )
  4.  
  5. local bIsPlayingZombies = engine.ActiveGamemode() == "nzombies"
  6. if bIsPlayingZombies then
  7.     local nzRound = nzRound or AddNZModule("Round")
  8. end
  9.  
  10. function ENT:SpawnFunction( ply, tr )
  11.     if ( not tr.Hit ) then
  12.         return
  13.     end
  14.     -- local SpawnPos = tr.HitPos + tr.HitNormal * 16
  15.     local ent = ents.Create( "cod-timebomb" )
  16.     ent:SetPos( Vector(0,0,0) )
  17.     ent:Spawn()
  18.     ent:Activate()
  19.  
  20.     ent:SetOwner(ply) -- Disables collision between the C4 and its owner
  21.     return ent
  22. end
  23.  
  24. local function CreateTimeBombConfig()
  25.     if file.Read("codzombies/timebomb.txt") == nil then
  26.         local config =
  27. [[Time Bomb programmed by Hoff
  28. The time bomb has an internal blacklist, but you can add additional entities, starting on line 5. Format is entity_class.
  29. Use notepad++ or Sublime Text to edit this file to avoid format errors.
  30.  
  31. ]]
  32.  
  33.         print("Time Bomb file non existant, creating 'data/codzombies/timebomb.txt'\n")
  34.  
  35.         if file.Read("codzombies/mysterybox.txt") == nil then
  36.             file.CreateDir("codzombies")
  37.         end
  38.  
  39.         file.Write("codzombies/timebomb.txt",config)
  40.     end
  41. end
  42.  
  43. hook.Add("Initialize","CreateTimeBombConfig",function()
  44.     CreateTimeBombConfig()
  45. end)
  46.  
  47. ENT.ArchivedWorld = ""
  48. ENT.ArchivedClaymores = {}
  49. ENT.ArchivedC4s = {}
  50. ENT.ArchivedTacInserts = {}
  51.  
  52. if bIsPlayingZombies then
  53.     ENT.StoredRound = -1
  54.     ENT.ZombiesKilled = 0
  55. end
  56.  
  57. ENT.EntityBlacklist =
  58. {
  59.     "env_fire",
  60.     "entityflame",
  61.     "_firesmoke",
  62.     "gmod_hands",
  63.     "info_player_start",
  64.     "predicted_viewmodel",
  65.     "cod-timebomb",
  66.     "seal6-claymore-bo2-ent",
  67.     "seal6-claymore-ent",
  68.     "cod-c4",
  69.     "cod-tac-insert",
  70.     "zombies_box_qmarks",
  71.     "zombies_box_weapon",
  72.     "zombies_teddybear",
  73.     "zombies_mysterybox",
  74.     "zombies_mysterybox_location",
  75.     "zombies_mysterybox_beam",
  76.     "nz_spawn_zombie_normal",
  77.     "logic_waves",
  78.     "logic_points",
  79.     "power_box",
  80.     "stinky_lever",
  81.     "nz_script_prop",
  82.     "prop_buys",
  83.     "nz_shootable",
  84.     "random_box",
  85.     "sent_sakarias_carwheel",
  86.     "sent_sakarias_carwheel_punked",
  87.     "sent_sakarias_lightentity",
  88.     "base_anim"
  89. }
  90.  
  91. function ENT:StoreOwnedProps()
  92.     self.ArchivedClaymores = {}
  93.     self.ArchivedC4s = {}
  94.     self.ArchivedTacInserts = {}
  95.     self.ArchivedWorld = self:GetArchivedWorld()
  96.  
  97.     self:SetNWInt("SaveTime", os.time())
  98.     if IsValid(self.ThisTrigger) then
  99.         self.ThisTrigger:CallOnClient("UpdateRelativeClock")
  100.     end
  101.  
  102.     if bIsPlayingZombies then
  103.         timer.Simple(0.15, function()
  104.             net.Start( "DisplayTimeBombRound" )
  105.                 net.WriteInt(nzRound:GetNumber(), 16)
  106.                 net.WriteEntity(self.ThisTrigger)
  107.             net.Send(self.BombOwner)
  108.         end)
  109.     end
  110. end
  111.  
  112. function ENT:RewindProps()
  113.  
  114.     self:SetParent()
  115.  
  116.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  117.  
  118.     if not bShouldSaveOwnerOnly then
  119.         for _, ply in ipairs(player.GetHumans()) do
  120.             ply:RemoveFlags(FL_NOTARGET)
  121.             ply:UnLock()
  122.         end
  123.     else
  124.         self.BombOwner:RemoveFlags(FL_NOTARGET)
  125.         self.BombOwner:UnLock()
  126.     end
  127.  
  128.     if IsValid(self.BombOwner) then
  129.         self:LoadArchivedWorld()
  130.     end
  131.  
  132.     self:Remove()
  133. end
  134.  
  135. function ENT:LoadArchivedWorld()
  136.     -- Strip off any crap before the start char..
  137.     local strMapContents = self.ArchivedWorld
  138.     local startchar = string.find( strMapContents, '' )
  139.     if ( startchar != nil ) then
  140.         strMapContents = string.sub( strMapContents, startchar )
  141.     end
  142.  
  143.     -- Stip off any crap after the end char..
  144.     strMapContents = strMapContents:reverse()
  145.     startchar = string.find( strMapContents, '' )
  146.     if ( startchar != nil ) then
  147.         strMapContents = string.sub( strMapContents, startchar )
  148.     end
  149.     strMapContents = strMapContents:reverse()
  150.     local tab = util.JSONToTable( strMapContents )
  151.     if ( !istable( tab ) ) then
  152.         -- Error loading save!
  153.         return false
  154.     end
  155.  
  156.     self:CleanupMap()
  157.  
  158.     DisablePropCreateEffect = true
  159.     duplicator.RemoveMapCreatedEntities()
  160.  
  161.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  162.     if not bShouldSaveOwnerOnly then
  163.         for k, ply in ipairs(player.GetHumans()) do
  164.             ply:SendLua( "hook.Run( \"OnSpawnMenuClose\" )" )
  165.             ply:SendLua( "surface.PlaySound('hoff/zmb/timebomb/timebomb_activate_2.mp3')")
  166.             if tab.Players[tostring(ply:SteamID())] != nil then
  167.                 self:SetPlayerInfo( ply, tab.Players[tostring(ply:SteamID())] )
  168.             end
  169.         end
  170.     else
  171.         self.BombOwner:SendLua( "hook.Run( \"OnSpawnMenuClose\" )" )
  172.         if GetConVar("TimeBomb_InstantTravel"):GetBool() then
  173.             self.BombOwner:SendLua( "surface.PlaySound('hoff/zmb/timebomb/timebomb_activate_2.mp3')")
  174.         end
  175.         if tab.Players[tostring(self.BombOwner:SteamID())] != nil then
  176.             self:SetPlayerInfo( self.BombOwner, tab.Players[tostring(self.BombOwner:SteamID())] )
  177.         end
  178.     end
  179.  
  180.     if bIsPlayingZombies then
  181.         nzRound:SetNumber(self.StoredRound - 1)
  182.         nzRound:SetZombiesKilled(self.ZombiesKilled)
  183.         nzRound:Prepare()
  184.  
  185.         local specint = GetConVar("nz_round_special_interval"):GetInt() or 6
  186.         nzRound:SetNextSpecialRound( math.ceil(self.StoredRound / specint) * specint)
  187.     end
  188.  
  189.     if istable( self.ArchivedClaymores ) and not table.IsEmpty(self.ArchivedClaymores) then
  190.         for k, ItClaymore in ipairs(self.ArchivedClaymores) do
  191.             local NewClaymore = ents.Create(ItClaymore.Class)
  192.             NewClaymore:SetPos(ItClaymore.Location)
  193.             NewClaymore:SetAngles(ItClaymore.Rotation)
  194.             NewClaymore:SetNWString("OwnerID", ItClaymore.OwnerID)
  195.             --NewClaymore.ClayParent = nil
  196.             NewClaymore.ClayOwner = ItClaymore.ClayOwner
  197.             --NewClaymore.Kids = nil
  198.             NewClaymore:Spawn()
  199.             NewClaymore:Activate()
  200.         end
  201.     end
  202.  
  203.     if istable( self.ArchivedC4s ) and not table.IsEmpty(self.ArchivedC4s) then
  204.         for k, ItC4 in ipairs(self.ArchivedC4s) do
  205.             local NewC4 = ents.Create("cod-c4")
  206.             NewC4:SetPos(ItC4.Location)
  207.             NewC4:SetAngles(ItC4.Rotation)
  208.             NewC4:SetNWString("OwnerID", ItC4.OwnerID)
  209.             NewC4.C4Owner = ItC4.C4Owner
  210.             NewC4.ThisTrigger = ItC4.ThisTrigger
  211.             NewC4.ExplodedViaWorld = ItC4.ExplodedViaWorld
  212.             NewC4.QueuedForExplode = ItC4.QueuedForExplode
  213.             NewC4.UniqueExplodeTimer = ItC4.UniqueExplodeTimer
  214.             NewC4.Stuck = ItC4.Stuck
  215.             NewC4.Hit = ItC4.Hit
  216.             NewC4:Spawn()
  217.             table.insert(NewC4.C4Owner.C4s, NewC4)
  218.  
  219.             if IsValid(NewC4) and ItC4.Hit then
  220.                 NewC4:SetCollisionGroup(COLLISION_GROUP_WEAPON)
  221.                 NewC4:SetSolid(SOLID_VPHYSICS)
  222.                 NewC4:SetMoveType(MOVETYPE_NONE)
  223.                 NewC4:SetNWBool("CanUse", true)
  224.                 NewC4:SetNWBool("Hit", ItC4.Hit)
  225.             end
  226.  
  227.             NewC4:Activate()
  228.  
  229.             if IsValid(ItC4.PhysData) and ItC4.Hit then
  230.                 NewC4:SetParent(ItC4.PhysData.HitEntity)
  231.             end
  232.         end
  233.     end
  234.  
  235.     if istable( self.ArchivedTacInserts ) and not table.IsEmpty(self.ArchivedTacInserts) then
  236.         for k, ItInsert in ipairs(self.ArchivedTacInserts) do
  237.             local NewInsert = ents.Create("cod-tac-insert")
  238.             NewInsert:SetPos(ItInsert.Location)
  239.             NewInsert:SetAngles(ItInsert.Rotation)
  240.             NewInsert.TacOwner = ItInsert.TacOwner
  241.             NewInsert.Owner = ItInsert.Owner
  242.             NewInsert:SetOwner(ItInsert.Owner)
  243.             NewInsert:SetNWString("TacOwner", ItInsert.NwTacOwner)
  244.             NewInsert:SetNWString("OwnerID", ItInsert.OwnerID)
  245.             NewInsert:Spawn()
  246.             NewInsert:Activate()
  247.             table.insert(NewInsert.TacOwner.Tacs, NewInsert)
  248.         end
  249.     end
  250.  
  251.     local TotalTable = {Constraints = {}, Entities = {}}
  252.  
  253.     local function BetterInherit(t, base)
  254.         for k, v in pairs(base) do
  255.             if t[k] == nil then
  256.                 t[k] = v
  257.             elseif v.IsNextBot then
  258.                 local i = k + 1
  259.                 while t[i] ~= nil and t[i].IsNextBot do
  260.                     i = i + 1
  261.                 end
  262.                 t[i] = v
  263.             end
  264.         end
  265.  
  266.         return t
  267.     end
  268.  
  269.     for k, it in ipairs(tab) do
  270.         if istable(it.Entities) then
  271.             BetterInherit(TotalTable.Entities, it.Entities)
  272.         end
  273.         if istable(it.Constraints) then
  274.             BetterInherit(TotalTable.Constraints, it.Constraints)
  275.         end
  276.     end
  277.     self:PasteArchive( nil, TotalTable.Entities, TotalTable.Constraints )
  278.  
  279.     for k,grenade in pairs(ents.FindByClass("npc_grenade_frag")) do
  280.         grenade:Fire("settimer",3)
  281.     end
  282.  
  283.     DisablePropCreateEffect = nil
  284. end
  285.  
  286. function ENT:CleanupMap()
  287.  
  288.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  289.     if not bShouldSaveOwnerOnly then
  290.         net.Start("CleanupTimebombRagdolls")
  291.         net.Broadcast()
  292.  
  293.         self:CleanupWeapons()
  294.  
  295.         game.CleanUpMap(false, self.EntityBlacklist)
  296.     else
  297.         self:CleanupPersonalProps(self.BombOwner)
  298.     end
  299.  
  300.  
  301.     for k, timebomb in pairs(ents.FindByClass("cod-timebomb")) do
  302.         if timebomb ~= self then
  303.             timebomb:Remove()
  304.         end
  305.     end
  306. end
  307.  
  308. function ENT:CleanupPersonalProps(ply)
  309.     if ( !IsValid( ply ) ) then
  310.         return
  311.     end
  312.  
  313.     local id = ply:UniqueID()
  314.  
  315.     local CleanupList = cleanup.GetList()
  316.  
  317.     if ( !CleanupList[ id ] ) then
  318.         return
  319.     end
  320.  
  321.     local count = 0
  322.  
  323.     for key, val in pairs( CleanupList[ id ] ) do
  324.  
  325.         for _, ent in pairs( val ) do
  326.  
  327.             local bDoesPlayerOwnProp = IsValid(ent) and (ent:GetOwner() == ply or self:GetPropOwningPlayer(ent) == ply)
  328.             if ( IsValid( ent ) and not table.HasValue(self.EntityBlacklist, ent:GetClass()) and bDoesPlayerOwnProp) then
  329.  
  330.                 local Ents = {}
  331.                 local Constraints = {}
  332.                 if not ent:IsNextBot() then
  333.                     self:GetEntityConstraints( ent, Ents, Constraints )
  334.                 else
  335.                     Ents = {Ent}
  336.                 end
  337.  
  338.                 for k,v in pairs(Ents) do
  339.                     v:Remove()
  340.                 end
  341.  
  342.             end
  343.             count = count + 1
  344.  
  345.         end
  346.  
  347.         table.Empty( val )
  348.  
  349.     end
  350.  
  351. end
  352.  
  353. function ENT:GetPropOwningPlayer(ent)
  354.     if !IsValid(ent) or bIsPlayingZombies then
  355.         return nil
  356.     end
  357.     if ent:IsNextBot() then
  358.         return ent:GetCreator()
  359.     end
  360.     if !istable(ent:GetTable().OnDieFunctions) then
  361.         return nil
  362.     end
  363.  
  364.     local undoKey
  365.     for key, _ in pairs(ent:GetTable().OnDieFunctions) do
  366.         if string.find(key, "undo") then
  367.             undoKey = key
  368.             break
  369.         end
  370.     end
  371.  
  372.     if undoKey then
  373.         local player = nil
  374.         local args = ent:GetTable().OnDieFunctions[undoKey].Args
  375.  
  376.         for i, arg in ipairs(args) do
  377.             if type(arg) == "Player" then
  378.                 player = arg
  379.                 break
  380.             end
  381.         end
  382.  
  383.         if player then
  384.             return player
  385.         end
  386.     end
  387.  
  388.     return nil
  389. end
  390.  
  391. function ENT:GetArchivedWorld()
  392.  
  393.     local SavedProps = {}
  394.     local SavedIndexes = {}
  395.  
  396.     local ClassBlacklist = self.EntityBlacklist
  397.  
  398.     local ZombiesConfig = file.Read("codzombies/timebomb.txt")
  399.     if ZombiesConfig then
  400.         local BrokenLines = string.Explode("\n", ZombiesConfig)
  401.  
  402.         for i = 5, #BrokenLines do
  403.             local ent_class = string.Trim(BrokenLines[i]) -- remove leading and trailing whitespaces
  404.             if ent_class != "" then -- if the line is not empty
  405.                 table.insert(ClassBlacklist, ent_class)
  406.             end
  407.         end
  408.     end
  409.  
  410.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  411.  
  412.     local Ents = ents.GetAll()
  413.     for index, prop in ipairs(Ents) do
  414.         if not IsValid(prop) or
  415.             not duplicator.IsAllowed( prop:GetClass() ) or
  416.             --not gmsave.ShouldSaveEntity( prop, prop:GetSaveTable() ) or
  417.             prop:IsConstraint() or
  418.             prop:IsWeapon() or
  419.             string.match(prop:GetClass(), "bulletpos") or
  420.             (prop:GetClass() == "prop_physics" and IsValid(prop:GetParent()) and prop:GetParent():GetClass() == "sent_sakarias_carwheel") or
  421.             table.HasValue(ClassBlacklist, prop:GetClass()) then
  422.  
  423.             continue
  424.         end
  425.         if bShouldSaveOwnerOnly and ((IsValid(prop:GetOwner()) and prop:GetOwner() ~= self.BombOwner) or (IsValid(self:GetPropOwningPlayer(prop)) and self:GetPropOwningPlayer(prop) ~= self.BombOwner)) then
  426.             continue
  427.         end
  428.  
  429.         -- Check if entity is already being copied
  430.         if not SavedIndexes[prop:EntIndex()] then
  431.             local connectedEntities = {}
  432.             local constraintTable = {}
  433.             if not prop:IsNextBot() then
  434.                 self:GetEntityConstraints(prop, connectedEntities, constraintTable)
  435.             else
  436.                 connectedEntities = {prop}
  437.             end
  438.             -- Check for connected entities that are already saved
  439.             local skipIteration = false
  440.             for k, connectedEnt in pairs(connectedEntities) do
  441.                 if SavedIndexes[connectedEnt:EntIndex()] then
  442.                     skipIteration = true
  443.                     break
  444.                 end
  445.             end
  446.  
  447.             if not skipIteration then
  448.                 local savedProp = self:CopyEntity(prop)
  449.                 table.insert(SavedProps, savedProp)
  450.                 SavedIndexes[prop:EntIndex()] = true
  451.                 for k, v in pairs(connectedEntities) do
  452.                     if not SavedIndexes[v:EntIndex()] then
  453.                         SavedIndexes[v:EntIndex()] = true
  454.                     end
  455.                 end
  456.             end
  457.         end
  458.     end
  459.  
  460. --[[
  461.     local Ents = ents.GetAll()
  462.     for index, prop in ipairs(Ents) do
  463.         if not IsValid(prop) or
  464.             not duplicator.IsAllowed( prop:GetClass() ) or
  465.             --not gmsave.ShouldSaveEntity( prop, prop:GetSaveTable() ) or
  466.             prop:IsConstraint() or
  467.             prop:IsWeapon() or
  468.             string.match(prop:GetClass(), "bulletpos") or
  469.             table.HasValue(ClassBlacklist, prop:GetClass()) then
  470.             continue
  471.         end
  472.         -- Check if entity is already being copied
  473.         if not table.HasValue(SavedIndexes, prop:EntIndex()) then
  474.             local connectedEntities = {}
  475.             local constraintTable = {}
  476.             if !prop:IsNextBot() then
  477.                 self:GetEntityConstraints(prop, connectedEntities, constraintTable)
  478.             else
  479.                 connectedEntities = {prop}
  480.             end
  481.             -- Check for connected entities that are already saved
  482.             local skipIteration = false
  483.             for k, connectedEnt in pairs(connectedEntities) do
  484.                 if table.HasValue(SavedIndexes, connectedEnt:EntIndex()) then
  485.                     skipIteration = true
  486.                     break
  487.                 end
  488.             end
  489.  
  490.             if not skipIteration then
  491.                 local savedProp = self:CopyEntity(prop)
  492.                 table.insert(SavedProps, savedProp)
  493.                 table.insert(SavedIndexes, prop:EntIndex())
  494.                 for k, v in pairs(connectedEntities) do
  495.                     if not table.HasValue(SavedIndexes, v:EntIndex()) then
  496.                         table.insert(SavedIndexes, v:EntIndex())
  497.                     end
  498.                 end
  499.             end
  500.         end
  501.     end
  502.     ]]
  503.     if bIsPlayingZombies then
  504.         self.StoredRound = nzRound:GetNumber()
  505.         self.ZombiesKilled = nzRound:GetZombiesKilled()
  506.     end
  507.  
  508.     -- This is to copy the constraints that are applied to the world only (ropes, etc)
  509.     -- It will not actually save and then try to restore the world entity, as that would cause issues
  510.     -- table.insert( SavedProps, game.GetWorld() )
  511.  
  512.     local WorldConstraints = self:CopyEntity(game.GetWorld())
  513.     local CleanedWorldStuff = {
  514.         Constraints = table.Copy(WorldConstraints.Constraints),
  515.         Entities = table.Copy(WorldConstraints.Entities),
  516.     }
  517.     table.insert(SavedProps, CleanedWorldStuff)
  518.  
  519.     self:ArchiveClaymores()
  520.     self:ArchiveC4()
  521.     self:ArchiveTacInserts()
  522.  
  523.     SavedProps.Players = {}
  524.     if bShouldSaveOwnerOnly then
  525.         SavedProps.Players[tostring(self.BombOwner:SteamID())] = self:GetPlayerInfo(self.BombOwner)
  526.     else
  527.         for k, ply in pairs(player.GetHumans()) do
  528.             SavedProps.Players[tostring(ply:SteamID())] = self:GetPlayerInfo(ply)
  529.         end
  530.     end
  531.     return util.TableToJSON( SavedProps )
  532. end
  533.  
  534. function ENT:CopyEntity( Ent, AddToTable )
  535.  
  536.     local Ents = {}
  537.     local Constraints = {}
  538.     if not Ent:IsNextBot() then
  539.         self:GetEntityConstraints( Ent, Ents, Constraints )
  540.     else
  541.         Ents = {Ent}
  542.     end
  543.    
  544.     local EntTables = {}
  545.     if ( AddToTable != nil ) then EntTables = AddToTable.Entities or {} end
  546.  
  547.     for k, v in pairs( Ents ) do
  548.  
  549.         if v.IsLambdaSpawned then
  550.             continue
  551.         end
  552.  
  553.         if not Ent:IsNextBot() then
  554.             EntTables[ k ] = duplicator.CopyEntTable( v )
  555.             if self:GetPropOwningPlayer(v) ~= nil and self:GetPropOwningPlayer(v):SteamID() ~= nil then
  556.                 EntTables[k].OwningPlayer = tostring(self:GetPropOwningPlayer(v):SteamID())
  557.             end
  558.             if v:IsVehicle() and IsValid(v:GetDriver()) then
  559.                 EntTables[k].VehiclePassenger = v:GetDriver():SteamID()
  560.                 if not v.IsScar and not v.EngineRPM then
  561.                     EntTables[k].CamInfo = {}
  562.                     EntTables[k].CamInfo.bIsThirdPerson = v:GetThirdPersonMode()
  563.                     EntTables[k].CamInfo.Distance = v:GetCameraDistance()
  564.                     EntTables[k].CamInfo.EyeAngles = v:GetDriver():GetAimVector():Angle()
  565.                 end
  566.             end
  567.         else
  568.             local output = {}
  569.             self:GetNextbotInfo(output, v)
  570.             EntTables[ k ] = output
  571.             if Ent:GetClass() == "npc_lambdaplayer" then
  572.                 EntTables[k].OwningPlayer = tostring(Ent:GetCreator():SteamID())
  573.             elseif self:GetPropOwningPlayer(v) ~= nil and self:GetPropOwningPlayer(v):SteamID() ~= nil then
  574.                 EntTables[k].OwningPlayer = tostring(self:GetPropOwningPlayer(v):SteamID())
  575.             end
  576.         end
  577.     end
  578.  
  579.     local ConstraintTables = {}
  580.     if !Ent:IsNextBot() then
  581.         if ( AddToTable != nil ) then ConstraintTables = AddToTable.Constraints or {} end
  582.  
  583.         for k, v in pairs( Constraints ) do
  584.             ConstraintTables[ k ] = v
  585.         end
  586.     end
  587.  
  588.     local mins, maxs = duplicator.WorkoutSize( EntTables )
  589.  
  590.     return {
  591.         Entities = EntTables,
  592.         Constraints = ConstraintTables,
  593.         Mins = mins,
  594.         Maxs = maxs
  595.     }
  596.  
  597. end
  598.  
  599. --
  600. -- The physics object Saver/Loader
  601. --
  602. local NextBotPhysicsObject =
  603. {
  604.     Save = function( data, phys )
  605.  
  606.         data.Pos = phys:GetPos()
  607.         data.Angle = phys:GetAngles()
  608.         data.Frozen = !phys:IsMoveable()
  609.         if ( !phys:IsGravityEnabled() ) then data.NoGrav = true end
  610.         if ( phys:IsAsleep() ) then data.Sleep = true end
  611.  
  612.         data.Pos, data.Angle = WorldToLocal( data.Pos, data.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
  613.  
  614.     end,
  615.  
  616.     Load = function( data, phys )
  617.  
  618.         if ( isvector( data.Pos ) && isangle( data.Angle ) ) then
  619.  
  620.             local pos, ang = LocalToWorld( data.Pos, data.Angle, LocalPos, LocalAng )
  621.             phys:SetPos( pos )
  622.             phys:SetAngles( ang )
  623.  
  624.         end
  625.  
  626.         -- Let's not Wake or put anything to sleep for now
  627.         --[[
  628.         if ( data.Sleep ) then
  629.             if ( IsValid( phys ) ) then phys:Sleep() end
  630.         else
  631.             phys:Wake()
  632.         end
  633.         ]]
  634.  
  635.         if ( data.Frozen ) then
  636.  
  637.             phys:EnableMotion( false )
  638.  
  639.             -- If we're being created by a player then add these to their frozen list so they can unfreeze them all
  640.             if ( IsValid( ActionPlayer ) ) then
  641.                 ActionPlayer:AddFrozenPhysicsObject( phys:GetEntity(), phys )
  642.             end
  643.  
  644.         end
  645.  
  646.         if ( data.NoGrav ) then phys:EnableGravity( false ) end
  647.  
  648.     end,
  649. }
  650.  
  651. --
  652. -- Entity physics saver
  653. --
  654. local NextbotPhysics =
  655. {
  656.     --
  657.     -- Loop each bone, calling PhysicsObject.Save
  658.     --
  659.     Save = function( data, Entity )
  660.  
  661.         local num = Entity:GetPhysicsObjectCount()
  662.  
  663.         for objectid = 0, num-1 do
  664.  
  665.             local obj = Entity:GetPhysicsObjectNum( objectid )
  666.             if ( !IsValid( obj ) ) then continue end
  667.  
  668.             data[ objectid ] = {}
  669.             NextBotPhysicsObject.Save( data[ objectid ], obj )
  670.  
  671.         end
  672.  
  673.     end,
  674.  
  675.     --
  676.     -- Loop each bone, calling PhysicsObject.Load
  677.     --
  678.     Load = function( data, Entity )
  679.  
  680.         if ( !istable( data ) ) then return end
  681.  
  682.         for objectid, objectdata in pairs( data ) do
  683.  
  684.             local Phys = Entity:GetPhysicsObjectNum( objectid )
  685.             if ( !IsValid( Phys ) ) then continue end
  686.  
  687.             PhysicsObject.Load( objectdata, Phys )
  688.  
  689.         end
  690.  
  691.     end,
  692. }
  693.  
  694. --
  695. -- Nextbot Saver
  696. --
  697. function ENT:GetNextbotInfo(data, ent)
  698.     --
  699.     -- Called on each entity when saving
  700.     --
  701.         if ent:GetClass() ~= "npc_lambdaplayer" then
  702.             if ( ent.PreEntityCopy ) then ent:PreEntityCopy() end
  703.             if ( ent.PostEntityCopy ) then ent:PostEntityCopy() end
  704.         end
  705.         --
  706.         -- Set so me generic variables that pretty much all entities
  707.         -- would like to save.
  708.         --
  709.  
  710.         data.Pos                = ent:GetPos()
  711.         data.Angle              = ent:GetAngles()
  712.         data.Class              = ent:GetClass()
  713.         data.Model              = ent:GetModel()
  714.         data.Skin               = ent:GetSkin()
  715.         data.Mins, data.Maxs    = ent:GetCollisionBounds()
  716.         data.ColGroup           = ent:GetCollisionGroup()
  717.         data.Name               = ent:GetName()
  718.         data.WorkshopID         = ent:GetWorkshopID()
  719.         data.IsNextBot          = true
  720.         data.Creator            = ent:GetCreator()
  721.  
  722.         data.Pos, data.Angle    = WorldToLocal( data.Pos, data.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
  723.  
  724.         data.ModelScale         = ent:GetModelScale()
  725.         if ( data.ModelScale == 1 ) then data.ModelScale = nil end
  726.  
  727.         -- Allow the entity to override the class
  728.         -- (this is a hack for the jeep, since it's real class is different from the one it reports as)
  729.         if ( ent.ClassOverride ) then data.Class = ent.ClassOverride end
  730.  
  731.         -- Save the physics
  732.         data.PhysicsObjects = data.PhysicsObjects or {}
  733.         NextbotPhysics.Save( data.PhysicsObjects, ent )
  734.  
  735.         -- Flexes
  736.         data.FlexScale = ent:GetFlexScale()
  737.         for i = 0, ent:GetFlexNum() do
  738.  
  739.             local w = ent:GetFlexWeight( i )
  740.             if ( w != 0 ) then
  741.                 data.Flex = data.Flex or {}
  742.                 data.Flex[ i ] = w
  743.             end
  744.  
  745.         end
  746.  
  747.         -- Body Groups
  748.         local bg = ent:GetBodyGroups()
  749.         if ( bg ) then
  750.  
  751.             for k, v in pairs( bg ) do
  752.  
  753.                 --
  754.                 -- If it has a non default setting, save it.
  755.                 --
  756.                 if ( ent:GetBodygroup( v.id ) > 0 ) then
  757.  
  758.                     data.BodyG = data.BodyG or {}
  759.                     data.BodyG[ v.id ] = ent:GetBodygroup( v.id )
  760.  
  761.                 end
  762.  
  763.             end
  764.  
  765.         end
  766.  
  767.         -- Non Sandbox tool set colors and material
  768.         if ( ent:GetColor() != color_white ) then data._DuplicatedColor = ent:GetColor() end
  769.         if ( ent:GetMaterial() != "" ) then data._DuplicatedMaterial = ent:GetMaterial() end
  770.  
  771.         -- Bone Manipulator
  772.         if ( ent:HasBoneManipulations() ) then
  773.  
  774.             data.BoneManip = {}
  775.  
  776.             for i = 0, ent:GetBoneCount() do
  777.  
  778.                 local t = {}
  779.  
  780.                 local s = ent:GetManipulateBoneScale( i )
  781.                 local a = ent:GetManipulateBoneAngles( i )
  782.                 local p = ent:GetManipulateBonePosition( i )
  783.  
  784.                 if ( s != Vector( 1, 1, 1 ) ) then t[ 's' ] = s end -- scale
  785.                 if ( a != angle_zero ) then t[ 'a' ] = a end -- angle
  786.                 if ( p != vector_origin ) then t[ 'p' ] = p end -- position
  787.  
  788.                 if ( !table.IsEmpty( t ) ) then
  789.                     data.BoneManip[ i ] = t
  790.                 end
  791.  
  792.             end
  793.  
  794.         end
  795.  
  796.         --
  797.         -- Store networks vars/DT vars (assigned using SetupDataTables)
  798.         --
  799.         if ( ent.GetNetworkVars ) then
  800.             data.DT = ent:GetNetworkVars()
  801.         end
  802.  
  803.  
  804.         -- Make this function on your SENT if you want to modify the
  805.         -- returned table specifically for your entity.
  806.         if ( ent.OnEntityCopyTableFinish ) then
  807.             ent:OnEntityCopyTableFinish( data )
  808.         end
  809.  
  810.         --
  811.         -- Exclude this crap
  812.         --
  813.         for k, v in pairs( data ) do
  814.  
  815.             if ( isfunction( v ) ) then
  816.                 data[k] = nil
  817.             end
  818.  
  819.         end
  820.  
  821.         data.OnDieFunctions = nil
  822.         data.AutomaticFrameAdvance = nil
  823.         data.BaseClass = nil
  824. end
  825.  
  826. function ENT:GetEntityConstraints( ent, OutEntTable, OutConstraintTable, CheckedEnts )
  827.  
  828.     if ( !IsValid( ent ) && !ent:IsWorld() ) then return end
  829.  
  830.     if !ent:IsNextBot() then
  831.         if not istable(CheckedEnts) then
  832.             CheckedEnts = {}
  833.         end
  834.  
  835.         if table.HasValue(CheckedEnts, ent) then
  836.             return
  837.         end
  838.  
  839.         table.insert(CheckedEnts, ent)
  840.     else
  841.         --table.insert(OutEntTable, ent)
  842.         --OutEntTable = {ent}
  843.         return {ent}, {}
  844.     end
  845.  
  846.     -- Translate the class name
  847.     local classname = ent:GetClass()
  848.     if ( ent.ClassOverride ) then classname = ent.ClassOverride end
  849.  
  850.     -- Is the entity in the dupe whitelist?
  851.     if ( !duplicator.IsAllowed( classname ) && !ent:IsWorld() ) then
  852.         return
  853.     end
  854.  
  855.     -- Entity doesn't want to be duplicated.
  856.     if ( ent.DoNotDuplicate ) then return end
  857.  
  858.     if ( !ent:IsWorld() ) then OutEntTable[ ent:EntIndex() ] = ent end
  859.  
  860.     if ( !constraint.HasConstraints( ent ) ) then return end
  861.  
  862.     local FoundConstraints = constraint.GetTable( ent )
  863.  
  864.     for key, constr in pairs( FoundConstraints ) do
  865.  
  866.         if ( table.HasValue(OutConstraintTable, constr) or table.HasValue(CheckedEnts, constr.Entity) ) then
  867.             continue
  868.         end
  869.  
  870.         -- Add constraint to the constraints table
  871.         OutConstraintTable[ #OutConstraintTable + 1 ] = constr
  872.  
  873.         -- Run the Function for any ents attached to this constraint
  874.         for _, ItConstrainedEnt in pairs( constr.Entity ) do
  875.  
  876.             if ( !ItConstrainedEnt.Entity:IsWorld() ) then
  877.                 self:GetEntityConstraints( ItConstrainedEnt.Entity, OutEntTable, OutConstraintTable, CheckedEnts )
  878.             end
  879.  
  880.         end
  881.     end
  882.  
  883.     return OutEntTable, OutConstraintTable
  884. end
  885.  
  886. function ENT:PasteArchive( Player, EntityList, ConstraintList )
  887.     --
  888.     -- Store the player
  889.     --
  890.     local oldplayer = ActionPlayer
  891.     ActionPlayer = Player
  892.     --
  893.     -- Copy the table - because we're gonna be changing some stuff on it.
  894.     --
  895.     local EntityList = table.Copy( EntityList )
  896.     local ConstraintList = table.Copy( ConstraintList )
  897.  
  898.     local CreatedEntities = {}
  899.  
  900.     --
  901.     -- Create the Entities
  902.     --         
  903.     for k, EntFromList in pairs( EntityList ) do
  904.         local e = nil
  905.         local b = ProtectedCall( function() e = self:CreateEntityFromTable( Player, EntFromList ) end )
  906.         if ( !b ) then continue end
  907.  
  908.         if ( IsValid( e ) ) then
  909.             --
  910.             -- Call this here ( as well as before :Spawn) because Spawn/Init might have stomped the values
  911.             --
  912.  
  913.             if ( e.RestoreNetworkVars ) then
  914.                 e:RestoreNetworkVars( EntFromList.DT )
  915.             end
  916.  
  917.             if ( e.OnDuplicated ) then
  918.                 e:OnDuplicated( EntFromList )
  919.             end
  920.  
  921.             if not bIsPlayingZombies then
  922.                 if EntFromList.VehiclePassenger ~= nil and e:IsVehicle() then
  923.                     --local passenger = player.GetByID(EntFromList.VehiclePassenger)
  924.                     local passenger = player.GetBySteamID( EntFromList.VehiclePassenger )
  925.                     if IsValid(passenger) and passenger:IsPlayer() then
  926.                         passenger:EnterVehicle(e)
  927.                         if not e.IsScar and not e.EngineRPM then
  928.                             e:SetThirdPersonMode(EntFromList.CamInfo.bIsThirdPerson)
  929.                             e:SetCameraDistance(EntFromList.CamInfo.Distance)
  930.                             passenger:SetEyeAngles(EntFromList.CamInfo.EyeAngles)
  931.                         elseif e.EngineRPM then
  932.                             e:StopEngine()
  933.                             passenger:SetMoveType(MOVETYPE_WALK)
  934.                             e:SetPos(e:GetPos() + Vector(0,0,20))
  935.                         end
  936.                     end
  937.                 end
  938.  
  939.                 if EntFromList.OwningPlayer ~= nil then
  940.                     local TargetPlayer = player.GetBySteamID(EntFromList.OwningPlayer)
  941.                     print(TargetPlayer)
  942.                     e:SetCreator(TargetPlayer)
  943.                     undo.Create("")
  944.                         undo.AddEntity(e)
  945.                         undo.SetPlayer(TargetPlayer)
  946.                     undo.Finish()
  947.                     cleanup.Add(TargetPlayer, "props", e)
  948.                 end
  949.             end
  950.         end
  951.  
  952.         CreatedEntities[ k ] = e
  953.  
  954.         if ( CreatedEntities[ k ] ) then
  955.  
  956.             CreatedEntities[ k ].BoneMods = table.Copy( EntFromList.BoneMods )
  957.             CreatedEntities[ k ].EntityMods = table.Copy( EntFromList.EntityMods )
  958.             CreatedEntities[ k ].PhysicsObjects = table.Copy( EntFromList.PhysicsObjects )
  959.  
  960.         else
  961.  
  962.             CreatedEntities[ k ] = nil
  963.  
  964.         end
  965.  
  966.     end
  967.  
  968.     --
  969.     -- Apply modifiers to the created entities
  970.     --
  971.     for EntID, Ent in pairs( CreatedEntities ) do
  972.  
  973.         duplicator.ApplyEntityModifiers( Player, Ent )
  974.         duplicator.ApplyBoneModifiers( Player, Ent )
  975.  
  976.         if ( Ent.PostEntityPaste ) then
  977.             Ent:PostEntityPaste( Player || NULL, Ent, CreatedEntities )
  978.         end
  979.  
  980.     end
  981.  
  982.     local CreatedConstraints = {}
  983.  
  984.     --
  985.     -- Create constraints
  986.     --
  987.     for k, Constraint in pairs( ConstraintList ) do
  988.  
  989.         local Entity = nil
  990.         ProtectedCall( function() Entity = self:CreateConstraints( Constraint, CreatedEntities, Player ) end )
  991.         if ( IsValid( Entity ) ) then
  992.             table.insert( CreatedConstraints, Constraint )
  993.         end
  994.  
  995.     end
  996.  
  997.     ActionPlayer = oldplayer
  998.  
  999.     return CreatedEntities, CreatedConstraints
  1000. end
  1001.  
  1002. --[[---------------------------------------------------------
  1003.    Create an entity from a table.
  1004. -----------------------------------------------------------]]
  1005. function ENT:CreateEntityFromTable( Player, EntTable )
  1006.  
  1007.     --
  1008.     -- Convert position/angle to `local`
  1009.     --
  1010.     if ( EntTable.Pos && EntTable.Angle ) then
  1011.  
  1012.         EntTable.Pos, EntTable.Angle = LocalToWorld( EntTable.Pos, EntTable.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
  1013.  
  1014.     end
  1015.  
  1016.     if EntTable.Class == "npc_lambdaplayer" then
  1017.         local newlambda = ents.Create( "npc_lambdaplayer" )
  1018.         newlambda:SetPos( EntTable.Pos )
  1019.         newlambda:SetAngles( EntTable.Angle )
  1020.         newlambda:Spawn()
  1021.  
  1022.         if EntTable.OwningPlayer ~= nil then
  1023.             local TargetPlayer = player.GetBySteamID(EntTable.OwningPlayer)
  1024.             print(TargetPlayer)
  1025.             newlambda:SetCreator(TargetPlayer)
  1026.             undo.Create("")
  1027.                 undo.AddEntity(newlambda)
  1028.                 undo.SetPlayer(TargetPlayer)
  1029.             undo.Finish()
  1030.             cleanup.Add(TargetPlayer, "props", newlambda)
  1031.         end
  1032.  
  1033.         return
  1034.     end
  1035.  
  1036.     local EntityClass = duplicator.FindEntityClass( EntTable.Class )
  1037.  
  1038.     -- This class is unregistered. Instead of failing try using a generic
  1039.     -- Duplication function to make a new copy..
  1040.     if ( !EntityClass ) then
  1041.  
  1042.         return duplicator.GenericDuplicatorFunction( Player, EntTable )
  1043.  
  1044.     end
  1045.  
  1046.     -- Build the argument list
  1047.     local ArgList = {}
  1048.  
  1049.     for iNumber, Key in pairs( EntityClass.Args ) do
  1050.  
  1051.         local Arg = nil
  1052.  
  1053.         -- Translate keys from old system
  1054.         if ( Key == "pos" or Key == "position" ) then Key = "Pos" end
  1055.         if ( Key == "ang" or Key == "Ang" or Key == "angle" ) then Key = "Angle" end
  1056.         if ( Key == "model" ) then Key = "Model" end
  1057.  
  1058.         Arg = EntTable[ Key ]
  1059.  
  1060.         -- Special keys
  1061.         if ( Key == "Data" ) then Arg = EntTable end
  1062.  
  1063.         -- If there's a missing argument then unpack will stop sending at that argument so send it as `false`
  1064.         if ( Arg == nil ) then Arg = false end
  1065.  
  1066.         ArgList[ iNumber ] = Arg
  1067.  
  1068.     end
  1069.  
  1070.     -- Create and return the entity
  1071.     return EntityClass.Func( Player, unpack( ArgList ) )
  1072.  
  1073. end
  1074.  
  1075. function ENT:CreateConstraints( Constraint, EntityList, Player )
  1076.  
  1077.     local Factory = duplicator.ConstraintType[ Constraint.Type ]
  1078.     if ( !Factory ) then return end
  1079.  
  1080.     local Args = {}
  1081.     for k, Key in pairs( Factory.Args ) do
  1082.  
  1083.         local Val = Constraint[ Key ]
  1084.  
  1085.         for i = 1, 6 do
  1086.  
  1087.             if ( Constraint.Entity[ i ] ) then
  1088.  
  1089.                 if ( Key == "Ent" .. i ) then
  1090.                     Val = EntityList[ Constraint.Entity[ i ].Index ]
  1091.                     if ( Constraint.Entity[ i ].World ) then
  1092.                         Val = game.GetWorld()
  1093.                     end
  1094.                 end
  1095.  
  1096.                 if ( Key == "Bone" .. i ) then Val = Constraint.Entity[ i ].Bone or 0 end
  1097.                 if ( Key == "LPos" .. i ) then Val = Constraint.Entity[ i ].LPos end
  1098.                 if ( Key == "WPos" .. i ) then Val = Constraint.Entity[ i ].WPos end
  1099.                 if ( Key == "Length" .. i ) then Val = Constraint.Entity[ i ].Length or 0 end
  1100.  
  1101.             end
  1102.         end
  1103.  
  1104.         -- A little hack to give the duped constraints the correct player object
  1105.         if ( Key:lower() == "pl" || Key:lower() == "ply" || Key:lower() == "player" ) then Val = Player end
  1106.  
  1107.         -- If there's a missing argument then unpack will stop sending at that argument
  1108.         if ( Val == nil ) then Val = false end
  1109.  
  1110.         table.insert( Args, Val )
  1111.     end
  1112.  
  1113.     local NewConstraint = Factory.Func( unpack( Args ) )
  1114.  
  1115.     return NewConstraint
  1116.  
  1117. end
  1118.  
  1119. function ENT:ArchiveClaymores()
  1120.     local AllClaymores = ents.FindByClass("seal6-claymore-bo2-ent")
  1121.     table.Merge(AllClaymores, ents.FindByClass("seal6-claymore-ent"))
  1122.  
  1123.     if table.IsEmpty(AllClaymores) then
  1124.         return
  1125.     end
  1126.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  1127.  
  1128.     for k,ItClaymore in ipairs(AllClaymores) do
  1129.         local bDoesPlayerOwnProp = IsValid(ItClaymore.ClayOwner) and ItClaymore.ClayOwner == self.BombOwner
  1130.         if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
  1131.             continue
  1132.         end
  1133.         local SavedClaymore = {}
  1134.         SavedClaymore.Class = ItClaymore:GetClass()
  1135.         SavedClaymore.Location = ItClaymore:GetPos()
  1136.         SavedClaymore.Rotation = ItClaymore:GetAngles()
  1137.         --SavedClaymore.ClayParent = ItClaymore.ClayParent
  1138.         SavedClaymore.OwnerID = ItClaymore:GetNWString("OwnerID")
  1139.         SavedClaymore.ClayOwner = ItClaymore.ClayOwner
  1140.         --SavedClaymore.Kids = nil
  1141.         table.insert(self.ArchivedClaymores, SavedClaymore)
  1142.     end
  1143. end
  1144.  
  1145. function ENT:ArchiveC4()
  1146.     local AllC4s = ents.FindByClass("cod-c4")
  1147.  
  1148.     if table.IsEmpty(AllC4s) then
  1149.         return
  1150.     end
  1151.  
  1152.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  1153.  
  1154.     for k,ItC4 in ipairs(AllC4s) do
  1155.         local bDoesPlayerOwnProp = IsValid(ItC4.C4Owner) and ItC4.C4Owner == self.BombOwner
  1156.         if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
  1157.             continue
  1158.         end
  1159.         local SavedC4 = {}
  1160.         SavedC4.Location = ItC4:GetPos()
  1161.         SavedC4.Rotation = ItC4:GetAngles()
  1162.         SavedC4.C4Owner = ItC4.C4Owner
  1163.         SavedC4.OwnerID = ItC4:GetNWString("OwnerID")
  1164.         SavedC4.ThisTrigger = ItC4.ThisTrigger
  1165.         SavedC4.ExplodedViaWorld = ItC4.ExplodedViaWorld
  1166.         SavedC4.QueuedForExplode = ItC4.QueuedForExplode
  1167.         SavedC4.UniqueExplodeTimer = ItC4.UniqueExplodeTimer
  1168.         SavedC4.Stuck = ItC4.Stuck
  1169.         SavedC4.Hit = ItC4.Hit
  1170.         if IsValid(ItC4.PhysData) then
  1171.             SavedC4.PhysData = ItC4.PhysData
  1172.         end
  1173.         table.insert(self.ArchivedC4s, SavedC4)
  1174.     end
  1175. end
  1176.  
  1177. function ENT:ArchiveTacInserts()
  1178.     local AllTacInserts = ents.FindByClass("cod-tac-insert")
  1179.  
  1180.     if table.IsEmpty(AllTacInserts) then
  1181.         return
  1182.     end
  1183.  
  1184.     local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
  1185.  
  1186.     for k,ItTacInsert in ipairs(AllTacInserts) do
  1187.         local bDoesPlayerOwnProp = IsValid(ItTacInsert.TacOwner) and ItTacInsert.TacOwner == self.BombOwner
  1188.         if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
  1189.             continue
  1190.         end
  1191.         local SavedInsert = {}
  1192.         SavedInsert.Location = ItTacInsert:GetPos()
  1193.         SavedInsert.Rotation = ItTacInsert:GetAngles()
  1194.         SavedInsert.TacOwner = ItTacInsert.TacOwner
  1195.         SavedInsert.Owner = ItTacInsert.Owner
  1196.         SavedInsert.NwTacOwner = ItTacInsert:GetNWString("TacOwner")
  1197.         SavedInsert.OwnerID = ItTacInsert:GetNWString("OwnerID")
  1198.         table.insert(self.ArchivedTacInserts, SavedInsert)
  1199.     end
  1200. end
  1201.  
  1202. function ENT:GetPlayerInfo(ent)
  1203.  
  1204.     if !IsValid(ent) then
  1205.         return
  1206.     end
  1207.  
  1208.     local tab = {}
  1209.     tab.Origin = ent:GetPos()
  1210.     tab.Angle = ent:GetAimVector():Angle()
  1211.     tab.MoveType = ent:GetMoveType()
  1212.     tab.Alive = ent:Alive()
  1213.     if ent:Alive() then
  1214.         tab.Health = ent:Health()
  1215.         tab.Armor = ent:Armor()
  1216.  
  1217.         if #ent:GetWeapons() > 0 then
  1218.  
  1219.             tab.Weapons = {}
  1220.             tab.Ammo = ent:GetAmmo()
  1221.  
  1222.             for k, ItWep in ipairs(ent:GetWeapons()) do
  1223.                 if string.match(ItWep:GetClass(), "zombies_perk_") then
  1224.                     continue
  1225.                 end
  1226.                 if not bIsPlayingZombies and ItWep:GetClass() ==  "seal6-timebomb" and ent:GetAmmoCount("ammo_timebomb") <= 0 and ent == self.BombOwner then
  1227.                     local bShouldKeepBomb = ConVarExists("TimeBomb_KeepWatchAfterTravel") and GetConVar("TimeBomb_KeepWatchAfterTravel"):GetBool() or false
  1228.                     if not bShouldKeepBomb then
  1229.                         continue
  1230.                     end
  1231.                 end
  1232.                 local SavedWeapon = {}
  1233.                 SavedWeapon.Class = ItWep:GetClass()
  1234.                 SavedWeapon.ClipOne = ItWep:Clip1()
  1235.                 SavedWeapon.ClipTwo = ItWep:Clip2()
  1236.                 table.insert(tab.Weapons, SavedWeapon)
  1237.             end
  1238.  
  1239.             if IsValid(ent:GetActiveWeapon()) then
  1240.                 tab.ActiveWep = ent:GetActiveWeapon():GetClass()
  1241.             end
  1242.         end
  1243.     end
  1244.  
  1245.     return tab
  1246. end
  1247.  
  1248. function ENT:SetPlayerInfo(ent, tab)
  1249.     if ( tab == nil or ent == nil ) then
  1250.         return
  1251.     end
  1252.  
  1253.     if not ent:Alive() then
  1254.         ent:Spawn()
  1255.     end
  1256.  
  1257.     if tab.Alive then
  1258.         if ( tab.Health ) then
  1259.             ent:SetHealth(tab.Health)
  1260.         end
  1261.  
  1262.         if ( tab.Armor ) then
  1263.             ent:SetArmor(tab.Armor)
  1264.         end
  1265.  
  1266.         if tab.Weapons then
  1267.             ent:StripWeapons()
  1268.             if bIsPlayingZombies then
  1269.                 ent:SetUsingSpecialWeapon(false)
  1270.             end
  1271.             for k, weapon in ipairs(tab.Weapons) do
  1272.                 local GivenWeapon = ent:Give(weapon.Class, true)
  1273.                 GivenWeapon:SetClip1(weapon.ClipOne)
  1274.                 GivenWeapon:SetClip2(weapon.ClipTwo)
  1275.             end
  1276.         end
  1277.  
  1278.         if tab.Ammo then
  1279.             timer.Simple(1, function()
  1280.                 for k, ammo in ipairs(tab.Ammo) do
  1281.                     ent:SetAmmo(ammo, k)
  1282.                 end
  1283.             end)
  1284.         end
  1285.  
  1286.         if tab.ActiveWep ~= nil and tab.ActiveWep ~= "" and tab.ActiveWep ~= "seal6-timebomb" then
  1287.             ent:SelectWeapon(tab.ActiveWep)
  1288.         end
  1289.  
  1290.         if ( tab.MoveType ) then
  1291.             ent:SetMoveType( tab.MoveType )
  1292.         end
  1293.     else
  1294.         ent:Spawn()
  1295.     end
  1296.  
  1297.     if ( tab.Origin ) then
  1298.         ent:SetPos( tab.Origin )
  1299.     end
  1300.  
  1301.     if ( tab.Angle ) then
  1302.         ent:SetEyeAngles( tab.Angle )
  1303.     end
  1304. end
  1305.  
  1306. function ENT:CleanupWeapons()
  1307.     local WeaponTable = {}
  1308.     table.Add(WeaponTable, ents.FindByClass("weapon_*"))
  1309.     table.Add(WeaponTable, ents.FindByClass("ai_weapon_*"))
  1310.     table.Add(WeaponTable, ents.FindByClass("item_ammo_ar2_altfire"))
  1311.     table.Add(WeaponTable, ents.FindByClass("item_healthvial"))
  1312.  
  1313.     for k,lambda in pairs(ents.FindByClass("npc_lambdaplayer")) do
  1314.         if IsValid(lambda.WeaponEnt) then
  1315.             lambda.WeaponEnt:Remove()
  1316.         end
  1317.     end
  1318.  
  1319.     for k,wep in pairs(WeaponTable) do
  1320.         if not IsValid(wep:GetOwner()) then
  1321.             wep:Remove()
  1322.         end
  1323.     end
  1324. end
  1325.  
  1326. function ENT:FreezeNPCs()
  1327.     for k, npc in pairs(ents.GetAll()) do
  1328.         if npc:IsNPC() then
  1329.             npc:CapabilitiesRemove(CAP_MOVE_GROUND)
  1330.             npc:CapabilitiesRemove(CAP_USE_WEAPONS)
  1331.         elseif npc:IsNextBot() then
  1332.             npc.BehaveThread = coroutine.create(function()
  1333.                 coroutine.wait(5)
  1334.             end)
  1335.         end
  1336.     end
  1337. end
  1338.  
  1339. function ENT:PlayScreenOverlayFX()
  1340.     net.Start( "CreateTimeBombOverlay" )
  1341.     net.Broadcast()
  1342. end
  1343.  
  1344. function ENT:Initialize()
  1345.  
  1346.     CreateTimeBombConfig()
  1347.  
  1348.     self:SetModel( "models/hoff/weapons/timebomb/w_timebomb.mdl" )
  1349.     self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
  1350.     self:PhysicsInit( SOLID_VPHYSICS )
  1351.     self:SetMoveType( MOVETYPE_VPHYSICS )
  1352.     self:SetSolid( SOLID_VPHYSICS )
  1353.     self:DrawShadow(false)
  1354.     local phys = self:GetPhysicsObject()
  1355.     if (phys:IsValid()) then
  1356.         phys:Wake()
  1357.     end
  1358.  
  1359.     ParticleEffectAttach("vortigaunt_hand_glow", PATTACH_POINT_FOLLOW, self, 1)
  1360. end
  1361.  
  1362. function ENT:PhysgunPickup(ply, ent)
  1363.     if ent:GetClass() == "cod-timebomb" then
  1364.         return false
  1365.     end
  1366. end
  1367.  
  1368. function ENT:SetupDataTables()
  1369.     self:DTVar( "Float", 0, "RotationSeed1" )
  1370.     self:DTVar( "Float", 1, "RotationSeed2" )
  1371. end
  1372.  
  1373. function ENT:OnRemove()
  1374.     self:StopSound("hoff/zmb/timebomb/timebomb_plant_2d.mp3")
  1375.     self.ThisTrigger:SetNWBool("bTimeBombOut", false)
  1376.     if bIsPlayingZombies then
  1377.         net.Start( "RemoveTimeBombRound" )
  1378.             net.WriteEntity(self.BombOwner)
  1379.         net.Send(self.BombOwner)
  1380.     end
  1381.     timer.Remove("TimeBombArchiver" .. self:EntIndex())
  1382. end
  1383.  
  1384. function ENT:PhysicsCollide(data,phys) 
  1385.     if data.HitEntity:GetClass() == "cod-timebomb" or data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then return end
  1386.  
  1387.     if self:IsValid() and not self.Hit then
  1388.  
  1389.         -- Instead of changing the collision group directly,
  1390.         -- set a flag that we want to change the collision group
  1391.         -- and start a timer to do it after the PhysicsCollide callback has finished.
  1392.         self.ChangeCollisionGroup = true
  1393.         timer.Simple(0, function()
  1394.             if self.ChangeCollisionGroup then
  1395.                 self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
  1396.                 self.ChangeCollisionGroup = false
  1397.  
  1398.                 local bHitValidEntity = IsValid(data.HitEntity)
  1399.                 if bHitValidEntity then
  1400.                     self:SetSolid(SOLID_VPHYSICS)
  1401.                     self:SetMoveType(MOVETYPE_NONE)
  1402.                     self:SetParent(data.HitEntity)
  1403.                     self.Stuck = true
  1404.                     self.Hit = true
  1405.                 else
  1406.                     self:SetMoveType(MOVETYPE_NONE)
  1407.                 end
  1408.                 self:EmitSound("hoff/zmb/timebomb/timebomb_plant_2d.mp3")
  1409.  
  1410.                 if IsValid(self.ThisTrigger) then
  1411.                     self.ThisTrigger:SetNWBool("bTimeBombOut", true)
  1412.                 end
  1413.  
  1414.                 self:StoreOwnedProps()
  1415.                 if IsValid(phys) then
  1416.                     local angVel = phys:GetAngleVelocity()
  1417.                     local maxAngVel = 1000
  1418.                     if angVel:Length() > maxAngVel then
  1419.                         angVel = angVel:GetNormalized() * maxAngVel
  1420.                         phys:SetAngleVelocity(angVel)
  1421.                     end
  1422.                 end
  1423.  
  1424.                 local HitAngle = data.HitNormal:Angle()
  1425.                 HitAngle.p = HitAngle.p + 270
  1426.  
  1427.                 self:SetPos(data.HitPos + (data.HitNormal / 5))
  1428.  
  1429.                 -- Generate a random yaw angle between -60 and 60 degrees
  1430.                 local yaw = math.random(-60, 60)
  1431.  
  1432.                 self:SetAngles(HitAngle)
  1433.                 -- Rotate the Angle object around the entity's up vector using the RotateAroundAxis function
  1434.                 HitAngle:RotateAroundAxis(self:GetUp(), yaw)
  1435.                 -- Set the entity's angles to the rotated angles
  1436.                 self:SetAngles(HitAngle)
  1437.                 self:SetOwner(nil)
  1438.             end
  1439.         end)
  1440.         self:SetNWBool("Hit", true)
  1441.         self.Hit = true
  1442.     end
  1443. end
  1444.  
  1445. function ENT:Touch(ent)
  1446. end
  1447.  
  1448. ENT.CanUse = true
  1449. ENT.LFS = true
  1450. function ENT:Use( activator, caller )
  1451.     if activator:IsPlayer() and self.CanUse and self:GetNWString("OwnerID") == activator:SteamID() then
  1452.         self.CanUse = false
  1453.         if SERVER then
  1454.             if activator:HasWeapon("seal6-timebomb") and (not GetConVar("TimeBomb_Infinite"):GetBool() or (GetConVar("TimeBomb_Infinite"):GetBool() and activator:GetAmmoCount("ammo_timebomb") < 1)) then
  1455.                 activator:GiveAmmo(1, "ammo_timebomb")
  1456.             else
  1457.                 activator:Give("seal6-timebomb")
  1458.                 activator:SelectWeapon("seal6-timebomb")
  1459.             end
  1460.             self:Remove()
  1461.         end
  1462.     end
  1463. end
Advertisement
Add Comment
Please, Sign In to add comment