Home | Download | Discussion | Help | Site Map | New Posts | Sign in

Latest Site News

New Creator Theme: Elders! - posted on 1st Sep 2018 at 6:43 AM
Replies: 8 (Who?), Viewed: 1349 times.
Test Subject
Original Poster
#1 Old 2nd Feb 2018 at 10:22 PM
Default HELP! Script mod to override pregnancy calculation.
Hi!

I'm new in this mod world, and I need some help.
I'm trying to have "real age" sims. It means they will live from 60 to 75 sim-years. It was easy to do, just changed the numbers of days they live and created a package. Its working. Yeah!

But the problem is: i want a 280 days (40 weeks, or 9 months) pregnancy. I tried to make this by changing the PREGNANCY_RATE in the pregnancy_tracker file. It turns that it works for little changes, but I could never reach the 280 days pregnancy (not even close).

Then, I went deeper. I start looking the codes, trying to find the formula that explains that RATE, and try to change it, with a script mod. I found it. In the pregnancy_tracker hehe.

It apparently add the RATE every sim-minute to the pregnancy, until it reaches the max, when it starts the "In Labor" time.
I tried to change the formula, in many ways, but when I play the game the mod doesn't change anything in the pregnancy time. Thats why I'm here. I tried to make it longer, shorter, altering the formula, but it changes nothing in the game.

I'll let the code here. The formula is not altered here:
Quote:
import injector
from sims.pregnancy.pregnancy_tracker import PregnancyTracker

@injector.inject_to(PregnancyTracker, 'update_pregnancy')
def my_pregnancy_time(original, self):
if self.is_pregnant:
if self._last_modified is not None:
tracker = self._sim_info.get_tracker(self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species))
pregnancy_commodity = tracker.get_statistic(self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species), add=True)
if pregnancy_commodity.get_value() >= self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species).max_value:
if self._sim_info.household is not services.active_household():
self._create_and_name_offspring()
self._show_npc_dialog()
self.clear_pregnancy()
else:
delta_time = services.time_service().sim_now - self._last_modified
delta = self.PREGNANCY_RATE * delta_time.in_minutes()
pregnancy_commodity.add_value(delta)
self._last_modified = services.time_service().sim_now
return


I tried
Quote:
delta = 280 * delta_time.in_minutes()
delta = self.PREGNANCY_RATE * delta_time.in_days()
delta = 280 * delta_time.in_days()
delta = (1 / 280) * delta_time.in_days()
delta = 0.00357 * delta_time.in_days()


Help?
Advertisement
Theorist
#2 Old 3rd Feb 2018 at 4:21 AM
The update_pregnancy method is only used for Sims that are not currently active. So any changes to it would only affect Sims that are off-lot.

The delta_time is the time between now (in Sim time) and the the last time the update was run for that Sim. So every once in a while (a Sim hour or so?) it runs that update on all off-lot pregnant Sims, calculates the time in Sim minutes since the last update, and multiplies that by the pregnancy rate modifier to simulate what would have happened if they were being played during that time period.

The pregnancy commodity climbs up from 0 to 100 (it will advance immediately to 20, if memory serves, when a pregnancy test is done to advance the pregnancy from not showing to 1st trimester). So to make the delta work you would need it to advance 1/403200th per Sim minute. That's roughly .00000248. The game should be able to handle numbers that low, it uses 24-bit precision floating point numbers internally if memory serves, so increments by that small a number should not lose precision even once it's getting close to 100. Not sure why setting that pregnancy rate that low doesn't work properly for you. It is possible it rounds it internally up to some value, or treats that low a value as invalid and reset to default. I'm not sure.

I'd suggest doing a quick script override for update_pregnancy to log that value in order to ensure that value is getting properly set. Looking at sims4.math it shows that EPSILON = 1.192092896e-07, so that 2.48e-06 from above should be an acceptably tunable value.
Test Subject
Original Poster
#3 Old 3rd Feb 2018 at 2:40 PM
Quote:
Originally Posted by scumbumbo
The update_pregnancy method is only used for Sims that are not currently active. So any changes to it would only affect Sims that are off-lot.

The delta_time is the time between now (in Sim time) and the the last time the update was run for that Sim. So every once in a while (a Sim hour or so?) it runs that update on all off-lot pregnant Sims, calculates the time in Sim minutes since the last update, and multiplies that by the pregnancy rate modifier to simulate what would have happened if they were being played during that time period.

The pregnancy commodity climbs up from 0 to 100 (it will advance immediately to 20, if memory serves, when a pregnancy test is done to advance the pregnancy from not showing to 1st trimester). So to make the delta work you would need it to advance 1/403200th per Sim minute. That's roughly .00000248. The game should be able to handle numbers that low, it uses 24-bit precision floating point numbers internally if memory serves, so increments by that small a number should not lose precision even once it's getting close to 100. Not sure why setting that pregnancy rate that low doesn't work properly for you. It is possible it rounds it internally up to some value, or treats that low a value as invalid and reset to default. I'm not sure.

I'd suggest doing a quick script override for update_pregnancy to log that value in order to ensure that value is getting properly set. Looking at sims4.math it shows that EPSILON = 1.192092896e-07, so that 2.48e-06 from above should be an acceptably tunable value.


I used your Logger (thanks for that, by the way), but it was not how i expected.
I edited the code of update_pregnancy like this:

Quote:
@PublicUnlock.rewrite(PregnancyTracker, 'update_pregnancy')
def seven_days_pregnancy(target, self):
logger.info('PR1 '.format(self.PREGNANCY_RATE))
if self.is_pregnant:
logger.info('PR2 '.format(self.PREGNANCY_RATE))
if self._last_modified is not None:
logger.info('PR3 '.format(self.PREGNANCY_RATE))
tracker = self._sim_info.get_tracker(self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species))
pregnancy_commodity = tracker.get_statistic(self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species), add=True)
if pregnancy_commodity.get_value() >= self.PREGNANCY_COMMODITY_MAP.get(self._sim_info.species).max_value:
logger.info('PR4 '.format(self.PREGNANCY_RATE))
if self._sim_info.household is not services.active_household():
logger.info('PR5 '.format(self.PREGNANCY_RATE))
self._create_and_name_offspring()
self._show_npc_dialog()
self.clear_pregnancy()
else:
logger.info('PR6 '.format(self.PREGNANCY_RATE))
delta_time = services.time_service().sim_now - self._last_modified
delta = self.PREGNANCY_RATE * delta_time.in_minutes()
pregnancy_commodity.add_value(delta)
self._last_modified = services.time_service().sim_now
logger.info('PR7 '.format(self.PREGNANCY_RATE))
return


But when I read the log, this is what I have:
Quote:
[INFO] PR1
[INFO] PR2
[INFO] PR7
[INFO] PR1
[INFO] PR2
[INFO] PR3
[INFO] PR6
[INFO] PR7
[INFO] PR1
[INFO] PR2
[INFO] PR7
[INFO] PR1
[INFO] PR2
[INFO] PR7
[INFO] PR1
[INFO] PR2
[INFO] PR3
[INFO] PR6
[INFO] PR7
[INFO] PR1
[INFO] PR2
[INFO] PR3
[INFO] PR6
[INFO] PR7


Its logging the marks, but not the RATE. Any idea?
Theorist
#4 Old 3rd Feb 2018 at 7:56 PM
The string.format() method uses the curly braces to inform it where to place the arguments you are trying to include in the string. There's a few ways you can log that value (you should only need to log it once btw, the pregnancy rate itself won't change during the update_pregnancy)
Code:
logger.info('PR1 {}'.format(self.PREGNANCY_RATE))

or just let the logger use it's own internal string.format(), like so:
Code:
logger.info('PR1 {}', self.PREGNANCY_RATE)

or you could simply concatenate the two values (after converting the float to a string) and skip the string.format() stuff all together:
Code:
logger.info('PR1 ' + str(self.PREGNANCY_RATE))

I typically use method #2 from the above myself, but your personal coding style may prefer one of the others.
Test Subject
Original Poster
#5 Old 4th Feb 2018 at 1:01 AM
Quote:
Originally Posted by scumbumbo
The string.format() method uses the curly braces to inform it where to place the arguments you are trying to include in the string. There's a few ways you can log that value (you should only need to log it once btw, the pregnancy rate itself won't change during the update_pregnancy)
Code:
logger.info('PR1 {}'.format(self.PREGNANCY_RATE))

or just let the logger use it's own internal string.format(), like so:
Code:
logger.info('PR1 {}', self.PREGNANCY_RATE)

or you could simply concatenate the two values (after converting the float to a string) and skip the string.format() stuff all together:
Code:
logger.info('PR1 ' + str(self.PREGNANCY_RATE))

I typically use method #2 from the above myself, but your personal coding style may prefer one of the others.


Thanks!!

I did it and changed the PREGNANCY_RATE to 00000248. In the log, it really appears to be 2.48E-06, but in the game, i have a problem.
It simply puts a random amount of days in the pregnancy buff (trimester 1), and when it reachs the 0, it restarts the time.
That is the problem.

My theory, is that it round down the number to 0. Thats because the same thing happens when I put PREGANCY_RATE = 0.
But I don't know where it does.

I don't know if this other information would help, but the greatest value that appears in the buff is 45 days.
There is were im stuck.
Theorist
#6 Old 4th Feb 2018 at 1:59 AM
Quote:
Originally Posted by SimSigma
I did it and changed the PREGNANCY_RATE to 00000248. In the log, it really appears to be 2.48E-06, but in the game, i have a problem.
It simply puts a random amount of days in the pregnancy buff (trimester 1), and when it reachs the 0, it restarts the time.

I don't know if this other information would help, but the greatest value that appears in the buff is 45 days.

Yeah, 2.48E-06 is a floating point representation of standard notation, so that's 2.48x10 to the -6 power which is correct. Let me re-check my math on what that number should be... 280 days x 24 hours x 60 minutes is 403,200 minutes for the pregnancy duration, so yeah you want to add 2.48E-06 - wait - no, that'd be for the commodity to advance from 0 to 1, you want to go to 100 so that value should be 2.48E-04, or .000248. My bad.

Maybe, if it was indeed rounding down at some point, setting it to that will fix it. Not sure. I may have to play around with this myself to see why it's not hitting the mark.
Test Subject
Original Poster
#7 Old 4th Feb 2018 at 2:39 PM
Quote:
Originally Posted by scumbumbo
Yeah, 2.48E-06 is a floating point representation of standard notation, so that's 2.48x10 to the -6 power which is correct. Let me re-check my math on what that number should be... 280 days x 24 hours x 60 minutes is 403,200 minutes for the pregnancy duration, so yeah you want to add 2.48E-06 - wait - no, that'd be for the commodity to advance from 0 to 1, you want to go to 100 so that value should be 2.48E-04, or .000248. My bad.

Maybe, if it was indeed rounding down at some point, setting it to that will fix it. Not sure. I may have to play around with this myself to see why it's not hitting the mark.


Are u sure its 100?
Looking at the pregnant_client_mixin file, i found this code:
Code:
 @pregnancy_progress.setter
def pregnancy_progress(self, value):
self._pregnancy_progress = clamp(0, value, 1) if value is not None else None
return

I don't know if this is the real progress of the pregnancy, or another thing.

Anyway, I changed the value to .000248 and the same thing is happening. The log says the PREGNANCY_RATE is correct, but the first trimester continues forever.
Theorist
#8 Old 4th Feb 2018 at 7:02 PM
Pretty sure, but never 100% sure, that's just typical of the values used with S4 commodities: 0 to 100, or -100 to 100. For the set pregnancy trimester in PMM I was setting the commodity to 1 for not showing, 25 for first trimester, 49 for second, 73 for third and then 97 for begin labor. But you can 100% count on EA to do things differently in different places of the code.

Like I said I may have to take a look myself.
Theorist
#9 Old 9th Feb 2018 at 10:49 AM
Following up on this, I figured out a bit tonight. The pregnancy_progress does indeed clamp from 0 to 1, but it is only used for communicating to the EXE how much to scale the pregnancy visual. The value can be set in the range of 0 to 1 to show the progression, but in the game it is set to 0.0 for not showing, and at the first trimester (commodity>25) it jumps to 0.5, at the second trimester (commodity>49) it goes to 0.75, third (commodity>73) is 0.95, and finally when ready for labor (commodity>97) it hits 1.0.

The two values don't appear to be linked at all except when those jumps occur at the specific commodity values, and the commodity itself (0-100) is what controls the actual length of the pregnancy.
Back to top