diff options
Diffstat (limited to 'crawl-ref/source/misc.cc')
-rw-r--r-- | crawl-ref/source/misc.cc | 315 |
1 files changed, 277 insertions, 38 deletions
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index b91504bda5..2335c74b42 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -43,20 +43,24 @@ #include "clua.h" #include "cloud.h" #include "delay.h" +#include "direct.h" #include "dgnevent.h" #include "direct.h" #include "dungeon.h" #include "files.h" #include "food.h" +#include "format.h" #include "hiscores.h" #include "it_use2.h" #include "itemprop.h" #include "items.h" #include "lev-pand.h" +#include "macro.h" #include "message.h" #include "mon-util.h" #include "monstuff.h" #include "ouch.h" +#include "overmap.h" #include "place.h" #include "player.h" #include "religion.h" @@ -65,6 +69,7 @@ #include "skills2.h" #include "spells3.h" #include "stash.h" +#include "state.h" #include "stuff.h" #include "terrain.h" #include "transfor.h" @@ -72,6 +77,7 @@ #include "travel.h" #include "tutorial.h" #include "view.h" +#include "xom.h" // void place_chunks(int mcls, unsigned char rot_status, unsigned char chx, // unsigned char chy, unsigned char ch_col) @@ -166,7 +172,8 @@ void search_around( bool only_adjacent ) { for ( int sry=you.y_pos - max_dist; sry<=you.y_pos + max_dist; ++sry ) { - if ( see_grid(srx,sry) ) // must have LOS + // must have LOS, with no translucent walls in the way. + if ( see_grid_no_trans(srx,sry) ) { // maybe we want distance() instead of grid_distance()? int dist = grid_distance(srx, sry, you.x_pos, you.y_pos); @@ -463,7 +470,57 @@ static void leaving_level_now() you.level_type_name = newtype; } -void up_stairs(dungeon_feature_type force_stair) +static void set_entry_cause(entry_cause_type default_cause, + level_area_type old_level_type) +{ + ASSERT(default_cause != NUM_ENTRY_CAUSE_TYPES); + + if (!(old_level_type != you.level_type + || you.entry_cause == EC_UNKNOWN)) + { + return; + } + + if (crawl_state.is_god_acting()) + { + if (crawl_state.is_god_retribution()) + you.entry_cause = EC_GOD_RETRIUBTION; + else + you.entry_cause = EC_GOD_ACT; + + you.entry_cause_god = crawl_state.which_god_acting(); + } + else if (default_cause != EC_UNKNOWN) + { + you.entry_cause = default_cause; + you.entry_cause_god = GOD_NO_GOD; + } + else + { + you.entry_cause = EC_SELF_EXPLICIT; + you.entry_cause_god = GOD_NO_GOD; + } +} + +static int runes_in_pack() +{ + int num_runes = 0; + + for (int i = 0; i < ENDOFPACK; i++) + { + if (is_valid_item( you.inv[i] ) + && you.inv[i].base_type == OBJ_MISCELLANY + && you.inv[i].sub_type == MISC_RUNE_OF_ZOT) + { + num_runes += you.inv[i].quantity; + } + } + + return num_runes; +} + +void up_stairs(dungeon_feature_type force_stair, + entry_cause_type entry_cause) { dungeon_feature_type stair_find = force_stair? force_stair : grd[you.x_pos][you.y_pos]; @@ -486,6 +543,31 @@ void up_stairs(dungeon_feature_type force_stair) return; } + level_id old_level_id = level_id::current(); + LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id); + + // Does the next level have a warning annotation? + coord_def pos(you.x_pos, you.y_pos); + level_id next_level_id = level_id::get_next_level_id(pos); + + crawl_state.level_annotation_shown = false; + + if (level_annotation_has("WARN", next_level_id) + && next_level_id != level_id::current() + && next_level_id.level_type == LEVEL_DUNGEON && !force_stair) + { + mpr("Warning: level annotation for next level is:", MSGCH_PROMPT); + mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT); + + if (!yesno("Enter next level anyways?", true, 0, true, false)) + { + interrupt_activity( AI_FORCE_INTERRUPT ); + return; + } + + crawl_state.level_annotation_shown = true; + } + // Since the overloaded message set turn_is_over, I'm assuming that // the overloaded character makes an attempt... so we're doing this // check before that one. -- bwr @@ -526,9 +608,6 @@ void up_stairs(dungeon_feature_type force_stair) // Interlevel travel data: const bool collect_travel_data = can_travel_interlevel(); - level_id old_level_id = level_id::current(); - LevelInfo &old_level_info = travel_cache.get_level_info(old_level_id); - int stair_x = you.x_pos, stair_y = you.y_pos; if (collect_travel_data) old_level_info.update(); @@ -558,9 +637,11 @@ void up_stairs(dungeon_feature_type force_stair) ouch(INSTANT_DEATH, 0, KILLED_BY_LEAVING); } - you.prev_targ = MHITNOT; + you.prev_targ = MHITNOT; you.pet_target = MHITNOT; + you.prev_grd_targ = coord_def(0, 0); + if (player_in_branch( BRANCH_VESTIBULE_OF_HELL )) { mpr("Thank you for visiting Hell. Please come again soon."); @@ -612,6 +693,9 @@ void up_stairs(dungeon_feature_type force_stair) load(stair_taken, LOAD_ENTER_LEVEL, old_level_type, old_level, old_where); + set_entry_cause(entry_cause, old_level_type); + entry_cause = you.entry_cause; + you.turn_is_over = true; save_game_state(); @@ -620,6 +704,21 @@ void up_stairs(dungeon_feature_type force_stair) viewwindow(1, true); + // Left Zot without enough runes to get back in (probably because + // of dropping some runes within Zot), but need to get back in Zot + // to get the Orb? Zom finds that funny. + if (stair_find == DNGN_RETURN_FROM_ZOT + && branches[BRANCH_HALL_OF_ZOT].branch_flags & BFLAG_HAS_ORB) + { + int runes_avail = you.attribute[ATTR_UNIQUE_RUNES] + + you.attribute[ATTR_DEMONIC_RUNES] + + you.attribute[ATTR_ABYSSAL_RUNES] + - you.attribute[ATTR_RUNES_IN_ZOT]; + + if (runes_avail < NUMBER_OF_RUNES_NEEDED) + xom_is_stimulated(255, "Xom snickers loudly.", true); + } + if (you.skills[SK_TRANSLOCATIONS] > 0 && !allow_control_teleport( true )) mpr( "You sense a powerful magical force warping space.", MSGCH_WARN ); @@ -638,6 +737,8 @@ void up_stairs(dungeon_feature_type force_stair) travel_cache.get_level_info(new_level_id); new_level_info.update(); + int stair_x = you.x_pos, stair_y = you.y_pos; + // First we update the old level's stair. level_pos lp; lp.id = new_level_id; @@ -662,7 +763,7 @@ void up_stairs(dungeon_feature_type force_stair) guess = true; } - old_level_info.update_stair(stair_x, stair_y, lp, guess); + old_level_info.update_stair(you.x_pos, you.y_pos, lp, guess); // We *guess* that going up a staircase lands us on a downstair, // and that we can descend that downstair and get back to where we @@ -682,7 +783,8 @@ void up_stairs(dungeon_feature_type force_stair) } } // end up_stairs() -void down_stairs( int old_level, dungeon_feature_type force_stair ) +void down_stairs( int old_level, dungeon_feature_type force_stair, + entry_cause_type entry_cause ) { int i; const level_area_type old_level_type = you.level_type; @@ -691,6 +793,12 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) branch_type old_where = you.where_are_you; + bool shaft = ((!force_stair + && trap_type_at_xy(you.x_pos, you.y_pos) == TRAP_SHAFT) + || force_stair == DNGN_TRAP_NATURAL); + level_id shaft_dest; + int shaft_level = -1; + #ifdef SHUT_LABYRINTH if (stair_find == DNGN_ENTER_LABYRINTH) { @@ -701,7 +809,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) #endif // probably still need this check here (teleportation) -- bwr - if (grid_stair_direction(stair_find) != CMD_GO_DOWNSTAIRS) + if (grid_stair_direction(stair_find) != CMD_GO_DOWNSTAIRS && !shaft) { if (stair_find == DNGN_STONE_ARCH) mpr("There is nothing on the other side of the stone arch."); @@ -730,6 +838,45 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) return; } + if (shaft) + { + bool known_trap = (grd[you.x_pos][you.y_pos] != DNGN_UNDISCOVERED_TRAP + && !force_stair); + + if (!known_trap && !force_stair) + { + mpr("You can't go down here!"); + return; + } + + if (you.flight_mode() == FL_LEVITATE && !force_stair) + { + if (known_trap) + mpr("You can't fall through a shaft while levitating."); + return; + } + + if (!is_valid_shaft_level()) + { + if (known_trap) + mpr("Strange, the shaft doesn't seem to lead anywhere."); + return; + } + + shaft_dest = you.shaft_dest(); + if (shaft_dest == level_id::current()) + { + if (known_trap) + mpr("Strange, the shaft doesn't seem to lead anywhere."); + return; + } + shaft_level = absdungeon_depth(shaft_dest.branch, + shaft_dest.depth); + + if (you.flight_mode() != FL_FLY || force_stair) + mpr("You fall through a shaft!"); + } + // All checks are done, the player is on the move now. // Fire level-leaving trigger. @@ -756,24 +903,14 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) if (stair_find == DNGN_ENTER_ZOT) { - int num_runes = 0; - - for (i = 0; i < ENDOFPACK; i++) - { - if (is_valid_item( you.inv[i] ) - && you.inv[i].base_type == OBJ_MISCELLANY - && you.inv[i].sub_type == MISC_RUNE_OF_ZOT) - { - num_runes += you.inv[i].quantity; - } - } + int num_runes = runes_in_pack(); if (num_runes < NUMBER_OF_RUNES_NEEDED) { switch (NUMBER_OF_RUNES_NEEDED) { case 1: - mpr("You need a Rune to enter this place."); + mpr("You need one more Rune to enter this place."); break; default: @@ -784,6 +921,28 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) } } + // Does the next level have a warning annotation? + coord_def pos = you.pos(); + level_id next_level_id = level_id::get_next_level_id(pos); + + crawl_state.level_annotation_shown = false; + + if (level_annotation_has("WARN", next_level_id) + && next_level_id != level_id::current() + && next_level_id.level_type == LEVEL_DUNGEON && !force_stair) + { + mpr("Warning: level annotation for next level is:", MSGCH_PROMPT); + mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT); + + if (!yesno("Enter next level anyways?", true, 0, true, false)) + { + interrupt_activity( AI_FORCE_INTERRUPT ); + return; + } + + crawl_state.level_annotation_shown = true; + } + // Interlevel travel data: bool collect_travel_data = can_travel_interlevel(); @@ -804,9 +963,11 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) you.level_type = LEVEL_DUNGEON; } - you.prev_targ = MHITNOT; + you.prev_targ = MHITNOT; you.pet_target = MHITNOT; + you.prev_grd_targ = coord_def(0, 0); + if (stair_find == DNGN_ENTER_HELL) { you.where_are_you = BRANCH_VESTIBULE_OF_HELL; @@ -864,7 +1025,8 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) if (stair_find == DNGN_EXIT_ABYSS || stair_find == DNGN_EXIT_PANDEMONIUM) { mpr("You pass through the gate."); - more(); + if (!(you.wizard && crawl_state.is_replaying_keys())) + more(); } if (old_level_type != you.level_type && you.level_type == LEVEL_DUNGEON) @@ -885,7 +1047,12 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) KILLED_BY_FALLING_DOWN_STAIRS ); } - if (you.level_type == LEVEL_DUNGEON) + if (shaft) + { + you.your_level = shaft_level; + you.where_are_you = shaft_dest.branch; + } + else if (you.level_type == LEVEL_DUNGEON) you.your_level++; dungeon_feature_type stair_taken = stair_find; @@ -896,6 +1063,9 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) if (you.level_type == LEVEL_PANDEMONIUM) stair_taken = DNGN_TRANSIT_PANDEMONIUM; + if (shaft) + stair_taken = DNGN_ROCK_STAIRS_DOWN; + switch (you.level_type) { case LEVEL_LABYRINTH: @@ -919,11 +1089,18 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) break; default: - climb_message(stair_find, false, old_level_type); + if (shaft) + { + if (you.flight_mode() == FL_FLY && !force_stair) + mpr("You dive down through the shaft."); + } + else + climb_message(stair_find, false, old_level_type); break; } - exit_stair_message(stair_find, false); + if (!shaft) + exit_stair_message(stair_find, false); if (entered_branch) { @@ -946,14 +1123,74 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) const bool newlevel = load(stair_taken, LOAD_ENTER_LEVEL, old_level_type, old_level, old_where); - + + set_entry_cause(entry_cause, old_level_type); + entry_cause = you.entry_cause; + if (newlevel) - xom_is_stimulated(49); + { + switch(you.level_type) + { + case LEVEL_DUNGEON: + xom_is_stimulated(49); + break; + + case LEVEL_PORTAL_VAULT: + // Portal vaults aren't as interesting. + xom_is_stimulated(25); + break; + + case LEVEL_LABYRINTH: + // Finding the way out of a labyrinth interests Xom. + xom_is_stimulated(98); + break; + + case LEVEL_ABYSS: + case LEVEL_PANDEMONIUM: + { + // Paranoia + if (old_level_type == you.level_type) + break; + + PlaceInfo &place_info = you.get_place_info(); + + // Entering voluntarily only stimulates Xom if you've never + // been there before + if ((place_info.num_visits == 1 && place_info.levels_seen == 1) + || entry_cause != EC_SELF_EXPLICIT) + { + if (crawl_state.is_god_acting()) + xom_is_stimulated(255); + else if (entry_cause == EC_SELF_EXPLICIT) + { + // Entering Pandemonium or the Abyss for the first + // time *voluntarily* stimulates Xom much more than + // entering a normal dungeon level for the first time. + xom_is_stimulated(128, XM_INTRIGUED); + } + else if (entry_cause == EC_SELF_RISKY) + xom_is_stimulated(128); + else + xom_is_stimulated(255); + } + + break; + } + + default: + ASSERT(false); + } + } unsigned char pc = 0; unsigned char pt = random2avg(28, 3); - if (level_type_exits_up(you.level_type)) + if (shaft) + { + you.your_level = shaft_level; + you.where_are_you = shaft_dest.branch; + } + else if (level_type_exits_up(you.level_type)) you.your_level++; else if (level_type_exits_down(you.level_type) && !level_type_exits_down(old_level_type)) @@ -1006,6 +1243,13 @@ void down_stairs( int old_level, dungeon_feature_type force_stair ) new_level(); + // clear list of beholding monsters + if (you.duration[DUR_BEHELD]) + { + you.beheld_by.clear(); + you.duration[DUR_BEHELD] = 0; + } + viewwindow(1, true); if (you.skills[SK_TRANSLOCATIONS] > 0 && !allow_control_teleport( true )) @@ -1097,8 +1341,6 @@ void new_level(void) take_note(Note(NOTE_DUNGEON_LEVEL_CHANGE)); cprintf("%s", level_description_string().c_str()); - dgn_set_floor_colours(); - clear_to_end_of_line(); #ifdef DGL_WHEREIS whereis_record(); @@ -1241,7 +1483,7 @@ bool go_berserk(bool intentional) deflate_hp(you.hp_max, false); if (!you.duration[DUR_MIGHT]) - modify_stat( STAT_STRENGTH, 5, true ); + modify_stat( STAT_STRENGTH, 5, true, "going berserk" ); you.duration[DUR_MIGHT] += you.duration[DUR_BERSERKER]; haste_player( you.duration[DUR_BERSERKER] ); @@ -1302,8 +1544,7 @@ std::string cloud_name(cloud_type type) bool mons_is_safe(const struct monsters *mon, bool want_move) { bool is_safe = mons_friendly(mon) || - (Options.safe_zero_exp && - mons_class_flag( mon->type, M_NO_EXP_GAIN )); + mons_class_flag(mon->type, M_NO_EXP_GAIN); #ifdef CLUA_BINDINGS bool moving = ((!you.delay_queue.empty() && @@ -1355,11 +1596,10 @@ bool i_feel_safe(bool announce, bool want_move) { for ( int x = xstart; x < xend; ++x ) { - /* if you can see a nonfriendly monster then you feel - unsafe */ + // if you can see a nonfriendly monster then you feel unsafe if ( see_grid(x,y) ) { - const unsigned char targ_monst = mgrd[x][y]; + const unsigned short targ_monst = mgrd[x][y]; if ( targ_monst != NON_MONSTER ) { const monsters *mon = &menv[targ_monst]; @@ -1630,4 +1870,3 @@ int speed_to_duration(int speed) return div_rand_round(100, speed); } - |