ThirdBlog-Top

Thursday, July 2, 2015

Fake Scripted Entity Creation (PART2) (GMOD)

Somewhere else, after creating an entity of this class, I may change the default material for this entity:

MyEntity.DefaultMaterial = "materialname"
Here are some examples of hooks that you may use. Remember: hooks that are not in this example are not implemented, it is your job.

function ENT:Initialize ()
end
In this example the implementation of the hook ENTITY:Initialize in the footer makes that it is not called when you use Entity:Spawn. Instead it is called immediatly when using ents.Create.

Avoid using Entity:Spawn on the fake SENT itself in this hook as this should be done by the script that created the entity. The risk is that Entity:Spawn may be called twice.

Fourth step: the footer

The footer is the most important part of the fake SENT: it modifies the Lua functions to create the expected entity.

local old_FindByClass = ents.FindByClass
function ents.FindByClass ( class, ... )
                if class == ClassName then -- Look for ClassName excluding anything else.
                                local entities = {}

                                for _, ent in pairs( old_FindByClass( BaseClassName ) ) do
                                                if ent:GetClass() == ClassName then
                                                                entities[#entities+1] = ent
                                                end
                                end
                                return entities
                elseif class == BaseClassName then -- Look for BaseClassName excluding ClassName.
                                local entities = {}

                                for _, ent in pairs( old_FindByClass( BaseClassName ) ) do
                                                if ent:GetClass() != ClassName then
                                                                entities[#entities+1] = ent
                                                end
                                end
                                return entities
                else
                                return old_FindByClass( class, ... )
                end
end
When calling ents.FindByClass("prop_vehicle_mr") we want to get a table containing all entities of the class prop_vehicle_mr. Without the code, the table would be always empty.

When calling ents.FindByClass("prop_dynamic") we want to get a table containing all entities of the class prop_dynamic, except that of the class prop_vehicle_mr. Without the code, the table would also contain entities of the class prop_vehicle_mr.

In other cases, ents.FindByClass will work like before.

local old_GetClass = BaseClass.GetClass
function BaseClass:GetClass ( ... )
                -- if self[ClassName] then -- Non-networked classname
                if self:GetNWBool( ClassName, false ) then -- Networked classname
                                return ClassName
                else
                                return old_GetClass( self, ... )
                end
end
We change the Entity:GetClass method in the Entity datatable so the proper value is returned for fake SENTs.

For some reason, the fake SENT class may need not to be shared with the client. In this case, use comment and uncomment the proper lines here and in the ents.Create block below.

local SENT_values = {}

for FuncName, Func in pairs( ENT ) do
                if isfunction( Func ) then -- This is a function value.
                                local old_Func = BaseClass[FuncName]
                                if isfunction( old_Func ) then -- The method is re-defined in the base class.
                                                BaseClass[FuncName] = function ( self, ... )
                                                                if self:GetClass() == ClassName then
                                                                                return Func( self, ... )
                                                                else
                                                                                return old_Func( self, ... )
                                                                end
                                                end
                                else -- The method is not defined in the base class.
                                                SENT_values[FuncName] = Func
                                end
                else -- This is a value that is not a function.
                                SENT_values[FuncName] = Func
                end
end
We modify all methods that exist in the Entity datatable that are defined in the content.

We add all methods that do not exist in the Entity datatable in a table to be added by ents.Create.

We add all properties in a table to be added by ents.Create.

local old_Create = ents.Create
function ents.Create ( class, ... )
                if class == ClassName then
                                local ent = old_Create( BaseClassName, ... )

                                if IsValid( ent ) then

No comments:

Post a Comment