Jump to content

Need help with custom component persistent data


Recommended Posts

Hello everyone,

I am trying to create a custom component that allows a prefab to summon bees on attack. It's kinda like "childspawner" component but less complicated. The problem is that I cannot persist the reference to summoned children. I use OnSave to save children's GUID and references, then use LoadPostPass to load new entities, however, LoadPostPass seems not to be called at all. Here is the code :

local function AddChild(self, child)
	if self.children[child] ~= nil then
		print("Already added child", child)
		return
	end

	self.children[child] = child
	self.numchildren = GetTableSize(self.children)
end

local function RemoveChild(self, child)
	if self.children[child] == nil then
		print("Not our child or already removed child", child)
		return
	end

	self.children[child] = nil
	self.numchildren = GetTableSize(self.children)
end

local function AddChildListeners(self, child)
    self.inst:ListenForEvent("ontrapped", self._onchildkilled, child)
    self.inst:ListenForEvent("death", self._onchildkilled, child)
    self.inst:ListenForEvent("detachchild", self._onchildkilled, child)
end

local function RemoveChildListeners(self, child)
    self.inst:RemoveEventCallback("ontrapped", self._onchildkilled, child)
    self.inst:RemoveEventCallback("death", self._onchildkilled, child)
    self.inst:RemoveEventCallback("detachchild", self._onchildkilled, child)
end

local BeeSummoner = Class(function(self, inst)
	print("COMPONENT INITIALIZED")
	self.inst = inst
	self.children = {}
	self.numchildren = 0
	self.maxchildren = 0
	self.childname = "mutantkillerbee"
	self.summonchance = 0.3
	self.radius = 0.5

	self._onchildkilled = function(child) self:OnChildKilled(child) end
	self._onattack = function(inst, data) self:SummonChild(data.target) end
	self.inst:ListenForEvent("onattackother", self._onattack, inst)
end)

function BeeSummoner:OnRemoveFromEntity()
	for k, v in pairs(self.children) do
		RemoveChildListeners(self, v)
	end
end

function BeeSummoner:SetMaxChildren(num)
	self.maxchildren = num
end

function BeeSummoner:SetSummonChance(chance)	
	self.summonchance = math.min(math.max(chance, 0), 1.0)
end

function BeeSummoner:OnChildKilled(child)
	RemoveChildListeners(self, child)
	RemoveChild(self, child)
end

local function NoHoles(pt)
    return not TheWorld.Map:IsPointNearHole(pt)
end

function BeeSummoner:TakeOwnership(child)
	if child.components.knownlocations ~= nil then
        child.components.knownlocations:RememberLocation("home", self.inst:GetPosition())
    end
    
	child:AddComponent("follower")
	
	if self.inst.components.leader ~= nil then
		self.inst.components.leader:AddFollower(child)
	end

	AddChildListeners(self, child)
	AddChild(self, child)
end

function BeeSummoner:DoSummonChild(target)
	if not self.childname then
		print("No child prefab defined")
		return
	end

	if self.numchildren < self.maxchildren and math.random() < self.summonchance then		
		local pos = self.inst:GetPosition()
		local start_angle = math.random() * PI * 2
	    local rad = self.radius or 0.5
	    if self.inst.Physics then
	        rad = rad + self.inst.Physics:GetRadius()
	    end
	    local offset = FindWalkableOffset(pos, start_angle, rad, 8, false, true, NoHoles)
	    if offset == nil then
	        return
	    end

	    local child = SpawnPrefab(self.childname)

		if child ~= nil then
			child.Transform:SetPosition(pos.x + offset.x, 0, pos.z + offset.z)
			if target ~= nil and child.components.combat ~= nil then
				child.components.combat:SetTarget(target)
			end
		end

		return child
	end
end

function BeeSummoner:SummonChild(target)
	local child = self:DoSummonChild(target)
	if child ~= nil then
		self:TakeOwnership(child)
	end
end

function BeeSummoner:OnSave()
	local children = {}
	local ref = {}

	for k, v in pairs(self.children) do	
		table.insert(children, v.GUID)		
		table.insert(ref, v.GUID)
	end
	
	for i, v in ipairs(children) do
		print("SAVED CHILD : ", v)
	end

	for i, v in ipairs(ref) do
		print("SAVED REF : ", v)
	end

	return {children = children}, ref
end

function BeeSummoner:OnLoad(data, newents)
	print("SAVED DATA HERE :")
	if not data.children then 
		print("EMPTY")
	end

	if data.children then
	for i, v in ipairs(data.children) do
		print("LOADED CHILD : ", v)
	end	
	end

	if newents then
	for k, v in pairs(newents) do
		print("ENT : ", k, v)
	end
end
end

function BeeSummoner:LoadPostPass(newents, savedata)
	print("SAVED DATA LoadPostPass")	

    if savedata.children then
    	for i, v in ipairs(savedata.children) do
			print(v)
		end
        for i, v in ipairs(savedata.children) do
            local child = newents[v]
            if child ~= nil then
                self:TakeOwnership(child.entity)
            end
        end
    end
end


return BeeSummoner

I tried to log every function call, OnSave and OnLoad seems OK, but LoadPostPass is not called. Please help me with this, thank you !

Link to comment
Share on other sites

I don't know about LoadPostPass, but you can use something like that:

Disable saving:

local function AddChild(self, child)
	if self.children[child] ~= nil then
		print("Already added child", child)
		return
	end

  	child.persists = false --disable saving for this entity, we will save/load it in another way
	self.children[child] = child
	self.numchildren = GetTableSize(self.children)
end

Save/Load

function BeeSummoner:OnSave()
	local children = {}

	for k, v in pairs(self.children) do	
		table.insert(children, v:GetSaveRecord())	
	end

	return {children = children}
end

function BeeSummoner:OnLoad(data)
	if data and data.children then
    	for k, v in pairs(data.children) do
			local obj = SpawnSaveRecord(v)
      		--some code  attach the spawned bee to the component owner
		end
    end
end

I use the similar code to save/load the prefab info (Ancient Watcher in the Green World), not sure about components.

Edited by ksaab
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...