summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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