Taking Questions about Mixintos and Overrides

Hey Everyone, sorry for the long delay.

@Relyss, re: the juniper/candyfloss trees:

@RepeatPan is totally right:

So your code was probably adding a model var array above the existing array, and lucky, the new one got read first. The actual version of the model variant that is read (if there are unexpectedly multiple) might be nondeterministic, so that might be why it works sometimes, but not others. I see why you want to do it this way, though–you want variants of the same tree, right? We’ll keep this in mind going forward.

@SteveAdamo is also correct, this is the same design issue he encountered when new personality types.

The short version is: thanks for beating on the API so we can be aware of what your use cases are trying to do that we haven’t thought of yet!

@Avairian, re: [quote=“Avairian, post:147, topic:5229”]
Not quite related to mixintos and overrides but I was wondering if you could explain how animations work with objects?
[/quote]

Right now, the region does indeed determine how close a person can stand to an object, but I don’t yet think that it affects the y (height) axis of interaction. If the y height is >=3, people cannot path over the object but if it’s less than 3 they walk right through.

To get sleeping on the bed to work, we tell the worker to go exactly to where the bed is, plus a unit of “1” and then run the same sleep animation he gets on the ground. Here’s our lua:

 --[[
    Follow the path to the bed, then play the sleep-related animations.
 --]]
 function SleepInBedAdjacent:run(ai, entity, args)
    local bed = args.bed
    ai:execute('stonehearth:run_effect', { effect = 'yawn' })
   
   --When sleeping, we have a small chance of dreaming
   radiant.events.trigger(stonehearth.personality,
                     'stonehearth:journal_event', 
                     {entity = entity, description = 'dreams'})

   -- move directly on top of the bed
   self._restore_location = radiant.entities.get_world_grid_location(entity)
   local bed_location = radiant.entities.get_world_grid_location(bed)
   bed_location.y = bed_location.y + 1
   radiant.entities.move_to(entity, bed_location)

   local q = bed:get_component('mob'):get_rotation()
   entity:get_component('mob'):set_rotation(q)

   -- goto sleep  
   radiant.entities.think(entity, '/stonehearth/data/effects/thoughts/sleepy')
   radiant.entities.add_buff(entity, 'stonehearth:buffs:sleeping');

   ai:execute('stonehearth:run_effect', { effect = 'goto_sleep' })
   ai:execute('stonehearth:run_effect_timed', { effect = 'sleep', duration = 1})   
   radiant.entities.set_attribute(entity, 'sleepiness', 0)
end

So you could try making a lua file that specifies a height of less than 1, and seeing what happens.

Let me know if you guys would like more info about adding/editing actions via lua. It’s rather in flux at the moment, but hey! Exciting!

1 Like

Gah, that’s a bug. I’ll look into it now.

Edit: Well, there was a bug with mixins, which when fixed, broke the mixintos. Now both bugs are fixed. Sorry about that, folks! Thanks to @Ponder is fixed on my machine now and should be in our next update, whenever that happens.

2 Likes

absolutely! but i imagine providing use cases/scenarios, or issues we run into with the logic, makes it easier to explain the actions?

although, a generic run through of code snippets, ala “Stephanie’s C0ding C0rner” has a nice ring to it… :smile:

1 Like

Yes, actually. So if anyone has specific questions, let me know! It will help me organize my thoughts, anyway.

1 Like

Out of interest… Was it because mixins overwrote normal properties and by changing that (i.e. defined properties overwrite mixin’d ones) you accidentally turned around the way mixintos work too?

1 Like

Yay! So soon I’ll be able to fix my mods to the latest release :slight_smile:
(Candyland1 is half way… A tiramisu terrain is not that easy to combine with candy-related trees, so I’m making new ones).

Yes, because the oak ones have variants, but the juniper ones don’t. And nevertheless I was able to push three variants of the large juniper tree (in my case, 3 candy floss) to overwrite it (it can be seen in the picture here), just with a mixinto. I guess now I’ll have to override the models first and then add variants. But if I’d like to replace the oak tree, which has variants by default, with just one model/variant, will it be possible?

Adding variants is nice, but when a mod needs to replace the standard assets there should be a way to apply all possibilities. Although I wouldn’t want to add variants to the bushes, as the empty ones could appear mixed (or not? Now to think of it, will they change colors depending on season? That’s another thing to take into account).

And what will be the way to add custom idle animations? To try them in-game I’m replacing the content of one of the idle animations (the idle_sway I think). If that’s still in progress, I’ll try the tutorial of voxel_pirate.

1 Like

Tony and I were just talking about this yesterday–it’s actually rather hard to remove things from arrays, because there’s no clear way to reference the item that you’re taking out. If you do it by index, the index might change if there’s another mixinto that adds stuff. If you do it by adding a unique ID to the array object, then… you might as well have a dictionary. So we’re still thinking about that! In the meantime, perhaps you could just replace all 3 model variants with the one model you like? And we could consider an option that just does that by default.

Voxel Pirate’s tutorial is actually spot on (and I don’t see things changing dramatically to contradict it any time soon). At a high level, the idea behind the action mechanism is that any entity can be loaded down with “actions” which are bits of AI that run when their conditions are met.

Actions are added to entities in their .json file, so if you want to see all the actions available to base_human, you can look at the “actions” section of base_human.json.

AI files can get pretty complicated, but at their simplest, they are made of:

  • a “name” field, which uniquely identifies them within a mod
  • a “does” field, which is like the category of action it belongs to
  • a “run” method which is what happens when this action is called upon by the AI service to run.
  • a “priority” number which determines how important this action is; higher is better

The idle_sway_action.lua demonstrates this pretty clearly:

 local IdleSwayAction = class() --declares this a lua class

IdleSwayAction.name = 'sway'  --here's the name
IdleSwayAction.does = 'stonehearth:idle:bored'  --here's its category
IdleSwayAction.args = { }  --args it takes, in this case none
IdleSwayAction.version = 2  --version of the action service, internal use
IdleSwayAction.priority = 1  --priority, kind of low
IdleSwayAction.preemptable = true  --can this be interrupted? Yes.

--function called when it's time to do the action
function IdleSwayAction:run(ai, entity)  
   --do this effect (which has an animation inside)
   ai:execute('stonehearth:run_effect', { effect = 'idle_sway'}) 
end

return IdleSwayAction  --so that you can reference the class from outside of itself

As @voxel_pirate says, to make a new bored animation, you have to make all the .json files, and make a copy of this .lua file, and then change the ai:execute to call your new bored effect instead of idle_sway

To test, you can see all the actions in progress on an entity by hitting the AI button in the upper left corner of the game, and then clicking on a person.

Because idle_sway “does” stonehearth:idle:bored, it will be entered into a prioritized-lottery whenever the AI service decides that it’s time for the person to do a “bored” animation. Actions with higher priority will get picked out of the lottery first. If a bunch of actions have the same priority then they have equal chances to run.

The AI service “does” the “bored” animation whenever there is nothing more pressing on its queue. More details on this if you need to have actions compete with each other (and not just within bored).

3 Likes

Well, part of the next modding request batch would be a way to mess around with JSON loading. I have a few ideas in mind, basically working around the idea of having “magic items” ("@MAGIC: remove(stonehearth/*.qb)@" or some silly syntax like that). We would have to see how it plays out, but that would be my worries then… Always open for some experiments.

1 Like

Btw, we pushed a build to Steam Latest that has the fix for the mixintos from yesterday. Thanks again to @Relyss and @RepeatPan for pointing it out.

3 Likes

OK, I don’t mind doing that.
R53 fixes the mixintos, but I still have a problem.
First, I override the default models so they don’t appear at all.
Second, I add the rest of the variants with a mixinto.

The result is that the files added with the mixinto will overlap the overridden ones. It’s difficult to notice it when the variants are just a color change, but I managed to conclude that, as the mixinto variants don’t show up in those cases.

For example, using my old mods, which added all models with the mixinto, my gummy bears evolve into little lions:

I guess I’ll try to reduce my number of variants and override only what we have, for the moment.

1 Like

I tried adding an animation to the oak log when it spawn during tree-cutting.

I have added to the oak_log.json:

"effect_list" : {
         "effects" : [
            "file(oak_log_animation.json)"
         ]  
      },

A file oak_log_animation.json with:

{
   "type" : "effect",
   "tracks": {
         "animation": {
         "type": "animation_effect",
         "start_time": 0,
         "animation": "file(animation.json)",
         "loop": false
         
      }
   }
} 

and in the animation.json I tried animating with the names “carry” and “Matrix_29”. Both dont work. The problem is somewhere in the animation part. Because when I tried another effect, it worked.

What I do wrong?
How is the ‘tree log block’ named when it spawns? Is it named “carry”? or “Matrix_29”? Or (probably) something else?

Stupid guesses: carry is the point where settlers are holding it, i.e. the connection point to the hand. Matrix_29 is the name of the matrix (i.e. the oak log) itself.

I suppose @voxel_pirate could shed some light here, but I assume you’re missing a skeleton file. Which, in all honesty, sounds like a complete overkill. I would probably animate it in lua, with interpolated movement, but even then it’s… questionable.

In good old GMod I’d just write a lua effect that runs on every Tick() and repositions the thing or something. Good old scripted effects. Making things go haywire exactly the way you didn’t want them to.

err, yea missed the skeleton file.
And its ‘stupid’ to do it in lua. Blender is far superior.

If it’s simple enough, let’s say a translation and a rotation, you have the choice between two lines of lua… or adding a skeleton file, an animation and an effect to an oak log, a pretty inanimate object that likely won’t have (or need) any other animation.

It’s all a matter of performance and reason. For me, having a spawn effect add so much overhead to a simple entity - one that is spawned all the time, most of the time off-screen too - isn’t worth it, neither the effort to implement it nor the time it needs to run.

To be completely honest, I feel like there should be a different way to approach this - one that is more generic, works without animations or skeletons and most importantly, for whatever entity you please. This might be somewhat possible already - but not with plain JSON.

Who cares, it is me learning the modding game. Particularly you should know that.

Wow! I am… not sure exactly what’s going on here. It looks like both the tree AND the bear are appearing? (Also, now I can’t unsee the lions!). Can you send an excerpt of your manifest and mixinto files?

1 Like

:confused: Seems I was able to fix it. More or less…
I overrode all the original tree models. For the oak trees there was no problem, as they originally have variants.

For the juniper ones… It’s so strange… For the large juniper I got the same behaviour I had achieved before: having three variants, repeating the model I used in the override and adding two more to the mixinto.

But for the medium juniper, using the same technique, but only two variants, and I still can’t see the second. Only the first one of the override.

Well, at last I’ve been able to upload the fixed version of the mod to stonehearthkingdom :smile:

I’ll keep investigating…

2 Likes

baby steps… sounds promising so far though! :+1:

1 Like

Doh… I know the reason behind this…
It’s because the first model is smaller than the others, and as the three variants are in the mixinto, all of them appear, but the overlap doesn’t show up because the first model is hidden inside the other two variants.

But if I have similar models or recolorings, the variants don’t show correctly because of the overlapping. Sigh…

In short, adding variants to a tree leads to this result.

3 Likes

You are definitely doing more complex things with mixintos and overrides than we have been so far, so I’m really glad you’re shining a light in all these dark, unexplored places. :stuck_out_tongue:

I’ve taken a look at your code, but I think I’m going to actually have to test it myself before I can figure out exactly what’s going on.

3 Likes