コード例 #1
0
bool gun_actor::call( monster &z ) const
{
    Creature *target;
    if( z.friendly != 0 ) {
        // Attacking monsters, not the player!
        int boo_hoo;
        target = z.auto_find_hostile_target( range, boo_hoo );
        if( target == nullptr ) {
            // Couldn't find any targets!
            if( boo_hoo > 0 && g->u.sees( z ) ) {
                // because that stupid oaf was in the way!
                add_msg( m_warning, ngettext( "Pointed in your direction, the %s emits an IFF warning beep.",
                                              "Pointed in your direction, the %s emits %d annoyed sounding beeps.",
                                              boo_hoo ),
                         z.name().c_str(), boo_hoo );
            }
            return false;
        }

        shoot( z, *target );
        return true;
    }

    // Not friendly; hence, firing at the player too
    target = z.attack_target();
    if( target == nullptr || rl_dist( z.pos(), target->pos() ) > range ||
        !z.sees( *target ) ) {
        return false;
    }

    shoot( z, *target );
    return true;
}
コード例 #2
0
bool gun_actor::call( monster &z ) const
{
    Creature *target;

    if( z.friendly ) {
        int max_range = 0;
        for( const auto &e : ranges ) {
            max_range = std::max( std::max( max_range, e.first.first ), e.first.second );
        }

        int hostiles; // hostiles which cannot be engaged without risking friendly fire
        target = z.auto_find_hostile_target( max_range, hostiles );
        if( !target ) {
            if( hostiles > 0 && g->u.sees( z ) ) {
                add_msg( m_warning, ngettext( "Pointed in your direction, the %s emits an IFF warning beep.",
                                              "Pointed in your direction, the %s emits %d annoyed sounding beeps.",
                                              hostiles ),
                         z.name(), hostiles );
            }
            return false;
        }

    } else {
        target = z.attack_target();
        if( !target || !z.sees( *target ) ) {
            return false;
        }
    }

    int dist = rl_dist( z.pos(), target->pos() );
    for( const auto &e : ranges ) {
        if( dist >= e.first.first && dist <= e.first.second ) {
            shoot( z, *target, e.second );
            return true;
        }
    }
    return false;
}
コード例 #3
0
bool leap_actor::call( monster &z ) const
{
    if( !z.can_act() ) {
        return false;
    }

    std::vector<tripoint> options;
    tripoint target = z.move_target();
    float best_float = trig_dist( z.pos(), target );
    if( best_float < min_consider_range || best_float > max_consider_range ) {
        return false;
    }

    // We wanted the float for range check
    // int here will make the jumps more random
    int best = ( int )best_float;
    if( !allow_no_target && z.attack_target() == nullptr ) {
        return false;
    }

    for( const tripoint &dest : g->m.points_in_radius( z.pos(), max_range ) ) {
        if( dest == z.pos() ) {
            continue;
        }
        if( !z.sees( dest ) ) {
            continue;
        }
        if( !g->is_empty( dest ) ) {
            continue;
        }
        int cur_dist = rl_dist( target, dest );
        if( cur_dist > best ) {
            continue;
        }
        if( trig_dist( z.pos(), dest ) < min_range ) {
            continue;
        }
        bool blocked_path = false;
        // check if monster has a clear path to the proposed point
        std::vector<tripoint> line = g->m.find_clear_path( z.pos(), dest );
        for( auto &i : line ) {
            if( g->m.impassable( i ) ) {
                blocked_path = true;
                break;
            }
        }
        if( blocked_path ) {
            continue;
        }

        if( cur_dist < best ) {
            // Better than any earlier one
            options.clear();
        }

        options.push_back( dest );
        best = cur_dist;
    }

    if( options.empty() ) {
        return false;    // Nowhere to leap!
    }

    z.moves -= move_cost;
    const tripoint chosen = random_entry( options );
    bool seen = g->u.sees( z ); // We can see them jump...
    z.setpos( chosen );
    seen |= g->u.sees( z ); // ... or we can see them land
    if( seen ) {
        add_msg( _( "The %s leaps!" ), z.name().c_str() );
    }

    return true;
}
コード例 #4
0
bool bite_actor::call( monster &z ) const
{
    if( !z.can_act() ) {
        return false;
    }

    Creature *target = z.attack_target();
    if( target == nullptr || !is_adjacent( z, *target ) ) {
        return false;
    }

    z.mod_moves( -move_cost );

    add_msg( m_debug, "%s attempting to bite %s", z.name().c_str(), target->disp_name().c_str() );

    int hitspread = target->deal_melee_attack( &z, z.hit_roll() );

    if( hitspread < 0 ) {
        auto msg_type = target == &g->u ? m_warning : m_info;
        sfx::play_variant_sound( "mon_bite", "bite_miss", sfx::get_heard_volume( z.pos() ),
                                 sfx::get_heard_angle( z.pos() ) );
        target->add_msg_player_or_npc( msg_type, _( "The %s lunges at you, but you dodge!" ),
                                       _( "The %s lunges at <npcname>, but they dodge!" ),
                                       z.name().c_str() );
        return true;
    }

    damage_instance damage = damage_max_instance;
    dealt_damage_instance dealt_damage;
    body_part hit;

    double multiplier = rng_float( min_mul, max_mul );
    damage.mult_damage( multiplier );

    target->deal_melee_hit( &z, hitspread, false, damage, dealt_damage );

    hit = dealt_damage.bp_hit;
    int damage_total = dealt_damage.total_damage();
    add_msg( m_debug, "%s's bite did %d damage", z.name().c_str(), damage_total );
    if( damage_total > 0 ) {
        auto msg_type = target == &g->u ? m_bad : m_info;
        //~ 1$s is monster name, 2$s bodypart in accusative
        if( target->is_player() ) {
            sfx::play_variant_sound( "mon_bite", "bite_hit", sfx::get_heard_volume( z.pos() ),
                                     sfx::get_heard_angle( z.pos() ) );
            sfx::do_player_death_hurt( *dynamic_cast<player *>( target ), 0 );
        }
        target->add_msg_player_or_npc( msg_type,
                                       _( "The %1$s bites your %2$s!" ),
                                       _( "The %1$s bites <npcname>'s %2$s!" ),
                                       z.name().c_str(),
                                       body_part_name_accusative( hit ).c_str() );
        if( one_in( no_infection_chance - damage_total ) ) {
            if( target->has_effect( effect_bite, hit ) ) {
                target->add_effect( effect_bite, 400, hit, true );
            } else if( target->has_effect( effect_infected, hit ) ) {
                target->add_effect( effect_infected, 250, hit, true );
            } else {
                target->add_effect( effect_bite, 1, hit, true );
            }
        }
    } else {
        sfx::play_variant_sound( "mon_bite", "bite_miss", sfx::get_heard_volume( z.pos() ),
                                 sfx::get_heard_angle( z.pos() ) );
        target->add_msg_player_or_npc( _( "The %1$s bites your %2$s, but fails to penetrate armor!" ),
                                       _( "The %1$s bites <npcname>'s %2$s, but fails to penetrate armor!" ),
                                       z.name().c_str(),
                                       body_part_name_accusative( hit ).c_str() );
    }

    return true;
}