X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fspells2.c;h=2d46fd58f52df2cac619ed7547c0014a1f317a55;hb=809f285c4a153afcad25d9462cd24f996ed54e6b;hp=975e3ff47f3e56d6e17b9f318b427a34c12e2b1c;hpb=fd1d0426e59fc285e58c9f972a561d270bd55d20;p=hengband%2Fhengband.git diff --git a/src/spells2.c b/src/spells2.c index 975e3ff47..2d46fd58f 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -13,6 +13,7 @@ #include "angband.h" #include "grid.h" +#include "trap.h" /*! @@ -2902,7 +2903,7 @@ bool fire_ball(int typ, int dir, HIT_POINT dam, int rad) */ bool fire_breath(int typ, int dir, HIT_POINT dam, int rad) { - fire_ball(typ, dir, dam, -rad); + return fire_ball(typ, dir, dam, -rad); } @@ -4253,3 +4254,755 @@ void remove_all_mirrors(bool explode) } } } + +/*! + * @brief 『一つの指輪』の効果処理 / + * Hack -- activate the ring of power + * @param dir 発動の方向ID + * @return なし + */ +void ring_of_power(int dir) +{ + /* Pick a random effect */ + switch (randint1(10)) + { + case 1: + case 2: + { + /* Message */ + msg_print(_("あなたは悪性のオーラに包み込まれた。", "You are surrounded by a malignant aura.")); + sound(SOUND_EVIL); + + /* Decrease all stats (permanently) */ + (void)dec_stat(A_STR, 50, TRUE); + (void)dec_stat(A_INT, 50, TRUE); + (void)dec_stat(A_WIS, 50, TRUE); + (void)dec_stat(A_DEX, 50, TRUE); + (void)dec_stat(A_CON, 50, TRUE); + (void)dec_stat(A_CHR, 50, TRUE); + + /* Lose some experience (permanently) */ + p_ptr->exp -= (p_ptr->exp / 4); + p_ptr->max_exp -= (p_ptr->exp / 4); + check_experience(); + + break; + } + + case 3: + { + /* Message */ + msg_print(_("あなたは強力なオーラに包み込まれた。", "You are surrounded by a powerful aura.")); + + /* Dispel monsters */ + dispel_monsters(1000); + + break; + } + + case 4: + case 5: + case 6: + { + /* Mana Ball */ + fire_ball(GF_MANA, dir, 600, 3); + + break; + } + + case 7: + case 8: + case 9: + case 10: + { + /* Mana Bolt */ + fire_bolt(GF_MANA, dir, 500); + + break; + } + } +} + +/*! +* @brief 運命の輪、並びにカオス的な効果の発動 +* @param spell ランダムな効果を選択するための基準ID +* @return なし +*/ +void wild_magic(int spell) +{ + int counter = 0; + int type = SUMMON_MOLD + randint0(6); + + if (type < SUMMON_MOLD) type = SUMMON_MOLD; + else if (type > SUMMON_MIMIC) type = SUMMON_MIMIC; + + switch (randint1(spell) + randint1(8) + 1) + { + case 1: + case 2: + case 3: + teleport_player(10, TELEPORT_PASSIVE); + break; + case 4: + case 5: + case 6: + teleport_player(100, TELEPORT_PASSIVE); + break; + case 7: + case 8: + teleport_player(200, TELEPORT_PASSIVE); + break; + case 9: + case 10: + case 11: + unlite_area(10, 3); + break; + case 12: + case 13: + case 14: + lite_area(damroll(2, 3), 2); + break; + case 15: + destroy_doors_touch(); + break; + case 16: case 17: + wall_breaker(); + case 18: + sleep_monsters_touch(); + break; + case 19: + case 20: + trap_creation(p_ptr->y, p_ptr->x); + break; + case 21: + case 22: + door_creation(); + break; + case 23: + case 24: + case 25: + aggravate_monsters(0); + break; + case 26: + earthquake(p_ptr->y, p_ptr->x, 5); + break; + case 27: + case 28: + (void)gain_random_mutation(0); + break; + case 29: + case 30: + apply_disenchant(1); + break; + case 31: + lose_all_info(); + break; + case 32: + fire_ball(GF_CHAOS, 0, spell + 5, 1 + (spell / 10)); + break; + case 33: + wall_stone(); + break; + case 34: + case 35: + while (counter++ < 8) + { + (void)summon_specific(0, p_ptr->y, p_ptr->x, (dun_level * 3) / 2, type, (PM_ALLOW_GROUP | PM_NO_PET)); + } + break; + case 36: + case 37: + activate_hi_summon(p_ptr->y, p_ptr->x, FALSE); + break; + case 38: + (void)summon_cyber(-1, p_ptr->y, p_ptr->x); + break; + default: + { + int count = 0; + (void)activate_ty_curse(FALSE, &count); + break; + } + } + + return; +} + +/*! +* @brief カオス魔法「流星群」の処理としてプレイヤーを中心に隕石落下処理を10+1d10回繰り返す。 +* / Drop 10+1d10 meteor ball at random places near the player +* @param dam ダメージ +* @param rad 効力の半径 +* @return なし +*/ +void cast_meteor(HIT_POINT dam, int rad) +{ + int i; + int b = 10 + randint1(10); + + for (i = 0; i < b; i++) + { + POSITION y = 0, x = 0; + int count; + + for (count = 0; count <= 20; count++) + { + int dy, dx, d; + + x = p_ptr->x - 8 + randint0(17); + y = p_ptr->y - 8 + randint0(17); + + dx = (p_ptr->x > x) ? (p_ptr->x - x) : (x - p_ptr->x); + dy = (p_ptr->y > y) ? (p_ptr->y - y) : (y - p_ptr->y); + + /* Approximate distance */ + d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)); + + if (d >= 9) continue; + + if (!in_bounds(y, x) || !projectable(p_ptr->y, p_ptr->x, y, x) + || !cave_have_flag_bold(y, x, FF_PROJECT)) continue; + + /* Valid position */ + break; + } + + if (count > 20) continue; + + project(0, rad, y, x, dam, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM, -1); + } +} + + +/*! +* @brief 破邪魔法「神の怒り」の処理としてターゲットを指定した後分解のボールを最大20回発生させる。 +* @param dam ダメージ +* @param rad 効力の半径 +* @return ターゲットを指定し、実行したならばTRUEを返す。 +*/ +bool cast_wrath_of_the_god(HIT_POINT dam, int rad) +{ + int x, y, tx, ty; + int nx, ny; + int dir, i; + int b = 10 + randint1(10); + + if (!get_aim_dir(&dir)) return FALSE; + + /* Use the given direction */ + tx = p_ptr->x + 99 * ddx[dir]; + ty = p_ptr->y + 99 * ddy[dir]; + + /* Hack -- Use an actual "target" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + } + + x = p_ptr->x; + y = p_ptr->y; + + while (1) + { + /* Hack -- Stop at the target */ + if ((y == ty) && (x == tx)) break; + + ny = y; + nx = x; + mmove2(&ny, &nx, p_ptr->y, p_ptr->x, ty, tx); + + /* Stop at maximum range */ + if (MAX_RANGE <= distance(p_ptr->y, p_ptr->x, ny, nx)) break; + + /* Stopped by walls/doors */ + if (!cave_have_flag_bold(ny, nx, FF_PROJECT)) break; + + /* Stopped by monsters */ + if ((dir != 5) && cave[ny][nx].m_idx != 0) break; + + /* Save the new location */ + x = nx; + y = ny; + } + tx = x; + ty = y; + + for (i = 0; i < b; i++) + { + int count = 20, d = 0; + + while (count--) + { + int dx, dy; + + x = tx - 5 + randint0(11); + y = ty - 5 + randint0(11); + + dx = (tx > x) ? (tx - x) : (x - tx); + dy = (ty > y) ? (ty - y) : (y - ty); + + /* Approximate distance */ + d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)); + /* Within the radius */ + if (d < 5) break; + } + + if (count < 0) continue; + + /* Cannot penetrate perm walls */ + if (!in_bounds(y, x) || + cave_stop_disintegration(y, x) || + !in_disintegration_range(ty, tx, y, x)) + continue; + + project(0, rad, y, x, dam, GF_DISINTEGRATE, PROJECT_JUMP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL, -1); + } + + return TRUE; +} + +/*! +* @brief 「ワンダー」のランダムな効果を決定して処理する。 +* @param dir 方向ID +* @return なし +* @details +* This spell should become more useful (more controlled) as the\n +* player gains experience levels. Thus, add 1/5 of the player's\n +* level to the die roll. This eliminates the worst effects later on,\n +* while keeping the results quite random. It also allows some potent\n +* effects only at high level. +*/ +void cast_wonder(int dir) +{ + int plev = p_ptr->lev; + int die = randint1(100) + plev / 5; + int vir = virtue_number(V_CHANCE); + + if (vir) + { + if (p_ptr->virtues[vir - 1] > 0) + { + while (randint1(400) < p_ptr->virtues[vir - 1]) die++; + } + else + { + while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--; + } + } + + if (die < 26) + chg_virtue(V_CHANCE, 1); + + if (die > 100) + { + msg_print(_("あなたは力がみなぎるのを感じた!", "You feel a surge of power!")); + } + + if (die < 8) clone_monster(dir); + else if (die < 14) speed_monster(dir, plev); + else if (die < 26) heal_monster(dir, damroll(4, 6)); + else if (die < 31) poly_monster(dir, plev); + else if (die < 36) + fire_bolt_or_beam(beam_chance() - 10, GF_MISSILE, dir, + damroll(3 + ((plev - 1) / 5), 4)); + else if (die < 41) confuse_monster(dir, plev); + else if (die < 46) fire_ball(GF_POIS, dir, 20 + (plev / 2), 3); + else if (die < 51) (void)lite_line(dir, damroll(6, 8)); + else if (die < 56) + fire_bolt_or_beam(beam_chance() - 10, GF_ELEC, dir, + damroll(3 + ((plev - 5) / 4), 8)); + else if (die < 61) + fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir, + damroll(5 + ((plev - 5) / 4), 8)); + else if (die < 66) + fire_bolt_or_beam(beam_chance(), GF_ACID, dir, + damroll(6 + ((plev - 5) / 4), 8)); + else if (die < 71) + fire_bolt_or_beam(beam_chance(), GF_FIRE, dir, + damroll(8 + ((plev - 5) / 4), 8)); + else if (die < 76) hypodynamic_bolt(dir, 75); + else if (die < 81) fire_ball(GF_ELEC, dir, 30 + plev / 2, 2); + else if (die < 86) fire_ball(GF_ACID, dir, 40 + plev, 2); + else if (die < 91) fire_ball(GF_ICE, dir, 70 + plev, 3); + else if (die < 96) fire_ball(GF_FIRE, dir, 80 + plev, 3); + else if (die < 101) hypodynamic_bolt(dir, 100 + plev); + else if (die < 104) + { + earthquake(p_ptr->y, p_ptr->x, 12); + } + else if (die < 106) + { + (void)destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE); + } + else if (die < 108) + { + symbol_genocide(plev + 50, TRUE); + } + else if (die < 110) dispel_monsters(120); + else /* RARE */ + { + dispel_monsters(150); + slow_monsters(plev); + sleep_monsters(plev); + hp_player(300); + } +} + + +/*! +* @brief 「悪霊召喚」のランダムな効果を決定して処理する。 +* @param dir 方向ID +* @return なし +*/ +void cast_invoke_spirits(int dir) +{ + int plev = p_ptr->lev; + int die = randint1(100) + plev / 5; + int vir = virtue_number(V_CHANCE); + + if (vir) + { + if (p_ptr->virtues[vir - 1] > 0) + { + while (randint1(400) < p_ptr->virtues[vir - 1]) die++; + } + else + { + while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--; + } + } + + msg_print(_("あなたは死者たちの力を招集した...", "You call on the power of the dead...")); + if (die < 26) + chg_virtue(V_CHANCE, 1); + + if (die > 100) + { + msg_print(_("あなたはおどろおどろしい力のうねりを感じた!", "You feel a surge of eldritch force!")); + } + + if (die < 8) + { + msg_print(_("なんてこった!あなたの周りの地面から朽ちた人影が立ち上がってきた!", + "Oh no! Mouldering forms rise from the earth around you!")); + + (void)summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)); + chg_virtue(V_UNLIFE, 1); + } + else if (die < 14) + { + msg_print(_("名状し難い邪悪な存在があなたの心を通り過ぎて行った...", "An unnamable evil brushes against your mind...")); + + set_afraid(p_ptr->afraid + randint1(4) + 4); + } + else if (die < 26) + { + msg_print(_("あなたの頭に大量の幽霊たちの騒々しい声が押し寄せてきた...", + "Your head is invaded by a horde of gibbering spectral voices...")); + + set_confused(p_ptr->confused + randint1(4) + 4); + } + else if (die < 31) + { + poly_monster(dir, plev); + } + else if (die < 36) + { + fire_bolt_or_beam(beam_chance() - 10, GF_MISSILE, dir, + damroll(3 + ((plev - 1) / 5), 4)); + } + else if (die < 41) + { + confuse_monster(dir, plev); + } + else if (die < 46) + { + fire_ball(GF_POIS, dir, 20 + (plev / 2), 3); + } + else if (die < 51) + { + (void)lite_line(dir, damroll(6, 8)); + } + else if (die < 56) + { + fire_bolt_or_beam(beam_chance() - 10, GF_ELEC, dir, + damroll(3 + ((plev - 5) / 4), 8)); + } + else if (die < 61) + { + fire_bolt_or_beam(beam_chance() - 10, GF_COLD, dir, + damroll(5 + ((plev - 5) / 4), 8)); + } + else if (die < 66) + { + fire_bolt_or_beam(beam_chance(), GF_ACID, dir, + damroll(6 + ((plev - 5) / 4), 8)); + } + else if (die < 71) + { + fire_bolt_or_beam(beam_chance(), GF_FIRE, dir, + damroll(8 + ((plev - 5) / 4), 8)); + } + else if (die < 76) + { + hypodynamic_bolt(dir, 75); + } + else if (die < 81) + { + fire_ball(GF_ELEC, dir, 30 + plev / 2, 2); + } + else if (die < 86) + { + fire_ball(GF_ACID, dir, 40 + plev, 2); + } + else if (die < 91) + { + fire_ball(GF_ICE, dir, 70 + plev, 3); + } + else if (die < 96) + { + fire_ball(GF_FIRE, dir, 80 + plev, 3); + } + else if (die < 101) + { + hypodynamic_bolt(dir, 100 + plev); + } + else if (die < 104) + { + earthquake(p_ptr->y, p_ptr->x, 12); + } + else if (die < 106) + { + (void)destroy_area(p_ptr->y, p_ptr->x, 13 + randint0(5), FALSE); + } + else if (die < 108) + { + symbol_genocide(plev + 50, TRUE); + } + else if (die < 110) + { + dispel_monsters(120); + } + else + { /* RARE */ + dispel_monsters(150); + slow_monsters(plev); + sleep_monsters(plev); + hp_player(300); + } + + if (die < 31) + { + msg_print(_("陰欝な声がクスクス笑う。「もうすぐおまえは我々の仲間になるだろう。弱き者よ。」", + "Sepulchral voices chuckle. 'Soon you will join us, mortal.'")); + } +} + +/*! +* @brief トランプ領域の「シャッフル」の効果をランダムに決めて処理する。 +* @return なし +*/ +void cast_shuffle(void) +{ + int plev = p_ptr->lev; + int dir; + int die; + int vir = virtue_number(V_CHANCE); + int i; + + /* Card sharks and high mages get a level bonus */ + if ((p_ptr->pclass == CLASS_ROGUE) || + (p_ptr->pclass == CLASS_HIGH_MAGE) || + (p_ptr->pclass == CLASS_SORCERER)) + die = (randint1(110)) + plev / 5; + else + die = randint1(120); + + + if (vir) + { + if (p_ptr->virtues[vir - 1] > 0) + { + while (randint1(400) < p_ptr->virtues[vir - 1]) die++; + } + else + { + while (randint1(400) < (0 - p_ptr->virtues[vir - 1])) die--; + } + } + + msg_print(_("あなたはカードを切って一枚引いた...", "You shuffle the deck and draw a card...")); + + if (die < 30) + chg_virtue(V_CHANCE, 1); + + if (die < 7) + { + msg_print(_("なんてこった!《死》だ!", "Oh no! It's Death!")); + + for (i = 0; i < randint1(3); i++) + activate_hi_summon(p_ptr->y, p_ptr->x, FALSE); + } + else if (die < 14) + { + msg_print(_("なんてこった!《悪魔》だ!", "Oh no! It's the Devil!")); + summon_specific(0, p_ptr->y, p_ptr->x, dun_level, SUMMON_DEMON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)); + } + else if (die < 18) + { + int count = 0; + msg_print(_("なんてこった!《吊られた男》だ!", "Oh no! It's the Hanged Man.")); + activate_ty_curse(FALSE, &count); + } + else if (die < 22) + { + msg_print(_("《不調和の剣》だ。", "It's the swords of discord.")); + aggravate_monsters(0); + } + else if (die < 26) + { + msg_print(_("《愚者》だ。", "It's the Fool.")); + do_dec_stat(A_INT); + do_dec_stat(A_WIS); + } + else if (die < 30) + { + msg_print(_("奇妙なモンスターの絵だ。", "It's the picture of a strange monster.")); + trump_summoning(1, FALSE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), (32 + randint1(6)), PM_ALLOW_GROUP | PM_ALLOW_UNIQUE); + } + else if (die < 33) + { + msg_print(_("《月》だ。", "It's the Moon.")); + unlite_area(10, 3); + } + else if (die < 38) + { + msg_print(_("《運命の輪》だ。", "It's the Wheel of Fortune.")); + wild_magic(randint0(32)); + } + else if (die < 40) + { + msg_print(_("テレポート・カードだ。", "It's a teleport trump card.")); + teleport_player(10, TELEPORT_PASSIVE); + } + else if (die < 42) + { + msg_print(_("《正義》だ。", "It's Justice.")); + set_blessed(p_ptr->lev, FALSE); + } + else if (die < 47) + { + msg_print(_("テレポート・カードだ。", "It's a teleport trump card.")); + teleport_player(100, TELEPORT_PASSIVE); + } + else if (die < 52) + { + msg_print(_("テレポート・カードだ。", "It's a teleport trump card.")); + teleport_player(200, TELEPORT_PASSIVE); + } + else if (die < 60) + { + msg_print(_("《塔》だ。", "It's the Tower.")); + wall_breaker(); + } + else if (die < 72) + { + msg_print(_("《節制》だ。", "It's Temperance.")); + sleep_monsters_touch(); + } + else if (die < 80) + { + msg_print(_("《塔》だ。", "It's the Tower.")); + + earthquake(p_ptr->y, p_ptr->x, 5); + } + else if (die < 82) + { + msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster.")); + trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_MOLD, 0L); + } + else if (die < 84) + { + msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster.")); + trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_BAT, 0L); + } + else if (die < 86) + { + msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster.")); + trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_VORTEX, 0L); + } + else if (die < 88) + { + msg_print(_("友好的なモンスターの絵だ。", "It's the picture of a friendly monster.")); + trump_summoning(1, TRUE, p_ptr->y, p_ptr->x, (dun_level * 3 / 2), SUMMON_COIN_MIMIC, 0L); + } + else if (die < 96) + { + msg_print(_("《恋人》だ。", "It's the Lovers.")); + + if (get_aim_dir(&dir)) + charm_monster(dir, MIN(p_ptr->lev, 20)); + } + else if (die < 101) + { + msg_print(_("《隠者》だ。", "It's the Hermit.")); + wall_stone(); + } + else if (die < 111) + { + msg_print(_("《審判》だ。", "It's the Judgement.")); + do_cmd_rerate(FALSE); + lose_all_mutations(); + } + else if (die < 120) + { + msg_print(_("《太陽》だ。", "It's the Sun.")); + chg_virtue(V_KNOWLEDGE, 1); + chg_virtue(V_ENLIGHTEN, 1); + wiz_lite(FALSE); + } + else + { + msg_print(_("《世界》だ。", "It's the World.")); + if (p_ptr->exp < PY_MAX_EXP) + { + s32b ee = (p_ptr->exp / 25) + 1; + if (ee > 5000) ee = 5000; + msg_print(_("更に経験を積んだような気がする。", "You feel more experienced.")); + gain_exp(ee); + } + } +} + +bool_hack life_stream(bool_hack message, bool_hack virtue) +{ + if(virtue) + { + chg_virtue(V_VITALITY, 1); + chg_virtue(V_UNLIFE, -5); + } + if(message) + { + msg_print(_("体中に生命力が満ちあふれてきた!", "You feel life flow through your body!")); + } + restore_level(); + (void)set_poisoned(0); + (void)set_blind(0); + (void)set_confused(0); + (void)set_image(0); + (void)set_stun(0); + (void)set_cut(0); + (void)do_res_stat(A_STR); + (void)do_res_stat(A_CON); + (void)do_res_stat(A_DEX); + (void)do_res_stat(A_WIS); + (void)do_res_stat(A_INT); + (void)do_res_stat(A_CHR); + (void)set_shero(0, TRUE); + update_stuff(); + hp_player(5000); + + return TRUE; +} +