Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- AddCSLuaFile( "cl_init.lua" )
- AddCSLuaFile( "shared.lua" )
- include( "shared.lua" )
- local bIsPlayingZombies = engine.ActiveGamemode() == "nzombies"
- if bIsPlayingZombies then
- local nzRound = nzRound or AddNZModule("Round")
- end
- function ENT:SpawnFunction( ply, tr )
- if ( not tr.Hit ) then
- return
- end
- -- local SpawnPos = tr.HitPos + tr.HitNormal * 16
- local ent = ents.Create( "cod-timebomb" )
- ent:SetPos( Vector(0,0,0) )
- ent:Spawn()
- ent:Activate()
- ent:SetOwner(ply) -- Disables collision between the C4 and its owner
- return ent
- end
- local function CreateTimeBombConfig()
- if file.Read("codzombies/timebomb.txt") == nil then
- local config =
- [[Time Bomb programmed by Hoff
- The time bomb has an internal blacklist, but you can add additional entities, starting on line 5. Format is entity_class.
- Use notepad++ or Sublime Text to edit this file to avoid format errors.
- ]]
- print("Time Bomb file non existant, creating 'data/codzombies/timebomb.txt'\n")
- if file.Read("codzombies/mysterybox.txt") == nil then
- file.CreateDir("codzombies")
- end
- file.Write("codzombies/timebomb.txt",config)
- end
- end
- hook.Add("Initialize","CreateTimeBombConfig",function()
- CreateTimeBombConfig()
- end)
- ENT.ArchivedWorld = ""
- ENT.ArchivedClaymores = {}
- ENT.ArchivedC4s = {}
- ENT.ArchivedTacInserts = {}
- if bIsPlayingZombies then
- ENT.StoredRound = -1
- ENT.ZombiesKilled = 0
- end
- ENT.EntityBlacklist =
- {
- "env_fire",
- "entityflame",
- "_firesmoke",
- "gmod_hands",
- "info_player_start",
- "predicted_viewmodel",
- "cod-timebomb",
- "seal6-claymore-bo2-ent",
- "seal6-claymore-ent",
- "cod-c4",
- "cod-tac-insert",
- "zombies_box_qmarks",
- "zombies_box_weapon",
- "zombies_teddybear",
- "zombies_mysterybox",
- "zombies_mysterybox_location",
- "zombies_mysterybox_beam",
- "nz_spawn_zombie_normal",
- "logic_waves",
- "logic_points",
- "power_box",
- "stinky_lever",
- "nz_script_prop",
- "prop_buys",
- "nz_shootable",
- "random_box",
- "sent_sakarias_carwheel",
- "sent_sakarias_carwheel_punked",
- "sent_sakarias_lightentity",
- "base_anim"
- }
- function ENT:StoreOwnedProps()
- self.ArchivedClaymores = {}
- self.ArchivedC4s = {}
- self.ArchivedTacInserts = {}
- self.ArchivedWorld = self:GetArchivedWorld()
- self:SetNWInt("SaveTime", os.time())
- if IsValid(self.ThisTrigger) then
- self.ThisTrigger:CallOnClient("UpdateRelativeClock")
- end
- if bIsPlayingZombies then
- timer.Simple(0.15, function()
- net.Start( "DisplayTimeBombRound" )
- net.WriteInt(nzRound:GetNumber(), 16)
- net.WriteEntity(self.ThisTrigger)
- net.Send(self.BombOwner)
- end)
- end
- end
- function ENT:RewindProps()
- self:SetParent()
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- if not bShouldSaveOwnerOnly then
- for _, ply in ipairs(player.GetHumans()) do
- ply:RemoveFlags(FL_NOTARGET)
- ply:UnLock()
- end
- else
- self.BombOwner:RemoveFlags(FL_NOTARGET)
- self.BombOwner:UnLock()
- end
- if IsValid(self.BombOwner) then
- self:LoadArchivedWorld()
- end
- self:Remove()
- end
- function ENT:LoadArchivedWorld()
- -- Strip off any crap before the start char..
- local strMapContents = self.ArchivedWorld
- local startchar = string.find( strMapContents, '' )
- if ( startchar != nil ) then
- strMapContents = string.sub( strMapContents, startchar )
- end
- -- Stip off any crap after the end char..
- strMapContents = strMapContents:reverse()
- startchar = string.find( strMapContents, '' )
- if ( startchar != nil ) then
- strMapContents = string.sub( strMapContents, startchar )
- end
- strMapContents = strMapContents:reverse()
- local tab = util.JSONToTable( strMapContents )
- if ( !istable( tab ) ) then
- -- Error loading save!
- return false
- end
- self:CleanupMap()
- DisablePropCreateEffect = true
- duplicator.RemoveMapCreatedEntities()
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- if not bShouldSaveOwnerOnly then
- for k, ply in ipairs(player.GetHumans()) do
- ply:SendLua( "hook.Run( \"OnSpawnMenuClose\" )" )
- ply:SendLua( "surface.PlaySound('hoff/zmb/timebomb/timebomb_activate_2.mp3')")
- if tab.Players[tostring(ply:SteamID())] != nil then
- self:SetPlayerInfo( ply, tab.Players[tostring(ply:SteamID())] )
- end
- end
- else
- self.BombOwner:SendLua( "hook.Run( \"OnSpawnMenuClose\" )" )
- if GetConVar("TimeBomb_InstantTravel"):GetBool() then
- self.BombOwner:SendLua( "surface.PlaySound('hoff/zmb/timebomb/timebomb_activate_2.mp3')")
- end
- if tab.Players[tostring(self.BombOwner:SteamID())] != nil then
- self:SetPlayerInfo( self.BombOwner, tab.Players[tostring(self.BombOwner:SteamID())] )
- end
- end
- if bIsPlayingZombies then
- nzRound:SetNumber(self.StoredRound - 1)
- nzRound:SetZombiesKilled(self.ZombiesKilled)
- nzRound:Prepare()
- local specint = GetConVar("nz_round_special_interval"):GetInt() or 6
- nzRound:SetNextSpecialRound( math.ceil(self.StoredRound / specint) * specint)
- end
- if istable( self.ArchivedClaymores ) and not table.IsEmpty(self.ArchivedClaymores) then
- for k, ItClaymore in ipairs(self.ArchivedClaymores) do
- local NewClaymore = ents.Create(ItClaymore.Class)
- NewClaymore:SetPos(ItClaymore.Location)
- NewClaymore:SetAngles(ItClaymore.Rotation)
- NewClaymore:SetNWString("OwnerID", ItClaymore.OwnerID)
- --NewClaymore.ClayParent = nil
- NewClaymore.ClayOwner = ItClaymore.ClayOwner
- --NewClaymore.Kids = nil
- NewClaymore:Spawn()
- NewClaymore:Activate()
- end
- end
- if istable( self.ArchivedC4s ) and not table.IsEmpty(self.ArchivedC4s) then
- for k, ItC4 in ipairs(self.ArchivedC4s) do
- local NewC4 = ents.Create("cod-c4")
- NewC4:SetPos(ItC4.Location)
- NewC4:SetAngles(ItC4.Rotation)
- NewC4:SetNWString("OwnerID", ItC4.OwnerID)
- NewC4.C4Owner = ItC4.C4Owner
- NewC4.ThisTrigger = ItC4.ThisTrigger
- NewC4.ExplodedViaWorld = ItC4.ExplodedViaWorld
- NewC4.QueuedForExplode = ItC4.QueuedForExplode
- NewC4.UniqueExplodeTimer = ItC4.UniqueExplodeTimer
- NewC4.Stuck = ItC4.Stuck
- NewC4.Hit = ItC4.Hit
- NewC4:Spawn()
- table.insert(NewC4.C4Owner.C4s, NewC4)
- if IsValid(NewC4) and ItC4.Hit then
- NewC4:SetCollisionGroup(COLLISION_GROUP_WEAPON)
- NewC4:SetSolid(SOLID_VPHYSICS)
- NewC4:SetMoveType(MOVETYPE_NONE)
- NewC4:SetNWBool("CanUse", true)
- NewC4:SetNWBool("Hit", ItC4.Hit)
- end
- NewC4:Activate()
- if IsValid(ItC4.PhysData) and ItC4.Hit then
- NewC4:SetParent(ItC4.PhysData.HitEntity)
- end
- end
- end
- if istable( self.ArchivedTacInserts ) and not table.IsEmpty(self.ArchivedTacInserts) then
- for k, ItInsert in ipairs(self.ArchivedTacInserts) do
- local NewInsert = ents.Create("cod-tac-insert")
- NewInsert:SetPos(ItInsert.Location)
- NewInsert:SetAngles(ItInsert.Rotation)
- NewInsert.TacOwner = ItInsert.TacOwner
- NewInsert.Owner = ItInsert.Owner
- NewInsert:SetOwner(ItInsert.Owner)
- NewInsert:SetNWString("TacOwner", ItInsert.NwTacOwner)
- NewInsert:SetNWString("OwnerID", ItInsert.OwnerID)
- NewInsert:Spawn()
- NewInsert:Activate()
- table.insert(NewInsert.TacOwner.Tacs, NewInsert)
- end
- end
- local TotalTable = {Constraints = {}, Entities = {}}
- local function BetterInherit(t, base)
- for k, v in pairs(base) do
- if t[k] == nil then
- t[k] = v
- elseif v.IsNextBot then
- local i = k + 1
- while t[i] ~= nil and t[i].IsNextBot do
- i = i + 1
- end
- t[i] = v
- end
- end
- return t
- end
- for k, it in ipairs(tab) do
- if istable(it.Entities) then
- BetterInherit(TotalTable.Entities, it.Entities)
- end
- if istable(it.Constraints) then
- BetterInherit(TotalTable.Constraints, it.Constraints)
- end
- end
- self:PasteArchive( nil, TotalTable.Entities, TotalTable.Constraints )
- for k,grenade in pairs(ents.FindByClass("npc_grenade_frag")) do
- grenade:Fire("settimer",3)
- end
- DisablePropCreateEffect = nil
- end
- function ENT:CleanupMap()
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- if not bShouldSaveOwnerOnly then
- net.Start("CleanupTimebombRagdolls")
- net.Broadcast()
- self:CleanupWeapons()
- game.CleanUpMap(false, self.EntityBlacklist)
- else
- self:CleanupPersonalProps(self.BombOwner)
- end
- for k, timebomb in pairs(ents.FindByClass("cod-timebomb")) do
- if timebomb ~= self then
- timebomb:Remove()
- end
- end
- end
- function ENT:CleanupPersonalProps(ply)
- if ( !IsValid( ply ) ) then
- return
- end
- local id = ply:UniqueID()
- local CleanupList = cleanup.GetList()
- if ( !CleanupList[ id ] ) then
- return
- end
- local count = 0
- for key, val in pairs( CleanupList[ id ] ) do
- for _, ent in pairs( val ) do
- local bDoesPlayerOwnProp = IsValid(ent) and (ent:GetOwner() == ply or self:GetPropOwningPlayer(ent) == ply)
- if ( IsValid( ent ) and not table.HasValue(self.EntityBlacklist, ent:GetClass()) and bDoesPlayerOwnProp) then
- local Ents = {}
- local Constraints = {}
- if not ent:IsNextBot() then
- self:GetEntityConstraints( ent, Ents, Constraints )
- else
- Ents = {Ent}
- end
- for k,v in pairs(Ents) do
- v:Remove()
- end
- end
- count = count + 1
- end
- table.Empty( val )
- end
- end
- function ENT:GetPropOwningPlayer(ent)
- if !IsValid(ent) or bIsPlayingZombies then
- return nil
- end
- if ent:IsNextBot() then
- return ent:GetCreator()
- end
- if !istable(ent:GetTable().OnDieFunctions) then
- return nil
- end
- local undoKey
- for key, _ in pairs(ent:GetTable().OnDieFunctions) do
- if string.find(key, "undo") then
- undoKey = key
- break
- end
- end
- if undoKey then
- local player = nil
- local args = ent:GetTable().OnDieFunctions[undoKey].Args
- for i, arg in ipairs(args) do
- if type(arg) == "Player" then
- player = arg
- break
- end
- end
- if player then
- return player
- end
- end
- return nil
- end
- function ENT:GetArchivedWorld()
- local SavedProps = {}
- local SavedIndexes = {}
- local ClassBlacklist = self.EntityBlacklist
- local ZombiesConfig = file.Read("codzombies/timebomb.txt")
- if ZombiesConfig then
- local BrokenLines = string.Explode("\n", ZombiesConfig)
- for i = 5, #BrokenLines do
- local ent_class = string.Trim(BrokenLines[i]) -- remove leading and trailing whitespaces
- if ent_class != "" then -- if the line is not empty
- table.insert(ClassBlacklist, ent_class)
- end
- end
- end
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- local Ents = ents.GetAll()
- for index, prop in ipairs(Ents) do
- if not IsValid(prop) or
- not duplicator.IsAllowed( prop:GetClass() ) or
- --not gmsave.ShouldSaveEntity( prop, prop:GetSaveTable() ) or
- prop:IsConstraint() or
- prop:IsWeapon() or
- string.match(prop:GetClass(), "bulletpos") or
- (prop:GetClass() == "prop_physics" and IsValid(prop:GetParent()) and prop:GetParent():GetClass() == "sent_sakarias_carwheel") or
- table.HasValue(ClassBlacklist, prop:GetClass()) then
- continue
- end
- if bShouldSaveOwnerOnly and ((IsValid(prop:GetOwner()) and prop:GetOwner() ~= self.BombOwner) or (IsValid(self:GetPropOwningPlayer(prop)) and self:GetPropOwningPlayer(prop) ~= self.BombOwner)) then
- continue
- end
- -- Check if entity is already being copied
- if not SavedIndexes[prop:EntIndex()] then
- local connectedEntities = {}
- local constraintTable = {}
- if not prop:IsNextBot() then
- self:GetEntityConstraints(prop, connectedEntities, constraintTable)
- else
- connectedEntities = {prop}
- end
- -- Check for connected entities that are already saved
- local skipIteration = false
- for k, connectedEnt in pairs(connectedEntities) do
- if SavedIndexes[connectedEnt:EntIndex()] then
- skipIteration = true
- break
- end
- end
- if not skipIteration then
- local savedProp = self:CopyEntity(prop)
- table.insert(SavedProps, savedProp)
- SavedIndexes[prop:EntIndex()] = true
- for k, v in pairs(connectedEntities) do
- if not SavedIndexes[v:EntIndex()] then
- SavedIndexes[v:EntIndex()] = true
- end
- end
- end
- end
- end
- --[[
- local Ents = ents.GetAll()
- for index, prop in ipairs(Ents) do
- if not IsValid(prop) or
- not duplicator.IsAllowed( prop:GetClass() ) or
- --not gmsave.ShouldSaveEntity( prop, prop:GetSaveTable() ) or
- prop:IsConstraint() or
- prop:IsWeapon() or
- string.match(prop:GetClass(), "bulletpos") or
- table.HasValue(ClassBlacklist, prop:GetClass()) then
- continue
- end
- -- Check if entity is already being copied
- if not table.HasValue(SavedIndexes, prop:EntIndex()) then
- local connectedEntities = {}
- local constraintTable = {}
- if !prop:IsNextBot() then
- self:GetEntityConstraints(prop, connectedEntities, constraintTable)
- else
- connectedEntities = {prop}
- end
- -- Check for connected entities that are already saved
- local skipIteration = false
- for k, connectedEnt in pairs(connectedEntities) do
- if table.HasValue(SavedIndexes, connectedEnt:EntIndex()) then
- skipIteration = true
- break
- end
- end
- if not skipIteration then
- local savedProp = self:CopyEntity(prop)
- table.insert(SavedProps, savedProp)
- table.insert(SavedIndexes, prop:EntIndex())
- for k, v in pairs(connectedEntities) do
- if not table.HasValue(SavedIndexes, v:EntIndex()) then
- table.insert(SavedIndexes, v:EntIndex())
- end
- end
- end
- end
- end
- ]]
- if bIsPlayingZombies then
- self.StoredRound = nzRound:GetNumber()
- self.ZombiesKilled = nzRound:GetZombiesKilled()
- end
- -- This is to copy the constraints that are applied to the world only (ropes, etc)
- -- It will not actually save and then try to restore the world entity, as that would cause issues
- -- table.insert( SavedProps, game.GetWorld() )
- local WorldConstraints = self:CopyEntity(game.GetWorld())
- local CleanedWorldStuff = {
- Constraints = table.Copy(WorldConstraints.Constraints),
- Entities = table.Copy(WorldConstraints.Entities),
- }
- table.insert(SavedProps, CleanedWorldStuff)
- self:ArchiveClaymores()
- self:ArchiveC4()
- self:ArchiveTacInserts()
- SavedProps.Players = {}
- if bShouldSaveOwnerOnly then
- SavedProps.Players[tostring(self.BombOwner:SteamID())] = self:GetPlayerInfo(self.BombOwner)
- else
- for k, ply in pairs(player.GetHumans()) do
- SavedProps.Players[tostring(ply:SteamID())] = self:GetPlayerInfo(ply)
- end
- end
- return util.TableToJSON( SavedProps )
- end
- function ENT:CopyEntity( Ent, AddToTable )
- local Ents = {}
- local Constraints = {}
- if not Ent:IsNextBot() then
- self:GetEntityConstraints( Ent, Ents, Constraints )
- else
- Ents = {Ent}
- end
- local EntTables = {}
- if ( AddToTable != nil ) then EntTables = AddToTable.Entities or {} end
- for k, v in pairs( Ents ) do
- if v.IsLambdaSpawned then
- continue
- end
- if not Ent:IsNextBot() then
- EntTables[ k ] = duplicator.CopyEntTable( v )
- if self:GetPropOwningPlayer(v) ~= nil and self:GetPropOwningPlayer(v):SteamID() ~= nil then
- EntTables[k].OwningPlayer = tostring(self:GetPropOwningPlayer(v):SteamID())
- end
- if v:IsVehicle() and IsValid(v:GetDriver()) then
- EntTables[k].VehiclePassenger = v:GetDriver():SteamID()
- if not v.IsScar and not v.EngineRPM then
- EntTables[k].CamInfo = {}
- EntTables[k].CamInfo.bIsThirdPerson = v:GetThirdPersonMode()
- EntTables[k].CamInfo.Distance = v:GetCameraDistance()
- EntTables[k].CamInfo.EyeAngles = v:GetDriver():GetAimVector():Angle()
- end
- end
- else
- local output = {}
- self:GetNextbotInfo(output, v)
- EntTables[ k ] = output
- if Ent:GetClass() == "npc_lambdaplayer" then
- EntTables[k].OwningPlayer = tostring(Ent:GetCreator():SteamID())
- elseif self:GetPropOwningPlayer(v) ~= nil and self:GetPropOwningPlayer(v):SteamID() ~= nil then
- EntTables[k].OwningPlayer = tostring(self:GetPropOwningPlayer(v):SteamID())
- end
- end
- end
- local ConstraintTables = {}
- if !Ent:IsNextBot() then
- if ( AddToTable != nil ) then ConstraintTables = AddToTable.Constraints or {} end
- for k, v in pairs( Constraints ) do
- ConstraintTables[ k ] = v
- end
- end
- local mins, maxs = duplicator.WorkoutSize( EntTables )
- return {
- Entities = EntTables,
- Constraints = ConstraintTables,
- Mins = mins,
- Maxs = maxs
- }
- end
- --
- -- The physics object Saver/Loader
- --
- local NextBotPhysicsObject =
- {
- Save = function( data, phys )
- data.Pos = phys:GetPos()
- data.Angle = phys:GetAngles()
- data.Frozen = !phys:IsMoveable()
- if ( !phys:IsGravityEnabled() ) then data.NoGrav = true end
- if ( phys:IsAsleep() ) then data.Sleep = true end
- data.Pos, data.Angle = WorldToLocal( data.Pos, data.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
- end,
- Load = function( data, phys )
- if ( isvector( data.Pos ) && isangle( data.Angle ) ) then
- local pos, ang = LocalToWorld( data.Pos, data.Angle, LocalPos, LocalAng )
- phys:SetPos( pos )
- phys:SetAngles( ang )
- end
- -- Let's not Wake or put anything to sleep for now
- --[[
- if ( data.Sleep ) then
- if ( IsValid( phys ) ) then phys:Sleep() end
- else
- phys:Wake()
- end
- ]]
- if ( data.Frozen ) then
- phys:EnableMotion( false )
- -- If we're being created by a player then add these to their frozen list so they can unfreeze them all
- if ( IsValid( ActionPlayer ) ) then
- ActionPlayer:AddFrozenPhysicsObject( phys:GetEntity(), phys )
- end
- end
- if ( data.NoGrav ) then phys:EnableGravity( false ) end
- end,
- }
- --
- -- Entity physics saver
- --
- local NextbotPhysics =
- {
- --
- -- Loop each bone, calling PhysicsObject.Save
- --
- Save = function( data, Entity )
- local num = Entity:GetPhysicsObjectCount()
- for objectid = 0, num-1 do
- local obj = Entity:GetPhysicsObjectNum( objectid )
- if ( !IsValid( obj ) ) then continue end
- data[ objectid ] = {}
- NextBotPhysicsObject.Save( data[ objectid ], obj )
- end
- end,
- --
- -- Loop each bone, calling PhysicsObject.Load
- --
- Load = function( data, Entity )
- if ( !istable( data ) ) then return end
- for objectid, objectdata in pairs( data ) do
- local Phys = Entity:GetPhysicsObjectNum( objectid )
- if ( !IsValid( Phys ) ) then continue end
- PhysicsObject.Load( objectdata, Phys )
- end
- end,
- }
- --
- -- Nextbot Saver
- --
- function ENT:GetNextbotInfo(data, ent)
- --
- -- Called on each entity when saving
- --
- if ent:GetClass() ~= "npc_lambdaplayer" then
- if ( ent.PreEntityCopy ) then ent:PreEntityCopy() end
- if ( ent.PostEntityCopy ) then ent:PostEntityCopy() end
- end
- --
- -- Set so me generic variables that pretty much all entities
- -- would like to save.
- --
- data.Pos = ent:GetPos()
- data.Angle = ent:GetAngles()
- data.Class = ent:GetClass()
- data.Model = ent:GetModel()
- data.Skin = ent:GetSkin()
- data.Mins, data.Maxs = ent:GetCollisionBounds()
- data.ColGroup = ent:GetCollisionGroup()
- data.Name = ent:GetName()
- data.WorkshopID = ent:GetWorkshopID()
- data.IsNextBot = true
- data.Creator = ent:GetCreator()
- data.Pos, data.Angle = WorldToLocal( data.Pos, data.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
- data.ModelScale = ent:GetModelScale()
- if ( data.ModelScale == 1 ) then data.ModelScale = nil end
- -- Allow the entity to override the class
- -- (this is a hack for the jeep, since it's real class is different from the one it reports as)
- if ( ent.ClassOverride ) then data.Class = ent.ClassOverride end
- -- Save the physics
- data.PhysicsObjects = data.PhysicsObjects or {}
- NextbotPhysics.Save( data.PhysicsObjects, ent )
- -- Flexes
- data.FlexScale = ent:GetFlexScale()
- for i = 0, ent:GetFlexNum() do
- local w = ent:GetFlexWeight( i )
- if ( w != 0 ) then
- data.Flex = data.Flex or {}
- data.Flex[ i ] = w
- end
- end
- -- Body Groups
- local bg = ent:GetBodyGroups()
- if ( bg ) then
- for k, v in pairs( bg ) do
- --
- -- If it has a non default setting, save it.
- --
- if ( ent:GetBodygroup( v.id ) > 0 ) then
- data.BodyG = data.BodyG or {}
- data.BodyG[ v.id ] = ent:GetBodygroup( v.id )
- end
- end
- end
- -- Non Sandbox tool set colors and material
- if ( ent:GetColor() != color_white ) then data._DuplicatedColor = ent:GetColor() end
- if ( ent:GetMaterial() != "" ) then data._DuplicatedMaterial = ent:GetMaterial() end
- -- Bone Manipulator
- if ( ent:HasBoneManipulations() ) then
- data.BoneManip = {}
- for i = 0, ent:GetBoneCount() do
- local t = {}
- local s = ent:GetManipulateBoneScale( i )
- local a = ent:GetManipulateBoneAngles( i )
- local p = ent:GetManipulateBonePosition( i )
- if ( s != Vector( 1, 1, 1 ) ) then t[ 's' ] = s end -- scale
- if ( a != angle_zero ) then t[ 'a' ] = a end -- angle
- if ( p != vector_origin ) then t[ 'p' ] = p end -- position
- if ( !table.IsEmpty( t ) ) then
- data.BoneManip[ i ] = t
- end
- end
- end
- --
- -- Store networks vars/DT vars (assigned using SetupDataTables)
- --
- if ( ent.GetNetworkVars ) then
- data.DT = ent:GetNetworkVars()
- end
- -- Make this function on your SENT if you want to modify the
- -- returned table specifically for your entity.
- if ( ent.OnEntityCopyTableFinish ) then
- ent:OnEntityCopyTableFinish( data )
- end
- --
- -- Exclude this crap
- --
- for k, v in pairs( data ) do
- if ( isfunction( v ) ) then
- data[k] = nil
- end
- end
- data.OnDieFunctions = nil
- data.AutomaticFrameAdvance = nil
- data.BaseClass = nil
- end
- function ENT:GetEntityConstraints( ent, OutEntTable, OutConstraintTable, CheckedEnts )
- if ( !IsValid( ent ) && !ent:IsWorld() ) then return end
- if !ent:IsNextBot() then
- if not istable(CheckedEnts) then
- CheckedEnts = {}
- end
- if table.HasValue(CheckedEnts, ent) then
- return
- end
- table.insert(CheckedEnts, ent)
- else
- --table.insert(OutEntTable, ent)
- --OutEntTable = {ent}
- return {ent}, {}
- end
- -- Translate the class name
- local classname = ent:GetClass()
- if ( ent.ClassOverride ) then classname = ent.ClassOverride end
- -- Is the entity in the dupe whitelist?
- if ( !duplicator.IsAllowed( classname ) && !ent:IsWorld() ) then
- return
- end
- -- Entity doesn't want to be duplicated.
- if ( ent.DoNotDuplicate ) then return end
- if ( !ent:IsWorld() ) then OutEntTable[ ent:EntIndex() ] = ent end
- if ( !constraint.HasConstraints( ent ) ) then return end
- local FoundConstraints = constraint.GetTable( ent )
- for key, constr in pairs( FoundConstraints ) do
- if ( table.HasValue(OutConstraintTable, constr) or table.HasValue(CheckedEnts, constr.Entity) ) then
- continue
- end
- -- Add constraint to the constraints table
- OutConstraintTable[ #OutConstraintTable + 1 ] = constr
- -- Run the Function for any ents attached to this constraint
- for _, ItConstrainedEnt in pairs( constr.Entity ) do
- if ( !ItConstrainedEnt.Entity:IsWorld() ) then
- self:GetEntityConstraints( ItConstrainedEnt.Entity, OutEntTable, OutConstraintTable, CheckedEnts )
- end
- end
- end
- return OutEntTable, OutConstraintTable
- end
- function ENT:PasteArchive( Player, EntityList, ConstraintList )
- --
- -- Store the player
- --
- local oldplayer = ActionPlayer
- ActionPlayer = Player
- --
- -- Copy the table - because we're gonna be changing some stuff on it.
- --
- local EntityList = table.Copy( EntityList )
- local ConstraintList = table.Copy( ConstraintList )
- local CreatedEntities = {}
- --
- -- Create the Entities
- --
- for k, EntFromList in pairs( EntityList ) do
- local e = nil
- local b = ProtectedCall( function() e = self:CreateEntityFromTable( Player, EntFromList ) end )
- if ( !b ) then continue end
- if ( IsValid( e ) ) then
- --
- -- Call this here ( as well as before :Spawn) because Spawn/Init might have stomped the values
- --
- if ( e.RestoreNetworkVars ) then
- e:RestoreNetworkVars( EntFromList.DT )
- end
- if ( e.OnDuplicated ) then
- e:OnDuplicated( EntFromList )
- end
- if not bIsPlayingZombies then
- if EntFromList.VehiclePassenger ~= nil and e:IsVehicle() then
- --local passenger = player.GetByID(EntFromList.VehiclePassenger)
- local passenger = player.GetBySteamID( EntFromList.VehiclePassenger )
- if IsValid(passenger) and passenger:IsPlayer() then
- passenger:EnterVehicle(e)
- if not e.IsScar and not e.EngineRPM then
- e:SetThirdPersonMode(EntFromList.CamInfo.bIsThirdPerson)
- e:SetCameraDistance(EntFromList.CamInfo.Distance)
- passenger:SetEyeAngles(EntFromList.CamInfo.EyeAngles)
- elseif e.EngineRPM then
- e:StopEngine()
- passenger:SetMoveType(MOVETYPE_WALK)
- e:SetPos(e:GetPos() + Vector(0,0,20))
- end
- end
- end
- if EntFromList.OwningPlayer ~= nil then
- local TargetPlayer = player.GetBySteamID(EntFromList.OwningPlayer)
- print(TargetPlayer)
- e:SetCreator(TargetPlayer)
- undo.Create("")
- undo.AddEntity(e)
- undo.SetPlayer(TargetPlayer)
- undo.Finish()
- cleanup.Add(TargetPlayer, "props", e)
- end
- end
- end
- CreatedEntities[ k ] = e
- if ( CreatedEntities[ k ] ) then
- CreatedEntities[ k ].BoneMods = table.Copy( EntFromList.BoneMods )
- CreatedEntities[ k ].EntityMods = table.Copy( EntFromList.EntityMods )
- CreatedEntities[ k ].PhysicsObjects = table.Copy( EntFromList.PhysicsObjects )
- else
- CreatedEntities[ k ] = nil
- end
- end
- --
- -- Apply modifiers to the created entities
- --
- for EntID, Ent in pairs( CreatedEntities ) do
- duplicator.ApplyEntityModifiers( Player, Ent )
- duplicator.ApplyBoneModifiers( Player, Ent )
- if ( Ent.PostEntityPaste ) then
- Ent:PostEntityPaste( Player || NULL, Ent, CreatedEntities )
- end
- end
- local CreatedConstraints = {}
- --
- -- Create constraints
- --
- for k, Constraint in pairs( ConstraintList ) do
- local Entity = nil
- ProtectedCall( function() Entity = self:CreateConstraints( Constraint, CreatedEntities, Player ) end )
- if ( IsValid( Entity ) ) then
- table.insert( CreatedConstraints, Constraint )
- end
- end
- ActionPlayer = oldplayer
- return CreatedEntities, CreatedConstraints
- end
- --[[---------------------------------------------------------
- Create an entity from a table.
- -----------------------------------------------------------]]
- function ENT:CreateEntityFromTable( Player, EntTable )
- --
- -- Convert position/angle to `local`
- --
- if ( EntTable.Pos && EntTable.Angle ) then
- EntTable.Pos, EntTable.Angle = LocalToWorld( EntTable.Pos, EntTable.Angle, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
- end
- if EntTable.Class == "npc_lambdaplayer" then
- local newlambda = ents.Create( "npc_lambdaplayer" )
- newlambda:SetPos( EntTable.Pos )
- newlambda:SetAngles( EntTable.Angle )
- newlambda:Spawn()
- if EntTable.OwningPlayer ~= nil then
- local TargetPlayer = player.GetBySteamID(EntTable.OwningPlayer)
- print(TargetPlayer)
- newlambda:SetCreator(TargetPlayer)
- undo.Create("")
- undo.AddEntity(newlambda)
- undo.SetPlayer(TargetPlayer)
- undo.Finish()
- cleanup.Add(TargetPlayer, "props", newlambda)
- end
- return
- end
- local EntityClass = duplicator.FindEntityClass( EntTable.Class )
- -- This class is unregistered. Instead of failing try using a generic
- -- Duplication function to make a new copy..
- if ( !EntityClass ) then
- return duplicator.GenericDuplicatorFunction( Player, EntTable )
- end
- -- Build the argument list
- local ArgList = {}
- for iNumber, Key in pairs( EntityClass.Args ) do
- local Arg = nil
- -- Translate keys from old system
- if ( Key == "pos" or Key == "position" ) then Key = "Pos" end
- if ( Key == "ang" or Key == "Ang" or Key == "angle" ) then Key = "Angle" end
- if ( Key == "model" ) then Key = "Model" end
- Arg = EntTable[ Key ]
- -- Special keys
- if ( Key == "Data" ) then Arg = EntTable end
- -- If there's a missing argument then unpack will stop sending at that argument so send it as `false`
- if ( Arg == nil ) then Arg = false end
- ArgList[ iNumber ] = Arg
- end
- -- Create and return the entity
- return EntityClass.Func( Player, unpack( ArgList ) )
- end
- function ENT:CreateConstraints( Constraint, EntityList, Player )
- local Factory = duplicator.ConstraintType[ Constraint.Type ]
- if ( !Factory ) then return end
- local Args = {}
- for k, Key in pairs( Factory.Args ) do
- local Val = Constraint[ Key ]
- for i = 1, 6 do
- if ( Constraint.Entity[ i ] ) then
- if ( Key == "Ent" .. i ) then
- Val = EntityList[ Constraint.Entity[ i ].Index ]
- if ( Constraint.Entity[ i ].World ) then
- Val = game.GetWorld()
- end
- end
- if ( Key == "Bone" .. i ) then Val = Constraint.Entity[ i ].Bone or 0 end
- if ( Key == "LPos" .. i ) then Val = Constraint.Entity[ i ].LPos end
- if ( Key == "WPos" .. i ) then Val = Constraint.Entity[ i ].WPos end
- if ( Key == "Length" .. i ) then Val = Constraint.Entity[ i ].Length or 0 end
- end
- end
- -- A little hack to give the duped constraints the correct player object
- if ( Key:lower() == "pl" || Key:lower() == "ply" || Key:lower() == "player" ) then Val = Player end
- -- If there's a missing argument then unpack will stop sending at that argument
- if ( Val == nil ) then Val = false end
- table.insert( Args, Val )
- end
- local NewConstraint = Factory.Func( unpack( Args ) )
- return NewConstraint
- end
- function ENT:ArchiveClaymores()
- local AllClaymores = ents.FindByClass("seal6-claymore-bo2-ent")
- table.Merge(AllClaymores, ents.FindByClass("seal6-claymore-ent"))
- if table.IsEmpty(AllClaymores) then
- return
- end
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- for k,ItClaymore in ipairs(AllClaymores) do
- local bDoesPlayerOwnProp = IsValid(ItClaymore.ClayOwner) and ItClaymore.ClayOwner == self.BombOwner
- if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
- continue
- end
- local SavedClaymore = {}
- SavedClaymore.Class = ItClaymore:GetClass()
- SavedClaymore.Location = ItClaymore:GetPos()
- SavedClaymore.Rotation = ItClaymore:GetAngles()
- --SavedClaymore.ClayParent = ItClaymore.ClayParent
- SavedClaymore.OwnerID = ItClaymore:GetNWString("OwnerID")
- SavedClaymore.ClayOwner = ItClaymore.ClayOwner
- --SavedClaymore.Kids = nil
- table.insert(self.ArchivedClaymores, SavedClaymore)
- end
- end
- function ENT:ArchiveC4()
- local AllC4s = ents.FindByClass("cod-c4")
- if table.IsEmpty(AllC4s) then
- return
- end
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- for k,ItC4 in ipairs(AllC4s) do
- local bDoesPlayerOwnProp = IsValid(ItC4.C4Owner) and ItC4.C4Owner == self.BombOwner
- if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
- continue
- end
- local SavedC4 = {}
- SavedC4.Location = ItC4:GetPos()
- SavedC4.Rotation = ItC4:GetAngles()
- SavedC4.C4Owner = ItC4.C4Owner
- SavedC4.OwnerID = ItC4:GetNWString("OwnerID")
- SavedC4.ThisTrigger = ItC4.ThisTrigger
- SavedC4.ExplodedViaWorld = ItC4.ExplodedViaWorld
- SavedC4.QueuedForExplode = ItC4.QueuedForExplode
- SavedC4.UniqueExplodeTimer = ItC4.UniqueExplodeTimer
- SavedC4.Stuck = ItC4.Stuck
- SavedC4.Hit = ItC4.Hit
- if IsValid(ItC4.PhysData) then
- SavedC4.PhysData = ItC4.PhysData
- end
- table.insert(self.ArchivedC4s, SavedC4)
- end
- end
- function ENT:ArchiveTacInserts()
- local AllTacInserts = ents.FindByClass("cod-tac-insert")
- if table.IsEmpty(AllTacInserts) then
- return
- end
- local bShouldSaveOwnerOnly = ConVarExists("TimeBomb_AffectSelfOnly") and GetConVar("TimeBomb_AffectSelfOnly"):GetBool() or false
- for k,ItTacInsert in ipairs(AllTacInserts) do
- local bDoesPlayerOwnProp = IsValid(ItTacInsert.TacOwner) and ItTacInsert.TacOwner == self.BombOwner
- if bShouldSaveOwnerOnly and not bDoesPlayerOwnProp then
- continue
- end
- local SavedInsert = {}
- SavedInsert.Location = ItTacInsert:GetPos()
- SavedInsert.Rotation = ItTacInsert:GetAngles()
- SavedInsert.TacOwner = ItTacInsert.TacOwner
- SavedInsert.Owner = ItTacInsert.Owner
- SavedInsert.NwTacOwner = ItTacInsert:GetNWString("TacOwner")
- SavedInsert.OwnerID = ItTacInsert:GetNWString("OwnerID")
- table.insert(self.ArchivedTacInserts, SavedInsert)
- end
- end
- function ENT:GetPlayerInfo(ent)
- if !IsValid(ent) then
- return
- end
- local tab = {}
- tab.Origin = ent:GetPos()
- tab.Angle = ent:GetAimVector():Angle()
- tab.MoveType = ent:GetMoveType()
- tab.Alive = ent:Alive()
- if ent:Alive() then
- tab.Health = ent:Health()
- tab.Armor = ent:Armor()
- if #ent:GetWeapons() > 0 then
- tab.Weapons = {}
- tab.Ammo = ent:GetAmmo()
- for k, ItWep in ipairs(ent:GetWeapons()) do
- if string.match(ItWep:GetClass(), "zombies_perk_") then
- continue
- end
- if not bIsPlayingZombies and ItWep:GetClass() == "seal6-timebomb" and ent:GetAmmoCount("ammo_timebomb") <= 0 and ent == self.BombOwner then
- local bShouldKeepBomb = ConVarExists("TimeBomb_KeepWatchAfterTravel") and GetConVar("TimeBomb_KeepWatchAfterTravel"):GetBool() or false
- if not bShouldKeepBomb then
- continue
- end
- end
- local SavedWeapon = {}
- SavedWeapon.Class = ItWep:GetClass()
- SavedWeapon.ClipOne = ItWep:Clip1()
- SavedWeapon.ClipTwo = ItWep:Clip2()
- table.insert(tab.Weapons, SavedWeapon)
- end
- if IsValid(ent:GetActiveWeapon()) then
- tab.ActiveWep = ent:GetActiveWeapon():GetClass()
- end
- end
- end
- return tab
- end
- function ENT:SetPlayerInfo(ent, tab)
- if ( tab == nil or ent == nil ) then
- return
- end
- if not ent:Alive() then
- ent:Spawn()
- end
- if tab.Alive then
- if ( tab.Health ) then
- ent:SetHealth(tab.Health)
- end
- if ( tab.Armor ) then
- ent:SetArmor(tab.Armor)
- end
- if tab.Weapons then
- ent:StripWeapons()
- if bIsPlayingZombies then
- ent:SetUsingSpecialWeapon(false)
- end
- for k, weapon in ipairs(tab.Weapons) do
- local GivenWeapon = ent:Give(weapon.Class, true)
- GivenWeapon:SetClip1(weapon.ClipOne)
- GivenWeapon:SetClip2(weapon.ClipTwo)
- end
- end
- if tab.Ammo then
- timer.Simple(1, function()
- for k, ammo in ipairs(tab.Ammo) do
- ent:SetAmmo(ammo, k)
- end
- end)
- end
- if tab.ActiveWep ~= nil and tab.ActiveWep ~= "" and tab.ActiveWep ~= "seal6-timebomb" then
- ent:SelectWeapon(tab.ActiveWep)
- end
- if ( tab.MoveType ) then
- ent:SetMoveType( tab.MoveType )
- end
- else
- ent:Spawn()
- end
- if ( tab.Origin ) then
- ent:SetPos( tab.Origin )
- end
- if ( tab.Angle ) then
- ent:SetEyeAngles( tab.Angle )
- end
- end
- function ENT:CleanupWeapons()
- local WeaponTable = {}
- table.Add(WeaponTable, ents.FindByClass("weapon_*"))
- table.Add(WeaponTable, ents.FindByClass("ai_weapon_*"))
- table.Add(WeaponTable, ents.FindByClass("item_ammo_ar2_altfire"))
- table.Add(WeaponTable, ents.FindByClass("item_healthvial"))
- for k,lambda in pairs(ents.FindByClass("npc_lambdaplayer")) do
- if IsValid(lambda.WeaponEnt) then
- lambda.WeaponEnt:Remove()
- end
- end
- for k,wep in pairs(WeaponTable) do
- if not IsValid(wep:GetOwner()) then
- wep:Remove()
- end
- end
- end
- function ENT:FreezeNPCs()
- for k, npc in pairs(ents.GetAll()) do
- if npc:IsNPC() then
- npc:CapabilitiesRemove(CAP_MOVE_GROUND)
- npc:CapabilitiesRemove(CAP_USE_WEAPONS)
- elseif npc:IsNextBot() then
- npc.BehaveThread = coroutine.create(function()
- coroutine.wait(5)
- end)
- end
- end
- end
- function ENT:PlayScreenOverlayFX()
- net.Start( "CreateTimeBombOverlay" )
- net.Broadcast()
- end
- function ENT:Initialize()
- CreateTimeBombConfig()
- self:SetModel( "models/hoff/weapons/timebomb/w_timebomb.mdl" )
- self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
- self:PhysicsInit( SOLID_VPHYSICS )
- self:SetMoveType( MOVETYPE_VPHYSICS )
- self:SetSolid( SOLID_VPHYSICS )
- self:DrawShadow(false)
- local phys = self:GetPhysicsObject()
- if (phys:IsValid()) then
- phys:Wake()
- end
- ParticleEffectAttach("vortigaunt_hand_glow", PATTACH_POINT_FOLLOW, self, 1)
- end
- function ENT:PhysgunPickup(ply, ent)
- if ent:GetClass() == "cod-timebomb" then
- return false
- end
- end
- function ENT:SetupDataTables()
- self:DTVar( "Float", 0, "RotationSeed1" )
- self:DTVar( "Float", 1, "RotationSeed2" )
- end
- function ENT:OnRemove()
- self:StopSound("hoff/zmb/timebomb/timebomb_plant_2d.mp3")
- self.ThisTrigger:SetNWBool("bTimeBombOut", false)
- if bIsPlayingZombies then
- net.Start( "RemoveTimeBombRound" )
- net.WriteEntity(self.BombOwner)
- net.Send(self.BombOwner)
- end
- timer.Remove("TimeBombArchiver" .. self:EntIndex())
- end
- function ENT:PhysicsCollide(data,phys)
- if data.HitEntity:GetClass() == "cod-timebomb" or data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then return end
- if self:IsValid() and not self.Hit then
- -- Instead of changing the collision group directly,
- -- set a flag that we want to change the collision group
- -- and start a timer to do it after the PhysicsCollide callback has finished.
- self.ChangeCollisionGroup = true
- timer.Simple(0, function()
- if self.ChangeCollisionGroup then
- self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
- self.ChangeCollisionGroup = false
- local bHitValidEntity = IsValid(data.HitEntity)
- if bHitValidEntity then
- self:SetSolid(SOLID_VPHYSICS)
- self:SetMoveType(MOVETYPE_NONE)
- self:SetParent(data.HitEntity)
- self.Stuck = true
- self.Hit = true
- else
- self:SetMoveType(MOVETYPE_NONE)
- end
- self:EmitSound("hoff/zmb/timebomb/timebomb_plant_2d.mp3")
- if IsValid(self.ThisTrigger) then
- self.ThisTrigger:SetNWBool("bTimeBombOut", true)
- end
- self:StoreOwnedProps()
- if IsValid(phys) then
- local angVel = phys:GetAngleVelocity()
- local maxAngVel = 1000
- if angVel:Length() > maxAngVel then
- angVel = angVel:GetNormalized() * maxAngVel
- phys:SetAngleVelocity(angVel)
- end
- end
- local HitAngle = data.HitNormal:Angle()
- HitAngle.p = HitAngle.p + 270
- self:SetPos(data.HitPos + (data.HitNormal / 5))
- -- Generate a random yaw angle between -60 and 60 degrees
- local yaw = math.random(-60, 60)
- self:SetAngles(HitAngle)
- -- Rotate the Angle object around the entity's up vector using the RotateAroundAxis function
- HitAngle:RotateAroundAxis(self:GetUp(), yaw)
- -- Set the entity's angles to the rotated angles
- self:SetAngles(HitAngle)
- self:SetOwner(nil)
- end
- end)
- self:SetNWBool("Hit", true)
- self.Hit = true
- end
- end
- function ENT:Touch(ent)
- end
- ENT.CanUse = true
- ENT.LFS = true
- function ENT:Use( activator, caller )
- if activator:IsPlayer() and self.CanUse and self:GetNWString("OwnerID") == activator:SteamID() then
- self.CanUse = false
- if SERVER then
- if activator:HasWeapon("seal6-timebomb") and (not GetConVar("TimeBomb_Infinite"):GetBool() or (GetConVar("TimeBomb_Infinite"):GetBool() and activator:GetAmmoCount("ammo_timebomb") < 1)) then
- activator:GiveAmmo(1, "ammo_timebomb")
- else
- activator:Give("seal6-timebomb")
- activator:SelectWeapon("seal6-timebomb")
- end
- self:Remove()
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment