-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hot air from fires and direct heat radiation applies to tile temperatures #24956
Changes from 3 commits
1ecc2b0
96b0331
302fb2a
5ecb832
d7e72be
cec0b41
72efb9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1789,10 +1789,83 @@ void game::update_weather() | |
} | ||
} | ||
|
||
int game::get_heat_radiation( const tripoint &location, bool direct ) | ||
{ | ||
// Direct heat from fire sources | ||
// Cache fires to avoid scanning the map around us bp times | ||
// Stored as intensity-distance pairs | ||
int temp_mod = 0; | ||
std::vector<std::pair<int, int>> fires; | ||
fires.reserve( 13 * 13 ); | ||
int best_fire = 0; | ||
for( const tripoint &dest : g->m.points_in_radius( location, 6 ) ) { | ||
int heat_intensity = 0; | ||
|
||
int ffire = g->m.get_field_strength( dest, fd_fire ); | ||
if( ffire > 0 ) { | ||
heat_intensity = ffire; | ||
} else if( g->m.tr_at( dest ).loadid == tr_lava ) { | ||
heat_intensity = 3; | ||
} | ||
if( heat_intensity == 0 || !g->m.sees( location, dest, -1 ) ) { | ||
// No heat source here | ||
continue; | ||
} | ||
// Ensure fire_dist >= 1 to avoid divide-by-zero errors. | ||
const int fire_dist = std::max( 1, square_dist( dest, location ) ); | ||
fires.emplace_back( std::make_pair( heat_intensity, fire_dist ) ); | ||
if( fire_dist <= 1 ) { | ||
// Extend limbs/lean over a single adjacent fire to warm up | ||
best_fire = std::max( best_fire, heat_intensity ); | ||
} | ||
} | ||
|
||
for( const auto &intensity_dist : fires ) { | ||
const int intensity = intensity_dist.first; | ||
const int distance = intensity_dist.second; | ||
temp_mod += 6 * intensity * intensity / distance; | ||
} | ||
if( direct ) { | ||
return best_fire; | ||
} | ||
return temp_mod; | ||
} | ||
|
||
int game::get_convection_temperature( const tripoint &location ) | ||
{ | ||
// Heat from hot air (fields) | ||
int temp_mod = 0; | ||
const trap &trap_at_pos = g->m.tr_at( location ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whether function is moved from
Function is only called currently as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's freed from game class it losses access to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a map-reference is added as a parameter to the free function you can get rid of the |
||
// directly on fire/lava tiles | ||
int tile_strength = g->m.get_field_strength( location, fd_fire ); | ||
if( tile_strength > 0 || trap_at_pos.loadid == tr_lava ) { | ||
temp_mod += 300; | ||
} | ||
// hot air of a fire/lava | ||
auto tile_strength_mod = []( const tripoint &loc, field_id fld, int case_1, int case_2, int case_3 ){ | ||
int strength = g->m.get_field_strength( loc, fld ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition to changing from |
||
int cases[3] = { case_1, case_2, case_3 }; | ||
return ( strength > 0 && strength < 4 ) ? cases[ strength - 1 ] : 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having looked into things more carefully the condition isn't necessary. Can be modified to just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and it sends the game into infinite loop with insane temperatures, stamina loss, and inevitable death. No, just no... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh I'm dumb. I was making an assumption and not validating that assumption. If the field does not exist at the location it's not going to be returning a value in range [1, 3]. Sorry for the bad suggestion. |
||
}; | ||
|
||
temp_mod += tile_strength_mod( location, fd_hot_air1, 2, 6, 10 ); | ||
temp_mod += tile_strength_mod( location, fd_hot_air2, 6, 16, 20 ); | ||
temp_mod += tile_strength_mod( location, fd_hot_air3, 16, 40, 70 ); | ||
temp_mod += tile_strength_mod( location, fd_hot_air4, 70, 100, 160 ); | ||
|
||
return temp_mod; | ||
} | ||
|
||
int game::get_temperature( const tripoint &location ) | ||
{ | ||
int temp_mod = 0; // local modifier | ||
|
||
if( !new_game ) { | ||
temp_mod += g->get_heat_radiation( location, false ); | ||
temp_mod += g->get_convection_temperature( location ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
} | ||
//underground temperature = average New England temperature = 43F/6C rounded to int | ||
return ( location.z < 0 ? AVERAGE_ANNUAL_TEMPERATURE : temperature ) + ( new_game ? 0 : m.temperature( location ) ); | ||
return ( location.z < 0 ? AVERAGE_ANNUAL_TEMPERATURE : temperature ) + ( new_game ? 0 : ( m.temperature( location ) + temp_mod ) ); | ||
} | ||
|
||
int game::assign_mission_id() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -605,6 +605,13 @@ class game | |
int get_user_action_counter() const; | ||
|
||
signed char temperature; // The air temperature | ||
// Returns temperature modifier from direct heat radiation of nearby sources | ||
// @param location Location affected by heat sources | ||
// @param direct forces return of heat intensity (and not temperature modifier) of | ||
// adjacent hottest heat source | ||
int get_heat_radiation( const tripoint &location, bool direct ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does not need to be in class game. Only uses the |
||
// Returns temperature modifier from hot air fields of given location | ||
int get_convection_temperature( const tripoint &location ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oes not need to be in |
||
// Returns outdoor or indoor temperature of given location (in absolute (@ref map::getabs)) | ||
int get_temperature( const tripoint &location ); | ||
weather_type weather; // Weather pattern--SEE weather.h | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1032,35 +1032,10 @@ void player::update_bodytemp() | |
// Sunlight | ||
const int sunlight_warmth = g->is_in_sunlight( pos() ) ? 0 : | ||
( g->weather == WEATHER_SUNNY ? 1000 : 500 ); | ||
// Fire at our tile | ||
const int fire_warmth = bodytemp_modifier_fire(); | ||
|
||
// Cache fires to avoid scanning the map around us bp times | ||
// Stored as intensity-distance pairs | ||
std::vector<std::pair<int, int>> fires; | ||
fires.reserve( 13 * 13 ); | ||
int best_fire = 0; | ||
for( const tripoint &dest : g->m.points_in_radius( pos(), 6 ) ) { | ||
int heat_intensity = 0; | ||
|
||
int ffire = g->m.get_field_strength( dest, fd_fire ); | ||
if( ffire > 0 ) { | ||
heat_intensity = ffire; | ||
} else if( g->m.tr_at( dest ).loadid == tr_lava ) { | ||
heat_intensity = 3; | ||
} | ||
if( heat_intensity == 0 || !g->m.sees( pos(), dest, -1 ) ) { | ||
// No heat source here | ||
continue; | ||
} | ||
// Ensure fire_dist >= 1 to avoid divide-by-zero errors. | ||
const int fire_dist = std::max( 1, square_dist( dest, pos() ) ); | ||
fires.emplace_back( std::make_pair( heat_intensity, fire_dist ) ); | ||
if( fire_dist <= 1 ) { | ||
// Extend limbs/lean over a single adjacent fire to warm up | ||
best_fire = std::max( best_fire, heat_intensity ); | ||
} | ||
} | ||
// Hot air from a heat source | ||
// times 50 to convert to weather.h BODYTEMP scale | ||
const int fire_warmth = g->get_convection_temperature( pos() ) * 50; | ||
const int best_fire = g->get_heat_radiation( pos(), true ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
|
||
const int lying_warmth = use_floor_warmth ? floor_warmth( pos() ) : 0; | ||
const int water_temperature = | ||
|
@@ -1122,16 +1097,14 @@ void player::update_bodytemp() | |
// CONVECTION HEAT SOURCES (generates body heat, helps fight frostbite) | ||
// Bark : lowers blister count to -10; harder to get blisters | ||
int blister_count = ( has_bark ? -10 : 0 ); // If the counter is high, your skin starts to burn | ||
for( const auto &intensity_dist : fires ) { | ||
const int intensity = intensity_dist.first; | ||
const int distance = intensity_dist.second; | ||
if( frostbite_timer[bp] > 0 ) { | ||
frostbite_timer[bp] -= std::max( 0, intensity - distance / 2 ); | ||
} | ||
const int heat_here = intensity * intensity / distance; | ||
temp_conv[bp] += 300 * heat_here; | ||
blister_count += heat_here; | ||
|
||
const int h_radiation = g->get_heat_radiation( pos(), false ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
temp_conv[bp] += h_radiation * 50; // conversion to BODYTEMP see weather.h | ||
if( frostbite_timer[bp] > 0 ) { | ||
frostbite_timer[bp] -= std::max( 5, h_radiation ); | ||
} | ||
blister_count += h_radiation - 111 > 0 ? std::max( h_radiation - 111, 0) : 0; | ||
|
||
// Bionic "Thermal Dissipation" says it prevents fire damage up to 2000F. | ||
// But it's kinda hard to get the balance right, let's go with 20 blisters | ||
if( has_heatsink ) { | ||
|
@@ -1569,80 +1542,6 @@ int player::floor_warmth( const tripoint &pos ) const | |
return ( item_warmth + bedding_warmth + floor_mut_warmth ); | ||
} | ||
|
||
int player::bodytemp_modifier_fire() const | ||
{ | ||
int temp_conv = 0; | ||
// Being on fire increases very intensely the convergent temperature. | ||
if( has_effect( effect_onfire ) ) { | ||
temp_conv += 15000; | ||
} | ||
|
||
const trap &trap_at_pos = g->m.tr_at( pos() ); | ||
// Same with standing on fire. | ||
int tile_strength = g->m.get_field_strength( pos(), fd_fire ); | ||
if( tile_strength > 2 || trap_at_pos.loadid == tr_lava ) { | ||
temp_conv += 15000; | ||
} | ||
// Standing in the hot air of a fire is nice. | ||
tile_strength = g->m.get_field_strength( pos(), fd_hot_air1 ); | ||
switch( tile_strength ) { | ||
case 3: | ||
temp_conv += 500; | ||
break; | ||
case 2: | ||
temp_conv += 300; | ||
break; | ||
case 1: | ||
temp_conv += 100; | ||
break; | ||
default: | ||
break; | ||
} | ||
tile_strength = g->m.get_field_strength( pos(), fd_hot_air2 ); | ||
switch( tile_strength ) { | ||
case 3: | ||
temp_conv += 1000; | ||
break; | ||
case 2: | ||
temp_conv += 800; | ||
break; | ||
case 1: | ||
temp_conv += 300; | ||
break; | ||
default: | ||
break; | ||
} | ||
tile_strength = g->m.get_field_strength( pos(), fd_hot_air3 ); | ||
switch( tile_strength ) { | ||
case 3: | ||
temp_conv += 3500; | ||
break; | ||
case 2: | ||
temp_conv += 2000; | ||
break; | ||
case 1: | ||
temp_conv += 800; | ||
break; | ||
default: | ||
break; | ||
} | ||
tile_strength = g->m.get_field_strength( pos(), fd_hot_air4 ); | ||
switch( tile_strength ) { | ||
case 3: | ||
temp_conv += 8000; | ||
break; | ||
case 2: | ||
temp_conv += 5000; | ||
break; | ||
case 1: | ||
temp_conv += 3500; | ||
break; | ||
default: | ||
break; | ||
} | ||
return temp_conv; | ||
} | ||
|
||
int player::bodytemp_modifier_traits( bool overheated ) const | ||
{ | ||
int mod = 0; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether function is moved from
class game
to be a free function, or remains as is, can shorten all instances ofg->m.__func__
to justm.__func__
Other lines impacted:
Function is only called currently as
g->get_heat_radiation
so it already has access to the global-g's map.