diff options
Diffstat (limited to 'stone_soup/crawl-ref/source/item_use.cc')
-rw-r--r-- | stone_soup/crawl-ref/source/item_use.cc | 3289 |
1 files changed, 0 insertions, 3289 deletions
diff --git a/stone_soup/crawl-ref/source/item_use.cc b/stone_soup/crawl-ref/source/item_use.cc deleted file mode 100644 index c1b37124ab..0000000000 --- a/stone_soup/crawl-ref/source/item_use.cc +++ /dev/null @@ -1,3289 +0,0 @@ -/* - * File: item_use.cc - * Summary: Functions for making use of inventory items. - * Written by: Linley Henzell - * - * Change History (most recent first): - * - * <8> 28July2000 GDL Revised player throwing - * <7> 11/23/99 LRH Horned characters can wear hats/caps - * <6> 7/13/99 BWR Lowered learning rates for - * throwing skills, and other - * balance tweaks - * <5> 5/28/99 JDJ Changed wear_armour to allow Spriggans to - * wear bucklers. - * <4> 5/26/99 JDJ body armour can be removed and worn if an - * uncursed cloak is being worn. - * Removed lots of unnessary mpr string copying. - * Added missing ponderous message. - * <3> 5/20/99 BWR Fixed staff of air bug, output of trial - * identified items, a few you.wield_changes so - * that the weapon gets updated. - * <2> 5/08/99 JDJ Added armour_prompt. - * <1> -/--/-- LRH Created - */ - -#include "AppHdr.h" -#include "item_use.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "externs.h" - -#include "beam.h" -#include "debug.h" -#include "delay.h" -#include "describe.h" -#include "direct.h" -#include "effects.h" -#include "fight.h" -#include "food.h" -#include "invent.h" -#include "it_use2.h" -#include "it_use3.h" -#include "items.h" -#include "itemname.h" -#include "itemprop.h" -#include "misc.h" -#include "monplace.h" -#include "monstuff.h" -#include "mstuff2.h" -#include "mon-util.h" -#include "ouch.h" -#include "player.h" -#include "randart.h" -#include "religion.h" -#include "skills.h" -#include "skills2.h" -#include "spells1.h" -#include "spells2.h" -#include "spells3.h" -#include "spl-book.h" -#include "spl-cast.h" -#include "stuff.h" -#include "transfor.h" -#include "view.h" -#include "wpn-misc.h" - -bool drink_fountain(void); -void use_randart(unsigned char item_wield_2); -static bool enchant_armour( void ); - -// Rather messy - we've gathered all the can't-wield logic from wield_weapon() -// here. -bool can_wield(const item_def& weapon) -{ - if (you.berserker) return false; - if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE - && !can_equip( EQ_WEAPON )) - return false; - - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && item_cursed( you.inv[you.equip[EQ_WEAPON]] )) - return false; - - if (weapon.base_type != OBJ_WEAPONS && weapon.base_type == OBJ_STAVES - && you.equip[EQ_SHIELD] != -1) - return false; - - if ((you.species < SP_OGRE || you.species > SP_OGRE_MAGE) - && item_mass( weapon ) >= 500) - return false; - - if ((you.species == SP_HALFLING || you.species == SP_GNOME - || you.species == SP_KOBOLD || you.species == SP_SPRIGGAN) - && (weapon.sub_type == WPN_GREAT_SWORD - || weapon.sub_type == WPN_TRIPLE_SWORD - || weapon.sub_type == WPN_GREAT_MACE - || weapon.sub_type == WPN_DIRE_FLAIL - || weapon.sub_type == WPN_BATTLEAXE - || weapon.sub_type == WPN_EXECUTIONERS_AXE - || weapon.sub_type == WPN_LOCHABER_AXE - || weapon.sub_type == WPN_HALBERD - || weapon.sub_type == WPN_GLAIVE - || weapon.sub_type == WPN_GIANT_CLUB - || weapon.sub_type == WPN_GIANT_SPIKED_CLUB - || weapon.sub_type == WPN_LONGBOW - || weapon.sub_type == WPN_SCYTHE)) - return false; - - if (hands_reqd_for_weapon( weapon.base_type, - weapon.sub_type ) == HANDS_TWO - && you.equip[EQ_SHIELD] != -1) - return false; - - int weap_brand = get_weapon_brand( weapon ); - if ((you.is_undead || you.species == SP_DEMONSPAWN) - && (!is_fixed_artefact( weapon ) - && (weap_brand == SPWPN_HOLY_WRATH - || weap_brand == SPWPN_DISRUPTION - || (weapon.base_type == OBJ_WEAPONS - && weapon.sub_type == WPN_BLESSED_BLADE)))) - return false; - - // We can wield this weapon. Phew! - return true; -} - -bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages) -{ - int item_slot = 0; - char str_pass[ ITEMNAME_SIZE ]; - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return (false); - } - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return (false); - } - - if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) - { - if (!can_equip( EQ_WEAPON )) - { - mpr("You can't wield anything in your present form."); - return (false); - } - } - - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS - && item_cursed( you.inv[you.equip[EQ_WEAPON]] )) - { - mpr("You can't unwield your weapon to draw a new one!"); - return (false); - } - - if (you.sure_blade) - { - mpr("The bond with your blade fades away."); - you.sure_blade = 0; - } - - if (auto_wield) - { - if (you.equip[EQ_WEAPON] == 0) // ie. weapon is currently 'a' - item_slot = 1; - else - item_slot = 0; - if (slot != -1) item_slot = slot; - } - - bool force_unwield = - you.inv[item_slot].base_type != OBJ_WEAPONS - && you.inv[item_slot].base_type != OBJ_MISSILES - && you.inv[item_slot].base_type != OBJ_STAVES; - - // Prompt if not using the auto swap command, - // or if the swap slot is empty. - if (!auto_wield || !is_valid_item(you.inv[item_slot]) || force_unwield) - { - if (!auto_wield) - item_slot = prompt_invent_item( "Wield which item (- for none)?", - OSEL_WIELD, true, true, true, '-' ); - else - item_slot = PROMPT_GOT_SPECIAL; - - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return (false); - } - else if (item_slot == PROMPT_GOT_SPECIAL) // '-' or bare hands - { - if (you.equip[EQ_WEAPON] != -1) - { - unwield_item(you.equip[EQ_WEAPON]); - you.turn_is_over = 1; - - you.equip[EQ_WEAPON] = -1; - canned_msg( MSG_EMPTY_HANDED ); - you.time_taken *= 3; - you.time_taken /= 10; - } - else - { - mpr( "You are already empty-handed." ); - } - return (true); - } - } - - if (item_slot == you.equip[EQ_WEAPON]) - { - mpr("You are already wielding that!"); - return (true); - } - - for (int i = EQ_CLOAK; i <= EQ_AMULET; i++) - { - if (item_slot == you.equip[i]) - { - mpr("You are wearing that object!"); - return (false); - } - } - - if (you.inv[item_slot].base_type != OBJ_WEAPONS) - { - if (you.inv[item_slot].base_type == OBJ_STAVES - && you.equip[EQ_SHIELD] != -1) - { - mpr("You can't wield that with a shield."); - return (false); - } - - if (you.equip[EQ_WEAPON] != -1) - unwield_item(you.equip[EQ_WEAPON]); - - you.equip[EQ_WEAPON] = item_slot; - } - else - { - if ((you.species < SP_OGRE || you.species > SP_OGRE_MAGE) - && item_mass( you.inv[item_slot] ) >= 500) - { - mpr("That's too large and heavy for you to wield."); - return (false); - } - - if ((you.species == SP_HALFLING || you.species == SP_GNOME - || you.species == SP_KOBOLD || you.species == SP_SPRIGGAN) - - && (you.inv[item_slot].sub_type == WPN_GREAT_SWORD - || you.inv[item_slot].sub_type == WPN_TRIPLE_SWORD - || you.inv[item_slot].sub_type == WPN_GREAT_MACE - || you.inv[item_slot].sub_type == WPN_DIRE_FLAIL - || you.inv[item_slot].sub_type == WPN_BATTLEAXE - || you.inv[item_slot].sub_type == WPN_EXECUTIONERS_AXE - || you.inv[item_slot].sub_type == WPN_LOCHABER_AXE - || you.inv[item_slot].sub_type == WPN_HALBERD - || you.inv[item_slot].sub_type == WPN_GLAIVE - || you.inv[item_slot].sub_type == WPN_GIANT_CLUB - || you.inv[item_slot].sub_type == WPN_GIANT_SPIKED_CLUB - || you.inv[item_slot].sub_type == WPN_LONGBOW - || you.inv[item_slot].sub_type == WPN_SCYTHE)) - { - mpr("That's too large for you to wield."); - return (false); - - } - - if (hands_reqd_for_weapon( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type ) == HANDS_TWO - && you.equip[EQ_SHIELD] != -1) - { - mpr("You can't wield that with a shield."); - return (false); - } - - int weap_brand = get_weapon_brand( you.inv[item_slot] ); - - if ((you.is_undead || you.species == SP_DEMONSPAWN) - && (!is_fixed_artefact( you.inv[item_slot] ) - && (weap_brand == SPWPN_HOLY_WRATH - || weap_brand == SPWPN_DISRUPTION - || (you.inv[item_slot].base_type == OBJ_WEAPONS - && you.inv[item_slot].sub_type == WPN_BLESSED_BLADE)))) - { - mpr("This weapon will not allow you to wield it."); - you.turn_is_over = 1; - return (false); - } - - if (you.equip[EQ_WEAPON] != -1) - unwield_item(you.equip[EQ_WEAPON]); - - you.equip[EQ_WEAPON] = item_slot; - } - - // any oddness on wielding taken care of here - wield_effects(item_slot, show_weff_messages); - - in_name( item_slot, DESC_INVENTORY_EQUIP, str_pass ); - mpr( str_pass ); - - // warn player about low str/dex or throwing skill - wield_warning(); - - // time calculations - you.time_taken *= 5; - you.time_taken /= 10; - - you.wield_change = true; - you.turn_is_over = 1; - - return (true); -} - -// provide a function for handling initial wielding of 'special' -// weapons, or those whose function is annoying to reproduce in -// other places *cough* auto-butchering *cough* {gdl} - -void wield_effects(int item_wield_2, bool showMsgs) -{ - unsigned char i_dam = 0; - - // and here we finally get to the special effects of wielding {dlb} - if (you.inv[item_wield_2].base_type == OBJ_MISCELLANY) - { - if (you.inv[item_wield_2].sub_type == MISC_LANTERN_OF_SHADOWS) - { - if (showMsgs) - mpr("The area is filled with flickering shadows."); - - you.special_wield = SPWLD_SHADOW; - } - } - - if (you.inv[item_wield_2].base_type == OBJ_STAVES) - { - if (you.inv[item_wield_2].sub_type == STAFF_POWER) - { - // inc_max_mp(13); - calc_mp(); - set_ident_flags( you.inv[item_wield_2], ISFLAG_EQ_WEAPON_MASK ); - } - else - { - // Most staves only give curse status when wielded and - // right now that's always "uncursed". -- bwr - set_ident_flags( you.inv[item_wield_2], ISFLAG_KNOW_CURSE ); - } - } - - if (you.inv[item_wield_2].base_type == OBJ_WEAPONS) - { - if (is_demonic(you.inv[item_wield_2].sub_type) - && (you.religion == GOD_ZIN || you.religion == GOD_SHINING_ONE - || you.religion == GOD_ELYVILON)) - { - if (showMsgs) - mpr("You really shouldn't be using a nasty item like this."); - } - - set_ident_flags( you.inv[item_wield_2], ISFLAG_EQ_WEAPON_MASK ); - - if (is_random_artefact( you.inv[item_wield_2] )) - { - i_dam = randart_wpn_property(you.inv[item_wield_2], RAP_BRAND); - use_randart(item_wield_2); - } - else - { - i_dam = you.inv[item_wield_2].special; - } - - if (i_dam != SPWPN_NORMAL) - { - // message first - if (showMsgs) - { - switch (i_dam) - { - case SPWPN_SWORD_OF_CEREBOV: - case SPWPN_FLAMING: - mpr("It bursts into flame!"); - break; - - case SPWPN_FREEZING: - mpr("It glows with a cold blue light!"); - break; - - case SPWPN_HOLY_WRATH: - mpr("It softly glows with a divine radiance!"); - break; - - case SPWPN_ELECTROCUTION: - mpr("You hear the crackle of electricity."); - break; - - case SPWPN_ORC_SLAYING: - mpr((you.species == SP_HILL_ORC) - ? "You feel a sudden desire to commit suicide." - : "You feel a sudden desire to kill orcs!"); - break; - - case SPWPN_VENOM: - mpr("It begins to drip with poison!"); - break; - - case SPWPN_PROTECTION: - mpr("You feel protected!"); - break; - - case SPWPN_DRAINING: - mpr("You sense an unholy aura."); - break; - - case SPWPN_SPEED: - mpr("Your hands tingle!"); - break; - - case SPWPN_FLAME: - mpr("It glows red for a moment."); - break; - - case SPWPN_FROST: - mpr("It is covered in frost."); - break; - - case SPWPN_VAMPIRICISM: - if (!you.is_undead) - mpr("You feel a strange hunger."); - else - mpr("You feel strangely empty."); - break; - - case SPWPN_DISRUPTION: - mpr("You sense a holy aura."); - break; - - case SPWPN_PAIN: - mpr("A searing pain shoots up your arm!"); - break; - - case SPWPN_SINGING_SWORD: - mpr("The Singing Sword hums in delight!"); - break; - - case SPWPN_WRATH_OF_TROG: - mpr("You feel bloodthirsty!"); - break; - - case SPWPN_SCYTHE_OF_CURSES: - mpr("A shiver runs down your spine."); - break; - - case SPWPN_GLAIVE_OF_PRUNE: - mpr("You feel pruney."); - break; - - case SPWPN_SCEPTRE_OF_TORMENT: - mpr("A terribly searing pain shoots up your arm!"); - break; - - case SPWPN_SWORD_OF_ZONGULDROK: - mpr("You sense an extremely unholy aura."); - break; - - case SPWPN_SWORD_OF_POWER: - mpr("You sense an aura of extreme power."); - break; - - case SPWPN_STAFF_OF_OLGREB: - // mummies cannot smell - if (you.species != SP_MUMMY) - mpr("You smell chlorine."); - else - mpr("The staff glows slightly green."); - break; - - case SPWPN_VAMPIRES_TOOTH: - // mummies cannot smell, and do not hunger {dlb} - if (!you.is_undead) - mpr("You feel a strange hunger, and smell blood on the air..."); - else - mpr("You feel strangely empty."); - break; - - default: - break; - } - } - - // effect second - switch (i_dam) - { - case SPWPN_PROTECTION: - you.redraw_armour_class = 1; - break; - - case SPWPN_DISTORTION: - miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" ); - break; - - case SPWPN_SINGING_SWORD: - you.special_wield = SPWLD_SING; - break; - - case SPWPN_WRATH_OF_TROG: - you.special_wield = SPWLD_TROG; - break; - - case SPWPN_SCYTHE_OF_CURSES: - you.special_wield = SPWLD_CURSE; - if (one_chance_in(5)) - do_curse_item( you.inv[item_wield_2] ); - break; - - case SPWPN_MACE_OF_VARIABILITY: - you.special_wield = SPWLD_VARIABLE; - break; - - case SPWPN_GLAIVE_OF_PRUNE: - you.special_wield = SPWLD_NONE; - break; - - case SPWPN_SCEPTRE_OF_TORMENT: - you.special_wield = SPWLD_TORMENT; - break; - - case SPWPN_SWORD_OF_ZONGULDROK: - you.special_wield = SPWLD_ZONGULDROK; - break; - - case SPWPN_SWORD_OF_POWER: - you.special_wield = SPWLD_POWER; - break; - - case SPWPN_STAFF_OF_OLGREB: - // josh declares mummies cannot smell {dlb} - you.special_wield = SPWLD_OLGREB; - break; - - case SPWPN_STAFF_OF_WUCAD_MU: - miscast_effect( SPTYP_DIVINATION, 9, 90, 100, "the Staff of Wucad Mu" ); - you.special_wield = SPWLD_WUCAD_MU; - break; - } - } - - if (item_cursed( you.inv[item_wield_2] )) - mpr("It sticks to your hand!"); - } -} // end wield_weapon() - -//--------------------------------------------------------------- -// -// armour_prompt -// -// Prompt the user for some armour. Returns true if the user picked -// something legit. -// -//--------------------------------------------------------------- -bool armour_prompt( const std::string & mesg, int *index ) -{ - ASSERT(index != NULL); - - bool succeeded = false; - int slot; - - if (inv_count() < 1) - canned_msg(MSG_NOTHING_CARRIED); - else if (you.berserker) - canned_msg(MSG_TOO_BERSERK); - else - { - slot = prompt_invent_item( mesg.c_str(), OBJ_ARMOUR ); - - if (slot != PROMPT_ABORT) - { - *index = slot; - succeeded = true; - } - } - - return (succeeded); -} // end armour_prompt() - -static bool cloak_is_being_removed( void ) -{ - if (current_delay_action() != DELAY_ARMOUR_OFF) - return (false); - - if (you.delay_queue.front().parm1 != you.equip[ EQ_CLOAK ]) - return (false); - - return (true); -} - -//--------------------------------------------------------------- -// -// wear_armour -// -//--------------------------------------------------------------- -void wear_armour(void) -{ - int armour_wear_2; - - if (!armour_prompt("Wear which item?", &armour_wear_2)) - return; - - do_wear_armour( armour_wear_2, false ); -} - -bool do_wear_armour( int item, bool quiet ) -{ - if (!is_valid_item( you.inv[item] )) - { - if (!quiet) - mpr("You don't have any such object."); - - return (false); - } - - const int base_type = you.inv[item].base_type; - if (base_type != OBJ_ARMOUR) - { - if (!quiet) - mpr("You can't wear that."); - - return (false); - } - - const int sub_type = you.inv[item].sub_type; - const item_def &invitem = you.inv[item]; - const equipment_type slot = get_armour_slot(invitem); - - if (item == you.equip[EQ_WEAPON]) - { - if (!quiet) - mpr("You are wielding that object!"); - - return (false); - } - - for (int loopy = EQ_CLOAK; loopy <= EQ_BODY_ARMOUR; loopy++) - { - if (item == you.equip[loopy]) - { - if (!quiet) - mpr("You are already wearing that!"); - - return (false); - } - } - - // if you're wielding something, - if (you.equip[EQ_WEAPON] != -1 - // attempting to wear a shield, - && (you.inv[item].sub_type == ARM_SHIELD - || you.inv[item].sub_type == ARM_BUCKLER - || you.inv[item].sub_type == ARM_LARGE_SHIELD) - // weapon is two-handed - && hands_reqd_for_weapon(you.inv[you.equip[EQ_WEAPON]].base_type, - you.inv[you.equip[EQ_WEAPON]].sub_type) == HANDS_TWO) - { - if (!quiet) - mpr("You'd need three hands to do that!"); - - return (false); - } - - bool can_wear = true; - if (sub_type == ARM_NAGA_BARDING) - can_wear = (you.species == SP_NAGA); - - if (sub_type == ARM_CENTAUR_BARDING) - can_wear = (you.species == SP_CENTAUR); - - if (!can_wear) - { - if (!quiet) - mpr("You can't wear that!"); - return (false); - } - - if (you.inv[item].sub_type == ARM_BOOTS) - { - if (you.species == SP_NAGA || you.species == SP_CENTAUR) - { - if (!quiet) - mpr("You can't wear that!"); - return (false); - } - - if (player_is_swimming() && you.species == SP_MERFOLK) - { - if (!quiet) - mpr("You don't currently have feet!"); - - return (false); - } - } - - if (you.species == SP_NAGA && sub_type == ARM_NAGA_BARDING - && !player_is_shapechanged()) - { - // it fits - } - else if (you.species == SP_CENTAUR - && sub_type == ARM_CENTAUR_BARDING - && !player_is_shapechanged()) - { - // it fits - } - else if (sub_type == ARM_HELMET - && (get_helmet_type(invitem) == THELM_CAP - || get_helmet_type(invitem) == THELM_WIZARD_HAT)) - { - // caps & wiz hats always fit, unless your head's too big (ogres &c) - } - else if (!can_equip( slot )) - { - if (!quiet) - mpr("You can't wear that in your present form."); - - return (false); - } - - // Cannot swim in heavy armour - if (player_is_swimming() - && slot == EQ_BODY_ARMOUR - && !is_light_armour( invitem )) - { - if (!quiet) - mpr("You can't swim in that!"); - - return (false); - } - - // Giant races - if ((you.species >= SP_OGRE && you.species <= SP_OGRE_MAGE) - || player_genus(GENPC_DRACONIAN)) - { - if ((sub_type >= ARM_LEATHER_ARMOUR - && sub_type <= ARM_PLATE_MAIL) - || (sub_type >= ARM_GLOVES - && sub_type <= ARM_BUCKLER) - || sub_type == ARM_CRYSTAL_PLATE_MAIL - || (sub_type == ARM_HELMET - && (get_helmet_type(invitem) == THELM_HELM - || get_helmet_type(invitem) == THELM_HELMET))) - { - if (!quiet) - mpr("This armour doesn't fit on your body."); - - return (false); - } - } - - // Tiny races - if (you.species == SP_SPRIGGAN) - { - if ((sub_type >= ARM_LEATHER_ARMOUR - && sub_type <= ARM_PLATE_MAIL) - || sub_type == ARM_GLOVES - || sub_type == ARM_BOOTS - || sub_type == ARM_SHIELD - || sub_type == ARM_LARGE_SHIELD - || sub_type == ARM_CRYSTAL_PLATE_MAIL - || (sub_type == ARM_HELMET - && (get_helmet_type(invitem) == THELM_HELM - || get_helmet_type(invitem) == THELM_HELMET))) - { - if (!quiet) - mpr("This armour doesn't fit on your body."); - - return (false); - } - } - - bool removedCloak = false; - int cloak = -1; - - if (slot == EQ_BODY_ARMOUR - && you.equip[EQ_CLOAK] != -1 && !cloak_is_being_removed()) - { - if (!item_cursed( you.inv[you.equip[EQ_CLOAK]] )) - { - cloak = you.equip[ EQ_CLOAK ]; - if (!takeoff_armour(you.equip[EQ_CLOAK])) - return (false); - - removedCloak = true; - } - else - { - if (!quiet) - mpr("Your cloak prevents you from wearing the armour."); - - return (false); - } - } - - if (slot == EQ_CLOAK && you.equip[EQ_CLOAK] != -1) - { - if (!takeoff_armour(you.equip[EQ_CLOAK])) - return (false); - } - - if (slot == EQ_HELMET && you.equip[EQ_HELMET] != -1) - { - if (!takeoff_armour(you.equip[EQ_HELMET])) - return (false); - } - - if (slot == EQ_GLOVES && you.equip[EQ_GLOVES] != -1) - { - if (!takeoff_armour(you.equip[EQ_GLOVES])) - return (false); - } - - if (slot == EQ_BOOTS && you.equip[EQ_BOOTS] != -1) - { - if (!takeoff_armour(you.equip[EQ_BOOTS])) - return (false); - } - - if (slot == EQ_SHIELD && you.equip[EQ_SHIELD] != -1) - { - if (!takeoff_armour(you.equip[EQ_SHIELD])) - return (false); - } - - if (slot == EQ_BODY_ARMOUR && you.equip[EQ_BODY_ARMOUR] != -1) - { - if (!takeoff_armour(you.equip[EQ_BODY_ARMOUR])) - return (false); - } - - you.turn_is_over = 1; - - int delay = property( you.inv[item], PARM_AC ); - - if (delay < 1) - delay = 1; - - if (delay) - start_delay( DELAY_ARMOUR_ON, delay, item ); - - if (removedCloak) - start_delay( DELAY_ARMOUR_ON, 1, cloak ); - - return (true); -} // do_end wear_armour() - -bool takeoff_armour(int item) -{ - if (you.inv[item].base_type != OBJ_ARMOUR) - { - mpr("You aren't wearing that!"); - return false; - } - - if (item_cursed( you.inv[item] )) - { - for (int loopy = EQ_CLOAK; loopy <= EQ_BODY_ARMOUR; loopy++) - { - if (item == you.equip[loopy]) - { - in_name(item, DESC_CAP_YOUR, info); - strcat(info, " is stuck to your body!"); - mpr(info); - return false; - } - } - } - - bool removedCloak = false; - int cloak = -1; - const equipment_type slot = get_armour_slot(you.inv[item]); - - if (slot == EQ_BODY_ARMOUR) - { - if (you.equip[EQ_CLOAK] != -1 && !cloak_is_being_removed()) - { - if (!item_cursed( you.inv[you.equip[EQ_CLOAK]] )) - { - cloak = you.equip[ EQ_CLOAK ]; - if (!takeoff_armour(you.equip[EQ_CLOAK])) - return (false); - - removedCloak = true; - } - else - { - mpr("Your cloak prevents you from removing the armour."); - return false; - } - } - - if (item != you.equip[EQ_BODY_ARMOUR]) - { - mpr("You aren't wearing that!"); - return false; - } - - // you.equip[EQ_BODY_ARMOUR] = -1; - } - else - { - switch (slot) - { - case EQ_SHIELD: - if (item != you.equip[EQ_SHIELD]) - { - mpr("You aren't wearing that!"); - return false; - } - break; - - case EQ_CLOAK: - if (item != you.equip[EQ_CLOAK]) - { - mpr("You aren't wearing that!"); - return false; - } - break; - - case EQ_HELMET: - if (item != you.equip[EQ_HELMET]) - { - mpr("You aren't wearing that!"); - return false; - } - break; - - case EQ_GLOVES: - if (item != you.equip[EQ_GLOVES]) - { - mpr("You aren't wearing that!"); - return false; - } - break; - - case EQ_BOOTS: - if (item != you.equip[EQ_BOOTS]) - { - mpr("You aren't wearing that!"); - return false; - } - break; - - default: - break; - } - } - - you.turn_is_over = 1; - - int delay = property( you.inv[item], PARM_AC ); - - if (delay < 1) - delay = 1; - - start_delay( DELAY_ARMOUR_OFF, delay, item ); - - if (removedCloak) - start_delay( DELAY_ARMOUR_ON, 1, cloak ); - - return true; -} // end takeoff_armour() - -void throw_anything(void) -{ - struct bolt beam; - int throw_slot; - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return; - } - else if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return; - } - - throw_slot = prompt_invent_item( "Throw which item?", OBJ_MISSILES ); - if (throw_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return; - } - - if (throw_slot == you.equip[EQ_WEAPON] - && (item_cursed( you.inv[you.equip[EQ_WEAPON]] ))) - { - mpr("That thing is stuck to your hand!"); - return; - } - else - { - for (int loopy = EQ_CLOAK; loopy <= EQ_AMULET; loopy++) - { - if (throw_slot == you.equip[loopy]) - { - mpr("You are wearing that object!"); - return; - } - } - } - - throw_it(beam, throw_slot); -} // end throw_anything() - -// Return index of first valid balanced throwing weapon or ENDOFPACK -static int try_finding_throwing_weapon( int sub_type ) -{ - int i; - - for (i = Options.fire_items_start; i < ENDOFPACK; i++) - { - // skip invalid objects, wielded object - if (!is_valid_item( you.inv[i] ) || you.equip[EQ_WEAPON] == i) - continue; - - // consider melee weapons that can also be thrown - if (you.inv[i].base_type == OBJ_WEAPONS - && you.inv[i].sub_type == sub_type) - { - break; - } - } - - return (i); -} - -// Return index of first missile of sub_type or ENDOFPACK -static int try_finding_missile( int sub_type ) -{ - int i; - - for (i = Options.fire_items_start; i < ENDOFPACK; i++) - { - // skip invalid objects - if (!is_valid_item( you.inv[i] )) - continue; - - // consider melee weapons that can also be thrown - if (you.inv[i].base_type == OBJ_MISSILES - && you.inv[i].sub_type == sub_type) - { - break; - } - } - - return (i); -} - -// Note: This is a simple implementation, not an efficient one. -- bwr -// -// Returns item index or ENDOFPACK if no item found for auto-firing -int get_fire_item_index( void ) -{ - int item = ENDOFPACK; - const int weapon = you.equip[ EQ_WEAPON ]; - - for (int i = 0; i < NUM_FIRE_TYPES; i++) - { - // look for next type on list... if found item is set != ENDOFPACK - switch (Options.fire_order[i]) - { - case FIRE_LAUNCHER: - // check if we have ammo for a wielded launcher: - if (weapon != -1 - && you.inv[ weapon ].base_type == OBJ_WEAPONS - && launches_things( you.inv[ weapon ].sub_type )) - { - int type_wanted = launched_by( you.inv[ weapon ].sub_type ); - item = try_finding_missile( type_wanted ); - } - break; - - case FIRE_DART: - item = try_finding_missile( MI_DART ); - break; - - case FIRE_STONE: - item = try_finding_missile( MI_STONE ); - break; - - case FIRE_DAGGER: - item = try_finding_throwing_weapon( WPN_DAGGER ); - break; - - case FIRE_SPEAR: - item = try_finding_throwing_weapon( WPN_SPEAR ); - break; - - case FIRE_HAND_AXE: - item = try_finding_throwing_weapon( WPN_HAND_AXE ); - break; - - case FIRE_CLUB: - item = try_finding_throwing_weapon( WPN_CLUB ); - break; - - case FIRE_NONE: - default: - break; - } - - // if successful break - if (item != ENDOFPACK) - break; - } - - // either item was found or is still ENDOFPACK for no item - return (item); -} - -void shoot_thing(void) -{ - struct bolt beam; // passed in by reference, but never used here - char str_pass[ ITEMNAME_SIZE ]; - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return; - } - - const int item = get_fire_item_index(); - - if (item == ENDOFPACK) - { - mpr("No suitable missiles."); - return; - } - - in_name( item, DESC_INVENTORY_EQUIP, str_pass ); - snprintf( info, INFO_SIZE, "Firing: %s", str_pass ); - mpr( info ); - - throw_it( beam, item ); -} // end shoot_thing() - -// throw_it - currently handles player throwing only. Monster -// throwing is handled in mstuff2:mons_throw() -// Note: If dummy_target is non-NULL, throw_it fakes a bolt and calls -// affect() on the monster's square. -// -// Return value is only relevant if dummy_target is non-NULL, and returns -// true if dummy_target is hit. -bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) -{ - struct dist thr; - char shoot_skill = 0; - - char wepClass, wepType; // ammo class and type - char lnchClass, lnchType; // launcher class and type - - int baseHit = 0, baseDam = 0; // from thrown or ammo - int ammoHitBonus = 0, ammoDamBonus = 0; // from thrown or ammo - int lnchHitBonus = 0, lnchDamBonus = 0; // special add from launcher - int exHitBonus = 0, exDamBonus = 0; // 'extra' bonus from skill/dex/str - int effSkill = 0; // effective launcher skill - int dice_mult = 100; - bool launched = false; // item is launched - bool thrown = false; // item is sensible thrown item - int slayDam = 0; - - if (dummy_target) - { - thr.isValid = true; - thr.isCancel = false; - thr.tx = dummy_target->x; - thr.ty = dummy_target->y; - } - else - { - mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT ); - message_current_target(); - direction( thr, DIR_NONE, TARG_ENEMY ); - } - - if (!thr.isValid) - { - if (thr.isCancel) - canned_msg(MSG_OK); - - return (false); - } - - // Must unwield before fire_beam() makes a copy in order to remove things - // like temporary branding. -- bwr - if (throw_2 == you.equip[EQ_WEAPON] && you.inv[throw_2].quantity == 1) - { - unwield_item( throw_2 ); - you.equip[EQ_WEAPON] = -1; - canned_msg( MSG_EMPTY_HANDED ); - } - - // Making a copy of the item: changed only for venom launchers - item_def item = you.inv[throw_2]; - item.quantity = 1; - item.slot = index_to_letter(item.link); - origin_set_unknown(item); - - char str_pass[ ITEMNAME_SIZE ]; - - if (you.conf) - { - thr.isTarget = true; - thr.tx = you.x_pos + random2(13) - 6; - thr.ty = you.y_pos + random2(13) - 6; - } - - // even though direction is allowed, we're throwing so we - // want to use tx, ty to make the missile fly to map edge. - pbolt.target_x = thr.tx; - pbolt.target_y = thr.ty; - - pbolt.flavour = BEAM_MISSILE; - // pbolt.range is set below - - switch (item.base_type) - { - case OBJ_WEAPONS: pbolt.type = SYM_WEAPON; break; - case OBJ_MISSILES: pbolt.type = SYM_MISSILE; break; - case OBJ_ARMOUR: pbolt.type = SYM_ARMOUR; break; - case OBJ_WANDS: pbolt.type = SYM_STICK; break; - case OBJ_FOOD: pbolt.type = SYM_CHUNK; break; - case OBJ_UNKNOWN_I: pbolt.type = SYM_BURST; break; - case OBJ_SCROLLS: pbolt.type = SYM_SCROLL; break; - case OBJ_JEWELLERY: pbolt.type = SYM_TRINKET; break; - case OBJ_POTIONS: pbolt.type = SYM_FLASK; break; - case OBJ_UNKNOWN_II: pbolt.type = SYM_ZAP; break; - case OBJ_BOOKS: pbolt.type = SYM_OBJECT; break; - // this does not seem right, but value was 11 {dlb} - // notice how the .type does not match the class -- hmmm... {dlb} - case OBJ_STAVES: pbolt.type = SYM_CHUNK; break; - } - - pbolt.source_x = you.x_pos; - pbolt.source_y = you.y_pos; - pbolt.colour = item.colour; - - item_name( item, DESC_PLAIN, str_pass ); - strcpy( pbolt.beam_name, str_pass ); - - pbolt.thrower = KILL_YOU_MISSILE; - pbolt.aux_source = NULL; - - // get the ammo/weapon type. Convenience. - wepClass = item.base_type; - wepType = item.sub_type; - - // get the launcher class,type. Convenience. - if (you.equip[EQ_WEAPON] < 0) - { - lnchClass = -1; - // set lnchType to 0 so the 'figure out if launched' - // code doesn't break - lnchType = 0; - } - else - { - lnchClass = you.inv[you.equip[EQ_WEAPON]].base_type; - lnchType = you.inv[you.equip[EQ_WEAPON]].sub_type; - } - - // baseHit and damage for generic objects - baseHit = you.strength - item_mass(item) / 10; - if (baseHit > 0) - baseHit = 0; - - baseDam = item_mass(item) / 100; - - // special: might be throwing generic weapon; - // use base wep. damage, w/ penalty - if (wepClass == OBJ_WEAPONS) - { - baseDam = property( item, PWPN_DAMAGE ) - 4; - if (baseDam < 0) - baseDam = 0; - } - - // figure out if we're thrown or launched - throw_type(lnchClass, lnchType, wepClass, wepType, launched, thrown); - - // extract launcher bonuses due to magic - if (launched) - { - lnchHitBonus = you.inv[you.equip[EQ_WEAPON]].plus; - lnchDamBonus = you.inv[you.equip[EQ_WEAPON]].plus2; - } - - // extract weapon/ammo bonuses due to magic - ammoHitBonus = item.plus; - ammoDamBonus = item.plus2; - - // CALCULATIONS FOR LAUNCHED WEAPONS - if (launched) - { - const item_def &launcher = you.inv[you.equip[EQ_WEAPON]]; - const int bow_brand = get_weapon_brand( launcher ); - const int ammo_brand = get_ammo_brand( item ); - const bool two_handed = (you.equip[EQ_SHIELD] == -1); - bool poisoned = (ammo_brand == SPMSL_POISONED - || ammo_brand == SPMSL_POISONED_II); - const int rc_skill = you.skills[SK_RANGED_COMBAT]; - - const int item_base_dam = property( item, PWPN_DAMAGE ); - const int lnch_base_dam = property( launcher, PWPN_DAMAGE ); - - const skill_type launcher_skill = range_skill( launcher ); - const int str_weight = weapon_str_weight( launcher ); - const int dex_weight = 10 - str_weight; - - int speed_base = 10 * property( launcher, PWPN_SPEED ); - int speed_min = 70; - int speed_stat = str_weight * you.strength + dex_weight * you.dex; - int speed = 100; - - baseHit = property( launcher, PWPN_HIT ); - baseDam = lnch_base_dam + random2(1 + item_base_dam); - - // Slings are terribly weakened otherwise - if (lnch_base_dam == 0) - baseDam = item_base_dam; - - if (launcher_skill == SK_BOWS) - speed_min = 60; - -#ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, - "Base hit == %d; Base damage == %d " - "(item %d + launcher %d)", - baseHit, baseDam, - item_base_dam, lnch_base_dam); -#endif - - // fix ammo damage bonus, since missiles only use inv_plus - ammoDamBonus = ammoHitBonus; - - // check for matches; dwarven,elven,orcish - if (!get_equip_race(you.inv[you.equip[EQ_WEAPON]]) == 0) - { - if (get_equip_race( you.inv[you.equip[EQ_WEAPON]] ) - == get_equip_race( item )) - { - baseHit += 1; - baseDam += 1; - - // elves with elven bows - if (get_equip_race(you.inv[you.equip[EQ_WEAPON]]) - == ISFLAG_ELVEN - && player_genus(GENPC_ELVEN)) - { - baseHit += 1; - } - } - } - - // for all launched weapons, maximum effective specific skill - // is twice throwing skill. This models the fact that no matter - // how 'good' you are with a bow, if you know nothing about - // trajectories you're going to be a damn poor bowman. Ditto - // for crossbows and slings. - - // [dshaligram] Throwing now two parts launcher skill, one part - // ranged combat. Removed the old model which is... silly. - - shoot_skill = you.skills[launcher_skill]; - effSkill = (shoot_skill * 2 + rc_skill) / 3; - - // FIXME: Use actual body size - if (!two_handed && hands_reqd(launcher, SIZE_MEDIUM) == HANDS_HALF) - { - speed_base = (speed_base * 3 + 1) / 2; - speed_min = (speed_min * 3 + 1) / 2; - } - - speed = speed_base - 4 * shoot_skill * speed_stat / 250; - if (speed < speed_min) - speed = speed_min; - - if (bow_brand == SPWPN_SPEED) - { - // Speed nerf as per 4.1 - speed = 2 * speed / 3; - } -#ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Final launcher speed: %d", speed); -#endif - - you.time_taken = speed * you.time_taken / 100; - - // effSkill = you.skills[SK_RANGED_COMBAT] * 2 + 1; - // effSkill = (shoot_skill > effSkill) ? effSkill : shoot_skill; - - // [dshaligram] Improving missile weapons: - // - Remove the strength/enchantment cap where you need to be strong - // to exploit a launcher bonus. - // - Add on launcher and missile pluses to extra damage. - - // [dshaligram] This can get large... - exDamBonus = lnchDamBonus + random2(1 + ammoDamBonus); - exDamBonus = exDamBonus > 0? random2(exDamBonus + 1) - : -random2(-exDamBonus + 1); - exHitBonus = lnchHitBonus > 0? random2(lnchHitBonus + 1) - : -random2(-lnchHitBonus + 1); - - // removed 2 random2(2)s from each of the learning curves, but - // left slings because they're hard enough to develop without - // a good source of shot in the dungeon. - switch (launcher_skill) - { - case SK_SLINGS: - { - // Slings are really easy to learn because they're not - // really all that good, and its harder to get ammo anyways. - exercise(SK_SLINGS, 1 + random2avg(3, 2)); - baseHit += 0; - exHitBonus += (effSkill * 3) / 2; - - // strength is good if you're using a nice sling. - int strbonus = (10 * (you.strength - 10)) / 9; - strbonus = (strbonus * (2 * baseDam + ammoDamBonus)) / 20; - - // cap - if (strbonus > lnchDamBonus + 1) - strbonus = lnchDamBonus + 1; - - exDamBonus += strbonus; - // add skill for slings.. helps to find those vulnerable spots - dice_mult = dice_mult * (14 + random2(1 + effSkill)) / 14; - - // now kill the launcher damage bonus - if (lnchDamBonus > 0) - lnchDamBonus = 0; - break; - } - // blowguns take a _very_ steady hand; a lot of the bonus - // comes from dexterity. (Dex bonus here as well as below) - case SK_DARTS: - baseHit -= 2; - exercise(SK_DARTS, (coinflip()? 2 : 1)); - exHitBonus += (effSkill * 3) / 2 + you.dex / 2; - - // no extra damage for blowguns - // exDamBonus = 0; - - // now kill the launcher damage and ammo bonuses - if (lnchDamBonus > 0) - lnchDamBonus = 0; - if (ammoDamBonus > 0) - ammoDamBonus = 0; - break; - - case SK_BOWS: - { - baseHit -= 3; - exercise(SK_BOWS, (coinflip()? 2 : 1)); - exHitBonus += (effSkill * 2); - - // strength is good if you're using a nice bow - int strbonus = (10 * (you.strength - 10)) / 4; - strbonus = (strbonus * (2 * baseDam + ammoDamBonus)) / 20; - - // cap; reduced this cap, because we don't want to allow - // the extremely-strong to quadruple the enchantment bonus. - if (strbonus > lnchDamBonus + 1) - strbonus = lnchDamBonus + 1; - - exDamBonus += strbonus; - - // add in skill for bows.. help you to find those vulnerable spots. - // exDamBonus += effSkill; - - dice_mult = dice_mult * (17 + random2(1 + effSkill)) / 17; - - // now kill the launcher damage bonus - if (lnchDamBonus > 0) - lnchDamBonus = 0; - break; - } - // Crossbows are easy for unskilled people. - - case SK_CROSSBOWS: - exercise(SK_CROSSBOWS, (coinflip()? 2 : 1)); - baseHit++; - exHitBonus += (3 * effSkill) / 2 + 6; - // exDamBonus += effSkill * 2 / 3 + 4; - - dice_mult = dice_mult * (22 + random2(1 + effSkill)) / 22; - - if (lnchType == WPN_HAND_CROSSBOW) - { - exHitBonus -= 2; - dice_mult = dice_mult * 26 / 30; - } - break; - - default: - break; - } - - // all launched weapons have a slight chance of improving - // throwing skill - if (coinflip()) - exercise(SK_RANGED_COMBAT, 1); - - // all launched weapons get a minor tohit boost from throwing skill. - exHitBonus += you.skills[SK_RANGED_COMBAT] / 5; - - if (bow_brand == SPWPN_VORPAL) - { - // Vorpal brand adds 25% damage bonus. - dice_mult = dice_mult * 125 / 100; - } - - // special cases for flame, frost, poison, etc. - // check for venom brand (usually only available for blowguns) - if (bow_brand == SPWPN_VENOM && ammo_brand == SPMSL_NORMAL) - { - // poison brand the ammo - set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED ); - item_name( item, DESC_PLAIN, str_pass ); - strcpy( pbolt.beam_name, str_pass ); - } - - // Note that bow_brand is known since the bow is equiped. - if ((bow_brand == SPWPN_FLAME || ammo_brand == SPMSL_FLAME) - && ammo_brand != SPMSL_ICE && bow_brand != SPWPN_FROST) - { - // [dshaligram] Branded arrows are much stronger. - dice_mult = dice_mult * 150 / 100; - - pbolt.flavour = BEAM_FIRE; - strcpy(pbolt.beam_name, "bolt of "); - - if (poisoned) - strcat(pbolt.beam_name, "poison "); - - strcat(pbolt.beam_name, "flame"); - pbolt.colour = RED; - pbolt.type = SYM_BOLT; - pbolt.thrower = KILL_YOU_MISSILE; - pbolt.aux_source = NULL; - - // ammo known if we can't attribute it to the bow - if (bow_brand != SPWPN_FLAME) - { - set_ident_flags( item, ISFLAG_KNOW_TYPE ); - set_ident_flags( you.inv[throw_2], ISFLAG_KNOW_TYPE ); - } - } - - if ((bow_brand == SPWPN_FROST || ammo_brand == SPMSL_ICE) - && ammo_brand != SPMSL_FLAME && bow_brand != SPWPN_FLAME) - { - // [dshaligram] Branded arrows are much stronger. - dice_mult = dice_mult * 150 / 100; - - pbolt.flavour = BEAM_COLD; - strcpy(pbolt.beam_name, "bolt of "); - - if (poisoned) - strcat(pbolt.beam_name, "poison "); - - strcat(pbolt.beam_name, "frost"); - pbolt.colour = WHITE; - pbolt.type = SYM_BOLT; - pbolt.thrower = KILL_YOU_MISSILE; - pbolt.aux_source = NULL; - - // ammo known if we can't attribute it to the bow - if (bow_brand != SPWPN_FROST) - { - set_ident_flags( item, ISFLAG_KNOW_TYPE ); - set_ident_flags( you.inv[throw_2], ISFLAG_KNOW_TYPE ); - } - } - - // ammo known if it cancels the effect of the bow - if ((bow_brand == SPWPN_FLAME && ammo_brand == SPMSL_ICE) - || (bow_brand == SPWPN_FROST && ammo_brand == SPMSL_FLAME)) - { - set_ident_flags( item, ISFLAG_KNOW_TYPE ); - set_ident_flags( you.inv[throw_2], ISFLAG_KNOW_TYPE ); - } - - /* the chief advantage here is the extra damage this does - * against susceptible creatures */ - - /* Note: weapons & ammo of eg fire are not cumulative - * ammo of fire and weapons of frost don't work together, - * and vice versa */ - - // ID check - if (!item_ident( you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES ) - && random2(100) < shoot_skill) - { - set_ident_flags(you.inv[you.equip[EQ_WEAPON]], ISFLAG_KNOW_PLUSES); - - strcpy(info, "You are wielding "); - in_name(you.equip[EQ_WEAPON], DESC_NOCAP_A, str_pass); - strcat(info, str_pass); - strcat(info, "."); - mpr(info); - - more(); - you.wield_change = true; - } - } - - // CALCULATIONS FOR THROWN WEAPONS - if (thrown) - { - baseHit = 0; - - // since darts/rocks are missiles, they only use inv_plus - if (wepClass == OBJ_MISSILES) - ammoDamBonus = ammoHitBonus; - - // all weapons that use 'throwing' go here.. - if (wepClass == OBJ_WEAPONS - || (wepClass == OBJ_MISSILES && wepType == MI_STONE)) - { - // elves with elven weapons - if (get_equip_race(item) == ISFLAG_ELVEN - && player_genus(GENPC_ELVEN)) - baseHit += 1; - - // give an appropriate 'tohit' - - // hand axes and clubs are -5 - // daggers are +1 - // spears are -1 - // rocks are 0 - if (wepClass == OBJ_WEAPONS) - { - switch (wepType) - { - case WPN_DAGGER: - baseHit += 1; - break; - case WPN_SPEAR: - baseHit -= 1; - break; - default: - baseHit -= 5; - break; - } - } - - exHitBonus = you.skills[SK_RANGED_COMBAT] * 2; - - baseDam = property( item, PWPN_DAMAGE ); - exDamBonus = - (10 * (you.skills[SK_RANGED_COMBAT] / 2 + you.strength - 10)) / 12; - - // now, exDamBonus is a multiplier. The full multiplier - // is applied to base damage, but only a third is applied - // to the magical modifier. - exDamBonus = (exDamBonus * (3 * baseDam + ammoDamBonus)) / 30; - } - - if (wepClass == OBJ_MISSILES && wepType == MI_DART) - { - // give an appropriate 'tohit' & damage - baseHit = 2; - baseDam = property( item, PWPN_DAMAGE ); - - exHitBonus = you.skills[SK_DARTS] * 2; - exHitBonus += (you.skills[SK_RANGED_COMBAT] * 2) / 3; - exDamBonus = you.skills[SK_DARTS] / 3; - exDamBonus += you.skills[SK_RANGED_COMBAT] / 5; - - // exercise skills - exercise(SK_DARTS, 1 + random2avg(3, 2)); - } - - if (wepClass == OBJ_MISSILES && wepType == MI_NEEDLE) - { - // Throwing needles is now seriously frowned upon; it's difficult - // to grip a fiddly little needle, and not penalising it cheapens - // blowguns. - exHitBonus -= (30 - you.skills[SK_DARTS]) / 3; - baseHit -= (30 - you.skills[SK_DARTS]) / 4; -#ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Needle base hit = %d, exHitBonus = %d", - baseHit, exHitBonus); -#endif - } - - // exercise skill - if (coinflip()) - exercise(SK_RANGED_COMBAT, 1); - } - - // range, dexterity bonus, possible skill increase for silly throwing - if (thrown || launched) - { - if (wepType == MI_LARGE_ROCK) - { - pbolt.range = 1 + random2( you.strength / 5 ); - if (pbolt.range > 9) - pbolt.range = 9; - - pbolt.rangeMax = pbolt.range; - } - else - { - pbolt.range = 9; - pbolt.rangeMax = 9; - - exHitBonus += you.dex / 2; - - // slaying bonuses - if (!(launched && wepType == MI_NEEDLE)) - { - slayDam = slaying_bonus(PWPN_DAMAGE); - slayDam = slayDam < 0? -random2(1 - slayDam) - : random2(1 + slayDam); - } - - exHitBonus += slaying_bonus(PWPN_HIT); - } - } - else - { - // range based on mass & strength, between 1 and 9 - pbolt.range = you.strength - item_mass(item) / 10 + 3; - if (pbolt.range < 1) - pbolt.range = 1; - - if (pbolt.range > 9) - pbolt.range = 9; - - // set max range equal to range for this - pbolt.rangeMax = pbolt.range; - - if (one_chance_in(20)) - exercise(SK_RANGED_COMBAT, 1); - - exHitBonus = you.dex / 4; - } - - // FINALIZE tohit and damage - if (exHitBonus >= 0) - pbolt.hit = baseHit + random2avg(exHitBonus + 1, 2); - else - pbolt.hit = baseHit - random2avg(0 - (exHitBonus - 1), 2); - - if (exDamBonus >= 0) - pbolt.damage = dice_def( 1, baseDam + random2(exDamBonus + 1) ); - else - pbolt.damage = dice_def( 1, baseDam - random2(0 - (exDamBonus - 1)) ); - - pbolt.damage.size = dice_mult * pbolt.damage.size / 100; - pbolt.damage.size += slayDam; - - scale_dice( pbolt.damage ); - - // only add bonuses if we're throwing something sensible - if (thrown || launched || wepClass == OBJ_WEAPONS) - { - pbolt.hit += ammoHitBonus + lnchHitBonus; - pbolt.damage.size += ammoDamBonus + lnchDamBonus; - } - -#if DEBUG_DIAGNOSTICS - mprf( MSGCH_DIAGNOSTICS, - "H:%d+%d;a%dl%d. D:%d+%d;a%dl%d -> %d,%dd%d", - baseHit, exHitBonus, ammoHitBonus, lnchHitBonus, - baseDam, exDamBonus, ammoDamBonus, lnchDamBonus, - pbolt.hit, pbolt.damage.num, pbolt.damage.size ); -#endif - - // create message - if (launched) - strcpy(info, "You shoot "); - else - strcpy(info, "You throw "); - - item_name( item, DESC_NOCAP_A, str_pass ); - - strcat(info, str_pass); - strcat(info, "."); - mpr(info); - - // ensure we're firing a 'missile'-type beam - pbolt.is_beam = false; - pbolt.is_tracer = false; - - // mark this item as thrown if it's a missile, so that we'll pick it up - // when we walk over it. - if (wepClass == OBJ_MISSILES || wepClass == OBJ_WEAPONS) - item.flags |= ISFLAG_THROWN; - - bool hit = false; - // using copy, since the launched item might be differect (venom blowgun) - if (dummy_target) - hit = (affect( pbolt, dummy_target->x, dummy_target->y ) != 0); - else - { - fire_beam( pbolt, &item ); - dec_inv_item_quantity( throw_2, 1 ); - } - - // throwing and blowguns are silent - if (launched && lnchType != WPN_BLOWGUN) - noisy( 6, you.x_pos, you.y_pos ); - - // but any monster nearby can see that something has been thrown: - alert_nearby_monsters(); - - you.turn_is_over = 1; - - return (hit); -} // end throw_it() - -bool puton_item(int item_slot, bool prompt_finger) -{ - if (item_slot == you.equip[EQ_LEFT_RING] - || item_slot == you.equip[EQ_RIGHT_RING] - || item_slot == you.equip[EQ_AMULET]) - { - mpr("You've already put that on!"); - return (true); - } - - if (item_slot == you.equip[EQ_WEAPON]) - { - mpr("You are wielding that object."); - return (false); - } - - if (you.inv[item_slot].base_type != OBJ_JEWELLERY) - { - //jmf: let's not take our inferiority complex out on players, eh? :-p - //mpr("You're sadly mistaken if you consider that jewellery.") - mpr("You can only put on jewellery."); - return (false); - } - - bool is_amulet = (you.inv[item_slot].sub_type >= AMU_RAGE); - - if (!is_amulet) // ie it's a ring - { - if (you.equip[EQ_GLOVES] != -1 - && item_cursed( you.inv[you.equip[EQ_GLOVES]] )) - { - mpr("You can't take your gloves off to put on a ring!"); - return (false); - } - - if (you.inv[item_slot].base_type == OBJ_JEWELLERY - && you.equip[EQ_LEFT_RING] != -1 - && you.equip[EQ_RIGHT_RING] != -1) - { - // and you are trying to wear body you.equip. - mpr("You've already put a ring on each hand."); - return (false); - } - } - else if (you.equip[EQ_AMULET] != -1) - { - strcpy(info, "You are already wearing an amulet."); - - if (one_chance_in(20)) - { - strcat(info, " And I must say it looks quite fetching."); - } - - mpr(info); - return (false); - } - - int hand_used = 0; - - if (you.equip[EQ_LEFT_RING] != -1) - hand_used = 1; - - if (you.equip[EQ_RIGHT_RING] != -1) - hand_used = 0; - - if (is_amulet) - hand_used = 2; - else if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] == -1) - { - if (prompt_finger) - { - mpr("Put on which hand (l or r)?", MSGCH_PROMPT); - - int keyin = get_ch(); - - if (keyin == 'l') - hand_used = 0; - else if (keyin == 'r') - hand_used = 1; - else if (keyin == ESCAPE) - return (false); - else - { - mpr("You don't have such a hand!"); - return (false); - } - } - else - { - // First ring goes on left hand if we're choosing automatically. - hand_used = 0; - } - } - - you.equip[ EQ_LEFT_RING + hand_used ] = item_slot; - - int ident = ID_TRIED_TYPE; - - switch (you.inv[item_slot].sub_type) - { - case RING_FIRE: - case RING_HUNGER: - case RING_ICE: - case RING_LIFE_PROTECTION: - case RING_POISON_RESISTANCE: - case RING_PROTECTION_FROM_COLD: - case RING_PROTECTION_FROM_FIRE: - case RING_PROTECTION_FROM_MAGIC: - case RING_SUSTAIN_ABILITIES: - case RING_SUSTENANCE: - case RING_SLAYING: - case RING_SEE_INVISIBLE: - case RING_TELEPORTATION: - case RING_WIZARDRY: - case RING_REGENERATION: - break; - - case RING_PROTECTION: - you.redraw_armour_class = 1; - if (you.inv[item_slot].plus != 0) - ident = ID_KNOWN_TYPE; - break; - - case RING_INVISIBILITY: - if (!you.invis) - { - mpr("You become transparent for a moment."); - ident = ID_KNOWN_TYPE; - } - break; - - case RING_EVASION: - you.redraw_evasion = 1; - if (you.inv[item_slot].plus != 0) - ident = ID_KNOWN_TYPE; - break; - - case RING_STRENGTH: - modify_stat(STAT_STRENGTH, you.inv[item_slot].plus, true); - if (you.inv[item_slot].plus != 0) - ident = ID_KNOWN_TYPE; - break; - - case RING_DEXTERITY: - modify_stat(STAT_DEXTERITY, you.inv[item_slot].plus, true); - if (you.inv[item_slot].plus != 0) - ident = ID_KNOWN_TYPE; - break; - - case RING_INTELLIGENCE: - modify_stat(STAT_INTELLIGENCE, you.inv[item_slot].plus, true); - if (you.inv[item_slot].plus != 0) - ident = ID_KNOWN_TYPE; - break; - - case RING_MAGICAL_POWER: - calc_mp(); - ident = ID_KNOWN_TYPE; - break; - - case RING_LEVITATION: - mpr("You feel buoyant."); - ident = ID_KNOWN_TYPE; - break; - - case RING_TELEPORT_CONTROL: - // XXX: is this safe or should we make it a function -- bwr - you.attribute[ATTR_CONTROL_TELEPORT]++; - break; - - case AMU_RAGE: - mpr("You feel a brief urge to hack something to bits."); - ident = ID_KNOWN_TYPE; - break; - } - - you.turn_is_over = 1; - - // Artefacts have completely different appearance than base types - // so we don't allow them to make the base types known - if (is_random_artefact( you.inv[item_slot] )) - use_randart(item_slot); - else - { - set_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type, ident ); - } - - if (ident == ID_KNOWN_TYPE) - set_ident_flags( you.inv[item_slot], ISFLAG_EQ_JEWELLERY_MASK ); - - if (item_cursed( you.inv[item_slot] )) - { - snprintf( info, INFO_SIZE, - "Oops, that %s feels deathly cold.", (is_amulet) ? "amulet" - : "ring" ); - mpr(info); - } - - // cursed or not, we know that since we've put the ring on - set_ident_flags( you.inv[item_slot], ISFLAG_KNOW_CURSE ); - - char str_pass[ ITEMNAME_SIZE ]; - in_name( item_slot, DESC_INVENTORY_EQUIP, str_pass ); - mpr( str_pass ); - - return (true); -} - -bool puton_ring(int slot, bool prompt_finger) -{ - int item_slot; - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return (false); - } - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return (false); - } - - if (slot != -1) - item_slot = slot; - else - item_slot = prompt_invent_item( "Put on which piece of jewellery?", - OBJ_JEWELLERY ); - - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return (false); - } - - return puton_item(item_slot, prompt_finger); -} // end puton_ring() - -bool remove_ring(int slot) -{ - int hand_used = 10; - int ring_wear_2; - char str_pass[ ITEMNAME_SIZE ]; - - if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] == -1 - && you.equip[EQ_AMULET] == -1) - { - mpr("You aren't wearing any rings or amulets."); - return (false); - } - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return (false); - } - - if (you.equip[EQ_GLOVES] != -1 - && item_cursed( you.inv[you.equip[EQ_GLOVES]] ) - && you.equip[EQ_AMULET] == -1) - { - mpr("You can't take your gloves off to remove any rings!"); - return (false); - } - - if (you.equip[EQ_LEFT_RING] != -1 && you.equip[EQ_RIGHT_RING] == -1 - && you.equip[EQ_AMULET] == -1) - { - hand_used = 0; - } - - if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] != -1 - && you.equip[EQ_AMULET] == -1) - { - hand_used = 1; - } - - if (you.equip[EQ_LEFT_RING] == -1 && you.equip[EQ_RIGHT_RING] == -1 - && you.equip[EQ_AMULET] != -1) - { - hand_used = 2; - } - - if (hand_used == 10) - { - int equipn = - slot == -1? prompt_invent_item( "Remove which piece of jewellery?", - OBJ_JEWELLERY ) - : slot; - - if (equipn == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return (false); - } - - if (you.inv[equipn].base_type != OBJ_JEWELLERY) - { - mpr("That isn't a piece of jewellery."); - return (false); - } - - if (you.equip[EQ_LEFT_RING] == equipn) - hand_used = 0; - else if (you.equip[EQ_RIGHT_RING] == equipn) - hand_used = 1; - else if (you.equip[EQ_AMULET] == equipn) - hand_used = 2; - else - { - mpr("You aren't wearing that."); - return (false); - } - } - - if (you.equip[EQ_GLOVES] != -1 - && item_cursed( you.inv[you.equip[EQ_GLOVES]] ) - && (hand_used == 0 || hand_used == 1)) - { - mpr("You can't take your gloves off to remove any rings!"); - return (false); - } - - if (you.equip[hand_used + 7] == -1) - { - mpr("I don't think you really meant that."); - return (false); - } - - if (item_cursed( you.inv[you.equip[hand_used + 7]] )) - { - mpr("It's stuck to you!"); - - set_ident_flags( you.inv[you.equip[hand_used + 7]], ISFLAG_KNOW_CURSE ); - return (false); - } - - strcpy(info, "You remove "); - in_name(you.equip[hand_used + 7], DESC_NOCAP_YOUR, str_pass); - - strcat(info, str_pass); - strcat(info, "."); - mpr(info); - - // I'll still use ring_wear_2 here. - ring_wear_2 = you.equip[hand_used + 7]; - - switch (you.inv[ring_wear_2].sub_type) - { - case RING_FIRE: - case RING_HUNGER: - case RING_ICE: - case RING_LIFE_PROTECTION: - case RING_POISON_RESISTANCE: - case RING_PROTECTION_FROM_COLD: - case RING_PROTECTION_FROM_FIRE: - case RING_PROTECTION_FROM_MAGIC: - case RING_REGENERATION: - case RING_SEE_INVISIBLE: - case RING_SLAYING: - case RING_SUSTAIN_ABILITIES: - case RING_SUSTENANCE: - case RING_TELEPORTATION: - case RING_WIZARDRY: - break; - - case RING_PROTECTION: - you.redraw_armour_class = 1; - break; - - case RING_EVASION: - you.redraw_evasion = 1; - break; - - case RING_STRENGTH: - modify_stat(STAT_STRENGTH, -you.inv[ring_wear_2].plus, true); - break; - - case RING_DEXTERITY: - modify_stat(STAT_DEXTERITY, -you.inv[ring_wear_2].plus, true); - break; - - case RING_INTELLIGENCE: - modify_stat(STAT_INTELLIGENCE, -you.inv[ring_wear_2].plus, true); - break; - - case RING_INVISIBILITY: - // removing this ring effectively cancels all invisibility {dlb} - if (you.invis) - you.invis = 1; - break; - - case RING_LEVITATION: - // removing this ring effectively cancels all levitation {dlb} - if (you.levitation) - you.levitation = 1; - break; - - case RING_MAGICAL_POWER: - // dec_max_mp(9); - break; - - case RING_TELEPORT_CONTROL: - you.attribute[ATTR_CONTROL_TELEPORT]--; - break; - } - - if (is_random_artefact( you.inv[ring_wear_2] )) - unuse_randart(ring_wear_2); - - you.equip[hand_used + 7] = -1; - - // must occur after ring is removed -- bwr - calc_mp(); - - you.turn_is_over = 1; - - return (true); -} // end remove_ring() - -void zap_wand(void) -{ - struct bolt beam; - struct dist zap_wand; - int item_slot; - char str_pass[ ITEMNAME_SIZE ]; - - // Unless the character knows the type of the wand, the targeting - // system will default to cycling through all monsters. -- bwr - int targ_mode = TARG_ANY; - - beam.obvious_effect = false; - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return; - } - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return; - } - - item_slot = prompt_invent_item( "Zap which item?", OBJ_WANDS ); - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return; - } - - if (you.inv[item_slot].base_type != OBJ_WANDS - || you.inv[item_slot].plus < 1) - { - canned_msg(MSG_NOTHING_HAPPENS); - you.turn_is_over = 1; - return; - } - - if (item_ident( you.inv[item_slot], ISFLAG_KNOW_TYPE )) - { - if (you.inv[item_slot].sub_type == WAND_HASTING - || you.inv[item_slot].sub_type == WAND_HEALING - || you.inv[item_slot].sub_type == WAND_INVISIBILITY) - { - targ_mode = TARG_FRIEND; - } - else - { - targ_mode = TARG_ENEMY; - } - } - - mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT ); - message_current_target(); - - direction( zap_wand, DIR_NONE, targ_mode ); - - if (!zap_wand.isValid) - { - if (zap_wand.isCancel) - canned_msg(MSG_OK); - return; - } - - if (you.conf) - { - zap_wand.tx = you.x_pos + random2(13) - 6; - zap_wand.ty = you.y_pos + random2(13) - 6; - } - - // blargh! blech! this is just begging to be a problem ... - // not to mention work-around after work-around as wands are - // added, removed, or altered {dlb}: - char type_zapped = you.inv[item_slot].sub_type; - - if (type_zapped == WAND_ENSLAVEMENT) - type_zapped = ZAP_ENSLAVEMENT; - - if (type_zapped == WAND_DRAINING) - type_zapped = ZAP_NEGATIVE_ENERGY; - - if (type_zapped == WAND_DISINTEGRATION) - type_zapped = ZAP_DISINTEGRATION; - - if (type_zapped == WAND_RANDOM_EFFECTS) - { - type_zapped = random2(16); - if (one_chance_in(20)) - type_zapped = ZAP_NEGATIVE_ENERGY; - if (one_chance_in(17)) - type_zapped = ZAP_ENSLAVEMENT; - } - - beam.source_x = you.x_pos; - beam.source_y = you.y_pos; - beam.target_x = zap_wand.tx; - beam.target_y = zap_wand.ty; - - zapping( type_zapped, 30 + roll_dice(2, you.skills[SK_EVOCATIONS]), beam ); - - if (beam.obvious_effect == 1 || you.inv[item_slot].sub_type == WAND_FIREBALL) - { - if (get_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type ) != ID_KNOWN_TYPE) - { - set_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type, ID_KNOWN_TYPE ); - - in_name(item_slot, DESC_INVENTORY_EQUIP, str_pass); - mpr( str_pass ); - - // update if wielding - if (you.equip[EQ_WEAPON] == item_slot) - you.wield_change = true; - } - } - else - { - set_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type, ID_TRIED_TYPE ); - } - - you.inv[item_slot].plus--; - - if (get_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type ) == ID_KNOWN_TYPE - && (item_ident( you.inv[item_slot], ISFLAG_KNOW_PLUSES ) - || you.skills[SK_EVOCATIONS] > 5 + random2(15))) - { - if (!item_ident( you.inv[item_slot], ISFLAG_KNOW_PLUSES )) - { - mpr("Your skill with magical items lets you calculate the power of this device..."); - } - - snprintf( info, INFO_SIZE, "This wand has %d charge%s left.", - you.inv[item_slot].plus, - (you.inv[item_slot].plus == 1) ? "" : "s" ); - - mpr(info); - set_ident_flags( you.inv[item_slot], ISFLAG_KNOW_PLUSES ); - } - - exercise( SK_EVOCATIONS, 1 ); - alert_nearby_monsters(); - - you.turn_is_over = 1; -} // end zap_wand() - -void drink(void) -{ - int item_slot; - - if (you.is_undead == US_UNDEAD) - { - mpr("You can't drink."); - return; - } - - if (grd[you.x_pos][you.y_pos] == DNGN_BLUE_FOUNTAIN - || grd[you.x_pos][you.y_pos] == DNGN_SPARKLING_FOUNTAIN) - { - if (drink_fountain()) - return; - } - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return; - } - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return; - } - - item_slot = prompt_invent_item( "Drink which item?", OBJ_POTIONS ); - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return; - } - - if (you.inv[item_slot].base_type != OBJ_POTIONS) - { - mpr("You can't drink that!"); - return; - } - - if (potion_effect( you.inv[item_slot].sub_type, 40 )) - { - set_ident_flags( you.inv[item_slot], ISFLAG_IDENT_MASK ); - - set_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type, ID_KNOWN_TYPE ); - } - else - { - set_ident_type( you.inv[item_slot].base_type, - you.inv[item_slot].sub_type, ID_TRIED_TYPE ); - } - - dec_inv_item_quantity( item_slot, 1 ); - you.turn_is_over = 1; - - lessen_hunger(40, true); -} // end drink() - -bool drink_fountain(void) -{ - bool gone_dry = false; - int temp_rand; // for probability determinations {dlb} - int fountain_effect = POT_WATER; // for fountain effects {dlb} - - switch (grd[you.x_pos][you.y_pos]) - { - case DNGN_BLUE_FOUNTAIN: - if (!yesno("Drink from the fountain?")) - return false; - - mpr("You drink the pure, clear water."); - break; - - case DNGN_SPARKLING_FOUNTAIN: - if (!yesno("Drink from the sparkling fountain?")) - return false; - - mpr("You drink the sparkling water."); - break; - } - - if (grd[you.x_pos][you.y_pos] == DNGN_SPARKLING_FOUNTAIN) - { - temp_rand = random2(4500); - - fountain_effect = ((temp_rand > 2399) ? POT_WATER : // 46.7% - (temp_rand > 2183) ? POT_DECAY : // 4.8% - (temp_rand > 2003) ? POT_MUTATION : // 4.0% - (temp_rand > 1823) ? POT_HEALING : // 4.0% - (temp_rand > 1643) ? POT_HEAL_WOUNDS :// 4.0% - (temp_rand > 1463) ? POT_SPEED : // 4.0% - (temp_rand > 1283) ? POT_MIGHT : // 4.0% - (temp_rand > 1139) ? POT_DEGENERATION ://3.2% - (temp_rand > 1019) ? POT_LEVITATION :// 2.7% - (temp_rand > 899) ? POT_POISON : // 2.7% - (temp_rand > 779) ? POT_SLOWING : // 2.7% - (temp_rand > 659) ? POT_PARALYSIS : // 2.7% - (temp_rand > 539) ? POT_CONFUSION : // 2.7% - (temp_rand > 419) ? POT_INVISIBILITY :// 2.7% - (temp_rand > 329) ? POT_MAGIC : // 2.0% - (temp_rand > 239) ? POT_RESTORE_ABILITIES :// 2.0% - (temp_rand > 149) ? POT_STRONG_POISON ://2.0% - (temp_rand > 59) ? POT_BERSERK_RAGE : //2.0% - (temp_rand > 39) ? POT_GAIN_STRENGTH : //0.4% - (temp_rand > 19) ? POT_GAIN_DEXTERITY //0.4% - : POT_GAIN_INTELLIGENCE);//0.4% - } - - potion_effect(fountain_effect, 100); - - switch (grd[you.x_pos][you.y_pos]) - { - case DNGN_BLUE_FOUNTAIN: - if (one_chance_in(20)) - gone_dry = true; - break; - - case DNGN_SPARKLING_FOUNTAIN: - if (one_chance_in(10)) - { - gone_dry = true; - break; - } - else - { - temp_rand = random2(50); - - // you won't know it (yet) - if (temp_rand > 40) // 18% probability - grd[you.x_pos][you.y_pos] = DNGN_BLUE_FOUNTAIN; - } - break; - } - - if (gone_dry) - { - mpr("The fountain dries up!"); - if (grd[you.x_pos][you.y_pos] == DNGN_BLUE_FOUNTAIN) - grd[you.x_pos][you.y_pos] = DNGN_DRY_FOUNTAIN_I; - else if (grd[you.x_pos][you.y_pos] == DNGN_SPARKLING_FOUNTAIN) - grd[you.x_pos][you.y_pos] = DNGN_DRY_FOUNTAIN_II; - } - - you.turn_is_over = 1; - return true; -} // end drink_fountain() - -static bool affix_weapon_enchantment( void ) -{ - const int wpn = you.equip[ EQ_WEAPON ]; - bool success = true; - - struct bolt beam; - - if (wpn == -1 || !you.duration[ DUR_WEAPON_BRAND ]) - return (false); - - switch (get_weapon_brand( you.inv[wpn] )) - { - case SPWPN_VORPAL: - if (get_vorpal_type( you.inv[wpn] ) != DVORP_CRUSHING) - { - strcat(info, "'s sharpness seems more permanent."); - } - else - { - strcat(info, "'s heaviness feels very stable."); - } - mpr(info); - break; - - case SPWPN_FLAMING: - strcat(info," is engulfed in an explosion of flames!"); - mpr(info); - - beam.type = SYM_BURST; - beam.damage = dice_def( 3, 10 ); - beam.flavour = 2; - beam.target_x = you.x_pos; - beam.target_y = you.y_pos; - strcpy(beam.beam_name, "fiery explosion"); - beam.colour = RED; - beam.thrower = KILL_YOU; - beam.aux_source = "a fiery explosion"; - beam.ex_size = 2; - beam.is_tracer = false; - beam.is_explosion = true; - - explosion(beam); - break; - - case SPWPN_FREEZING: - strcat(info," glows brilliantly blue for a moment."); - mpr(info); - cast_refrigeration(60); - break; - - case SPWPN_DRAINING: - strcat(info," thirsts for the lives of mortals!"); - mpr(info); - drain_exp(); - break; - - case SPWPN_VENOM: - strcat(info, " seems more permanently poisoned."); - mpr(info); - cast_toxic_radiance(); - break; - - case SPWPN_DISTORTION: - // [dshaligram] Attempting to fix a distortion brand gets you a free - // distortion effect, and no permabranding. Sorry, them's the breaks. - strcat(info, " twongs alarmingly."); - mpr(info); - - // from unwield_item - miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, - "a distortion effect" ); - success = false; - break; - - default: - success = false; - break; - } - - if (success) - you.duration[DUR_WEAPON_BRAND] = 0; - - return (success); -} - -bool enchant_weapon( int which_stat, bool quiet ) -{ - const int wpn = you.equip[ EQ_WEAPON ]; - bool affected = true; - int enchant_level; - char str_pass[ ITEMNAME_SIZE ]; - - if (wpn == -1 - || (you.inv[ wpn ].base_type != OBJ_WEAPONS - && you.inv[ wpn ].base_type != OBJ_MISSILES)) - { - if (!quiet) - canned_msg(MSG_NOTHING_HAPPENS); - - return (false); - } - - you.wield_change = true; - - // missiles only have one stat - if (you.inv[ wpn ].base_type == OBJ_MISSILES) - which_stat = ENCHANT_TO_HIT; - - if (which_stat == ENCHANT_TO_HIT) - enchant_level = you.inv[ wpn ].plus; - else - enchant_level = you.inv[ wpn ].plus2; - - // artefacts can't be enchanted, but scrolls still remove curses - if (you.inv[ wpn ].base_type == OBJ_WEAPONS - && (is_fixed_artefact( you.inv[wpn] ) - || is_random_artefact( you.inv[wpn] ))) - { - affected = false; - } - - if (enchant_level >= 4 && random2(9) < enchant_level) - { - affected = false; - } - - // if it isn't affected by the enchantment, it will still - // be uncursed: - if (!affected) - { - if (item_cursed( you.inv[you.equip[EQ_WEAPON]] )) - { - if (!quiet) - { - in_name(you.equip[EQ_WEAPON], DESC_CAP_YOUR, str_pass); - strcpy(info, str_pass); - strcat(info, " glows silver for a moment."); - mpr(info); - } - - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); - - return (true); - } - else - { - if (!quiet) - canned_msg(MSG_NOTHING_HAPPENS); - - return (false); - } - } - - // vVvVv This is *here* (as opposed to lower down) for a reason! - in_name( wpn, DESC_CAP_YOUR, str_pass ); - strcpy( info, str_pass ); - - do_uncurse_item( you.inv[ wpn ] ); - - if (you.inv[ wpn ].base_type == OBJ_WEAPONS) - { - if (which_stat == ENCHANT_TO_DAM) - { - you.inv[ wpn ].plus2++; - - if (!quiet) - { - strcat(info, " glows red for a moment."); - mpr(info); - } - } - else if (which_stat == ENCHANT_TO_HIT) - { - you.inv[ wpn ].plus++; - - if (!quiet) - { - strcat(info, " glows green for a moment."); - mpr(info); - } - } - } - else if (you.inv[ wpn ].base_type == OBJ_MISSILES) - { - strcat( info, (you.inv[ wpn ].quantity > 1) ? " glow" - : " glows" ); - - strcat(info, " red for a moment."); - - you.inv[ wpn ].plus++; - } - - return (true); -} - -static bool enchant_armour( void ) -{ - // NOTE: It is assumed that armour which changes in this way does - // not change into a form of armour with a different evasion modifier. - char str_pass[ ITEMNAME_SIZE ]; - int nthing = you.equip[EQ_BODY_ARMOUR]; - - if (nthing != -1 - && (you.inv[nthing].sub_type == ARM_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_ICE_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_STEAM_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_MOTTLED_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_STORM_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_GOLD_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_SWAMP_DRAGON_HIDE - || you.inv[nthing].sub_type == ARM_TROLL_HIDE)) - { - in_name( you.equip[EQ_BODY_ARMOUR], DESC_CAP_YOUR, str_pass ); - strcpy(info, str_pass); - strcat(info, " glows purple and changes!"); - mpr(info); - - you.redraw_armour_class = 1; - - hide2armour(you.inv[nthing]); - return (true); - } - - // pick random piece of armour - int count = 0; - int affected_slot = EQ_WEAPON; - - for (int i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++) - { - if (you.equip[i] != -1) - { - count++; - if (one_chance_in( count )) - affected_slot = i; - } - } - - // no armour == no enchantment - if (affected_slot == EQ_WEAPON) - { - canned_msg(MSG_NOTHING_HAPPENS); - return (false); - } - - bool affected = true; - item_def &item = you.inv[you.equip[ affected_slot ]]; - - if (is_random_artefact( item ) - || ((item.sub_type >= ARM_CLOAK && item.sub_type <= ARM_BOOTS) - && item.plus >= 2) - || ((item.sub_type == ARM_SHIELD - || item.sub_type == ARM_BUCKLER - || item.sub_type == ARM_LARGE_SHIELD) - && item.plus >= 2) - || (item.plus >= 3 && random2(8) < item.plus)) - { - affected = false; - } - - // even if not affected, it may be uncursed. - if (!affected) - { - if (item_cursed( item )) - { - item_name(item, DESC_CAP_YOUR, str_pass); - strcpy(info, str_pass); - strcat(info, " glows silver for a moment."); - mpr(info); - - do_uncurse_item( item ); - return (true); - } - else - { - canned_msg( MSG_NOTHING_HAPPENS ); - return (false); - } - } - - // vVvVv This is *here* for a reason! - item_name(item, DESC_CAP_YOUR, str_pass); - strcpy(info, str_pass); - strcat(info, " glows green for a moment."); - mpr(info); - - item.plus++; - - do_uncurse_item( item ); - you.redraw_armour_class = 1; - return (true); -} - -static void handle_read_book( int item_slot ) -{ - int spell, spell_index, nthing; - - if (you.inv[item_slot].sub_type == BOOK_DESTRUCTION) - { - if (silenced(you.x_pos, you.y_pos)) - { - mpr("This book does not work if you cannot read it aloud!"); - return; - } - - tome_of_power(item_slot); - return; - } - else if (you.inv[item_slot].sub_type == BOOK_MANUAL) - { - skill_manual(item_slot); - return; - } - else - { - // Spellbook - spell = read_book( you.inv[item_slot], RBOOK_READ_SPELL ); - } - - if (spell < 'a' || spell > 'h') //jmf: was 'g', but 8=h - { - mesclr( true ); - return; - } - - spell_index = letter_to_index( spell ); - - nthing = which_spell_in_book(you.inv[item_slot].sub_type, spell_index); - if (nthing == SPELL_NO_SPELL) - { - mesclr( true ); - return; - } - - describe_spell( nthing ); - redraw_screen(); - - mesclr( true ); - return; -} - -void read_scroll(void) -{ - int affected = 0; - int i; - int count; - int nthing; - struct bolt beam; - char str_pass[ ITEMNAME_SIZE ]; - - // added: scroll effects are never tracers. - beam.is_tracer = false; - - if (you.berserker) - { - canned_msg(MSG_TOO_BERSERK); - return; - } - - if (inv_count() < 1) - { - canned_msg(MSG_NOTHING_CARRIED); - return; - } - - int item_slot = prompt_invent_item( "Read which item?", OBJ_SCROLLS ); - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return; - } - - if (you.inv[item_slot].base_type != OBJ_BOOKS - && you.inv[item_slot].base_type != OBJ_SCROLLS) - { - mpr("You can't read that!"); - return; - } - - // here we try to read a book {dlb}: - if (you.inv[item_slot].base_type == OBJ_BOOKS) - { - handle_read_book( item_slot ); - return; - } - - if (silenced(you.x_pos, you.y_pos)) - { - mpr("Magic scrolls do not work when you're silenced!"); - return; - } - - // ok - now we FINALLY get to read a scroll !!! {dlb} - you.turn_is_over = 1; - - // imperfect vision prevents players from reading actual content {dlb}: - if (you.mutation[MUT_BLURRY_VISION] - && random2(5) < you.mutation[MUT_BLURRY_VISION]) - { - mpr((you.mutation[MUT_BLURRY_VISION] == 3 && one_chance_in(3)) - ? "This scroll appears to be blank." - : "The writing blurs in front of your eyes."); - return; - } - - // decrement and handle inventory if any scroll other than paper {dlb}: - const int scroll_type = you.inv[item_slot].sub_type; - if (scroll_type != SCR_PAPER) - { - mpr("As you read the scroll, it crumbles to dust."); - // Actual removal of scroll done afterwards. -- bwr - } - - // scrolls of paper are also exempted from this handling {dlb}: - if (scroll_type != SCR_PAPER) - { - if (you.conf) - { - random_uselessness(random2(9), item_slot); - dec_inv_item_quantity( item_slot, 1 ); - return; - } - - if (!you.skills[SK_SPELLCASTING]) - exercise(SK_SPELLCASTING, (coinflip()? 2 : 1)); - } - - bool id_the_scroll = true; // to prevent unnecessary repetition - - // it is the exception, not the rule, that - // the scroll will not be identified {dlb}: - switch (scroll_type) - { - case SCR_PAPER: - // remember paper scrolls handled as special case above, too: - mpr("This scroll appears to be blank."); - break; - - case SCR_RANDOM_USELESSNESS: - random_uselessness(random2(9), item_slot); - id_the_scroll = false; - break; - - case SCR_BLINKING: - blink(); - break; - - case SCR_TELEPORTATION: - you_teleport(); - break; - - case SCR_REMOVE_CURSE: - if (!remove_curse(false)) - id_the_scroll = false; - break; - - case SCR_DETECT_CURSE: - if (!detect_curse(false)) - id_the_scroll = false; - break; - - case SCR_ACQUIREMENT: - acquirement(OBJ_RANDOM, AQ_SCROLL); - break; - - case SCR_FEAR: - if (!mass_enchantment(ENCH_FEAR, 1000, MHITYOU)) - id_the_scroll = false; - break; - - case SCR_NOISE: - mpr("You hear a loud clanging noise!"); - noisy( 25, you.x_pos, you.y_pos ); - break; - - case SCR_SUMMONING: - if (create_monster( MONS_ABOMINATION_SMALL, ENCH_ABJ_VI, BEH_FRIENDLY, - you.x_pos, you.y_pos, you.pet_target, 250 ) != -1) - { - mpr("A horrible Thing appears!"); - } - break; - - case SCR_FORGETFULNESS: - mpr("You feel momentarily disoriented."); - if (!wearing_amulet(AMU_CLARITY)) - forget_map(50 + random2(50)); - break; - - case SCR_MAGIC_MAPPING: - if (you.level_type == LEVEL_LABYRINTH - || you.level_type == LEVEL_ABYSS) - { - mpr("You feel momentarily disoriented."); - id_the_scroll = false; - } - else - { - mpr("You feel aware of your surroundings."); - magic_mapping(50, 90 + random2(11)); - } - break; - - case SCR_TORMENT: - torment( you.x_pos, you.y_pos ); - - // is only naughty if you know you're doing it - if (get_ident_type( OBJ_SCROLLS, SCR_TORMENT ) == ID_KNOWN_TYPE) - { - did_god_conduct(DID_UNHOLY, 10); - } - break; - - case SCR_IMMOLATION: - mpr("The scroll explodes in your hands!"); - - beam.type = SYM_BURST; - beam.damage = dice_def( 3, 10 ); - // unsure about this // BEAM_EXPLOSION instead? {dlb} - beam.flavour = BEAM_FIRE; - beam.target_x = you.x_pos; - beam.target_y = you.y_pos; - strcpy(beam.beam_name, "fiery explosion"); - beam.colour = RED; - // your explosion, (not someone else's explosion) - beam.thrower = KILL_YOU; - beam.aux_source = "reading a scroll of immolation"; - beam.ex_size = 2; - beam.is_explosion = true; - - explosion(beam); - break; - - case SCR_IDENTIFY: - set_ident_flags( you.inv[item_slot], ISFLAG_IDENT_MASK ); - - // important {dlb} - set_ident_type( OBJ_SCROLLS, SCR_IDENTIFY, ID_KNOWN_TYPE ); - - identify(-1); - you.wield_change = true; - break; - - case SCR_CURSE_WEAPON: - nthing = you.equip[EQ_WEAPON]; - - if (nthing == -1 - || you.inv[nthing].base_type != OBJ_WEAPONS - || item_cursed( you.inv[nthing] )) - { - canned_msg(MSG_NOTHING_HAPPENS); - id_the_scroll = false; - } - else - { - in_name( nthing, DESC_CAP_YOUR, str_pass ); - strcpy(info, str_pass); - strcat(info, " glows black for a moment."); - mpr(info); - - do_curse_item( you.inv[nthing] ); - you.wield_change = true; - } - break; - - // everything [in the switch] below this line is a nightmare {dlb}: - case SCR_ENCHANT_WEAPON_I: - id_the_scroll = enchant_weapon( ENCHANT_TO_HIT ); - break; - - case SCR_ENCHANT_WEAPON_II: - id_the_scroll = enchant_weapon( ENCHANT_TO_DAM ); - break; - - case SCR_ENCHANT_WEAPON_III: - if (you.equip[ EQ_WEAPON ] != -1) - { - if (!affix_weapon_enchantment()) - { - in_name( you.equip[EQ_WEAPON], DESC_CAP_YOUR, str_pass ); - strcpy( info, str_pass ); - strcat( info, " glows bright yellow for a while." ); - mpr( info ); - - enchant_weapon( ENCHANT_TO_HIT, true ); - - if (coinflip()) - enchant_weapon( ENCHANT_TO_HIT, true ); - - enchant_weapon( ENCHANT_TO_DAM, true ); - - if (coinflip()) - enchant_weapon( ENCHANT_TO_DAM, true ); - - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); - } - } - else - { - canned_msg(MSG_NOTHING_HAPPENS); - id_the_scroll = false; - } - break; - - case SCR_VORPALISE_WEAPON: - nthing = you.equip[EQ_WEAPON]; - if (nthing == -1 - || you.inv[ nthing ].base_type != OBJ_WEAPONS - || (you.inv[ nthing ].base_type == OBJ_WEAPONS - && (is_fixed_artefact( you.inv[ nthing ] ) - || is_random_artefact( you.inv[ nthing ] ) - || you.inv[nthing].sub_type == WPN_BLOWGUN))) - { - canned_msg(MSG_NOTHING_HAPPENS); - break; - } - - in_name(nthing, DESC_CAP_YOUR, str_pass); - - strcpy(info, str_pass); - strcat(info, " emits a brilliant flash of light!"); - mpr(info); - - alert_nearby_monsters(); - - if (get_weapon_brand( you.inv[nthing] ) != SPWPN_NORMAL) - { - mpr("You feel strangely frustrated."); - break; - } - - you.wield_change = true; - set_item_ego_type( you.inv[nthing], OBJ_WEAPONS, SPWPN_VORPAL ); - break; - - case SCR_RECHARGING: - nthing = you.equip[EQ_WEAPON]; - - if (nthing != -1 - && !is_random_artefact( you.inv[nthing] ) - && !is_fixed_artefact( you.inv[nthing] ) - && get_weapon_brand( you.inv[nthing] ) == SPWPN_ELECTROCUTION) - { - id_the_scroll = !enchant_weapon( ENCHANT_TO_DAM ); - break; - } - - if (!recharge_wand()) - { - canned_msg(MSG_NOTHING_HAPPENS); - id_the_scroll = false; - } - break; - - case SCR_ENCHANT_ARMOUR: - id_the_scroll = enchant_armour(); - break; - - case SCR_CURSE_ARMOUR: - // make sure there's something to curse first - count = 0; - affected = EQ_WEAPON; - for (i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++) - { - if (you.equip[i] != -1 && !item_cursed( you.inv[you.equip[i]] )) - { - count++; - if (one_chance_in( count )) - affected = i; - } - } - - if (affected == EQ_WEAPON) - { - canned_msg(MSG_NOTHING_HAPPENS); - id_the_scroll = false; - break; - } - - // make the name _before_ we curse it - in_name( you.equip[affected], DESC_CAP_YOUR, str_pass ); - do_curse_item( you.inv[you.equip[affected]] ); - - strcpy(info, str_pass); - strcat(info, " glows black for a moment."); - mpr(info); - break; - } // end switch - - // finally, destroy and identify the scroll - if (scroll_type != SCR_PAPER) - { - dec_inv_item_quantity( item_slot, 1 ); - } - - set_ident_type( OBJ_SCROLLS, scroll_type, - (id_the_scroll) ? ID_KNOWN_TYPE : ID_TRIED_TYPE ); -} // end read_scroll() - -void original_name(void) -{ - int item_slot = prompt_invent_item( "Examine which item?", -1 ); - if (item_slot == PROMPT_ABORT) - { - canned_msg( MSG_OK ); - return; - } - - describe_item( you.inv[item_slot] ); - redraw_screen(); -} // end original_name() - -void use_randart(unsigned char item_wield_2) -{ - ASSERT( is_random_artefact( you.inv[ item_wield_2 ] ) ); - - FixedVector< char, RA_PROPERTIES > proprt; - randart_wpn_properties( you.inv[item_wield_2], proprt ); - - if (proprt[RAP_AC]) - you.redraw_armour_class = 1; - - if (proprt[RAP_EVASION]) - you.redraw_evasion = 1; - - // modify ability scores - modify_stat( STAT_STRENGTH, proprt[RAP_STRENGTH], true ); - modify_stat( STAT_INTELLIGENCE, proprt[RAP_INTELLIGENCE], true ); - modify_stat( STAT_DEXTERITY, proprt[RAP_DEXTERITY], true ); - - if (proprt[RAP_NOISES]) - you.special_wield = 50 + proprt[RAP_NOISES]; -} |