summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-15 10:57:23 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-15 10:57:23 +0000
commit79282d0e5bbed27cc5df50413bfd2d9db0874fd3 (patch)
tree89e21722bdc18717d02adcb409076ea6ddee7619 /crawl-ref
parent4140d2abd9dfcd9cdda476fc4722067beefe0426 (diff)
downloadcrawl-ref-79282d0e5bbed27cc5df50413bfd2d9db0874fd3.tar.gz
crawl-ref-79282d0e5bbed27cc5df50413bfd2d9db0874fd3.zip
FR #2424917: holy monsters should drop non-summoned items when they die rather
than taking their entire inventory with them. If a monster drops/fires/throws a summoned item the item will vanish (assuming it's not a fired/thrown item which returns to the monster). Don't generate summoned monsters with throwing nets since the net will disappear as soon as it hits the target. If a monster drops an item onto a item destroying grid the item will be destroyed, accompanied by the approriate sound. This should never happen, since monsters only drop items in order to pick up another one, and they can't pick up items off of item destroying grids since there won't be any items there, but maybe in the future confused monsters will spontaneously drop items or something. Don't let orcs use orc-slaying weapons or draconians use dragon-slaying weapons. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7836 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc16
-rw-r--r--crawl-ref/source/makeitem.cc13
-rw-r--r--crawl-ref/source/makeitem.h2
-rw-r--r--crawl-ref/source/mon-util.cc60
-rw-r--r--crawl-ref/source/monplace.cc13
-rw-r--r--crawl-ref/source/monstuff.cc51
-rw-r--r--crawl-ref/source/mstuff2.cc73
-rw-r--r--crawl-ref/source/mstuff2.h7
8 files changed, 171 insertions, 64 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 2bf23be891..da31322807 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -3003,6 +3003,22 @@ void beam_drop_object( bolt &beam, item_def *item, const coord_def& _p )
if (!in_bounds(p))
p = beam.pos;
+ if (item->flags & ISFLAG_SUMMONED)
+ {
+ if (see_grid(p))
+ {
+ mprf("%s %s!",
+ item->name(DESC_CAP_THE).c_str(),
+ summoned_poof_msg(beam.beam_source, *item).c_str());
+ }
+ item_was_destroyed(*item, beam.beam_source);
+
+ beam.dropped_item = true;
+ beam.item_pos = p;
+ beam.item_index = NON_ITEM;
+ return;
+ }
+
// Conditions: beam is missile and not tracer.
if (YOU_KILL(beam.thrower)
&& !thrown_object_destroyed(item, p, false)
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index ff1c2a7a7c..df03e7258d 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -3662,7 +3662,8 @@ static item_make_species_type _give_weapon(monsters *mon, int level,
// Hands out ammunition fitting the monster's launcher (if any), or else any
// throwable weapon depending on the monster type.
static void _give_ammo(monsters *mon, int level,
- item_make_species_type item_race)
+ item_make_species_type item_race,
+ bool mons_summoned)
{
// Note that item_race is not reset for this section.
if (const item_def *launcher = mon->launcher())
@@ -3763,7 +3764,7 @@ static void _give_ammo(monsters *mon, int level,
qty = 3 + random2(6);
}
}
- if (one_chance_in(6))
+ if (one_chance_in(6) && !mons_summoned)
{
weap_class = OBJ_MISSILES;
weap_type = MI_THROWING_NET;
@@ -3781,6 +3782,9 @@ static void _give_ammo(monsters *mon, int level,
// fall through
case MONS_HAROLD: // bounty hunters
case MONS_JOZEF: // up to 5 nets
+ if (mons_summoned)
+ break;
+
weap_class = OBJ_MISSILES;
weap_type = MI_THROWING_NET;
qty = 1;
@@ -4149,7 +4153,8 @@ void give_armour(monsters *mon, int level)
mitm[thing_created].colour = force_colour;
}
-void give_item(int mid, int level_number) //mv: cleanup+minor changes
+void give_item(int mid, int level_number,
+ bool mons_summoned) //mv: cleanup+minor changes
{
monsters *mons = &menv[mid];
@@ -4159,7 +4164,7 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
const item_make_species_type item_race = _give_weapon(mons, level_number);
- _give_ammo(mons, level_number, item_race);
+ _give_ammo(mons, level_number, item_race, mons_summoned);
give_armour(mons, 1 + level_number / 2);
give_shield(mons, 1 + level_number / 2);
}
diff --git a/crawl-ref/source/makeitem.h b/crawl-ref/source/makeitem.h
index 7335055592..08478e6258 100644
--- a/crawl-ref/source/makeitem.h
+++ b/crawl-ref/source/makeitem.h
@@ -27,7 +27,7 @@ int items( int allow_uniques, object_class_type force_class, int force_type,
void item_colour( item_def &item );
void init_rod_mp(item_def &item);
-void give_item(int mid, int level_number);
+void give_item(int mid, int level_number, bool mons_summoned);
jewellery_type get_random_ring_type();
jewellery_type get_random_amulet_type();
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index e95ef6729f..01197f79ea 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -3733,13 +3733,23 @@ bool monsters::could_wield(const item_def &item, bool ignore_brand,
if (!ignore_brand)
{
+ const int brand = get_weapon_brand(item);
+
+ // Draconians won't use dragon slaying weapons.
+ if (brand == SPWPN_DRAGON_SLAYING && is_dragonkind(this, this))
+ return (false);
+
+ // Orcs won't use orc slaying weapons.
+ if (brand == SPWPN_ORC_SLAYING && is_orckind(this, this))
+ return (false);
+
// Demonic/undead monsters won't use holy weapons.
if (mons_is_unholy(this) && is_holy_item(item))
return (false);
// Holy monsters won't use demonic or chaotic weapons.
- if (mons_holiness(this) == MH_HOLY
- && (is_evil_item(item) || get_weapon_brand(item) == SPWPN_CHAOS))
+ if ((mons_holiness(this) == MH_HOLY || is_good_god(god))
+ && (is_evil_item(item) || brand == SPWPN_CHAOS))
{
return (false);
}
@@ -4111,32 +4121,62 @@ bool monsters::drop_item(int eslot, int near)
if (item_index == NON_ITEM)
return (true);
+ item_def &item(mitm[item_index]);
+
// Unequip equipped items before dropping them; unequip() prevents
// cursed items from being removed.
bool was_unequipped = false;
if (eslot == MSLOT_WEAPON || eslot == MSLOT_ARMOUR
|| eslot == MSLOT_ALT_WEAPON && mons_wields_two_weapons(this))
{
- if (!unequip(mitm[item_index], eslot, near))
+ if (!unequip(item, eslot, near))
return (false);
was_unequipped = true;
}
- const std::string iname = mitm[item_index].name(DESC_NOCAP_A);
- if (!move_item_to_grid(&item_index, pos()))
+ bool on_floor = true;
+
+ if (item.flags & ISFLAG_SUMMONED)
+ {
+ on_floor = false;
+
+ if (need_message(near))
+ mprf("%s %s as %s drops %s!",
+ item.name(DESC_CAP_THE).c_str(),
+ summoned_poof_msg(this, item).c_str(),
+ name(DESC_NOCAP_THE).c_str(),
+ item.quantity > 1 ? "them" : "it");
+
+ item_was_destroyed(item, mindex());
+ }
+ else if (!move_item_to_grid(&item_index, pos()))
{
// Re-equip item if we somehow failed to drop it.
if (was_unequipped)
- equip(mitm[item_index], eslot, near);
+ equip(item, eslot, near);
return (false);
}
- if (mons_friendly(this))
- mitm[item_index].flags |= ISFLAG_DROPPED_BY_ALLY;
+ if (on_floor)
+ {
+ if (mons_friendly(this))
+ item.flags |= ISFLAG_DROPPED_BY_ALLY;
- if (need_message(near))
- mprf("%s drops %s.", name(DESC_CAP_THE).c_str(), iname.c_str());
+ if (need_message(near))
+ mprf("%s drops %s.", name(DESC_CAP_THE).c_str(),
+ item.name(DESC_NOCAP_A).c_str());
+
+ dungeon_feature_type feat = grd(pos());
+ if (grid_destroys_items(feat))
+ {
+ if ( player_can_hear(pos()) )
+ mprf(MSGCH_SOUND, grid_item_destruction_message(feat));
+
+ item_was_destroyed(item, mindex());
+ unlink_item(item_index);
+ }
+ }
inv[eslot] = NON_ITEM;
return (true);
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index a95a26a04f..5e21057810 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -990,19 +990,23 @@ static int _place_monster_aux( const mgen_data &mg,
menv[id].flags |= MF_JUST_SUMMONED;
+ // dur should always be 1-6 for monsters that can be abjured.
+ const bool summoned = mg.abjuration_duration >= 1
+ && mg.abjuration_duration <= 6;
+
if (mg.cls == MONS_DANCING_WEAPON && mg.number != 1) // ie not from spell
{
- give_item(id, mg.power);
+ give_item(id, mg.power, summoned);
if (menv[id].inv[MSLOT_WEAPON] != NON_ITEM)
menv[id].colour = mitm[menv[id].inv[MSLOT_WEAPON]].colour;
}
else if (mons_class_itemuse(mg.cls) >= MONUSE_STARTING_EQUIPMENT)
{
- give_item(id, mg.power);
+ give_item(id, mg.power, summoned);
// Give these monsters a second weapon -- bwr
if (mons_class_wields_two_weapons(mg.cls))
- give_item(id, mg.power);
+ give_item(id, mg.power, summoned);
unwind_var<int> save_speedinc(menv[id].speed_increment);
menv[id].wield_melee_weapon(false);
@@ -1038,8 +1042,7 @@ static int _place_monster_aux( const mgen_data &mg,
menv[id].behaviour = BEH_WANDER;
}
- // dur should always be 1-6 for monsters that can be abjured.
- if (mg.abjuration_duration >= 1 && mg.abjuration_duration <= 6)
+ if (summoned)
menv[id].mark_summoned( mg.abjuration_duration, true,
mg.summon_type );
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 9c349d3d3a..0753e6dac4 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -920,60 +920,29 @@ void _monster_die_cloud(const monsters* monster, bool corpse, bool silent,
if (!summoned)
return;
- std::string prefix;
- std::string msg = " disappears in a puff of smoke!";
- cloud_type cloud = random_smoke_type();
- int dur = 1 + random2(3);
-
+ std::string prefix = " ";
if (corpse)
{
if (mons_weight(mons_species(monster->type)) == 0)
return;
- prefix = "'s corpse";
+ prefix = "'s corpse ";
}
- switch(summon_type)
- {
- case SPELL_SHADOW_CREATURES:
- msg = " disolves into shadows!";
- cloud = CLOUD_NONE;
- break;
-
- case MON_SUMM_CHAOS:
- msg = " degenerates into a cloud of primal chaos!";
- cloud = CLOUD_CHAOS;
- break;
-
- case MON_SUMM_WRATH:
- case MON_SUMM_AID:
- if (is_good_god(monster->god))
- {
- msg = " disolves into sparkling lights!";
- cloud = CLOUD_NONE;
- }
- break;
- }
+ std::string msg = summoned_poof_msg(monster);
+ msg += "!";
- if (monster->god == GOD_XOM && one_chance_in(10)
- || cloud != CLOUD_NONE && monster->type == MONS_CHAOS_SPAWN)
- {
- msg = " degenerates into a cloud of primal chaos!";
+ cloud_type cloud = CLOUD_NONE;
+ if (msg.find("smoke") != std::string::npos)
+ cloud = random_smoke_type();
+ else if (msg.find("chaos") != std::string::npos)
cloud = CLOUD_CHAOS;
- }
-
- if (mons_is_holy(monster) && summon_type != SPELL_SHADOW_CREATURES
- && summon_type != MON_SUMM_CHAOS)
- {
- msg = " disolves into sparkling lights!";
- cloud = CLOUD_NONE;
- }
if (!silent)
simple_monster_message(monster, (prefix + msg).c_str());
if (cloud != CLOUD_NONE)
- place_cloud( cloud, monster->pos(), dur,
+ place_cloud( cloud, monster->pos(), 1 + random2(3),
monster->kill_alignment() );
}
@@ -1002,7 +971,7 @@ void monster_die(monsters *monster, killer_type killer,
const bool gives_xp = !summoned
&& !mons_enslaved_body_and_soul(monster);
- const bool drop_items = !hard_reset && !mons_is_holy(monster);
+ const bool drop_items = !hard_reset;
const bool mons_reset( killer == KILL_RESET || killer == KILL_DISMISSED );
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 5c9407f0fe..f10d9c9d7b 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -1372,7 +1372,8 @@ bool mons_thrown_object_destroyed( item_def *item, const coord_def& where,
if (returning && !destroyed)
hostile_grid = false;
- if (hostile_grid)
+ // Summoned items go poof if they're not returning.
+ if (hostile_grid || !returning && (item->flags & ISFLAG_SUMMONED))
{
// No destruction sound here. Too much message spam otherwise.
item_was_destroyed(*item, midx);
@@ -2538,3 +2539,73 @@ int clone_mons(const monsters* orig, bool quiet, bool* obvious,
return (midx);
}
+
+std::string summoned_poof_msg(const monsters* monster, bool plural)
+{
+ int summon_type = 0;
+ bool valid_mon = false;
+ if (monster != NULL && !invalid_monster(monster))
+ {
+ (void) monster->is_summoned(NULL, &summon_type);
+ valid_mon = true;
+ }
+
+ std::string msg = "disappear%s in a puff of smoke";
+ bool no_chaos = false;
+
+ switch(summon_type)
+ {
+ case SPELL_SHADOW_CREATURES:
+ msg = "disolve%s into shadows";
+ no_chaos = true;
+ break;
+
+ case MON_SUMM_CHAOS:
+ msg = "degenerate%s into a cloud of primal chaos";
+ break;
+
+ case MON_SUMM_WRATH:
+ case MON_SUMM_AID:
+ if (valid_mon && is_good_god(monster->god))
+ {
+ msg = "disolve%s into sparkling lights";
+ no_chaos = true;
+ }
+ break;
+ }
+
+ if (valid_mon)
+ {
+ if (monster->god == GOD_XOM && !no_chaos && one_chance_in(10)
+ || monster->type == MONS_CHAOS_SPAWN)
+ {
+ msg = "degenerate%s into a cloud of primal chaos";
+ }
+
+ if (mons_is_holy(monster) && summon_type != SPELL_SHADOW_CREATURES
+ && summon_type != MON_SUMM_CHAOS)
+ {
+ msg = "disolve%s into sparkling lights";
+ }
+ }
+
+ // Conjugate.
+ msg = make_stringf(msg.c_str(), plural ? "" : "s");
+
+ return (msg);
+}
+
+std::string summoned_poof_msg(const int midx, const item_def &item)
+{
+ if (midx == NON_MONSTER)
+ return summoned_poof_msg(NULL, item);
+ else
+ return summoned_poof_msg(&menv[midx], item);
+}
+
+std::string summoned_poof_msg(const monsters* monster, const item_def &item)
+{
+ ASSERT(item.flags & ISFLAG_SUMMONED);
+
+ return summoned_poof_msg(monster, item.quantity > 1);
+}
diff --git a/crawl-ref/source/mstuff2.h b/crawl-ref/source/mstuff2.h
index 65e3d0d0bb..ce2966bc31 100644
--- a/crawl-ref/source/mstuff2.h
+++ b/crawl-ref/source/mstuff2.h
@@ -38,7 +38,10 @@ bool moth_incite_monsters(const monsters *mon);
void mons_clear_trapping_net(monsters *mon);
bool mons_clonable(const monsters* orig, bool needs_adjacent = true);
-int clone_mons(const monsters* orig, bool quiet = false,
- bool* obvious = NULL, coord_def pos = coord_def(0, 0) );
+int clone_mons(const monsters* orig, bool quiet = false,
+ bool* obvious = NULL, coord_def pos = coord_def(0, 0) );
+std::string summoned_poof_msg(const monsters* monster, bool plural = false);
+std::string summoned_poof_msg(const int midx, const item_def &item);
+std::string summoned_poof_msg(const monsters* monster, const item_def &item);
#endif