Saving variables in adv duplicator

Hello! I couldnt understand the duplicator functions on the wiki properly. [https://wiki.garrysmod.com/page/Category:duplicator](Yes, i did read it.) and i was wondering how do i save a variable inside a entity for later duping it.

I just need to store a small table of 3 and a string, and well, it’s sorta killing me

So as i think it might work, besides my supositions is this:

I first have to store entity modifiers, with [lua] duplicator.StoreEntityModifiers( self , “table 1”, self.tableName ) [/lua]

Then when i spawn this entity, i would have to place in the initialization duplicator.ApplyEntityModifiers? I’m really lost and i could use some help :slight_smile:

duplicator.ApplyEntityModifiers gets called for you internally if you use Duplicator/AdvDupe/AdvDupe2, so you don’t need to call it yourself.

You can look at all of the Sandbox tools inside of /garrysmod/gamemodes/sandbox/entities/weapons/gmod_tool/stools to get an idea of how it’s already being done.

What you would basically do is define some local or library function that applies whatever modifiers you stored, then register that function as a callback via duplicator.RegisterEntityModifier so that when duplicator.ApplyEntitiyModifiers gets called, it runs your function.

For example, storing mass this way might look something like:



-- serverside
local function SetMass( ply, ent, data )
    if ( not IsValid( ent ) or not IsValid( ent:GetPhysicsObject() ) ) then return end -- don't run on invalid entities
    if ( not data.Mass ) then return end -- don't run if no mass was stored
    
    local phys = ent:GetPhysicsObject()
    phys:SetMass( data.Mass )
    
    duplicator.StoreEntityModifier( ent, "mass", data ) -- store it again for future dupes
end
duplicator.RegisterEntityModifier( "mass", SetMass ) -- register our callback function so it gets called by duplicator.ApplyEntityModifiers


Once you’ve SetMass’d an entity (might look like this), duping it will automatically run SetMass again when it gets spawned. That way the mass get reapplied on the new entity and any other future dupings of it.

(I do nearly the exact same thing on my improved weight tool)

[lua]
function OnDuped( ply, ent, data)

print("called")

if (not IsValid(ent)) or (not IsValid(ent:GetPhysicsObject())) then print("no 1")return end
if (not ent.data ) or (ent.overlayText )then print("no 2")return end

local speed = ent.engineStats.maxSpeed
local angspeed = ent.engineStats.maxAngSpeed
local points = ent.engineStats.maxArmament
local text = ent.OverlayText

ent.data = {speed, angspeed, points,text}

duplicator.StoreEntityModifier(ent , "enginestats" , data)

end
duplicator.RegisterEntityModifier( “enginestats”, onDuped )

function ENT:Initialize()

duplicator.ApplyEntityModifiers( self:GetOwner() , self)

[/lua]
Well, this is what i got so far, I dont know why it wont work, actually i dont know why it would :hurr:

Can you give a little more detail on what you’re trying to accomplish? From your code, it looks like you’re still misunderstanding a few things.

The whole point of doing duplicator.StoreEntityModifier is to save data you want so that it gets reapplied when you dupe your entity and spawn a copy of it. The 3rd parameter of the callback function is the saved data. It might be a bit confusing because we’re using the same function to act as both a callback for duplicator.StoreEntityModifier and and the function we use to store the data. Maybe it would make more sense if they were separated out:



-- Don't make this a global function, keep it local!
-- This function will get called ~only~ when things like Duplicator/AdvDupe/AdvDupe2 are trying to paste an entity with the 'enginestats' modifier applied to it.
-- YOU have to actually store the data on the original entity so that the duped copies will receive it too (that is what ENT:UpdateData is for below).
local function ApplyEngineStats( ply, ent, data )
    print("called")

    if ( not IsValid(ent) ) then print("no 1") return end
    
    -- the 'data' parameter holds the saved values, so apply them to this new duped entity
    ent.enginestats = {
        maxSpeed    = data.maxSpeed,
        maxAngSpeed = data.maxAngSpeed,
        maxArmament = data.maxArmament,
        overlayText = data.overlayText
    }
end
duplicator.RegisterEntityModifier( "enginestats", ApplyEngineStats )


-- Now you can call this function any time one of your 'enginestats' variables changes.
-- The whole reason of doing this is so that it stores the enginestats variables for future duped copies.
function ENT:UpdateData()
    duplicator.StoreEntityModifier( ent, "enginestats", self.enginestats )
end

Now there are 2 functions that do only one thing each, rather than 1 function that makes things a little more confusing.

You don’t call duplicator.ApplyEntityModifiers youself. Get rid of that in your ENT:Initialize() function.

Basically, with the code above, any time you change one of the ‘enginestats’ variables on your entity, you need to call self:UpdateData() to store the new data. That way when you dupe it and spawn it again, ApplyEngineStats() will get called and the ‘data’ parameter will hold the data you stored, thus allowing you to setup the new copy with exactly the same data as the original one.

E.g., if you had something like:



function ENT:SetMaxSpeed( speed )
    self.enginestats.maxSpeed = speed

    -- other stuff ...
end


Then you would just have to add self:UpdateData() after changing self.enginestats.maxSpeed. The new speed will get stored, and if you dupe the entity and spawn a copy, the copy will contain the same new max speed.

This was what i just needed, and indeed i had problems understanting how the function works. Anyways i got it to work… Thanks a lot for the help!