From 2d1dc73ba81562198242670c328146d3f13695c6 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Fri, 3 Apr 2009 17:06:22 +0000 Subject: * Allow fleeing monster to push past higher ranked monsters of the same type. * Allow quivering of wielded missiles (stones for Sandblast etc.) and wielded weapons of returning if your throwing skill is > 0. * Add stairs/gates/shops to the 'V' command, mostly for the convenience of the easy travel feature. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9574 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/beam.cc | 5 +- crawl-ref/source/command.cc | 1 - crawl-ref/source/dat/descript/skills.txt | 3 +- crawl-ref/source/directn.cc | 83 +++++++++++++++++++++++++++++--- crawl-ref/source/item_use.cc | 2 +- crawl-ref/source/itemprop.cc | 3 ++ crawl-ref/source/menu.cc | 35 ++++++++++++-- crawl-ref/source/menu.h | 12 +++++ crawl-ref/source/mon-util.cc | 25 +++++----- crawl-ref/source/mon-util.h | 3 +- crawl-ref/source/monstuff.cc | 3 +- crawl-ref/source/quiver.cc | 28 ++++++++--- crawl-ref/source/stash.cc | 14 +++--- 13 files changed, 170 insertions(+), 47 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 605c07b749..dae307097d 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4956,12 +4956,11 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon) return (MON_OTHER); } - if (mon->add_ench(ENCH_CHARM)) + if (!mon->has_ench(ENCH_CHARM)) { - // FIXME: Put in an exception for fungi, plants and other - // things you won't notice becoming charmed. if (simple_monster_message(mon, " is charmed.")) obvious_effect = true; + mon->add_ench(ENCH_CHARM); } return (MON_AFFECTED); diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 6bcb35072f..6014528aae 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -1371,7 +1371,6 @@ static bool _do_description(std::string key, std::string type, if (thing_created != NON_ITEM && (type == "item" || type == "spell")) { - char name[80]; strncpy(name, key.c_str(), sizeof(name)); if (get_item_by_name(&mitm[thing_created], name, OBJ_WEAPONS)) diff --git a/crawl-ref/source/dat/descript/skills.txt b/crawl-ref/source/dat/descript/skills.txt index d3a00884ad..44fb34a4e4 100644 --- a/crawl-ref/source/dat/descript/skills.txt +++ b/crawl-ref/source/dat/descript/skills.txt @@ -278,5 +278,6 @@ Evocations Evocations is all about using magical items like wands, decks or other uncommon objects. The higher your skill, the more likely is a -positive outcome when evoking items. +positive outcome when evoking items. Also, high skill may let you determine +the amount of charges a zapped wand has left. %%%% diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 605192bf47..4926bffab3 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -457,10 +457,14 @@ void full_describe_view() { std::vector list_mons; std::vector list_items; + std::vector list_features; // Grab all items known (or thought) to be in the stashes in view. for (radius_iterator ri(you.pos(), LOS_RADIUS); ri; ++ri) { + if (grid_stair_direction(grd(*ri)) != CMD_NO_CMD) + list_features.push_back(*ri); + const monsters *mon = monster_at(*ri); const bool unknown_mimic = (mon && mons_is_unknown_mimic(mon)); @@ -506,9 +510,9 @@ void full_describe_view() for (unsigned int i = 0; i < mons.size(); i++) list_mons.push_back(mons[i].m_mon); - if (list_mons.empty() && list_items.empty()) + if (list_mons.empty() && list_items.empty() && list_features.empty()) { - mprf("Neither monsters nor items are visible."); + mprf("No monsters, items or features are visible."); return; } @@ -518,9 +522,23 @@ void full_describe_view() desc_menu.set_highlighter(NULL); // FIXME: Need different title for the opposite toggle: // "Visible Monsters/Items (select for more detail, '!' to examine):" - desc_menu.set_title( - new MenuEntry("Visible Monsters/Items (select for more detail, '!' to view/travel):", - MEL_TITLE)); + std::string title = ""; + if (!list_mons.empty()) + title += "Monsters"; + if (!list_items.empty()) + { + if (!title.empty()) + title += "/"; + title += "Items"; + } + if (!list_features.empty()) + { + if (!title.empty()) + title += "/"; + title += "Features"; + } + title = "Visible " + title + " (select for more detail, '!' to view/travel):"; + desc_menu.set_title( new MenuEntry(title, MEL_TITLE)); desc_menu.set_tag("pickup"); desc_menu.set_type(MT_PICKUP); // necessary for sorting of the item submenu @@ -538,7 +556,6 @@ void full_describe_view() if (!list_mons.empty()) { desc_menu.add_entry( new MenuEntry("Monsters", MEL_SUBTITLE) ); -// desc_menu.mdisplay->set_num_columns(1); for (unsigned int i = 0; i < list_mons.size(); ++i, ++hotkey) { // List monsters in the form @@ -601,7 +618,7 @@ void full_describe_view() } // Build menu entries for items. - if (list_items.size()) + if (!list_items.empty()) { std::vector all_items; for (unsigned int i = 0; i < list_items.size(); ++i) @@ -626,6 +643,40 @@ void full_describe_view() } } + if (!list_features.empty()) + { + desc_menu.add_entry( new MenuEntry("Features", MEL_SUBTITLE) ); + for (unsigned int i = 0; i < list_features.size(); ++i, ++hotkey) + { + const coord_def c = list_features[i]; + std::string desc = ""; +#ifndef USE_TILE +// get_screen_glyph(c) + const coord_def e = c - you.pos() + coord_def(9,9); + unsigned short col = env.show_col(e);; + int object = env.show(e); + unsigned ch; + get_item_symbol( object, &ch, &col ); + + const std::string colour_str = colour_to_str(col); + desc = "(<" + colour_str + ">"; + desc += stringize_glyph(ch); + if (ch == '<') + desc += '<'; + + desc += ") "; +#endif + desc += feature_description(c); + if (is_travelable_stair(grd(c)) && !travel_cache.know_stair(c)) + desc += " (not visited)"; + FeatureMenuEntry *me = new FeatureMenuEntry(desc, c, hotkey); + me->tag = "description"; + // Hack to make features selectable. + me->quantity = c.x*100 + c.y + 3; + desc_menu.add_entry(me); + } + } + // Select an item to read its full description, or a monster to read its // e'x'amine description. Toggle with '!' to travel to an item's position // or read a monster's database entry. @@ -633,9 +684,10 @@ void full_describe_view() // For ASCII, the 'x' information may include short database descriptions. // Menu loop + std::vector sel; while (true) { - std::vector sel = desc_menu.show(); + sel = desc_menu.show(); redraw_screen(); if (sel.empty()) @@ -692,6 +744,21 @@ void full_describe_view() break; } } + else + { + const int num = quant - 3; + const int y = num % 100; + const int x = (num - y)/100; + coord_def c(x,y); + + if (desc_menu.menu_action == InvMenu::ACT_EXAMINE) + describe_feature_wide(c); + else // ACT_EXECUTE -> travel to feature + { + start_travel( c ); + break; + } + } } #ifndef USE_TILE diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index b505f3aac7..e20ab461d5 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -3873,7 +3873,7 @@ void zap_wand(int slot) return; } - // if you happen to be wielding the wand, its display might change. + // If you happen to be wielding the wand, its display might change. if (you.equip[EQ_WEAPON] == item_slot) you.wield_change = true; diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index 5603d1ac76..e0e6e5dc2b 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -513,6 +513,9 @@ void do_curse_item( item_def &item, bool quiet ) { mprf("Your %s glows black for a moment.", item.name(DESC_PLAIN).c_str()); + + // If we get the message, we know the item is cursed now. + item.flags |= ISFLAG_KNOW_CURSE; } item.flags |= ISFLAG_CURSED; diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 67af41fd61..d39d1080c6 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -20,7 +20,11 @@ REVISION("$Rev$"); #include "mon-util.h" #endif #include "player.h" -#include "tiles.h" +#ifdef USE_TILE + #include "stuff.h" + #include "tiles.h" + #include "travel.h" +#endif #include "tutorial.h" #include "view.h" #include "initfile.h" @@ -692,10 +696,17 @@ MonsterMenuEntry::MonsterMenuEntry(const std::string &str, const monsters* mon, quantity = 1; } +FeatureMenuEntry::FeatureMenuEntry(const std::string &str, const coord_def p, int hotkey) : + MenuEntry(str, MEL_ITEM, 1, hotkey) +{ + pos = p; + quantity = 1; +} + #ifdef USE_TILE bool MenuEntry::get_tiles(std::vector& tileset) const { - return false; + return (false); } bool MonsterMenuEntry::get_tiles(std::vector& tileset) const @@ -781,6 +792,19 @@ bool MonsterMenuEntry::get_tiles(std::vector& tileset) const return (true); } + +bool FeatureMenuEntry::get_tiles(std::vector& tileset) const +{ + if (!in_bounds(pos)) + return (false); + + tileset.push_back(tile_def(tileidx_feature(grd(pos), pos.x, pos.y), + TEX_DUNGEON)); + if (is_travelable_stair(grd(pos)) && !travel_cache.know_stair(pos)) + tileset.push_back(tile_def(TILE_NEW_STAIR, TEX_DEFAULT)); + + return (true); +} #endif bool Menu::is_selectable(int item) const @@ -1505,11 +1529,12 @@ formatted_scroller::formatted_scroller(int _flags, const std::string& s) : void formatted_scroller::add_text(const std::string& s) { size_t eolpos = 0; - while ( true ) + while (true) { const size_t newpos = s.find( "\n", eolpos ); - add_item_formatted_string(formatted_string::parse_string(std::string(s, eolpos, newpos-eolpos))); - if ( newpos == std::string::npos ) + add_item_formatted_string(formatted_string::parse_string( + std::string(s, eolpos, newpos-eolpos))); + if (newpos == std::string::npos) break; else eolpos = newpos + 1; diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index 12517ec097..d3d358e8ac 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -172,6 +172,18 @@ public: #endif }; +class FeatureMenuEntry : public MenuEntry +{ +public: + coord_def pos; + + FeatureMenuEntry(const std::string &str, const coord_def p, int hotkey); + +#ifdef USE_TILE + virtual bool get_tiles(std::vector& tileset) const; +#endif +}; + class MenuHighlighter { public: diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 1bd90804d2..982c671771 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3393,7 +3393,7 @@ bool monster_shover(const monsters *m) // Returns true if m1 and m2 are related, and m1 is higher up the totem pole // than m2. The criteria for being related are somewhat loose, as you can see // below. -bool monster_senior(const monsters *m1, const monsters *m2) +bool monster_senior(const monsters *m1, const monsters *m2, bool fleeing) { const monsterentry *me1 = get_monster_data(m1->type), *me2 = get_monster_data(m2->type); @@ -3406,12 +3406,12 @@ bool monster_senior(const monsters *m1, const monsters *m2) // If both are demons, the smaller number is the nastier demon. if (isdigit(mchar1) && isdigit(mchar2)) - return (mchar1 < mchar2); + return (fleeing || mchar1 < mchar2); // &s are the evillest demons of all, well apart from Geryon, who really // profits from *not* pushing past beasts. if (mchar1 == '&' && isdigit(mchar2) && m1->type != MONS_GERYON) - return (m1->hit_dice > m2->hit_dice); + return (fleeing || m1->hit_dice > m2->hit_dice); // If they're the same holiness, monsters smart enough to use stairs can // push past monsters too stupid to use stairs (so that e.g. non-zombified @@ -3422,21 +3422,24 @@ bool monster_senior(const monsters *m1, const monsters *m2) return (true); } - if (m1->type == MONS_QUEEN_BEE - && (m2->type == MONS_KILLER_BEE - || m2->type == MONS_KILLER_BEE_LARVA)) + if (mons_genus(m1->type) == MONS_KILLER_BEE + && mons_genus(m2->type) == MONS_KILLER_BEE) { - return (true); - } + if (fleeing) + return (true); - if (m1->type == MONS_KILLER_BEE && m2->type == MONS_KILLER_BEE_LARVA) - return (true); + if (m1->type == MONS_QUEEN_BEE && m2->type != MONS_QUEEN_BEE) + return (true); + + if (m1->type == MONS_KILLER_BEE && m2->type == MONS_KILLER_BEE_LARVA) + return (true); + } // Special-case gnolls, so they can't get past (hob)goblins. if (m1->type == MONS_GNOLL && m2->type != MONS_GNOLL) return (false); - return (mchar1 == mchar2 && m1->hit_dice > m2->hit_dice); + return (mchar1 == mchar2 && (fleeing || m1->hit_dice > m2->hit_dice)); } diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 92eacdaf3b..116b215a80 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -815,7 +815,8 @@ bool mons_is_petrifying(const monsters *m); bool mons_cannot_act(const monsters *m); bool mons_cannot_move(const monsters *m); -bool monster_senior(const monsters *first, const monsters *second); +bool monster_senior(const monsters *first, const monsters *second, + bool fleeing = false); monster_type draco_subspecies( const monsters *mon ); std::string draconian_colour_name(monster_type mtype); monster_type draconian_colour_by_name(const std::string &colour); diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index c0048a05d6..a7fe9465d8 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -7649,7 +7649,8 @@ static bool _mons_can_displace(const monsters *mpusher, const monsters *mpushee) if (!monster_shover(mpusher)) return (false); - if (!monster_senior(mpusher, mpushee)) + // Fleeing monsters of the same type may push past higher ranking ones. + if (!monster_senior(mpusher, mpushee, mons_is_fleeing(mpusher))) return (false); return (true); diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc index 12187347b1..315db5edcc 100644 --- a/crawl-ref/source/quiver.cc +++ b/crawl-ref/source/quiver.cc @@ -166,14 +166,19 @@ void choose_item_for_quiver() : "hand crossbow"); return; } - else if (slot == you.equip[EQ_WEAPON]) + else if (slot == you.equip[EQ_WEAPON] + && you.inv[slot].base_type == OBJ_WEAPONS + && (get_weapon_brand(you.inv[slot]) != SPWPN_RETURNING + || you.skills[SK_THROWING] == 0)) { - mpr("You can't quiver wielded items."); + // Don't quiver a wielded weapon unless it's a weapon of returning + // and we've got some throwing skill. + mpr("You can't quiver wielded weapons."); return; } else { - for (int i = 0; i < NUM_EQUIP; i++) + for (int i = EQ_CLOAK; i < NUM_EQUIP; i++) { if (you.equip[i] == slot) { @@ -320,8 +325,11 @@ void player_quiver::_maybe_fill_empty_slot() // If we're wielding an item previously quivered, the quiver may need // to be cleared. Else, any already quivered item is valid and we // don't need to do anything else. - if (m_last_used_of_type[slot].link == you.equip[EQ_WEAPON]) + if (m_last_used_of_type[slot].link == you.equip[EQ_WEAPON] + && you.equip[EQ_WEAPON] == -1) + { unquiver_weapon = true; + } else return; } @@ -332,8 +340,6 @@ void player_quiver::_maybe_fill_empty_slot() const launch_retval desired_ret = (weapon && is_range_weapon(*weapon)) ? LRET_LAUNCHED : LRET_THROWN; -// const launch_retval desired_ret = -// (slot == AMMO_THROW ? LRET_THROWN : LRET_LAUNCHED); std::vector order; _get_fire_order(order, false, weapon); @@ -398,9 +404,15 @@ void player_quiver::_get_fire_order( std::vector& order, if (!is_valid_item(item)) continue; - // Don't quiver wielded weapon. - if (you.equip[EQ_WEAPON] == i_inv) + // Don't quiver a wielded weapon unless it's a weapon of returning + // and we've got some throwing skill. + if (you.equip[EQ_WEAPON] == i_inv + && you.inv[i_inv].base_type == OBJ_WEAPONS + && (get_weapon_brand(you.inv[i_inv]) != SPWPN_RETURNING + || you.skills[SK_THROWING] == 0)) + { continue; + } // Don't do anything if this item is not really fit for throwing. if (is_launched(&you, you.weapon(), item) == LRET_FUMBLED) diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index caa4eed7d5..0b1002c5e3 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -908,7 +908,7 @@ void ShopInfo::describe_shop_item(const shop_item &si) const item_def it = static_cast(si.item); describe_item( it ); - if ( oldflags != si.item.flags ) + if (oldflags != si.item.flags) const_cast(si).item.flags = oldflags; } @@ -920,7 +920,7 @@ public: menu_letter hotkey) : InvEntry(it.item) { text = item_name; - add_hotkey(hotkey); + hotkeys[0] = hotkey; } }; @@ -930,8 +930,8 @@ bool ShopInfo::show_menu(const std::string &place, StashMenu menu; MenuEntry *mtitle = new MenuEntry(name + " (" + place, MEL_TITLE); - menu.can_travel = can_travel; - mtitle->quantity = items.size(); + menu.can_travel = can_travel; + mtitle->quantity = items.size(); menu.set_title(mtitle); menu_letter hotkey; @@ -949,9 +949,9 @@ bool ShopInfo::show_menu(const std::string &place, { for (int i = 0, count = items.size(); i < count; ++i) { - MenuEntry *me = new ShopItemEntry(items[i], - shop_item_name(items[i]), - hotkey++); + ShopItemEntry *me = new ShopItemEntry(items[i], + shop_item_name(items[i]), + hotkey++); menu.add_entry(me); } } -- cgit v1.2.3-54-g00ecf