Skip to content

Commit

Permalink
Rot away items inside reality bubble (#39822)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hirmuolio authored Apr 26, 2020
1 parent cddfa7b commit 4ac15ac
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 74 deletions.
4 changes: 2 additions & 2 deletions src/iexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4719,7 +4719,7 @@ static void mill_activate( player &p, const tripoint &examp )
for( auto &it : g->m.i_at( examp ) ) {
if( it.has_flag( flag_MILLABLE ) ) {
// Do one final rot check before milling, then apply the PROCESSING flag to prevent further checks.
it.process_temperature_rot( 1, examp, nullptr );
it.process_temperature_rot( 1, false, examp, nullptr );
it.set_flag( flag_PROCESSING );
}
}
Expand Down Expand Up @@ -4819,7 +4819,7 @@ static void smoker_activate( player &p, const tripoint &examp )
p.use_charges( "fire", 1 );
for( auto &it : g->m.i_at( examp ) ) {
if( it.has_flag( flag_SMOKABLE ) ) {
it.process_temperature_rot( 1, examp, nullptr );
it.process_temperature_rot( 1, false, examp, nullptr );
it.set_flag( flag_PROCESSING );
}
}
Expand Down
50 changes: 33 additions & 17 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8483,23 +8483,27 @@ bool item::detonate( const tripoint &p, std::vector<item> &drops )

return false;
}
bool item::has_rotten_away() const
{
if( is_corpse() && !can_revive() ) {
return get_rot() > 10_days;
} else {
return is_food() && get_relative_rot() > 2.0;
}
}

bool item::has_rotten_away( const tripoint &pnt )
{
if( is_corpse() && goes_bad() ) {
process_temperature_rot( 1, pnt, nullptr );
return get_rot() > 10_days && !can_revive();
} else if( goes_bad() ) {
process_temperature_rot( 1, pnt, nullptr );
return has_rotten_away();
if( goes_bad() ) {
return process_temperature_rot( 1, false, pnt, nullptr );
} else if( type->container && type->container->preserves ) {
// Containers like tin cans preserves all items inside, they do not rot at all.
return false;
} else if( type->container && type->container->seals ) {
// Items inside rot but do not vanish as the container seals them in.
for( item *c : contents.all_items_top() ) {
if( c->goes_bad() ) {
c->process_temperature_rot( 1, pnt, nullptr );
c->process_temperature_rot( 1, true, pnt, nullptr );
}
}
return false;
Expand Down Expand Up @@ -8644,7 +8648,8 @@ void item::apply_freezerburn()
}
}

void item::process_temperature_rot( float insulation, const tripoint &pos,
bool item::process_temperature_rot( float insulation, const bool seals,
const tripoint &pos,
player *carrier, const temperature_flag flag )
{
const time_point now = calendar::turn;
Expand All @@ -8654,14 +8659,14 @@ void item::process_temperature_rot( float insulation, const tripoint &pos,
if( now - last_temp_check < 0_turns ) {
reset_temp_check();
last_rot_check = now;
return;
return false;
}

// process temperature and rot at most once every 100_turns (10 min)
// note we're also gated by item::processing_speed
time_duration smallest_interval = 10_minutes;
if( now - last_temp_check < smallest_interval && specific_energy > 0 ) {
return;
return false;
}

int temp = g->weather.get_temperature( pos );
Expand Down Expand Up @@ -8772,9 +8777,9 @@ void item::process_temperature_rot( float insulation, const tripoint &pos,
if( process_rot && time - last_rot_check > smallest_interval ) {
calc_rot( time, env_temperature );

if( has_rotten_away() || ( is_corpse() && rot > 10_days ) ) {
if( has_rotten_away() && carrier == nullptr && !seals ) {
// No need to track item that will be gone
return;
return true;
}
}
}
Expand All @@ -8786,14 +8791,19 @@ void item::process_temperature_rot( float insulation, const tripoint &pos,
calc_temp( temp, insulation, now );
if( process_rot ) {
calc_rot( now, temp );

if( has_rotten_away() && carrier == nullptr && !seals ) {
return true;
}
}
return;
return false;
}

// Just now created items will get here.
if( specific_energy < 0 ) {
set_item_temperature( temp_to_kelvin( temp ) );
}
return false;
}

void item::calc_temp( const int temp, const float insulation, const time_point &time )
Expand Down Expand Up @@ -9459,14 +9469,16 @@ bool item::process( player *carrier, const tripoint &pos, bool activate, float i
temperature_flag flag )
{
const bool preserves = type->container && type->container->preserves;
const bool seals = type->container && type->container->seals;
std::vector<item *> removed_items;
visit_items( [&]( item * it ) {
if( preserves ) {
// Simulate that the item has already "rotten" up to last_rot_check, but as item::rot
// is not changed, the item is still fresh.
it->last_rot_check = calendar::turn;
}
if( it->process_internal( carrier, pos, activate, type->insulation_factor * insulation, flag ) ) {
if( it->process_internal( carrier, pos, activate, type->insulation_factor * insulation, seals,
flag ) ) {
removed_items.push_back( it );
}
return VisitResponse::NEXT;
Expand All @@ -9478,7 +9490,7 @@ bool item::process( player *carrier, const tripoint &pos, bool activate, float i
}

bool item::process_internal( player *carrier, const tripoint &pos, bool activate,
float insulation, const temperature_flag flag )
float insulation, const bool seals, const temperature_flag flag )
{
if( has_flag( flag_ETHEREAL_ITEM ) ) {
if( !has_var( "ethereal" ) ) {
Expand Down Expand Up @@ -9559,8 +9571,12 @@ bool item::process_internal( player *carrier, const tripoint &pos, bool activate
return process_tool( carrier, pos );
}
// All foods that go bad have temperature
if( has_temperature() ) {
process_temperature_rot( insulation, pos, carrier, flag );
if( has_temperature() &&
process_temperature_rot( insulation, seals, pos, carrier, flag ) ) {
if( is_comestible() ) {
g->m.rotten_item_spawn( *this, pos );
}
return true;
}

return false;
Expand Down
18 changes: 11 additions & 7 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,14 @@ class item : public visitable<item>
* Update rot for things that perish
* All items that rot also have temperature
* @param insulation Amount of insulation item has from surroundings
* @param seals Wether the item is in sealed container
* @param pos The current position
* @param carrier The current carrier
* @param flag to specify special temperature situations
* @return true if the item is fully rotten and is ready to be removed
*/
void process_temperature_rot( float insulation, const tripoint &pos, player *carrier,
temperature_flag flag = temperature_flag::TEMP_NORMAL );
bool process_temperature_rot( float insulation, bool seals, const tripoint &pos,
player *carrier, temperature_flag flag = temperature_flag::TEMP_NORMAL );

/** Set the item to HOT */
void heat_up();
Expand Down Expand Up @@ -837,10 +839,12 @@ class item : public visitable<item>
return get_relative_rot() > 1.0;
}

/** at twice regular shelf life perishable foods rot away completely. Corpses last longer */
bool has_rotten_away() const {
return is_food() && get_relative_rot() > 2.0;
}
/**
* Whether the item has enough rot that it should get removed.
* Regular shelf life perishable foods rot away completely at 2x shelf life. Corpses last 10 days
* @return true if the item has enough rot to be removed, false otherwise.
*/
bool has_rotten_away() const;

/** remove frozen tag and if it takes freezerburn, applies mushy/rotten */
void apply_freezerburn();
Expand Down Expand Up @@ -2080,7 +2084,7 @@ class item : public visitable<item>
const std::function<bool( const item & )> &filter = return_true<item> );
const use_function *get_use_internal( const std::string &use_name ) const;
bool process_internal( player *carrier, const tripoint &pos, bool activate, float insulation = 1,
temperature_flag flag = temperature_flag::TEMP_NORMAL );
bool seals = false, temperature_flag flag = temperature_flag::TEMP_NORMAL );
/**
* Calculate the thermal energy and temperature change of the item
* @param temp Temperature of surroundings
Expand Down
13 changes: 7 additions & 6 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,13 @@ class map
* If false, monsters are not spawned in view of player character.
*/
void spawn_monsters( bool ignore_sight );

/**
* Checks to see if the item that is rotting away generates a creature when it does.
* @param item item that is spawning creatures
* @param p The point on this map where the item is and creature will be
*/
void rotten_item_spawn( const item &item, const tripoint &p );
private:
// Helper #1 - spawns monsters on one submap
void spawn_monsters_submap( const tripoint &gp, bool ignore_sight );
Expand Down Expand Up @@ -1487,12 +1494,6 @@ class map
*/
template <typename Container>
void remove_rotten_items( Container &items, const tripoint &p );
/**
* Checks to see if the item that is rotting away generates a creature when it does.
* @param item item that is spawning creatures
* @param p The point on this map where the item is and creature will be
*/
void rotten_item_spawn( const item &item, const tripoint &p );
/**
* Try to fill funnel based items here. Simulates rain from @p since till now.
* @param p The location in this map where to fill funnels.
Expand Down
24 changes: 24 additions & 0 deletions tests/rot_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,27 @@ TEST_CASE( "Rate of rotting" )
CHECK( !freeze_item.item_tags.count( "FROZEN" ) );
}
}

TEST_CASE( "Items rot away" )
{
SECTION( "Item in reality bubble rots away" ) {
// Item should rot away when it has 2x of its shelf life in rot.

if( calendar::turn <= calendar::start_of_cataclysm ) {
calendar::turn = calendar::start_of_cataclysm + 1_minutes;
}

item test_item( "meat_cooked" );

// Process item once to set all of its values.
test_item.process( nullptr, tripoint_zero, false, 1, temperature_flag::TEMP_HEATER );

// Set rot to >2 days and process again. process_temperature_rot should return true.
calendar::turn += 20_minutes;
test_item.mod_rot( 2_days );

CHECK( test_item.process_temperature_rot( 1, false, tripoint_zero, nullptr,
temperature_flag::TEMP_HEATER ) );
INFO( "Rot: " << to_turns<int>( test_item.get_rot() ) );
}
}
Loading

0 comments on commit 4ac15ac

Please sign in to comment.