/* * Check if an object is melee weapon and allows wielding with two-hands */ bool object_allow_two_hands_wielding(object_type *o_ptr) { if (object_is_melee_weapon(o_ptr) && ((o_ptr->weight > 99) || (o_ptr->tval == TV_POLEARM))) return TRUE; /* Hack: Shield Mastery technique */ if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH && object_is_shield(o_ptr)) return TRUE; return FALSE; }
void combat_attack(Character *who, Character *whom) { int dir; int tohit, damage, damage1, damage2, damage_reduced; int hits, hits2, luck1, luck2; int i; int item, weapon_skill; char *attack_type; int bonus; who->ap -= COMBAT_ATTACK_COST; if (abs(who->x - whom->x) > abs(who->y - whom->y)) { if (who->x > whom->x) dir = CHARACTER_LEFT; else dir = CHARACTER_RIGHT; } else { if (who->y > whom->y) dir = CHARACTER_UP; else dir = CHARACTER_DOWN; } character_attack(who, dir); tohit = 0; if (game_in_party(who)) damage = 4; /* bare hand */ else damage = 6; /* something better */ attack_type = "swings"; /* when unarmed, brawl is in effect */ weapon_skill = 0x40; bonus = 0; for (i = 0; i < who->items_num; ++i) if (who->item_used[i]) { item = who->items[i]; if (object_is_weapon(item)) { weapon_skill = object_weapon_skill(item); damage = object_weapon_damage(item); tohit += object_weapon_to_hit(item); if (object_weapon_class(item) == 8) /* bow */ attack_type = "fires"; /* Sting, Glamdring, Anduril, Durin's Axe, Magic Bow */ if (item == 0x60 || item == 0x63 || item == 0x62 || item == 0x67 || item == 0x65) bonus = 1; /* Spider Sword */ if (item == 0x64 && strcmp(whom->name, "Spider")) bonus = 1; /* Troll Slayer */ if (item == 0x66 && (strcmp(whom->name, "Troll") || strcmp(whom->name, "Olog-hai"))) bonus = 1; } /* armours have impairing effect */ if (object_is_armour(item)) tohit -= object_weapon_to_hit(item); } /* better chance to hit if we are skilled with our weapon */ for (i = 0; i < who->skills_num; ++i) if (weapon_skill == who->skills[i]) { tohit += 2; break; } damage_reduced = 0; for (i = 0; i < whom->items_num; ++i) if (whom->item_used[i]) { item = who->items[i]; /* armours have impairing effect */ if (object_is_armour(item)) { damage_reduced = object_armour_reduced(item); tohit += object_weapon_to_hit(item); } if (object_is_shield(item)) tohit -= object_shield_to_hit(item); } /* better chance to defend if we have dodge */ for (i = 0; i < whom->skills_num; ++i) if (whom->skills[i] == 0x46) { tohit -= 2; break; } hits = combat_if_hits(who->dex, whom->dex, tohit); hits2 = combat_if_hits(who->dex, whom->dex, tohit); luck1 = lotr_rnd(30 + who->luck); luck2 = lotr_rnd(30 + who->luck); if (luck1 > 2 * luck2) hits = max(hits, hits2); if (2 * luck1 < luck2) hits = min(hits, hits2); /* Balrog must be a deadly foe */ if (!strcmp(who->name, "Balrog")) { hits = 1; bonus = 1; } if (hits) { damage1 = lotr_rnd(who->str) / 10 + lotr_rnd(damage) + bonus * lotr_rnd(damage) - damage_reduced; damage2 = lotr_rnd(who->str) / 10 + lotr_rnd(damage) + bonus * lotr_rnd(damage) - damage_reduced; luck1 = lotr_rnd(30 + who->luck); luck2 = lotr_rnd(30 + who->luck); damage = damage1; if (luck1 > 2 * luck2) damage = max(damage1, damage2); if (2 * luck1 < luck2) damage = min(damage1, damage2); if (damage < 0) damage = 0; whom->life -= damage; if (whom->life < 0) whom->life = 0; } combat_who_attacked = whom; if (hits) { if (damage > 0) { if (whom->life == 0) { snprintf(combat_result_text, sizeof(combat_result_text), "%s kills %s.", who->name, whom->name); combat_character_remove(whom); } else { if (whom->life >= 6 || !game_in_party(whom)) { snprintf(combat_result_text, sizeof(combat_result_text), "%s hits %s for %d points of damage.", who->name, whom->name, damage); } else { snprintf(combat_result_text, sizeof(combat_result_text), "%s hits %s for %d points of damage, knocking %s out of cold.", who->name, whom->name, damage, whom->name); } } } else { snprintf(combat_result_text, sizeof(combat_result_text), "%s hits %s but does no damage.", who->name, whom->name); } } else { snprintf(combat_result_text, sizeof(combat_result_text), "%s %s at and misses %s.", who->name, attack_type, whom->name); } if (hits) sound_play(10); else sound_play(11); combat_attack_animation = 1; }
void display_weapon_info(doc_ptr doc, int hand) { object_type *o_ptr = equip_obj(p_ptr->weapon_info[hand].slot); char o_name[MAX_NLEN]; u32b flgs[TR_FLAG_SIZE]; int dd; int ds; int to_d = 0; int to_h = 0; int mult; critical_t crit = {0}; int crit_pct = 0; int num_blow = NUM_BLOWS(hand); bool force = FALSE; doc_ptr cols[2] = {0}; if (p_ptr->weapon_info[hand].wield_how == WIELD_NONE) return; if (!o_ptr) return; dd = o_ptr->dd + p_ptr->weapon_info[hand].to_dd; ds = o_ptr->ds + p_ptr->weapon_info[hand].to_ds; if (object_is_known(o_ptr)) { to_d = o_ptr->to_d; to_h = o_ptr->to_h; } switch (display_weapon_mode) { case MAULER_STUNNING_BLOW: case MAULER_CRITICAL_BLOW: case MAULER_CRUSHING_BLOW: case MAULER_KNOCKBACK: num_blow = 100; break; case MAULER_KNOCKOUT_BLOW: num_blow = 100; to_h -= 50; break; case PY_POWER_ATTACK: to_h += 10; to_d += p_ptr->lev / 2; break; } weapon_flags_known(hand, flgs); if ( (have_flag(flgs, TR_FORCE_WEAPON) || p_ptr->tim_force) && (p_ptr->csp > o_ptr->dd*o_ptr->ds/5) ) { force = TRUE; } if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH && object_is_shield(o_ptr)) { dd = 3 + p_ptr->weapon_info[hand].to_dd; ds = o_ptr->ac + p_ptr->weapon_info[hand].to_ds; if (object_is_known(o_ptr)) { to_h = o_ptr->to_a; to_d = o_ptr->to_a; to_h += 2*o_ptr->to_h; to_d += 2*o_ptr->to_d; } } mult = 100; if (have_flag(flgs, TR_VORPAL2)) mult = mult * 5 / 3; else if (have_flag(flgs, TR_VORPAL)) mult = mult * 11 / 9; mult += mult * p_ptr->weapon_info[hand].to_mult / 100; if (display_weapon_mode == MAULER_CRUSHING_BLOW) { int d = p_ptr->lev/5; int n = 10*(1 + d)/2; /* scale by 10 */ mult = mult * (50 + n)/30; } if (!have_flag(flgs, TR_ORDER)) { const int attempts = 10 * 1000; int i; int crits = 0; /* Compute Average Effects of Criticals by sampling */ for (i = 0; i < attempts; i++) { critical_t tmp = critical_norm(o_ptr->weight, to_h, p_ptr->weapon_info[hand].to_h, display_weapon_mode, hand); if (tmp.desc) { crit.mul += tmp.mul; crit.to_d += tmp.to_d; crits++; } else crit.mul += 100; } crit.mul = crit.mul / attempts; crit.to_d = crit.to_d * 100 / attempts; crit_pct = crits * 1000 / attempts; } else crit.mul = 100; /* Display in 2 columns, side by side */ cols[0] = doc_alloc(60); cols[1] = doc_alloc(10); /* Column #1 */ object_desc(o_name, o_ptr, OD_COLOR_CODED | OD_NAME_AND_ENCHANT); if (prace_is_(RACE_MON_SWORD)) doc_printf(cols[0], "<color:y> You :</color> <indent><style:indent>%s</style></indent>\n", o_name); else doc_printf(cols[0], "<color:y> Hand #%d:</color> <indent><style:indent>%s</style></indent>\n", hand+1, o_name); doc_printf(cols[0], " %-7.7s: %d.%d lbs\n", "Weight", o_ptr->weight/10, o_ptr->weight%10); if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH) { assert(o_ptr->tval == TV_SHIELD); doc_printf(cols[0], " %-7.7s: %dd%d (%+d,%+d)\n", "Bash", dd, ds, to_h, to_d); doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n", "Profic", skills_shield_describe_current(o_ptr->sval), skills_shield_calc_bonus(o_ptr->sval)); } else { doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n", "Profic", skills_weapon_describe_current(o_ptr->tval, o_ptr->sval), skills_weapon_calc_bonus(o_ptr->tval, o_ptr->sval)); } doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Hit", to_h, p_ptr->weapon_info[hand].to_h, to_h + p_ptr->weapon_info[hand].to_h); doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Dam", to_d, p_ptr->weapon_info[hand].to_d, to_d + p_ptr->weapon_info[hand].to_d); doc_printf(cols[0], " %-7.7s: %d.%2.2d\n", "Blows", num_blow/100, num_blow%100); if (p_ptr->weapon_info[hand].dual_wield_pct < 1000) { doc_printf(cols[0], " %-7.7s: %d.%d%%\n", "Skill", p_ptr->weapon_info[hand].dual_wield_pct/ 10, p_ptr->weapon_info[hand].dual_wield_pct % 10); } mult = mult * crit.mul / 100; to_d = to_d + crit.to_d/100 + p_ptr->weapon_info[hand].to_d; doc_printf(cols[0], "<color:G> %-7.7s</color>\n", "Damage"); if (!have_flag(flgs, TR_ORDER)) { if (crit.to_d) { doc_printf(cols[0], " %-7.7s: %d.%02dx + %d.%02d\n", "Crits", crit.mul/100, crit.mul%100, crit.to_d/100, crit.to_d%100); } else { doc_printf(cols[0], " %-7.7s: %d.%02dx (%d.%d%%)\n", "Crits", crit.mul/100, crit.mul%100, crit_pct / 10, crit_pct % 10); } } if (p_ptr->weapon_info[hand].to_mult) { int m = 100 + p_ptr->weapon_info[hand].to_mult; doc_printf(cols[0], " %-7.7s: %d.%02dx\n", "Mauler", m / 100, m % 100); } _display_weapon_slay(mult, 100, FALSE, num_blow, dd, ds, to_d, "Normal", TERM_WHITE, cols[0]); if (force) _display_weapon_slay(mult, 100, force, num_blow, dd, ds, to_d, "Force", TERM_L_BLUE, cols[0]); if (p_ptr->tim_slay_sentient) _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Sent.", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_ANIMAL)) _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_ANIMAL)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_EVIL)) _display_weapon_slay(mult, 350, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_EVIL)) _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_SLAY_GOOD)) _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Good", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_SLAY_LIVING)) _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Living", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_HUMAN)) _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_HUMAN)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_UNDEAD)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_UNDEAD)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_DEMON)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_DEMON)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_ORC)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_ORC)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_TROLL)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_TROLL)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_GIANT)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_GIANT)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_KILL_DRAGON)) _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]); else if (have_flag(flgs, TR_SLAY_DRAGON)) _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]); if (have_flag(flgs, TR_BRAND_ACID)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Acid", TERM_RED, cols[0]); if (have_flag(flgs, TR_BRAND_ELEC)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Elec", TERM_RED, cols[0]); if (have_flag(flgs, TR_BRAND_FIRE)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Fire", TERM_RED, cols[0]); if (have_flag(flgs, TR_BRAND_COLD)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Cold", TERM_RED, cols[0]); if (have_flag(flgs, TR_BRAND_POIS)) _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Poison", TERM_RED, cols[0]); if (p_ptr->weapon_info[hand].wield_how == WIELD_TWO_HANDS) { if (p_ptr->weapon_info[hand].omoi) doc_insert(cols[0], " Your weapon requires two hands to wield properly.\n"); } if (p_ptr->weapon_info[hand].info) { byte a = p_ptr->weapon_info[hand].info_attr; if (!a) a = TERM_WHITE; /* uninitialized is TERM_DARK???! */ doc_printf(cols[0], " <color:%c>%s</color>\n", attr_to_attr_char(a), p_ptr->weapon_info[hand].info); } /* Column #1 */ doc_insert(cols[1], "<color:G>Accuracy</color>\n"); doc_insert(cols[1], " AC Hit\n"); doc_printf(cols[1], "%3d %2d%%\n", 25, hit_chance(hand, to_h, 25)); doc_printf(cols[1], "%3d %2d%%\n", 50, hit_chance(hand, to_h, 50)); doc_printf(cols[1], "%3d %2d%%\n", 75, hit_chance(hand, to_h, 75)); doc_printf(cols[1], "%3d %2d%%\n", 100, hit_chance(hand, to_h, 100)); doc_printf(cols[1], "%3d %2d%%\n", 125, hit_chance(hand, to_h, 125)); doc_printf(cols[1], "%3d %2d%%\n", 150, hit_chance(hand, to_h, 150)); doc_printf(cols[1], "%3d %2d%%\n", 175, hit_chance(hand, to_h, 175)); doc_printf(cols[1], "%3d %2d%%\n", 200, hit_chance(hand, to_h, 200)); /* Assemble the result */ doc_insert_cols(doc, cols, 2, 1); doc_free(cols[0]); doc_free(cols[1]); }
void combat_start(void) { int i, j; int leader_x, leader_y; combat_mode = 1; music_combat_started(); quit_menu(); combat_attack_animation = 0; map_get_center(&combat_x, &combat_y); combat_x /= 8; combat_y /= 8; combat_x -= COMBAT_C_X; combat_y -= COMBAT_C_Y; combat_party_size = game_get_party_characters(combat_party); combat_leader_x = game_get_leader()->x; leader_x = combat_leader_x / 4 - combat_x; combat_leader_y = game_get_leader()->y; leader_y = combat_leader_y / 4 - combat_y; if (leader_x < 0) leader_x = 0; if (leader_y < 0) leader_y = 0; if (leader_x >= COMBAT_WIDTH) leader_x = COMBAT_WIDTH - 1; if (leader_y >= COMBAT_HEIGHT) leader_x = COMBAT_HEIGHT - 1; combat_area_init(); combat_area[leader_x][leader_y] = 1; combat_stack[0][0] = leader_x; combat_stack[0][1] = leader_y; combat_stack_size = 1; combat_stack_start = 0; combat_stack_proceed(); for (i = 0; i < combat_party_size; ++i) combat_move_to_area(combat_party[i]); ring_not_working = 0; for (i = 0; i < combat_enemies_num; ++i) { /* somewhat stupid */ if (!strcmp(combat_enemies[i]->name, "Nazgul") || !strcmp(combat_enemies[i]->name, "Witch-King") || !strcmp(combat_enemies[i]->name, "Ghostking") || !strcmp(combat_enemies[i]->name, "Ghost") || !strcmp(combat_enemies[i]->name, "Balrog") || !strcmp(combat_enemies[i]->name, "Barrow Wight") || !strcmp(combat_enemies[i]->name, "Werewolf")) ring_not_working = 1; if (strcmp(combat_enemies[i]->name, "Tentacles")) combat_move_to_area(combat_enemies[i]); for (j = 0; j < combat_enemies[i]->items_num; ++j) combat_enemies[i]->item_used[j] = 0; for (j = 0; j < combat_enemies[i]->items_num; ++j) if (object_is_weapon(combat_enemies[i]->items[j])) { combat_enemies[i]->item_used[j] = 1; break; } for (j = 0; j < combat_enemies[i]->items_num; ++j) if (object_is_armour(combat_enemies[i]->items[j])) { combat_enemies[i]->item_used[j] = 1; break; } for (j = 0; j < combat_enemies[i]->items_num; ++j) if (object_is_shield(combat_enemies[i]->items[j])) { combat_enemies[i]->item_used[j] = 1; break; } } active_character = NULL; combat_next_turn(); }