[Spoiler] Preview of the Weaver (Patch r22)

I want to do something like this. Create an placeable entity. And when it is placed is has an action button in the UI. When that button is pressed it destroys the created entity and replaces it with an fuctioning robot with ‘worker AI’ for example.

3 Likes

At least this part should not be too difficult as there is the “destroy_entity”-command which you can already add to such entities. However, you might need to customize the implementation a bit as you want to have two commands executed, not only one.

2 Likes

Piece of cake. Add a command json, have it execute a callback (server-sided) that you define, which first saves the entity’s location, then destroys it, then creates the new one.

It might even be possible to have real “stacking” behaviour, i.e. that you place part 2 on top of part 1.

2 Likes

So it turns out that “male_1” does indeed work (I was mostly asleep last night and tried “male1” >.>; ). However, like @RepeatPan said it doesn’t have a name or attributes, also, it has no profession, so it doesn’t even have the basic worker functionality, and just it just kinda wanders. =/


That’s a great idea! =D
I wonder if we’ll still need the 3rd gender/new race though =/


Is is possible to hardcode a profession to an entity? Like… Have a robot be a worker without it being able to upgrade to carpenter?

1 Like

Everything is possible, the only question is to what lengths you are willing to go. For promoting, all entities that have a profession and whose profession is “worker” are considered. For the AI, I have absolutely no idea. I can’t seem to find references to worker whatsoever.

However, if you manually initialize an entity (basically by calling professions/worker/worker.lua:promote on the entity) and then just call entity:get_component('stonehearth:profession'):set_info('robot'), you end up with something that seems to work AI-wise, but is not promotable.

I would have to do more research as to what exactly does the AI magic, but I’m quite certain that it is the promotion. Without promoting, the naked guys just stand around and don’t do anything - with a promotion, but changed description, they work as intended.

So in theory, you could do that already with RP’s hooks.

1 Like

How can you make it sound so easy, and yet so hard at the same time? lol

Can any entity be promoted to a profession? What’s to stop me from promoting a bunny to carpenter =P There has to be more? right?

I’m pretty sure it’s the promoting too. Or rather, I think the promoting gives the entity the needed AI actions to do the worker stuff. In worker_outfit.json it lists the AIs it injects into the entity (such as chop tree, light fire, sheer sheep, etc). So… it should be possible to assign these individually, if I can’t give the entity the profession directly.

So, I could create a place-able entity, which has a command json to save it’s cords, delete itself, and create an entity with the worker profession and/or AI actions?
And I suppose I’d have to worry about animations for everything a worker can do…

hmmm…

What are RP hooks? and how would they work with this?
(Sorry for all the questions, I’m still new to lua and json and stonehearth >.<; )
[end rambling]

2 Likes

“Professions” itself are just another component that can, in theory, be attached to any entity. So yes, if you want to, you can give trees professions too. Whether or not said profession is actually coded to work with trees is a different topic, however. I doubt trees have a worker outfit as example.

Ah, so there we go - the outfit does the magic (entity:add_component("stonehearth:equipment"):equip_item("stonehearth:worker_outfit")). That could easily be replicated - or perhaps even modified. For example, robots that only chop trees, or only carry stuff. But yes, you are right - AI stuff can be “injected” (whyever they choose that terminology) into entities - which is just what the outfit does. I guess the promotion to the carpenter then removes certain abilities again or re-initializes the AI or something like that (haven’t bothered to look, sorry!)

No. The json itself just specifies which command (in lua) that should be called. The lua callback handler (as they’re called) then does those steps: save coordinates, remove, create. The json merely points the game to the right direction à “If you click this button, please call that lua function.” Extremely simplified.

If you name your bones the same way they do and don’t want to have different animations (for now), I guess you could simply re-use the normal animations. Somehow. I’m not sure how SH deals with missing animations; many things could possibly break however if one is missing (chopping for example is more or less repeat play_animation('chop') tree:chop() until tree:is_chopped().

RP is just a little framework I wrote that allows people (… well, as far as I can tell only me) to create mods that are independent, i.e. work by adding an smod, not modifying the default ones. In order to get that done, RP overloads/overwrites the default methods and provides events (I call them hooks sometimes, old GMod habit).

In the recent change for RP, I’ve added events for factions. I’ll be lazy and just copy-paste them from the source:

  • QUERY faction / stonehearth:propose_citizen_name { gender = …, proposals = {} }: Allows mods to propose a name { name = …, priority = … }; the highest priority one wins.
  • EVENT radiant.events / stonehearth:faction_created { faction = …, kingdom = … }: Fired whenever this faction is first created
  • QUERY faction / stonehearth:propose_citizen_gender { proposals = {} }: Allows mods to specify a gender for a newly created citizen. Weird balancing tricks go here. { gender = …, priority = … }
  • QUERY faction / stonehearth:propose_citizen_kind { gender = …, proposals = {} }: Allow mods to specify a certain model for a newly created citizen { entity_id = …, priority = … }
  • EVENT faction / stonehearth:citizen_created { gender = …, entity_id = …, object = … }: Fired when a citizen was created using these arguments

What you likely wanted to use would be propose_citizen_name to have something robot-ish (of course rp_alternate_naming could be used for that too), propose_citizen_gender could be overriden to return robot or whatever (if your robots have no gender), propose_citizen_kind would then insert your entity instead of “stonehearth:male_1” (for example, "robots:robot_" .. math.random(1, 3)), and last but not least citizen_created would then re-name their profession or tweak their AI abilities. Now that I think about it, it sounds like this should be handled in a separate event, hmmm.

So anyway, if you are okay with messing around with the stonehearth.smod directly, you won’t need RP as it is much easier to change the code directly. However, RP’s approach is of course “update safe” (as in, updates are less likely to break your mod - while a game update will break the stonehearth.smod anyway, the worst that happens with RP mods is that they stop working) and easier maintainable because you don’t need to worry about changes to the normal files - RP takes care of it.

It’s kind of an unofficial, temporary modding API.

Keep in mind that all this is only really necessary if you plan on replacing the normal spawn behaviour. If you want to spawn them on-demand, all this stuff is (likely) not necessary as you will have to deal with the whole process yourself.

Although you could certainly create a faction that simply pretends to be civ and has functions for that stuff implemented. place_citizen, as seen in “new_world_generation_handler_or_something_like_that.lua” is not accessible.

Weeeell, not really.

Real stacking behaviour would be like… the holy grail. Then a craftsman can really build a robot.
I choose the way I did it, because I know it is possible with RP and the code we have now. But I just dont know all the pieces of code I need.

I think it is easier to give it other or non promote button. But unlike you maybe I want to have some robots created by humans. :blush:

Yea, pretty much heheh

yes sir… im not sure if you’ve had an opportunity to watch the most recent stream, but Tom goes into this very discussion around the 01:00:00 mark (walking through the various code pieces)…

I did skip through it for some parts… even waited for the delay, but missed that one. I’m not that interested in model design decisions, so I thought the stream itself wasn’t going to be overly interesting.

I still want to know the skip_title secret though.

Thanks @RepeatPan, It’s going to take me a while to digest all that info, but I’ll definately look into RP hooks.


Well, I want to have my robots make other smaller robots to do all the hard labor… so it’s kind of the same thing? lol

Ah, then it is easier to make it a different gender I suppose. Easier to give it a different AI and cloths and so on. :blush:

I could always provide code snippets (smaller or larger) or extend RP’s functionality if you require a certain feature.

About the robot stacking, I’m not too sure how well that would work. In my head I have the idea for an API that would allow these things (and on top of that stuff like “It’s possible to stack X on Y”-callbacks). This could allow you to have robots really “built”, as in different components that change the robot’s appearance/functions/stats.

Could probably also be nice for a totem pole or something like that.

If you could modify the ‘summoning worker’ code so it destroys the entity and replaces it with a human with AI, I would be grateful. You made some code for destroying the entity earlier, but I could not get it to work.

Maybe you can see how they do it with buildings. It does also stack things I suppose.

function SummonWorkerHandler:summon_worker(session, response, standard)
	local pos = radiant.entities.get_location_aligned(standard)
	rp.run_safe(place_citizen, pos.x, pos.z)
	radiant.entities.destroy_entity(standard)
end

Replace rp.run_safe (or place_citizen) with whatever you need to create the new entity. This will, however, not close the GUI. But I think that’s a general “bug” as destroying entities aren’t clearing their GUI properly - it’s the same with trees.

ok, so I do something like this?
rp.run_safe(place_male_1, pos.x, pos.z)

If place_male_1 is a valid function, yes.

It really depends - you have to be a bit more precise on what you want to do. The current code simply does the same like the normal workforce, but removes the standard and spawns the citizen at the same location (but not rotation) as the standard.

Yes that is exactly what I want, but instead of spawning a random one from all the humans, I would like to spawn a specific one. But I dont understand this…

If you want to spawn a specific human I’m afraid we will need to go deeper. Much deeper. Of course I could simply make place_citizen public within a faction, that would be one way to deal with the issue…

As for now, I’m afraid you will have to modify place_citizen and simulate whatever faction:create_new_citizen() does. Which means…

	local gender = 'my_gender' -- preferably "male" or "female", unless you deal with the name generator too
	local kind = "my_mod:foobar"
	local citizen = radiant.entities.create_entity(kind)
	citizen:add_component("unit_info"):set_faction(self._faction_name)
	faction:_set_citizen_initial_state(citizen, gender)

I’m afraid that’s still a bit too imprecise for a really “elegant” solution.

ok thanks I will try.