Skip to content

Commit

Permalink
Corpses can decay into bones, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
RenechCDDA committed Jun 5, 2024
1 parent 8249ff5 commit 5ef67e4
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doc/MONSTERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ Property | Description
`path_settings` | (object) How monster may find a path, open doors, avoid traps, or bash obstacles
`biosignature` | (object) Droppings or feces left by the animal or monster
`harvest` | (string) ID of a "harvest" type describing what can be harvested from the corpse
`dissect` | (string) (Optional) ID of a "harvest" type describing what is returned when a corpse of this monster is dissected
`decay` | (string) (Optional) ID of a "harvest" type describing what is left when a corpse of this monster rots away
`zombify_into` | (string) mtype_id this monster zombifies into after it's death
`fungalize_into` | (string) mtype_id this monster turns into when fungalized by spores
`shearing` | (array of objects) Items produced when the monster is sheared
Expand Down
8 changes: 8 additions & 0 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14234,6 +14234,9 @@ bool item::process_internal( map &here, Character *carrier, const tripoint &pos,
if( is_comestible() ) {
here.rotten_item_spawn( *this, pos );
}
if( is_corpse() ) {
here.handle_decayed_corpse( *this, here.getglobal( pos ) );
}
return true;
}
} else {
Expand Down Expand Up @@ -14620,6 +14623,11 @@ std::string item::type_name( unsigned int quantity, bool use_variant, bool use_c
return ret_name;
}

const mtype *item::get_corpse_mon() const
{
return corpse;
}

std::string item::get_corpse_name() const
{
return corpse_name;
Expand Down
1 change: 1 addition & 0 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -3081,6 +3081,7 @@ class item : public visitable
item_components components;
/** What faults (if any) currently apply to this item */
cata::heap<std::set<fault_id>> faults;
const mtype *get_corpse_mon() const;

private:
item_contents contents;
Expand Down
50 changes: 50 additions & 0 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8414,6 +8414,56 @@ void map::loadn( const point &grid, bool update_vehicles )
}
}

void map::handle_decayed_corpse( const item &it, const tripoint_abs_ms &pnt )
{
if( !it.is_corpse() ) {
debugmsg( "Tried to decay a non-corpse item %s. Aborted", it.tname() );
return;
}
const mtype *dead_monster = it.get_corpse_mon();
if( !dead_monster ) {
debugmsg( "Corpse at abs_ms %s has no associated monster?!", pnt.to_string() );
return;
}

if( dead_monster->decay.is_null() ) {
return;
}
int decayed_weight_grams = to_gram( dead_monster->weight ); // corpse might have stuff in it!
decayed_weight_grams += std::round( decayed_weight_grams * rng_float( -0.1, 0.1 ) );
bool notify_player = false;
if( calendar::once_every( 30_minutes ) ) {
//one corpse max in 30 minutes will notify if seen, for *all* the items it left
notify_player = true;
}

bool anything_left = false;
for( const harvest_entry &entry : dead_monster->decay.obj() ) {
item harvest = item( entry.drop );
const float random_decay_modifier = rng_float( 0.0f, static_cast<float>( MAX_SKILL ) );
const float min_num = entry.scale_num.first * random_decay_modifier + entry.base_num.first;
const float max_num = entry.scale_num.second * random_decay_modifier + entry.base_num.second;
int roll = 0;
if( entry.mass_ratio != 0.00f ) {
roll = static_cast<int>( std::round( entry.mass_ratio * decayed_weight_grams ) );
roll = std::ceil( static_cast<double>( roll ) / to_gram( harvest.type->weight ) );
} else {
roll = std::min<int>( entry.max, std::round( rng_float( min_num, max_num ) ) );
}
anything_left = roll > 0;
for( int i = 0; i < roll; i++ ) {
if( harvest.has_temperature() ) {
harvest.set_item_temperature( get_weather().get_temperature( project_to<coords::omt>( pnt ) ) );
}
add_item_or_charges( bub_from_abs( pnt ), harvest, false );
if( anything_left && notify_player ) {
add_msg_if_player_sees( getlocal( pnt ), _( "You notice a %1$s has rotted away, leaving a %2$s." ),
it.tname(), harvest.tname() );
}
}
}
}

void map::rotten_item_spawn( const item &item, const tripoint &pnt )
{
if( get_creature_tracker().creature_at( pnt ) != nullptr ) {
Expand Down
7 changes: 7 additions & 0 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,13 @@ class map
*/
void spawn_monsters( bool ignore_sight, bool spawn_nonlocal = false );

/**
* Checks to see if the corpse that is rotting away generates items when it does.
* @param it item that is spawning creatures
* @param pnt The point on this map where the item is and where bones/etc will be
*/
void handle_decayed_corpse( const item &it, const tripoint_abs_ms &pnt );

/**
* Checks to see if the item that is rotting away generates a creature when it does.
* @param item item that is spawning creatures
Expand Down
2 changes: 2 additions & 0 deletions src/monstergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,8 @@ void mtype::load( const JsonObject &jo, const std::string &src )

optional( jo, was_loaded, "dissect", dissect );

optional( jo, was_loaded, "decay", decay );

if( jo.has_array( "shearing" ) ) {
std::vector<shearing_entry> entries;
for( JsonObject shearing_entry : jo.get_array( "shearing" ) ) {
Expand Down
2 changes: 2 additions & 0 deletions src/mtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "weakpoint.h"

static const harvest_id harvest_list_human( "human" );
static const harvest_id harvest_list_null( "null" );

static const itype_id itype_bone( "bone" );
static const itype_id itype_bone_tainted( "bone_tainted" );
Expand Down Expand Up @@ -319,6 +320,7 @@ mtype::mtype()
sp_defense = nullptr;
melee_training_cap = MAX_SKILL;
harvest = harvest_list_human;
decay = harvest_list_null;
luminance = 0;
bash_skill = 0;

Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ struct mtype {
mfaction_str_id default_faction;
harvest_id harvest;
harvest_id dissect;
harvest_id decay;
speed_description_id speed_desc;
// Monster upgrade variables
mtype_id upgrade_into;
Expand Down

0 comments on commit 5ef67e4

Please sign in to comment.