forked from camcamcamcamcam/mindful-eating
-
Notifications
You must be signed in to change notification settings - Fork 0
/
designlog.txt
48 lines (29 loc) · 12.9 KB
/
designlog.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Mindful Eating
Currently, the food system in Minecraft is easily overcome with automatic food sources like Chicken Cookers. After that, it largely becomes an annoyance of having to eat every so often. To add more strategy to eating, I thought of this idea on the spot on the 5th of August, 2018, and later mentioned it in my video titled "Should Minecraft be a Survival Game?" Many previous ideas/mods for food system overhauls tried to encourage diversity of diet by giving potion effects or similar buffs to different food, or punishing eating too much of one food. My idea aims to encourage diversity of diet in a helpful yet unintrusive way - by making some foods more suitable for different scenarios.
Essentially, each food in the game would be in a group. And each group would decrease the amount of saturation/hunger lost from a certain activity. If you were planning an activity that required a lot of sprinting, for example, you'd use up less food if you ate vegetables instead of meat. This mechanic, paired with a possible rebalancing of eat times and saturation/hunger values, would encourage strategy of diet, consumption of more complex foods (since they would provide the buff in more than one exhaustion source) and less eating interruptions - without disadvantaging people who wished to stick with one food.
Implementation
To implement this, I decided the buff to be based on the last food eaten, so you can easily switch between foods if your dominant activity changes - the group of the last food eaten are represented as icons that replace the chicken drumsticks on the hunger bar. I made it an add-on to the Diet mod, which provides food groups for vanilla and many popular mods. The owner of the mod was kind enough to add an API method to easily get the groups a food belongs to. However, I do plan to support Diet's native functionality, where the effects are given if enough food in that group is consumed.
I started off by registering some tracked data to record the last food eaten by a player, as well as a hook to update it. Then I looked into how exhaustion was handled in vanilla code. The method addExhaustion() is called multiple times, but Forge provides hooks that can record every action that would add exhaustion. All I would need to do is subscribe to those events, filter out the invalid triggers, and remove a portion of the exhaustion if the food group matches the exhaustion source.
I made an Enum to represent all the different exhaustion sources I would need to target, then added a method to check the group against the exhaustion source and return the percentage of exhaustion that is nullified. Mining, jumping hitting and hurting were simple enough, but the LivingHealEvent doesn't differentiate between natural and artificial regeneration, so I would need to check if the player is under any relevant potion effects. Or I could leave it in as an extra perk if it's not feasible to fix.
The LivingUpdateEvent is used to check if the player is sprinting or swimming, but since it fires every time the player is updated, I would need to filter out the other updates so they aren't fired twice. I could've also used this to check to see if the player is under the hunger status effect. I ended up using PlayerTickEvent instead, but still needed to iron out some kinks. I also implemented a config to allow any food group to be tied to any exhaustion source.
Rebalancing
The next step was to make a list of vanilla foods from each category for the purposes of rebalancing. I included the hunger and saturation values for each, as well as their stackability, food group, extra effects, and how easy it was to farm. I asked people on twitter what their go-to food in Minecraft was, and what could encourage them to use different foods. Even though the player would be encouraged to use food from different groups, less useful foods within those groups (like mutton or beetroots) would still be used infrequently. The grains and sugars category didn't contain much, so it didn't need much balancing. There also weren't many foods that fell into more than one - only Cookies (sugar + grain), Pumpkin Pie (sugar + veges) and Rabbit Stew (veges + protein).
I ended up adding two measurements - Hunger/Time, meaning how much hunger points were restored per second, and Hunger*Stackability, meaning the total hunger points within a full stack. Soups and stews received an increased stack size of 16, encouraging their use a lot more, and cake a stack size of 64 to be in line with Bedrock edition. For the other less used foods, I changed their eat time to be the same as kelp, so their H/T score was increased but their H*St score was less than the better foods. Therefore the player is encouraged to choose between efficiency of consumption and efficiency of storage.
Efficiency of storage isn't that important when one has easy access to food, however, so I modified the meats I'd given a quicker eating time to. Their saturation is now their old saturation minus their hunger. I added the equivalent measurements for Saturation to identify this (S/T and S*St) so the choice is now between being able to eat quickly but often, or slowly but infrequently. Hopefully that will be a more interesting decision because it would vary based on the activity - a dangerous one would want quick eating to heal more easily, but a relaxing one would want infrequent eating as to not interrupt. More playtesting will be required, especially with a system as fundamental as hunger, to better balance this idea.
Telegraphing
The replacement of the hunger bar was much more complex than I expected. I used a RenderGameOverlayEvent to swap the icons, but this wouldn't work for all my functionality (as there would be no way to alternate the icons for foods with more than one group). So I ended up adapting the code that renders the hunger bar. Gegy helped make the rendering work by optimising the FoodGroup enum, cleaning up the code, and fixing bugs. Now it looks great!
Next step was compatibility with other mods that change the hunger bar rendering. The Nourished effect from Farmer's Delight makes the chicken bones golden, but that was easily achieved by reimplementing its functionality with the food group icons added. Appleskin also changes rendering, adding a subtle checkerboard effect behind the icons to represent exhaustion. Changing the event's priority to Lowest handled the checkerboard behind it, but reimplementing the saturation was slightly more complex. Since Appleskin is in the public domain, I simply copied the code and modified it.
When I asked kingbdogz from Mojang about the idea, he mentioned it could quickly get confusing for new players. To mitigate this, I decided to add an indicator that shows when the exhaustion reduction is applied. I took inspiration from how loading bars are often animated to give the illusion of progress, with a subtle sheen across the icon borders to imply the hunger was going down more slowly. This was implemented via a tracked data integer. It used to be a boolean, but instant things like mining and taking damage did not leave enough time for the sheen to last, so I made it an integer that counts down from 10. From playtesting, I found that a 50% decrease in exhaustion wasn't that noticable, so I buffed it to 75%. Another round of playtesting might be in order.
I posted a no context video of this telegraphing on my youtube and twitter, and also showed it to a friend. I asked them to guess how the mechanic worked; the people who guessed closest thought the sheen would cause hunger to be drained quicker, not slower. I suppose they associate the animation with motion and change, instead of slowing down. I will try reversing the direction of the sheen and enabling it when a non-exhaustion reducing activity is being done. Some alternative suggestions was to make the hunger bar look "protected" or "stronger" in some way, such as making the outline bolder or the sheen more constant or like an energy shield.
Configuration
Before releasing it officially, I wanted to make it compatible with mods most likely to be playtested with it. I started with the food in the abnormals mods and farmer's delight, with the intention of balancing their food in a similar way to how I did vanilla's. However, this would've involved balancing around 200 foods with vanilla's 31 - so instead I decided to give people the power to change the stats I might have with datapacks. This meant I had to learn how to load datapacks, which Gegy was happy to help me with again. The last uni course I took dealt with json, so parsing that was easy to code.
The harder bit was resetting these modifications, so if people removed changes to their food, they'd be removed in the game on datapack refresh. I achieved that by recording the food's name and values before the food is initially changed, and then I put these values back in whenever the datapack is reloaded. I also changed my overrides to be in an autogenerated json, so that people can see what structure the json takes. Because of this, I had to redo my json parser to take food stats first, then food type, instead of the other way around. I also decided to add the ability to change whether a food can be eaten when full (like you can with honey, golden apples and chorus fruit). A silly mistake with reflection impeded my progress, but after that it was all good. I also changed the regular config to allow binding of multiple food groups to a single exhaustive activity, to increase customisability.
Reception
I then made a video adapting this development log into a video. At the start, I included a less confusing version of the telegraphing and encouraged people to comment with their impressions, before they learn what it meant. I have gotten a lot of comments, and these are now on a document waiting for me to sift through them. I plan to record how many people guessed correctly versus guessing the opposite, as well as some other common response types. I also plan to record some ideas for telegraphing that I particularly liked, so I can decide what to do.
A lot of people seemed to think that the hunger bar was refilling, so I wondered if I could make that essentially happen (because a slow loss is the same as a quick loss and a slow gain). I'd have an effect showing the hunger bar "filling" up for continuous exhaustion loss, and for instant exhaustion loss I would add a flash similar to the one done when regaining hearts. Or, I could add the exhaustion reduction to a buffer that heals hunger over time, shown by a potion effect. The problem with that though, is that it wouldn't be clear when the effect is being added to. I'll need to think about it a bit more, but I'm currently thinking it's too complex a solution, and creates its own problems.
Also, some people thought the new hunger icons looked messy, especially when alternating. I got Rye to change the icons to still have a recognisable shape and colour, but have an orientation similar to the shank to look neater.
Bugfixing
I got a few bug reports, too. Some client code was running on the server causing it to crash, which was an easy fix. Since Farmer's Delight also makes soup stackable, it also included similar logic for eating soup, meaning with mine two bowls were produced per soup, instead of one. This was fixed by me checking if Farmer's Delight was installed and the stackable soup config was on. I also needed to make cake count as food, which was as easy as adding an event for right-clicking on a block, then checking if it was cake.
Another common bug was other GUI tweaks from mods failing to show. This was because I cancelled the event to stop other icons from overlapping mine. I decided to uncancel the event and manually disable overlapping changes. Appleskin could do this via events, but I had to hook into these events in a different way - Silk and gigaherz helped me to keep it working when Appleskin wasn't installed. While I was at it, I made sure Appleskin's config influenced my replacements, like the saturation outline. For vanilla, I bound an empty texture during the pre render event, which was a little jank, but even more jank was how I fixed the Farmer's Delight nourishment icons. I changed the runtime record of its config to be false after checking if it ran, and then resetting the record to what it should be in the pre event, thereby preventing them from rendering. I also added some small tweaks, like making the default last food eaten steak, and added some tooltips for Diet compatibility.
Future
I have a few plans for what I want to do next. Some people have offered to help with balancing Farmer's Delight at least, since it's a very popular food mod. I also plan to rebalance individual exhaustion reductions, because even if one is fighting a lot, they're still running around so it may be more useful to eat vegetables anyway. If I've learnt anything from this, I think it would be that a better way to improve the hunger system would to be first simplify it, then add complexity. Not only was there a lot to consider for this mod's balance, it is also not very intuitive for players, even with the telegraphing.