diff options
Diffstat (limited to 'crawl-ref/source/spells3.cc')
-rw-r--r-- | crawl-ref/source/spells3.cc | 299 |
1 files changed, 186 insertions, 113 deletions
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 200c0cfa83..032f3bb2a7 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -43,6 +43,7 @@ #include "place.h" #include "player.h" #include "randart.h" +#include "religion.h" #include "spells1.h" #include "spells4.h" #include "spl-cast.h" @@ -50,7 +51,8 @@ #include "stuff.h" #include "traps.h" #include "view.h" -#include "xom.h" + +static bool monster_on_level(int monster); bool cast_selective_amnesia(bool force) { @@ -487,6 +489,31 @@ void dancing_weapon(int pow, bool force_hostile) burden_change(); } // end dancing_weapon() +static bool monster_on_level(int monster) +{ + for (int i = 0; i < MAX_MONSTERS; i++) + { + if (menv[i].type == monster) + return true; + } + + return false; +} // end monster_on_level() + +// XXX: Relies on RUNE_xxx == BRANCH_xxx. See rune_type in enum.h. +static bool player_has_rune(branch_type branch) +{ + 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 + && you.inv[i].plus == branch) + { + return (true); + } + return (false); +} + // // This function returns true if the player can use controlled // teleport here. @@ -495,10 +522,58 @@ bool allow_control_teleport( bool silent ) { bool ret = true; - if (testbits(env.level_flags, LFLAG_NO_TELE_CONTROL) - || testbits(get_branch_flags(), BFLAG_NO_TELE_CONTROL)) - { + if (you.level_type == LEVEL_ABYSS || you.level_type == LEVEL_LABYRINTH) ret = false; + else + { + switch (you.where_are_you) + { + case BRANCH_TOMB: + ret = player_has_rune(you.where_are_you); + break; + + case BRANCH_COCYTUS: + case BRANCH_DIS: + case BRANCH_TARTARUS: + case BRANCH_GEHENNA: + if (player_branch_depth() == branches[you.where_are_you].depth) + ret = player_has_rune(you.where_are_you); + break; + + case BRANCH_SLIME_PITS: + // Cannot teleport into the slime pit vaults until + // royal jelly is gone. + if (monster_on_level(MONS_ROYAL_JELLY)) + ret = false; + break; + + case BRANCH_ELVEN_HALLS: + // Cannot raid the elven halls vaults until fountain drained + if (player_branch_depth() == branches[BRANCH_ELVEN_HALLS].depth) + { + for (int x = 5; x < GXM - 5; x++) + { + for (int y = 5; y < GYM - 5; y++) + { + if (grd[x][y] == DNGN_SPARKLING_FOUNTAIN) + ret = false; + } + } + } + break; + + case BRANCH_HALL_OF_ZOT: + // Cannot control teleport until the Orb is picked up + if (player_branch_depth() == branches[BRANCH_HALL_OF_ZOT].depth + && you.char_direction != GDT_ASCENDING) + { + ret = false; + } + break; + + default: + break; + } } // Tell the player why if they have teleport control. @@ -562,7 +637,10 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) return true; } - coord_def pos(1, 0); + FixedVector < int, 2 > plox; + + plox[0] = 1; + plox[1] = 0; if (is_controlled) { @@ -570,24 +648,25 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) mpr("Expect minor deviation."); more(); - show_map(pos, false); + show_map(plox, false); redraw_screen(); #if DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", pos.x, pos.y ); + mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", plox[0], plox[1] ); #endif - pos.x += random2(3) - 1; - pos.y += random2(3) - 1; + plox[0] += random2(3) - 1; + plox[1] += random2(3) - 1; if (one_chance_in(4)) { - pos.x += random2(3) - 1; - pos.y += random2(3) - 1; + plox[0] += random2(3) - 1; + plox[1] += random2(3) - 1; } - if (!in_bounds(pos)) + if (plox[0] < 6 || plox[1] < 6 || plox[0] > (GXM - 5) + || plox[1] > (GYM - 5)) { mpr("Nearby solid objects disrupt your rematerialisation!"); is_controlled = false; @@ -595,16 +674,16 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) #if DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, - "Scattered target square (%d,%d)", pos.x, pos.y ); + "Scattered target square (%d,%d)", plox[0], plox[1] ); #endif if (is_controlled) { // no longer held in net - if (pos.x != you.x_pos || pos.y != you.y_pos) + if (plox[0] != you.x_pos || plox[1] != you.y_pos) clear_trapping_net(); - you.moveto(pos.x, pos.y); + you.moveto(plox[0], plox[1]); if ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) @@ -627,8 +706,8 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) do { - newx = random_range(X_BOUND_1 + 1, X_BOUND_2 - 1); - newy = random_range(Y_BOUND_1 + 1, Y_BOUND_2 - 1); + newx = 5 + random2( GXM - 10 ); + newy = 5 + random2( GYM - 10 ); } while ((grd[newx][newy] != DNGN_FLOOR && grd[newx][newy] != DNGN_SHALLOW_WATER) @@ -659,34 +738,28 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) void you_teleport_now( bool allow_control, bool new_abyss_area ) { const bool randtele = teleport_player(allow_control, new_abyss_area); - // Xom is amused by uncontrolled teleports that land you in a - // dangerous place, unless the player is in the Abyss and - // teleported to escape from all the monsters chasing him/her, - // since in that case the new dangerous area is almost certainly - // *less* dangerous than the old dangerous area. - if (randtele && player_in_a_dangerous_place() - && you.level_type != LEVEL_ABYSS) - { + // dangerous place. + if (randtele && player_in_a_dangerous_place()) xom_is_stimulated(255); - } } bool entomb(int powc) { - // power guidelines: - // powc is roughly 50 at Evoc 10 with no godly assistance, ranging - // up to 300 or so with godly assistance or end-level, and 1200 - // as more or less the theoretical maximum. int number_built = 0; const dungeon_feature_type safe_to_overwrite[] = { DNGN_FLOOR, DNGN_SHALLOW_WATER, DNGN_OPEN_DOOR, - DNGN_TRAP_MECHANICAL, DNGN_TRAP_MAGICAL, DNGN_TRAP_NATURAL, + DNGN_TRAP_MECHANICAL, DNGN_TRAP_MAGICAL, DNGN_TRAP_III, DNGN_UNDISCOVERED_TRAP, DNGN_FLOOR_SPECIAL }; + if ( powc > 95 ) + powc = 95; + if ( powc < 25 ) + powc = 25; + for (int srx = you.x_pos - 1; srx < you.x_pos + 2; srx++) { for (int sry = you.y_pos - 1; sry < you.y_pos + 2; sry++) @@ -698,7 +771,7 @@ bool entomb(int powc) continue; } - if ( one_chance_in(powc/5) ) + if ( random2(100) > powc ) continue; bool proceed = false; @@ -769,29 +842,7 @@ bool entomb(int powc) } if (number_built > 0) - { mpr("Walls emerge from the floor!"); - - for (int i = you.beheld_by.size() - 1; i >= 0; i--) - { - const monsters* mon = &menv[you.beheld_by[i]]; - const coord_def pos = mon->pos(); - int walls = num_feats_between(you.x_pos, you.y_pos, - pos.x, pos.y, DNGN_UNSEEN, - DNGN_MAXWALL); - - if (walls > 0) - { - update_beholders(mon, true); - if (you.beheld_by.empty()) - { - you.duration[DUR_BEHELD] = 0; - break; - } - continue; - } - } - } else canned_msg(MSG_NOTHING_HAPPENS); @@ -828,24 +879,29 @@ void cast_poison_ammo(void) bool project_noise(void) { bool success = false; + FixedVector < int, 2 > plox; - coord_def pos(1, 0); + plox[0] = 1; + plox[1] = 0; mpr( "Choose the noise's source (press '.' or delete to select)." ); more(); - show_map(pos, false); + show_map(plox, false); redraw_screen(); #if DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", pos.x, pos.y ); + mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", plox[0], plox[1] ); #endif - if (!silenced( pos.x, pos.y )) + if (!silenced( plox[0], plox[1] )) { - if (in_bounds(pos) && !grid_is_solid(grd(pos))) + // player can use this spell to "sound out" the dungeon -- bwr + if (plox[0] > 1 && plox[0] < (GXM - 2) + && plox[1] > 1 && plox[1] < (GYM - 2) + && !grid_is_solid(grd[ plox[0] ][ plox[1] ])) { - noisy( 30, pos.x, pos.y ); + noisy( 30, plox[0], plox[1] ); success = true; } @@ -853,7 +909,7 @@ bool project_noise(void) { if (success) mprf(MSGCH_SOUND, "You hear a %svoice call your name.", - (!see_grid( pos.x, pos.y ) ? "distant " : "") ); + (see_grid( plox[0], plox[1] ) ? "distant " : "") ); else mprf(MSGCH_SOUND, "You hear a dull thud."); } @@ -946,10 +1002,13 @@ bool recall(char type_recalled) return (success); } // end recall() -// Restricted to main dungeon for historical reasons, probably for -// balance: otherwise you have an instant teleport from anywhere. -int portal() +int portal(void) { + char dir_sign = 0; + unsigned char keyi; + int target_level = 0; + int old_level = you.your_level; + if (!player_in_branch( BRANCH_MAIN_DUNGEON )) { mpr("This spell doesn't work here."); @@ -960,70 +1019,84 @@ int portal() mpr("You must find a clear area in which to cast this spell."); return (-1); } - else if (you.char_direction == GDT_ASCENDING) + else { - // be evil if you've got the Orb - mpr("An empty arch forms before you, then disappears."); - return 1; - } + // the first query {dlb}: + mpr("Which direction ('<' for up, '>' for down, 'x' to quit)?", MSGCH_PROMPT); - mpr("Which direction ('<' for up, '>' for down, 'x' to quit)?", - MSGCH_PROMPT); - - int dir_sign = 0; - while (dir_sign == 0) - { - const int keyin = getch(); - switch ( keyin ) + for (;;) { - case '<': - if (you.your_level == 0) - mpr("You can't go any further upwards with this spell."); - else - dir_sign = -1; - break; + keyi = get_ch(); - case '>': - if (you.your_level + 1 == your_branch().depth) - mpr("You can't go any further downwards with this spell."); - else - dir_sign = 1; - break; + if (keyi == '<') + { + if (you.your_level == 0) + mpr("You can't go any further upwards with this spell."); + else + { + dir_sign = -1; + break; + } + } - case 'x': - canned_msg(MSG_OK); - return (-1); + if (keyi == '>') + { + if (you.your_level == 35) + mpr("You can't go any further downwards with this spell."); + else + { + dir_sign = 1; + break; + } + } - default: - break; + if (keyi == 'x') + { + canned_msg(MSG_OK); + return (-1); // an early return {dlb} + } } - } - mpr("How many levels (1 - 9, 'x' to quit)?", MSGCH_PROMPT); + // the second query {dlb}: + mpr("How many levels (1 - 9, 'x' to quit)?", MSGCH_PROMPT); - int amount = 0; - while (amount == 0) - { - const int keyin = getch(); - if ( isdigit(keyin) ) - amount = (keyin - '0') * dir_sign; - else if (keyin == 'x') + for (;;) { - canned_msg(MSG_OK); - return (-1); + keyi = get_ch(); + + if (keyi == 'x') + { + canned_msg(MSG_OK); + return (-1); // another early return {dlb} + } + + if (!(keyi < '1' || keyi > '9')) + { + target_level = you.your_level + ((keyi - '0') * dir_sign); + break; + } } - } - mpr( "You fall through a mystic portal, and materialise at the " - "foot of a staircase." ); - more(); + // actual handling begins here {dlb}: + if (player_in_branch( BRANCH_MAIN_DUNGEON )) + { + if (target_level < 0) + target_level = 0; + else if (target_level > 26) + target_level = 26; + } - const int old_level = you.your_level; - you.your_level = std::max(0, std::min(26, you.your_level + amount)) - 1; - down_stairs( old_level, DNGN_STONE_STAIRS_DOWN_I ); + mpr( "You fall through a mystic portal, and materialise at the " + "foot of a staircase." ); + more(); + + you.your_level = target_level - 1; + + down_stairs( old_level, DNGN_STONE_STAIRS_DOWN_I ); + } return (1); -} +} // end portal() bool cast_death_channel(int power) { |