void textui_obj_wield(object_type *o_ptr, int item) { int slot = wield_slot(o_ptr); /* Usually if the slot is taken we'll just replace the item in the slot, * but in some cases we need to ask the user which slot they actually * want to replace */ if (p_ptr->inventory[slot].k_idx) { if (o_ptr->tval == TV_RING) { cptr q = "Replace which ring? "; cptr s = "Error in obj_wield, please report"; item_tester_hook = obj_is_ring; if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return; } if (obj_is_ammo(o_ptr) && !object_similar(&p_ptr->inventory[slot], o_ptr, OSTACK_QUIVER)) { cptr q = "Replace which ammunition? "; cptr s = "Error in obj_wield, please report"; item_tester_hook = obj_is_ammo; if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return; } } cmd_insert(CMD_WIELD); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_number(cmd_get_top(), 1, slot); }
/* * Carry an object and delete it. */ static void py_pickup_aux(int o_idx, bool domsg) { int slot, quiver_slot = 0; char o_name[80]; object_type *o_ptr = object_byid(o_idx); /* Carry the object */ slot = inven_carry(p_ptr, o_ptr); /* Handle errors (paranoia) */ if (slot < 0) return; /* If we have picked up ammo which matches something in the quiver, note * that it so that we can wield it later (and suppress pick up message) */ if (obj_is_ammo(o_ptr)) { int i; for (i = QUIVER_START; i < QUIVER_END; i++) { if (!p_ptr->inventory[i].kind) continue; if (!object_similar(&p_ptr->inventory[i], o_ptr, OSTACK_QUIVER)) continue; quiver_slot = i; break; } } /* Get the new object */ o_ptr = &p_ptr->inventory[slot]; /* Set squelch status */ p_ptr->notice |= PN_SQUELCH; /* Automatically sense artifacts */ object_notice_artifact(o_ptr); /* Optionally, display a message */ if (domsg && !quiver_slot) { /* Describe the object */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Message */ msg("You have %s (%c).", o_name, index_to_label(slot)); } /* Update object_idx if necessary */ if (p_ptr->object_idx == (0 - o_idx)) { track_object(slot); } /* Delete the object */ delete_object_idx(o_idx); /* If we have a quiver slot that this ammo matches, use it */ if (quiver_slot) wield_item(o_ptr, slot, quiver_slot); }
static size_t obj_desc_combat(const object_type *o_ptr, char *buf, size_t max, size_t end, bool spoil) { bitflag flags[OF_SIZE]; bitflag flags_known[OF_SIZE]; object_flags(o_ptr, flags); object_flags_known(o_ptr, flags_known); if (of_has(flags, OF_SHOW_DICE)) { /* Only display the real damage dice if the combat stats are known */ if (spoil || object_attack_plusses_are_visible(o_ptr)) strnfcat(buf, max, &end, " (%dd%d)", o_ptr->dd, o_ptr->ds); else strnfcat(buf, max, &end, " (%dd%d)", o_ptr->kind->dd, o_ptr->kind->ds); } if (of_has(flags, OF_SHOW_MULT)) { /* Display shooting power as part of the multiplier */ if (of_has(flags, OF_MIGHT) && (spoil || object_flag_is_known(o_ptr, OF_MIGHT))) strnfcat(buf, max, &end, " (x%d)", (o_ptr->sval % 10) + o_ptr->pval[which_pval(o_ptr, OF_MIGHT)]); else strnfcat(buf, max, &end, " (x%d)", o_ptr->sval % 10); } /* Show weapon bonuses */ if (spoil || object_attack_plusses_are_visible(o_ptr)) { if (wield_slot(o_ptr) == INVEN_WIELD || wield_slot(o_ptr) == INVEN_BOW || obj_is_ammo(o_ptr) || o_ptr->to_d || o_ptr->to_h) { /* Make an exception for body armor with only a to-hit penalty */ if (o_ptr->to_h < 0 && o_ptr->to_d == 0 && (o_ptr->tval == TV_SOFT_ARMOR || o_ptr->tval == TV_HARD_ARMOR || o_ptr->tval == TV_DRAG_ARMOR)) strnfcat(buf, max, &end, " (%+d)", o_ptr->to_h); /* Otherwise, always use the full tuple */ else strnfcat(buf, max, &end, " (%+d,%+d)", o_ptr->to_h, o_ptr->to_d); } } /* Show armor bonuses */ if (spoil || object_defence_plusses_are_visible(o_ptr)) { if (obj_desc_show_armor(o_ptr)) strnfcat(buf, max, &end, " [%d,%+d]", o_ptr->ac, o_ptr->to_a); else if (o_ptr->to_a) strnfcat(buf, max, &end, " [%+d]", o_ptr->to_a); } else if (obj_desc_show_armor(o_ptr)) strnfcat(buf, max, &end, " [%d]", object_was_sensed(o_ptr) ? o_ptr->ac : o_ptr->kind->ac); return end; }
/* * Apply magic to a weapon. */ static void apply_magic_weapon(object_type *o_ptr, int level, int power) { if (power <= 0) return; o_ptr->to_h += randint1(5) + m_bonus(5, level); o_ptr->to_d += randint1(5) + m_bonus(5, level); if (power > 1) { o_ptr->to_h += m_bonus(10, level); o_ptr->to_d += m_bonus(10, level); if (wield_slot(o_ptr) == INVEN_WIELD || obj_is_ammo(o_ptr)) { /* Super-charge the damage dice */ while ((o_ptr->dd * o_ptr->ds > 0) && one_in_(10L * o_ptr->dd * o_ptr->ds)) o_ptr->dd++; /* But not too high */ if (o_ptr->dd > 9) o_ptr->dd = 9; } } }
/* Wield or wear an item */ void do_cmd_wield(cmd_code code, cmd_arg args[]) { object_type *equip_o_ptr; char o_name[80]; unsigned n; int item = args[0].item; int slot = args[1].number; object_type *o_ptr = object_from_item_idx(item); if (!item_is_available(item, NULL, USE_INVEN | USE_FLOOR)) { msg("You do not have that item to wield."); return; } /* Check the slot */ if (!slot_can_wield_item(slot, o_ptr)) { msg("You cannot wield that item there."); return; } equip_o_ptr = &p_ptr->inventory[slot]; /* If the slot is open, wield and be done */ if (!equip_o_ptr->kind) { wield_item(o_ptr, item, slot); return; } /* If the slot is in the quiver and objects can be combined */ if (obj_is_ammo(equip_o_ptr) && object_similar(equip_o_ptr, o_ptr, OSTACK_QUIVER)) { wield_item(o_ptr, item, slot); return; } /* Prevent wielding into a cursed slot */ if (cursed_p(equip_o_ptr->flags)) { object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_BASE); msg("The %s you are %s appears to be cursed.", o_name, describe_use(slot)); return; } /* "!t" checks for taking off */ n = check_for_inscrip(equip_o_ptr, "!t"); while (n--) { /* Prompt */ object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_PREFIX | ODESC_FULL); /* Forget it */ if (!get_check(format("Really take off %s? ", o_name))) return; } wield_item(o_ptr, item, slot); }
/* * Wield or wear a single item from the pack or floor */ void wield_item(object_type *o_ptr, int item, int slot) { object_type object_type_body; object_type *i_ptr = &object_type_body; const char *fmt; char o_name[80]; bool combined_ammo = FALSE; bool track_wielded_item = FALSE; int num = 1; /* If we are stacking ammo in the quiver */ if (obj_is_ammo(o_ptr)) { num = o_ptr->number; combined_ammo = object_similar(o_ptr, &p_ptr->inventory[slot], OSTACK_QUIVER); } /* Take a turn */ p_ptr->energy_use = 100; /* Obtain local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = num; /* Update object_idx if necessary, once object is in slot */ if (p_ptr->object_idx == item) { track_wielded_item = TRUE; } /* Decrease the item (from the pack) */ if (item >= 0) { inven_item_increase(item, -num); inven_item_optimize(item); } /* Decrease the item (from the floor) */ else { floor_item_increase(0 - item, -num); floor_item_optimize(0 - item); } /* Get the wield slot */ o_ptr = &p_ptr->inventory[slot]; if (combined_ammo) { /* Add the new ammo to the already-quiver-ed ammo */ object_absorb(o_ptr, i_ptr); } else { /* Take off existing item */ if (o_ptr->kind) (void)inven_takeoff(slot, 255); /* If we are wielding ammo we may need to "open" the slot by shifting * later ammo up the quiver; this is because we already called the * inven_item_optimize() function. */ if (slot >= QUIVER_START) open_quiver_slot(slot); /* Wear the new stuff */ object_copy(o_ptr, i_ptr); /* Increment the equip counter by hand */ p_ptr->equip_cnt++; } /* Increase the weight */ p_ptr->total_weight += i_ptr->weight * num; /* Track object if necessary */ if (track_wielded_item) { track_object(slot); } /* Do any ID-on-wield */ object_notice_on_wield(o_ptr); /* Where is the item now */ if (slot == INVEN_WIELD) fmt = "You are wielding %s (%c)."; else if (slot == INVEN_BOW) fmt = "You are shooting with %s (%c)."; else if (slot == INVEN_LIGHT) fmt = "Your light source is %s (%c)."; else if (combined_ammo) fmt = "You combine %s in your quiver (%c)."; else if (slot >= QUIVER_START && slot < QUIVER_END) fmt = "You add %s to your quiver (%c)."; else fmt = "You are wearing %s (%c)."; /* Describe the result */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Message */ msgt(MSG_WIELD, fmt, o_name, index_to_label(slot)); /* Cursed! */ if (cursed_p(o_ptr->flags)) { /* Warn the player */ msgt(MSG_CURSED, "Oops! It feels deathly cold!"); /* Sense the object */ object_notice_curses(o_ptr); } /* Save quiver size */ save_quiver_size(p_ptr); /* See if we have to overflow the pack */ pack_overflow(); /* Recalculate bonuses, torch, mana */ p_ptr->notice |= PN_SORT_QUIVER; p_ptr->update |= (PU_BONUS | PU_TORCH | PU_MANA); p_ptr->redraw |= (PR_INVEN | PR_EQUIP); }
/* * Evaluate the object's overall power level. */ s32b object_power(const object_type* o_ptr, int verbose, ang_file *log_file, bool known) { s32b p = 0, q = 0, slay_pwr = 0; unsigned int i, j; int extra_stat_bonus = 0, mult = 1, num_slays = 0, k = 1; bitflag flags[OF_SIZE], mask[OF_SIZE]; /* Zero the flag counts */ for (i = 0; i < N_ELEMENTS(sets); i++) sets[i].count = 0; /* Extract the flags */ if (known) { file_putf(log_file, "Object is deemed known\n"); object_flags(o_ptr, flags); } else { file_putf(log_file, "Object may not be fully known\n"); object_flags_known(o_ptr, flags); } /* Log the flags in human-readable form */ if (verbose) log_flags(flags, log_file); /* Get the slay power and number of slay/brand types */ create_mask(mask, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX); num_slays = list_slays(flags, mask, NULL, NULL, NULL, TRUE); if (num_slays) slay_pwr = slay_power(o_ptr, verbose, log_file, known); /* Start with any damage boost from the item itself */ p += (o_ptr->to_d * DAMAGE_POWER / 2); file_putf(log_file, "Adding power from to_dam, total is %d\n", p); /* Add damage from dice for any wieldable weapon or ammo */ if (wield_slot(o_ptr) == INVEN_WIELD || obj_is_ammo(o_ptr)) { p += (o_ptr->dd * (o_ptr->ds + 1) * DAMAGE_POWER / 4); file_putf(log_file, "Adding power for dam dice, total is %d\n", p); /* Add 2nd lot of damage power for nonweapons */ } else if (wield_slot(o_ptr) != INVEN_BOW) { p += (o_ptr->to_d * DAMAGE_POWER); file_putf(log_file, "Adding power from nonweap to_dam, total is %d\n", p); /* Add power boost for nonweapons with combat flags */ if (num_slays || of_has(flags, OF_BLOWS) || of_has(flags, OF_SHOTS) || of_has(flags, OF_MIGHT)) { p += (WEAP_DAMAGE * DAMAGE_POWER); file_putf(log_file, "Adding power for nonweap combat flags, total is %d\n", p); } } /* Add ammo damage for launchers, get multiplier and rescale */ if (wield_slot(o_ptr) == INVEN_BOW) { p += (archery[o_ptr->sval / 10].ammo_dam * DAMAGE_POWER / 2); file_putf(log_file, "Adding power from ammo, total is %d\n", p); mult = bow_multiplier(o_ptr->sval); file_putf(log_file, "Base mult for this weapon is %d\n", mult); } /* Add launcher bonus for ego ammo, multiply for launcher and rescale */ if (obj_is_ammo(o_ptr)) { if (o_ptr->ego) p += (archery[o_ptr->tval - TV_SHOT].launch_dam * DAMAGE_POWER / 2); p = p * archery[o_ptr->tval - TV_SHOT].launch_mult / (2 * MAX_BLOWS); file_putf(log_file, "After multiplying ammo and rescaling, power is %d\n", p); } /* Add power for extra blows */ if (of_has(flags, OF_BLOWS)) { j = which_pval(o_ptr, OF_BLOWS); if (known || object_this_pval_is_visible(o_ptr, j)) { if (o_ptr->pval[j] >= INHIBIT_BLOWS) { p += INHIBIT_POWER; file_putf(log_file, "INHIBITING - too many extra blows\n"); } else { p = p * (MAX_BLOWS + o_ptr->pval[j]) / MAX_BLOWS; /* Add boost for assumed off-weapon damage */ p += (NONWEAP_DAMAGE * o_ptr->pval[j] * DAMAGE_POWER / 2); file_putf(log_file, "Adding power for extra blows, total is %d\n", p); } } } /* Add power for extra shots - note that we cannot handle negative shots */ if (of_has(flags, OF_SHOTS)) { j = which_pval(o_ptr, OF_SHOTS); if (known || object_this_pval_is_visible(o_ptr, j)) { if (o_ptr->pval[j] >= INHIBIT_SHOTS) { p += INHIBIT_POWER; file_putf(log_file, "INHIBITING - too many extra shots\n"); } else if (o_ptr->pval[j] > 0) { p = (p * (1 + o_ptr->pval[j])); file_putf(log_file, "Extra shots: multiplying power by 1 + %d, total is %d\n", o_ptr->pval[j], p); } } } /* Add power for extra might */ if (of_has(flags, OF_MIGHT)) { j = which_pval(o_ptr, OF_MIGHT); if (known || object_this_pval_is_visible(o_ptr, j)) { if (o_ptr->pval[j] >= INHIBIT_MIGHT) { p += INHIBIT_POWER; mult = 1; /* don't overflow */ file_putf(log_file, "INHIBITING - too much extra might\n"); } else mult += o_ptr->pval[j]; file_putf(log_file, "Mult after extra might is %d\n", mult); } } p *= mult; file_putf(log_file, "After multiplying power for might, total is %d\n", p); /* Apply the correct slay multiplier */ if (slay_pwr) { p = (p * (slay_pwr / 10)) / (tot_mon_power / 10); file_putf(log_file, "Adjusted for slay power, total is %d\n", p); } /* Melee weapons assume MAX_BLOWS per turn, so we must divide by MAX_BLOWS * to get equal ratings for launchers. */ if (wield_slot(o_ptr) == INVEN_BOW) { p /= MAX_BLOWS; file_putf(log_file, "Rescaling bow power, total is %d\n", p); } /* Add power for +to_hit */ p += (o_ptr->to_h * TO_HIT_POWER / 2); file_putf(log_file, "Adding power for to hit, total is %d\n", p); /* Add power for base AC and adjust for weight */ if (o_ptr->ac) { q += BASE_ARMOUR_POWER; q += (o_ptr->ac * BASE_AC_POWER / 2); file_putf(log_file, "Adding %d power for base AC value\n", q); /* Add power for AC per unit weight */ if (o_ptr->weight > 0) { i = 800 * (o_ptr->ac + o_ptr->to_a) / o_ptr->weight; /* Avoid overpricing Elven Cloaks */ if (i > 450) i = 450; q *= i; q /= 100; /* Weightless (ethereal) armour items get fixed boost */ } else q *= 5; p += q; file_putf(log_file, "Adding power for AC per unit weight, now %d\n", p); } /* Add power for +to_ac */ p += (o_ptr->to_a * TO_AC_POWER / 2); file_putf(log_file, "Adding power for to_ac of %d, total is %d\n", o_ptr->to_a, p); if (o_ptr->to_a > HIGH_TO_AC) { p += ((o_ptr->to_a - (HIGH_TO_AC - 1)) * TO_AC_POWER); file_putf(log_file, "Adding power for high to_ac value, total is %d\n", p); } if (o_ptr->to_a > VERYHIGH_TO_AC) { p += ((o_ptr->to_a - (VERYHIGH_TO_AC -1)) * TO_AC_POWER * 2); file_putf(log_file, "Adding power for very high to_ac value, total is %d\n", p); } if (o_ptr->to_a >= INHIBIT_AC) { p += INHIBIT_POWER; file_putf(log_file, "INHIBITING: AC bonus too high\n"); } /* Add power for light sources by radius XXX Hack - rewrite calc_torch! */ if (wield_slot(o_ptr) == INVEN_LIGHT) { p += BASE_LIGHT_POWER; /* Artifact lights have larger radius so add more */ if (o_ptr->artifact) p += BASE_LIGHT_POWER; file_putf(log_file, "Adding power for light radius, total is %d\n", p); } /* Add base power for jewelry */ if (object_is_jewelry(o_ptr)) { p += BASE_JEWELRY_POWER; file_putf(log_file, "Adding power for jewelry, total is %d\n", p); } /* Add power for non-derived flags (derived flags have flag_power 0) */ for (i = 0; i < OF_MAX; i++) { if (of_has(flags, i)) { if (flag_uses_pval(i)) { j = which_pval(o_ptr, i); if (known || object_this_pval_is_visible(o_ptr, j)) { k = o_ptr->pval[j]; extra_stat_bonus += (k * pval_mult(i)); } } else k = 1; if (flag_power(i)) { p += (k * flag_power(i) * slot_mult(i, wield_slot(o_ptr))); file_putf(log_file, "Adding power for %s, total is %d\n", flag_name(i), p); } /* Track combinations of flag types - note we ignore SUST_CHR */ for (j = 0; j < N_ELEMENTS(sets); j++) if ((sets[j].type == obj_flag_type(i)) && (i != OF_SUST_CHR)) sets[j].count++; } } /* Add extra power term if there are a lot of ability bonuses */ if (extra_stat_bonus > 249) { file_putf(log_file, "Inhibiting! (Total ability bonus of %d is too high)\n", extra_stat_bonus); p += INHIBIT_POWER; } else { p += ability_power[extra_stat_bonus / 10]; file_putf(log_file, "Adding power for pval total of %d, total is %d\n", extra_stat_bonus, p); } /* Add extra power for multiple flags of the same type */ for (i = 0; i < N_ELEMENTS(sets); i++) { if (sets[i].count > 1) { p += (sets[i].factor * sets[i].count * sets[i].count); file_putf(log_file, "Adding power for multiple flags of type %d, total is %d\n", i, p); } /* Add bonus if item has a full set of these flags */ if (sets[i].count == sets[i].size) { p += sets[i].bonus; file_putf(log_file, "Adding power for full set of type %d, total is %d\n", i, p); } } /* add power for effect */ if (known || object_effect_is_known(o_ptr)) { if (o_ptr->artifact && o_ptr->artifact->effect) { p += effect_power(o_ptr->artifact->effect); file_putf(log_file, "Adding power for artifact activation, total is %d\n", p); } else { p += effect_power(o_ptr->kind->effect); file_putf(log_file, "Adding power for item activation, total is %d\n", p); } } file_putf(log_file, "FINAL POWER IS %d\n", p); return p; }