Exemple #1
0
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 );
        }
    }
}
Exemple #5
0
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);
    }
}