示例#1
0
void shoot_monster(player &p, monster &mon, int &dam, double goodhit,
                   item* weapon, const std::set<std::string> &effects)
{
// Gunmods don't have a type, so use the player weapon type.
    it_gun* firing = dynamic_cast<it_gun*>(p.weapon.type);
    std::string message;
    bool u_see_mon = g->u_see(&(mon));
    int adjusted_damage = dam;
    if (mon.has_flag(MF_HARDTOSHOOT) && !one_in(10 - 10 * (.8 - goodhit)) && // Maxes out at 50% chance with perfect hit
    weapon->curammo->phase != LIQUID && !effects.count("SHOT") && !effects.count("BOUNCE")) {
        if (u_see_mon)
            g->add_msg(_("The shot passes through the %s without hitting."),
            mon.name().c_str());
    } else { // Not HARDTOSHOOT
        // Bounce applies whether it does damage or not.
        if (effects.count("BOUNCE")) {
            mon.add_effect("bounced", 1);
        }
        // Armor blocks BEFORE any critical effects.
        int zarm = mon.get_armor_cut(bp_torso);
        zarm -= weapon->gun_pierce();
        if (weapon->curammo->phase == LIQUID)
            zarm = 0;
        else if (effects.count("SHOT")) // Shot doesn't penetrate armor well
            zarm *= rng(2, 3);
        if (zarm > 0)
            adjusted_damage -= zarm;
        if (adjusted_damage <= 0) {
            if (u_see_mon)
                g->add_msg(_("The shot reflects off the %s!"),
                mon.name_with_armor().c_str());
            adjusted_damage = 0;
            goodhit = 1;
        }
        if (goodhit <= .1 && !mon.has_flag(MF_NOHEAD)) {
            message = _("Headshot!");
            adjusted_damage = rng(5 * adjusted_damage, 8 * adjusted_damage);
            p.practice(g->turn, firing->skill_used, 5);
            p.lifetime_stats()->headshots++;
        } else if (goodhit <= .2) {
            message = _("Critical!");
            adjusted_damage = rng(adjusted_damage * 2, adjusted_damage * 3);
            p.practice(g->turn, firing->skill_used, 3);
        } else if (goodhit <= .4) {
            message = _("Good hit!");
            adjusted_damage = rng(adjusted_damage , adjusted_damage * 2);
            p.practice(g->turn, firing->skill_used, 2);
        } else if (goodhit <= .6) {
            adjusted_damage = rng(adjusted_damage / 2, adjusted_damage);
            p.practice(g->turn, firing->skill_used, 1);
        } else if (goodhit <= .8) {
            message = _("Grazing hit.");
            adjusted_damage = rng(0, adjusted_damage);
        } else {
            adjusted_damage = 0;
        }

        if(item(weapon->curammo, 0).has_flag("NOGIB"))
        {
            adjusted_damage = std::min(adjusted_damage, mon.hp+10);
        }

// Find the zombie at (x, y) and hurt them, MAYBE kill them!
        if (adjusted_damage > 0) {
            switch (mon.type->size) {
            case MS_TINY:
                mon.moves -= rng(0, adjusted_damage * 5);
                break;
            case MS_SMALL:
                mon.moves -= rng(0, adjusted_damage * 3);
                break;
            case MS_MEDIUM:
                mon.moves -= rng(0, adjusted_damage);
                break;
            case MS_LARGE:
                mon.moves -= rng(0, adjusted_damage / 3);
                break;
            case MS_HUGE:
                mon.moves -= rng(0, adjusted_damage / 5);
                break;
            }

            if (&p == &(g->u) && u_see_mon) {
                g->add_msg(_("%s You hit the %s for %d damage."), message.c_str(), mon.name().c_str(), adjusted_damage);
            } else if (u_see_mon) {
                g->add_msg(_("%s %s shoots the %s."), message.c_str(), p.name.c_str(), mon.name().c_str());
            }
            g->hit_monster_with_flags(mon, effects);
            damage_instance d;
            d.add_damage(DT_CUT, adjusted_damage, weapon->gun_pierce(),
                    effects.count("SHOT")?rng(2,3):1); // Shot doesn't penetrate armor well
            mon.deal_damage(&p, bp_torso, -1, d);
            if( u_see_mon ) {
                g->draw_hit_mon(mon.posx(), mon.posy(), mon, mon.is_dead_state());
            }
        }
    }
    dam = adjusted_damage;
}