summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-09 00:28:37 +0000
committerdolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-09 00:28:37 +0000
commitd5950593f2e966032a81d4f150b24834c18a521b (patch)
tree8eb0aed3e97b4dd1b34a81487250c42cf96bb08b /crawl-ref
parent297297da01e51a1ba70d3fde8c994ab9bb4f890c (diff)
downloadcrawl-ref-d5950593f2e966032a81d4f150b24834c18a521b.tar.gz
crawl-ref-d5950593f2e966032a81d4f150b24834c18a521b.zip
Clean up the routines to animate the dead.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5621 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/abl-show.cc12
-rw-r--r--crawl-ref/source/it_use3.cc3
-rw-r--r--crawl-ref/source/monstuff.cc6
-rw-r--r--crawl-ref/source/mstuff2.cc8
-rw-r--r--crawl-ref/source/spells2.cc345
-rw-r--r--crawl-ref/source/spells2.h16
-rw-r--r--crawl-ref/source/spells3.cc337
-rw-r--r--crawl-ref/source/spells3.h21
-rw-r--r--crawl-ref/source/spl-cast.cc6
9 files changed, 374 insertions, 380 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 0591520d59..299c4e7698 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -1463,10 +1463,8 @@ static bool _do_ability(const ability_def& abil)
case ABIL_YRED_ANIMATE_CORPSE:
mpr("You call on the dead to walk for you...");
-
- animate_a_corpse( you.x_pos, you.y_pos, BEH_FRIENDLY,
- you.pet_target, CORPSE_BODY );
-
+ animate_a_corpse(you.x_pos, you.y_pos, CORPSE_BODY, BEH_FRIENDLY,
+ you.pet_target, true);
exercise(SK_INVOCATIONS, 2 + random2(4));
break;
@@ -1477,10 +1475,8 @@ static bool _do_ability(const ability_def& abil)
case ABIL_YRED_ANIMATE_DEAD:
mpr("You call on the dead to walk for you...");
-
- animate_dead( &you, 1 + you.skills[SK_INVOCATIONS], BEH_FRIENDLY,
- you.pet_target, 1 );
-
+ animate_dead(&you, 1 + you.skills[SK_INVOCATIONS], BEH_FRIENDLY,
+ you.pet_target, true);
exercise(SK_INVOCATIONS, 2 + random2(4));
break;
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index 05c8c8ce55..4b813afd81 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -47,6 +47,7 @@
#include "skills2.h"
#include "spells1.h"
#include "spells2.h"
+#include "spells3.h"
#include "spl-book.h"
#include "spl-cast.h"
#include "spl-util.h"
@@ -199,7 +200,7 @@ void special_wielded()
case SPWLD_ZONGULDROK:
if (one_chance_in(5))
{
- animate_dead( &you, 1 + random2(3), BEH_HOSTILE, MHITYOU, 1 );
+ animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU);
did_god_conduct( DID_NECROMANCY, 1 );
}
break;
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index b698997be7..991e8d6e1d 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -62,7 +62,7 @@
#include "religion.h"
#include "spl-cast.h"
#include "spl-util.h"
-#include "spells2.h"
+#include "spells3.h"
#include "spells4.h"
#include "state.h"
#include "stuff.h"
@@ -4819,8 +4819,8 @@ static bool _handle_spell( monsters *monster, bolt & beem )
// Try to animate dead: if nothing rises, pretend we didn't cast it.
if (spell_cast == SPELL_ANIMATE_DEAD
- && !animate_dead( monster, 100, SAME_ATTITUDE(monster),
- monster->foe, 0 ))
+ && !animate_dead(monster, 100, SAME_ATTITUDE(monster),
+ monster->foe, false, false))
{
return (false);
}
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index ff8ce661f7..3a549ffc20 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -40,7 +40,7 @@
#include "mon-util.h"
#include "player.h"
#include "randart.h"
-#include "spells2.h"
+#include "spells3.h"
#include "spells4.h"
#include "spl-cast.h"
#include "spl-util.h"
@@ -634,9 +634,9 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast)
return;
case SPELL_ANIMATE_DEAD:
- // see special handling in monstuff::handle_spell {dlb}
- animate_dead( monster, 5 + random2(5), SAME_ATTITUDE(monster),
- monster->foe, 1 );
+ // see special handling in monstuff::handle_spell() {dlb}
+ animate_dead(monster, 5 + random2(5), SAME_ATTITUDE(monster),
+ monster->foe);
return;
case SPELL_CALL_IMP: // class 5 demons
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index 6e991ea386..0c238f3a6a 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -58,15 +58,6 @@
#include "view.h"
#include "xom.h"
-static int raise_corpse( int corps, int corx, int cory, beh_type corps_beh,
- int corps_hit, int actual );
-
-static bool is_animatable_corpse(const item_def& item)
-{
- return (item.base_type == OBJ_CORPSES &&
- mons_zombie_size(item.plus) != Z_NOZOMBIE);
-}
-
unsigned char detect_traps( int pow )
{
unsigned char traps_found = 0;
@@ -317,342 +308,6 @@ int corpse_rot(int power)
return 0;
} // end corpse_rot()
-int animate_dead( actor *caster, int power, beh_type corps_beh,
- int corps_hit, int actual )
-{
- UNUSED( power );
- static env_show_grid losgrid;
-
- const coord_def c(caster->pos());
- int minx = c.x - 6;
- int maxx = c.x + 7;
- int miny = c.y - 6;
- int maxy = c.y + 7;
- int xinc = 1;
- int yinc = 1;
-
- int number_raised = 0;
- int number_seen = 0;
-
- if (coinflip())
- {
- minx = c.x + 6;
- maxx = c.x - 7;
- xinc = -1;
- }
-
- if (coinflip())
- {
- miny = c.y + 6;
- maxy = c.y - 7;
- yinc = -1;
- }
-
- if (caster != &you)
- losight(losgrid, grd, c.x, c.y, true);
-
- env_show_grid &los(caster == &you? env.no_trans_show : losgrid);
-
- coord_def a;
- bool was_butchered = false;
- for (a.x = minx; a.x != maxx; a.x += xinc)
- for (a.y = miny; a.y != maxy; a.y += yinc)
- {
- if (!in_bounds(a) || !see_grid(los, c, a))
- continue;
-
- if (igrd(a) != NON_ITEM)
- {
- int objl = igrd(a);
- int hrg = 0;
-
- // This searches all the items on the ground for a corpse.
- // Only one of a stack will be raised.
- while (objl != NON_ITEM)
- {
- if (is_animatable_corpse(mitm[objl])
- && !is_being_butchered(mitm[objl]))
- {
- if (is_being_butchered(mitm[objl], false))
- was_butchered = true;
-
- int num = raise_corpse(objl, a.x, a.y, corps_beh,
- corps_hit, actual);
-
- number_raised += num;
- if (see_grid(env.show, you.pos(), a))
- number_seen += num;
- break;
- }
-
- hrg = mitm[objl].link;
- objl = hrg;
- }
-
- objl = 1;
- }
- }
-
- if (actual == 0)
- return (number_raised);
-
- if (was_butchered)
- mpr("The corpse you are butchering rises to attack!");
-
- if (number_seen > 0)
- mpr("The dead are walking!");
-
- return (number_raised);
-}
-
-int animate_a_corpse( int axps, int ayps, beh_type corps_beh, int corps_hit,
- int class_allowed )
-{
- int rc = 0;
- int objl = igrd[axps][ayps];
- // This searches all the items on the ground for a corpse
- while (objl != NON_ITEM)
- {
- const item_def& item = mitm[objl];
- if (is_animatable_corpse(item)
- && (class_allowed == CORPSE_BODY
- || item.sub_type == CORPSE_SKELETON))
- {
- bool was_butchering = is_being_butchered(item);
-
- rc = raise_corpse(objl, axps, ayps, corps_beh, corps_hit, 1);
- if (rc)
- {
- if (was_butchering)
- mpr("The corpse you are butchering rises to attack!");
-
- if (is_terrain_seen(axps, ayps))
- mpr("The dead are walking!");
-
- if (was_butchering)
- xom_is_stimulated(255);
- }
- break;
- }
- objl = item.link;
- }
-
- return rc;
-}
-
-// Try to equip the zombie/skeleton with the objects it died with.
-// This excludes items which were dropped by the player onto the corpse,
-// and corpses which were picked up and moved by the player, so the player
-// can't equip their undead slaves with items of their choice.
-//
-// The item selection logic has one problem: if a first monster without
-// any items dies and leaves a corpse, and then a second monster with
-// items dies on the same spot but doesn't leave a corpse, then the
-// undead can be equipped with the second monster's items if the second
-// monster is either of the same type as the first, or if the second
-// monster wasn't killed by the player or a player's pet.
-static void _equip_undead( int x, int y, int corps, int monster, int monnum)
-{
-// Delay this until after 0.4
-#if 0
- monsters* mon = &menv[monster];
-
- monster_type type = static_cast<monster_type>(monnum);
-
- if (mons_itemuse(monnum) < MONUSE_STARTING_EQUIPMENT)
- return;
-
- // If the player picked up and dropped the corpse then all its
- // original equipment fell off.
- if (mitm[corps].flags & ISFLAG_DROPPED)
- return;
-
- // A monster's corpse is last in the linked list after its items,
- // so (for example) the first item after the second-to-last corpse
- // is the first item belonging to the last corpse.
- int objl = igrd[x][y];
- int first_obj = NON_ITEM;
-
- while (objl != NON_ITEM && objl != corps)
- {
- item_def item(mitm[objl]);
-
- if (item.base_type == OBJ_CORPSES)
- {
- first_obj = NON_ITEM;
- continue;
- }
-
- if (first_obj == NON_ITEM)
- first_obj = objl;
-
- objl = item.link;
- }
-
- ASSERT(objl == corps);
-
- if (first_obj == NON_ITEM)
- return;
-
- // Iterate backwards over the list, since the items earlier in the
- // linked list were dropped most recently and hence more likely to
- // be items the monster didn't die with.
- std::vector<int> item_list;
- objl = first_obj;
- while (objl != NON_ITEM && objl != corps)
- {
- item_list.push_back(objl);
- objl = mitm[objl].link;
- }
-
- for (int i = item_list.size() - 1; i >= 0; i--)
- {
- objl = item_list[i];
- item_def &item(mitm[objl]);
-
- // Stop equipping monster if the item probably didn't originally
- // belong to the monster.
- if ( (origin_known(item) && (item.orig_monnum - 1) != monnum)
- || (item.flags & (ISFLAG_DROPPED | ISFLAG_THROWN))
- || item.base_type == OBJ_CORPSES)
- {
- return;
- }
-
- mon_inv_type mslot;
-
- switch(item.base_type)
- {
- case OBJ_WEAPONS:
- if (mon->inv[MSLOT_WEAPON] != NON_ITEM)
- {
- if (mons_wields_two_weapons(type))
- mslot = MSLOT_ALT_WEAPON;
- else
- {
- if (is_range_weapon(mitm[mon->inv[MSLOT_WEAPON]])
- == is_range_weapon(item))
- {
- // Two different items going into the same
- // slot indicate that this and further items
- // weren't equipment the monster died with.
- return;
- }
- else
- // The undead are too stupid to switch between weapons.
- continue;
- }
- }
- else
- mslot = MSLOT_WEAPON;
- break;
- case OBJ_ARMOUR:
- mslot = equip_slot_to_mslot(get_armour_slot(item));
-
- // A piece of armour which can't be worn indicates that this
- // and further items weren't the equipment the monster died
- // with.
- if (mslot == NUM_MONSTER_SLOTS)
- return;
- break;
-
- case OBJ_MISSILES:
- mslot = MSLOT_MISSILE;
- break;
-
- case OBJ_GOLD:
- mslot = MSLOT_GOLD;
- break;
-
- // The undead are too stupid to use these.
- case OBJ_WANDS:
- case OBJ_SCROLLS:
- case OBJ_POTIONS:
- case OBJ_MISCELLANY:
- continue;
-
- default:
- continue;
- } // switch
-
- // Two different items going into the same slot indicate that
- // this and further items weren't equipment the monster died
- // with.
- if (mon->inv[mslot] != NON_ITEM)
- return;
-
- unlink_item(objl);
- mon->inv[mslot] = objl;
-
- if (mslot != MSLOT_ALT_WEAPON || mons_wields_two_weapons(mon))
- mon->equip(item, mslot, 0);
- } // while
-#endif
-}
-
-static int raise_corpse( int corps, int corx, int cory,
- beh_type corps_beh, int corps_hit, int actual )
-{
- int returnVal = 1;
-
- if (!mons_zombie_size(mitm[corps].plus))
- returnVal = 0;
- else if (actual != 0)
- {
- monster_type type = MONS_PROGRAM_BUG;
- if (mitm[corps].sub_type == CORPSE_BODY)
- {
- if (mons_zombie_size(mitm[corps].plus) == Z_SMALL)
- type = MONS_ZOMBIE_SMALL;
- else
- type = MONS_ZOMBIE_LARGE;
- }
- else
- {
- if (mons_zombie_size(mitm[corps].plus) == Z_SMALL)
- type = MONS_SKELETON_SMALL;
- else
- type = MONS_SKELETON_LARGE;
- }
-
- const int number =
- mitm[corps].props.exists(MONSTER_NUMBER)
- ? mitm[corps].props[MONSTER_NUMBER].get_short()
- : 0;
-
- const monster_type zombie_type =
- static_cast<monster_type>(mitm[corps].plus);
-
- // Headless hydras cannot be raised, sorry.
- if (!number && zombie_type == MONS_HYDRA)
- return (0);
-
- int monster = create_monster(
- mgen_data(
- type, corps_beh, 0,
- coord_def(corx, cory), corps_hit,
- 0, zombie_type, number));
-
- if (monster != -1)
- {
- const int monnum = mitm[corps].orig_monnum - 1;
- if (mons_is_unique(monnum))
- {
- menv[monster].mname = origin_monster_name(mitm[corps]);
- // Special case for Blork the orc: shorten his name to "Blork"
- // to avoid mentions of "Blork the orc the orc skeleton".
- if (monnum == MONS_BLORK_THE_ORC)
- menv[monster].mname = "Blork";
- }
- _equip_undead(corx, cory, corps, monster, monnum);
- }
-
- destroy_item(corps);
- }
-
- return returnVal;
-} // end raise_corpse()
-
bool brand_weapon(brand_type which_brand, int power)
{
int temp_rand; // probability determination {dlb}
diff --git a/crawl-ref/source/spells2.h b/crawl-ref/source/spells2.h
index 6a6d1bb0d0..d1abd1a22f 100644
--- a/crawl-ref/source/spells2.h
+++ b/crawl-ref/source/spells2.h
@@ -27,22 +27,6 @@ bool brand_weapon(brand_type which_brand, int power);
// last updated 24may2000 {dlb}
/* ***********************************************************************
- * called from: ability - spell
- * *********************************************************************** */
-int animate_a_corpse(int axps, int ayps, beh_type corps_beh,
- int corps_hit, int class_allowed);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
- * called from: ability - it_use3 - monstuff - mstuff2 - spell
- * *********************************************************************** */
-int animate_dead(actor *caster, int power, beh_type corps_beh,
- int corps_hit, int actual);
-
-
-// last updated 24may2000 {dlb}
-/* ***********************************************************************
* called from: spell
* *********************************************************************** */
char burn_freeze(int pow, beam_type b_f);
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 07250c2722..72d7fdf03e 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -643,6 +643,343 @@ bool cast_summon_horrible_things(int pow, bool god_gift)
return (false);
}
+static bool _is_animatable_corpse(const item_def& item)
+{
+ return (item.base_type == OBJ_CORPSES
+ && mons_zombie_size(item.plus) != Z_NOZOMBIE);
+}
+
+// Try to equip the zombie/skeleton with the objects it died with.
+// This excludes items which were dropped by the player onto the corpse,
+// and corpses which were picked up and moved by the player, so the player
+// can't equip their undead slaves with items of their choice.
+//
+// The item selection logic has one problem: if a first monster without
+// any items dies and leaves a corpse, and then a second monster with
+// items dies on the same spot but doesn't leave a corpse, then the
+// undead can be equipped with the second monster's items if the second
+// monster is either of the same type as the first, or if the second
+// monster wasn't killed by the player or a player's pet.
+static void _equip_undead(int x, int y, int corps, int monster, int monnum)
+{
+// Delay this until after 0.4
+#if 0
+ monsters* mon = &menv[monster];
+
+ monster_type type = static_cast<monster_type>(monnum);
+
+ if (mons_itemuse(monnum) < MONUSE_STARTING_EQUIPMENT)
+ return;
+
+ // If the player picked up and dropped the corpse then all its
+ // original equipment fell off.
+ if (mitm[corps].flags & ISFLAG_DROPPED)
+ return;
+
+ // A monster's corpse is last in the linked list after its items,
+ // so (for example) the first item after the second-to-last corpse
+ // is the first item belonging to the last corpse.
+ int objl = igrd[x][y];
+ int first_obj = NON_ITEM;
+
+ while (objl != NON_ITEM && objl != corps)
+ {
+ item_def item(mitm[objl]);
+
+ if (item.base_type == OBJ_CORPSES)
+ {
+ first_obj = NON_ITEM;
+ continue;
+ }
+
+ if (first_obj == NON_ITEM)
+ first_obj = objl;
+
+ objl = item.link;
+ }
+
+ ASSERT(objl == corps);
+
+ if (first_obj == NON_ITEM)
+ return;
+
+ // Iterate backwards over the list, since the items earlier in the
+ // linked list were dropped most recently and hence more likely to
+ // be items the monster didn't die with.
+ std::vector<int> item_list;
+ objl = first_obj;
+ while (objl != NON_ITEM && objl != corps)
+ {
+ item_list.push_back(objl);
+ objl = mitm[objl].link;
+ }
+
+ for (int i = item_list.size() - 1; i >= 0; i--)
+ {
+ objl = item_list[i];
+ item_def &item(mitm[objl]);
+
+ // Stop equipping monster if the item probably didn't originally
+ // belong to the monster.
+ if ( (origin_known(item) && (item.orig_monnum - 1) != monnum)
+ || (item.flags & (ISFLAG_DROPPED | ISFLAG_THROWN))
+ || item.base_type == OBJ_CORPSES)
+ {
+ return;
+ }
+
+ mon_inv_type mslot;
+
+ switch(item.base_type)
+ {
+ case OBJ_WEAPONS:
+ if (mon->inv[MSLOT_WEAPON] != NON_ITEM)
+ {
+ if (mons_wields_two_weapons(type))
+ mslot = MSLOT_ALT_WEAPON;
+ else
+ {
+ if (is_range_weapon(mitm[mon->inv[MSLOT_WEAPON]])
+ == is_range_weapon(item))
+ {
+ // Two different items going into the same
+ // slot indicate that this and further items
+ // weren't equipment the monster died with.
+ return;
+ }
+ else
+ // The undead are too stupid to switch between weapons.
+ continue;
+ }
+ }
+ else
+ mslot = MSLOT_WEAPON;
+ break;
+ case OBJ_ARMOUR:
+ mslot = equip_slot_to_mslot(get_armour_slot(item));
+
+ // A piece of armour which can't be worn indicates that this
+ // and further items weren't the equipment the monster died
+ // with.
+ if (mslot == NUM_MONSTER_SLOTS)
+ return;
+ break;
+
+ case OBJ_MISSILES:
+ mslot = MSLOT_MISSILE;
+ break;
+
+ case OBJ_GOLD:
+ mslot = MSLOT_GOLD;
+ break;
+
+ // The undead are too stupid to use these.
+ case OBJ_WANDS:
+ case OBJ_SCROLLS:
+ case OBJ_POTIONS:
+ case OBJ_MISCELLANY:
+ continue;
+
+ default:
+ continue;
+ } // switch
+
+ // Two different items going into the same slot indicate that
+ // this and further items weren't equipment the monster died
+ // with.
+ if (mon->inv[mslot] != NON_ITEM)
+ return;
+
+ unlink_item(objl);
+ mon->inv[mslot] = objl;
+
+ if (mslot != MSLOT_ALT_WEAPON || mons_wields_two_weapons(mon))
+ mon->equip(item, mslot, 0);
+ } // while
+#endif
+}
+
+static bool _raise_corpse(int x, int y, int corps, beh_type beha,
+ unsigned short hitting, bool god_gift, bool actual)
+{
+ const item_def& item = mitm[corps];
+
+ if (!_is_animatable_corpse(item))
+ return (false);
+
+ if (!actual)
+ return (true);
+
+ const monster_type zombie_type =
+ static_cast<monster_type>(item.plus);
+
+ const int number = (item.props.exists(MONSTER_NUMBER)) ?
+ item.props[MONSTER_NUMBER].get_short() : 0;
+
+ // Headless hydras cannot be raised, sorry.
+ if (zombie_type == MONS_HYDRA && number == 0)
+ return (false);
+
+ monster_type mon = MONS_PROGRAM_BUG;
+
+ if (item.sub_type == CORPSE_BODY)
+ {
+ mon = (mons_zombie_size(item.plus) == Z_SMALL) ?
+ MONS_ZOMBIE_SMALL : MONS_ZOMBIE_LARGE;
+ }
+ else
+ {
+ mon = (mons_zombie_size(item.plus) == Z_SMALL) ?
+ MONS_SKELETON_SMALL : MONS_SKELETON_LARGE;
+ }
+
+ int monster = create_monster(
+ mgen_data(mon, beha, 0,
+ coord_def(x, y), hitting,
+ god_gift ? MF_GOD_GIFT : 0,
+ zombie_type, number));
+
+ if (monster != -1)
+ {
+ const int monnum = item.orig_monnum - 1;
+
+ if (mons_is_unique(monnum))
+ {
+ menv[monster].mname = origin_monster_name(item);
+
+ // Special case for Blork the orc: shorten his name to "Blork"
+ // to avoid mentions of "Blork the orc the orc skeleton".
+ if (monnum == MONS_BLORK_THE_ORC)
+ menv[monster].mname = "Blork";
+ }
+
+ _equip_undead(x, y, corps, monster, monnum);
+ }
+
+ destroy_item(corps);
+
+ return (true);
+}
+
+bool animate_a_corpse(int x, int y, corpse_type class_allowed,
+ beh_type beha, unsigned short hitting,
+ bool god_gift, bool actual,
+ bool silent)
+{
+ bool success = false;
+
+ int corps = igrd[x][y];
+
+ // This searches all the items on the ground for a corpse.
+ while (corps != NON_ITEM)
+ {
+ const item_def& item = mitm[corps];
+
+ if (_is_animatable_corpse(item)
+ && (class_allowed == CORPSE_BODY
+ || item.sub_type == CORPSE_SKELETON))
+ {
+ bool was_butchering = is_being_butchered(item);
+
+ success = _raise_corpse(x, y, corps, beha, hitting, god_gift,
+ actual);
+
+ if (actual && success)
+ {
+ if (!silent)
+ {
+ if (was_butchering)
+ mpr("The corpse you are butchering rises to attack!");
+
+ if (is_terrain_seen(x, y))
+ mpr("The dead are walking!");
+ }
+
+ if (was_butchering)
+ xom_is_stimulated(255);
+ }
+ break;
+ }
+
+ corps = item.link;
+ }
+
+ return (success);
+}
+
+int animate_dead(actor *caster, int pow, beh_type beha, unsigned short hitting,
+ bool god_gift, bool actual)
+{
+ UNUSED(pow);
+
+ static env_show_grid losgrid;
+
+ const coord_def c(caster->pos());
+
+ int minx = c.x - 6;
+ int maxx = c.x + 7;
+ int miny = c.y - 6;
+ int maxy = c.y + 7;
+ int xinc = 1;
+ int yinc = 1;
+
+ int number_raised = 0;
+ int number_seen = 0;
+
+ if (coinflip())
+ {
+ minx = c.x + 6;
+ maxx = c.x - 7;
+ xinc = -1;
+ }
+
+ if (coinflip())
+ {
+ miny = c.y + 6;
+ maxy = c.y - 7;
+ yinc = -1;
+ }
+
+ if (caster != &you)
+ losight(losgrid, grd, c.x, c.y, true);
+
+ env_show_grid &los(caster == &you? env.no_trans_show : losgrid);
+
+ coord_def a;
+
+ for (a.x = minx; a.x != maxx; a.x += xinc)
+ {
+ for (a.y = miny; a.y != maxy; a.y += yinc)
+ {
+ if (!in_bounds(a) || !see_grid(los, c, a))
+ continue;
+
+ int corps = igrd(a);
+
+ if (corps != NON_ITEM)
+ {
+ // This searches all the items on the ground for a
+ // corpse. Only one of a stack will be raised.
+ while (corps != NON_ITEM)
+ {
+ if (animate_a_corpse(a.x, a.y, CORPSE_BODY, beha,
+ hitting, god_gift, actual, true))
+ {
+ number_raised++;
+ if (see_grid(env.show, you.pos(), a))
+ number_seen++;
+ break;
+ }
+
+ corps = mitm[corps].link;
+ }
+ }
+ }
+ }
+
+ return (number_raised);
+}
+
// Simulacrum
//
// This spell extends creating undead to Ice mages, as such it's high
diff --git a/crawl-ref/source/spells3.h b/crawl-ref/source/spells3.h
index 842f31512f..9988f54ee8 100644
--- a/crawl-ref/source/spells3.h
+++ b/crawl-ref/source/spells3.h
@@ -14,6 +14,7 @@
#ifndef SPELLS3_H
#define SPELLS3_H
+#include "itemprop.h" // from _raise_corpse()
struct dist;
struct bolt;
@@ -123,6 +124,26 @@ bool cast_summon_greater_demon(int pow, bool god_gift = false);
bool cast_shadow_creatures(bool god_gift = false);
bool cast_summon_horrible_things(int pow, bool god_gift = false);
+// last updated 24may2000 {dlb}
+/* ***********************************************************************
+ * called from: ability - spell
+ * *********************************************************************** */
+bool animate_a_corpse(int x, int y, corpse_type class_allowed,
+ beh_type beha, unsigned short hitting,
+ bool god_gift = false, bool actual = true,
+ bool silent = false);
+
+// last updated 24may2000 {dlb}
+/* ***********************************************************************
+ * called from: ability - it_use3 - monstuff - mstuff2 - spell
+ * *********************************************************************** */
+int animate_dead(actor *caster, int pow, beh_type beha, unsigned short hitting,
+ bool god_gift = false, bool actual = true);
+
+// updated 24may2000 {dlb}
+/* ***********************************************************************
+ * called from: spell
+ * *********************************************************************** */
bool cast_simulacrum(int pow, bool god_gift = false);
bool cast_twisted_resurrection(int pow, bool god_gift = false);
bool cast_summon_wraiths(int pow, bool god_gift = false);
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index cf7ed6063c..43547aafa0 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -1390,7 +1390,7 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
case SPELL_ANIMATE_DEAD:
mpr("You call on the dead to walk for you.");
- animate_dead(&you, powc + 1, BEH_FRIENDLY, you.pet_target, 1);
+ animate_dead(&you, powc + 1, BEH_FRIENDLY, you.pet_target);
break;
case SPELL_PAIN:
@@ -1409,8 +1409,8 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
case SPELL_ANIMATE_SKELETON:
mpr("You attempt to give life to the dead...");
- animate_a_corpse(you.x_pos, you.y_pos, BEH_FRIENDLY, you.pet_target,
- CORPSE_SKELETON);
+ animate_a_corpse(you.x_pos, you.y_pos, CORPSE_SKELETON, BEH_FRIENDLY,
+ you.pet_target);
break;
case SPELL_VAMPIRIC_DRAINING: