How do I save an entity created in one campaign node and then reference it later in another node?

At some point in my campaign, I create an entity. Later in the campaign, I need to get that specific entity.

I’m saving it using this:

	local raft = radiant.entities.create_entity("archipelago_biome:decoration:raft", {owner = player_id})
	radiant.terrain.place_entity(raft, location, { force_iconic = false })
	game_master_lib.register_entities(ctx, 'visitors', { raft = raft })

And then in another script from another node, I tried accessing it again but it didn’t worked, using this few methods:

	ctx.visitors.raft

	ctx.entity_registration_paths.visitors.raft 

	ctx:get("visitors.raft") -- this one does not raise error, but fails used in a if ctx:get() then condition

Can you see that raft in the context if you expand the node that created it in the Campaign browser?

No. :frowning:
image

Maybe because I’m probably doing things the way they are not supposed to work? The spawn node is just a script node, and in the lua script I do all the spawning.

Though, in the same node in same script, I create a bulletin that targets the raft (to zoom into it) and it works by filling the bulletin target field with ctx.visitors.raft

Is there anything if you click in the show private icon there (the one that looks like the incognito mode) ? Actually the other icon might also show things.
Any ctx that you can inspect?
Have you tried with things like ctx._sv.parent_node and then accessing properties from it?

image

Then clicking on the ctx:
image

I can see the 3 objects in the visitors, those are three hearthlings that are created after the raft. Though I can’t access them using ctx.visitors[1]

Like ctx._sv.parent_node.ctx.visitors[1]? That returned “attempt to index nil value” for the second ctx

1 Like

Anything in the log for any of the different attempts to reach it in the other node? I hope it’s not a bug :slightly_frowning_face:

@linda should know.

Did you have to do it in a script because our default options to zoom are for enemies? I remember doing this once in the past, and it’s a pain. So I will make a request to be able to have zoom bulletins for whatever type of entity/encounter, if we don’t have that already.

Nothing in the logs besides the error of trying to access nil ctx variables.

The zoom is just a bonus. A few guys and their raft spawns and I added the bulletin just to make sure the player will see them.
The main idea is having temporary guests, so I need the saved context to be able to delete them later. They will behave as any other worker, but are not counted into the player citizens, can’t have their jobs changed, etc… I didn’t wanted to create them as citizens of another player id (like goblins) because them they would not interact and help with the town along the player workers.
I’m probably over complicating it…

If you guys need to take a look into my mess, it is here: GitHub - BrunoSupremo/archipelago_biome: Archipelago Biome mod for Stonehearth

1 Like

I’m still trying to solve this problem, although I have made 0 progress.
I’m checking a lot of files, and trying any solution I can imagine.

Checking the game_master_lib, I’m not understanding this “[^.]+” expression. Isn’t it basically targeting nothing? Reading the lua manual, a dot means any character, while the ^ accent inverts (or negates), so it means nothing?

for i in string.gmatch(prefix_path, “[^.]+”) do
if not registered_entity_path then

Actually I think that pattern is just splitting the path by the dots (that dot there is a literal dot, not the “any character” wildcard. So what’s receiving there is probably something like “ctx.entities.my_entities”, and creating the ones that are missing in the tree.

Uhm, I’m completely lost on why this is not working.
To simplify the topic, I have this:
image

“show the visitors” is a script encounter. There I run this line:
game_master_lib.register_entities(ctx, ‘visitors’, { raft = raft })
The raft is an entity that is being created and works fine apparently.

Then in the next, the “confirm visitors spawned” wait_for_requirements_met encounter, I have in its json a requirement, like so:

	"requirements": {
		"confirm_visitors": {
			"item": "script",
			"type": "deny_if_not",
			"value": true,
			"script": "file(has_visitor.lua)"
		}
	}

The pointed script has this:

local raft = ctx:get("visitors.raft")
if raft then
	return true
end

return false

The raft variable is always empty…

So, the raft gets saved in the ctx perfectly fine, however, it will be removed later on because of the code

game_master_lib.register_entities(ctx, 'visitors', { [i] = visitor })

further down in the following loop. The problem here is that the key which each visitor is given is a literal integer and not a string, which apparently forces the table to become an array instead, and all previous values will then be gone.

It can easily be fixed by having a longer path to your visitors in the ctx, maybe something like ‘entities.visitors’. But then I’d also recommend to change so that the raft is registered to the path ‘entities’ as well (to be consistent), and, of course, you’d also have to change line 75 so that the zoom_to_entity variable gets a correct value.


Next problem is that the has_visitor script still can’t find the raft, what I did to get around this was to access the parent node and get the raft from its ctx. So instead of the code you showed, I used:

local parent_node = ctx:get_data().parent_node
if parent_node then
	local raft = parent_node:get_ctx():get("entities.raft")
	if raft then
		return true
	end
end

return false

I check if the parent node exists first of all, since it seems that the game master continues to run the script after we have continued to the next encounter, and parent node was nil at one point. So it might return false then, but it doesn’t matter since we’ve already continued on to the next encounter by then anyway.

Thanks Drotten.

Uhm, I thought that would not happen in lua.
I had tested it before without the visitors, just the raft, but it didn’t worked either (now I see, it was because of the other problems)

Would this work for any other node? The code I have was just for testing it, I really don’t need it right in the next node, but after a few others (some dialogues and other things between)
I guess if that is a problem I can simple access the parent of parent of…

I noticed that it keeps running the script while we have the campaign browser open, but once closed it stops. I guess it is polling it for the tooltips.

I will try your suggestions. I had found one workaround that was really bad :sweat_smile:, I basically saved the id of the entities in the user_settings. Of course that is a bad idea, cause one save file could overwrite the values from another, but was what I had :stuck_out_tongue:

It surprised me as well, it should work fine if you were to convert the number into a string though and use that as a string, but, personally, I’d do it as I explained above, so as to keep each visitor in an array instead of a table, and it helps to separate the raft from the hearthlings. Anyway, that’s just how I’d do it, you’re by no means restricted to that and there are other means to achieve the same result. :slight_smile:

I would think that it does, but, as you said, you’d have to go through all the parent nodes (and maybe even child nodes) to get to it.

Ah, that makes sense now that you mention it! I didn’t notice it before, it’s good to know. :slight_smile:

Good luck! :smile: