Skip to content

Commit

Permalink
The dissoluted devourer zombie (#34057)
Browse files Browse the repository at this point in the history
  • Loading branch information
free-coffee authored and kevingranade committed Oct 22, 2019
1 parent ae2ed10 commit 46ae118
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 11 deletions.
20 changes: 20 additions & 0 deletions data/json/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,26 @@
"desc": [ "You've been struck by lightning, and feel... different." ],
"base_mods": { "speed_mod": [ 50 ] }
},
{
"type": "effect_type",
"id": "grown_of_fuse",
"name": [ "Grown of Fusion" ],
"desc": [ "AI effect to increase stats after fusing with another critter. 1 stack means one absorbed max_hp." ],
"//": "stats modified by the zombie_fuse special attack.",
"//1": "scaling:",
"//2": "/48 HP: +0,5 melee_skill, +0,5 dodge_skill (unexpected movement), +5 Speed (bigger steps&more to attack with), +4 bash",
"//3": "/160 HP: +1 size",
"max_intensity": 480,
"base_mods": { "hit_mod": [ 0.0104 ], "dodge_mod": [ 0.0104 ], "speed_mod": [ 0.1042 ], "bash_mod": [ 0.08333 ] },
"scaling_mods": {
"hit_mod": [ 0.0104 ],
"dodge_mod": [ 0.0104 ],
"speed_mod": [ 0.1042 ],
"bash_mod": [ 0.08333 ],
"growth_mod": [ 0.00625 ]
},
"int_decay_step": 0
},
{
"type": "effect_type",
"id": "has_og_comm_freq"
Expand Down
51 changes: 51 additions & 0 deletions data/json/monsters/monsters.json
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,56 @@
"FILTHY"
]
},
{
"id": "mon_devourer",
"type": "MONSTER",
"name": "dissoluted devourer",
"description": "Human bodies fused together into a colossus with heads and limbs sticking out of its bloated body. You may have trouble estimating its healthiness and its capabilities might change.",
"default_faction": "zombie",
"bodytype": "human",
"species": [ "ZOMBIE", "HUMAN" ],
"diff": 8,
"volume": "92500 ml",
"weight": 120000,
"hp": 112,
"speed": 60,
"material": [ "flesh" ],
"symbol": "Z",
"color": "dark_gray_yellow",
"aggression": 100,
"morale": 100,
"melee_skill": 4,
"melee_dice": 3,
"melee_dice_sides": 3,
"melee_cut": 0,
"armor_bash": 5,
"armor_cut": 5,
"vision_night": 3,
"harvest": "zombie",
"special_attacks": [ [ "GRAB", 7 ], [ "scratch", 20 ], [ "ZOMBIE_FUSE", 80 ] ],
"death_drops": {
"subtype": "collection",
"groups": [ "default_zombie_death_drops", "default_zombie_death_drops", "default_zombie_death_drops" ]
},
"death_function": [ "SPLATTER", "NORMAL" ],
"flags": [
"SEES",
"HEARS",
"SMELLS",
"STUMBLES",
"WARM",
"BASHES",
"GROUP_BASH",
"POISON",
"NO_BREATHE",
"REVIVES",
"BILE_BLOOD",
"PUSH_MON",
"PATH_AVOID_DANGER_1",
"FILTHY",
"REGENERATES_1"
]
},
{
"id": "mon_breather",
"type": "MONSTER",
Expand Down Expand Up @@ -4775,6 +4825,7 @@
"death_drops": "default_zombie_death_drops",
"death_function": [ "NORMAL" ],
"burn_into": "mon_zombie_scorched",
"upgrades": { "half_life": 23, "into": "mon_devourer" },
"flags": [
"SEES",
"HEARS",
Expand Down
2 changes: 2 additions & 0 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,7 @@ void Creature::set_armor_cut_bonus( int ncutarm )
armor_cut_bonus = ncutarm;
}


void Creature::set_speed_base( int nspeed )
{
speed_base = nspeed;
Expand All @@ -1485,6 +1486,7 @@ void Creature::set_dodge_bonus( float ndodge )
{
dodge_bonus = ndodge;
}

void Creature::set_block_bonus( int nblock )
{
block_bonus = nblock;
Expand Down
13 changes: 6 additions & 7 deletions src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ struct pathfinding_settings;
struct trap;

enum m_size : int {
MS_TINY = 0, // Squirrel
MS_SMALL, // Dog
MS_MEDIUM, // Human
MS_LARGE, // Cow
MS_HUGE // TAAAANK
MS_TINY = 1, // Squirrel
MS_SMALL = 2, // Dog
MS_MEDIUM = 3, // Human
MS_LARGE = 4, // Cow
MS_HUGE = 5 // TAAAANK
};

enum FacingDirection {
Expand Down Expand Up @@ -342,7 +342,7 @@ class Creature
/** Removes a listed effect. bp = num_bp means to remove all effects of
* a given type, targeted or untargeted. Returns true if anything was
* removed. */
bool remove_effect( const efftype_id &eff_id, body_part bp = num_bp );
virtual bool remove_effect( const efftype_id &eff_id, body_part bp = num_bp );
/** Remove all effects. */
void clear_effects();
/** Check if creature has the matching effect. bp = num_bp means to check if the Creature has any effect
Expand Down Expand Up @@ -745,7 +745,6 @@ class Creature

int armor_bash_bonus;
int armor_cut_bonus;

int speed_base; // only speed needs a base, the rest are assumed at 0 and calculated off skills

int speed_bonus;
Expand Down
12 changes: 12 additions & 0 deletions src/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ bool effect_type::load_mod_data( JsonObject &jo, const std::string &member )
extract_effect( j, mod_data, "healing_head", member, "HEAL_HEAD", "amount" );
extract_effect( j, mod_data, "healing_torso", member, "HEAL_TORSO", "amount" );

// creature stats mod
extract_effect( j, mod_data, "dodge_mod", member, "DODGE", "min" );
extract_effect( j, mod_data, "hit_mod", member, "HIT", "min" );
extract_effect( j, mod_data, "bash_mod", member, "BASH", "min" );
extract_effect( j, mod_data, "cut_mod", member, "CUT", "min" );
extract_effect( j, mod_data, "growth_mod", member, "GROWTH", "min" );

return true;
} else {
return false;
Expand Down Expand Up @@ -465,6 +472,11 @@ bool effect_type::load_decay_msgs( JsonObject &jo, const std::string &member )
return false;
}

int effect_type::get_max_intensity() const
{
return max_intensity;
}

effect effect::null_effect;

bool effect::is_null() const
Expand Down
3 changes: 3 additions & 0 deletions src/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ class effect_type
/** Registers the effect in the global map */
static void register_ma_buff_effect( const effect_type &eff );

/** Returns the maximum intensity of this type. */
int get_max_intensity() const;

protected:
int max_intensity;
int max_effective_intensity;
Expand Down
31 changes: 31 additions & 0 deletions src/monattack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const efftype_id effect_fungus( "fungus" );
const efftype_id effect_glowing( "glowing" );
const efftype_id effect_got_checked( "got_checked" );
const efftype_id effect_grabbed( "grabbed" );
const efftype_id effect_grown_of_fuse( "grown_of_fuse" );
const efftype_id effect_grabbing( "grabbing" );
const efftype_id effect_has_bag( "has_bag" );
const efftype_id effect_infected( "infected" );
Expand Down Expand Up @@ -5269,6 +5270,36 @@ bool mattack::stretch_attack( monster *z )
return true;
}

bool mattack::zombie_fuse( monster *z )
{
monster *critter = nullptr;
for( const tripoint &p : g->m.points_in_radius( z->pos(), 1 ) ) {
critter = g->critter_at<monster>( p );
if( critter != nullptr && critter->faction == z->faction
&& critter != z && critter->get_size() <= z->get_size() ) {
break;
}
}

if( critter == nullptr ||
( z->get_hp() + critter->get_hp() > z->get_hp_max() +
effect_grown_of_fuse.obj().get_max_intensity() ) ) {
return false;
}
if( g->u.sees( *z ) ) {
add_msg( _( "The %1$s fuses with the %2$s." ),
critter->name(),
z->name() );
}
z->moves -= 200;
z->add_effect( effect_grown_of_fuse, 10_days, num_bp, true,
critter->get_hp_max() + z->get_effect( effect_grown_of_fuse ).get_intensity() );
z->heal( critter->get_hp(), true );
critter->death_drops = false;
critter->die( z );
return true;
}

bool mattack::doot( monster *z )
{
z->moves -= 300;
Expand Down
1 change: 1 addition & 0 deletions src/monattack.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ bool kamikaze( monster *z );
bool grenadier( monster *z );
bool grenadier_elite( monster *z );
bool doot( monster *z );
bool zombie_fuse( monster *z );

void taze( monster *z, Creature *target );
void rifle( monster *z, Creature *target ); // Automated M4
Expand Down
62 changes: 59 additions & 3 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ monster::monster()
upgrade_time = -1;
last_updated = 0;
biosig_timer = -1;

monster::reset_bonuses();
}

monster::monster( const mtype_id &id ) : monster()
Expand Down Expand Up @@ -620,6 +622,10 @@ int monster::print_info( const catacurses::window &w, int vStart, int vLines, in
mvwprintz( w, point( column, vStart++ ), c_white, _( "Rider: %s" ), mounted_player->disp_name() );
}

if( effect_cache[MODIFIED] ) {
wprintz( w, c_light_gray, _( " It is %s." ), size_names.at( get_size() ) );
}

std::vector<std::string> lines = foldstring( type->get_description(), getmaxx( w ) - 1 - column );
int numlines = lines.size();
for( int i = 0; i < numlines && vStart <= vEnd; i++ ) {
Expand Down Expand Up @@ -1685,6 +1691,29 @@ void monster::add_effect( const efftype_id &eff_id, const time_duration dur, bod
{
// Effects are not applied to specific monster body part
Creature::add_effect( eff_id, dur, num_bp, permanent, intensity, force, deferred );

effect_cache[MODIFIED] = effect_cache[MODIFIED] | effect_is_modifier_enabled( get_effect(
eff_id ) );
}

bool monster::remove_effect( const efftype_id &eff_id, body_part bp )
{
bool modif = effect_is_modifier_enabled( get_effect( eff_id ) );
bool rtrn = Creature::remove_effect( eff_id, bp );

if( modif && effect_cache[MODIFIED] ) {
modif = false;
for( const auto &ef : *effects ) {
modif |= effect_is_modifier_enabled( ef.second.at( num_bp ) );
}
effect_cache[MODIFIED] = modif;
}
return rtrn;
}

bool monster::effect_is_modifier_enabled( const effect &eff )
{
return eff.get_mod( "GROWTH" ) != 0;
}

std::string monster::get_effect_status() const
Expand Down Expand Up @@ -2242,6 +2271,17 @@ bool monster::check_mech_powered() const
return true;
}

int monster::get_effect_bonus( std::string arg, bool reduced ) const
{
int rtrn = 0;
for( const auto effbody : *effects ) {
for( const auto ef : effbody.second ) {
rtrn += ef.second.get_mod( arg, reduced );
}
}
return rtrn;
}

void monster::drop_items_on_death()
{
if( is_hallucination() ) {
Expand Down Expand Up @@ -2293,6 +2333,10 @@ void monster::process_one_effect( effect &it, bool is_new )
};

mod_speed_bonus( get_effect( "SPEED", reduced ) );
mod_dodge_bonus( get_effect( "DODGE", reduced ) );
mod_hit_bonus( get_effect( "HIT", reduced ) );
mod_bash_bonus( get_effect( "BASH", reduced ) );
mod_cut_bonus( get_effect( "CUT", reduced ) );

int val = get_effect( "HURT", reduced );
if( val > 0 ) {
Expand Down Expand Up @@ -2528,17 +2572,29 @@ field_type_id monster::gibType() const

m_size monster::get_size() const
{
return type->size;
if( effect_cache[MODIFIED] ) {
return m_size( type->size + get_effect_bonus( "GROWTH" ) );
} else {
return type->size;
}
}

units::mass monster::get_weight() const
{
return type->weight;
if( effect_cache[MODIFIED] ) {
return units::operator*( type->weight, get_size() / type->size );
} else {
return type->weight;
}
}

units::volume monster::get_volume() const
{
return type->volume;
if( effect_cache[MODIFIED] ) {
return units::operator*( type->volume, get_size() / type->size );
} else {
return type->volume;
}
}

void monster::add_msg_if_npc( const std::string &msg ) const
Expand Down
10 changes: 9 additions & 1 deletion src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ enum monster_effect_cache_fields {
MOVEMENT_IMPAIRED = 0,
FLEEING,
VISION_IMPAIRED,
MODIFIED, // Uses data hold by effects instead of itself.
NUM_MEFF
};

Expand Down Expand Up @@ -320,6 +321,10 @@ class monster : public Creature
void add_effect( const efftype_id &eff_id, time_duration dur, body_part bp = num_bp,
bool permanent = false,
int intensity = 0, bool force = false, bool deferred = false ) override;
/** Same for removing effects.*/
bool remove_effect( const efftype_id &eff_id, body_part bp = num_bp ) override;
/** Returns true for an effect, whoose funcionality is enabled through effect_cache[MODIFIED] to reduce overhead.*/
bool effect_is_modifier_enabled( const effect &eff );
/** Returns a std::string containing effects for descriptions */
std::string get_effect_status() const;

Expand Down Expand Up @@ -378,7 +383,7 @@ class monster : public Creature
/** Resets stats, and applies effects in an idempotent manner */
void reset_stats() override;

void die( Creature *killer ) override; //this is the die from Creature, it calls kill_mon
void die( Creature *killer ) override;
void drop_items_on_death();

// Other
Expand All @@ -396,6 +401,9 @@ class monster : public Creature
bool use_mech_power( int amt );
bool check_mech_powered() const;
int mech_str_addition() const;
// get an value from the effect data.
int get_effect_bonus( std::string arg, bool reduced = false ) const;

/**
* Makes monster react to heard sound
*
Expand Down
1 change: 1 addition & 0 deletions src/monstergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ void MonsterGenerator::init_attack()
add_hardcoded_attack( "GRAB", mattack::grab );
add_hardcoded_attack( "GRAB_DRAG", mattack::grab_drag );
add_hardcoded_attack( "DOOT", mattack::doot );
add_hardcoded_attack( "ZOMBIE_FUSE", mattack::zombie_fuse );
}

void MonsterGenerator::init_defense()
Expand Down

0 comments on commit 46ae118

Please sign in to comment.