Ludeon Forums

RimWorld => Bugs => Topic started by: colinfang on January 29, 2022, 09:05:35 PM

Title: [1.3.3200] MinLeaflessTemperature & MaxLeaflessTemperature is not what it is
Post by: colinfang on January 29, 2022, 09:05:35 PM
Not sure if this is a bug or a feature, but I will write it down here any way.

I knew for a while that a plant is inedible if it is leafless. And the leafless temperature is controlled by 2 values `MinLeaflessTemperature=-10` &   `MaxLeaflessTemperature=-2`, which implies that a plant might lose its leaves as soon as the temperature drops below -2 °C

However, today I happened to notice in a game while the outdoor temperature is -9, none of the plants show leafless textures, so I started to wonder why...

Here is the relevant code (RimWorld 1.3) in `Plant.cs`, it is quite short and simple (at a first glance)

    protected virtual float LeaflessTemperatureThresh
    {
    get
    {
    float diff = MaxLeaflessTemperature - MinLeaflessTemperature;
    float leaflessThresh = ((this.HashOffset() * 0.01f) % diff) - diff + MaxLeaflessTemperature;
   
    return leaflessThresh;
    }
    }


The purpose of this code is to generate an instance dependent temperature threshold, so each plant has a different value which persists over its lifetime. This adds a bit of variation to ensure not all plants become leafless at the same time. Once we get the threshold, the leafless check is a straightforward `AmbientTemperature < threshold`. However from this code I cannot spot off the top of my head why `threshold` is not between (-10, -2)

... hours of debugging...

It turns out `HashOffset()` often returns a negative value. In fact, it is seeded by `ThingIDNumber`. One can verify that as long as there are less than 20M spawned things in the game in history, `HashOffset` is always negative.

C# remainder operator % has a feature that it would return negative values for negative operand. So `(this.HashOffset() * 0.01f) % diff)` has a range of (-8, 0), which gives the final leafless temperature threshold as (-18, -10). Myth solved.

A side note: The code converts the hash into single precision floats. Hence quite a lot of precisions are lost before  `%` operation. As a consequence plants that are spawned close in time together would have very similar leafless temperature threshold.
Title: Re: [1.3.3200] MinLeaflessTemperature & MaxLeaflessTemperature is not what it is
Post by: ison on February 04, 2022, 09:32:38 AM
Interesting! I checked it and it indeed ranges from -18 to -10. I checked the git history and it's been like this at least since 2014, so even if we change the code we'll probably adjust the values to match the old behavior. Thanks for finding this!