--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] --[[--------------------------------------------------------- Name: scripted_ents Desc: Scripted Entity factory -----------------------------------------------------------]] module( "scripted_ents", package.seeall ) local Aliases = {} local SEntList = {} local BaseClasses = {} BaseClasses[ "anim" ] = "base_anim" BaseClasses[ "point" ] = "base_point" BaseClasses[ "brush" ] = "base_brush" BaseClasses[ "filter" ] = "base_filter" --[[--------------------------------------------------------- Name: TableInherit( t, base ) Desc: Copies any missing data from base to t -----------------------------------------------------------]] local function TableInherit( t, base ) for k, v in pairs( base ) do if ( t[ k ] == nil ) then t[ k ] = v elseif ( k != "BaseClass" && istable( t[ k ] ) && istable( v ) ) then TableInherit( t[ k ], v ) end end t[ "BaseClass" ] = base return t end --[[--------------------------------------------------------- Name: IsBasedOn( name, base ) Desc: Checks if name is based on base -----------------------------------------------------------]] function IsBasedOn( name, base ) local t = GetStored( name ) if not t then return false end if t.Base == name then return false end if t.Base == base then return true end return IsBasedOn( t.Base, base ) end function Register( t, name ) if ( hook.Run( "PreRegisterSENT", t, name ) == false ) then return end if ( isstring( t.ClassNameOverride ) ) then name = t.ClassNameOverride end local Base = t.Base if ( !Base ) then Base = BaseClasses[ t.Type ] end local old = SEntList[ name ] local tab = {} tab.type = t.Type tab.t = t tab.isBaseType = true tab.Base = Base tab.t.ClassName = name if ( !Base ) then Msg( "WARNING: Scripted entity " .. name .. " has an invalid base entity!\n" ) end SEntList[ name ] = tab -- Allow all SENTS to be duplicated, unless specified if ( !t.DisableDuplicator ) then duplicator.Allow( name ) end -- -- If we're reloading this entity class -- then refresh all the existing entities. -- if ( old != nil ) then -- -- For each entity using this class -- for _, entity in ipairs( ents.FindByClass( name ) ) do -- -- Replace the contents with this entity table -- table.Merge( entity, tab.t ) -- -- Call OnReloaded hook (if it has one) -- if ( entity.OnReloaded ) then entity:OnReloaded() end end -- Update entity table of entities that are based on this entity for _, e in ipairs( ents.GetAll() ) do if ( IsBasedOn( e:GetClass(), name ) ) then table.Merge( e, Get( e:GetClass() ) ) if ( e.OnReloaded ) then e:OnReloaded() end end end end if ( !t.Spawnable ) then return end list.Set( "SpawnableEntities", name, { -- Required information PrintName = t.PrintName, ClassName = name, Category = t.Category, -- Optional information NormalOffset = t.NormalOffset, DropToFloor = t.DropToFloor, Author = t.Author, AdminOnly = t.AdminOnly, Information = t.Information, ScriptedEntityType = t.ScriptedEntityType, IconOverride = t.IconOverride } ) end -- -- All scripts have been loaded... -- function OnLoaded() -- -- Once all the scripts are loaded we can set up the baseclass -- - we have to wait until they're all setup because load order -- could cause some entities to load before their bases! -- for k, v in pairs( SEntList ) do baseclass.Set( k, Get( k ) ) end end function Get( name, retval ) -- Do we have an alias? if ( Aliases[ name ] ) then name = Aliases[ name ] end if ( SEntList[ name ] == nil ) then return nil end -- Create/copy a new table local retval = retval or {} for k, v in pairs( SEntList[ name ].t ) do if ( istable( v ) ) then retval[ k ] = table.Copy( v ) else retval[ k ] = v end end -- Derive from base class if ( SEntList[ name ].Base != name ) then local base = Get( SEntList[ name ].Base ) if ( !base ) then Msg("ERROR: Trying to derive entity " .. tostring( name ) .. " from non existant entity " .. tostring( SEntList[ name ].Base ) .. "!\n" ) else retval = TableInherit( retval, base ) end end return retval end function GetType( name ) for k, v in pairs( BaseClasses ) do if ( name == v ) then return k end end local ent = SEntList[ name ] if ( ent == nil ) then return nil end if ( ent.type ) then return ent.type end if ( ent.Base ) then return GetType( ent.Base ) end return nil end --[[--------------------------------------------------------- Name: GetStored( string ) Desc: Gets the REAL sent table, not a copy -----------------------------------------------------------]] function GetStored( name ) return SEntList[ name ] end --[[--------------------------------------------------------- Name: GetList( string ) Desc: Get a list of all the registered SENTs -----------------------------------------------------------]] function GetList() local result = {} for k,v in pairs( SEntList ) do result[ k ] = v end return result end function GetSpawnable() local result = {} for k, v in pairs( SEntList ) do local tab = v.t if ( tab.Spawnable ) then table.insert( result, tab ) end end return result end function Alias( From, To ) Aliases[ From ] = To end function GetMember( entity_name, membername ) if ( !entity_name ) then return end local ent = SEntList[ entity_name ] if ( !ent ) then return end local member = ent.t[ membername ] if ( member != nil ) then return member end -- If our base is the same as us - don't infinite loop! if ( entity_name == ent.Base ) then return end return GetMember( ent.Base, membername ) end