diff options
Diffstat (limited to 'crawl-ref/source/spells3.cc')
-rw-r--r-- | crawl-ref/source/spells3.cc | 299 |
1 files changed, 113 insertions, 186 deletions
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 032f3bb2a7..200c0cfa83 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -43,7 +43,6 @@ #include "place.h" #include "player.h" #include "randart.h" -#include "religion.h" #include "spells1.h" #include "spells4.h" #include "spl-cast.h" @@ -51,8 +50,7 @@ #include "stuff.h" #include "traps.h" #include "view.h" - -static bool monster_on_level(int monster); +#include "xom.h" bool cast_selective_amnesia(bool force) { @@ -489,31 +487,6 @@ 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. @@ -522,58 +495,10 @@ bool allow_control_teleport( bool silent ) { bool ret = true; - if (you.level_type == LEVEL_ABYSS || you.level_type == LEVEL_LABYRINTH) - ret = false; - else + if (testbits(env.level_flags, LFLAG_NO_TELE_CONTROL) + || testbits(get_branch_flags(), BFLAG_NO_TELE_CONTROL)) { - 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; - } + ret = false; } // Tell the player why if they have teleport control. @@ -637,10 +562,7 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) return true; } - FixedVector < int, 2 > plox; - - plox[0] = 1; - plox[1] = 0; + coord_def pos(1, 0); if (is_controlled) { @@ -648,25 +570,24 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) mpr("Expect minor deviation."); more(); - show_map(plox, false); + show_map(pos, false); redraw_screen(); #if DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", plox[0], plox[1] ); + mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", pos.x, pos.y ); #endif - plox[0] += random2(3) - 1; - plox[1] += random2(3) - 1; + pos.x += random2(3) - 1; + pos.y += random2(3) - 1; if (one_chance_in(4)) { - plox[0] += random2(3) - 1; - plox[1] += random2(3) - 1; + pos.x += random2(3) - 1; + pos.y += random2(3) - 1; } - if (plox[0] < 6 || plox[1] < 6 || plox[0] > (GXM - 5) - || plox[1] > (GYM - 5)) + if (!in_bounds(pos)) { mpr("Nearby solid objects disrupt your rematerialisation!"); is_controlled = false; @@ -674,16 +595,16 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) #if DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, - "Scattered target square (%d,%d)", plox[0], plox[1] ); + "Scattered target square (%d,%d)", pos.x, pos.y ); #endif if (is_controlled) { // no longer held in net - if (plox[0] != you.x_pos || plox[1] != you.y_pos) + if (pos.x != you.x_pos || pos.y != you.y_pos) clear_trapping_net(); - you.moveto(plox[0], plox[1]); + you.moveto(pos.x, pos.y); if ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) @@ -706,8 +627,8 @@ static bool teleport_player( bool allow_control, bool new_abyss_area ) do { - newx = 5 + random2( GXM - 10 ); - newy = 5 + random2( GYM - 10 ); + newx = random_range(X_BOUND_1 + 1, X_BOUND_2 - 1); + newy = random_range(Y_BOUND_1 + 1, Y_BOUND_2 - 1); } while ((grd[newx][newy] != DNGN_FLOOR && grd[newx][newy] != DNGN_SHALLOW_WATER) @@ -738,28 +659,34 @@ 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. - if (randtele && player_in_a_dangerous_place()) + // 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) + { 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_III, + DNGN_TRAP_MECHANICAL, DNGN_TRAP_MAGICAL, DNGN_TRAP_NATURAL, 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++) @@ -771,7 +698,7 @@ bool entomb(int powc) continue; } - if ( random2(100) > powc ) + if ( one_chance_in(powc/5) ) continue; bool proceed = false; @@ -842,7 +769,29 @@ 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); @@ -879,29 +828,24 @@ void cast_poison_ammo(void) bool project_noise(void) { bool success = false; - FixedVector < int, 2 > plox; - plox[0] = 1; - plox[1] = 0; + coord_def pos(1, 0); mpr( "Choose the noise's source (press '.' or delete to select)." ); more(); - show_map(plox, false); + show_map(pos, false); redraw_screen(); #if DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", plox[0], plox[1] ); + mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", pos.x, pos.y ); #endif - if (!silenced( plox[0], plox[1] )) + if (!silenced( pos.x, pos.y )) { - // 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] ])) + if (in_bounds(pos) && !grid_is_solid(grd(pos))) { - noisy( 30, plox[0], plox[1] ); + noisy( 30, pos.x, pos.y ); success = true; } @@ -909,7 +853,7 @@ bool project_noise(void) { if (success) mprf(MSGCH_SOUND, "You hear a %svoice call your name.", - (see_grid( plox[0], plox[1] ) ? "distant " : "") ); + (!see_grid( pos.x, pos.y ) ? "distant " : "") ); else mprf(MSGCH_SOUND, "You hear a dull thud."); } @@ -1002,13 +946,10 @@ bool recall(char type_recalled) return (success); } // end recall() -int portal(void) +// Restricted to main dungeon for historical reasons, probably for +// balance: otherwise you have an instant teleport from anywhere. +int portal() { - 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."); @@ -1019,84 +960,70 @@ int portal(void) mpr("You must find a clear area in which to cast this spell."); return (-1); } - else + else if (you.char_direction == GDT_ASCENDING) { - // the first query {dlb}: - mpr("Which direction ('<' for up, '>' for down, 'x' to quit)?", MSGCH_PROMPT); + // be evil if you've got the Orb + mpr("An empty arch forms before you, then disappears."); + return 1; + } - for (;;) + 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 ) { - keyi = get_ch(); + case '<': + if (you.your_level == 0) + mpr("You can't go any further upwards 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 '>': + 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 == 35) - mpr("You can't go any further downwards with this spell."); - else - { - dir_sign = 1; - break; - } - } + case 'x': + canned_msg(MSG_OK); + return (-1); - if (keyi == 'x') - { - canned_msg(MSG_OK); - return (-1); // an early return {dlb} - } + default: + break; } + } - // the second query {dlb}: - mpr("How many levels (1 - 9, 'x' to quit)?", MSGCH_PROMPT); - - for (;;) - { - keyi = get_ch(); - - if (keyi == 'x') - { - canned_msg(MSG_OK); - return (-1); // another early return {dlb} - } + mpr("How many levels (1 - 9, 'x' to quit)?", MSGCH_PROMPT); - if (!(keyi < '1' || keyi > '9')) - { - target_level = you.your_level + ((keyi - '0') * dir_sign); - break; - } - } - - // actual handling begins here {dlb}: - if (player_in_branch( BRANCH_MAIN_DUNGEON )) + int amount = 0; + while (amount == 0) + { + const int keyin = getch(); + if ( isdigit(keyin) ) + amount = (keyin - '0') * dir_sign; + else if (keyin == 'x') { - if (target_level < 0) - target_level = 0; - else if (target_level > 26) - target_level = 26; + canned_msg(MSG_OK); + return (-1); } + } - mpr( "You fall through a mystic portal, and materialise at the " - "foot of a staircase." ); - more(); - - you.your_level = target_level - 1; + mpr( "You fall through a mystic portal, and materialise at the " + "foot of a staircase." ); + more(); - down_stairs( old_level, DNGN_STONE_STAIRS_DOWN_I ); - } + 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 ); return (1); -} // end portal() +} bool cast_death_channel(int power) { |