From 4199cb903775df050465148d7ade49daf09fac39 Mon Sep 17 00:00:00 2001 From: dolorous Date: Sun, 23 Mar 2008 21:46:25 +0000 Subject: Add a weapon enchantment blessing that will enchant a monster's weapon by two points (either this or armor enchantment blessing can occur, with 5% rarity). Whether to-hit or to-damage is chosen is random. Split handling of weapon enchantment into enchant_weapon() for the generic item routines, and handle_enchant_weapon() for the player-specific routines. Furthermore, make enchant_weapon() and enchant_armour() more similar in terms of structure. Also, in bless_follower(), store the blessing description and monster name in std::strings instead of const char*'s. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3839 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/effects.cc | 6 +- crawl-ref/source/invent.cc | 2 +- crawl-ref/source/item_use.cc | 128 +++++++++++++++++++++---------------------- crawl-ref/source/item_use.h | 3 +- crawl-ref/source/itemprop.cc | 29 +++++++++- crawl-ref/source/itemprop.h | 1 + crawl-ref/source/religion.cc | 74 ++++++++++++++++++------- 7 files changed, 151 insertions(+), 92 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index fddc3d2efd..257e58e237 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -1715,18 +1715,16 @@ bool recharge_wand(int item_slot) item_def &wand = you.inv[ item_slot ]; if (wand.base_type == OBJ_WEAPONS - && !is_random_artefact( wand ) - && !is_fixed_artefact( wand ) && get_weapon_brand( wand ) == SPWPN_ELECTROCUTION) { // might fail because of already high enchantment - if (enchant_weapon( ENCHANT_TO_DAM, false, item_slot )) + if ( enchant_weapon( ENCHANT_TO_DAM, false, wand )) { you.wield_change = true; if (!item_ident(wand, ISFLAG_KNOW_TYPE)) set_ident_flags(wand, ISFLAG_KNOW_TYPE); - + return (true); } return (false); diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index bee34b1cb7..cb7d0c78ac 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -757,7 +757,7 @@ static bool item_class_selected(const item_def &i, int selector) return (itype == OBJ_MISSILES || itype == OBJ_WEAPONS); case OBJ_WEAPONS: case OSEL_WIELD: - return (itype == OBJ_WEAPONS || itype == OBJ_STAVES + return (itype == OBJ_WEAPONS || itype == OBJ_STAVES || itype == OBJ_MISCELLANY); case OSEL_MEMORISE: return (itype == OBJ_BOOKS && i.sub_type != BOOK_MANUAL diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index f818edac69..d13c85b591 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -81,6 +81,8 @@ #include "xom.h" static bool drink_fountain(); +static bool handle_enchant_weapon( enchant_stat_type which_stat, + bool quiet = false, int item_slot = -1 ); static bool handle_enchant_armour( int item_slot = -1 ); static int _fire_prompt_for_item(std::string& err); @@ -3812,64 +3814,39 @@ static bool affix_weapon_enchantment() return (success); } -bool enchant_weapon( enchant_stat_type which_stat, bool quiet, int wpn ) +bool enchant_weapon( enchant_stat_type which_stat, bool quiet, item_def &wpn ) { - if (wpn == -1) - wpn = you.equip[ EQ_WEAPON ]; - - bool affected = true; - int enchant_level; - - if (wpn == -1 - || (you.inv[ wpn ].base_type != OBJ_WEAPONS - && you.inv[ wpn ].base_type != OBJ_MISSILES)) + // cannot be enchanted nor uncursed + if (!is_enchantable_weapon(wpn, true)) { if (!quiet) - canned_msg(MSG_NOTHING_HAPPENS); + canned_msg( MSG_NOTHING_HAPPENS ); return (false); } - item_def& item = you.inv[wpn]; - - you.wield_change = true; + const bool is_cursed = item_cursed(wpn); // missiles only have one stat - if (item.base_type == OBJ_MISSILES) + if (wpn.base_type == OBJ_MISSILES) which_stat = ENCHANT_TO_HIT; - if (which_stat == ENCHANT_TO_HIT) - enchant_level = item.plus; - else - enchant_level = item.plus2; - - // artefacts can't be enchanted, but scrolls still remove curses - if (item.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; - } + int enchant_level = (which_stat == ENCHANT_TO_HIT) ? wpn.plus + : wpn.plus2; - // if it isn't affected by the enchantment, it will still - // be uncursed. - if (!affected) + // Even if not affected, it may be uncursed. + if (!is_enchantable_weapon(wpn, false) + || enchant_level >= 4 && random2(9) < enchant_level) { - if (item_cursed(item)) + if (is_cursed) { if (!quiet) { mprf("%s glows silver for a moment.", - item.name(DESC_CAP_YOUR).c_str()); + wpn.name(DESC_CAP_YOUR).c_str()); } - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); - + do_uncurse_item( wpn ); return (true); } else @@ -3881,43 +3858,62 @@ bool enchant_weapon( enchant_stat_type which_stat, bool quiet, int wpn ) } } - // Get the item name now before the enchantment changes it. - std::string iname = item.name(DESC_CAP_YOUR); - - do_uncurse_item( item ); + // get item name now before changing enchantment + std::string iname = wpn.name(DESC_CAP_YOUR); - if (item.base_type == OBJ_WEAPONS) + if (wpn.base_type == OBJ_WEAPONS) { - if (which_stat == ENCHANT_TO_DAM) + if (which_stat == ENCHANT_TO_HIT) { - item.plus2++; - if (!quiet) - mprf("%s glows red for a moment.", iname.c_str()); + mprf("%s glows green for a moment.", iname.c_str()); + + wpn.plus++; } - else if (which_stat == ENCHANT_TO_HIT) + else { - item.plus++; - if (!quiet) - mprf("%s glows green for a moment.", iname.c_str()); + mprf("%s glows red for a moment.", iname.c_str()); + + wpn.plus2++; } } - else if (item.base_type == OBJ_MISSILES) + else if (wpn.base_type == OBJ_MISSILES) { if (!quiet) { mprf("%s %s red for a moment.", iname.c_str(), - item.quantity > 1 ? "glow" : "glows"); + wpn.quantity > 1 ? "glow" : "glows"); } - item.plus++; + wpn.plus++; } + if (is_cursed) + do_uncurse_item( wpn ); + xom_is_stimulated(16); return (true); } +static bool handle_enchant_weapon( enchant_stat_type which_stat, + bool quiet, int item_slot ) +{ + if (item_slot == -1) + item_slot = you.equip[ EQ_WEAPON ]; + + if (item_slot == -1) + return (false); + + item_def& wpn(you.inv[item_slot]); + + bool result = enchant_weapon(which_stat, quiet, wpn); + + you.wield_change = true; + + return result; +} + bool enchant_armour( int &ac_change, bool quiet, item_def &arm ) { ac_change = 0; @@ -3927,10 +3923,11 @@ bool enchant_armour( int &ac_change, bool quiet, item_def &arm ) { if (!quiet) canned_msg( MSG_NOTHING_HAPPENS ); + return (false); } - bool is_cursed = item_cursed(arm); + const bool is_cursed = item_cursed(arm); // Turn hides into mails where applicable. // NOTE: It is assumed that armour which changes in this way does @@ -3973,6 +3970,7 @@ bool enchant_armour( int &ac_change, bool quiet, item_def &arm ) { if (!quiet) canned_msg( MSG_NOTHING_HAPPENS ); + return (false); } } @@ -4000,7 +3998,7 @@ static bool handle_enchant_armour( int item_slot ) item_slot = prompt_invent_item( "Enchant which item?", MT_INVLIST, OSEL_ENCH_ARM, true, true, false ); - if (item_slot == PROMPT_ABORT) + if (item_slot == -1) { canned_msg( MSG_OK ); return (false); @@ -4353,11 +4351,11 @@ void read_scroll( int slot ) // everything [in the switch] below this line is a nightmare {dlb}: case SCR_ENCHANT_WEAPON_I: - id_the_scroll = enchant_weapon( ENCHANT_TO_HIT ); + id_the_scroll = handle_enchant_weapon( ENCHANT_TO_HIT ); break; case SCR_ENCHANT_WEAPON_II: - id_the_scroll = enchant_weapon( ENCHANT_TO_DAM ); + id_the_scroll = handle_enchant_weapon( ENCHANT_TO_DAM ); break; case SCR_ENCHANT_WEAPON_III: @@ -4372,17 +4370,17 @@ void read_scroll( int slot ) mprf("%s glows bright yellow for a while.", iname.c_str() ); - enchant_weapon( ENCHANT_TO_HIT, true ); + do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); + + handle_enchant_weapon( ENCHANT_TO_HIT, true ); if (coinflip()) - enchant_weapon( ENCHANT_TO_HIT, true ); + handle_enchant_weapon( ENCHANT_TO_HIT, true ); - enchant_weapon( ENCHANT_TO_DAM, true ); + handle_enchant_weapon( ENCHANT_TO_DAM, true ); if (coinflip()) - enchant_weapon( ENCHANT_TO_DAM, true ); - - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); + handle_enchant_weapon( ENCHANT_TO_DAM, true ); } } else diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h index 1c79a93ecc..997f84b741 100644 --- a/crawl-ref/source/item_use.h +++ b/crawl-ref/source/item_use.h @@ -160,8 +160,7 @@ void use_randart(item_def &item); bool puton_item(int slot, bool prompt_finger = true); -bool enchant_weapon( enchant_stat_type which_stat, bool quiet = false, - int wpn = -1 ); +bool enchant_weapon( enchant_stat_type which_stat, bool quiet, item_def &wpn ); bool enchant_armour( int &ac_change, bool quiet, item_def &arm ); bool throw_it(bolt &pbolt, int throw_2, bool teleport=false, int acc_bonus=0, diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index 9db56d82d7..14851779d4 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -1291,6 +1291,33 @@ bool item_is_rechargable(const item_def &it, bool known) && (!known || item_type_known(it)) ); } +bool is_enchantable_weapon(const item_def &wpn, bool uncurse) +{ + if (wpn.base_type != OBJ_WEAPONS && wpn.base_type != OBJ_MISSILES) + return (false); + + // only equipped items should be affected +// if (!item_is_equipped(wpn)) +// return (false); + + // artefacts cannot be enchanted (missiles can't be artefacts) + if (wpn.base_type == OBJ_WEAPONS + && (is_fixed_artefact( wpn ) + || is_random_artefact( wpn ))) + { + return (uncurse && item_cursed( wpn )); // ?EW may uncurse artefacts + } + + // Nor can highly enchanted items (missiles only have one stat) + if ( wpn.plus >= 9 || + (wpn.base_type == OBJ_WEAPONS && wpn.plus2 >= 9) ) + { + return (uncurse && item_cursed( wpn )); // ?EW may uncurse items + } + + return (true); +} + bool is_enchantable_armour(const item_def &arm, bool uncurse) { if (arm.base_type != OBJ_ARMOUR) @@ -1312,7 +1339,7 @@ bool is_enchantable_armour(const item_def &arm, bool uncurse) && (arm.sub_type >= ARM_CLOAK && arm.sub_type <= ARM_BOOTS || is_shield(arm)) ) { - return (uncurse && item_cursed( arm )); // ?EA may uncurse item + return (uncurse && item_cursed( arm )); // ?EA may uncurse items } return (true); diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h index da16b46a38..8f42cb6a19 100644 --- a/crawl-ref/source/itemprop.h +++ b/crawl-ref/source/itemprop.h @@ -632,6 +632,7 @@ bool check_armour_size( const item_def &item, size_type size ); bool check_armour_shape( const item_def &item, bool quiet ); bool item_is_rechargable(const item_def &it, bool known = false); +bool is_enchantable_weapon(const item_def &wpn, bool uncurse); bool is_enchantable_armour(const item_def &arm, bool uncurse); // weapon functions: diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index fd2cf18989..aa44ff1bc2 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -775,6 +775,21 @@ static bool blessing_priesthood(monsters* mon) return false; } +static bool blessing_wpn(monsters *mon) +{ + // Pick a monster's weapon. + const int weapon = mon->inv[MSLOT_WEAPON]; + + if (weapon == NON_ITEM) + return false; + + item_def& wpn(mitm[weapon]); + + // And enchant or uncurse it. + return enchant_weapon((coinflip()) ? ENCHANT_TO_HIT + : ENCHANT_TO_DAM, true, wpn); +} + static bool blessing_ac(monsters* mon) { // Pick either a monster's armour or its shield. @@ -796,7 +811,7 @@ static bool blessing_ac(monsters* mon) int ac_change; - // And enchant it. + // And enchant or uncurse it. return enchant_armour(ac_change, true, arm); } @@ -852,10 +867,10 @@ void bless_follower(god_type god, mon = &menv[monster]; } - const char *blessed = (follower && !mons_near(follower)) - ? "your follower" - : mon->name(DESC_NOCAP_THE).c_str(); - const char *result; + std::string blessed = (follower && !mons_near(follower)) + ? "your follower" + : mon->name(DESC_NOCAP_THE).c_str(); + std::string result; int chance = random2(20); @@ -869,23 +884,43 @@ void bless_follower(god_type god, } } - // Enchant a monster's armour or shield by one or two points, or at - // least uncurse it, if possible. The message doesn't make a - // distinction. + // Enchant a monster's weapon or armour/shield by one or two points, + // or at least uncurse it, if possible. if (chance <= 1) { - bool ac_effect = blessing_ac(mon); + bool affected; - if (!ac_effect || coinflip()) + if (coinflip()) { - if (blessing_ac(mon)) - ac_effect = true; - } + affected = blessing_wpn(mon); + + if (!affected || coinflip()) + { + if (blessing_wpn(mon)) + affected = true; + } - if (ac_effect) + if (affected) + { + result = "extra attack power"; + goto blessing_done; + } + } + else { - result = "extra defence"; - goto blessing_done; + affected = blessing_ac(mon); + + if (!affected || coinflip()) + { + if (blessing_ac(mon)) + affected = true; + } + + if (affected) + { + result = "extra defence"; + goto blessing_done; + } } } @@ -921,7 +956,8 @@ void bless_follower(god_type god, } blessing_done: - snprintf(info, INFO_SIZE, " blesses %s with %s.", blessed, result); + snprintf(info, INFO_SIZE, " blesses %s with %s.", blessed.c_str(), + result.c_str()); simple_god_message(info); } @@ -3761,8 +3797,8 @@ static bool bless_weapon( god_type god, int brand, int colour ) you.inv[wpn].colour = colour; do_uncurse_item( you.inv[wpn] ); - enchant_weapon( ENCHANT_TO_HIT, true ); - enchant_weapon( ENCHANT_TO_DAM, true ); + enchant_weapon( ENCHANT_TO_HIT, true, you.inv[wpn] ); + enchant_weapon( ENCHANT_TO_DAM, true, you.inv[wpn] ); you.wield_change = true; you.num_gifts[god]++; -- cgit v1.2.3-54-g00ecf