bool Creature::is_immune( const std::string &type ) const { damage_type dt = dt_by_name( type ); if( dt != DT_NULL ) { return is_immune_damage( dt ); } return is_immune_effect( type ); }
void Creature::deal_melee_hit( Creature *source, int hit_spread, bool critical_hit, const damage_instance &dam, dealt_damage_instance &dealt_dam ) { damage_instance d = dam; // copy, since we will mutate in block_hit body_part bp_hit = select_body_part(source, hit_spread); block_hit(source, bp_hit, d); // Bashing critical if( critical_hit && !is_immune_effect( effect_stunned ) ) { if( d.type_damage(DT_BASH) * hit_spread > get_hp_max() ) { add_effect( effect_stunned, 1_turns ); // 1 turn is enough } } // Stabbing effects int stab_moves = rng( d.type_damage(DT_STAB) / 2, d.type_damage(DT_STAB) * 1.5 ); if (critical_hit) { stab_moves *= 1.5; } if( stab_moves >= 150 && !is_immune_effect( effect_downed ) ) { if( is_player() ) { source->add_msg_if_npc( m_bad, _("<npcname> forces you to the ground!")); } else { source->add_msg_player_or_npc( m_good, _("You force %s to the ground!"), _("<npcname> forces %s to the ground!"), disp_name().c_str() ); } add_effect( effect_downed, 1_turns ); mod_moves(-stab_moves / 2); } else { mod_moves(-stab_moves); } on_hit( source, bp_hit ); // trigger on-gethit events dealt_dam = deal_damage(source, bp_hit, d); dealt_dam.bp_hit = bp_hit; }
bool Creature::add_env_effect( const efftype_id &eff_id, body_part vector, int strength, const time_duration dur, body_part bp, bool permanent, int intensity, bool force ) { if( !force && is_immune_effect( eff_id ) ) { return false; } if (dice(strength, 3) > dice(get_env_resist(vector), 3)) { // Only add the effect if we fail the resist roll // Don't check immunity (force == true), because we did check above add_effect( eff_id, dur, bp, permanent, intensity, true ); return true; } else { return false; } }
void Creature::add_effect( const efftype_id &eff_id, const time_duration dur, body_part bp, bool permanent, int intensity, bool force, bool deferred ) { // Check our innate immunity if( !force && is_immune_effect( eff_id ) ) { return; } if( !eff_id.is_valid() ) { debugmsg( "Invalid effect, ID: %s", eff_id.c_str() ); return; } const effect_type &type = eff_id.obj(); // Mutate to a main (HP'd) body_part if necessary. if (type.get_main_parts()) { bp = mutate_to_main_part(bp); } bool found = false; // Check if we already have it auto matching_map = effects->find(eff_id); if (matching_map != effects->end()) { auto &bodyparts = matching_map->second; auto found_effect = bodyparts.find(bp); if (found_effect != bodyparts.end()) { found = true; effect &e = found_effect->second; const int prev_int = e.get_intensity(); // If we do, mod the duration, factoring in the mod value e.mod_duration( dur * e.get_dur_add_perc() / 100); // Limit to max duration if( e.get_max_duration() > 0_turns && e.get_duration() > e.get_max_duration() ) { e.set_duration( e.get_max_duration() ); } // Adding a permanent effect makes it permanent if( e.is_permanent() ) { e.pause_effect(); } // int_dur_factor overrides all other intensity settings // ...but it's handled in set_duration, so explicitly do nothing here if( e.get_int_dur_factor() > 0_turns ) { // Set intensity if value is given } else if (intensity > 0) { e.set_intensity(intensity); // Else intensity uses the type'd step size if it already exists } else if (e.get_int_add_val() != 0) { e.mod_intensity(e.get_int_add_val()); } // Bound intensity by [1, max intensity] if (e.get_intensity() < 1) { add_msg( m_debug, "Bad intensity, ID: %s", e.get_id().c_str() ); e.set_intensity(1); } else if (e.get_intensity() > e.get_max_intensity()) { e.set_intensity(e.get_max_intensity()); } if( e.get_intensity() != prev_int ) { on_effect_int_change( eff_id, e.get_intensity(), bp ); } } } if( !found ) { // If we don't already have it then add a new one // Then check if the effect is blocked by another for( auto &elem : *effects ) { for( auto &_effect_it : elem.second ) { for( const auto& blocked_effect : _effect_it.second.get_blocks_effects() ) { if (blocked_effect == eff_id) { // The effect is blocked by another, return return; } } } } // Now we can make the new effect for application effect e( &type, dur, bp, permanent, intensity, calendar::turn ); // Bound to max duration if( e.get_max_duration() > 0_turns && e.get_duration() > e.get_max_duration() ) { e.set_duration( e.get_max_duration() ); } // Force intensity if it is duration based if( e.get_int_dur_factor() != 0_turns ) { // + 1 here so that the lowest is intensity 1, not 0 e.set_intensity( e.get_duration() / e.get_int_dur_factor() + 1 ); } // Bound new effect intensity by [1, max intensity] if (e.get_intensity() < 1) { add_msg( m_debug, "Bad intensity, ID: %s", e.get_id().c_str() ); e.set_intensity(1); } else if (e.get_intensity() > e.get_max_intensity()) { e.set_intensity(e.get_max_intensity()); } ( *effects )[eff_id][bp] = e; if (is_player()) { // Only print the message if we didn't already have it if( !type.get_apply_message().empty() ) { add_msg(type.gain_game_message_type(), _(type.get_apply_message().c_str())); } add_memorial_log(pgettext("memorial_male", type.get_apply_memorial_log().c_str()), pgettext("memorial_female", type.get_apply_memorial_log().c_str())); } on_effect_int_change( eff_id, e.get_intensity(), bp ); // Perform any effect addition effects. // only when not deferred if( !deferred ) { process_one_effect( e, true ); } } }
void Creature::add_effect( efftype_id eff_id, int dur, body_part bp, bool permanent, int intensity, bool force ) { // Check our innate immunity if( !force && is_immune_effect( eff_id ) ) { return; } // Mutate to a main (HP'd) body_part if necessary. if (effect_types[eff_id].get_main_parts()) { bp = mutate_to_main_part(bp); } bool found = false; // Check if we already have it auto matching_map = effects.find(eff_id); if (matching_map != effects.end()) { auto found_effect = effects[eff_id].find(bp); if (found_effect != effects[eff_id].end()) { found = true; effect &e = found_effect->second; // If we do, mod the duration, factoring in the mod value e.mod_duration(dur * e.get_dur_add_perc() / 100); // Limit to max duration if (e.get_max_duration() > 0 && e.get_duration() > e.get_max_duration()) { e.set_duration(e.get_max_duration()); } // Adding a permanent effect makes it permanent if( e.is_permanent() ) { e.pause_effect(); } // Set intensity if value is given if (intensity > 0) { e.set_intensity(intensity); // Else intensity uses the type'd step size if it already exists } else if (e.get_int_add_val() != 0) { e.mod_intensity(e.get_int_add_val()); } // Bound intensity by [1, max intensity] if (e.get_intensity() < 1) { add_msg( m_debug, "Bad intensity, ID: %s", e.get_id().c_str() ); e.set_intensity(1); } else if (e.get_intensity() > e.get_max_intensity()) { e.set_intensity(e.get_max_intensity()); } } } if( found == false ) { // If we don't already have it then add a new one // First make sure it's a valid effect if (effect_types.find(eff_id) == effect_types.end()) { return; } // Then check if the effect is blocked by another for( auto &elem : effects ) { for( auto &_effect_it : elem.second ) { for( const auto blocked_effect : _effect_it.second.get_blocks_effects() ) { if (blocked_effect == eff_id) { // The effect is blocked by another, return return; } } } } // Now we can make the new effect for application effect new_eff(&effect_types[eff_id], dur, bp, permanent, intensity); effect &e = new_eff; // Bound to max duration if (e.get_max_duration() > 0 && e.get_duration() > e.get_max_duration()) { e.set_duration(e.get_max_duration()); } // Bound new effect intensity by [1, max intensity] if (new_eff.get_intensity() < 1) { add_msg( m_debug, "Bad intensity, ID: %s", new_eff.get_id().c_str() ); new_eff.set_intensity(1); } else if (new_eff.get_intensity() > new_eff.get_max_intensity()) { new_eff.set_intensity(new_eff.get_max_intensity()); } effects[eff_id][bp] = new_eff; if (is_player()) { // Only print the message if we didn't already have it if(effect_types[eff_id].get_apply_message() != "") { add_msg(effect_types[eff_id].gain_game_message_type(), _(effect_types[eff_id].get_apply_message().c_str())); } add_memorial_log(pgettext("memorial_male", effect_types[eff_id].get_apply_memorial_log().c_str()), pgettext("memorial_female", effect_types[eff_id].get_apply_memorial_log().c_str())); } // Perform any effect addition effects. bool reduced = has_effect(e.get_resist_effect()) || has_trait(e.get_resist_trait()); add_eff_effects(e, reduced); } }