OSDN Git Service

スターバースト自体は透明な壁の向こうに投げることは出来ないがボール爆
authornothere <nothere@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 2 Dec 2003 20:31:55 +0000 (20:31 +0000)
committernothere <nothere@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 2 Dec 2003 20:31:55 +0000 (20:31 +0000)
風範囲は透明な壁を通過する仕様になったことで, 透明な壁の向こうにいる
モンスターがスターバーストを使える場合, プレイヤーに向けて投げられた
ボールの中心から半径3以内の爆風範囲にいる場合はスターバーストを選択肢
に入れて, 透明な壁の向こうから攻撃できるように変更. なお, 以下の変更
を含む.
* 閃光のブレスと分解のブレスの両方を持つモンスターの視界内のPROJECTの
  ない地形にプレイヤーがいる場合, 分解の判定を優先するように変更.
* 以前にget_project_point()を簡略化した結果着弾点の計算がずれていて,
  ボール範囲でのペットの巻き添えバグも再発していたので再修正.
* スターバーストの巻き添え範囲判定を透明な壁に対応.

src/externs.h
src/mspells1.c
src/mspells2.c

index e08b33d..d4879a0 100644 (file)
@@ -1416,6 +1416,7 @@ extern bool raise_possible(monster_type *m_ptr);
 extern bool spell_is_inate(u16b spell);
 
 /* mspells2.c */
+extern void get_project_point(int sy, int sx, int *ty, int *tx, int flg);
 extern bool monst_spell_monst(int m_idx);
 
 /* artifact.c */
index 2b196ca..6ab2bb9 100644 (file)
@@ -1192,6 +1192,11 @@ bool spell_is_inate(u16b spell)
 }
 
 
+#define DO_SPELL_NONE    0
+#define DO_SPELL_BR_LITE 1
+#define DO_SPELL_BR_DISI 2
+#define DO_SPELL_BA_LITE 3
+
 /*
  * Creatures can cast spells, shoot missiles, and breathe.
  *
@@ -1258,8 +1263,7 @@ bool make_attack_spell(int m_idx)
        char            m_poss[80];
 #endif
        bool            no_inate = FALSE;
-       bool            do_br_lite = FALSE;
-       bool            do_br_disi = FALSE;
+       bool            do_spell = DO_SPELL_NONE;
        int             dam = 0;
        u32b mode = 0L;
        int s_num_6 = (easy_band ? 2 : 6);
@@ -1320,11 +1324,11 @@ bool make_attack_spell(int m_idx)
        {
                if (!have_flag(f_flags_bold(y, x), FF_PROJECT))
                {
-                       /* Breath lite to the transparent wall if possible */
-                       if ((f4 & RF4_BR_LITE) && cave_los_bold(y, x) && one_in_(2)) do_br_lite = TRUE;
-
                        /* Breath disintegration to the wall if possible */
-                       if ((f4 & RF4_BR_DISI) && have_flag(f_flags_bold(y, x), FF_HURT_DISI) && one_in_(2)) do_br_disi = TRUE;
+                       if ((f4 & RF4_BR_DISI) && have_flag(f_flags_bold(y, x), FF_HURT_DISI) && one_in_(2)) do_spell = DO_SPELL_BR_DISI;
+
+                       /* Breath lite to the transparent wall if possible */
+                       else if ((f4 & RF4_BR_LITE) && cave_los_bold(y, x) && one_in_(2)) do_spell = DO_SPELL_BR_LITE;
                }
        }
 
@@ -1333,23 +1337,33 @@ bool make_attack_spell(int m_idx)
        {
                bool success = FALSE;
 
-               if ((f4 & RF4_BR_DISI) &&
-                   (m_ptr->cdis < MAX_RANGE/2) &&
+               if ((f4 & RF4_BR_DISI) && (m_ptr->cdis < MAX_RANGE/2) &&
                    in_disintegration_range(m_ptr->fy, m_ptr->fx, y, x) &&
                    (one_in_(10) || (projectable(y, x, m_ptr->fy, m_ptr->fx) && one_in_(2))))
                {
-                       do_br_disi = TRUE;
+                       do_spell = DO_SPELL_BR_DISI;
                        success = TRUE;
                }
-               else if ((f4 & RF4_BR_LITE) &&
-                   (m_ptr->cdis < MAX_RANGE/2) &&
+               else if ((f4 & RF4_BR_LITE) && (m_ptr->cdis < MAX_RANGE/2) &&
                    los(m_ptr->fy, m_ptr->fx, y, x) &&
                    (one_in_(10) || (projectable(y, x, m_ptr->fy, m_ptr->fx) && one_in_(2))))
                {
-                       do_br_lite = TRUE;
+                       do_spell = DO_SPELL_BR_LITE;
                        success = TRUE;
                }
-               else
+               else if ((f5 & RF5_BA_LITE) && (m_ptr->cdis <= MAX_RANGE))
+               {
+                       int by = y, bx = x;
+                       get_project_point(m_ptr->fy, m_ptr->fx, &by, &bx, 0L);
+                       if ((distance(by, bx, y, x) <= 3) && los(by, bx, y, x) &&
+                           (one_in_(10) || (projectable(y, x, m_ptr->fy, m_ptr->fx) && one_in_(2))))
+                       {
+                               do_spell = DO_SPELL_BA_LITE;
+                               success = TRUE;
+                       }
+               }
+
+               if (!success)
                {
                        int i;
                        int tonari;
@@ -1556,27 +1570,33 @@ bool make_attack_spell(int m_idx)
        monster_desc(m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
 #endif
 
-       if (do_br_lite && do_br_disi)
-       {
-               if (one_in_(2)) thrown_spell = 96+14; /* RF4_BR_LITE */
-               else thrown_spell = 96+31; /* RF4_BR_DISI */
-       }
-       else if (do_br_lite)
-       {
-               thrown_spell = 96+14; /* RF4_BR_LITE */
-       }
-       else if (do_br_disi)
-       {
-               thrown_spell = 96+31; /* RF4_BR_DISI */
-       }
-       else
+       switch (do_spell)
        {
-               int attempt = 10;
-               while(attempt--)
+       case DO_SPELL_NONE:
                {
-                       thrown_spell = choose_attack_spell(m_idx, spell, num);
-                       if (thrown_spell) break;
+                       int attempt = 10;
+                       while (attempt--)
+                       {
+                               thrown_spell = choose_attack_spell(m_idx, spell, num);
+                               if (thrown_spell) break;
+                       }
                }
+               break;
+
+       case DO_SPELL_BR_LITE:
+               thrown_spell = 96+14; /* RF4_BR_LITE */
+               break;
+
+       case DO_SPELL_BR_DISI:
+               thrown_spell = 96+31; /* RF4_BR_DISI */
+               break;
+
+       case DO_SPELL_BA_LITE:
+               thrown_spell = 128+20; /* RF5_BA_LITE */
+               break;
+
+       default:
+               return FALSE; /* Paranoia */
        }
 
        /* Abort if no spell was chosen */
index 486f5aa..621866a 100644 (file)
@@ -168,23 +168,27 @@ static bool breath_direct(int y1, int x1, int y2, int x2, int rad, int typ, bool
 }
 
 /*
- * Get the actual center point of ball spells (originally from TOband)
+ * Get the actual center point of ball spells (rad > 1) (originally from TOband)
  */
-static void get_project_point(int sy, int sx, int *ty, int *tx, int flg)
+void get_project_point(int sy, int sx, int *ty, int *tx, int flg)
 {
        u16b path_g[128];
-       int  path_n;
+       int  path_n, i;
 
        path_n = project_path(path_g, MAX_RANGE, sy, sx, *ty, *tx, flg);
 
-       if (path_n)
-       {
-               /* Use final point of projection */
-               *ty = GRID_Y(path_g[path_n - 1]);
-               *tx = GRID_X(path_g[path_n - 1]);
-       }
-       else
+       *ty = sy;
+       *tx = sx;
+
+       /* Project along the path */
+       for (i = 0; i < path_n; i++)
        {
+               sy = GRID_Y(path_g[i]);
+               sx = GRID_X(path_g[i]);
+
+               /* Hack -- Balls explode before reaching walls */
+               if (!have_flag(f_flags_bold(sy, sx), FF_PROJECT)) break;
+
                *ty = sy;
                *tx = sx;
        }
@@ -438,6 +442,11 @@ bool monst_spell_monst(int m_idx)
                                                f6 &= ~(RF6_BIG_BALL_MASK);
                                        }
                                }
+                               else if (f5 & RF5_BA_LITE)
+                               {
+                                       if ((distance(real_y, real_x, py, px) <= 4) && los(real_y, real_x, py, px))
+                                               f5 &= ~(RF5_BA_LITE);
+                               }
                        }
 
                        if (f4 & RF4_ROCKET)