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; }
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; }
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; }
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; }