Jump to content

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 !

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

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
×
  • Create New...