summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/spells3.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/spells3.cc')
-rw-r--r--crawl-ref/source/spells3.cc299
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)
{