Ludeon Forums

RimWorld => Mods => Help => Topic started by: Cozarkian on June 15, 2020, 03:26:32 PM

Title: Help with food tracking mod
Post by: Cozarkian on June 15, 2020, 03:26:32 PM
I'm trying to create a mod that makes it important to provide a variety of foods, so that pawns won't be happy eating nothing but fine meals made from corn and chicken eggs. The basic idea is to create a variety need that falls over time and increases when a pawn eats different ingredients. That is similar to how the chemical interest traits work, but unlike those traits, the need should only be satisfied if the pawn hasn't recently consumed the same ingredient. In order to do that, I need to set some kind of invisible tag that tracks what foods have been recently consumed. I could use some (major) guidance on creating the tag and making it mod friendly as a companion to food-expansion mods like RimCuisine and VGP.

In basic sum, the idea will:

1. When something is ingested, return null if it is pemmican, kibble, nutrient paste, RawBad, or a drug (I think I can figure this out).
2. Grab the ingredient list or the single ingredient for RawTasty foods (again, I think I can do this).
3. Check for a "recently consumed" tag for each ingredient.
4. If recently consumed, refresh the tag.
5. If not recently consumed, satisfy the need and add a recently consumed tag.

I am at a loss on how to accomplish steps 3-5. My first thought was to use a system similar to joyKinds tolerance using vanilla foodTypes. However, there aren't enough foodType varieties and if I make my own characteristic and add it manually to each food, it wouldn't work with modded foods. My second thought was to try an xpath patch that will add a tracking trait to ThingDefs. That should increase compatibility with mods that add foods. However, I noticed raw meat is a ThingDefCategory rather than individual ThingDefs, so I'm not sure how to do that in a way that would distinguish between different types of meat. My third thought was to use a hediff similar to drug addiction/tolerance that falls over time. However, the tag won't have an actual health effect and it shouldn't be displayed, so I don't think that will work either.

If someone can help me figure out how to create a mod-friendly tagging system, or give me a push in the right direction, I think I can muddle through the rest (creating the need, setting thresholds and sending thoughts).
Title: Re: Help with food tracking mod
Post by: LWM on June 16, 2020, 10:25:03 AM
What sorts of foods are not similar?

Pork and beef - similar?
Chicken and chocobo - similar?
T-rex and ...chicken? - similar?
Corn and wheat?

And if they are similar, you're (probably) going to have to do a lot of work to make it work.

Anyway, each meat does have its own def in the def database. So you don't have to use xpath to get your tags; you can get information directly from the Ingredient comp.

Speaking of the ingredient comp, you'll probably want to look at it and think about how you want to deal with merging two meals with different ingredients.  If you want to track each meal separately, you're either going to have risk a lot of 4-stack meals (yay storage mods?) or you're going to have to do some fancy work with a derived Comp that tracks the ingredients carefully.

Do you have a plan for where to store the information on what pawns have eaten recently?
Title: Re: Help with food tracking mod
Post by: Cozarkian on June 16, 2020, 11:44:26 AM
Quote from: LWM on June 16, 2020, 10:25:03 AM
What sorts of foods are not similar?

None. I intend to treat each food as a unique ingredient.

The original idea was to class foods by type, i.e. meat, animal products, fruit, vegetable, grain, fish, etc..., but after looking at the files, I think that would take more work and be less compatible.

Quote from: LWM on June 16, 2020, 10:25:03 AM
Anyway, each meat does have its own def in the def database. So you don't have to use xpath to get your tags; you can get information directly from the Ingredient comp.

To clarify, I meant each meat doesn't have a ThingDef in xml. I understand meat and leather are derived using c# and therefore, that an xpath patch using e.g., */ThingDef [def Name = "ChickenMeat"] wouldn't work. Is that wrong?

Quote from: LWM on June 16, 2020, 10:25:03 AM
Speaking of the ingredient comp, you'll probably want to look at it and think about how you want to deal with merging two meals with different ingredients.  If you want to track each meal separately, you're either going to have risk a lot of 4-stack meals (yay storage mods?) or you're going to have to do some fancy work with a derived Comp that tracks the ingredients carefully.

I was going for the fancy work. The game tracks the ingredients used in meals in order to apply humanlikeMeat and InsectMeat thoughts. I'm planning on copying the code to call the ingredients and then checking each ingredient to see if it was recently consumed, applying need satisfaction if it wasn't, and then adding the ingredient to the recently consumed list.

Quote from: LWM on June 16, 2020, 10:25:03 AM
Do you have a plan for where to store the information on what pawns have eaten recently?

That's kind of my starting question. I'm trying to avoid giving each food a tolerance-like HediffDef, each of which would require a description and would fill the health panel UI.

I was hoping to give each pawn a "recently consumed" list, add ingredients when consumed, and remove them from the list over time. I have no clue where to start with that. Would that be possible with a single hediff that has no actual effect other than to show what foods were recently consumed (like a "stomach contents" list)?

Title: Re: Help with food tracking mod
Post by: LWM on June 16, 2020, 12:07:28 PM
Quote from: Cozarkian on June 16, 2020, 11:44:26 AM

Quote from: LWM on June 16, 2020, 10:25:03 AM
Anyway, each meat does have its own def in the def database. So you don't have to use xpath to get your tags; you can get information directly from the Ingredient comp.

To clarify, I meant each meat doesn't have a ThingDef in xml. I understand meat and leather are derived using c# and therefore, that an xpath patch using e.g., */ThingDef [def Name = "ChickenMeat"] wouldn't work. Is that wrong?
I very specifically specified "in the def database:" as I understand it, on game load, the engine goes through all the def-makers and creates a bunch of defs for things like meat.  So they don't exist as xml, but from the viewpoint of C#, they quiet clearly exist.  So you can do things like

ThingDef ingredient1=....
if (!recentlyConsumed.Contains(ingredient)) //etc
Scribe_...Look?  // I forget how defs are saved. Something "save by reference" something something.


But - as you said - there won't be any xml you can xpath.

Aside:
"*/ThingDef..." is VERY slow for an xpath - the "*" means it checks against EVERY node.  /Defs/ThingDef... is the fastest (I can show my work if you want)

Quote

Quote from: LWM on June 16, 2020, 10:25:03 AM
Speaking of the ingredient comp, you'll probably want to look at it and think about how you want to deal with merging two meals with different ingredients.
The issue is that the vanilla CompIngredients only handles a max of 3...4? ingredients and everything in the stack of 10 gets those same few ingredients.

Quote from: LWM on June 16, 2020, 10:25:03 AM
Do you have a plan for where to store the information on what pawns have eaten recently?

That's kind of my starting question. I'm trying to avoid giving each food a tolerance-like HediffDef, each of which would require a description and would fill the health panel UI.

I was hoping to give each pawn a "recently consumed" list, add ingredients when consumed, and remove them from the list over time. I have no clue where to start with that. Would that be possible with a single hediff that has no actual effect other than to show what foods were recently consumed (like a "stomach contents" list)?
[/quote]

I think I would probably use a WorldComp (RimWorld.Planet.WorldComponent), and store a list of pawns who are eating there - preferably only human pawns ;) .  Then on saving, I'd check and see if the pawns are alive before saving their data.

But an HeDiff that every human-like pawn always has?  I think that could work?  I don't see a reason it wouldn't.  It might have slightly higher processing costs in-game, but would keep the data with the pawn.
Title: Re: Help with food tracking mod
Post by: Cozarkian on June 16, 2020, 01:34:04 PM
Quote from: LWM on June 16, 2020, 12:07:28 PM
I very specifically specified "in the def database:" as I understand it, on game load, the engine goes through all the def-makers and creates a bunch of defs for things like meat.  So they don't exist as xml, but from the viewpoint of C#, they quiet clearly exist.  So you can do things like

ThingDef ingredient1=....
if (!recentlyConsumed.Contains(ingredient)) //etc
Scribe_...Look?  // I forget how defs are saved. Something "save by reference" something something.

Thanks. The fact I didn't fully understand what you meant is a clue as to how little I know. I'm probably in over my head but I figure the worst that will happen from trying and failing is learning a few new things.

Quote from: LWM on June 16, 2020, 12:07:28 PM
Aside:
"*/ThingDef..." is VERY slow for an xpath - the "*" means it checks against EVERY node.  /Defs/ThingDef... is the fastest (I can show my work if you want)

No need to show your work. I'll go and change my other mod right now.

Quote from: LWM on June 16, 2020, 10:25:03 AM
The issue is that the vanilla CompIngredients only handles a max of 3...4? ingredients and everything in the stack of 10 gets those same few ingredients.

Oh, you mean when meals made from different ingredients are placed/merged in the same stack, the game gives them all the same ingredients? Yes, that does make it harder to feed pawns a variety of ingredients, and I hadn't thought of that. However, I'm not sure that is a problem. To start, I'll tweak the value on how easy it is to fulfill the need based on the number of ingredients that can reasonably be provided. If that isn't sufficient I'll find a solution down the road (like finding/making a companion meals or storage mod that will make ingredient management easier). Heck, maybe down the road I'll take a stab at preferability to make pawns prefer foods with new ingredients. That could lead to other mods as well, such as a trait mod for traits like vegetarian.

Quote from: LWM on June 16, 2020, 10:25:03 AM
I think I would probably use a WorldComp (RimWorld.Planet.WorldComponent), and store a list of pawns who are eating there - preferably only human pawns ;) .  Then on saving, I'd check and see if the pawns are alive before saving their data.

But an HeDiff that every human-like pawn always has?  I think that could work?  I don't see a reason it wouldn't.  It might have slightly higher processing costs in-game, but would keep the data with the pawn.

Thanks. I think that helps give me a starting point. I've realized I'm going to have to build this in steps. Perhaps I'll be back with some more specific problems.
Title: Re: Help with food tracking mod
Post by: LWM on June 16, 2020, 10:33:19 PM
Quote from: Cozarkian on June 16, 2020, 01:34:04 PM
Thanks. The fact I didn't fully understand what you meant is a clue as to how little I know. I'm probably in over my head but I figure the worst that will happen from trying and failing is learning a few new things.
;D

That is the general idea. The other half of that is "everything is possible" (altho may not be easy).  This mod idea of yours won't be the easiest thing ever, but it also strikes me as very doable?

Quote
Quote from: LWM on June 16, 2020, 10:25:03 AM
The issue is that the vanilla CompIngredients only handles a max of 3...4? ingredients and everything in the stack of 10 gets those same few ingredients.

Oh, you mean when meals made from different ingredients are placed/merged in the same stack, the game gives them all the same ingredients?
If you haven't decompiled the code, you should do that now, and then you should probably read through CompIngredients before you get any deeper, just to start getting familiar :)  RW isn't too bad to work with once you get used to it, but ...it can be confusing.  It probably makes more sense to the devs.

Yes, that does make it harder to feed pawns a variety of ingredients, and I hadn't thought of that. However, I'm not sure that is a problem. To start, I'll tweak the value on how easy it is to fulfill the need based on the number of ingredients that can reasonably be provided. If that isn't sufficient I'll find a solution down the road (like finding/making a companion meals or storage mod that will make ingredient management easier). Heck, maybe down the road I'll take a stab at preferability to make pawns prefer foods with new ingredients. That could lead to other mods as well, such as a trait mod for traits like vegetarian.
[/quote]
One possibility (way down the road), is to use xpath to replace CompIngredients in meals with your own derivative of CompIngredients, which CAN keep track of all that stuff...but that would be a way down the road, and only if you wanted to go there after you see how it plays out - v possibly not needed.

I think you've got a good way to head forward.  I can't think of anything that does WorldComps right off the top of my head, but looking at other mods could also help give concrete examples.  Good luck!  You got this!