bool Creature::remove_effect( const efftype_id &eff_id, body_part bp ) { if (!has_effect(eff_id, bp)) { //Effect doesn't exist, so do nothing return false; } const effect_type &type = eff_id.obj(); if (is_player()) { // Print the removal message and add the memorial log if needed if(type.get_remove_message() != "") { add_msg(type.lose_game_message_type(), _(type.get_remove_message().c_str())); } add_memorial_log(pgettext("memorial_male", type.get_remove_memorial_log().c_str()), pgettext("memorial_female", type.get_remove_memorial_log().c_str())); } // num_bp means remove all of a given effect id if (bp == num_bp) { effects.erase(eff_id); } else { effects[eff_id].erase(bp); // If there are no more effects of a given type remove the type map if (effects[eff_id].empty()) { effects.erase(eff_id); } } return true; }
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 ); } } }