Skip to content

Commit

Permalink
Merge pull request #79429 from GuardianDll/better_revivify
Browse files Browse the repository at this point in the history
expand revivification
  • Loading branch information
Maleclypse authored Feb 1, 2025
2 parents 128e933 + 3bf8300 commit 5a3d433
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 0 deletions.
19 changes: 19 additions & 0 deletions doc/JSON/MONSTERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Property | Description
`absorb_material` | (array of string) For monsters with the `ABSORB_ITEMS` special attack. Specifies the types of materials that the monster will seek to absorb. Items with multiple materials will be matched as long as it is made of at least one of the materials in this list. If not specified the monster will absorb all materials.
`no_absorb_material` | (array of string) For monsters with the `ABSORB_ITEMS` special attack. Specifies the types of materials that the monster is unable to absorb. This takes precedence over absorb_material; even if the monster is whitelisted for this material, it cannot do so if any of its materials are found here. If not specified, there are no limits placed on what was whitelisted.
`split_move_cost` | (int) For monsters with the `SPLIT` special attack. Determines the move cost when splitting into a copy of itself.
`revive_forms` | (array of objects) allows to define conditional monster revival, see explanation below

Properties in the above tables are explained in more detail in the sections below.

Expand Down Expand Up @@ -557,6 +558,24 @@ Field | Description
When defined the monster's unpulped corpse will rise, zombifying into the defined (different) monster. For mutated animals (including giant arthropods) the `mon_meat_cocoon` line of monsters should be defined, depending on the monster's weight:
No cocoon below 10 kg; 10 - 35 kg monsters zombify into the tiny cocoon; 36 - 100 kg monsters turn into the small cocoon; 101 - 300 kg monsters turn into the medium cocoon; 301+ kg monsters turn into a large cocoon.

## "revive_forms"

Advanced form of `zombify_into`, allows to specify reviving into different monsters depending on condition;

```c++
"revive_forms": [
{
// condition as dialogue condition, but with neither alpha nor beta talkers
// instead context variables `loc` (location of corpse) and `corpse_damage` are exposed
// can be omitted, in this case condition would be assumed to always be TRUE
"condition": { "map_terrain_with_flag": "SWIMMABLE", "loc": { "context_val": "loc" } },
// either `monster` or `monster_group` should be used
"monster": "pseudo_debug_mon"
"monster_group": "GROUP_ANIMALPOUND_CATS"
}
],
```
## "baby_flags"
(Array, optional)
Designate seasons during which this monster is capable of reproduction. ie: `[ "SPRING", "SUMMER" ]`
Expand Down
26 changes: 26 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5641,6 +5641,9 @@ bool game::revive_corpse( const tripoint_bub_ms &p, item &it, int radius )
// Failed reanimation due to corpse being butchered
return false;
}

assing_revive_form( it, p );

shared_ptr_fast<monster> newmon_ptr;
if( it.has_var( "zombie_form" ) ) {
// the monster was not a zombie but turns into one when its corpse is revived
Expand All @@ -5667,6 +5670,29 @@ bool game::revive_corpse( const tripoint_bub_ms &p, item &it, int radius )
return place_critter_around( newmon_ptr, tripoint_bub_ms( p ), radius );
}

void game::assing_revive_form( item &it, tripoint_bub_ms p )
{
const mtype *montype = it.get_mtype();
if( montype == nullptr ) {
return;
}
dialogue d( nullptr, nullptr );
write_var_value( var_type::context, "loc", &d, get_map().get_abs( p ).to_string() );
write_var_value( var_type::context, "corpse_damage", &d, it.damage() );
for( const revive_type &rev_type : montype->revive_types ) {
if( rev_type.condition( d ) ) {
if( !rev_type.revive_mon.is_null() ) {
it.set_var( "zombie_form", rev_type.revive_mon.str() );
return;
}
if( !rev_type.revive_monster_group.is_null() ) {
mtype_id mon = MonsterGroupManager::GetRandomMonsterFromGroup( rev_type.revive_monster_group );
it.set_var( "zombie_form", mon.str() );
}
}
}
}

void game::save_cyborg( item *cyborg, const tripoint_bub_ms &couch_pos, Character &installer )
{
int damage = cyborg->damage();
Expand Down
2 changes: 2 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ class game
bool revive_corpse( const tripoint_bub_ms &p, item &it );
// same as above, but with relaxed placement radius.
bool revive_corpse( const tripoint_bub_ms &p, item &it, int radius );
// evaluate what monster it should be, if necessary
void assing_revive_form( item &it, tripoint_bub_ms p );
/**Turns Broken Cyborg monster into Cyborg NPC via surgery*/
void save_cyborg( item *cyborg, const tripoint_bub_ms &couch_pos, Character &installer );
/** Asks if the player wants to cancel their activity, and if so cancels it. */
Expand Down
13 changes: 13 additions & 0 deletions src/monstergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,19 @@ void mtype::load( const JsonObject &jo, const std::string &src )
optional( jo_mount_items, was_loaded, "storage", mount_items.storage, itype_id() );
}

if( jo.has_array( "revive_forms" ) ) {
revive_type foo;
for( JsonObject jo_form : jo.get_array( "revive_forms" ) ) {
read_condition( jo_form, "condition", foo.condition, true );
if( jo_form.has_string( "monster" ) ) {
mandatory( jo_form, was_loaded, "monster", foo.revive_mon );
} else {
mandatory( jo_form, was_loaded, "monster_group", foo.revive_monster_group );
}
revive_types.push_back( foo );
}
}

optional( jo, was_loaded, "zombify_into", zombify_into, string_id_reader<::mtype> {},
mtype_id() );

Expand Down
8 changes: 8 additions & 0 deletions src/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ struct reproduction_type {
item_group_id baby_egg_group = item_group_id::NULL_ID();
};

struct revive_type {
std::function<bool( const_dialogue const & )> condition;
mtype_id revive_mon = mtype_id::NULL_ID();
mongroup_id revive_monster_group = mongroup_id::NULL_ID();
};

struct mtype {
private:
friend class MonsterGenerator;
Expand Down Expand Up @@ -316,6 +322,8 @@ struct mtype {
mongroup_id upgrade_group;
mtype_id burn_into;

std::vector<revive_type> revive_types;

mtype_id zombify_into; // mtype_id this monster zombifies into
mtype_id fungalize_into; // mtype_id this monster fungalize into

Expand Down

0 comments on commit 5a3d433

Please sign in to comment.