As more mods are being added to the game, I’ve noticed that a lot of the values kept on a character aren’t done in a way that allows for certain types of events.
For example:
The current way the body handles fat is to take a total value, and distribute it based on percentage values with hard caps on those percentages to prevent their combined total from exceeding 100%. While it works for the basic setup, there are some things it can’t do.
-
This system cannot be used to dynamically calculated added or lost fat if the values for the percentage distributions change as fat is gained/lost. If a percentage value changes, it affects not only the added/lost amount, but also what is already present in that organ/area.
-
None of the distribution values can exceed 33% without breaking the engine or requiring a mod/dev-hack to achieve.
This one’s actually a simple enough fix. Using a feature similar to how the game calculates for stretchmarks, you can have the total fat have a current and previous value stored to the character. As for the percentages, There’s a simple formula to check for the values to keep them in scale with one another.
(area) + (areas) + (etc) > 100
or, with the current genes:
(fat-chest) + (fat-waist) + (fat-hips) > 100
Using that as a check, if the total comes up over 100, the next step is to fix a problem when it happens. This would be done with a loop that uses a check something like this:
{(area) + (areas) + (etc) - 100} / (number of areas) =< 0
for now…
{(fat-chest) + (fat-waist) + (fat-hips) - 100} / 3 =< 0
The number of areas is important for later, as it allows this feature to be expanded when other organs and their fat content become implemented (such as butt, legs, arms, all that fun stuff). As long as this check is FALSE, you use that formula to make a number that gets applied to each of the fat values to scale them all down relative to one another.
Something like:
check = {(area) + (areas) + (etc) - 100} / (number of areas)
While (check >= 0) Do
{
red_val = check
new_area = (area * red_val) * (red_val / 100)
new_areas = (areas * red_val) * (red_val / 100)
new_etc = (etc * red_val) * (red_val / 100)
// add more values here when new fat placements are added
area = new_area
areas = new_areas
etc = new_etc
// see above comment
check = {(area) + (areas) + (etc) - 100} / (number of areas)
// make sure all formulas used have the full list of areas in them as well as the proper number to divide by
}
if (area + areas + etc < 100)
{
fat-left = 100 - (area + areas + etc)
}
From there, it can do the fat distribution by using the current and previous fat totals to add/subtract with the updated values. If it looks a little confusing without numbers, then here’s an example.
breasts = 54
waist = 30
hips = 40
check_over = (55) + (31) + (40)
// in this example, check_over = 126
while (check_over) > 100
{
check_redo = {(check_over) - 100} / 3
// in this example, check_redo = 8
new_breasts = (55 * 8) *(8 / 100)
new_waist = (31 * 8) * (8 / 100)
new_hips = (40 * 8) * (8 / 100)
// in order, the new values are: 35.2, 19.84, and 25.6
breasts = (35.2)
waist = (19.84)
hips = (25.6)
// numbers would be replaced by the names for new_breasts, new_waist , and new_hips in the actual code
check_over = {(35.2) + (19.84) + (25.6)
// total comes up to 80.64 before subtraction of 100, loop ends
// may consider hard capping the decimals to prevent loop running infinitely.
}
if check_over < 100
{
left_fat = 100 - {(25.2) + (19.84) + (25.6)}
// in this example, fat_left = 19.36
}
// Results:
// breasts = 35.2
// waist = 19.84
// hips = 25.6
// left_fat = 19.36
Okay, so it’s imperfect what with the leftover value being kind of large, but it does reduce the allotted total below 100 without messing up the non-remainder values’ relative to one another which was the primary issue. At this point, the calculations can carry out about the same way they used to, but instead of the engine redistributing all of the person’s fat, it just takes the difference of the current from previous volumes and adds/subtracts that result.
fat_mod = fat_now - fat_then
fat_breasts = fat_breasts + (breasts / 100) * fat_mod
fat_waist = fat_waist + (waist / 100) * fat_mod
fat_hips = fat_hips + (hips / 100) * fat_mod
fat_left = fat_left + (left_fat / 100) * fat_mod
So, if the numbers before calculation are are:
fat_breasts = 275
fat_waist = 250
fat_hips = 375
fat_left = 100
calorie_add = 200
// this is fetched by adding the result of the calorie conversion to fat_then, pretty much the same way it has been
// if it wasn’t for wanting the potential to lose fat, just using calorie_add and fat_total would’ve worked
fat_then = (275) + (250) + (375) + (100)
// in this example, the total is 1000
fat_now = fat_then + calorie_add
// in this example, the total is 1200
fat_mod = (1200) - (1000)
// in this example, the total is 200
// This will be using the percentages from the previous example
fat_breasts = (275) + (35.2 / 100) * (200)
fat_waist = (250) + (19.84 / 100) * (200)
fat_hips = (375) + (25.6 / 100) * (200)
fat_left = (100) + (19.36 / 100) * (200)
// this system’s results are:
// fat_breasts = 345.4
// fat_waist = 289.68
// fat_hips = 426.2
// fat_left = 138.72
//old system’s results would be:
// fat_breasts = 422.4
// fat_waist = 238.08
// fat_hips = 307.2
// fat_left = 232.32
With this in place, the engine would only use the 200 units worth with the new percentages instead of the full 1200. To make this system play nice with mods like the ‘Watermelon Special’ body mod, just have the event set the previous volume to 0 for both the total and individual area values when it recalculates the fat distribution to replicate how the old system handled fat distribution.
This next bit could be used as a model to handle fat distribution just so the system doesn’t go through all of the motions every time an hour goes by when the proxy hasn’t had a change in their fat totals.
if (fat_mod != 0)
{
// do all the stuff for check_ over
// do fat_recalc for each organ
}
This is just one step, as it might help to move all the fat calculations into their own organ, if just to minimize the amount of code that needs to be added.
There’s more I had in mind for overhauls/additions to the base system, but that’ll be in another post.