diff options
Diffstat (limited to 'stone_soup/crawl-ref/source/spells3.cc')
-rw-r--r-- | stone_soup/crawl-ref/source/spells3.cc | 1093 |
1 files changed, 0 insertions, 1093 deletions
diff --git a/stone_soup/crawl-ref/source/spells3.cc b/stone_soup/crawl-ref/source/spells3.cc deleted file mode 100644 index 1d6f710b05..0000000000 --- a/stone_soup/crawl-ref/source/spells3.cc +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * File: spells3.cc - * Summary: Implementations of some additional spells. - * Written by: Linley Henzell - * - * Change History (most recent first): - * - * <2> 9/11/99 LRH Teleportation takes longer in the Abyss - * <2> 8/05/99 BWR Added allow_control_teleport - * <1> -/--/-- LRH Created - */ - -#include "AppHdr.h" -#include "spells3.h" - -#include <ctype.h> -#include <stdio.h> -#include <string.h> - -#include "externs.h" - -#include "abyss.h" -#include "beam.h" -#include "cloud.h" -#include "direct.h" -#include "debug.h" -#include "delay.h" -#include "itemname.h" -#include "itemprop.h" -#include "items.h" -#include "it_use2.h" -#include "misc.h" -#include "monplace.h" -#include "mon-pick.h" -#include "monstuff.h" -#include "mon-util.h" -#include "player.h" -#include "randart.h" -#include "spells1.h" -#include "spl-cast.h" -#include "spl-util.h" -#include "stuff.h" -#include "view.h" -#include "wpn-misc.h" - -static bool monster_on_level(int monster); - -void cast_selective_amnesia(bool force) -{ - char ep_gain = 0; - unsigned char keyin = 0; - - if (you.spell_no == 0) - mpr("You don't know any spells."); // re: sif muna {dlb} - else - { - // query - conditional ordering is important {dlb}: - for (;;) - { - mpr( "Forget which spell ([?*] list [ESC] exit)? ", MSGCH_PROMPT ); - - keyin = (unsigned char) get_ch(); - - if (keyin == ESCAPE) - return; // early return {dlb} - - if (keyin == '?' || keyin == '*') - { - // this reassignment is "key" {dlb} - keyin = (unsigned char) list_spells(); - - redraw_screen(); - } - - if (!isalpha( keyin )) - mesclr( true ); - else - break; - } - - // actual handling begins here {dlb}: - const int spell = get_spell_by_letter( keyin ); - const int slot = get_spell_slot_by_letter( keyin ); - - if (spell == SPELL_NO_SPELL) - mpr( "You don't know that spell." ); - else - { - if (!force - && (you.religion != GOD_SIF_MUNA - && random2(you.skills[SK_SPELLCASTING]) - < random2(spell_difficulty( spell )))) - { - mpr("Oops! This spell sure is a blunt instrument."); - forget_map(20 + random2(50)); - } - else - { - ep_gain = spell_mana( spell ); - del_spell_from_memory_by_slot( slot ); - - if (ep_gain > 0) - { - inc_mp(ep_gain, false); - mpr( "The spell releases its latent energy back to you as " - "it unravels." ); - } - } - } - } - - return; -} // end cast_selective_amnesia() - -bool remove_curse(bool suppress_msg) -{ - int loopy = 0; // general purpose loop variable {dlb} - bool success = false; // whether or not curse(s) removed {dlb} - - // special "wield slot" case - see if you can figure out why {dlb}: - // because only cursed weapons in hand only count as cursed -- bwr - if (you.equip[EQ_WEAPON] != -1 - && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS) - { - if (item_cursed( you.inv[you.equip[EQ_WEAPON]] )) - { - do_uncurse_item( you.inv[you.equip[EQ_WEAPON]] ); - success = true; - you.wield_change = true; - } - } - - // everything else uses the same paradigm - are we certain? - // what of artefact rings and amulets? {dlb}: - for (loopy = EQ_CLOAK; loopy < NUM_EQUIP; loopy++) - { - if (you.equip[loopy] != -1 && item_cursed(you.inv[you.equip[loopy]])) - { - do_uncurse_item( you.inv[you.equip[loopy]] ); - success = true; - } - } - - // messaging output {dlb}: - if (!suppress_msg) - { - if (success) - mpr("You feel as if something is helping you."); - else - canned_msg(MSG_NOTHING_HAPPENS); - } - - return (success); -} // end remove_curse() - -bool detect_curse(bool suppress_msg) -{ - int loopy = 0; // general purpose loop variable {dlb} - bool success = false; // whether or not any curses found {dlb} - - for (loopy = 0; loopy < ENDOFPACK; loopy++) - { - if (you.inv[loopy].quantity - && (you.inv[loopy].base_type == OBJ_WEAPONS - || you.inv[loopy].base_type == OBJ_ARMOUR - || you.inv[loopy].base_type == OBJ_JEWELLERY)) - { - if (!item_ident( you.inv[loopy], ISFLAG_KNOW_CURSE )) - success = true; - - set_ident_flags( you.inv[loopy], ISFLAG_KNOW_CURSE ); - } - } - - // messaging output {dlb}: - if (!suppress_msg) - { - if (success) - mpr("You sense the presence of curses on your possessions."); - else - canned_msg(MSG_NOTHING_HAPPENS); - } - - return (success); -} // end detect_curse() - -bool cast_smiting(int power) -{ - bool success = false; - struct dist beam; - struct monsters *monster = 0; // NULL {dlb} - - mpr("Smite whom?", MSGCH_PROMPT); - - direction( beam, DIR_TARGET, TARG_ENEMY ); - - if (!beam.isValid - || mgrd[beam.tx][beam.ty] == NON_MONSTER - || beam.isMe) - { - canned_msg(MSG_SPELL_FIZZLES); - } - else - { - monster = &menv[mgrd[beam.tx][beam.ty]]; - - strcpy(info, "You smite "); - strcat(info, ptr_monam( monster, DESC_NOCAP_THE )); - strcat(info, "!"); - mpr(info); - - hurt_monster(monster, random2(8) + (random2(power) / 3)); - - if (monster->hit_points < 1) - monster_die(monster, KILL_YOU, 0); - else - print_wounds(monster); - - success = true; - } - - return (success); -} // end cast_smiting() - -bool airstrike(int power) -{ - bool success = false; - struct dist beam; - struct monsters *monster = 0; // NULL {dlb} - int hurted = 0; - - mpr("Strike whom?", MSGCH_PROMPT); - - direction( beam, DIR_TARGET, TARG_ENEMY ); - - if (!beam.isValid - || mgrd[beam.tx][beam.ty] == NON_MONSTER - || beam.isMe) - { - canned_msg(MSG_SPELL_FIZZLES); - } - else - { - monster = &menv[mgrd[beam.tx][beam.ty]]; - - strcpy(info, "The air twists around and strikes "); - strcat(info, ptr_monam( monster, DESC_NOCAP_THE )); - strcat(info, "!"); - mpr(info); - - hurted = random2( random2(12) + (random2(power) / 6) - + (random2(power) / 7) ); - hurted -= random2(1 + monster->armour_class); - - if (hurted < 0) - hurted = 0; - else - { - hurt_monster(monster, hurted); - - if (monster->hit_points < 1) - monster_die(monster, KILL_YOU, 0); - else - print_wounds(monster); - } - - success = true; - } - - return (success); -} // end airstrike() - -bool cast_bone_shards(int power) -{ - bool success = false; - struct bolt beam; - struct dist spelld; - - if (you.equip[EQ_WEAPON] == -1 - || you.inv[you.equip[EQ_WEAPON]].base_type != OBJ_CORPSES) - { - canned_msg(MSG_SPELL_FIZZLES); - } - else if (you.inv[you.equip[EQ_WEAPON]].sub_type != CORPSE_SKELETON) - mpr("The corpse collapses into a mass of pulpy flesh."); - else if (spell_direction(spelld, beam) != -1) - { - // practical max of 100 * 15 + 3000 = 4500 - // actual max of 200 * 15 + 3000 = 6000 - power *= 15; - power += mons_weight( you.inv[you.equip[EQ_WEAPON]].plus ); - - mpr("The skeleton explodes into sharp fragments of bone!"); - - dec_inv_item_quantity( you.equip[EQ_WEAPON], 1 ); - zapping(ZAP_BONE_SHARDS, power, beam); - - success = true; - } - - return (success); -} // end cast_bone_shards() - -void sublimation(int power) -{ - unsigned char loopy = 0; // general purpose loop variable {dlb} - - if (you.equip[EQ_WEAPON] == -1 - || you.inv[you.equip[EQ_WEAPON]].base_type != OBJ_FOOD - || you.inv[you.equip[EQ_WEAPON]].sub_type != FOOD_CHUNK) - { - if (you.deaths_door) - { - mpr( "A conflicting enchantment prevents the spell from " - "coming into effect." ); - } - else if (!enough_hp( 2, true )) - { - mpr("Your attempt to draw power from your own body fails."); - } - else - { - mpr("You draw magical energy from your own body!"); - - while (you.magic_points < you.max_magic_points && you.hp > 1) - { - inc_mp(1, false); - dec_hp(1, false); - - for (loopy = 0; loopy < (you.hp > 1 ? 3 : 0); loopy++) - { - if (random2(power) < 6) - dec_hp(1, false); - } - - if (random2(power) < 6) - break; - } - } - } - else - { - mpr("The chunk of flesh you are holding crumbles to dust."); - mpr("A flood of magical energy pours into your mind!"); - - inc_mp( 7 + random2(7), false ); - - dec_inv_item_quantity( you.equip[EQ_WEAPON], 1 ); - } - - return; -} // end sublimation() - -// Simulacrum -// -// This spell extends creating undead to Ice mages, as such it's high -// level, requires wielding of the material component, and the undead -// aren't overly powerful (they're also vulnerable to fire). I've put -// back the abjuration level in order to keep down the army sizes again. -// -// As for what it offers necromancers considering all the downsides -// above... it allows the turning of a single corpse into an army of -// monsters (one per food chunk)... which is also a good reason for -// why it's high level. -// -// Hides and other "animal part" items are intentionally left out, it's -// unrequired complexity, and fresh flesh makes more "sense" for a spell -// reforming the original monster out of ice anyways. -void simulacrum(int power) -{ - int max_num = 4 + random2(power) / 20; - if (max_num > 8) - max_num = 8; - - const int chunk = you.equip[EQ_WEAPON]; - - if (chunk != -1 - && is_valid_item( you.inv[ chunk ] ) - && (you.inv[ chunk ].base_type == OBJ_CORPSES - || (you.inv[ chunk ].base_type == OBJ_FOOD - && you.inv[ chunk ].sub_type == FOOD_CHUNK))) - { - const int mons_type = you.inv[ chunk ].plus; - - // Can't create more than the available chunks - if (you.inv[ chunk ].quantity < max_num) - max_num = you.inv[ chunk ].quantity; - - dec_inv_item_quantity( chunk, max_num ); - - int summoned = 0; - - for (int i = 0; i < max_num; i++) - { - if (create_monster( MONS_SIMULACRUM_SMALL, ENCH_ABJ_VI, - BEH_FRIENDLY, you.x_pos, you.y_pos, - you.pet_target, mons_type ) != -1) - { - summoned++; - } - } - - if (summoned) - { - strcpy( info, (summoned == 1) ? "An icy figure forms " - : "Some icy figures form " ); - strcat( info, "before you!" ); - mpr( info ); - } - else - mpr( "You feel cold for a second." ); - } - else - { - mpr( "You need to wield a piece of raw flesh for this spell " - "to be effective!" ); - } -} // end sublimation() - -void dancing_weapon(int pow, bool force_hostile) -{ - int numsc = ENCH_ABJ_II + (random2(pow) / 5); - char str_pass[ ITEMNAME_SIZE ]; - - if (numsc > ENCH_ABJ_VI) - numsc = ENCH_ABJ_VI; - - int i; - int summs = 0; - char behavi = BEH_FRIENDLY; - - const int wpn = you.equip[EQ_WEAPON]; - - // See if weilded item is appropriate: - if (wpn == -1 - || you.inv[wpn].base_type != OBJ_WEAPONS - || launches_things( you.inv[wpn].sub_type ) - || is_fixed_artefact( you.inv[wpn] )) - { - goto failed_spell; - } - - // See if we can get an mitm for the dancing weapon: - i = get_item_slot(); - if (i == NON_ITEM) - goto failed_spell; - - // cursed weapons become hostile - if (item_cursed( you.inv[wpn] ) || force_hostile) - behavi = BEH_HOSTILE; - - summs = create_monster( MONS_DANCING_WEAPON, numsc, behavi, - you.x_pos, you.y_pos, you.pet_target, 1 ); - - if (summs < 0) - { - // must delete the item before failing! - mitm[i].base_type = OBJ_UNASSIGNED; - mitm[i].quantity = 0; - goto failed_spell; - } - - // We are successful: - unwield_item( wpn ); // remove wield effects - - // copy item (done here after any wield effects are removed) - mitm[i] = you.inv[wpn]; - mitm[i].quantity = 1; - mitm[i].x = 0; - mitm[i].y = 0; - mitm[i].link = NON_ITEM; - - in_name( wpn, DESC_CAP_YOUR, str_pass ); - strcpy( info, str_pass ); - strcat( info, " dances into the air!" ); - mpr( info ); - - you.inv[ wpn ].quantity = 0; - you.equip[EQ_WEAPON] = -1; - - menv[summs].inv[MSLOT_WEAPON] = i; - menv[summs].number = mitm[i].colour; - - return; - -failed_spell: - mpr("Your weapon vibrates crazily for a second."); -} // 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() - -// -// This function returns true if the player can use controlled -// teleport here. -// -bool allow_control_teleport( bool silent ) -{ - bool ret = true; - - if (you.level_type == LEVEL_ABYSS || you.level_type == LEVEL_LABYRINTH) - ret = false; - else - { - switch (you.where_are_you) - { - case BRANCH_TOMB: - // The tomb is a laid out maze, it'd be a shame if the player - // just teleports through any of it... so we only allow - // teleport once they have the rune. - ret = false; - 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_TOMB) - { - ret = true; - break; - } - } - 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 (you.branch_stairs[STAIRS_ELVEN_HALLS] + - branch_depth(STAIRS_ELVEN_HALLS) == you.your_level) - { - 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 (you.branch_stairs[STAIRS_HALL_OF_ZOT] + - branch_depth(STAIRS_HALL_OF_ZOT) == you.your_level - && you.char_direction != DIR_ASCENDING) - { - ret = false; - } - break; - } - } - - // Tell the player why if they have teleport control. - if (!ret && you.attribute[ATTR_CONTROL_TELEPORT] && !silent) - mpr("A powerful magic prevents control of your teleportation."); - - return ret; -} // end allow_control_teleport() - -void you_teleport(void) -{ - if (scan_randarts(RAP_PREVENT_TELEPORTATION)) - mpr("You feel a weird sense of stasis."); - else if (you.duration[DUR_TELEPORT]) - { - mpr("You feel strangely stable."); - you.duration[DUR_TELEPORT] = 0; - } - else - { - mpr("You feel strangely unstable."); - - you.duration[DUR_TELEPORT] = 3 + random2(3); - - if (you.level_type == LEVEL_ABYSS && !one_chance_in(5)) - { - mpr("You have a feeling this translocation may take a while to kick in..."); - you.duration[DUR_TELEPORT] += 5 + random2(10); - } - } - - return; -} // end you_teleport() - -void you_teleport2( bool allow_control, bool new_abyss_area ) -{ - bool is_controlled = (allow_control && !you.conf - && you.attribute[ATTR_CONTROL_TELEPORT] - && allow_control_teleport()); - - if (scan_randarts(RAP_PREVENT_TELEPORTATION)) - { - mpr("You feel a strange sense of stasis."); - return; - } - - // after this point, we're guaranteed to teleport. Turn off auto-butcher. - // corpses still get butchered, but at least we don't get a silly message. - if (current_delay_action() == DELAY_BUTCHER) - stop_delay(); - - interrupt_activity( AI_TELEPORT ); - - if (you.duration[DUR_CONDENSATION_SHIELD] > 0) - { - you.duration[DUR_CONDENSATION_SHIELD] = 0; - you.redraw_armour_class = 1; - } - - if (you.level_type == LEVEL_ABYSS) - { - abyss_teleport( new_abyss_area ); - you.pet_target = MHITNOT; - return; - } - - FixedVector < int, 2 > plox; - - plox[0] = 1; - plox[1] = 0; - - if (is_controlled) - { - mpr("You may choose your destination (press '.' or delete to select)."); - mpr("Expect minor deviation."); - more(); - - show_map(plox); - - redraw_screen(); - -#if DEBUG_DIAGNOSTICS - snprintf( info, INFO_SIZE, "Target square (%d,%d)", plox[0], plox[1] ); - mpr( info, MSGCH_DIAGNOSTICS ); -#endif - - plox[0] += random2(3) - 1; - plox[1] += random2(3) - 1; - - if (one_chance_in(4)) - { - plox[0] += random2(3) - 1; - plox[1] += random2(3) - 1; - } - - 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; - } - -#if DEBUG_DIAGNOSTICS - snprintf( info, INFO_SIZE, "Scattered target square (%d,%d)", plox[0], plox[1] ); - mpr( info, MSGCH_DIAGNOSTICS ); -#endif - - if (is_controlled) - { - you.x_pos = plox[0]; - you.y_pos = plox[1]; - - if ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR - && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) - || mgrd[you.x_pos][you.y_pos] != NON_MONSTER - || env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD) - { - is_controlled = false; - } - else - { - // controlling teleport contaminates the player -- bwr - contaminate_player(1); - } - } - } // end "if is_controlled" - - if (!is_controlled) - { - mpr("Your surroundings suddenly seem different."); - - do - { - you.x_pos = 5 + random2( GXM - 10 ); - you.y_pos = 5 + random2( GYM - 10 ); - } - while ((grd[you.x_pos][you.y_pos] != DNGN_FLOOR - && grd[you.x_pos][you.y_pos] != DNGN_SHALLOW_WATER) - || mgrd[you.x_pos][you.y_pos] != NON_MONSTER - || env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD); - } -} // end you_teleport() - -bool entomb(void) -{ - int loopy = 0; // general purpose loop variable {dlb} - bool proceed = false; // loop management varaiable {dlb} - int which_trap = 0; // used in clearing out certain traps {dlb} - char srx = 0, sry = 0; - char number_built = 0; - - FixedVector < unsigned char, 7 > safe_to_overwrite; - - // hack - passing chars through '...' promotes them to ints, which - // barfs under gcc in fixvec.h. So don't. - safe_to_overwrite[0] = DNGN_FLOOR; - safe_to_overwrite[1] = DNGN_SHALLOW_WATER; - safe_to_overwrite[2] = DNGN_OPEN_DOOR; - safe_to_overwrite[3] = DNGN_TRAP_MECHANICAL; - safe_to_overwrite[4] = DNGN_TRAP_MAGICAL; - safe_to_overwrite[5] = DNGN_TRAP_III; - safe_to_overwrite[6] = DNGN_UNDISCOVERED_TRAP; - - - for (srx = you.x_pos - 1; srx < you.x_pos + 2; srx++) - { - for (sry = you.y_pos - 1; sry < you.y_pos + 2; sry++) - { - proceed = false; - - // tile already occupied by monster or yourself {dlb}: - if (mgrd[srx][sry] != NON_MONSTER - || (srx == you.x_pos && sry == you.y_pos)) - { - continue; - } - - // the break here affects innermost containing loop {dlb}: - for (loopy = 0; loopy < 7; loopy++) - { - if (grd[srx][sry] == safe_to_overwrite[loopy]) - { - proceed = true; - break; - } - } - - // checkpoint one - do we have a legitimate tile? {dlb} - if (!proceed) - continue; - - int objl = igrd[srx][sry]; - int hrg = 0; - - while (objl != NON_ITEM) - { - // hate to see the orb get detroyed by accident {dlb}: - if (mitm[objl].base_type == OBJ_ORBS) - { - proceed = false; - break; - } - - hrg = mitm[objl].link; - objl = hrg; - } - - // checkpoint two - is the orb resting in the tile? {dlb}: - if (!proceed) - continue; - - objl = igrd[srx][sry]; - hrg = 0; - - while (objl != NON_ITEM) - { - hrg = mitm[objl].link; - destroy_item(objl); - objl = hrg; - } - - // deal with clouds {dlb}: - if (env.cgrid[srx][sry] != EMPTY_CLOUD) - delete_cloud( env.cgrid[srx][sry] ); - - // mechanical traps are destroyed {dlb}: - if ((which_trap = trap_at_xy(srx, sry)) != -1) - { - if (trap_category(env.trap[which_trap].type) - == DNGN_TRAP_MECHANICAL) - { - env.trap[which_trap].type = TRAP_UNASSIGNED; - env.trap[which_trap].x = 1; - env.trap[which_trap].y = 1; - } - } - - // finally, place the wall {dlb}: - grd[srx][sry] = DNGN_ROCK_WALL; - number_built++; - } // end "for srx,sry" - } - - if (number_built > 0) - mpr("Walls emerge from the floor!"); - else - canned_msg(MSG_NOTHING_HAPPENS); - - return (number_built > 0); -} // end entomb() - -void cast_poison_ammo(void) -{ - const int ammo = you.equip[EQ_WEAPON]; - char str_pass[ ITEMNAME_SIZE ]; - - if (ammo == -1 - || you.inv[ammo].base_type != OBJ_MISSILES - || get_ammo_brand( you.inv[ammo] ) != SPMSL_NORMAL - || you.inv[ammo].sub_type == MI_STONE - || you.inv[ammo].sub_type == MI_LARGE_ROCK) - { - canned_msg(MSG_NOTHING_HAPPENS); - return; - } - - if (set_item_ego_type( you.inv[ammo], OBJ_MISSILES, SPMSL_POISONED )) - { - in_name(ammo, DESC_CAP_YOUR, str_pass); - strcpy(info, str_pass); - strcat(info, (you.inv[ammo].quantity == 1) ? " is" : " are"); - strcat(info, " covered in a thin film of poison."); - mpr(info); - - you.wield_change = true; - } - else - { - canned_msg(MSG_NOTHING_HAPPENS); - } -} // end cast_poison_ammo() - -bool project_noise(void) -{ - bool success = false; - FixedVector < int, 2 > plox; - - plox[0] = 1; - plox[1] = 0; - - mpr( "Choose the noise's source (press '.' or delete to select)." ); - more(); - show_map(plox); - - redraw_screen(); - -#if DEBUG_DIAGNOSTICS - snprintf( info, INFO_SIZE, "Target square (%d,%d)", plox[0], plox[1] ); - mpr( info, MSGCH_DIAGNOSTICS ); -#endif - - if (!silenced( plox[0], plox[1] )) - { - // 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, plox[0], plox[1] ); - success = true; - } - - if (!silenced( you.x_pos, you.y_pos )) - { - if (!success) - mpr("You hear a dull thud.", MSGCH_SOUND); - else - { - snprintf( info, INFO_SIZE, "You hear a %svoice call your name.", - (see_grid( plox[0], plox[1] ) ? "distant " : "") ); - mpr( info , MSGCH_SOUND ); - } - } - } - - return (success); -} // end project_noise() - -/* - Type recalled: - 0 = anything - 1 = undead only (Kiku religion ability) - */ -bool recall(char type_recalled) -{ - int loopy = 0; // general purpose looping variable {dlb} - bool success = false; // more accurately: "apparent success" {dlb} - int start_count = 0; - int step_value = 1; - int end_count = (MAX_MONSTERS - 1); - FixedVector < char, 2 > empty; - struct monsters *monster = 0; // NULL {dlb} - - empty[0] = empty[1] = 0; - -// someone really had to make life difficult {dlb}: -// sometimes goes through monster list backwards - if (coinflip()) - { - start_count = (MAX_MONSTERS - 1); - end_count = 0; - step_value = -1; - } - - for (loopy = start_count; loopy != end_count; loopy += step_value) - { - monster = &menv[loopy]; - - if (monster->type == -1) - continue; - - if (!mons_friendly(monster)) - continue; - - if (monster_habitat(monster->type) != DNGN_FLOOR) - continue; - - if (type_recalled == 1) - { - /* abomin created by twisted res, although it gets others too */ - if ( !((monster->type == MONS_ABOMINATION_SMALL - || monster->type == MONS_ABOMINATION_LARGE) - && (monster->number == BROWN - || monster->number == RED - || monster->number == LIGHTRED)) ) - { - if (monster->type != MONS_REAPER - && mons_holiness(monster) != MH_UNDEAD) - { - continue; - } - } - } - - if (empty_surrounds(you.x_pos, you.y_pos, DNGN_FLOOR, false, empty)) - { - // clear old cell pointer -- why isn't there a function for moving a monster? - mgrd[monster->x][monster->y] = NON_MONSTER; - // set monster x,y to new value - monster->x = empty[0]; - monster->y = empty[1]; - // set new monster grid pointer to this monster. - mgrd[monster->x][monster->y] = monster_index(monster); - - // only informed if monsters recalled are visible {dlb}: - if (simple_monster_message(monster, " is recalled.")) - success = true; - } - else - { - break; // no more room to place monsters {dlb} - } - } - - if (!success) - mpr("Nothing appears to have answered your call."); - - return (success); -} // end recall() - -void 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."); - } - else if (grd[you.x_pos][you.y_pos] != DNGN_FLOOR) - { - mpr("You must find a clear area in which to cast this spell."); - } - else - { - // the first query {dlb}: - mpr("Which direction ('<' for up, '>' for down, 'x' to quit)?", MSGCH_PROMPT); - - for (;;) - { - keyi = (unsigned char) get_ch(); - - if (keyi == '<') - { - 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 == 35) - mpr("You can't go any further downwards with this spell."); - else - { - dir_sign = 1; - break; - } - } - - if (keyi == 'x') - { - canned_msg(MSG_OK); - return; // an early return {dlb} - } - } - - // the second query {dlb}: - mpr("How many levels (1 - 9, 'x' to quit)?", MSGCH_PROMPT); - - for (;;) - { - keyi = (unsigned char) get_ch(); - - if (keyi == 'x') - { - canned_msg(MSG_OK); - return; // another early return {dlb} - } - - 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 )) - { - if (target_level < 0) - target_level = 0; - else if (target_level > 26) - target_level = 26; - } - - mpr( "You fall through a mystic portal, and materialise at the " - "foot of a staircase." ); - more(); - - you.your_level = target_level - 1; - grd[you.x_pos][you.y_pos] = DNGN_STONE_STAIRS_DOWN_I; - - down_stairs( true, old_level, true ); - untag_followers(); - } - - return; -} // end portal() - -bool cast_death_channel(int power) -{ - bool success = false; - - if (you.duration[DUR_DEATH_CHANNEL] < 30) - { - mpr("Malign forces permeate your being, awaiting release."); - - you.duration[DUR_DEATH_CHANNEL] += 15 + random2(1 + (power / 3)); - - if (you.duration[DUR_DEATH_CHANNEL] > 100) - you.duration[DUR_DEATH_CHANNEL] = 100; - - success = true; - } - else - { - canned_msg(MSG_NOTHING_HAPPENS); - } - - return (success); -} // end cast_death_channel() |