From 1572e9c9223b1b45eada6fec2e1a82eb6950ebfd Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Fri, 13 Jun 2008 14:19:42 +0000 Subject: Added several new tutorial triggers including information on being caught in a net, specific skills, magic resistance, and which stat to choose. In a given game you'll only ever see a small fraction of all tutorial events (we're at 71 now, and some of them are exclusive). In fact, a lot of the information is so generally useful (esp. on gods, skills and items) that I'm seriously considering opening up the general information (How do I use item x? What does Spellcasting do?) to a wider selection of characters. I don't think we'll want to explain the intricacies of Mummies, Ghouls, or Vampires, but a lot of this stuff even applies to them... (If we overhaul the tutorial, it's certainly not a 0.4 target, though.) Resetting the tutorial version to 8 as we somehow switched from digital version to binary and back to digital. It will take some time until we actually reach 110, and by then, I am sure the base files won't be save compatible anymore. :) git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5777 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 73 +-- crawl-ref/source/dat/database/monspeak.txt | 2 +- crawl-ref/source/delay.cc | 2 +- crawl-ref/source/describe.cc | 5 +- crawl-ref/source/directn.cc | 10 +- crawl-ref/source/effects.cc | 16 +- crawl-ref/source/enum.h | 50 +- crawl-ref/source/externs.h | 2 +- crawl-ref/source/food.cc | 4 - crawl-ref/source/item_use.cc | 18 +- crawl-ref/source/itemname.cc | 4 - crawl-ref/source/items.cc | 2 +- crawl-ref/source/message.cc | 2 +- crawl-ref/source/monplace.cc | 12 +- crawl-ref/source/monstuff.cc | 27 +- crawl-ref/source/mutation.cc | 16 +- crawl-ref/source/player.cc | 19 +- crawl-ref/source/religion.cc | 88 +-- crawl-ref/source/skills.cc | 24 +- crawl-ref/source/stuff.cc | 3 +- crawl-ref/source/travel.cc | 21 +- crawl-ref/source/tutorial.cc | 922 +++++++++++++++++++++-------- crawl-ref/source/tutorial.h | 5 +- crawl-ref/source/view.cc | 8 +- 24 files changed, 883 insertions(+), 452 deletions(-) (limited to 'crawl-ref/source') diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 9f80d6db9a..2677bff431 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -247,7 +247,7 @@ int main( int argc, char *argv[] ) const bool game_start = _initialise(); - // override some options for tutorial + // Override some options for tutorial. init_tutorial_options(); msg::stream << "Welcome, " << you.your_name << " the " @@ -264,15 +264,17 @@ int main( int argc, char *argv[] ) _god_greeting_message( game_start ); - // warn player about their weapon, if unsuitable + // Warn player about their weapon, if unsuitable. wield_warning(false); - if ( game_start ) + if (game_start) { if (Options.tutorial_left) _startup_tutorial(); _take_starting_note(); } + else + learned_something_new(TUT_LOAD_SAVED_GAME); while (true) _input(); @@ -1215,11 +1217,8 @@ static bool _recharge_rod( item_def &rod, bool wielded ) static void _recharge_rods() { const int wielded = you.equip[EQ_WEAPON]; - if (wielded != -1) - { - if (_recharge_rod( you.inv[wielded], true )) - return ; - } + if (wielded != -1 && _recharge_rod( you.inv[wielded], true )) + return; for (int i = 0; i < ENDOFPACK; ++i) { @@ -1259,7 +1258,7 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_READ_MESSAGES: case CMD_SEARCH_STASHES: mpr("You can't repeat informational commands."); - return false; + return (false); // Multi-turn commands case CMD_PICKUP: @@ -1275,7 +1274,7 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_EXPLORE: case CMD_INTERLEVEL_TRAVEL: mpr("You can't repeat multi-turn commands."); - return false; + return (false); // Miscellaneous non-repeatable commands. case CMD_TOGGLE_AUTOPICKUP: @@ -1297,20 +1296,20 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_MAKE_NOTE: case CMD_CYCLE_QUIVER_FORWARD: mpr("You can't repeat that command."); - return false; + return (false); case CMD_DISPLAY_MAP: mpr("You can't repeat map commands."); - return false; + return (false); case CMD_MOUSE_MOVE: case CMD_MOUSE_CLICK: mpr("You can't repeat mouse clicks or movements."); - return false; + return (false); case CMD_REPEAT_CMD: mpr("You can't repeat the repeat command!"); - return false; + return (false); case CMD_RUN_LEFT: case CMD_RUN_DOWN: @@ -1321,14 +1320,14 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_RUN_UP_RIGHT: case CMD_RUN_DOWN_RIGHT: mpr("Why would you want to repeat a run command?"); - return false; + return (false); case CMD_PREV_CMD_AGAIN: ASSERT(!is_again); if (crawl_state.prev_cmd == CMD_NO_CMD) { mpr("No previous command to repeat."); - return false; + return (false); } return _cmd_is_repeatable(crawl_state.prev_cmd, true); @@ -1336,7 +1335,7 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_MOVE_NOWHERE: case CMD_REST: case CMD_SEARCH: - return i_feel_safe(true); + return (i_feel_safe(true)); case CMD_MOVE_LEFT: case CMD_MOVE_DOWN: @@ -1347,20 +1346,22 @@ static bool _cmd_is_repeatable(command_type cmd, bool is_again = false) case CMD_MOVE_UP_RIGHT: case CMD_MOVE_DOWN_RIGHT: if (!i_feel_safe()) + { return yesno("Really repeat movement command while monsters " "are nearby?", false, 'n'); + } - return true; + return (true); case CMD_NO_CMD: mpr("Unknown command, not repeating."); - return false; + return (false); default: - return true; + return (true); } - return false; + return (false); } // Used to determine whether to apply the berserk penalty at end of round. @@ -1390,15 +1391,19 @@ static void _input() fire_monster_alerts(); - Options.tut_just_triggered = false; - bool player_feels_safe = i_feel_safe(); - // He, we don't want those "Whew, it's safe to rest now" messages when - // you were just cast into the Abyss. Right? - if (player_feels_safe && you.level_type != LEVEL_ABYSS) + if (Options.tutorial_left) { - if (Options.tutorial_left) + Options.tut_just_triggered = false; + + if (you.attribute[ATTR_HELD]) + { + learned_something_new(TUT_CAUGHT_IN_NET); + } + // We don't want those "Whew, it's safe to rest now" messages when + // you were just cast into the Abyss. Right? + else if (player_feels_safe && you.level_type != LEVEL_ABYSS) { if (2 * you.hp < you.hp_max || 2 * you.magic_points < you.max_magic_points) @@ -1422,14 +1427,14 @@ static void _input() learned_something_new(TUT_MAP_VIEW); } } - } - else - { - if (2*you.hp < you.hp_max) - learned_something_new(TUT_RUN_AWAY); + else + { + if (2*you.hp < you.hp_max) + learned_something_new(TUT_RUN_AWAY); - if (Options.tutorial_type == TUT_MAGIC_CHAR && you.magic_points < 1) - learned_something_new(TUT_RETREAT_CASTER); + if (Options.tutorial_type == TUT_MAGIC_CHAR && you.magic_points < 1) + learned_something_new(TUT_RETREAT_CASTER); + } } if (you.cannot_act()) diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index 4ef184552f..215658c4e4 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -2248,7 +2248,7 @@ w:5 @The_monster@ seems like @pronoun@ is about to say something to you, then stops. -@The_monster@ says, "When this is all over, I'm going to start a fungus farm." +@The_monster@ @mutters@, "When this is all over, I'm going to start a fungus farm." %%%% ################################################ # Make this work for other predefined orcs! diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index d038ce7c9a..81f8aba5ca 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -1656,7 +1656,7 @@ inline static void _monster_warning(activity_interrupt_type ai, { std::string text = mon->name(DESC_CAP_A); // For named monsters also mention the base type. - if (!(mon->mname).empty()) + if (!(mon->mname).empty() && mon->type != MONS_PLAYER_GHOST) text += " the " + mon->name(DESC_BASENAME); if (at.context == "thin air") diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 120f9de79c..379ca1f684 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1641,7 +1641,7 @@ std::string get_item_description( const item_def &item, bool verbose, break; // intentional fall-through case OBJ_FOOD: - if (item.sub_type == FOOD_CHUNK) + if (item.base_type == OBJ_CORPSES || item.sub_type == FOOD_CHUNK) { if (food_is_rotten(item)) { @@ -1682,13 +1682,14 @@ std::string get_item_description( const item_def &item, bool verbose, case CE_CONTAMINATED: if (player_mutation_level(MUT_SAPROVOROUS) < 3) { - description << "$$Chunks like this may occasionally cause " + description << "$$Meat like this may occasionally cause " "sickness."; } break; default: break; } + if (is_good_god(you.religion) && is_player_same_species(item.plus) || you.religion == GOD_ZIN && mons_intel(item.plus) >= I_NORMAL) diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 0437b72ca0..9bcc52bb8c 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -2112,7 +2112,7 @@ static std::string _stair_destination_description(const coord_def &pos) static void _describe_monster(const monsters *mon) { - // first print type and equipment + // First print type and equipment. std::string text = get_monster_desc(mon); text += "."; print_formatted_paragraph(text, get_number_of_cols()); @@ -2346,9 +2346,9 @@ static void _describe_cell(int mx, int my) { std::string msg; #ifdef USE_TILE - msg = "(Right-click for more information.)"; + msg = "(Right-click for more information.)"; #else - msg = "(Press v for more information.)"; + msg = "(Press v for more information.)"; #endif print_formatted_paragraph(msg, get_number_of_cols()); } @@ -2427,9 +2427,9 @@ static void _describe_cell(int mx, int my) if (Options.tutorial_left && tutorial_pos_interesting(mx, my)) { #ifdef USE_TILE - feature_desc += " (Right-click for more information.)"; + feature_desc += " (Right-click for more information.)"; #else - feature_desc += " (Press v for more information.)"; + feature_desc += " (Press v for more information.)"; #endif print_formatted_paragraph(feature_desc, get_number_of_cols()); } diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index f391c4520c..bf88181561 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -1959,29 +1959,27 @@ void yell(bool force) } mpr("What do you say?", MSGCH_PROMPT); - mprf(" t - %s", cap_shout.c_str()); + mprf(" t - %s!", cap_shout.c_str()); if (!you.duration[DUR_BERSERKER]) { - mpr(" a - Order allies to attack a monster"); - + std::string previous = ""; if (!(you.prev_targ == MHITNOT || you.prev_targ == MHITYOU)) { monsters *target = &menv[you.prev_targ]; if (target->alive() && mons_near(target) && player_monster_visible(target)) { - mpr(" p - Order allies to attack your previous target"); + previous = " p - Attack previous target."; targ_prev = true; } } - mpr(" s - Order allies to stop attacking"); - mpr(" w - Order allies to wait here"); - mpr(" f - Order allies to follow you"); + mprf("Orders for allies: a - Attack new target.%s", previous.c_str()); + mpr( " s - Stop attacking."); + mpr( " w - Wait here. f - Follow me."); } - - mprf(" Anything else - Stay silent%s", + mprf(" Anything else - Stay silent%s.", one_chance_in(20)? " (and be thought a fool)" : ""); unsigned char keyn = get_ch(); diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 32d5efbd46..d9fb425c16 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -2669,82 +2669,90 @@ enum trap_type // env.trap_type[] TRAP_RANDOM = 255 // set at 255 to avoid potential conflicts {dlb} }; -// any change in this list warrants an increase in the -// version number in tutorial.cc +// Any change in this list warrants an increase in the version number in +// tutorial.cc. enum tutorial_event_type { - TUT_SEEN_FIRST_OBJECT, // 0 + TUT_SEEN_FIRST_OBJECT, // 0 // seen certain items TUT_SEEN_POTION, TUT_SEEN_SCROLL, TUT_SEEN_WAND, TUT_SEEN_SPBOOK, - TUT_SEEN_JEWELLERY, // 5 + TUT_SEEN_JEWELLERY, // 5 TUT_SEEN_MISC, TUT_SEEN_STAFF, TUT_SEEN_WEAPON, TUT_SEEN_MISSILES, - TUT_SEEN_ARMOUR, // 10 + TUT_SEEN_ARMOUR, // 10 TUT_SEEN_RANDART, TUT_SEEN_FOOD, TUT_SEEN_CARRION, TUT_SEEN_GOLD, // encountered dungeon features - TUT_SEEN_STAIRS, // 15 + TUT_SEEN_STAIRS, // 15 TUT_SEEN_ESCAPE_HATCH, TUT_SEEN_BRANCH, TUT_SEEN_TRAP, TUT_SEEN_ALTAR, - TUT_SEEN_SHOP, // 20 + TUT_SEEN_SHOP, // 20 TUT_SEEN_DOOR, TUT_SEEN_SECRET_DOOR, // other 'first events' TUT_SEEN_MONSTER, TUT_MONSTER_BRAND, - TUT_MONSTER_FRIENDLY, // 25 + TUT_MONSTER_FRIENDLY, // 25 TUT_KILLED_MONSTER, TUT_NEW_LEVEL, TUT_SKILL_RAISE, + TUT_GAINED_MAGICAL_SKILL, + TUT_GAINED_MELEE_SKILL, // 30 + TUT_GAINED_RANGED_SKILL, + TUT_CHOOSE_STAT, TUT_MAKE_CHUNKS, - TUT_OFFER_CORPSE, // 30 - TUT_NEW_ABILITY, + TUT_OFFER_CORPSE, + TUT_NEW_ABILITY, // 35 TUT_FLEEING_MONSTER, TUT_ROTTEN_FOOD, TUT_CONVERT, - TUT_GOD_DISPLEASED, // 35 - TUT_EXCOMMUNICATE, + TUT_GOD_DISPLEASED, + TUT_EXCOMMUNICATE, // 40 TUT_SPELL_MISCAST, TUT_SPELL_HUNGER, TUT_GLOWING, + TUT_YOU_RESIST, // status changes - TUT_YOU_ENCHANTED, // 40 + TUT_YOU_ENCHANTED, // 45 TUT_YOU_SICK, TUT_YOU_POISON, TUT_YOU_ROTTING, TUT_YOU_CURSED, - TUT_YOU_HUNGRY, // 45 + TUT_YOU_HUNGRY, // 50 TUT_YOU_STARVING, TUT_YOU_MUTATED, + TUT_CAN_BERSERK, TUT_POSTBERSERK, + TUT_CAUGHT_IN_NET, // 55 // warning TUT_RUN_AWAY, - TUT_RETREAT_CASTER, // 50 + TUT_RETREAT_CASTER, TUT_WIELD_WEAPON, TUT_NEED_HEALING, - TUT_NEED_POISON_HEALING, + TUT_NEED_POISON_HEALING, // 60 TUT_INVISIBLE_DANGER, - TUT_NEED_HEALING_INVIS, // 55 + TUT_NEED_HEALING_INVIS, TUT_ABYSS, // interface TUT_MULTI_PICKUP, - TUT_HEAVY_LOAD, + TUT_HEAVY_LOAD, // 65 TUT_SHIFT_RUN, - TUT_MAP_VIEW, // 60 + TUT_MAP_VIEW, TUT_DONE_EXPLORE, TUT_STAIR_BRAND, - TUT_EVENTS_NUM // 63 + TUT_LOAD_SAVED_GAME, // 70 + TUT_EVENTS_NUM // 71 }; -// NOTE: For numbers higher than 70 change size of tutorial_events in externs.h. +// NOTE: For numbers higher than 75 change size of tutorial_events in externs.h. enum tutorial_types { diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 3cbf438d20..2aaae1d938 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -1888,7 +1888,7 @@ public: /////////////////////////////////////////////////////////////////////// // tutorial - FixedVector tutorial_events; + FixedVector tutorial_events; bool tut_explored; bool tut_stashes; bool tut_travel; diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index a964d9e753..779faab8c9 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -398,8 +398,6 @@ static bool _have_corpses_in_pack(bool remind) pronoun = "them"; } - std::ostringstream text; - if (remind) { mprf("You might want to also %s the %s in your pack.", verb.c_str(), @@ -411,8 +409,6 @@ static bool _have_corpses_in_pack(bool remind) verb.c_str(), noun.c_str(), pronoun.c_str()); } - mpr(text.str().c_str()); - return (true); } diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index 0ce876643e..b524f4a78a 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -2814,7 +2814,7 @@ void jewellery_wear_effects(item_def &item) xom_is_stimulated(128); } - // cursed or not, we know that since we've put the ring on + // Cursed or not, we know that since we've put the ring on. set_ident_flags( item, ISFLAG_KNOW_CURSE ); mpr( item.name(DESC_INVENTORY_EQUIP).c_str() ); @@ -4373,6 +4373,7 @@ void read_scroll( int slot ) { // Also sets wield_change. do_curse_item( you.inv[nthing], false ); + learned_something_new(TUT_YOU_CURSED); } break; @@ -4459,10 +4460,10 @@ void read_scroll( int slot ) break; case SCR_ENCHANT_ARMOUR: - if ( !item_type_known(scroll) ) - id_the_scroll = scroll_modify_item(which_scroll); + if (!item_type_known(scroll)) + id_the_scroll = scroll_modify_item(which_scroll); else - _handle_enchant_armour(-1); + _handle_enchant_armour(-1); break; case SCR_CURSE_ARMOUR: @@ -4485,11 +4486,10 @@ void read_scroll( int slot ) id_the_scroll = false; break; } - else - { - // Make the name before we curse it. - do_curse_item( you.inv[you.equip[affected]], false ); - } + + // Make the name before we curse it. + do_curse_item( you.inv[you.equip[affected]], false ); + learned_something_new(TUT_YOU_CURSED); break; case SCR_HOLY_WORD: diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index 41fabbd8bc..0e0441d786 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -2355,10 +2355,6 @@ bool is_useless_item(const item_def &item, bool temp) case OBJ_ARMOUR: return (!can_wear_armour(item, false, true)); - case OBJ_BOOKS: - return (item.sub_type != BOOK_DESTRUCTION - && item.sub_type != BOOK_MANUAL && you.religion == GOD_TROG); - case OBJ_SCROLLS: if (!item_type_known(item)) return (false); diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc index d9c9f5a89a..7eb738e89d 100644 --- a/crawl-ref/source/items.cc +++ b/crawl-ref/source/items.cc @@ -701,7 +701,7 @@ static int _item_name_specialness(const item_def& item) } if (item_type_known(item)) { - if ( is_artefact(item) ) + if (is_artefact(item)) return 2; // XXX Unite with l_item_branded() in clua.cc diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 159af003eb..72a381bafb 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -861,7 +861,7 @@ void more(void) message_out(crawl_view.msgsz.y - 1, LIGHTGREY, "--more-- " - "Press Ctrl-P to reread old messages", + "Press Ctrl-P to reread old messages.", 2, false); } else diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index 43651ad435..5a737f1b2b 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -2466,7 +2466,7 @@ bool monster_pathfind::calc_path_to_neighbours() dist[npos.x][npos.y] = distance; // Set backtracking information. - // Converts the Compass direction to their counterpart. + // Converts the Compass direction to its counterpart. // 0 1 2 4 5 6 // 7 . 3 ==> 3 . 7 e.g. (3 + 4) % 8 = 7 // 6 5 4 2 1 0 (7 + 4) % 8 = 11 % 8 = 3 @@ -2557,11 +2557,11 @@ std::vector monster_pathfind::backtrack() // Reduces the path coordinates to only a couple of key waypoints needed // to reach the target. Waypoints are chosen such that from one waypoint you -// can only just see the next one. Note that grid_see_grid() is probably -// rather too conservative in these estimates. -// This is done because Crawl's path finding once a target can be seen is -// very robust and because it allows for more natural traversing if there are -// other monsters in the way. +// can see (and, more importantly, reach) the next one. Note that +// grid_see_grid() is probably rather too conservative in these estimates. +// This is done because Crawl's pathfinding once a target is in sight and easy +// reach is both very robust and natural, especially if we want to flexibly +// avoid plants and other monsters in the way. std::vector monster_pathfind::calc_waypoints() { diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 627f0d68ef..ec702a54df 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -2833,20 +2833,24 @@ static void _handle_behaviour(monsters *mon) range = 3; break; case I_ANIMAL: - range = 5; + range = 4; break; case I_NORMAL: - range = 10; + range = 8; break; default: // Highly intelligent monsters can find their way - // anywhere. - range = 0; + // anywhere. (range == 0 means no restriction.) break; } - if (range && native) - range += 3; + if (range) + { + if (native) + range += 3; + else if (mons_class_flag(mon->type, M_BLOOD_SCENT)) + range++; + } if (range > 0 && dist > range) { @@ -3116,10 +3120,10 @@ static void _handle_behaviour(monsters *mon) // currently no distinction between smart and // stupid monsters when it comes to travelling // back to the patrol point. This is in part due - // to the flavourness of bees finding their way - // back to the Hive (patrolling should really be - // restricted to cases like this), and for the - // other part it's not that important because + // to the flavour in e.g. bees finding their way + // back to the Hive (and patrolling should really + // be restricted to cases like this), and for the + // other part it's not all that important because // we calculate the path once and then follow it // home, and the player won't ever see the // orderly fashion the bees will trudge along. @@ -3139,8 +3143,7 @@ static void _handle_behaviour(monsters *mon) else { // We're so close we don't even need - // a path. (Shouldn't happen as that - // should have been found above.) + // a path. mon->target_x = mon->patrol_point.x; mon->target_y = mon->patrol_point.y; } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 078cf67eae..7b8a24976f 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -1069,15 +1069,15 @@ formatted_string describe_mutations() break; case SP_NAGA: - if ( you.mutation[MUT_DEFORMED] > 1) + if (you.mutation[MUT_DEFORMED] > 1) result += ""; result += naga_deformed_descrip[you.mutation[MUT_DEFORMED] - 1]; - if ( you.mutation[MUT_DEFORMED] > 1) + if (you.mutation[MUT_DEFORMED] > 1) result += ""; result += EOL; result += "You cannot wear boots." EOL; - // breathe poison replaces spit poison + // Breathe poison replaces spit poison. if (!you.mutation[MUT_BREATHE_POISON]) result += "You can spit poison." EOL; else @@ -1086,8 +1086,8 @@ formatted_string describe_mutations() "" EOL ; } - // slowness can be overridden - if ( you.mutation[MUT_FAST] ) + // Slowness can be overridden. + if (you.mutation[MUT_FAST]) result += ""; result += naga_speed_descrip[you.mutation[MUT_FAST]]; if ( you.mutation[MUT_FAST] ) @@ -1097,7 +1097,7 @@ formatted_string describe_mutations() break; case SP_TROLL: - if ( you.mutation[MUT_CLAWS] ) + if (you.mutation[MUT_CLAWS]) result += ""; result += troll_claw_descrip[you.mutation[MUT_CLAWS]]; if ( you.mutation[MUT_CLAWS] ) @@ -1107,10 +1107,10 @@ formatted_string describe_mutations() break; case SP_CENTAUR: - if ( you.mutation[MUT_DEFORMED] > 1) + if (you.mutation[MUT_DEFORMED] > 1) result += ""; result += centaur_deformed_descrip[you.mutation[MUT_DEFORMED] - 1]; - if ( you.mutation[MUT_DEFORMED] > 1) + if (you.mutation[MUT_DEFORMED] > 1) result += ""; result += EOL; have_any = true; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index f5214973fd..a8f4d8f79d 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -2186,11 +2186,13 @@ bool player_light_armour(bool with_skill) const int arm = you.equip[EQ_BODY_ARMOUR]; if (arm == -1) - return true; + return (true); - if (with_skill && - property(you.inv[arm], PARM_EVASION) + you.skills[SK_ARMOUR]/3 >= 0) - return true; + if (with_skill + && property(you.inv[arm], PARM_EVASION) + you.skills[SK_ARMOUR]/3 >= 0) + { + return (true); + } return (is_light_armour(you.inv[arm])); } // end player_light_armour() @@ -2925,13 +2927,15 @@ void level_change(bool skip_attribute_increase) inc_hp( 4, true ); inc_mp( 1, true ); } - else // character has gained a new level + else // Character has gained a new level { if (you.experience_level == 27) mprf(MSGCH_INTRINSIC_GAIN, "You have reached level 27, the final one!"); else + { mprf(MSGCH_INTRINSIC_GAIN, "You have reached level %d!", - you.experience_level ); + you.experience_level); + } if (!skip_more) more(); @@ -3178,7 +3182,7 @@ void level_change(bool skip_attribute_increase) case SP_WHITE_DRACONIAN: case SP_GREEN_DRACONIAN: case SP_YELLOW_DRACONIAN: -/* Grey is later */ + // Grey is handled later. case SP_BLACK_DRACONIAN: case SP_PURPLE_DRACONIAN: case SP_MOTTLED_DRACONIAN: @@ -3626,6 +3630,7 @@ static void _attribute_increase() mpr("Your experience leads to an increase in your attributes!", MSGCH_INTRINSIC_GAIN); + learned_something_new(TUT_CHOOSE_STAT); more(); mesclr(); diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 813a1979dd..0a0d2ad4a3 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -2713,11 +2713,16 @@ bool is_evil_item(const item_def& item) bool god_dislikes_item_handling(const item_def &item) { - return (item_type_known(item) - && (is_good_god(you.religion) && is_evil_item(item) - || you.religion == GOD_TROG && item.base_type == OBJ_BOOKS - && item.sub_type != BOOK_MANUAL - && item.sub_type != BOOK_DESTRUCTION)); + if (you.religion == GOD_TROG) + { + return (item.base_type == OBJ_BOOKS + && item.sub_type != BOOK_MANUAL + && (!item_type_known(item) + || item.sub_type != BOOK_DESTRUCTION)); + } + + return (is_good_god(you.religion) && is_evil_item(item) + && item_type_known(item)); } // Is the destroyed weapon valuable enough to gain piety by doing so? @@ -2810,7 +2815,7 @@ bool ely_destroy_weapons() return success; } -// returns false if invocation fails (no books in sight etc.) +// Returns false if the invocation fails (no books in sight etc.). bool trog_burn_books() { if (you.religion != GOD_TROG) @@ -2877,47 +2882,44 @@ bool trog_burn_books() continue; } - rarity += book_rarity(mitm[i].sub_type); - // Piety increases by 2 for books never picked up, else by 1. - if (mitm[i].flags & ISFLAG_DROPPED - || mitm[i].flags & ISFLAG_THROWN) - { - totalpiety++; - } - else - totalpiety += 2; + rarity += book_rarity(mitm[i].sub_type); + // Piety increases by 2 for books never cracked open, else 1. + // Conversely, rarity influences the duration of the pyre. + if (!item_type_known(mitm[i])) + totalpiety += 2; + else + totalpiety++; #ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Burned book rarity: %d", rarity); + mprf(MSGCH_DIAGNOSTICS, "Burned book rarity: %d", rarity); #endif + destroy_item(i); + count++; + i = next; + } + + if (count) + { + if (cloud != EMPTY_CLOUD) + { + // Reinforce the cloud. + mpr( "The fire roars with new energy!" ); + const int extra_dur = count + random2(rarity/2); + env.cloud[cloud].decay += extra_dur * 5; + env.cloud[cloud].whose = KC_YOU; + continue; + } - destroy_item(i); - count++; - i = next; - } - - if (count) - { - if ( cloud != EMPTY_CLOUD ) - { - // reinforce the cloud - mpr( "The fire roars with new energy!" ); - const int extra_dur = count + random2(rarity/2); - env.cloud[cloud].decay += extra_dur * 5; - env.cloud[cloud].whose = KC_YOU; - continue; - } - - int durat = 4 + count + random2(rarity/2); - - if (durat > 23) - durat = 23; - - place_cloud( CLOUD_FIRE, xpos, ypos, durat, KC_YOU ); - - mpr(count == 1 ? "The book bursts into flames." - : "The books burst into flames.", MSGCH_GOD); - } + int durat = 4 + count + random2(rarity/2); + + if (durat > 23) + durat = 23; + + place_cloud( CLOUD_FIRE, xpos, ypos, durat, KC_YOU ); + + mpr(count == 1 ? "The book bursts into flames." + : "The books burst into flames.", MSGCH_GOD); + } } diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc index bc696f93d8..4bdc9b55a8 100644 --- a/crawl-ref/source/skills.cc +++ b/crawl-ref/source/skills.cc @@ -188,7 +188,7 @@ static int _exercise2( int exsk ) // being good at some weapons makes others easier to learn: if (exsk < SK_ARMOUR) { - /* blades to blades */ + // Blades to Blades. if ((exsk == SK_SHORT_BLADES || exsk == SK_LONG_BLADES) && (you.skills[SK_SHORT_BLADES] > you.skills[exsk] || you.skills[SK_LONG_BLADES] > you.skills[exsk])) @@ -196,7 +196,7 @@ static int _exercise2( int exsk ) bonus += random2(3); } - /* Axes and Polearms */ + // Axes and Polearms. if ((exsk == SK_AXES || exsk == SK_POLEARMS) && (you.skills[SK_AXES] > you.skills[exsk] || you.skills[SK_POLEARMS] > you.skills[exsk])) @@ -204,7 +204,7 @@ static int _exercise2( int exsk ) bonus += random2(3); } - /* Polearms and Staves */ + // Polearms and Staves. if ((exsk == SK_POLEARMS || exsk == SK_STAVES) && (you.skills[SK_POLEARMS] > you.skills[exsk] || you.skills[SK_STAVES] > you.skills[exsk])) @@ -212,7 +212,7 @@ static int _exercise2( int exsk ) bonus += random2(3); } - /* Axes and Maces */ + // Axes and Maces. if ((exsk == SK_AXES || exsk == SK_MACES_FLAILS) && (you.skills[SK_AXES] > you.skills[exsk] || you.skills[SK_MACES_FLAILS] > you.skills[exsk])) @@ -220,7 +220,7 @@ static int _exercise2( int exsk ) bonus += random2(3); } - /* Slings and Throwing */ + // Slings and Throwing. if ((exsk == SK_SLINGS || exsk == SK_THROWING) && (you.skills[SK_SLINGS] > you.skills[exsk] || you.skills[SK_THROWING] > you.skills[exsk])) @@ -234,7 +234,7 @@ static int _exercise2( int exsk ) if (exsk == SK_STEALTH) bonus += random2(3); - // spell casting is cheaper early on, and elementals hinder each other + // Spellcasting is cheaper early on, and elementals hinder each other. if (exsk >= SK_SPELLCASTING) { if (you.skill_cost_level < 5) @@ -247,7 +247,7 @@ static int _exercise2( int exsk ) skill_change /= 20; } - // being good at elemental magic makes other elements harder to learn: + // Being good at elemental magic makes other elements harder to learn. if (exsk >= SK_FIRE_MAGIC && exsk <= SK_EARTH_MAGIC && (you.skills[SK_FIRE_MAGIC] > you.skills[exsk] || you.skills[SK_ICE_MAGIC] > you.skills[exsk] @@ -258,12 +258,12 @@ static int _exercise2( int exsk ) return (0); } - // some are direct opposites + // Some are direct opposites. if ((exsk == SK_FIRE_MAGIC || exsk == SK_ICE_MAGIC) && (you.skills[SK_FIRE_MAGIC] > you.skills[exsk] || you.skills[SK_ICE_MAGIC] > you.skills[exsk])) { - // of course, this is cumulative with the one above. + // Of course, this is cumulative with the one above. if (!one_chance_in(3)) return (0); } @@ -276,7 +276,7 @@ static int _exercise2( int exsk ) return (0); } - // experimental restriction (too many spell schools) -- bwr + // Experimental restriction (too many spell schools). -- bwr int skill_rank = 1; for (i = SK_CONJURATIONS; i <= SK_DIVINATIONS; i++) @@ -293,7 +293,7 @@ static int _exercise2( int exsk ) int spending_limit = (you.exp_available < MAX_SPENDING_LIMIT) ? you.exp_available : MAX_SPENDING_LIMIT; - // handle fractional learning + // Handle fractional learning. if (skill_change > spending_limit) { // This system is a bit hard on missile weapons in the late game @@ -415,6 +415,8 @@ static int _exercise2( int exsk ) { mprf(MSGCH_INTRINSIC_GAIN, "You have gained %s skill!", skill_name( exsk ) ); + + tut_gained_new_skill(exsk); } else { diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index bebf74d937..a03bb0cc5b 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -831,13 +831,14 @@ void canned_msg(canned_message_type which_message) case MSG_SOMETHING_APPEARS: mprf("Something appears %s!", (you.species == SP_NAGA || player_mutation_level(MUT_HOOVES)) - ? "before you" : "at your feet"); + ? "before you" : "at your feet"); break; case MSG_NOTHING_HAPPENS: mpr("Nothing appears to happen."); break; case MSG_YOU_RESIST: mpr("You resist."); + learned_something_new(TUT_YOU_RESIST); break; case MSG_YOU_PARTIALLY_RESIST: mpr("You partially resist."); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 08abb41ec7..27a21f3010 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -1437,17 +1437,18 @@ coord_def travel_pathfind::pathfind(run_mode_type rmode) ignore_hostile = false; - // Set the seed point. // For each round, circumference will store all points that were discovered - // in the previous round of a given distance. We use an array of size 2, - // so we can comfortably switch between the list of points to be - // investigated this round and the slowly growing list of points to be - // inspected next round. Once we've finished with the current round, i.e. - // there are no more points to be looked at in the current array, we switch - // circ_index over to !circ_index (between 0 and 1), so the "next round" - // becomes the current one, and the old points can be overwritten with - // newer ones. Since we count the number of points for next round in - // next_iter_points, we don't even need to reset the array. + // in the previous round of a given distance. Because we check all grids of + // a certain distance from the starting point in one round, and move + // outwards in concentric circles, this is an implementation of Dijkstra. + // We use an array of size 2, so we can comfortably switch between the list + // of points to be investigated this round and the slowly growing list of + // points to be inspected next round. Once we've finished with the current + // round, i.e. there are no more points to be looked at in the current + // array, we switch circ_index over to !circ_index (between 0 and 1), so + // the "next round" becomes the current one, and the old points can be + // overwritten with newer ones. Since we count the number of points for + // next round in next_iter_points, we don't even need to reset the array. circumference[circ_index][0] = start; // Zap out previous distances array diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index 42c24e53b2..7abc98742d 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -9,12 +9,14 @@ */ #include "AppHdr.h" +#include "cio.h" #include #include #include "tutorial.h" -#include "cio.h" + +#include "abl-show.h" #include "cloud.h" #include "command.h" #include "food.h" @@ -29,6 +31,7 @@ #include "mon-pick.h" #include "mon-util.h" #include "monstuff.h" +#include "mutation.h" #include "newgame.h" #include "output.h" #include "player.h" @@ -52,7 +55,7 @@ static void _tutorial_describe_cloud(int x, int y); static bool _water_is_disturbed(int x, int y); //#define TUTORIAL_DEBUG -#define TUTORIAL_VERSION 113 +#define TUTORIAL_VERSION 8 static int _get_tutorial_cols() { @@ -68,7 +71,7 @@ void save_tutorial(writer& outf) { marshallLong( outf, TUTORIAL_VERSION); marshallShort( outf, Options.tutorial_type); - for ( long i = 0; i < TUT_EVENTS_NUM; ++i ) + for (long i = 0; i < TUT_EVENTS_NUM; ++i) marshallShort( outf, Options.tutorial_events[i] ); } @@ -161,7 +164,7 @@ bool pick_tutorial() Options.tut_melee_counter = 0; Options.tut_berserk_counter = 0; - // for occasional healing reminders + // For occasional healing reminders. Options.tut_last_healed = 0; // Did the player recently see a monster turn invisible? @@ -175,7 +178,6 @@ bool pick_tutorial() if (keyn == CK_BKSP || keyn == ' ') { // In this case, undo previous choices. - // set_startup_options(); you.species = SP_UNKNOWN; you.char_class = JOB_UNKNOWN; Options.race = 0; @@ -303,132 +305,144 @@ static std::string _tut_debug_list(int event) { switch(event) { - case TUT_SEEN_FIRST_OBJECT: - return "seen first object"; - case TUT_SEEN_POTION: - return "seen first potion"; - case TUT_SEEN_SCROLL: - return "seen first scroll"; - case TUT_SEEN_WAND: - return "seen first wand"; - case TUT_SEEN_SPBOOK: - return "seen first spellbook"; - case TUT_SEEN_WEAPON: - return "seen first weapon"; - case TUT_SEEN_MISSILES: - return "seen first missiles"; - case TUT_SEEN_ARMOUR: - return "seen first armour"; - case TUT_SEEN_RANDART: - return "seen first random artefact"; - case TUT_SEEN_FOOD: - return "seen first food"; - case TUT_SEEN_CARRION: - return "seen first corpse"; - case TUT_SEE_GOLD: - return "seen first pile of gold"; - case TUT_SEEN_JEWELLERY: - return "seen first jewellery"; - case TUT_SEEN_MISC: - return "seen first misc. item"; - case TUT_SEEN_MONSTER: - return "seen first monster"; - case TUT_SEEN_STAIRS: - return "seen first stairs"; - case TUT_SEEN_ESCAPE_HATCH: - return "seen first escape hatch"; - case TUT_SEEN_BRANCH: - return "seen first branch entrance"; - case TUT_SEEN_TRAP: - return "encountered a trap"; - case TUT_SEEN_ALTAR: - return "seen an altar"; - case TUT_SEEN_SHOP: - return "seen a shop"; - case TUT_SEEN_DOOR: - return "seen a closed door"; - case TUT_SEEN_SECRET_DOOR: - return "found a secret door"; - case TUT_KILLED_MONSTER: - return "killed first monster"; - case TUT_NEW_LEVEL: - return "gained a new level"; - case TUT_SKILL_RAISE: - return "raised a skill"; - case TUT_YOU_ENCHANTED: - return "caught an enchantment"; - case TUT_YOU_SICK: - return "became sick"; - case TUT_YOU_POISON: - return "were poisoned"; - case TUT_YOU_ROTTING: - return "were rotting"; - case TUT_YOU_CURSED: - return "had something cursed"; - case TUT_YOU_HUNGRY: - return "felt hungry"; - case TUT_YOU_STARVING: - return "were starving"; - case TUT_MAKE_CHUNKS: - return "learned about chunks"; - case TUT_OFFER_CORPSE: - return "learned about sacrifice"; - case TUT_MULTI_PICKUP: - return "read about pickup menu"; - case TUT_HEAVY_LOAD: - return "were encumbered"; - case TUT_ROTTEN_FOOD: - return "carried rotten food"; - case TUT_NEED_HEALING: - return "needed healing"; - case TUT_NEED_POISON_HEALING: - return "needed healing for poison"; - case TUT_INVISIBLE_DANGER: - return "encountered an invisible foe"; - case TUT_NEED_HEALING_INVIS: - return "had to heal near an unseen monster"; - case TUT_ABYSS: - return "was cast into the Abyss"; - case TUT_POSTBERSERK: - return "learned about Berserk aftereffects"; - case TUT_RUN_AWAY: - return "were told to run away"; - case TUT_RETREAT_CASTER: - return "were told to retreat as a caster"; - case TUT_SHIFT_RUN: - return "learned about shift-run"; - case TUT_MAP_VIEW: - return "learned about the level map"; - case TUT_DONE_EXPLORE: - return "explored a level"; - case TUT_YOU_MUTATED: - return "caught a mutation"; - case TUT_NEW_ABILITY: - return "gained a divine ability"; - case TUT_WIELD_WEAPON: - return "wielded an unsuitable weapon"; - case TUT_FLEEING_MONSTER: - return "made a monster flee"; - case TUT_MONSTER_BRAND: - return "learned about colour brandings"; - case TUT_MONSTER_FRIENDLY: - return "seen first friendly monster"; - case TUT_CONVERT: - return "converted to a god"; - case TUT_GOD_DISPLEASED: - return "piety ran low"; - case TUT_EXCOMMUNICATE: - return "excommunicated by a god"; - case TUT_SPELL_MISCAST: - return "spell miscast"; - case TUT_SPELL_HUNGER: - return "spell casting caused hunger"; - case TUT_GLOWING: - return "player glowing from contamination"; - case TUT_STAIR_BRAND: - return "saw stairs with objects on it"; - default: - return "faced a bug"; + case TUT_SEEN_FIRST_OBJECT: + return "seen first object"; + case TUT_SEEN_POTION: + return "seen first potion"; + case TUT_SEEN_SCROLL: + return "seen first scroll"; + case TUT_SEEN_WAND: + return "seen first wand"; + case TUT_SEEN_SPBOOK: + return "seen first spellbook"; + case TUT_SEEN_WEAPON: + return "seen first weapon"; + case TUT_SEEN_MISSILES: + return "seen first missiles"; + case TUT_SEEN_ARMOUR: + return "seen first armour"; + case TUT_SEEN_RANDART: + return "seen first random artefact"; + case TUT_SEEN_FOOD: + return "seen first food"; + case TUT_SEEN_CARRION: + return "seen first corpse"; + case TUT_SEE_GOLD: + return "seen first pile of gold"; + case TUT_SEEN_JEWELLERY: + return "seen first jewellery"; + case TUT_SEEN_MISC: + return "seen first misc. item"; + case TUT_SEEN_MONSTER: + return "seen first monster"; + case TUT_SEEN_STAIRS: + return "seen first stairs"; + case TUT_SEEN_ESCAPE_HATCH: + return "seen first escape hatch"; + case TUT_SEEN_BRANCH: + return "seen first branch entrance"; + case TUT_SEEN_TRAP: + return "encountered a trap"; + case TUT_SEEN_ALTAR: + return "seen an altar"; + case TUT_SEEN_SHOP: + return "seen a shop"; + case TUT_SEEN_DOOR: + return "seen a closed door"; + case TUT_SEEN_SECRET_DOOR: + return "found a secret door"; + case TUT_KILLED_MONSTER: + return "killed first monster"; + case TUT_NEW_LEVEL: + return "gained a new level"; + case TUT_SKILL_RAISE: + return "raised a skill"; + case TUT_YOU_ENCHANTED: + return "caught an enchantment"; + case TUT_YOU_SICK: + return "became sick"; + case TUT_YOU_POISON: + return "were poisoned"; + case TUT_YOU_ROTTING: + return "were rotting"; + case TUT_YOU_CURSED: + return "had something cursed"; + case TUT_YOU_HUNGRY: + return "felt hungry"; + case TUT_YOU_STARVING: + return "were starving"; + case TUT_MAKE_CHUNKS: + return "learned about chunks"; + case TUT_OFFER_CORPSE: + return "learned about sacrifice"; + case TUT_MULTI_PICKUP: + return "read about pickup menu"; + case TUT_HEAVY_LOAD: + return "were encumbered"; + case TUT_ROTTEN_FOOD: + return "carried rotten food"; + case TUT_NEED_HEALING: + return "needed healing"; + case TUT_NEED_POISON_HEALING: + return "needed healing for poison"; + case TUT_INVISIBLE_DANGER: + return "encountered an invisible foe"; + case TUT_NEED_HEALING_INVIS: + return "had to heal near an unseen monster"; + case TUT_ABYSS: + return "was cast into the Abyss"; + case TUT_POSTBERSERK: + return "learned about Berserk after-effects"; + case TUT_RUN_AWAY: + return "were told to run away"; + case TUT_RETREAT_CASTER: + return "were told to retreat as a caster"; + case TUT_SHIFT_RUN: + return "learned about shift-run"; + case TUT_MAP_VIEW: + return "learned about the level map"; + case TUT_DONE_EXPLORE: + return "explored a level"; + case TUT_YOU_MUTATED: + return "caught a mutation"; + case TUT_NEW_ABILITY: + return "gained a divine ability"; + case TUT_WIELD_WEAPON: + return "wielded an unsuitable weapon"; + case TUT_FLEEING_MONSTER: + return "made a monster flee"; + case TUT_MONSTER_BRAND: + return "learned about colour brandings"; + case TUT_MONSTER_FRIENDLY: + return "seen first friendly monster"; + case TUT_CONVERT: + return "converted to a god"; + case TUT_GOD_DISPLEASED: + return "piety ran low"; + case TUT_EXCOMMUNICATE: + return "excommunicated by a god"; + case TUT_SPELL_MISCAST: + return "spell miscast"; + case TUT_SPELL_HUNGER: + return "spell casting caused hunger"; + case TUT_GLOWING: + return "player glowing from contamination"; + case TUT_STAIR_BRAND: + return "saw stairs with objects on it"; + case TUT_YOU_RESIST: + return "resisted some magic"; + case TUT_CAUGHT_IN_NET: + return "were caught in a net"; + case TUT_LOAD_SAVED_GAME: + return "restored a saved game"; + case TUT_GAINED_MAGICAL_SKILL: + return "gained a new magical skill"; + case TUT_CHOOSE_STAT: + return "could choose a stat"; + case TUT_CAN_BERSERK: + return "were told to Berserk"; + default: + return "faced a bug"; } } @@ -495,7 +509,7 @@ static formatted_string _tutorial_map_intro() result += "" EOL; - result += " --more-- Press Escape to skip the basics"; + result += " --more-- Press Escape to skip the basics."; linebreak_string2(result, _get_tutorial_cols()); return formatted_string::parse_block(result, false); @@ -548,7 +562,7 @@ static void _tutorial_message_intro() "you missed something, previous messages can be read again with " "Ctrl-P" #ifdef USE_TILE - " or by clicking into the message area" + " or by clicking into the message area" #endif "." EOL; result += " --more-- Press Escape to skip the basics"; @@ -999,6 +1013,151 @@ void taken_new_item(unsigned char item_type) } } +// Give a special message if you gain a skill you didn't have before. +void tut_gained_new_skill(int skill) +{ + learned_something_new(TUT_SKILL_RAISE); + + switch (skill) + { + // Special cases first. + case SK_FIGHTING: + mpr("Apart from making you more proficient in hand-to-hand combat, " + "Fighting also increases your maximum hitpoints.", MSGCH_TUTORIAL); + break; + + case SK_ARMOUR: + mpr("Armour skill helps lessen the hinderance of heavy armour on " + "moving, spellcasting and other actions.", MSGCH_TUTORIAL); + break; + + case SK_STEALTH: + mpr("By training stealth, you can make it less likely that monsters " + "will notice you. Note that monsters become more suspicious and " + "observant as you descend.", MSGCH_TUTORIAL); + break; + + case SK_STABBING: + mpr("Stabbing is the skill that governs the likeliness of doing a " + "great amount of damage on a distracted or helpless creature. " + "Some gods may disapprove of this.", MSGCH_TUTORIAL); + break; + + case SK_TRAPS_DOORS: + mpr("A character trained in Traps & Doors will be more observant to " + "his or her surroundings and be quicker in noticing traps and " + "secret doors.", MSGCH_TUTORIAL); + break; + + case SK_UNARMED_COMBAT: + { + std::string text; + text = "A character trained in unarmed combat will occasionally do an " + "additional melee attack, provided they have the means to do " + "so."; + + if (you.species == SP_MINOTAUR) + { + text += " For example, with your horns you can do a dangerous " + "headbutt attack."; + } + else if (you.species == SP_CENTAUR) + text += " For example, with your hooves you can kick your enemies."; + + text += " Of course, this skill also trains your proficiency in " + "barehanded combat."; + + mpr(text.c_str(), MSGCH_TUTORIAL); + break; + } + case SK_INVOCATIONS: + mpr("Your Invocations skill affects the likelihood trying to use a " + "divine ability will be successful.", MSGCH_TUTORIAL); + break; + + case SK_EVOCATIONS: + mpr("Evocations is all about using magical items like wands, decks or " + "other objects. The higher your skill, the more likely is a " + "positive outcome when evoking items.", MSGCH_TUTORIAL); + break; + + case SK_DODGING: + mpr("Obviously, the Dodging skill will affect your chance of dodging " + "an attack, be it melee, ranged, or magical. You cannot dodge " + "enchantments, sadly. You'll need magic resistance to resist them.", + MSGCH_TUTORIAL); + break; + + case SK_SHIELDS: + mpr("A high Shields skill of blocking a melee or ranged attack with " + "your equipped (or a magical) shield.", MSGCH_TUTORIAL); + break; + + case SK_THROWING: + mpr("Training Throwing will make thrown weapons (as opposed to ones " + "fired from a launcher) more effective. In particular, it makes " + "weapons of returning more likely to actually return to the " + "thrower.", MSGCH_TUTORIAL); + break; + + case SK_SPELLCASTING: + { + std::string text; + text = "Now that you have the basic Spellcasting skill, you can learn " + "and cast spells, if you wish to. "; + + if (you.religion == GOD_TROG) + text += "Note that Trog will disapprove of this, though."; + else + { + text += "In addition, gaining another level in Spellcasting will " + "occasionally grant your more magic and \"spell slots\" to " + "spend on new spells. A high Spellcasting skill will also " + "decrease the amount by which casting a high level spell " + "makes you hunger."; + } + mpr(text.c_str(), MSGCH_TUTORIAL); + break; + } + // Only one message for all magic skills (except Spellcasting). + case SK_CONJURATIONS: + case SK_ENCHANTMENTS: + case SK_SUMMONINGS: + case SK_NECROMANCY: + case SK_TRANSLOCATIONS: + case SK_TRANSMIGRATION: + case SK_DIVINATIONS: + case SK_FIRE_MAGIC: + case SK_ICE_MAGIC: + case SK_AIR_MAGIC: + case SK_EARTH_MAGIC: + case SK_POISON_MAGIC: + learned_something_new(TUT_GAINED_MAGICAL_SKILL); + break; + + // Melee skills. + case SK_SHORT_BLADES: + case SK_LONG_BLADES: + case SK_AXES: + case SK_MACES_FLAILS: + case SK_POLEARMS: + case SK_STAVES: + learned_something_new(TUT_GAINED_MELEE_SKILL); + break; + + // Ranged skills. + case SK_SLINGS: + case SK_BOWS: + case SK_CROSSBOWS: + case SK_DARTS: + learned_something_new(TUT_GAINED_RANGED_SKILL); + break; + + default: + break; + } +} + #ifndef USE_TILE // As safely as possible, colourize the passed glyph. // Handles quoting "<", MBCS-ing unicode, and @@ -1084,6 +1243,14 @@ void tutorial_first_monster(const monsters &mon) if (mons_friendly(&mon)) learned_something_new(TUT_MONSTER_FRIENDLY); + if (!Options.tut_just_triggered + && one_chance_in(4) + && you.religion == GOD_TROG && !you.duration[DUR_BERSERKER] + && !you.duration[DUR_EXHAUSTED] + && you.hunger_state >= HS_SATIATED) + { + learned_something_new(TUT_CAN_BERSERK); + } return; } @@ -1183,12 +1350,17 @@ void tutorial_first_monster(const monsters &mon) void tutorial_first_item(const item_def &item) { + // Happens if monster is standing on dropped corpse or item. + if (mgrd[item.x][item.y] != NON_MONSTER) + return; + if (!Options.tutorial_events[TUT_SEEN_FIRST_OBJECT] || Options.tut_just_triggered) { // NOTE: Since a new player might not think to pick up a // corpse, TUT_SEEN_CARRION is done when a corpse is first seen. - if (item.base_type == OBJ_CORPSES + if (!Options.tut_just_triggered + && item.base_type == OBJ_CORPSES && mgrd[item.x][item.y] == NON_MONSTER) { learned_something_new(TUT_SEEN_CARRION, item.x, item.y); @@ -1196,10 +1368,6 @@ void tutorial_first_item(const item_def &item) return; } - // happens if monster standing on dropped corpse or item - if (mgrd[item.x][item.y] != NON_MONSTER) - return; - stop_running(); Options.tutorial_events[TUT_SEEN_FIRST_OBJECT] = 0; @@ -1229,11 +1397,14 @@ void tutorial_first_item(const item_def &item) "button while standing on its square. " #endif "Also, several types of objects will usually be picked up " - "automatically. " EOL - "Once it is in your inventory, you can drop it again with " + "automatically. " +#ifdef USE_TILE + "(In Tiles, these will be marked with a green frame around them.)" +#endif + EOL "Once it is in your inventory, you can drop it again with " #ifdef USE_TILE "a left mouse click while pressing the Shift key. " - "Whenever you right-click on an item " + "Whenever you right-click on an item" #else "d. Any time you look at an item in your inventory" #endif @@ -1244,11 +1415,6 @@ void tutorial_first_item(const item_def &item) // Force more() to highlight this item. more(); #endif - - // NOTE: Since a new player might not think to pick up a corpse, - // TUT_SEEN_CARRION is done when a corpse is first seen. - if (item.base_type == OBJ_CORPSES) - learned_something_new(TUT_SEEN_CARRION, item.x, item.y); } static void _new_god_conduct() @@ -1308,7 +1474,7 @@ static void _new_god_conduct() case GOD_TROG: likes.push_back("destroy spell books (especially ones you've" - "never touched) via the a command"); + "never read) via the a command"); break; case GOD_NEMELEX_XOBEH: @@ -1631,7 +1797,11 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) #endif "to wield it, but be aware that this weapon " "might train a different skill from your current one. You can " - "view the weapon's properties from your inventory."; + "view the weapon's properties from your inventory" +#ifdef USE_TILE + " or by right-clicking on it" +#endif + "."; if (Options.tutorial_type == TUT_BERSERK_CHAR) { @@ -1717,9 +1887,9 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) break; case TUT_SEEN_CARRION: - // NOTE: This is called when a corpse is first seen, rather than - // first picked up, since a new player might not think to pick - // up a corpse. + // NOTE: This is called when a corpse is first seen as well as when + // first picked up, since a new player might not think to pick + // up a corpse. if (x <= 0 || y <= 0) text << "Ah, a corpse!"; @@ -1842,6 +2012,13 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "your inventory, takes up no space in your inventory, weighs " "nothing and can't be dropped. Gold can be used to buy " "items from shops, and can also be sacrificed to some gods."; + + if (!Options.show_gold_turns) + { + text << "Whenever you pick up some gold, your current amount will " + "be mentioned. If you'd like to check your wealth at other " + "times, it will be listed on the % screen."; + } break; case TUT_SEEN_STAIRS: @@ -2028,7 +2205,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "C, followed by the direction, or simply " "Ctrl-Direction."; #ifdef USE_TILE - text << "\nIn tiles, the same can be achieved by clicking on an " + text << "\nIn Tiles, the same can be achieved by clicking on an " "adjacent door square."; #endif break; @@ -2101,7 +2278,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "(the Spellcasting skill also does this). For now, you " "should try to memorise the second spell of your " "starting book with Mcb, which can then be zapped " - "zapped with zb."; + "with zb."; #ifdef USE_TILE text << " Memorising is also possible by doing a left " "click on the book in your inventory."; @@ -2114,6 +2291,46 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "skill set, type m."; break; + case TUT_GAINED_MAGICAL_SKILL: + text << "Being skilled in a magical \"school\" makes it easier to " + "learn and cast spells of this school. Many spells belong to " + "a combination of several schools, in which case the average " + "skill in these schools will decide on spellcasting success " + "and power."; + break; + + case TUT_GAINED_MELEE_SKILL: + text << "Being skilled with a particular type of weapon will make it " + "easier to fight with all weapons of this type and make you " + "deal more damage with them. It is generally recommended to " + "concentrate your efforts on one or two weapon types to become " + "more powerful in them. Some weapons are closely related, and " + "being trained in one will ease training the other. This is " + "true for the following pairs: Short Blades/Long Blades, " + "Axes/Polearms, Polearms/Staves, Axes/Maces, and (though not " + "strictly a weapon skill) Slings/Throwing."; + break; + + case TUT_GAINED_RANGED_SKILL: + text << "Being skilled in a particular type of ranged attack will let " + "you deal more damage when using the appropriate weapons. It " + "is usually best to concentrate on one type of ranged attack " + "(including spells), and to add another one as back-up."; + break; + + case TUT_CHOOSE_STAT: + text << "Every third level you may choose what stat to invest in, " + "Strength, Dexterity, or Intelligence.\n" + "Strength influences the amount you can carry, and " + "increases the damage you deal in melee.\n" + "Dexterity increases your evasion and thus influences " + "your chance of dodging attacks or traps.\n" + "Intelligence increases your success in casting spells " + "and decreases the amount by which you hunger when you do so." + "\nNote that it is generally recommended to raise all your " + "stats to a minimum of 7, so as to prevent death by stat loss."; + break; + case TUT_YOU_ENCHANTED: text << "Enchantments of all types can befall you temporarily. " "Brief descriptions of these appear at the lower end of the " @@ -2137,7 +2354,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) text << "wait with 5" #ifdef USE_TILE - "or by clicking onto the stats area" + " or by clicking into the stats area" #endif "), or you could quaff a potion of healing. "; break; @@ -2161,11 +2378,12 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) break; case TUT_YOU_ROTTING: - // Hack: reset tut_just_triggered, to force recursive calling of - // learned_something_new(). + // Hack: Reset tut_just_triggered, to force recursive calling of + // learned_something_new(). Options.tut_just_triggered = false; learned_something_new(TUT_YOU_ENCHANTED); Options.tut_just_triggered = true; + text << "Ugh, your flesh is rotting! Not only does this slowly " "reduce your HP, it also slowly reduces your maximum " "HP (your usual maximum HP will be indicated by a number in " @@ -2256,8 +2474,15 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) text << "How lucky! That monster left a corpse which you can now " "chop up. One or more chunks will appear that you " "can then eat. Beware that some chunks may be, " - "sometimes or always, hazardous. Only experience can help " - "you here."; + "sometimes or always, hazardous. You can find out whether " + "that might be the case by " +#ifdef USE_TILE + "clicking with your right mouse button onto the corpse " + "or chunk."; +#else + "viewing a corpse or chunk on the floor or by having a " + "look at it in your inventory."; +#endif if (you.duration[DUR_PRAYER] && (god_likes_butchery(you.religion) @@ -2320,7 +2545,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "spots; use s, . or for 100 turns with " "5 " #ifdef USE_TILE - "(or alternatively click on the stat area) " + "(or alternatively click into the stat area) " #endif "to do so."; } @@ -2337,7 +2562,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "down stairs. Unexplored parts can often be accessed via " "another level or through secret doors. To find the " "latter, search the adjacent squares of walls for one " - "turn with s or ., or for 100 turns with " + "turn with . or s, or for 100 turns with " "5 or Shift-numpad 5" #ifdef USE_TILE ", or by clicking on the stat area" @@ -2355,7 +2580,7 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "interrupted by a wandering monster. Press 5 or " "shift-numpad-5" #ifdef USE_TILE - ", or click on the stat area" + ", or click into the stat area" #endif " to do so."; break; @@ -2389,6 +2614,16 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) Options.tut_last_healed = you.num_turns; break; + case TUT_CAN_BERSERK: + // Don't print this information if the player already knows it. + if (!Options.tut_berserk_counter) + { + text << "Against particularly difficult foes, you should use your " + "Berserk ability. Berserk will last longer if you " + "kill a lot of monsters."; + } + break; + case TUT_POSTBERSERK: text << "Berserking is extremely exhausting! It burns a lot of " "nutrition, and afterwards you are slowed down and " @@ -2408,10 +2643,10 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "running is an option!"; } - text << "If retreating to another level, keep in mind that monsters " + text << " If retreating to another level, keep in mind that monsters " "may follow you if they're standing right next to you when " "you start climbing or descending the stairs. And even if " - " you'vemanaged to shake them off, they'll still be there when " + "you've managed to shake them off, they'll still be there when " "you come back, though, so you'll want to use a different set " "of stairs when you return."; @@ -2452,14 +2687,18 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) case GOD_KIKUBAAQUDGHA: case GOD_YREDELEMNUL: case GOD_NEMELEX_XOBEH: case GOD_ZIN: case GOD_OKAWARU: case GOD_SIF_MUNA: case GOD_TROG: case GOD_ELYVILON: case GOD_LUGONU: - text << "You just gained a new ability. Press a to " - "take a look at your abilities or to use one of them."; + text << "You just gained a new ability. Press a to " + "take a look at your abilities or to use one of them."; break; // Gods where first granted ability is passive. default: - text << "You just gained a new ability. Press ^ to " - "take a look at your ability."; + text << "You just gained a new ability. Press ^ " +#ifdef USE_TILE + "or press Shift and right-click on the " + "player tile " +#endif + "to take a look at your abilities."; break; } break; @@ -2470,20 +2709,26 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) case TUT_GOD_DISPLEASED: text << "Uh-oh, " << god_name(you.religion) << " is growing " - "displeased because your piety is running low. This can be " - "caused by your doing things to annoy him"; + "displeased because your piety is running low. Possibly this " + "is the case because you're committing heretic acts"; if (!is_good_god(you.religion)) { - // Piety decreases over time for non-good gods - text << ", not doing things to please him frequently enough, or " - "a combination of the two"; + // Piety decreases over time for non-good gods. + text << ", because " << god_name(you.religion) << " finds your " + "worship lacking, or a combination of the two"; } - text << ". "; - - text << "If your piety goes to zero, then you'll be excommunicated. " + text << ". If your piety goes to zero, then you'll be excommunicated. " "Better get cracking on raising your piety, and/or stop " - "annoying your god."; + "annoying your god. "; + + text << "In any case, you'd better reread the religious description. " + "To do so, " +#ifdef USE_TILE + "press Shift and right-click on your avatar."; +#else + "type ^."; +#endif break; case TUT_EXCOMMUNICATE: @@ -2502,49 +2747,87 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) const std::string old_god_name = god_name(old_god); const std::string new_god_name = god_name(new_god); - // FIXME: Modify the tutorial texts to be more generic concerning - // the gods' genders. if (new_god == GOD_NO_GOD) { if (old_piety < 1) { - text << "Uh-oh, " << old_god << " just excommunicated you " + text << "Uh-oh, " << old_god_name << " just excommunicated you " "for running out of piety (your divine favour went " - "to nothing). Maybe you repeatedly annoyed him, " - "or maybe you weren't doing things that pleased him " - "often enough, or some combination of the two. If you " - "can find an altar dedicated to " << old_god; + "to nothing). Maybe you repeatedly violated the " + "religious rules, or maybe you failed to please your " + "deity often enough, or some combination of the two. " + "If you can find an altar dedicated to " + << old_god_name; } else { - text << "If you decide that abandoning " << old_god << "wasn't " - "such a smart move after all, and you'd like to return " - "to your old faith you'll have to find an altar " - "dedicated to " << old_god << " where"; + text << "Should you decide that abandoning " << old_god_name + << "wasn't such a smart move after all, and you'd like to " + "return to your old faith you'll have to find an altar " + "dedicated to " << old_god_name << " where"; } - text << " you can re-convert and all will be well; otherwise " - "you'll have to weather this god's displeasure until their " + text << " you can re-convert, and all will be well. Otherwise " + "you'll have to weather this god's displeasure until all " "divine wrath is spent."; } else { - if (is_good_god(old_god) && is_good_god(new_god)) + bool angry = false; + if (is_good_god(old_god)) { - text << "Fortunately, it seems that " << old_god << " didn't " - "mind you converting to " << new_god << ". This " - "is only the case when converting from one of the " - "three good gods to a different good god, so don't " - "expect this to be the norm."; + if (is_good_god(new_god)) + { + text << "Fortunately, it seems that " << old_god_name << + " didn't mind you converting to " << new_god_name + << ". "; + + if (old_piety > 30) + text << "You even kept some of your piety! "; + + text << "Note that this kind of alliance only exists " + "between the three good gods, so don't expect this " + "to be the norm."; + } + else if (!god_hates_your_god(old_god)) + { + text << "Fortunately, it seems that " << old_god_name << + " didn't mind you converting to " << new_god_name + << ". That's because " << old_god_name << " is one of " + "the good gods who generally are rather forgiving " + "about change of faith - unless you switch over to " + "the path of evil, in which case their retribution " + "can be nasty indeed!"; + } + else + { + text << "Looks like " << old_god_name << " didn't " + "appreciate you converting to " << new_god_name + << "! But really, changing from one of the good gods " + "to an evil one, what did you expect!? For any god " + "not on the opposing side of the faith, " + << old_god_name << " would have been much more " + "forgiving. "; + + angry = true; + } } else { - text << "Looks like " << old_god << " didn't appreciate you " - "converting to " << new_god << "! (It's only safe to " - "convert between the three good gods.) Unfortunately, " - "converting back to " << old_god << " will annoy " - << new_god << ", so you're stuck with having to suffer " - "the wrath of one god or another."; + text << "Looks like " << old_god_name << " didn't appreciate " + "you converting to " << new_god_name << "! (Actually, " + "only the three good gods will sometimes be forgiving " + "about this kind of faithlessness.) "; + + angry = true; + } + + if (angry) + { + text << "Unfortunately, while converting back would appease " + << old_god_name << ", it would annoy " << new_god_name + << ", so you're stuck with having to suffer the wrath of " + "one god or another."; } } @@ -2567,8 +2850,8 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) text << "While unsporting, it is sometimes useful to attack a " "fleeing monster by throwing something after it. To do this, " #ifdef USE_TILE - "in tiles, you can choose your firing " - "ammunition by left-clicking on it with your mouse. " + "you can choose your firing ammunition by left-clicking " + "on it with your mouse. " "In the case of weapons (rather than missiles) you need to " "be pressing Ctrl at the same time, to distinguish " "the action from wielding. Then target the monster by " @@ -2589,11 +2872,11 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) tile_place_cursor(ep.x-1,ep.y-1,true); #endif text << "That monster looks a bit unusual. You might wish to examine " - "it a bit more closely by pressing " + "it a bit more closely by " #ifdef USE_TILE "hovering your mouse over its tile"; #else - "x and moving the cursor onto its square."; + "pressing x and moving the cursor onto its square."; #endif break; @@ -2602,15 +2885,15 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) tile_place_cursor(ep.x-1,ep.y-1,true); #endif text << "That monster is friendly to you and will attack your " - "enemies, though you get only half the experience for " - "monsters killed by allies that you'd get for killing them " + "enemies, though you'll get only half the experience for " + "monsters killed by allies of what you'd get for killing them " "yourself. You can command your allies by pressing t " - "to talk to them, and can tell them which items to pick up " - "(or not pick up) by pressing Ctrl-T."; + "to talk to them."; break; case TUT_SEEN_MONSTER: case TUT_SEEN_FIRST_OBJECT: + // Handled in special functions. break; case TUT_ABYSS: @@ -2618,16 +2901,19 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "place where you cannot remember or map where you've been; it " "is filled with nasty monsters, and you're probably going to " "die.\n"; - text << "You can increase your chances of survival until you can find " - "the exit (a flickering \\), keep moving, don't fight " - "any of the monsters, and don't bother picking up any items " - "on the ground. If you're encumbered or overburdened then " - "lighten up your load, and if the monsters are closing in, try " - "to use items of speed to get away. And where possible, move " - "in a direction slightly off from a compass direction (for " - "example, north-by-northwest instead of north or northwest), " - "as you'll likely miss the exit if you keep heading solely " - "in a compass direction."; + text << "To increase your chances of survival until you can find the " + "exit" +#ifndef USE_TILE + " (a flickering \\)" +#endif + ", keep moving, don't fight any of the monsters, and don't " + "bother picking up any items on the ground. If you're " + "encumbered or overburdened then lighten up your load, and if " + "the monsters are closing in, try to use items of speed to get " + "away. Also, wherever possible, move in a direction slightly " + "off from a compass direction (for example, north-by-northwest " + "instead of north or northwest), as you're more likely to miss " + "the exit if you keep heading solely in a compass direction."; break; case TUT_SPELL_MISCAST: @@ -2662,16 +2948,80 @@ void learned_something_new(tutorial_event_type seen_what, int x, int y) "or potions of resistance. This normally isn't a problem as " "contamination slowly bleeds off on its own, but it seems that " "you've accumulated so much contamination over a short amount " - "of time, that it can have nasty effects, such as mutate you " + "of time that it can have nasty effects, such as mutate you " "or deal direct damage. In addition, glowing is going to make " "you much more noticeable."; break; + case TUT_YOU_RESIST: + text << "There are many dangers in Crawl. Luckily, there are ways to " + "(at least partially) resist some of them, if you are " + "fortunate enough to find them. There are two basic variants " + "of resistances: the innate magic resistance that depends on " + "your species, grows with the experience level, and protects " + "against hostile enchantments; and the specific resistances " + "against certain types of magic and also other effects, e.g. " + "fire or draining.\n" + "You can find items in the dungeon or gain mutations that will " + "increase (or lower) one or more of your resistances. To view " + "your current set of resistances, " +#ifdef USE_TILE + "right-click on the player avatar."; +#else + "press %%."; +#endif + break; + + case TUT_CAUGHT_IN_NET: + text << "While you are held in a net, you cannot move around or engage " + "monsters in combat. Instead, any movement you take is counted " + "as an attempt to struggle free from the net. With a wielded " + "bladed weapon you will be able to cut the net faster"; + + if (Options.tutorial_type == TUT_BERSERK_CHAR) + text << ", especially if you're berserking while doing so"; + + text << ". Small races may also wriggle out of a net, only damaging it " + "a bit, so as to then fire it at a monster."; + + if (Options.tutorial_type == TUT_MAGIC_CHAR) + text << " Note that casting spells is still very much possible."; + break; + + case TUT_LOAD_SAVED_GAME: + { + text << "Welcome back! If it's been a while since you last played this " + "character, you should take some time to refresh your memory " + "of your character's progress. It is recommended to at least " + "have a look through your inventory, but you should " + "also check "; + + std::vector listed; + if (!your_talents(false).empty()) + listed.push_back("your abilities"); + if (Options.tutorial_type != TUT_MAGIC_CHAR || how_mutated()) + listed.push_back("your set of mutations (A)"); + if (you.religion != GOD_NO_GOD) + listed.push_back("your religious standing (^)"); + + listed.push_back("the character overview screen (%)."); + text << comma_separated_line(listed.begin(), listed.end(), + " and ", ", "); + + text << "\nAlternatively, you can dump all information pertaining to " + "your character into a text file with the # command. " + "You can then find said file in the /morgue folder (" + << you.your_name << ".txt) and read it at your leasure. Also, " + "such a file will automatically be created upon death (the " + "filename will then also contain the date) but that won't be " + "of much use to you now."; + break; + } default: text << "You've found something new (but I don't know what)!"; } - if ( !text.str().empty() ) + if (!text.str().empty()) { std::string s = text.str(); formatted_message_history(s, MSGCH_TUTORIAL, 0, _get_tutorial_cols()); @@ -2693,15 +3043,16 @@ formatted_string tut_abilities_info() if (you.religion != GOD_NO_GOD) { - text << - "Renounce Religion will make your character leave your god" EOL - "(and usually anger said god)"; - if (you.religion == GOD_TROG) - { - text << ", while Berserk temporarily increases your" EOL - "damage output in melee fights"; - } - text << "."; + text << + "Renounce Religion will make your character leave your god" EOL + "(and usually anger said god)"; + + if (you.religion == GOD_TROG) + { + text << ", while Berserk temporarily increases your" EOL + "damage output in melee fights"; + } + text << "."; } text << ""; @@ -2848,7 +3199,7 @@ void tutorial_describe_item(const item_def &item) if (you.skills[curr_wpskill] + 2 < you.skills[best_wpskill]) { - ostr << "\nOn second look you've been training in " + ostr << "\nOn second look, you've been training in " << skill_name(best_wpskill) << " for a while, so maybe you should " "continue training that rather than " @@ -2964,6 +3315,22 @@ void tutorial_describe_item(const item_def &item) "."; } + if (Options.tutorial_type == TUT_MAGIC_CHAR + && !is_light_armour(item)) + { + ostr << "\nNote that body armour with high evasion penalties " + "may hinder your ability to learn and cast spells. " + "Light armour such as robes, leather armour or any " + "elven armour will be generally safe for any aspiring " + "spellcaster."; + } + else if (Options.tutorial_type == TUT_RANGER_CHAR + && is_shield(item)) + { + ostr << "\nNote that wearing a shield will greatly decrease " + "the speed at which you can shoot arrows."; + } + if (!item_type_known(item) && (is_artefact(item) || get_equip_desc( item ) != ISFLAG_NO_DESC)) @@ -3049,7 +3416,7 @@ void tutorial_describe_item(const item_def &item) ostr << "Jewellery can be Put on or Removed " "again" #ifdef USE_TILE - ", though in tiles, either can be done by clicking on the " + ", though in Tiles, either can be done by clicking on the " "item in your inventory" #endif "."; @@ -3101,7 +3468,7 @@ void tutorial_describe_item(const item_def &item) "this will drain said pool, so only use this manual " "if you think you need the skill in question."; } - else // it's a spellbook + else // It's a spellbook! { if (you.religion == GOD_TROG && (item.sub_type != BOOK_DESTRUCTION @@ -3145,7 +3512,7 @@ void tutorial_describe_item(const item_def &item) "you've learned the basics of Spellcasting by " "reading lots of scrolls."; } - else // actually can cast spells + else // You actually can cast spells. { if (player_can_memorise(item)) { @@ -3208,11 +3575,11 @@ void tutorial_describe_item(const item_def &item) #endif ostr << "If there are several items in your inventory you'd " "like to drop, the most convenient way is to use the " - "drop menu. On a related note, offering several " - "corpses on a floor square is facilitated by using the " - "chop prompt where c is a valid synonym " - "for yes or you can directly chop all " - "corpses."; + "drop menu. On a related note, butchering " + "several corpses on a floor square is facilitated by " + "using the chop prompt where c is a " + "valid synonym for yes or you can directly chop " + "all corpses."; } Options.tutorial_events[TUT_SEEN_CARRION] = 0; break; @@ -3452,7 +3819,7 @@ void tutorial_describe_feature(dungeon_feature_type feat) "down (>). To get back to this level again, " "press << while standing on the upstairs."; #ifdef USE_TILE - ostr << " In tiles, you can achieve the same, in either direction, " + ostr << " In Tiles, you can achieve the same, in either direction, " "by clicking the left mouse button while pressing " "Shift. "; #endif @@ -3479,7 +3846,7 @@ void tutorial_describe_feature(dungeon_feature_type feat) "level again, press > while standing on the " "downstairs."; #ifdef USE_TILE - ostr << " In tiles, you can perform either action simply by " + ostr << " In Tiles, you can perform either action simply by " "clicking the left mouse button while pressing " "Shift instead. "; #endif @@ -3692,56 +4059,101 @@ void tutorial_describe_monster(const monsters *mons) std::ostringstream ostr; ostr << "\n\n<" << colour_to_str(channel_to_colour(MSGCH_TUTORIAL)) << ">"; + bool dangerous = false; if (mons_is_unique(mons->type)) { ostr << "Did you think you were the only adventurer in the dungeon? " "Well, you thought wrong! These unique adversaries often " "possess skills that normal monster wouldn't, so be " "careful.\n\n"; + dangerous = true; } else if (mons->type == MONS_PLAYER_GHOST) { ostr << "The ghost of a deceased adventurer, it would like nothing " "better than to send you the same way.\n\n"; + dangerous = true; } else { - // 8 is the default value for the note-taking of OOD monsters. - int level_diff = mons_level(mons->type) - (you.your_level + 8); + // 8 is the default value for the note-taking of OOD monsters. + // Since I'm too lazy to come up with any measurement of my own + // I'll simply reuse that one. + int level_diff = mons_level(mons->type) - (you.your_level + 8); - if (you.level_type == LEVEL_DUNGEON && level_diff >= 0) - { - ostr << "This kind of monster is usually only encountered " - << (level_diff > 5 ? "much " : "") - << "deeper in the dungeon, so it's probably " - << (level_diff > 5 ? "extremely" : "very") - << " dangerous!\n\n"; - } + if (you.level_type == LEVEL_DUNGEON && level_diff >= 0) + { + ostr << "This kind of monster is usually only encountered " + << (level_diff > 5 ? "much " : "") + << "deeper in the dungeon, so it's probably " + << (level_diff > 5 ? "extremely" : "very") + << " dangerous!\n\n"; + dangerous = true; + } } if (mons->has_ench(ENCH_BERSERK)) - ostr << "A berserking monster is bloodthirsty and fighting madly.\n"; + { + ostr << "A berserking monster is bloodthirsty and fighting madly. " + "Such a blood rage makes it particularly dangerous!\n\n"; + dangerous = true; + } // Monster is highlighted. if (mons_friendly(mons)) { ostr << "Friendly monsters will follow you around and attempt to aid " - "you in battle."; + "you in battle. You can order your allies by talking " + "to them."; + } + else if (dangerous) + { + if (!Options.tut_explored && mons->foe != MHITYOU) + { + ostr << "You can easily mark its square as dangerous to avoid " + "accidentally entering into its field of view when using " + "auto-explore or auto-travel. To do so, enter the level " + "map with X and then press Ctrl-X when your " + "cursor is hovering over the monster's grid. Doing so will " + "mark this grid and all surrounding ones within a radius " + "of 8 as \"excluded\" ones that explore or travel modus " + "won't enter.\n"; +#ifdef USE_TILE + ostr << "Upon returning to the main map, you'll even find all " + "surrounding grids visibly highlighted."; +#endif + } + else + { + ostr << "This might be a good time to run away"; + + if (you.religion == GOD_TROG && !you.duration[DUR_BERSERKER] + && !you.duration[DUR_EXHAUSTED] + && you.hunger_state >= HS_SATIATED) + { + ostr << " or apply your Berserk ability"; + } + ostr << "."; + } } else if (Options.stab_brand != CHATTR_NORMAL && mons_looks_stabbable(mons)) { ostr << "Apparently " << mons_pronoun((monster_type) mons->type, PRONOUN_NOCAP) - << " has not noticed you - yet."; + << " has not noticed you - yet. Note that you do not have to " + "engage every monster you meet. Sometimes, discretion is the " + "better part of valour."; } else if (Options.may_stab_brand != CHATTR_NORMAL && mons_looks_distracted(mons)) { ostr << "Apparently " << mons_pronoun((monster_type) mons->type, PRONOUN_NOCAP) - << " has been distracted by something."; + << " has been distracted by something. You could use this " + "opportunity to sneak up on this monster - or to sneak away."; } + ostr << ""; std::string broken = ostr.str(); diff --git a/crawl-ref/source/tutorial.h b/crawl-ref/source/tutorial.h index 0d28e29d31..a9646570e2 100644 --- a/crawl-ref/source/tutorial.h +++ b/crawl-ref/source/tutorial.h @@ -39,13 +39,14 @@ void tutorial_dissection_reminder(bool healthy); void tutorial_healing_reminder(void); void taken_new_item(unsigned char item_type); +void tut_gained_new_skill(int skill); void tutorial_first_monster(const monsters& mon); void tutorial_first_item(const item_def& item); -void learned_something_new(tutorial_event_type seen_what, int x=0, int y=0); +void learned_something_new(tutorial_event_type seen_what, int x = 0, int y = 0); formatted_string tut_abilities_info(void); void print_tut_skills_info(void); -// additional information for tutorial players +// Additional information for tutorial players. void tutorial_describe_item(const item_def &item); void tutorial_inscription_info(bool autoinscribe); bool tutorial_pos_interesting(int x, int y); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 075b058599..a14738ea47 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1574,10 +1574,10 @@ void blood_smell( int strength, int blood_x, int blood_y ) blood_x, blood_y, range); #endif - // of the player species, only vampires can smell blood + // Of the player species, only Vampires can smell blood. if (you.species == SP_VAMPIRE) { - // whether they actually do so, depends on their hunger state + // Whether they actually do so, depends on their hunger state. int vamp_strength = strength - 2 * (you.hunger_state - 1); if (vamp_strength > 0) { @@ -1594,7 +1594,7 @@ void blood_smell( int strength, int blood_x, int blood_y ) you.x_pos, you.y_pos, player_distance); #endif you.check_awaken(range - player_distance); - // don't message if you can see the square + // Don't message if you can see the square. if (!see_grid(blood_x, blood_y)) { mprf("You smell fresh blood%s.", @@ -1616,7 +1616,7 @@ void blood_smell( int strength, int blood_x, int blood_y ) if (distance(monster->x, monster->y, blood_x, blood_y) <= range) { - // let sleeping hounds lie + // Let sleeping hounds lie. if (mons_is_sleeping(monster) && mons_species(monster->type) != MONS_VAMPIRE) { -- cgit v1.2.3-54-g00ecf