Пример #1
0
void ANI::print_attack_speed()
{
	for (int race = 0; race < MAIN_RACE_MAX_NUM; ++race)
	{
		for (int weapon = 0; weapon < WEAPON_NUM_TYPES; ++weapon)
		{
			printf("[%s][%s] = %u\n",
					FN_race_string(race),
					FN_weapon_string(weapon),
					attack_speed(race, weapon));
		}
		printf("\n");
	}
}
Пример #2
0
void player::hit_player(game *g, player &p, bool allow_grab)
{
 bool is_u = (this == &(g->u));	// Affects how we'll display messages

 if (is_u && p.is_npc()) {
  npc* npcPtr = dynamic_cast<npc*>(&p);
  npcPtr->make_angry();
 }

 std::string You  = (is_u ? "You"  : name);
 std::string Your = (is_u ? "Your" : name + "'s");
 std::string your = (is_u ? "your" : (male ? "his" : "her"));
 std::string verb = "hit";

// Divide their dodge roll by 2 if this is a grab
 int target_dodge = (allow_grab ? p.dodge_roll(g) : p.dodge_roll(g) / 2);
 int hit_value = hit_roll() - target_dodge;
 bool missed = (hit_roll() <= 0);

 int move_cost = attack_speed(*this, missed);

 if (missed) {
  int stumble_pen = stumble(*this);
  if (is_u) {	// Only display messages if this is the player
   if (weapon.has_technique(TEC_FEINT, this))
    g->add_msg("You feint.");
   else if (stumble_pen >= 60)
    g->add_msg("You miss and stumble with the momentum.");
   else if (stumble_pen >= 10)
    g->add_msg("You swing wildly and miss.");
   else
    g->add_msg("You miss.");
  }
  melee_practice(*this, false, unarmed_attack(),
                 weapon.is_bashing_weapon(), weapon.is_cutting_weapon(),
                 (weapon.has_flag(IF_SPEAR) || weapon.has_flag(IF_STAB)));
  move_cost += stumble_pen;
  if (weapon.has_technique(TEC_FEINT, this))
   move_cost = rng(move_cost / 3, move_cost);
  moves -= move_cost;
  return;
 }
 moves -= move_cost;

 body_part bp_hit;
 int side = rng(0, 1);
 hit_value += rng(-10, 10);
 if (hit_value >= 30)
  bp_hit = bp_eyes;
 else if (hit_value >= 20)
  bp_hit = bp_head;
 else if (hit_value >= 10)
  bp_hit = bp_torso;
 else if (one_in(4))
  bp_hit = bp_legs;
 else
  bp_hit = bp_arms;

 std::string target = (p.is_npc() ? p.name + "'s " : "your ");
 target += body_part_name(bp_hit, side);

 bool critical_hit = scored_crit(target_dodge);

 int bash_dam = roll_bash_damage(NULL, critical_hit);
 int cut_dam  = roll_cut_damage(NULL, critical_hit);
 int stab_dam = roll_stab_damage(NULL, critical_hit);

 technique_id tech_def = p.pick_defensive_technique(g, NULL, this);
 p.perform_defensive_technique(tech_def, g, NULL, this, bp_hit, side,
                               bash_dam, cut_dam, stab_dam);

 if (bash_dam + cut_dam + stab_dam <= 0)
  return; // Defensive technique canceled our attack!

 if (critical_hit) // Crits cancel out Toad Style's armor boost
  p.rem_disease(DI_ARMOR_BOOST);

 int pain = 0; // Boost to pain; required for perform_technique

// Moves lost to getting your weapon stuck
 int stuck_penalty = roll_stuck_penalty(NULL, (stab_dam >= cut_dam));
 if (weapon.is_style())
  stuck_penalty = 0;

// Pick one or more special attacks
 technique_id technique = pick_technique(g, NULL, &p, critical_hit, allow_grab);

// Handles effects as well; not done in melee_affect_*
 perform_technique(technique, g, NULL, &p, bash_dam, cut_dam, stab_dam, pain);
 p.pain += pain;

// Mutation-based attacks
 perform_special_attacks(g, NULL, &p, bash_dam, cut_dam, stab_dam);

// Handles speed penalties to monster & us, etc
 melee_special_effects(g, NULL, &p, critical_hit, bash_dam, cut_dam, stab_dam);

// Make a rather quiet sound, to alert any nearby monsters
 if (weapon.typeId() != "style_ninjutsu") // Ninjutsu is silent!
  g->sound(posx, posy, 8, "");

 p.hit(g, bp_hit, side, bash_dam, (cut_dam > stab_dam ? cut_dam : stab_dam));

 verb = melee_verb(technique, your, *this, bash_dam, cut_dam, stab_dam);
 int dam = bash_dam + (cut_dam > stab_dam ? cut_dam : stab_dam);
 hit_message(g, You.c_str(), verb.c_str(), target.c_str(), dam, critical_hit);

 bool bashing = (bash_dam >= 10 && !unarmed_attack());
 bool cutting = (cut_dam >= 10 && cut_dam >= stab_dam);
 bool stabbing = (stab_dam >= 10 && stab_dam >= cut_dam);
 melee_practice(*this, true, unarmed_attack(), bashing, cutting, stabbing);

 if (dam >= 5 && has_artifact_with(AEP_SAP_LIFE))
  healall( rng(dam / 10, dam / 5) );

 if (allow_grab && technique == TEC_GRAB) {
// Move our weapon to a temp slot, if it's not unarmed
  if (p.weapon.has_technique(TEC_BREAK, &p) &&
      dice(p.dex_cur + p.skillLevel("melee"), 12) >
      dice(dex_cur + skillLevel("melee"), 10)) {
   if (is_u)
    g->add_msg("%s break%s the grab!", target.c_str(), (p.is_npc() ? "s" : ""));
  } else if (!unarmed_attack()) {
   item tmpweap = remove_weapon();
   hit_player(g, p, false); // False means a second grab isn't allowed
   weapon = tmpweap;
  } else
   hit_player(g, p, false); // False means a second grab isn't allowed
 }
 if (tech_def == TEC_COUNTER) {
  if (!p.is_npc())
   g->add_msg("Counter-attack!");
  p.hit_player(g, *this);
 }
}
Пример #3
0
void player::perform_technique(technique_id technique, game *g, monster *z,
                               player *p, int &bash_dam, int &cut_dam,
                               int &stab_dam, int &pain)
{
 bool mon = (z != NULL);
 std::string You = (is_npc() ? name : "You");
 std::string target = (mon ? "the " + z->name() :
                       (p->is_npc() ? p->name : "you"));
 std::string s = (is_npc() ? "s" : "");
 int tarx = (mon ? z->posx : p->posx), tary = (mon ? z->posy : p->posy);

 int junk;
 bool u_see = (!is_npc() || g->u_see(posx, posy, junk));

 if (technique == TEC_RAPID) {
  moves += int( attack_speed(*this, false) / 2);
  return;
 }
 if (technique == TEC_BLOCK) {
  bash_dam *= .7;
  return;
 }
// The rest affect our target, and thus depend on z vs. p
 switch (technique) {

 case TEC_SWEEP:
  if (z != NULL && !z->has_flag(MF_FLIES)) {
   z->add_effect(ME_DOWNED, rng(1, 2));
   bash_dam += z->fall_damage();
  } else if (p != NULL && p->weapon.typeId() != "style_judo") {
   p->add_disease(DI_DOWNED, rng(1, 2), g);
   bash_dam += 3;
  }
  break;

 case TEC_PRECISE:
  if (z != NULL)
   z->add_effect(ME_STUNNED, rng(1, 4));
  else if (p != NULL)
   p->add_disease(DI_STUNNED, rng(1, 2), g);
  pain += rng(5, 8);
  break;

 case TEC_BRUTAL:
  if (z != NULL) {
   z->add_effect(ME_STUNNED, 1);
   z->knock_back_from(g, posx, posy);
  } else if (p != NULL) {
   p->add_disease(DI_STUNNED, 1, g);
   p->knock_back_from(g, posy, posy);
  }
  break;

 case TEC_THROW:
// Throws are less predictable than brutal strikes.
// We knock them back from a tile adjacent to us!
  if (z != NULL) {
   z->add_effect(ME_DOWNED, rng(1, 2));
   z->knock_back_from(g, posx + rng(-1, 1), posy + rng(-1, 1));
  } else if (p != NULL) {
   p->knock_back_from(g, posx + rng(-1, 1), posy + rng(-1, 1));
   if (p->weapon.typeId() != "style_judo")
    p->add_disease(DI_DOWNED, rng(1, 2), g);
  }
  break;

 case TEC_WIDE: {
  int count_hit = 0;
  for (int x = posx - 1; x <= posx + 1; x++) {
   for (int y = posy - 1; y <= posy + 1; y++) {
    if (x != tarx || y != tary) { // Don't double-hit our target
     int mondex = g->mon_at(x, y);
     if (mondex != -1 && hit_roll() >= rng(0, 5) + g->z[mondex].dodge_roll()) {
      count_hit++;
      int dam = roll_bash_damage(&(g->z[mondex]), false) +
                roll_cut_damage (&(g->z[mondex]), false);
      g->z[mondex].hurt(dam);
      if (u_see)
       g->add_msg("%s hit%s %s for %d damage!", You.c_str(), s.c_str(),
                                                target.c_str(), dam);
     }
     int npcdex = g->npc_at(x, y);
     if (npcdex != -1 &&
         hit_roll() >= rng(0, 5) + g->active_npc[npcdex].dodge_roll(g)) {
      count_hit++;
      int dam = roll_bash_damage(NULL, false);
      int cut = roll_cut_damage (NULL, false);
      g->active_npc[npcdex].hit(g, bp_legs, 3, dam, cut);
      if (u_see)
       g->add_msg("%s hit%s %s for %d damage!", You.c_str(), s.c_str(),
                  g->active_npc[npcdex].name.c_str(), dam + cut);
     }
    }
   }
  }
  if (!is_npc())
   g->add_msg("%d enemies hit!", count_hit);
 } break;

 case TEC_DISARM:
  g->m.add_item(p->posx, p->posy, p->remove_weapon());
  if (u_see)
   g->add_msg("%s disarm%s %s!", You.c_str(), s.c_str(), target.c_str());
  break;

 } // switch (tech)
}
Пример #4
0
int player::hit_mon(game *g, monster *z, bool allow_grab) // defaults to true
{
 bool is_u = (this == &(g->u));	// Affects how we'll display messages
 if (is_u)
  z->add_effect(ME_HIT_BY_PLAYER, 100); // Flag as attacked by us

 std::string You  = (is_u ? "You"  : name);
 std::string Your = (is_u ? "Your" : name + "'s");
 std::string your = (is_u ? "your" : (male ? "his" : "her"));
 std::string verb = "hit";
 std::string target = "the " + z->name();

// If !allow_grab, then we already grabbed them--meaning their dodge is hampered
 int mondodge = (allow_grab ? z->dodge_roll() : z->dodge_roll() / 3);

 bool missed = (hit_roll() < mondodge ||
                one_in(4 + dex_cur + weapon.type->m_to_hit));

 int move_cost = attack_speed(*this, missed);

 if (missed) {
  int stumble_pen = stumble(*this);
  if (is_u) {	// Only display messages if this is the player
   if (weapon.has_technique(TEC_FEINT, this))
    g->add_msg("You feint.");
   else if (stumble_pen >= 60)
    g->add_msg("You miss and stumble with the momentum.");
   else if (stumble_pen >= 10)
    g->add_msg("You swing wildly and miss.");
   else
    g->add_msg("You miss.");
  }
  melee_practice(*this, false, unarmed_attack(),
                 weapon.is_bashing_weapon(), weapon.is_cutting_weapon(),
                 (weapon.has_flag(IF_SPEAR) || weapon.has_flag(IF_STAB)));
  move_cost += stumble_pen;
  if (weapon.has_technique(TEC_FEINT, this))
   move_cost = rng(move_cost / 3, move_cost);
  moves -= move_cost;
  return 0;
 }
 moves -= move_cost;

 bool critical_hit = scored_crit(mondodge);

 int bash_dam = roll_bash_damage(z, critical_hit);
 int cut_dam  = roll_cut_damage(z, critical_hit);
 int stab_dam = roll_stab_damage(z, critical_hit);

 int pain = 0; // Boost to pain; required for perform_technique

// Moves lost to getting your weapon stuck
 int stuck_penalty = roll_stuck_penalty(z, (stab_dam >= cut_dam));
 if (weapon.is_style())
  stuck_penalty = 0;

// Pick one or more special attacks
 technique_id technique = pick_technique(g, z, NULL, critical_hit, allow_grab);

// Handles effects as well; not done in melee_affect_*
 perform_technique(technique, g, z, NULL, bash_dam, cut_dam, stab_dam, pain);
 z->speed -= int(pain / 2);

// Mutation-based attacks
 perform_special_attacks(g, z, NULL, bash_dam, cut_dam, stab_dam);

// Handles speed penalties to monster & us, etc
 melee_special_effects(g, z, NULL, critical_hit, bash_dam, cut_dam, stab_dam);

// Make a rather quiet sound, to alert any nearby monsters
 if (weapon.typeId() != "style_ninjutsu") // Ninjutsu is silent!
  g->sound(posx, posy, 8, "");

 verb = melee_verb(technique, your, *this, bash_dam, cut_dam, stab_dam);

 int dam = bash_dam + (cut_dam > stab_dam ? cut_dam : stab_dam);

 hit_message(g, You.c_str(), verb.c_str(), target.c_str(), dam, critical_hit);

 bool bashing = (bash_dam >= 10 && !unarmed_attack());
 bool cutting = (cut_dam >= 10 && cut_dam >= stab_dam);
 bool stabbing = (stab_dam >= 10 && stab_dam >= cut_dam);
 melee_practice(*this, true, unarmed_attack(), bashing, cutting, stabbing);

 if (allow_grab && technique == TEC_GRAB) {
// Move our weapon to a temp slot, if it's not unarmed
  if (!unarmed_attack()) {
   item tmpweap = remove_weapon();
   dam += hit_mon(g, z, false); // False means a second grab isn't allowed
   weapon = tmpweap;
  } else
   dam += hit_mon(g, z, false); // False means a second grab isn't allowed
 }

 if (dam >= 5 && has_artifact_with(AEP_SAP_LIFE))
  healall( rng(dam / 10, dam / 5) );
 return dam;
}