OSDN Git Service

プレイヤーのテレポートに受動テレポートモードを与えた. 主に自分の意志
[hengband/hengband.git] / src / spells1.c
index c52d46d..e6df64b 100644 (file)
@@ -368,6 +368,10 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
                        {
                                if ((n > 0) && cave_stop_disintegration(y, x)) break;
                        }
+                       else if (flg & (PROJECT_LOS))
+                       {
+                               if ((n > 0) && !cave_los_bold(y, x)) break;
+                       }
                        else if (!(flg & (PROJECT_PATH)))
                        {
                                /* Always stop at non-initial wall grids */
@@ -453,6 +457,10 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
                        {
                                if ((n > 0) && cave_stop_disintegration(y, x)) break;
                        }
+                       else if (flg & (PROJECT_LOS))
+                       {
+                               if ((n > 0) && !cave_los_bold(y, x)) break;
+                       }
                        else if (!(flg & (PROJECT_PATH)))
                        {
                                /* Always stop at non-initial wall grids */
@@ -520,6 +528,10 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
                        {
                                if ((n > 0) && cave_stop_disintegration(y, x)) break;
                        }
+                       else if (flg & (PROJECT_LOS))
+                       {
+                               if ((n > 0) && !cave_los_bold(y, x)) break;
+                       }
                        else if (!(flg & (PROJECT_PATH)))
                        {
                                /* Always stop at non-initial wall grids */
@@ -686,7 +698,6 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                case GF_FORCE:
                case GF_HOLY_FIRE:
                case GF_HELL_FIRE:
-               case GF_DISINTEGRATE:
                case GF_PSI:
                case GF_PSI_DRAIN:
                case GF_TELEKINESIS:
@@ -827,6 +838,7 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        if (have_flag(f_ptr->flags, FF_SPIKE))
                        {
                                s16b old_mimic = c_ptr->mimic;
+                               feature_type *mimic_f_ptr = &f_info[get_feat_mimic(c_ptr)];
 
                                cave_alter_feat(y, x, FF_SPIKE);
 
@@ -839,13 +851,13 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                                lite_spot(y, x);
 
                                /* Check line of sight */
-                               if (known && !c_ptr->mimic)
+                               if (known && have_flag(mimic_f_ptr->flags, FF_OPEN))
                                {
                                        /* Message */
 #ifdef JP
-                                       msg_format("%s¤Ë²¿¤«¤¬¤Ä¤Ã¤«¤¨¤Æ³«¤«¤Ê¤¯¤Ê¤Ã¤¿¡£", f_name + f_ptr->name);
+                                       msg_format("%s¤Ë²¿¤«¤¬¤Ä¤Ã¤«¤¨¤Æ³«¤«¤Ê¤¯¤Ê¤Ã¤¿¡£", f_name + mimic_f_ptr->name);
 #else
-                                       msg_format("The %s seems stuck.", f_name + f_ptr->name);
+                                       msg_format("The %s seems stuck.", f_name + mimic_f_ptr->name);
 #endif
 
                                        obvious = TRUE;
@@ -859,15 +871,13 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                {
                        if (have_flag(f_ptr->flags, FF_HURT_ROCK))
                        {
-                               cptr name = f_name + f_ptr->name;
-
                                /* Message */
                                if (known && (c_ptr->info & (CAVE_MARK)))
                                {
 #ifdef JP
-                                       msg_format("%s¤¬ÍϤ±¤ÆÅ¥¤Ë¤Ê¤Ã¤¿¡ª", name);
+                                       msg_format("%s¤¬ÍϤ±¤ÆÅ¥¤Ë¤Ê¤Ã¤¿¡ª", f_name + f_info[get_feat_mimic(c_ptr)].name);
 #else
-                                       msg_format("The %s turns into mud!", name);
+                                       msg_format("The %s turns into mud!", f_name + f_info[get_feat_mimic(c_ptr)].name);
 #endif
 
                                        obvious = TRUE;
@@ -907,10 +917,6 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                /* Make traps */
                case GF_MAKE_TRAP:
                {
-                       /* Require a "naked" floor grid */
-                       if (!have_flag(f_ptr->flags, FF_FLOOR) || is_mirror_grid(c_ptr))
-                               break;
-
                        /* Place a trap */
                        place_trap(y, x);
 
@@ -979,8 +985,11 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        /* Shallow Lava */
                        if (dam == 1)
                        {
-                               /* Require a "naked" floor grid */
-                               if (!cave_naked_bold(y, x)) break;
+                               /* Ignore permanent grid */
+                               if (cave_perma_bold(y, x)) break;
+
+                               /* Ignore grid without enough space */
+                               if (!have_flag(f_flags_bold(y, x), FF_FLOOR)) break;
 
                                /* Place a shallow lava */
                                cave_set_feat(y, x, FEAT_SHAL_LAVA);
@@ -988,7 +997,7 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        /* Deep Lava */
                        else if (dam)
                        {
-                               /* Require a "naked" floor grid */
+                               /* Ignore permanent grid */
                                if (cave_perma_bold(y, x)) break;
 
                                /* Place a deep lava */
@@ -1002,8 +1011,11 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        /* Shallow Water */
                        if (dam == 1)
                        {
-                               /* Require a "naked" floor grid */
-                               if (!cave_naked_bold(y, x)) break;
+                               /* Ignore permanent grid */
+                               if (cave_perma_bold(y, x)) break;
+
+                               /* Ignore grid without enough space */
+                               if (!have_flag(f_flags_bold(y, x), FF_FLOOR)) break;
 
                                /* Place a shallow lava */
                                cave_set_feat(y, x, FEAT_SHAL_WATER);
@@ -1011,7 +1023,7 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        /* Deep Water */
                        else if (dam)
                        {
-                               /* Require a "naked" floor grid */
+                               /* Ignore permanent grid */
                                if (cave_perma_bold(y, x)) break;
 
                                /* Place a deep lava */
@@ -1025,20 +1037,25 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                case GF_LITE:
                {
                        /* Turn on the light */
-                       if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) c_ptr->info |= (CAVE_GLOW);
+                       if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS))
+                       {
+                               c_ptr->info |= (CAVE_GLOW);
 
-                       /* Notice */
-                       note_spot(y, x);
+                               /* Notice */
+                               note_spot(y, x);
 
-                       /* Redraw */
-                       lite_spot(y, x);
+                               /* Redraw */
+                               lite_spot(y, x);
 
-                       /* Observe */
-                       if (player_can_see_bold(y, x)) obvious = TRUE;
+                               update_local_illumination(y, x);
 
-                       /* Mega-Hack -- Update the monster in the affected grid */
-                       /* This allows "spear of light" (etc) to work "correctly" */
-                       if (c_ptr->m_idx) update_mon(c_ptr->m_idx, FALSE);
+                               /* Observe */
+                               if (player_can_see_bold(y, x)) obvious = TRUE;
+
+                               /* Mega-Hack -- Update the monster in the affected grid */
+                               /* This allows "spear of light" (etc) to work "correctly" */
+                               if (c_ptr->m_idx) update_mon(c_ptr->m_idx, FALSE);
+                       }
 
                        break;
                }
@@ -1049,9 +1066,6 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                {
                        if (!p_ptr->inside_battle)
                        {
-                               /* Notice */
-                               if (player_can_see_bold(y, x)) obvious = TRUE;
-
                                /* Turn off the light. */
                                if (!is_mirror_grid(c_ptr))
                                {
@@ -1066,14 +1080,19 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                                                /* Notice */
                                                note_spot(y, x);
                                        }
-                               }
 
-                               /* Redraw */
-                               lite_spot(y, x);
+                                       /* Redraw */
+                                       lite_spot(y, x);
 
-                               /* Mega-Hack -- Update the monster in the affected grid */
-                               /* This allows "spear of light" (etc) to work "correctly" */
-                               if (c_ptr->m_idx) update_mon(c_ptr->m_idx, FALSE);
+                                       update_local_illumination(y, x);
+
+                                       /* Notice */
+                                       if (player_can_see_bold(y, x)) obvious = TRUE;
+
+                                       /* Mega-Hack -- Update the monster in the affected grid */
+                                       /* This allows "spear of light" (etc) to work "correctly" */
+                                       if (c_ptr->m_idx) update_mon(c_ptr->m_idx, FALSE);
+                               }
                        }
 
                        /* All done */
@@ -1108,6 +1127,23 @@ static bool project_f(int who, int r, int y, int x, int dam, int typ)
                        }
                        break;
                }
+
+               case GF_DISINTEGRATE:
+               {
+                       /* Destroy mirror */
+                       if (is_mirror_grid(c_ptr)) remove_mirror(y, x);
+
+                       /* Permanent features don't get effect */
+                       /* But not protect monsters and other objects */
+                       if (have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT))
+                       {
+                               cave_alter_feat(y, x, FF_HURT_DISI);
+
+                               /* Update some things -- similar to GF_KILL_WALL */
+                               p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS | PU_MON_LITE);
+                       }
+                       break;
+               }
        }
 
        lite_spot(y, x);
@@ -6418,8 +6454,7 @@ static bool project_p(int who, cptr who_name, int r, int y, int x, int dam, int
                        t_x = m_list[who].fx - 1 + randint1(3);
                        max_attempts--;
                }
-               while (max_attempts && in_bounds2u(t_y, t_x) &&
-                    !(player_has_los_bold(t_y, t_x)));
+               while (max_attempts && in_bounds2u(t_y, t_x) && !projectable(py, px, t_y, t_x));
 
                if (max_attempts < 1)
                {
@@ -7157,7 +7192,7 @@ msg_print("
                        msg_print("Gravity warps around you.");
 #endif
 
-                       teleport_player(5);
+                       teleport_player(5, TRUE);
                        if (!p_ptr->ffall)
                                (void)set_slow(p_ptr->slow + randint0(4) + 4, FALSE);
                        if (!(p_ptr->resist_sound || p_ptr->ffall))
@@ -7959,41 +7994,9 @@ bool in_disintegration_range(int y1, int x1, int y2, int x2)
 
 
 /*
- *  Do disintegration effect on the terrain
- *  before we decide the region of the effect.
- */
-static bool do_disintegration(int by, int bx, int y, int x)
-{
-       feature_type *f_ptr;
-
-       /* Disintegration balls explosions are stopped by perma-walls */
-       if (!in_disintegration_range(by, bx, y, x)) return FALSE;
-
-       /* Permanent walls and artifacts don't get effect */
-       /* But not protect monsters and other objects */
-       if (!cave_valid_bold(y, x)) return TRUE;
-
-       /* Destroy mirror/glyph */
-       remove_mirror(y, x);
-
-       f_ptr = &f_info[cave[y][x].feat];
-
-       if (have_flag(f_ptr->flags, FF_HURT_DISI))
-       {
-               cave_alter_feat(y, x, FF_HURT_DISI);
-
-               /* Update some things -- similar to GF_KILL_WALL */
-               p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS | PU_MON_LITE);
-       }
-
-       return TRUE;
-}
-
-
-/*
  * breath shape
  */
-void breath_shape(u16b *path_g, int dist, int *pgrids, byte *gx, byte *gy, byte *gm, int *pgm_rad, int rad, int y1, int x1, int y2, int x2, bool disint_ball, bool real_breath)
+void breath_shape(u16b *path_g, int dist, int *pgrids, byte *gx, byte *gy, byte *gm, int *pgm_rad, int rad, int y1, int x1, int y2, int x2, int typ)
 {
        int by = y1;
        int bx = x1;
@@ -8002,8 +8005,7 @@ void breath_shape(u16b *path_g, int dist, int *pgrids, byte *gx, byte *gy, byte
        int bdis = 0;
        int cdis;
        int path_n = 0;
-       int tdis = distance(y1, x1, y2, x2);
-       int mdis = tdis + rad;
+       int mdis = distance(y1, x1, y2, x2) + rad;
 
        while (bdis <= mdis)
        {
@@ -8041,25 +8043,21 @@ void breath_shape(u16b *path_g, int dist, int *pgrids, byte *gx, byte *gy, byte
                                        /* Enforce an arc */
                                        if (distance(by, bx, y, x) != cdis) continue;
 
-
-                                       if (disint_ball)
+                                       switch (typ)
                                        {
-                                               /* Disintegration are stopped only by perma-walls */
-                                               if (real_breath)
-                                               {
-                                                       /* Destroy terrains */
-                                                       if (!do_disintegration(by, bx, y, x)) continue;
-                                               }
-                                               else
-                                               {
-                                                       /* No actual disintegration */
-                                                       if (!in_disintegration_range(by, bx, y, x)) continue;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               /* The blast is stopped by walls */
+                                       case GF_LITE:
+                                       case GF_LITE_WEAK:
+                                               /* Lights are stopped by opaque terrains */
                                                if (!los(by, bx, y, x)) continue;
+                                               break;
+                                       case GF_DISINTEGRATE:
+                                               /* Disintegration are stopped only by perma-walls */
+                                               if (!in_disintegration_range(by, bx, y, x)) continue;
+                                               break;
+                                       default:
+                                               /* Ball explosions are stopped by walls */
+                                               if (!projectable(by, bx, y, x)) continue;
+                                               break;
                                        }
 
                                        /* Save this grid */
@@ -8369,9 +8367,16 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                grids++;
        }
 
-       if (breath && typ == GF_DISINTEGRATE)
+       switch (typ)
        {
-               flg |= (PROJECT_DISI);
+       case GF_LITE:
+       case GF_LITE_WEAK:
+               if (breath || (flg & PROJECT_BEAM)) flg |= (PROJECT_LOS);
+               break;
+       case GF_DISINTEGRATE:
+               flg |= (PROJECT_GRID);
+               if (breath || (flg & PROJECT_BEAM)) flg |= (PROJECT_DISI);
+               break;
        }
 
        /* Calculate the projection path */
@@ -8659,6 +8664,11 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                        /* Hack -- Balls explode before reaching walls */
                        if (cave_stop_disintegration(ny, nx) && (rad > 0)) break;
                }
+               else if (flg & PROJECT_LOS)
+               {
+                       /* Hack -- Balls explode before reaching walls */
+                       if (!cave_los_bold(ny, nx) && (rad > 0)) break;
+               }
                else
                {
                        /* Hack -- Balls explode before reaching walls */
@@ -8730,14 +8740,16 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                }
        }
 
+       path_n = i;
+
        /* Save the "blast epicenter" */
        by = y;
        bx = x;
 
-       if (breath && (y1 == by) && (x1 == bx))
+       if (breath && !path_n)
        {
                breath = FALSE;
-               gm_rad = 1;
+               gm_rad = rad;
                if (!old_hide)
                {
                        flg &= ~(PROJECT_HIDE);
@@ -8775,7 +8787,7 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                {
                        flg &= ~(PROJECT_HIDE);
 
-                       breath_shape(path_g, dist, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, by, bx, (bool)(typ == GF_DISINTEGRATE), TRUE);
+                       breath_shape(path_g, dist, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, by, bx, typ);
                }
                else
                {
@@ -8793,15 +8805,21 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                                                /* Enforce a "circular" explosion */
                                                if (distance(by, bx, y, x) != dist) continue;
 
-                                               if (typ == GF_DISINTEGRATE)
+                                               switch (typ)
                                                {
+                                               case GF_LITE:
+                                               case GF_LITE_WEAK:
+                                                       /* Lights are stopped by opaque terrains */
+                                                       if (!los(by, bx, y, x)) continue;
+                                                       break;
+                                               case GF_DISINTEGRATE:
                                                        /* Disintegration are stopped only by perma-walls */
-                                                       if (!do_disintegration(by, bx, y, x)) continue;
-                                               }
-                                               else
-                                               {
+                                                       if (!in_disintegration_range(by, bx, y, x)) continue;
+                                                       break;
+                                               default:
                                                        /* Ball explosions are stopped by walls */
-                                                       if (!los(by, bx, y, x)) continue;
+                                                       if (!projectable(by, bx, y, x)) continue;
+                                                       break;
                                                }
 
                                                /* Save this grid */
@@ -8931,6 +8949,8 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                }
        }
 
+       /* Update stuff if needed */
+       if (p_ptr->update) update_stuff();
 
        /* Check objects */
        if (flg & (PROJECT_ITEM))
@@ -9006,8 +9026,7 @@ bool project(int who, int rad, int y, int x, int dam, int typ, int flg, int mons
                                                t_x = x_saver - 1 + randint1(3);
                                                max_attempts--;
                                        }
-                                       while (max_attempts && in_bounds2u(t_y, t_x) &&
-                                           !(los(y, x, t_y, t_x)));
+                                       while (max_attempts && in_bounds2u(t_y, t_x) && !projectable(y, x, t_y, t_x));
 
                                        if (max_attempts < 1)
                                        {
@@ -9285,7 +9304,8 @@ bool binding_field( int dam )
                        if( is_mirror_grid(&cave[y][x]) &&
                            distance(py,px,y,x) <= MAX_RANGE &&
                            distance(py,px,y,x) != 0 &&
-                           player_has_los_bold(y,x)
+                           player_has_los_bold(y,x) &&
+                           projectable(py, px, y, x)
                            ){
                                mirror_y[mirror_num]=y;
                                mirror_x[mirror_num]=x;
@@ -9335,7 +9355,7 @@ bool binding_field( int dam )
                            centersign*( (point_x[2]-x)*(point_y[0]-y)
                                         -(point_y[2]-y)*(point_x[0]-x)) >=0 )
                        {
-                               if( player_has_los_bold(y,x)){
+                               if (player_has_los_bold(y, x) && projectable(py, px, y, x)) {
                                        /* Visual effects */
                                        if(!(p_ptr->blind)
                                           && panel_contains(y,x)){
@@ -9358,7 +9378,7 @@ bool binding_field( int dam )
                            centersign*( (point_x[2]-x)*(point_y[0]-y)
                                         -(point_y[2]-y)*(point_x[0]-x)) >=0 )
                        {
-                               if( player_has_los_bold(y,x)){
+                               if (player_has_los_bold(y, x) && projectable(py, px, y, x)) {
                                        (void)project_f(0,0,y,x,dam,GF_MANA); 
                                }
                        }
@@ -9373,7 +9393,7 @@ bool binding_field( int dam )
                            centersign*( (point_x[2]-x)*(point_y[0]-y)
                                         -(point_y[2]-y)*(point_x[0]-x)) >=0 )
                        {
-                               if( player_has_los_bold(y,x)){
+                               if (player_has_los_bold(y, x) && projectable(py, px, y, x)) {
                                        (void)project_o(0,0,y,x,dam,GF_MANA); 
                                }
                        }
@@ -9388,7 +9408,7 @@ bool binding_field( int dam )
                            centersign*( (point_x[2]-x)*(point_y[0]-y)
                                         -(point_y[2]-y)*(point_x[0]-x)) >=0 )
                        {
-                               if( player_has_los_bold(y,x) ){
+                               if (player_has_los_bold(y, x) && projectable(py, px, y, x)) {
                                        (void)project_m(0,0,y,x,dam,GF_MANA,
                                          (PROJECT_GRID|PROJECT_ITEM|PROJECT_KILL|PROJECT_JUMP));
                                }