From 33f39e1feb49c5f7ef0fc748e16195849627faf9 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Sun, 1 Jun 2008 21:38:06 +0000 Subject: * Fix some issues with the new food colourings, and make it respect Vampires' drinking habits. * Allow other channels than MSGCH_TUTORIAL to use formatted strings and use it to send a coloured string through the butcher prompt, thus visibly setting off dangerous corpses. I'd like normal corpses (no patterns in food_colouring.txt matching) not to be highlighted at all, but they're currently shown in lightgrey, that will have to be improved. * Fix Vampire mutation screen displaying poison resistance wrongly. * Add a new option force_more_message whose syntax is copied from travel_stop_message. Any message containing a regex within this listing will enforce a -More- prompt. By default, it's only enabled for "You start to lose your buoyoncy." * Tweak the messages for Kenku flying to fix 1823833. * Make Xom be amused at players teleporting in a labyrinth or when becoming (Near) Starving while in a labyrinth and with little food at their disposal. Yes, it's one of those "Something for everyone" commits. :D git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5416 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/docs/options_guide.txt | 13 +- crawl-ref/settings/food_colouring.txt | 3 - crawl-ref/settings/menu_colours.txt | 2 +- crawl-ref/source/abl-show.cc | 33 ++++-- crawl-ref/source/decks.cc | 2 +- crawl-ref/source/externs.h | 1 + crawl-ref/source/food.cc | 217 +++++++++++++++++++++++++++------- crawl-ref/source/initfile.cc | 40 +++++-- crawl-ref/source/item_use.cc | 7 +- crawl-ref/source/itemname.cc | 16 ++- crawl-ref/source/message.cc | 149 +++++++++++++---------- crawl-ref/source/mutation.cc | 2 +- crawl-ref/source/player.cc | 10 +- crawl-ref/source/spells3.cc | 23 ++-- crawl-ref/source/stuff.cc | 6 +- crawl-ref/source/xom.cc | 4 +- 16 files changed, 374 insertions(+), 154 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index b8b404f7a2..b5418f5e3d 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -45,9 +45,10 @@ The contents of this text are: explore_greedy, explore_stop, explore_improved, tc_reachable, tc_dangerous, tc_disconnected, tc_excluded, tc_exclude_circle, - travel_stop_message, runrest_ignore_message, - runrest_ignore_poison, runrest_ignore_monster, - trapwalk_safe_hp, trap_prompt, rest_wait_both + travel_stop_message, force_more_message, + runrest_ignore_message, runrest_ignore_poison, + runrest_ignore_monster, trapwalk_safe_hp, + trap_prompt, rest_wait_both 4-h Stashes. stash_tracking, stash_filter, annotate_item_class 4-i Command Enhancements. @@ -772,6 +773,12 @@ travel_stop_message = list of such options. It can be included by include = travel_stoppers.txt +force_more_message = + Any message that contains a regex specified here, will enforce a + -More- prompt, so it can be used to highlight really important + events. + The syntax is identical to that of travel_stop_message. + runrest_ignore_message = This only works if runrest.lua has already been sourced in init.txt. Any message containing the string will *not* stop your diff --git a/crawl-ref/settings/food_colouring.txt b/crawl-ref/settings/food_colouring.txt index ebdea7fd35..40f8d2055f 100644 --- a/crawl-ref/settings/food_colouring.txt +++ b/crawl-ref/settings/food_colouring.txt @@ -5,9 +5,6 @@ msg := message_colour inv := menu_colour -# Spriggans don't care for corpses and chunks. -# - msg = darkgrey:.*inedible.* inv = darkgrey:.*inedible.* diff --git a/crawl-ref/settings/menu_colours.txt b/crawl-ref/settings/menu_colours.txt index c3a5c092c0..6f5343e4d0 100644 --- a/crawl-ref/settings/menu_colours.txt +++ b/crawl-ref/settings/menu_colours.txt @@ -114,7 +114,7 @@ menu = yellow:.*potion.*(porridge|gluggy white) # Defaults for normal items # menu = lightred:.*equipped.*cursed -menu = lightgreen:.*equipped.* +menu = green:.*equipped.* menu = green:uncursed menu = red:cursed menu = lightgrey:^(scroll|potion|ring|amulet) diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc index d86c658715..b71a0e3b7b 100644 --- a/crawl-ref/source/abl-show.cc +++ b/crawl-ref/source/abl-show.cc @@ -822,9 +822,18 @@ bool activate_ability() std::vector talents = your_talents(false); if ( talents.empty() ) { - // Vampires can't turn into bats when full of blood. + // Give messages if the character cannot use innate talents right now. + // * Vampires can't turn into bats when full of blood. + // * Permanent flying (Kenku) cannot be turned off. if (you.species == SP_VAMPIRE && you.experience_level >= 3) mpr("Sorry, you're too full to transform right now."); + else if (you.species == SP_KENKU && you.experience_level >= 5) + { + if (you.flight_mode() == FL_FLY) + mpr("You're already flying!"); + else if (you.flight_mode() == FL_LEVITATE) + mpr("You can only start flying from the ground."); + } else mpr("Sorry, you're not good enough to have a special ability."); @@ -2151,19 +2160,23 @@ std::vector your_talents( bool check_confused ) _add_talent(talents, ABIL_EVOKE_TURN_INVISIBLE, check_confused ); } - //jmf: "upgrade" for draconians -- expensive flight - // note: this ability only applies to this counter + // jmf: "upgrade" for draconians -- expensive flight + // Note: This ability only applies to this counter. if (player_equip( EQ_RINGS, RING_LEVITATION ) || player_equip_ego_type( EQ_BOOTS, SPARM_LEVITATION ) || scan_randarts( RAP_LEVITATE )) { - // Now you can only turn levitation off if you have an - // activatable item. Potions and miscast effects will - // have to time out (this makes the miscast effect actually - // a bit annoying). -- bwr - _add_talent(talents, you.duration[DUR_LEVITATION] ? - ABIL_EVOKE_STOP_LEVITATING : ABIL_EVOKE_LEVITATE, - check_confused); + // Has no effect on permanently flying Kenku. + if (!you.permanent_levitation() && you.flight_mode() != FL_FLY) + { + // Now you can only turn levitation off if you have an + // activatable item. Potions and miscast effects will + // have to time out (this makes the miscast effect actually + // a bit annoying). -- bwr + _add_talent(talents, you.duration[DUR_LEVITATION] ? + ABIL_EVOKE_STOP_LEVITATING : ABIL_EVOKE_LEVITATE, + check_confused); + } } if (player_equip( EQ_RINGS, RING_TELEPORTATION ) diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index e6c18f591d..db45b50fdb 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -1274,7 +1274,7 @@ void evoke_deck( item_def& deck ) << std::endl; } - if ( !fake_draw ) + if (!fake_draw) did_god_conduct(DID_CARDS, brownie_points); // Always wield change, since the number of cards used/left has diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 461c87bb86..4786cf4c7f 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -1710,6 +1710,7 @@ public: // Messages that stop travel std::vector travel_stop_message; + std::vector force_more_message; int stash_tracking; // How stashes are tracked diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index ad84a5916b..6638f544b0 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -165,7 +165,7 @@ void weapon_switch( int targ ) autopickup(); } -// look for a butchering implement. If fallback is true, +// Look for a butchering implement. If fallback is true, // prompt the user if no obvious options exist. // Returns whether a weapon was switched. static bool _find_butchering_implement( bool fallback ) @@ -181,6 +181,7 @@ static bool _find_butchering_implement( bool fallback ) mprf(MSGCH_WARN, "You're wielding a weapon of distortion, will not autoswap " "for butchering."); + return (false); } // No switching necessary. @@ -212,14 +213,14 @@ static bool _find_butchering_implement( bool fallback ) if (!fallback) return false; - // if we didn't swap above, then we still can't cut...let's call + // If we didn't swap above, then we still can't cut...let's call // wield_weapon() in the "prompt the user" way... - // prompt for new weapon + // Prompt for new weapon. mpr("What would you like to use?", MSGCH_PROMPT); wield_weapon( false ); - // let's see if the user did something... + // Let's see if the user did something... return (you.equip[EQ_WEAPON] != old_weapon); } @@ -330,7 +331,13 @@ static void _terminate_butchery(bool wpn_switch, bool removed_gloves, static bool _have_corpses_in_pack(bool remind) { - int num = 0; + const bool can_bottle = (you.species == SP_VAMPIRE + && you.experience_level > 5 + && (!you.duration[DUR_PRAYER] + || !god_likes_butchery(you.religion))); + + int num = 0; + int num_bottle = 0; for (int i = 0; i < ENDOFPACK; i++) { @@ -339,17 +346,27 @@ static bool _have_corpses_in_pack(bool remind) if (!is_valid_item( obj )) continue; - if (obj.base_type == OBJ_CORPSES && obj.sub_type == CORPSE_BODY) - num++; + // Only actually count corpses, not skeletons. + if (obj.base_type != OBJ_CORPSES || obj.sub_type != CORPSE_BODY) + continue; + + // Only saprovorous characters care about rotten food. + if (food_is_rotten(obj) && !player_mutation_level(MUT_SAPROVOROUS)) + continue; + + num++; + if (can_bottle && mons_has_blood(obj.plus)) + num_bottle++; } if (num == 0) return (false); - std::string verb = (you.species == SP_VAMPIRE - && you.experience_level > 5) ? "bottle" : "butcher"; - std::string noun, pronoun; + std::string verb = (num_bottle ? (num == num_bottle ? "bottle" + : "bottle or butcher") + : "butcher"); + std::string noun, pronoun; if (num == 1) { noun = "corpse"; @@ -370,8 +387,8 @@ static bool _have_corpses_in_pack(bool remind) } else { - text << "If you dropped the " << noun << " in your pack on solid " - << "ground then you could " << verb << " " << pronoun << "."; + text << "If you dropped the " << noun << " in your pack " + << "then you could " << verb << " " << pronoun << "."; } mpr(text.str().c_str()); @@ -440,7 +457,7 @@ bool butchery(int which_corpse) corpse_id = o; num_corpses++; - // return pre-chosen corpse if it exists + // Return pre-chosen corpse if it exists. if (prechosen && corpse_id == which_corpse) break; } @@ -450,9 +467,9 @@ bool butchery(int which_corpse) { if (!_have_corpses_in_pack(false)) { - mprf("There isn't anything to %s here.", + mprf("There isn't anything to %sbutcher here.", (you.species == SP_VAMPIRE - && you.experience_level > 5) ? "bottle" : "butcher"); + && you.experience_level > 5) ? "bottle or " : ""); } return (false); } @@ -519,13 +536,41 @@ bool butchery(int which_corpse) { corpse_id = -1; + std::string corpse_name = mitm[o].name(DESC_NOCAP_A); + + const bool sacrifice = (you.duration[DUR_PRAYER] + && god_likes_butchery(you.religion)); + + // We don't need to check for undead because + // * Mummies can't eat + // * Ghouls relish the bad things + // * Vampires won't bottle bad corpses + if (!sacrifice && !you.is_undead) + { + // Don't bother colouring if it's only for sacrificing. + std::string cprf = menu_colour_item_prefix(mitm[o]); + std::string colour = ""; + std::string colour_off = ""; + int col = menu_colour(corpse_name, cprf, "pickup"); + + if (col != LIGHTGRAY) + colour = colour_to_str( col ); + + if (!colour.empty()) + { + // Order is important here. + colour_off = ""; + colour = "<" + colour + ">"; + corpse_name = colour + corpse_name + colour_off; + } + } + // Shall we butcher this corpse? snprintf(info, INFO_SIZE, "%s %s?", - (!can_bottle_blood_from_corpse(mitm[o].plus) - || you.duration[DUR_PRAYER] - && god_likes_butchery(you.religion)) ? "Butcher" - : "Bottle", - mitm[o].name(DESC_NOCAP_A).c_str()); + (sacrifice + || !can_bottle_blood_from_corpse(mitm[o].plus)) ? + "Butcher" : "Bottle", + corpse_name.c_str()); const int result = yesnoquit(info, true, 'N', true, false, 'C', 'D'); @@ -657,19 +702,19 @@ bool prompt_eat_from_inventory(int slot) { which_inventory_slot = (slot != -1) ? slot : prompt_invent_item( "Eat which item?", - MT_INVLIST, - OBJ_FOOD, - true, true, true, 0, NULL, - OPER_EAT ); + MT_INVLIST, + OBJ_FOOD, + true, true, true, 0, NULL, + OPER_EAT ); } else { which_inventory_slot = (slot != -1) ? slot : prompt_invent_item( "Drain what?", - MT_INVLIST, - OSEL_VAMP_EAT, - true, true, true, 0, NULL, - OPER_EAT ); + MT_INVLIST, + OSEL_VAMP_EAT, + true, true, true, 0, NULL, + OPER_EAT ); } if (which_inventory_slot == PROMPT_ABORT) @@ -745,7 +790,7 @@ bool eat_food(bool run_hook, int slot) } return (prompt_eat_from_inventory(slot)); -} // end eat_food() +} /* ************************************************** @@ -754,6 +799,68 @@ bool eat_food(bool run_hook, int slot) * * ************************************************** */ + +static bool _player_has_enough_food() +{ + int food_value = 0; + item_def item; + for (unsigned slot = 0; slot < ENDOFPACK; ++slot) + { + item = you.inv[slot]; + if (!is_valid_item(item)) + continue; + + if (!can_ingest(item.base_type, item.sub_type, true, true, false)) + continue; + + if (food_is_rotten(item) && !player_mutation_level(MUT_SAPROVOROUS)) + continue; + + if (is_poisonous(item)) + continue; + + if (is_mutagenic(item)) + continue; + + if (causes_rot(item) && you.species != SP_GHOUL) + continue; + + // Vampires can only drain corpses. + if (you.species == SP_VAMPIRE) + food_value += 3; + else + { + if (item.base_type != OBJ_FOOD) + continue; + switch (item.sub_type) + { + case FOOD_CHUNK: + if (!player_mutation_level(MUT_HERBIVOROUS)) + food_value += 2 * item.quantity; + break; + case FOOD_MEAT_RATION: + if (!player_mutation_level(MUT_HERBIVOROUS)) + food_value += 3 * item.quantity; + break; + case FOOD_BREAD_RATION: + if (!player_mutation_level(MUT_CARNIVOROUS)) + food_value += 3 * item.quantity; + break; + default: + // Only count snacks if we really like them + if (is_preferred_food(item)) + food_value += item.quantity; + break; + } + } + } + + // You have "enough" food if you have, e.g. + // 1 meat ration + 1 chunk, or 2 chunks for carnivores, or + // 5 items of fruit, or 1 bread ration and 2 fruit items as a herbivore. + return (food_value > 5); +} + static std::string _how_hungry() { if (you.hunger_state > HS_SATIATED) @@ -846,6 +953,15 @@ static bool _food_change(bool suppress_message) else msg += "are starving!"; mpr(msg.c_str(), MSGCH_FOOD, less_hungry); + + // Xom thinks this is funny if you're in a labyrinth + // and are low on food. + if (you.level_type == LEVEL_LABYRINTH + && !_player_has_enough_food()) + { + xom_is_stimulated(64); + } + learned_something_new(TUT_YOU_STARVING); you.check_awaken(500); break; @@ -856,6 +972,15 @@ static bool _food_change(bool suppress_message) else msg += "are near starving!"; mpr(msg.c_str(), MSGCH_FOOD, less_hungry); + + // Xom thinks this is funny if you're in a labyrinth + // and are low on food. + if (you.level_type == LEVEL_LABYRINTH + && !_player_has_enough_food()) + { + xom_is_stimulated(32); + } + learned_something_new(TUT_YOU_HUNGRY); break; @@ -1122,10 +1247,7 @@ static int _chunk_nutrition(bool likes_chunks) const int epercent = effective_nutrition * 100 / nutrition; mprf(MSGCH_DIAGNOSTICS, "Gourmand factor: %d, chunk base: %d, effective: %d, %%: %d", - gourmand, - nutrition, - effective_nutrition, - epercent); + gourmand, nutrition, effective_nutrition, epercent); #endif return (_apply_herbivore_chunk_effects(effective_nutrition)); @@ -1150,8 +1272,8 @@ static void _eat_chunk( int chunk_effect, bool cannibal, int mon_intel ) if (you.species == SP_GHOUL) { - nutrition = CHUNK_BASE_NUTRITION; - hp_amt = 1 + random2(5) + random2(1 + you.experience_level); + nutrition = CHUNK_BASE_NUTRITION; + hp_amt = 1 + random2(5) + random2(1 + you.experience_level); suppress_msg = true; } @@ -1683,14 +1805,20 @@ void vampire_nutrition_per_turn(const item_def &corpse, int feeding) lessen_hunger(food_value / duration, !start_feeding); } +// Returns true if a food item (also corpses) is poisonous AND the player +// is not poison resistant. bool is_poisonous(const item_def &food) { if (food.base_type != OBJ_FOOD && food.base_type != OBJ_CORPSES) return (false); + if (player_res_poison()) + return (false); + return (mons_corpse_effect(food.plus) == CE_POISONOUS); } +// Returns true if a food item (also corpses) is mutagenic. bool is_mutagenic(const item_def &food) { if (food.base_type != OBJ_FOOD && food.base_type != OBJ_CORPSES) @@ -1699,6 +1827,7 @@ bool is_mutagenic(const item_def &food) return (mons_corpse_effect(food.plus) == CE_MUTAGEN_RANDOM); } +// Returns true if a food item (also corpses) may cause sickness. bool is_contaminated(const item_def &food) { if (food.base_type != OBJ_FOOD && food.base_type != OBJ_CORPSES) @@ -1707,9 +1836,10 @@ bool is_contaminated(const item_def &food) return (mons_corpse_effect(food.plus) == CE_CONTAMINATED); } +// Returns true if a food item (also corpses) will cause rotting. bool causes_rot(const item_def &food) { - if (food.base_type != OBJ_FOOD && food.sub_type != FOOD_CHUNK) + if (food.base_type != OBJ_FOOD && food.base_type != OBJ_CORPSES) return (false); return (mons_corpse_effect(food.plus) == CE_HCL); @@ -1753,6 +1883,11 @@ static int _player_likes_food_type(int food_type) // still be edible or even delicious. bool is_preferred_food(const item_def &food) { + // Vampires don't really have a preferred food type, but they really + // like blood potions. + if (you.species == SP_VAMPIRE) + return (is_blood_potion(food)); + if (food.base_type != OBJ_FOOD) return (false); @@ -1797,7 +1932,7 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, if (you.species == SP_VAMPIRE) { if (what_isit == OBJ_CORPSES && kindof_thing == CORPSE_BODY) - return true; + return (true); if (what_isit == OBJ_POTIONS && (kindof_thing == POT_BLOOD || kindof_thing == POT_BLOOD_COAGULATED)) @@ -1887,19 +2022,19 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, if (you.species == SP_VAMPIRE) { if (kindof_thing == CORPSE_BODY) - return true; + return (true); else { if (!suppress_msg) mpr("Blech - you need blood!"); - return false; + return (false); } } - return false; + return (false); case OBJ_POTIONS: // called by lua if (get_ident_type(OBJ_POTIONS, kindof_thing) != ID_KNOWN_TYPE) - return true; + return (true); switch (kindof_thing) { diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 0df51a676a..2ec348288b 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -146,12 +146,10 @@ int str_to_colour( const std::string &str, int default_colour, ASSERT(ARRAYSZ(element_cols) == (EC_RANDOM - EC_FIRE) + 1); for (ret = 0; ret < 16; ret++) - { if (str == cols[ret]) break; - } - // check for alternate spellings + // Check for alternate spellings. if (ret == 16) { if (str == "lightgray") @@ -177,7 +175,7 @@ int str_to_colour( const std::string &str, int default_colour, if (ret == 16 && accept_number) { - // Check if we have a direct colour index + // Check if we have a direct colour index. const char *s = str.c_str(); char *es = NULL; const int ci = static_cast(strtol(s, &es, 10)); @@ -188,7 +186,7 @@ int str_to_colour( const std::string &str, int default_colour, return ((ret == 16) ? default_colour : ret); } -// returns -1 if unmatched else returns 0-15 +// Returns -1 if unmatched else returns 0-15. static int _str_to_channel_colour( const std::string &str ) { int ret = str_to_colour( str ); @@ -874,6 +872,7 @@ void game_options::reset_options() note_items.clear(); note_skill_levels.clear(); travel_stop_message.clear(); + force_more_message.clear(); sound_mappings.clear(); menu_colour_mappings.clear(); menu_colour_prefix_class = false; @@ -1744,7 +1743,7 @@ void game_options::read_option_line(const std::string &str, bool runscript) && key != "race" && key != "class" && key != "ban_pickup" && key != "autopickup_exceptions" && key != "stop_travel" && key != "sound" - && key != "travel_stop_message" + && key != "travel_stop_message" && key != "force_more_message" && key != "drop_filter" && key != "lua_file" && key != "note_items" && key != "autoinscribe" && key != "note_monsters" && key != "note_messages" @@ -2400,7 +2399,7 @@ void game_options::read_option_line(const std::string &str, bool runscript) std::string s = fragments[i].substr( pos + 1 ); trim_string( s ); travel_stop_message.push_back( - message_filter( channel, s ) ); + message_filter( channel, s ) ); continue; } } @@ -2409,6 +2408,33 @@ void game_options::read_option_line(const std::string &str, bool runscript) message_filter( fragments[i] ) ); } } + else if (key == "force_more_message") + { + std::vector fragments = split_string(",", field); + for (int i = 0, count = fragments.size(); i < count; ++i) + { + if (fragments[i].length() == 0) + continue; + + std::string::size_type pos = fragments[i].find(":"); + if (pos && pos != std::string::npos) + { + std::string prefix = fragments[i].substr(0, pos); + int channel = str_to_channel( prefix ); + if (channel != -1 || prefix == "any") + { + std::string s = fragments[i].substr( pos + 1 ); + trim_string( s ); + force_more_message.push_back( + message_filter( channel, s ) ); + continue; + } + } + + force_more_message.push_back( + message_filter( fragments[i] ) ); + } + } else if (key == "drop_filter") { append_vector(drop_filter, split_string(",", field)); diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index d0c1b8e051..2db9c511e4 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -3541,10 +3541,13 @@ void drink( int slot ) if (slot != -1) item_slot = slot; else + { item_slot = prompt_invent_item( "Drink which item?", MT_INVLIST, OBJ_POTIONS, true, true, true, 0, NULL, OPER_QUAFF ); + } + if (item_slot == PROMPT_ABORT) { canned_msg( MSG_OK ); @@ -3570,8 +3573,8 @@ void drink( int slot ) // The "> 1" part is to reduce the amount of times that Xom is // stimulated when you are a low-level 1 trying your first unknown // potions on monsters. - const bool dangerous = - (player_in_a_dangerous_place() && you.experience_level > 1); + const bool dangerous = (player_in_a_dangerous_place() + && you.experience_level > 1); if (potion_effect(static_cast(you.inv[item_slot].sub_type), 40, alreadyknown)) diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index 4b3ca9f252..947937e859 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -2194,8 +2194,18 @@ const std::string menu_colour_item_prefix(const item_def &item) switch (item.base_type) { + case OBJ_CORPSES: + // Skeletons cannot be eaten. + if (item.sub_type == CORPSE_SKELETON) + { + prefixes.push_back("inedible"); + break; + } + // intentional fall-through case OBJ_FOOD: - if (!can_ingest(item.base_type, item.sub_type, true, true, false) + if (item.base_type != OBJ_CORPSES + && !can_ingest(item.base_type, item.sub_type, true, true, false) + || you.species == SP_VAMPIRE && !mons_has_blood(item.plus) || food_is_rotten(item) && !player_mutation_level(MUT_SAPROVOROUS)) { @@ -2204,9 +2214,7 @@ const std::string menu_colour_item_prefix(const item_def &item) else if (is_preferred_food(item)) prefixes.push_back("preferred"); - // intentional fall-through - case OBJ_CORPSES: - if (is_poisonous(item) && !player_res_poison()) + if (is_poisonous(item)) prefixes.push_back("poisonous"); else if (is_mutagenic(item)) prefixes.push_back("mutagenic"); diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 009a7d789f..479899d853 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -43,7 +43,7 @@ #include "view.h" #include "menu.h" -// circular buffer for keeping past messages +// Circular buffer for keeping past messages. message_item Store_Message[ NUM_STORED_MESSAGES ]; // buffer of old messages int Next_Message = 0; // end of messages @@ -170,7 +170,7 @@ static char god_message_altar_colour( god_type god ) return (WHITE); case GOD_ELYVILON: - return (LIGHTBLUE); // really, LIGHTGREY but that's plain text + return (LIGHTBLUE); // Really, LIGHTGREY but that's plain text. case GOD_OKAWARU: return (CYAN); @@ -221,7 +221,7 @@ static char god_message_altar_colour( god_type god ) #ifdef USE_COLOUR_MESSAGES -// returns a colour or MSGCOL_MUTED +// Returns a colour or MSGCOL_MUTED. int channel_to_colour( msg_channel_type channel, int param ) { if (you.asleep()) @@ -232,7 +232,7 @@ int channel_to_colour( msg_channel_type channel, int param ) switch (Options.channels[ channel ]) { case MSGCOL_PLAIN: - // note that if the plain channel is muted, then we're protecting + // Note that if the plain channel is muted, then we're protecting // the player from having that spread to other channels here. // The intent of plain is to give non-coloured messages, not to // suppress them. @@ -338,9 +338,9 @@ int channel_to_colour( msg_channel_type channel, int param ) // cases should be handled above. if (channel == MSGCH_MONSTER_DAMAGE) { - // a special case right now for monster damage (at least until + // A special case right now for monster damage (at least until // the init system is improved)... selecting a specific - // colour here will result in only the death messages coloured + // colour here will result in only the death messages coloured. if (param == MDAM_DEAD) ret = Options.channels[ channel ]; else if (Options.channels[ MSGCH_PLAIN ] >= MSGCOL_DEFAULT) @@ -390,7 +390,7 @@ void mprf( msg_channel_type channel, const char *format, ... ) { va_list argp; va_start( argp, format ); - do_message_print( channel, channel == MSGCH_GOD? you.religion : 0, + do_message_print( channel, channel == MSGCH_GOD ? you.religion : 0, format, argp ); va_end( argp ); } @@ -411,22 +411,37 @@ void mpr(const char *inf, msg_channel_type channel, int param) fprintf(stderr, "%s\n", inf); return; } + + std::string help = inf; + if (help.find("" + help + ""; + + // Handing over to the experts... + formatted_mpr(formatted_string::parse_string(help), channel); + return; + } + + char mbuf[400]; size_t i = 0; const int stepsize = get_number_of_cols() - 1; const size_t msglen = strlen(inf); const int lookback_size = (stepsize < 12 ? 0 : 12); - // if a message is exactly STEPSIZE characters long, + + // If a message is exactly STEPSIZE characters long, // it should precisely fit in one line. The printing is thus // from I to I + STEPSIZE - 1. Stop when I reaches MSGLEN. while ( i < msglen || i == 0 ) { strncpy( mbuf, inf + i, stepsize ); mbuf[stepsize] = 0; - // did the message break? + // Did the message break? if ( i + stepsize < msglen ) { - // yes, find a nicer place to break it. + // Aes, find a nicer place to break it. int lookback, where = 0; for ( lookback = 0; lookback < lookback_size; ++lookback ) { @@ -438,15 +453,16 @@ void mpr(const char *inf, msg_channel_type channel, int param) if ( lookback != lookback_size ) { - // found a good spot to break + // Found a good spot to break. mbuf[where] = 0; - i += where + 1; // skip past the space! + i += where + 1; // Skip past the space! } else i += stepsize; } else i += stepsize; + base_mpr( mbuf, channel, param ); } } @@ -486,8 +502,8 @@ void mpr_comma_separated_list(const std::string prefix, } -// checks whether a given message contains patterns relevant for -// notes, stop_running or sounds and handles these cases +// Checks whether a given message contains patterns relevant for +// notes, stop_running or sounds and handles these cases. static void mpr_check_patterns(const std::string& message, msg_channel_type channel, int param) @@ -555,7 +571,7 @@ static bool channel_message_history(msg_channel_type channel) } } -// adds a given message to the message history +// Adds a given message to the message history. static void mpr_store_messages(const std::string& message, msg_channel_type channel, int param) { @@ -570,16 +586,16 @@ static void mpr_store_messages(const std::string& message, if (Message_Line < num_lines - 1) Message_Line++; - // reset colour + // Reset colour. textcolor(LIGHTGREY); - // equipment lists just waste space in the message recall + // Equipment lists just waste space in the message recall. if (channel_message_history(channel)) { // Put the message into Store_Message, and move the '---' line forward - Store_Message[ Next_Message ].text = message; + Store_Message[ Next_Message ].text = message; Store_Message[ Next_Message ].channel = channel; - Store_Message[ Next_Message ].param = param; + Store_Message[ Next_Message ].param = param; Next_Message++; if (Next_Message >= NUM_STORED_MESSAGES) @@ -630,11 +646,11 @@ static void base_mpr(const char *inf, msg_channel_type channel, int param) const std::string imsg = inf; const int colour = prepare_message( imsg, channel, param ); - if ( colour == MSGCOL_MUTED ) + if (colour == MSGCOL_MUTED) return; - if (silenced(you.x_pos, you.y_pos) && - (channel == MSGCH_SOUND || channel == MSGCH_TALK)) + if (silenced(you.x_pos, you.y_pos) + && (channel == MSGCH_SOUND || channel == MSGCH_TALK)) { return; } @@ -648,6 +664,17 @@ static void base_mpr(const char *inf, msg_channel_type channel, int param) message_out( Message_Line, colour, inf, Options.delay_message_clear? 2 : 1 ); + for (unsigned i = 0; i < Options.force_more_message.size(); ++i) + { + if (Options.force_more_message[i].is_filtered( channel, imsg )) + { + more(); + New_Message_Count = 0; + // One more() is quite enough, thank you! + break; + } + } + mpr_store_messages(imsg, channel, param); } // end mpr() @@ -697,7 +724,7 @@ void formatted_mpr(const formatted_string& fs, msg_channel_type channel, mpr_store_messages(imsg, channel, param); } -// output given string as formatted message(s), but check patterns +// Output given string as formatted message(s), but check patterns // for string stripped of tags and store the original tagged string // for message history. Newlines break the string into multiple // messages. @@ -728,9 +755,7 @@ void formatted_message_history(const std::string &st_nocolor, } if (wrap_col) - { linebreak_string2(st, wrap_col); - } std::vector fss; formatted_string::parse_string_to_multiple(st, fss); @@ -750,13 +775,17 @@ void formatted_message_history(const std::string &st_nocolor, mpr_formatted_output(fs, colour); - // message playback explicitly only handles colors for - // the tutorial channel... guess we'll store bare strings - // for the rest, then. - if (channel == MSGCH_TUTORIAL) - mpr_store_messages(fs.to_colour_string(), channel, param); - else - mpr_store_messages(unformatted, channel, param); + for (unsigned f = 0; f < Options.force_more_message.size(); ++f) + { + if (Options.force_more_message[f].is_filtered(channel, st_nocolor)) + { + more(); + New_Message_Count = 0; + // One more() is quite enough, thank you! + break; + } + } + mpr_store_messages(fs.to_colour_string(), channel, param); } } @@ -779,13 +808,13 @@ void mesclr( bool force ) return; } - // turn cursor off -- avoid 'cursor dance' + // Turn cursor off -- avoid 'cursor dance'. cursor_control cs(false); clear_message_window(); need_prefix = false; Message_Line = 0; -} // end mseclr() +} void more(void) { @@ -808,14 +837,18 @@ void more(void) int keypress = 0; if (Options.tutorial_left) + { message_out(crawl_view.msgsz.y - 1, LIGHTGREY, "--more-- " "Press Ctrl-P to reread old messages", 2, false); + } else + { message_out(crawl_view.msgsz.y - 1, LIGHTGREY, "--more--", 2, false); + } #ifdef USE_TILE mouse_control mc(MOUSE_MODE_MORE); @@ -917,12 +950,12 @@ void replay_messages(void) for (int i = 0; i < num_lines - 2; i++) { - // calculate line in circular buffer + // Calculate line in circular buffer. int line = win_start_line + i; if (line >= NUM_STORED_MESSAGES) line -= NUM_STORED_MESSAGES; - // avoid wrap-around + // Avoid wrap-around. if (line == first_message && i != 0) break; @@ -935,37 +968,27 @@ void replay_messages(void) textcolor( colour ); std::string text = Store_Message[ line ].text; - // for tutorial texts (for now, used for debugging) - // allow formatted output of tagged messages - if (Store_Message[ line ].channel == MSGCH_TUTORIAL) + + // Allow formatted output of tagged messages. + formatted_string fs = formatted_string::parse_string(text, true); + int curcol = 1; + for ( unsigned int j = 0; j < fs.ops.size(); ++j ) { - formatted_string fs = formatted_string::parse_string(text, true); - int curcol = 1; - for ( unsigned int j = 0; j < fs.ops.size(); ++j ) + switch ( fs.ops[j].type ) { - switch ( fs.ops[j].type ) - { - case FSOP_COLOUR: - colour = fs.ops[j].x; - break; - case FSOP_TEXT: - textcolor( colour ); - cgotoxy(curcol, wherey(), GOTO_CRT); - cprintf(fs.ops[j].text.c_str()); - curcol += multibyte_strlen(fs.ops[j].text); - break; - case FSOP_CURSOR: - break; - } + case FSOP_COLOUR: + colour = fs.ops[j].x; + break; + case FSOP_TEXT: + textcolor( colour ); + cgotoxy(curcol, wherey(), GOTO_CRT); + cprintf(fs.ops[j].text.c_str()); + curcol += multibyte_strlen(fs.ops[j].text); + break; + case FSOP_CURSOR: + break; } } - else -#if DEBUG_DIAGNOSTICS - cprintf( "%d: %s", line, text.c_str() ); -#else - cprintf( "%s", text.c_str() ); -#endif - cprintf(EOL); textcolor(LIGHTGREY); } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 2beb5a54ad..fabf3852aa 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -1418,7 +1418,7 @@ static void _display_vampire_attributes() {"Regeneration ", "very fast ", "fast ", "normal ", "normal ", "slow ", "none"}, - {"Poison resistance ", " ", " ", " + ", " + ", " + ", " + "}, + {"Poison resistance ", " ", " ", " ", " + ", " + ", " + "}, {"Cold resistance ", " ", " ", " ", " + ", " + ", " ++ "}, diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 84feba599b..cbf12e67ec 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1463,13 +1463,13 @@ int player_res_torment(bool) || you.species == SP_VAMPIRE && you.hunger_state == HS_STARVING); } -// funny that no races are susceptible to poisons {dlb} +// Funny that no races are susceptible to poisons. {dlb} // If temp is set to false, temporary sources or resistance won't be counted. int player_res_poison(bool calc_unid, bool temp) { int rp = 0; - // only thirsty vampires are naturally poison resistant + // Only thirsty vampires are naturally poison resistant. if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED) rp++; @@ -6247,9 +6247,11 @@ flight_type player::flight_mode() const return FL_FLY; } else if (is_levitating()) + { return (you.duration[DUR_CONTROLLED_FLIGHT] - || wearing_amulet(AMU_CONTROLLED_FLIGHT) - ? FL_FLY : FL_LEVITATE); + || wearing_amulet(AMU_CONTROLLED_FLIGHT) ? FL_FLY + : FL_LEVITATE); + } else return (FL_NONE); } diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 597e5a8887..c58bf6b3a2 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -606,7 +606,7 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) if (scan_randarts(RAP_PREVENT_TELEPORTATION)) { mpr("You feel a strange sense of stasis."); - return false; + return (false); } // after this point, we're guaranteed to teleport. Kill the appropriate @@ -624,7 +624,8 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) abyss_teleport( new_abyss_area ); if (you.pet_target != MHITYOU) you.pet_target = MHITNOT; - return true; + + return (true); } coord_def pos(1, 0); @@ -671,8 +672,8 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) you.moveto(pos.x, pos.y); - if ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR - && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) + if (grd[you.x_pos][you.y_pos] != DNGN_FLOOR + && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER || mgrd[you.x_pos][you.y_pos] != NON_MONSTER || env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD) { @@ -680,11 +681,11 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) } else { - // controlling teleport contaminates the player -- bwr + // Controlling teleport contaminates the player. -- bwr contaminate_player(1, true); } } - } // end "if is_controlled" + } // end "if is_controlled" if (!is_controlled) { @@ -695,8 +696,8 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) newx = random_range(X_BOUND_1 + 1, X_BOUND_2 - 1); newy = random_range(Y_BOUND_1 + 1, Y_BOUND_2 - 1); } - while ((grd[newx][newy] != DNGN_FLOOR - && grd[newx][newy] != DNGN_SHALLOW_WATER) + while (grd[newx][newy] != DNGN_FLOOR + && grd[newx][newy] != DNGN_SHALLOW_WATER || mgrd[newx][newy] != NON_MONSTER || env.cgrid[newx][newy] != EMPTY_CLOUD); @@ -730,8 +731,10 @@ void you_teleport_now( bool allow_control, bool new_abyss_area ) // teleported to escape from all the monsters chasing him/her, // since in that case the new dangerous area is almost certainly // *less* dangerous than the old dangerous area. - if (randtele && player_in_a_dangerous_place() - && you.level_type != LEVEL_ABYSS) + // Teleporting in a labyrinth is also funny, but only for non-minotaurs. + if (randtele + && (you.level_type == LEVEL_LABYRINTH && you.species != SP_MINOTAUR + || you.level_type != LEVEL_ABYSS && player_in_a_dangerous_place())) { xom_is_stimulated(255); } diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 2c30a5d7d9..7b25581bd2 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -995,8 +995,9 @@ static const char* _list_allowed_keys(char yes1, char yes2, return (result.c_str()); } -// like yesno(), but returns 0 for no, 1 for yes, and -1 for quit -// alt_yes and alt_yes2 allow up to two synonyms for 'Y' +// Like yesno(), but returns 0 for no, 1 for yes, and -1 for quit. +// alt_yes and alt_yes2 allow up to two synonyms for 'Y'. +// FIXME: This function is shaping up to be a monster. Help! int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, bool clear_after, char alt_yes, char alt_yes2 ) { @@ -1006,7 +1007,6 @@ int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, std::string prompt = make_stringf("%s%s ", str ? str : "Buggy prompt?", _list_allowed_keys(alt_yes, alt_yes2, safe, allow_all)); - while (true) { mpr(prompt.c_str(), MSGCH_PROMPT); diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index cdeba01205..2a4c74d1ee 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -1031,12 +1031,14 @@ void xom_check_lost_item(const item_def& item) { // Ignore Abyss area shifts. if (you.level_type != LEVEL_ABYSS) + { // Abyssal runes are a lot more trouble to find than // demonic runes, so they get twice the stimulation. xom_is_stimulated(128, "Xom snickers.", true); + } } else if (item.plus == RUNE_DEMONIC - && you.attribute[ATTR_DEMONIC_RUNES] == 0) + && you.attribute[ATTR_DEMONIC_RUNES] == 0) { xom_is_stimulated(64, "Xom snickers softly.", true); } -- cgit v1.2.3-54-g00ecf