Allow food items to be members of multiple food groups, with special mechanics for them
abculatter2 opened this issue ยท 30 comments
I'm not entirely sure what mechanics would be best for foods in multiple food groups, though one could be that food in multiple food groups could count as more then one different item eaten. So, for example, eating a food in 3 food groups allows you to eat three times as much of that food.
Also, a config to change how much weight each additional food group counts as (for example, counting additional food groups beyond 1 as 0.5, so a 3 food group food would count as 2 different foods eaten)
It's been suggested before, but I really don't know how to make this work. I have a few general problems with items being in multiple food groups:
- It's hard to understand in general. Every suggested implementation I've seen is difficult for me to understand, so I'm sure it would be difficult for players to understand as well.
- It'll probably be very hard to communicate to players. I don't want to have to add giant tooltips to each food item to attempt to explain a convoluted system.
- The number of possible implementations is too large for me to know which one to settle on. There is no obvious implementation, and any one would be as valid as any other. The goals of the people that want this functionality would probably also be very different, so it'd likely lead to an ever-expanding list of configuration options that I don't want to deal with.
I'll leave this open because I'm not really opposed to the idea, I just don't know how to implement it in a way that I'd be happy with. If anyone can come up with a straight-forward, simple, and easily communicated implementation, I'm all ears.
Well, I did come up with something that would probably be easier to implement and a bit more intuitive, which is to make eating a food item that's a member of multiple food groups choose whatever food group the player has currently eaten the least of. In cases of ties, it will either choose randomly, or will go for the higher-priority food group. It will then act as if it were a member of that food group when calculating diminishing returns.
As for communicating when a food is a member of multiple food group, if you want to show every food group a food is a member of I think it's unavoidable for there to be potentially large tooltips, and personally I think that's more a problem for the config creators that put a massive number of food groups on food items and have them be non-intuitive enough that the tooltips are necessary. As for ways to combat it, I suppose either using the expanded tooltips thing (I think it's alt-H?) to shove any large tooltips behind a keypress and/or, if the above is implemented, you could have the tooltip only display the food group that it will choose if you eat it.
So when a food is a member of three food groups, what would the Eaten x times out of the last y foods
tooltip say?
I'm not entirely sure how foods are tracked, but would it be possible for the food itself to be tracked in addition to what food group it counted as? Then you can make it say how many times that food was eaten.
Unless you implemented it so that it displays the entire food group has been eaten x number of times, in which case, the player will probably just want to know how many times they've eaten the next food group it will choose, so you can just display that. The number of times the other food groups it is a member of have been eaten can, if you want, be displayed in the advanced tooltip.
The food itself is tracked, and the food group is looked up based on the food. Right now, anything in a food group displays the number of times that the food group was eaten, because that is what is used when calculating the nutritional value percentage. That is, food groups are basically treated as a single food in terms of nutritional value.
I'm not convinced that the rotating food group thing will make a lot of sense. It's still hard for me to understand or think about how it would work in practice.
The implementation that seems the simplest to me, but I still don't know how to communicate it, would be to treat each food group of a food separately when calculating nutritional values, and then take the average value of those food groups and use that. For example, a food that is:
- In food group A, and food group A has been eaten 4 times recently
- In food group B, and food group B has not been eaten recently
- In food group C, and food group C has been eaten 12 times recently
For the sake of simplicity, we'll assume the nutritional value formula is 1 - count/12
. Using that, we get the following nutritional values:
- Food group A:
1 - 4/12
=66.6667%
- Food group B:
1 - 0/12
=100%
- Food group C:
1 - 12/12
=0%
So, then a food that is in all three food groups would have a nutritional value of (0.66667 + 1 + 0) / 3
= 55.5556%
This still has the problem of large tooltips, as I'd need to do something like:
Food Name
Nutritional value: 55.56%
Food Group: A
A eaten 4 times in the last x foods
Food Group: B
B not eaten recently
Food Group: C
C eaten 12 times in the last x foods
Perhaps the Food Group:
lines could be removed, so it could just be one line per food group? Not sure how clear that would be.
I thought that shift to expand the tooltip was already a thing. Apologies for not suggesting that earlier.
I also think that increasing by whole numbers would be best, as there could also be strange things if someone adds a food with a number of food groups that doesn't divide easily, such as 7 or the aforementioned 3.
Also, while incrementing all food groups would be simple and intuitive, it does have one issue which is why I didn't suggest it, as it means that combination foods will be counted as three different foods by spice of life, but only increase the food bar once. If the diminishing returns list counted by total food groups instead of individual food items eaten then this would only be an issue for those who use the time-out list rather then the number-of-items list, though if it does count individual items then it would make combination foods worse rather then better then their individual ingredients.
well, worse/better depends on how you look at it. a complex food item could provide more raw hunger/saturation than the sum of its ingredients, making it instantly more worthwhile, even if it only counts towards one of the groups it's a part of. if it counts towards multiple groups, that might balance* out the food item a bit, causing the player to choose between raw ingredients that don't fill them up nearly as much, or more complex foods that degrade quicker. If anything, you're filling up the food history quicker.
*Note: balance is subjective.
If anything, you're filling up the food history quicker.
Do you mean filling it up quicker by eating lots of raw ingredients or by eating foods in multiple food groups? Eating a food in multiple food groups wouldn't fill it up any quicker than eating a food in one food group (assuming food history is based on the number of foods eaten).
I meant foods with multiple groups, but yeah that depends on how it's calculated, I guess.
Maybe the aggregated food name and nutritional value percentage could display at all times, and if a food is in at most one group, display instead a "press shift to view detailed food history" message, and upon pressing shift, the player is presented with the food's groups and their history information.
I personally like the averaging of the multiple food groups to get the final amount, as a complex food item such as a sandwich from Pam's Harvestcraft should be included in multiple groups. If, for instance, those groups were grains, vegetables, and meats, eating the sandwich would provide the average nutritional value of all 3 groups, since it's made out of at least one item of each of those groups.
As for calculating which group should be increased, would it make sense to have a config option to either pick the least eaten group, a random group, or even something like adding to each group in the item? Obviously picking the most eaten group doesn't make much sense as it'd never pick anything other than that group, and a random one will eventually even them out without having to figure out a round robin ordering of food groups. This would lead to three "difficulties" of multi-grouped foods: picking the least eaten group at all times means you get the most amount of consumption from a single food item, and is therefore the easiest; picking a random order could lead to somewhat lower aggregated totals since groups that were already higher to begin with have an equal chance of being picked and therefore the aggregate could decrease faster than the prior system; and picking each group is obviously the hardest, as the aggregate would decrease the fastest out of all three systems.
I like the idea of a "Press shift for details" tooltip.
I'd lean towards incrementing all food groups of a food at the same time (eating a sandwich that's part of grains, vegetables, and meat would give you +1 eaten in grains, +1 eaten in vegetables, and +1 eaten in meat). The other systems sound rather confusing.
Another non-confusing alternative I guess would be to split the food evenly across all food groups (+1/3 to each), but that seems a bit strange and would require quite a few under-the-hood changes.
Yeah, increasing a food group only partially sounds like a hassle, especially for increasing in repeating decimals, like thirds. you'd need to increase by whole amounts, in my opinion.
Yeah, for the 'number of foods eaten' style of food history, each food is always just counted as one. So, for example, starting from zero foods eaten:
Player eats a food in food groups A, B, and C
A eaten 1 time in the last x foods
B eaten 1 time in the last x foods
C eaten 1 time in the last x foods
Food history length is 1, and 1 food is shown in the food journal
Oh, so the groups would fill up "faster", but the overall history length would remain the same?
What would happen then if you set up your formula to count the number of times a food (or its group(s)) has/have been eaten instead of the current food history length? Would a complex food that exists in multiple groups count as the sum, average, lowest, or highest of those groups? I would say average would fit considering that's how the nutritional value is calculated, but that's just my opinion.
Food history is empty Player eats a food in food groups A, B, and C Food history length is ?, food journal shows ? Player eats a food in no food group Food history length is ?, food journal shows ? Player eats a food in food group A Food history length is ?, food journal shows ?
The history length would increase by one since you ate one food. My question is more for the "count" variable when defining the food formula. Count is defined as "The number of times the food (or its food group) has been eaten within the food history". since the food belongs to 3 groups, how is this count related?
Actually, thinking about it now, this formula is used per food/group. Since the food belongs to multiple groups, we'd iterate through each group and use this formula to find the end result for each group, then average them as you've explained above. That makes my previous question invalid, as shown below:
Nutritional Value Fomula is "MAX(0, (1 - count/12))^MIN(8, cur_history_length)".
Food history is empty
Player eats a food in food group A twice.
Player eats a food in food group C.
Player eats a food in food groups A, B, C.
Food history length is 4, food journal shows 4.
Food shows the following:
Group A = MAX(0, (1 - 3/12))^MIN(8, 4) = 9/12^4 = 0.316
Group B = MAX(0, (1 - 1/12))^MIN(8, 4) = 11/12^4 = 0.706
Group C = MAX(0, (1 - 2/12))^MIN(8, 4) = 10/12^4 = 0.482
Final Nutritional Value = (0.316 + 0.706 + 0.482)/3 = 0.501 = 50.1%
Which I think is what you've explained above, so if I'm just re-iterating what you've explained, sorry. I think we're on the same page now, though.
Ah, yes, you're correct. Small side note: each food group could even use totally different formulas by using the formula
field in the food group json format.
Ah, yes. I was using the same one for simplicity's sake, but yeah they can be entirely independent, which furthers the point that the count
variable is for the current group in the food item.
What would happen then if you set up your formula to count the number of times a food (or its group(s)) has/have been eaten instead of the current food history length?
That is how it currently works when calculating nutritional value. For the history size, though, it only uses the number of foods eaten.
Would a complex food that exists in multiple groups count as the sum, average, lowest, or highest of those groups? I would say average would fit considering that's how the nutritional value is calculated, but that's just my opinion.
I'm not sure what you mean. Could you give an example? What would happen in the following scenario?
Food history is empty
Player eats a food in food groups A, B, and C
Food history length is ?, food journal shows ?
Player eats a food in no food group
Food history length is ?, food journal shows ?
Player eats a food in food group A
Food history length is ?, food journal shows ?
Would it be difficult to make the nutrition calculation be based on number of food groups eaten rather then number of food items eaten, at least as a config option? As I said above, tracking it by food items rather then food groups will make foods in multiple food groups worse then foods in one group, since the number of foods tracked will increase much less then the number of food groups eaten.
Would it be difficult to make the nutrition calculation be based on number of food groups eaten rather then number of food items eaten, at least as a config option?
Not sure what you mean. Could you give an example in this format?
Nutritional Value Fomula is "MAX(0, (1 - count/12))^MIN(8, cur_history_length)".
Food history is empty
Player eats a food in food group A twice.
Player eats a food in food group C.
Player eats a food in food groups A, B, C.
Food history length is 4, food journal shows 4.
Food shows the following:
Group A = MAX(0, (1 - 3/12))^MIN(8, 4) = 9/12^4 = 0.316
Group B = MAX(0, (1 - 1/12))^MIN(8, 4) = 11/12^4 = 0.706
Group C = MAX(0, (1 - 2/12))^MIN(8, 4) = 10/12^4 = 0.482
Final Nutritional Value = (0.316 + 0.706 + 0.482)/3 = 0.501 = 50.1%
As I said above, tracking it by food items rather then food groups will make foods in multiple food groups worse then foods in one group, since the number of foods tracked will increase much less then the number of food groups eaten.
This sort of thing has always been a problem with the 'number of foods eaten'-based history size (less complex foods cycle the history faster, so it makes eating them more useful than eating complex foods). You might want to consider using the hunger-based history size (use.hunger.restored.for.food.history.length
) or time-based history size (use.time.for.food.history.length
) if that's a concern for you.
I did not know that hunger-based history was a thing, though I did know about the time-based one. Thinking about how it would play out in-game, I would still prefer tracking based on total food groups eaten, but I can work with the above settings.
by the way, using the example you copy-pasted, the only thing I am suggesting be change is that:
"Food history length is 4"
Be changed to:
Food history length is 6"
Since that is the total number of food groups eaten across all the foods. Everything else would be the same.
Ah, I see. If I implement that style of food history, I'll make it a config option (use.food.groups.for.food.history.length
or something like that).
Also, thanks to both of you for all the feedback about this. I'm happy with what we've settled on and will try implementing it soon.
\o/
No problem, I like thinking through problems, coming up with solutions; it's basically the reason I'm a software engineer.
Okay, I've got the core of this mostly implemented. It'd be great if either/both of you could test it out and provide feedback. Please try to break it as much as possible.
SpiceOfLife-mc1.7.10-1.3.0+236eb9d.jar
How it works (from the commit log):
- A food that is in multiple food groups will get its nutritional value % from an average of all of its food groups, where each food group calculates its nutritional value % independently.
- Replaced food group priority system with an "exclude" property in the food group json, to be able to exclude certain foods from a food group even if they would otherwise be caught by a wildcard metadata/oredict entry. For example, you can include "listAllBerry" oredict and then exclude "harvestcraft:strawberryItem". See example-food-group.json
Appreciate it. Here's the latest build:
Released in v1.3.0: https://github.com/squeek502/SpiceOfLife/releases/tag/v1.3.0
Oh, sorry I was busy earlier this weekend and was about to test it this afternoon. I'll still take a look and report anything I find.