From 781c1cda9ce49cec2064cbf438e52ef6aaff41a3 Mon Sep 17 00:00:00 2001 From: zelgadis Date: Mon, 25 May 2009 07:09:56 +0000 Subject: Added some new tutorial events (not tested with the tile build): * Auto-explore hint (200 turns after level map hint). * Explanation of the "Your equipment suddenly weighs less" message. * Explanations of trap and heap branding (non-tile builds only). * A note that monsters that have moved out of LOS haven't just vanished. * Events for gaining an ability from a mutation and gaining one from an item which was just equipped, separate from the event for the first divinely granted ability. * An explanation that shouting monsters have just noticed you, plus that their shout is likely to attract the attention of other monsters. * A "seen portal vault entrance" event, since the entry to the sewers can appear on DL 3 through 6, and there's also a very small chance of a Zigguart entrance apearing as early as DL 3. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9823 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/tutorial.cc | 273 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 260 insertions(+), 13 deletions(-) (limited to 'crawl-ref/source/tutorial.cc') diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index c1981c2072..6ff5b7018f 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -63,7 +63,7 @@ static void _tutorial_describe_feature(int x, int y); static bool _water_is_disturbed(int x, int y); //#define TUTORIAL_DEBUG -#define TUTORIAL_VERSION 8 +#define TUTORIAL_VERSION 9 static int _get_tutorial_cols() { @@ -348,7 +348,7 @@ static std::string _tut_debug_list(int event) return "seen first food"; case TUT_SEEN_CARRION: return "seen first corpse"; - case TUT_SEE_GOLD: + case TUT_SEEN_GOLD: return "seen first pile of gold"; case TUT_SEEN_JEWELLERY: return "seen first jewellery"; @@ -362,6 +362,8 @@ static std::string _tut_debug_list(int event) return "seen first escape hatch"; case TUT_SEEN_BRANCH: return "seen first branch entrance"; + case TUT_SEEN_PORTAL: + return "seen first portal vault entrance"; case TUT_SEEN_TRAP: return "encountered a trap"; case TUT_SEEN_ALTAR: @@ -402,6 +404,8 @@ static std::string _tut_debug_list(int event) return "were encumbered"; case TUT_ROTTEN_FOOD: return "carried rotten food"; + case TUT_ROTTEN_GONE: + return "rotten food rotted away completely"; case TUT_NEED_HEALING: return "needed healing"; case TUT_NEED_POISON_HEALING: @@ -422,12 +426,18 @@ static std::string _tut_debug_list(int event) return "learned about shift-run"; case TUT_MAP_VIEW: return "learned about the level map"; + case TUT_AUTO_EXPLORE: + return "learned about auto-explore"; case TUT_DONE_EXPLORE: return "explored a level"; case TUT_YOU_MUTATED: return "caught a mutation"; - case TUT_NEW_ABILITY: + case TUT_NEW_ABILITY_GOD: return "gained a divine ability"; + case TUT_NEW_ABILITY_MUT: + return "gained a mutation-granted ability"; + case TUT_NEW_ABILITY_ITEM: + return "gained an item-granted ability"; case TUT_WIELD_WEAPON: return "wielded an unsuitable weapon"; case TUT_FLEEING_MONSTER: @@ -436,6 +446,8 @@ static std::string _tut_debug_list(int event) return "learned about colour brandings"; case TUT_MONSTER_FRIENDLY: return "seen first friendly monster"; + case TUT_MONSTER_SHOUT: + return "experienced first shouting monster"; case TUT_CONVERT: return "converted to a god"; case TUT_GOD_DISPLEASED: @@ -450,6 +462,10 @@ static std::string _tut_debug_list(int event) return "player glowing from contamination"; case TUT_STAIR_BRAND: return "saw stairs with objects on it"; + case TUT_HEAP_BRAND: + return "saw heap of objects"; + case TUT_TRAP_BRAND: + return "saw trap with objects on it"; case TUT_YOU_RESIST: return "resisted some magic"; case TUT_CAUGHT_IN_NET: @@ -1468,6 +1484,64 @@ static int _num_butchery_tools() return (num); } +static std::string _describe_portal(const coord_def &gc) +{ + const std::string desc = feature_description(gc); + + std::ostringstream text; + + // Zigguart entrances can rarely appear as early as DL 3. + if (desc.find("zig") != std::string::npos) + { + text << "is a portal to a set of special levels filled with very " + "tough monsters; you probably shouldn't even think of going " + "in here. Additionally, entering a zigguart takes a lot of " + "gold, a lot more than you'd have right now; don't bother " + "saving gold up for it, since at this point your gold is " + "better spent at shops buying items which can help you " + "survive." + + "\n\nIf you still want to enter (and somehow have " + "gathered enough gold to do so) "; + } + // For the sake of completeness, though it's very unlikely that a + // player will find a bazaar entrance before reahing XL 7. + else if (desc.find("bazaar") != std::string::npos) + { + text << "is a portal to an inter-dimensional bazaar filled with " + "shops. It will disappear if you don't enter it soon, " + "so hurry. To enter "; + } + // The sewers can appear from DL 3 to DL 6. + else + { + text << "is a portal to a special level where you'll have to fight " + "your way back to the exit through some tougher than average " + "monsters (the monsters around the portal should give a " + "good indication as to how tough), but with the reward of " + "some good loot. There's no penalty for skipping it, but if " + "you do skip it the portal will disappear, so you have to " + "decide now if you want to risk it. To enter "; + } + + text << "stand over the portal and press >. To return find " +#ifdef USE_TILE + "a similar looking portal tile " +#else + "another \\ " +#endif + "(though NOT the ancient stone arch you'll start out on) " + "and press <<."; + +#ifdef USE_TILE + text << "\nAlternatively, clicking on your left mouse button " + "while pressing the Shift key will let you enter any " + "portal you're standing on."; +#endif + + return (text.str()); +} + #define DELAY_EVENT \ { \ Options.tutorial_events[seen_what] = true; \ @@ -1920,6 +1994,32 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) "altars at which you might convert to a new god."; break; + case TUT_SEEN_PORTAL: + // Delay in the unlikely event that a player still in tutorial mode + // creates a portal with a Trowel card, since a portal vault + // entry's description doesn't seem to get set properly until + // after the vault is done being placed. + if (you.pos() == gc) + DELAY_EVENT; + + text << "This "; +#ifndef USE_TILE + // Is a monster blocking the view? + if (monster_at(gc)) + DELAY_EVENT; + + object = env.show(e); + colour = env.show_col(e); + { unsigned short dummy; get_item_symbol( object, &ch, &dummy ); } + + text << _colourize_glyph(colour, ch) << " "; +#else + tiles.place_cursor(CURSOR_TUTORIAL, gc); + tiles.add_text_tag(TAG_TUTORIAL, "Portal", gc); +#endif + text << _describe_portal(gc); + break; + case TUT_STAIR_BRAND: #ifdef USE_TILE // XXX: How does stair branding work with tiles? @@ -1936,6 +2036,36 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) #endif break; + case TUT_HEAP_BRAND: +#ifdef USE_TILE + // XXX: How does heap branding work with tiles? + return; +#else + // Monster or player standing on heap. + if (monster_at(gc) || (you.pos() == gc)) + DELAY_EVENT; + + text << "If two or more items are on a single square then the square " + "will be highlighted, and the symbol for the item on the top " + "of the heap will be shown."; +#endif + break; + + case TUT_TRAP_BRAND: +#ifdef USE_TILE + // XXX: How does trap branding work with tiles? + return; +#else + // Monster or player standing on trap. + if (monster_at(gc) || (you.pos() == gc)) + DELAY_EVENT; + + text << "If any items are covering a trap then that will be " + "indicated by highlighting the ^ symbol, instead of " + "hiding the trap symbol with an item glyph."; +#endif + break; + case TUT_SEEN_TRAP: if (you.pos() == gc) text << "Oops... you just triggered a trap. "; @@ -2325,6 +2455,12 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) "just as well drop them now."; break; + case TUT_ROTTEN_GONE: + text << "One of the skeletons or rotten chunks of meat you carried " + "rotted away completely, or one of the rotten corpses you " + "carried rotted away into a skeleton."; + break; + case TUT_MAKE_CHUNKS: text << "How lucky! That monster left a corpse which you can now " "chop up"; @@ -2407,6 +2543,19 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) #endif break; + case TUT_AUTO_EXPLORE: + if (!Options.tut_explored) + DELAY_EVENT; + + text << "Fully exploring a level and piciking up all the interesting " + "looking items can be tedious. To save on this tedium you " + "can press o to auto-explore, which will " + "automatically explore unmapped regions, automatically pick " + "up interesting items, and stop if a monster or interesting " + "dungeon feature (stairs, altar, etc) is encountered."; + Options.tut_explored = false; + break; + case TUT_DONE_EXPLORE: // XXX: You'll only get this message if you're using auto exploration. text << "Hey, you've finished exploring the dungeon on this level! " @@ -2557,20 +2706,20 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) "have three levels. Check your mutations with A."; break; - case TUT_NEW_ABILITY: + case TUT_NEW_ABILITY_GOD: switch (you.religion) { // Gods where first granted ability is active. 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 " + text << "You just gained a divine 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 ^ " + text << "You just gained a divine ability. Press ^ " #ifdef USE_TILE "or press Shift and right-click on the " "player tile " @@ -2580,6 +2729,20 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) } break; + case TUT_NEW_ABILITY_MUT: + text << "That mutation granted you a new ability. Press a to " + "take a look at your abilities or to use one of them."; + break; + break; + + case TUT_NEW_ABILITY_ITEM: + text << "That item you just equipped granted you a new ability " + "(un-equipping the item will remove the ability). " + "Press a to take a look at your abilities or to " + "use one of them."; + break; + break; + case TUT_CONVERT: _new_god_conduct(); break; @@ -2768,10 +2931,15 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) break; case TUT_MONSTER_FRIENDLY: + { + const monsters *m = monster_at(gc); + + if (!m) + DELAY_EVENT; + #ifdef USE_TILE tiles.place_cursor(CURSOR_TUTORIAL, gc); - if (const monsters *m = monster_at(gc)) - tiles.add_text_tag(TAG_TUTORIAL, m->name(DESC_CAP_A), gc); + tiles.add_text_tag(TAG_TUTORIAL, m->name(DESC_CAP_A), gc); #endif text << "That monster is friendly to you and will attack your " "enemies, though you'll get only half the experience for " @@ -2779,12 +2947,69 @@ void learned_something_new(tutorial_event_type seen_what, coord_def gc) "yourself. You can command your allies by pressing t " "to talk to them."; - if (!mons_att_wont_attack(monster_at(gc)->attitude)) + if (!mons_att_wont_attack(m->attitude)) text << "\n\nHowever, it is only temporarily friendly, " "and will become dangerous again when this friendliness " "wears off."; break; + } + case TUT_MONSTER_SHOUT: + { + const monsters* m = monster_at(gc); + + if (!m) + DELAY_EVENT; + + const bool vis = you.can_see(m); + +#ifdef USE_TILE + if (vis) + { + tiles.place_cursor(CURSOR_TUTORIAL, gc); + tiles.add_text_tag(TAG_TUTORIAL, m->name(DESC_CAP_A), gc); + } +#endif + if (!vis) + { + text << "Uh-oh, some monster noticed you, either one that's " + "around a corner or one that's invisible. Plus, the " + "noise it made will alert other monsters in the " + "vacinity, who will come to check out what the commotion " + "was about."; + } + else if (mons_shouts(m->type, false) == S_SILENT) + { + text << "Uh-oh, that monster noticed you! Forutnately, it " + "didn't make any noise, but many mosters do make " + "noise when they notice you, which alerts other monsters " + "in the area, who will come to check out what the " + "commotion was about."; + } + else + { + text << "Uh-oh, taht monster noticed you! Plus, the " + "noise it made will alert other monsters in the " + "vacinity, who will come to check out what the commotion " + "was about."; + } + break; + } + + case TUT_MONSTER_LEFT_LOS: + { + const monsters* m = monster_at(gc); + + if (!m || !you.can_see(m)) + DELAY_EVENT; + + text << m->name(DESC_CAP_THE, true) << " didn't vanish, but merely " + "moved onto a square which isn't in your current LOS. It " + "will still be there, unless something happens to it in the " + "short amount of time it's out of sight."; + break; + } + case TUT_SEEN_MONSTER: case TUT_SEEN_FIRST_OBJECT: // Handled in special functions. @@ -3704,6 +3929,7 @@ static bool _tutorial_feat_interesting(dungeon_feature_type feat) case DNGN_STONE_STAIRS_UP_III: case DNGN_ESCAPE_HATCH_DOWN: case DNGN_ESCAPE_HATCH_UP: + case DNGN_ENTER_PORTAL_VAULT: return (true); default: return (false); @@ -3830,6 +4056,11 @@ static void _tutorial_describe_feature(int x, int y) Options.tutorial_events[TUT_SEEN_ESCAPE_HATCH] = false; break; + case DNGN_ENTER_PORTAL_VAULT: + ostr << "This " << _describe_portal(where); + Options.tutorial_events[TUT_SEEN_PORTAL] = false; + break; + default: if (feat >= DNGN_ALTAR_FIRST_GOD && feat <= DNGN_ALTAR_LAST_GOD) { @@ -4139,15 +4370,31 @@ void tutorial_observe_cell(const coord_def& gc) learned_something_new(TUT_SEEN_STAIRS, gc); else if (is_feature('_', gc)) learned_something_new(TUT_SEEN_ALTAR, gc); + else if (is_feature('^', gc)) + learned_something_new(TUT_SEEN_TRAP, gc); else if (grd(gc) == DNGN_CLOSED_DOOR) learned_something_new(TUT_SEEN_DOOR, gc); else if (grd(gc) == DNGN_ENTER_SHOP) learned_something_new(TUT_SEEN_SHOP, gc); + else if (grd(gc) == DNGN_ENTER_PORTAL_VAULT) + learned_something_new(TUT_SEEN_PORTAL, gc); - if (igrd(gc) != NON_ITEM - && Options.feature_item_brand != CHATTR_NORMAL - && (is_feature('>', gc) || is_feature('<', gc))) + const int it = igrd(gc); + if (it != NON_ITEM) { - learned_something_new(TUT_STAIR_BRAND, gc); + const item_def& item(mitm[it]); + + if (Options.feature_item_brand != CHATTR_NORMAL + && (is_feature('>', gc) || is_feature('<', gc))) + { + learned_something_new(TUT_STAIR_BRAND, gc); + } + else if (Options.trap_item_brand != CHATTR_NORMAL + && is_feature('^', gc)) + { + learned_something_new(TUT_TRAP_BRAND, gc); + } + else if (Options.heap_brand != CHATTR_NORMAL && item.link != NON_ITEM) + learned_something_new(TUT_HEAP_BRAND, gc); } } -- cgit v1.2.3-54-g00ecf