Shoes' Temperature mod

My temperature mod has been merged with the main game, hooray! (Feb 11th)

Features :

  • Each limb has its temperature tracked. If it gets too low, cold penalties apply in the form of diseases. Same for too hot.
    ** Body temperature is based on the outdoor temperature, the clothing the player wears, how wet the player is, how fatigued the player is.
  • The warmth of items have been put on a scale of 0 to 100 instead of 0 to 10. Fitted clothing is slightly warmer than non fitted.
  • The player will wake up due to cold. This is calculted based on what the player is sleeping on, and how tired the player is. When death from cold is implemented, it would be possible for a player to be so tired that he would continue sleeping until death if he is not careful.
  • Fire adds to player warmth. The intent is that one tile of fire will warm the player up considerably if he is close enough. In turn, standing next to a multi tile inferno will be very dangerous.
  • Being hot or cold affects morale.

Things to do :
* I want to make sure that a sensible combination of clothing will protext the player from cold. Legwear, for example, doesn’t have much that protects up to 100, so I will add snow pants or ski pants or long underwear to help.

  • I want to add a few more items that help with warmths. Things like cloaks, house coats, blankets, sleeping bags.
  • I want to make the makeshift bed more difficult to craft. Perhaps having stages (1 : wooden frame 2 : frame and bedding 3 : bedding and blanket).
  • I want to add some heated variants to craftable clothing. Fur lined trenchcoat, for example.
  • I want to add morale values to sleeping.
  • I will look into making fire a long term heat generator… something like fire + wood = charcoal, which will eventually “rot” by becoming cold. It would generate no light, but it would generate heat. You could pile charcoals together to keep warm at night… The alternative, would be to have fire pit “items” that consume fire as “fuel” for a longer time… Perhaps again, without generating light.
  • I need to allow bionics and other diseases to interact with body temp. Having a cold should lower temp, a flu increase it. There are a few bionics that protect from fire heat, or maintan internal body temps…
  • Indoor/outdoor should affect body temperature, as should a few weather effects. “Sunny” should probably add to bodytemp if the player is outdoors. Clear, a little less. Cloudy and others, not at all.
    * Add lava to the fire check.
  • In the future, I may look into adding a “heat map” much like the light map.
  • In the future, have hot and cold foods affect bodytemp.

Known issues :
None.

I would appreciate some feedback balance wise. I played a little bit to make sure certain things happened, but I doubt the system is perfect. I think, as is, it’s possible to wear a winter coat in the rain in +14C and have body temp drop dangerously low…

Feedback :

Update Feb 15th : Pushed some changes and another morale fix.

  • My first attempt at the morale fix was incomplete. Now, for cold, morale loss is a maximum of 22 for the total body, and then 44 for very cold, and 66 for freezing.
  • I added some frostbite code, so you can get frostnip or frostbite, causing pain as you warm up. Also added some messages
  • Added one in 200 chance for the player to complain about temperature. At the moment, it’s very simple (and the player may over complain at the moment…)

Take a look at player::try_to_sleep() and player::can_sleep() for the existing checks on whether the player can fall asleep initially, which is basically a balance between fatigue and comfort.

Aren’t bed frames just for storage purposes and vermin avoidance? I’ve never noticed them to result in a bed that was any warmer, at least.

More comfort perhaps?
I don’t know myself, because I sleep on a mattress, Perhaps warmth/comfort could simply be dependant of the number of sheets, blankets and pillows lying on the bed itself?

Perhaps the bed frame will just be for ingame difficulty in that case… but it is colder on ground level.

From the effects on temps thread, the idea of body temperature arose. I think this is key to much of what we want to do with temperature, especially sleep, because really, I want to player to wake up if he is too cold, and this should be measured from his body temp.

So I will try and look into assigning a body temperature and having it vary according to weather, clothing, and temperature… I hope this doesn’t get out of hand!

The actual purposes of bedframes are to isolate the sleeper from the ground thermally, make getting into and out of bed easier, and to reduce contact with vermin.

The second is pretty pointless for game purposes and I don’t think we want to mess with the third, but when it’s cold a bedframe would be superior to just a matress for maintaining body warmth.

You probably haven’t noticed a difference because in the past rooms weren’t maintained at “room temperature” at night, they’d often drop below freezing, so you’d really have to work to stay warm while sleeping. In modern homes it isn’t an issue.

The main factors I can think of are game::temperature, either an average or a min/max of player::warmth() across the body parts, map::is_outside() and type of bedding. There also might be some interactions with various mutations and/or bionics that you want to take into account. Nice and simple right :slight_smile:

Also probably want to figure out if being wet wakes you up already, if it does you can probably just ignore it…

The good news is all the data is there already, I don’t think you need to add any new data, just make some checks based on existing data.

Pff, you’re probably one of these people who actually pay for heat instead of just getting extra blankets, turning off their water and emptying the pipes in winter. :stuck_out_tongue:

I’ve had some very very cold nights, both with and without a frame, and didn’t notice much of an issue. But that’s also probably because I have/had a thermal sleeping bag and a LOT of blankets. Its hard to notice when both ways are “good enough”.

I live in the tropics here, Above the mosquito line, So basically I sleep with just a sheet, The only time you need a blanket is in winter.
Considering I don’t live in a place where the temperature even hits 0, I cannot really relate.
Most houses here do not have any form of climate control at all (just cheap pedestal fans and windows basically).

Since cataclysm is set somewhere much colder, I guess having a bed frame for thermal isolation would be a good idea.

THIS

What I think I will use as a formula to calculate loss of heat is the following :

new_bodytemp = current_bodytemp + modifier * (current_bodytemp - felt_air_temp)

or

new_bodytemp = current_bodytemp * ( 1 + modifier ) + modifier * felt_air_temp

felt_air_temp : combination of air temp and humidity.

Stock modifier, with no clothing, would be -0.018. This means that, half an hour in 32F weather drops body temps to death levels of cold, which I’m told is reality. The decline is quadratic, but barely so. I tried getting something exponential, but my math wasn’t working out.

Body temps also don’t drop below felt air temps.

At room temps, it would take about 3 hours for body temps to drop to room temps. I am not sure if reality works this way.

Warmth and wetness would affect the modifier somehow.

EDIT: It’s not really behaving how I want… I think all my formula above does is, after 30 minutes, the body temp will be nearly the felt air temp. Also, my 30 minutes is actually 3 minutes at the moment. Back to the drawing board…

I think I may be over thinking this. A model that slowly increments body temp towards outdoor temp, with warmth slowing down the increment, is incomplete, because the body is able to maintain 37C at 22C with light clothing. Perhaps I should just start with making hands and feet feel cold, and work that into sleeping…

This is why I said we should just treat the player as cold-blooded for the moment and keep it simple, The main drawback to this is that it means you can’t use actual body temp values because body temp will converge on ambient temp, which doesn’t actually happen unless you’re dead.

If you want to use realistic body temps internally*, you’ll need to add in a modifier for how much heat the body is generating to offset the losses or contribute to gains due to ambient temperature. This is a MUCH more difficult to balance system though and I think it’s a good idea to get a cold-blooded body temperature system working first, then see about converting to warm-blooded once all of the rest of the stuff is working.

And yes, if your goal is to just add the “being too cold makes you wake up” feature, you’re massively over thinking it, you don’t need to track body temp for that at all, just determine how uncomfortable the current temperature is for the player and use that to determine how likely it is to wake the player up.

We should rarely, if ever report actual body temp to the player*, so there’s no real reason to keep them realistic other than to make reasoning about them easier for the developers.

**Though we’ll probably want a debug option to stick an actual body temp readout somewhere for testing.

What I think I will do is look at a very simple, linear system.

Base body temp 37C + 0.10*warmth , base outdoor temp 22C.

Body temp will {+0.5, -0.5} for each {+2, -2} degrees outdoor temp stays from 22C. For every -2C, your body loses 0.5C. At 24C, you are 37.5 + 0.10amount of warmth. At 20C, you are 36.5 + 0.10amount of warmth. Simple solution. If you are indoor, changes occur at {+1, -4} ; indoor is hotter. Under ground could be {+3, -3}, or something similar once humidity is modeled. If you are wet, {+4, -1}, or perhaps your warmth modifier is cut in half, or even ignored. **see edit

The only thing that’s missing is a higher temp change at high gaps of temps. Perhaps for every 4 degrees the outdoor temp is different from the body temp, it’s a x2 to the +/-. If you are sitting at 37C and step outside to 6C, your body temp will change (-0.5 + warmth)*2^(4). The cap remains the same, but your body temp reaches it quicker.

I think this system could work. Body temps rise and fall with outdoor temp, fast if the gap is great. Body temps will not “reach” ambient temps, because “they generate heat” (ie my code doesn’t let them wander).

I don’t think limbs need body temps, perhaps just warmth; if modifier*warmth does not exceed temperature, then penalties occur. Like I mentioned in the other thread, the penalties will be of varying intensity, but the duration will only last until a small time after limbs and body are covered up. Perhaps 10 turns * intensity.

EDIT : Instead, the +/-0.5 will be a cap on body temp, and it will increment 0.1*2^(abs(22C - temp)/4) or something. It will take some time to reach a cap.

EDIT 2 : Here is my code at the moment.


void game::update_bodytemp()
{
 // Reference units
 int base_bodytemp = 37; // Celsius
 int base_airtemp  = 22; // Celsius, disregards humidity at the moment
 int converging_bodytemp = 37; // Bodytemp wants to converge to this ; starts at 37C
  
 int Ctemperature = (temperature - 32) * 5/9; // Converts temperature to Celsius!(Wito plans on using degrees Kelvin later)
 int temp_gap = Ctemperature - base_airtemp;  // distance between reference temperature and actual temperature ; this is negative if it is colder out.
 
 // Determine max bodytemp
 // PSEUDO CODE : need real values for outdoor, warmth and wetness
 if 	 ( outdoor && temp_gap < 0) 	{converging_bodytemp = base_bodytemp + temp_gap*0.20 + 0.10*(1 - wetness)*warmth;}
 else if      ( outdoor && temp_gap > 0) 	{converging_bodytemp = base_bodytemp + temp_gap*0.30 + 0.10*(1 - wetness)*warmth;}
 else if      (!outdoor && temp_gap < 0) 	{converging_bodytemp = base_bodytemp + temp_gap*0.50 + 0.10*(1 - wetness)*warmth;}
 else 	 (!outdoor && temp_gap > 0) 	{converging_bodytemp = base_bodytemp + temp_gap*0.10 + 0.10*(1 - wetness)*warmth;}
  
 // Actually change bodytemp
 if (turn % 10 == 0 && bodytemp > converging_bodytemp){ //if you're hotter than your surroundings
	bodytemp -= 0.1*2^(temp_gap/4);
 else if (turn % 10 == 0 && bodytemp > converging_bodytemp) //if you're colder
	bodytemp += 0.1*2^(temp_gap/4);
 else 								//if you're just right, +/- 0.1
	bodytemp += rng(-1, 1)/10;
 } 

 // Diseases
 // Body temp can ready three levels of low or high. Each level corresponds to the intensity of the disease, and brings with it symptoms.
 // The disease will last until the player is warmed up enough. Of course, it takes time for the body to warm up ; the higher the max temp, the faster the player warms up.
 // Remedys like drinking fluids or being near a fire _should_ reduce the intensity, but I am not sure how... perhaps by adding a flat amount to body temp. Hot adds, cold removes.
   

}

I am aware I am using int for things that clearly are not integers. I would like advice on that. Also, wetness in my mind is a measure of the morale wetness : from 0 to 50, and decreases slowly.

I am also not a coder, but I do have a math background and coding intrigues me. Any tips on how to make this more effecient or clean, let me know :slight_smile:

Mapping body temp to ambient temp with a simple offset to make it look like the model is warm-blooded sounds like a good approximation. I’m guessing this is what you were doing with the example code you posted in the other thread, unfortunately it’s gotten rather confusing since there are two conversations happening in parallel.
Indoors isn’t necessarily hotter, remember it isn’t climate controlled (except perhaps in a lab?), the only effect is that you aren’t exposed to wind/rain/sunlight.
Similarly I think underground areas already have their ambient temperature adjusted as appropriate, so you don’t have to worry about that impacting the calculation.

It seems that what you want to do is map body temp to ambient temp, which includes an offset and a magnitude change. The offset is 15C, and the magnitude you’re proposing is 4/1
So to do that directly, you have:
normalized_ambient_temp = (ambient_temp + 15) / 4;
Then you can just do:
temp_difference = normalized_ambient_temp - body temp;
and feed that into the code we were discussing before by reducing the magnitude of it to limit the rate of change.

The more general solution is to make the mapping explicit by defining some constants and calculating the offset and ratio explicitly like so:
#define MAX_AMBIENT_TEMP 100
#define MIN_AMBIENT_TEMP -40???
#define MAX_BODY_TEMP 42
#define MIN_BODY_TEMP 20

int normalize_ambient_temp(ambient_temp) {
const int ambient_to_body_ratio = (MAX_BODY_TEMP - MIN_BODY_TEMP) / (MAX_AMBIENT_TEMP - MIN_AMBIENT_TEMP);
return (ambient_temp - MIN_AMBIENT_TEMP) * ambient_to_body_ratio + MIN_BODY_TEMP;
}

Leaving the calculations explicit like this makes it easier for people to understand what you’re doing instead of baking the ratios into the code, and it also makes it easier to adjust in the future.

I’m wondering if warmth should just be applied as a raw bonus to effective body temp, so just to throw a number out there, each point of warmth adds 3C to effective body temp when calculating penalties. So if the first level of cold penalties sets in at 35C (definition of hypothermia), then one point of warmth would move the onset of penalties down to 33C.

If you aren’t tracking temp per limb, why are you even tracking temp?
As long as you keep your torso warm, you won’t actually lose any temp via exposed limbs, just suffer penalties, that doesn’t sound like it meets the goals of modelling temp in the first place.
It sounds like you’re planning on adding some kind of system for having temp-based conditions slowly recover based on adjusting temp or adding warmth, wasn’t that the point of tracking body temp in the first place?

Leaving the calculations explicit like this makes it easier for people to understand what you're doing instead of baking the ratios into the code, and it also makes it easier to adjust in the future.

Ideally, I would write this as explicitly as possible so it can be tweaked or balanced. If am going to try and clean up the start of my code with what you were talking about with normalized temperatures and whatnot.

I'm wondering if warmth should just be applied as a raw bonus to effective body temp, so just to throw a number out there, each point of warmth adds 3C to effective body temp when calculating penalties. So if the first level of cold penalties sets in at 35C (definition of hypothermia), then one point of warmth would move the onset of penalties down to 33C.

We’re sort of saying the same thing here. My code calculates the limits of how low/high the bodytemp can increment, and warmth adds a flat amount to that. So like you say, wearing warmth should offset temperature at which cold penalties kick in. Instead of dropping down to 33C, it’ll drop down to 35C due to the warmth bonus.

If you aren't tracking temp per limb, why are you even tracking temp? As long as you keep your torso warm, you won't actually lose any temp via exposed limbs, just suffer penalties, that doesn't sound like it meets the goals of modelling temp in the first place.

It wouldn’t be hard to do, really, just a pain to balance. My thoughts were that cold limbs won’t kill you, only cause frostbite and motor penalties. And I suppose to do this, I would end up having a similar system in place, just with different thresholds…

It sounds like you're planning on adding some kind of system for having temp-based conditions slowly recover based on adjusting temp or adding warmth, wasn't that the point of tracking body temp in the first place?

You’re right. Warming up from cold should be a slow process, but piling on fur coats with my code would shoot your body temp way up. Perhaps, because bodytemp rising from cold to hot is done via the body, it should be capped at the 0.1 increment (or something). Same thing could be done for going from hot to normal.

Edit: Oh, and thanks for the great feedback!

Edit: I am also not sure what to do with your feedback :slight_smile: Is the goal of your suggestion to fix the 5 int variables I have at the start? I think it is… because introduction 5 variables for this is silly indeed!

Edit: Also, I don’t like the idea of setting max temps for things. I like having body temp follow ambient temp, but at a slower rate. Mins and maxs would happen through death of the player. But I like the idea of defining my two reference temps of 22C and 37C with the #define

[quote=“Shoes, post:15, topic:128”]

If you aren’t tracking temp per limb, why are you even tracking temp?
As long as you keep your torso warm, you won’t actually lose any temp via exposed limbs, just suffer penalties, that doesn’t sound like it meets the goals of modelling temp in the first place.

It wouldn’t be hard to do, really, just a pain to balance. My thoughts were that cold limbs won’t kill you, only cause frostbite and motor penalties. And I suppose to do this, I would end up having a similar system in place, just with different thresholds…[/quote]

See that’s the problem, no matter what you have on your torso, if you sit around in sub-zero temps with no protection on head/legs/arms, you’re gonna die eventually, you are losing heat through the exposed extremities. Arguably you could just lose your fingers/hands/feet/etc without dying, but limb exposure can kill you, and even before that it can trigger hypothermic effects.

[quote=“Shoes, post:15, topic:128”]

It sounds like you’re planning on adding some kind of system for having temp-based conditions slowly recover based on adjusting temp or adding warmth, wasn’t that the point of tracking body temp in the first place?

You’re right. Warming up from cold should be a slow process, but piling on fur coats with my code would shoot your body temp way up. Perhaps, because bodytemp rising from cold to hot is done via the body, it should be capped at the 0.1 increment (or something). Same thing could be done for going from hot to normal.[/quote]

Ouch, that goes double for my suggestion, putting on enough clothes would immediately “cure” hypothermia. Still looking for where to stick the warmth value then.

Thanks for listening! :wink:

Even more so, thanks for putting in the time to figure it all out. I think I’m starting to see why Whales shelved the temperature handling stuff in the first place, it’s not as easy as it looked at first!

Ouch, that goes double for my suggestion, putting on enough clothes would immediately "cure" hypothermia. Still looking for where to stick the warmth value then.

I updated my model to handle it!

 int body_temp_gap = bodytemp - converging_bodytemp 

 // Actually change bodytemp
 if      (turn % 10 == 0 && bodytemp > converging_bodytemp && converging_bodytemp < 37) {bodytemp -= 0.1*2^(body_temp_gap/4);} // It is cold, you are getting cold
 else if (turn % 10 == 0 && bodytemp > converging_bodytemp && converging_bodytemp > 37) {bodytemp -= 0.1;}                     // It is warm, you are getting cold
 else if (turn % 10 == 0 && bodytemp < converging_bodytemp && converging_bodytemp < 37) {bodytemp += 0.1;}                     // It is cold, you are getting warm
 else if (turn % 10 == 0 && bodytemp < converging_bodytemp && converging_bodytemp > 37) {bodytemp += 0.1*2^(body_temp_gap/4);} // It is warm, you are getting warm
 else 												
	bodytemp += rng(-1, 1)/10;

There are four cases ; two where it’s your body recovering, and two where your body is suffering. If you are suffering from cold or heat, the body temp increments increase : suddenly -40C? You’re gonna lose 0.1*2[1] degrees the first minute, and then less the second minute, until your body temp converges to convering_bodytemp. But if you suddenly layer up, you will only gain 0.1 degree every minute, regardless of how many fur coats. This way, getting very cold is very detrimental, because it is slower to recover. It’s still easy to recover from ; wait 1 hour or so and you’re back, just like in reality.

Eventually, I could add a check to see if fire is nearby to add a bonus to the rate of increase. The bonus would be lower when you are already warm.


  1. bodyheat - min bodyheat ↩︎

Guys if you just use my formulas this is all so much simpler and you don’t have to worry about this weird behaviour! :stuck_out_tongue:

Our codes to pretty much the same thing: every 10 or 30 turns, update body temp and the increment is based on how far body temp is from environment temp. What I added in mine is the size of the temp gap also affects the size of the temp increment ; you get cold fast if it’s very cold out.

I do think where my code is now it covers more than yours, but you’re right I could have easily gone with what you wrote. I think it would be harder to balance heatGeneration though.

I am going to add the temp normalizing like you have at the end too :slight_smile: once I get this chunk done and working in game and I move onto the other body parts.

(I also like mine better because it’s the first real code I am contributing! :D)

If you have any feedback on what I wrote, lemme hear it too!

Uh… mine did this from the get go. It was built into the original formula. And it didn’t have any of the weird fixed offsets/fixed values or strange logic. I mean, do you have a random heating/cooling element there? Whats that for? :stuck_out_tongue:

I do think where my code is now it covers more than yours, but you're right I could have easily gone with what you wrote. I think it would be harder to balance heatGeneration though.
I don't. Hell, I could have given you the exact numbers to use if it would have helped.

Since I only provided the algorithm not the code, you still would have had to have written that. :wink: