]> granicus.if.org Git - nethack/commitdiff
Fix #H4411: Targeting detected monster through wall with fireball
authorPasi Kallinen <paxed@alt.org>
Mon, 20 Jun 2016 06:11:52 +0000 (09:11 +0300)
committerPasi Kallinen <paxed@alt.org>
Mon, 20 Jun 2016 06:11:56 +0000 (09:11 +0300)
Fireball and cone of cold could target detected monsters
through a wall when cast at skilled or higher.  This allowed
eg. targeting the Wiz from outside his tower.

Use walk_path to determine the actual location where the
spell will hit, so trying to cast through a wall will
make the explosion happen at the nearest empty space.

src/spell.c

index 0dd84ddf05b863caa23c14a9c72550a50bf4283b..40969a62ed364076c1dc6829b94894b0f50f7d9e 100644 (file)
@@ -43,6 +43,7 @@ STATIC_DCL int NDECL(throwspell);
 STATIC_DCL void NDECL(cast_protection);
 STATIC_DCL void FDECL(spell_backfire, (int));
 STATIC_DCL const char *FDECL(spelltypemnemonic, (int));
+STATIC_DCL boolean FDECL(spell_hurtle_step, (genericptr_t, int, int));
 
 /* The roles[] table lists the role-specific values for tuning
  * percent_success().
@@ -1180,11 +1181,23 @@ boolean atme;
     return 1;
 }
 
+STATIC_OVL boolean
+spell_hurtle_step(arg, x, y)
+genericptr_t arg;
+int x, y;
+{
+    if (!isok(x,y)) return FALSE;
+    if (!ZAP_POS(levl[x][y].typ)
+        && !(IS_DOOR(levl[x][y].typ) && (levl[x][y].doormask & D_ISOPEN)))
+        return FALSE;
+    return TRUE;
+}
+
 /* Choose location where spell takes effect. */
 STATIC_OVL int
 throwspell()
 {
-    coord cc;
+    coord cc, uc;
     struct monst *mtmp;
 
     if (u.uinwater) {
@@ -1217,6 +1230,11 @@ throwspell()
         return 0;
     }
 
+    uc.x = u.ux;
+    uc.y = u.uy;
+
+    walk_path(&uc, &cc, spell_hurtle_step, NULL);
+
     u.dx = cc.x;
     u.dy = cc.y;
     return 1;