Пример #1
0
int monster::bash_at(int x, int y) {
    //Hallucinations can't bash stuff.
    if(is_hallucination()) {
      return 0;
    }
    bool try_bash = !can_move_to(g, x, y) || one_in(3);
    bool can_bash = g->m.has_flag("BASHABLE", x, y) && has_flag(MF_BASHES);
    if(try_bash && can_bash) {
        std::string bashsound = "NOBASH"; // If we hear "NOBASH" it's time to debug!
        int bashskill = int(type->melee_dice * type->melee_sides);

        // pileup = more bashskill, but only help bashing mob directly infront of target
        const int max_helper_depth = 5;
        const std::vector<point> bzone = get_bashing_zone( point(x, y), pos(), max_helper_depth );
        int diffx = pos().x - x;
        int diffy = pos().y - y;
        int mo_bash = 0;
        for( int i = 0; i < bzone.size(); i++ ) {
           if ( g->mon_at( bzone[i] ) != -1 ) {
              monster & helpermon = g->zombie( g->mon_at( bzone[i] ) );
              // trying for the same door and can bash; put on helper hat
              if ( helpermon.wandx == wandx && helpermon.wandy == wandy && helpermon.has_flag(MF_BASHES) ) {
                 // helpers lined up behind primary basher add full strength, so do those at either shoulder, others add 50%
                 //addbash *= ( bzone[i].x == pos().x || bzone[i].y == pos().y ? 2 : 1 );
                 int addbash = int(helpermon.type->melee_dice * helpermon.type->melee_sides); 
                 // helpers lined up behind primary basher add full strength, others 50%
                 addbash *= ( ( diffx == 0 && bzone[i].x == pos().x ) || ( diffy == 0 && bzone[i].y == pos().y ) ) ? 2 : 1;
                 mo_bash += addbash;
                 // g->add_msg("+ bashhelp: %d,%d : +%d = %d", bzone[i].x, bzone[i].y, addbash/2, mo_bash/2 );
              }
           }
        }
        // by our powers combined...
        bashskill += int (mo_bash / 2);

        g->m.bash(x, y, bashskill, bashsound);
        g->sound(x, y, 18, bashsound);
        moves -= 100;
        return 1;
    } else if (g->m.move_cost(x, y) == 0 &&
            !g->m.is_divable(x, y) && //No smashing water into rubble!
            has_flag(MF_DESTROYS)) {
        g->m.destroy(g, x, y, true); //todo: add bash info without BASHABLE flag to walls etc, balanced to these guys
        moves -= 250;
        return 1;
    }
    return 0;
}
Пример #2
0
int monster::bash_at(int x, int y) {

    if (has_effect("pacified")) return 0;

    //Hallucinations can't bash stuff.
    if(is_hallucination()) {
        return 0;
    }
    bool try_bash = !can_move_to(x, y) || one_in(3);
    bool can_bash = g->m.is_bashable(x, y) && has_flag(MF_BASHES);
    if(try_bash && can_bash) {
        int bashskill = bash_skill();

        // pileup = more bashskill, but only help bashing mob directly infront of target
        const int max_helper_depth = 5;
        const std::vector<point> bzone = get_bashing_zone( point(x, y), pos(), max_helper_depth );
        int diffx = pos().x - x;
        int diffy = pos().y - y;
        int mo_bash = 0;
        for( size_t i = 0; i < bzone.size(); ++i ) {
            if ( g->mon_at( bzone[i] ) != -1 ) {
                monster & helpermon = g->zombie( g->mon_at( bzone[i] ) );
                // trying for the same door and can bash; put on helper hat
                if ( helpermon.wandx == wandx && helpermon.wandy == wandy &&
                     helpermon.has_flag(MF_BASHES) ) {
                    // helpers lined up behind primary basher add full strength,
                    // so do those at either shoulder, others add 50%
                    int addbash = int(helpermon.type->melee_dice * helpermon.type->melee_sides);
                    if (helpermon.has_flag(MF_DESTROYS)) {
                        addbash *= 2.5;
                    }
                    // helpers lined up behind primary basher add full strength, others 50%
                    addbash *= ( ( diffx == 0 && bzone[i].x == pos().x ) ||
                                 ( diffy == 0 && bzone[i].y == pos().y ) ) ? 2 : 1;
                    mo_bash += addbash;
                }
            }
        }
        // by our powers combined...
        bashskill += int (mo_bash / 2);

        g->m.bash( x, y, bashskill );
        moves -= 100;
        return 1;
    }
    return 0;
}
Пример #3
0
int monster::group_bash_skill( point target )
{
    if( !has_flag(MF_GROUP_BASH) ) {
        return bash_skill();
    }
    int bashskill = 0;

    // pileup = more bashskill, but only help bashing mob directly infront of target
    const int max_helper_depth = 5;
    const std::vector<point> bzone = get_bashing_zone( target, pos(), max_helper_depth );

    for( point candidate : bzone ) {
        // Drawing this line backwards excludes the target and includes the candidate.
        std::vector<point> path_to_target = line_to( target.x, target.y,
                                                     candidate.x, candidate.y, 0);
        bool connected = true;
        int mondex = -1;
        for( point in_path : path_to_target ) {
            // If any point in the line from zombie to target is not a cooperating zombie,
            // it can't contribute.
            mondex = g->mon_at( in_path );
            if( mondex == -1 ) {
                connected = false;
                break;
            }
            monster &helpermon = g->zombie( mondex );
            if( !helpermon.has_flag(MF_GROUP_BASH) ) {
                connected = false;
                break;
            }
        }
        if( !connected ) {
            continue;
        }
        // If we made it here, the last monster checked was the candidate.
        monster &helpermon = g->zombie( mondex );
        // Contribution falls off rapidly with distance from target.
        bashskill += helpermon.bash_skill() / rl_dist( candidate, target );
    }

    return bashskill;
}
Пример #4
0
int monster::group_bash_skill( const tripoint &target )
{
    if( !has_flag( MF_GROUP_BASH ) ) {
        return bash_skill();
    }
    int bashskill = 0;

    // pileup = more bash skill, but only help bashing mob directly in front of target
    const int max_helper_depth = 5;
    const std::vector<tripoint> bzone = get_bashing_zone( target, pos(), max_helper_depth );

    for( const tripoint &candidate : bzone ) {
        // Drawing this line backwards excludes the target and includes the candidate.
        std::vector<tripoint> path_to_target = line_to( target, candidate, 0, 0 );
        bool connected = true;
        monster *mon = nullptr;
        for( const tripoint &in_path : path_to_target ) {
            // If any point in the line from zombie to target is not a cooperating zombie,
            // it can't contribute.
            mon = g->critter_at<monster>( in_path );
            if( !mon ) {
                connected = false;
                break;
            }
            monster &helpermon = *mon;
            if( !helpermon.has_flag( MF_GROUP_BASH ) || helpermon.is_hallucination() ) {
                connected = false;
                break;
            }
        }
        if( !connected || !mon ) {
            continue;
        }
        // If we made it here, the last monster checked was the candidate.
        monster &helpermon = *mon;
        // Contribution falls off rapidly with distance from target.
        bashskill += helpermon.bash_skill() / rl_dist( candidate, target );
    }

    return bashskill;
}