summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/beam.cc2
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/item_use.cc15
-rw-r--r--crawl-ref/source/itemname.cc1
-rw-r--r--crawl-ref/source/makeitem.cc10
-rw-r--r--crawl-ref/source/mon-util.cc4
-rw-r--r--crawl-ref/source/monstuff.cc19
-rw-r--r--crawl-ref/source/mstuff2.cc31
8 files changed, 71 insertions, 12 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 89d3bb0c3d..fee514c479 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -3633,7 +3633,7 @@ static int affect_monster(bolt &beam, monsters *mon)
if (player_monster_visible( &menv[tid] ) && mons_near(mon))
{
msg::stream << "The " << beam.name << " misses "
- << str_monam(*mon, DESC_NOCAP_THE) << std::endl;
+ << mon->name(DESC_NOCAP_THE) << '.' << std::endl;
}
return (0);
}
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index f0c36af87f..11f49aabd4 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -3172,6 +3172,7 @@ enum brand_type // equivalent to (you.inv[].special or mitm[].special) % 30
SPWPN_PAIN, // 15
SPWPN_DISTORTION,
SPWPN_REACHING, // 17
+ SPWPN_RETURNING,
SPWPN_CONFUSE,
SPWPN_RANDART_I = 25, // 25
SPWPN_RANDART_II,
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index a9df7881e1..676fb0cbd1 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -514,6 +514,10 @@ void wield_effects(int item_wield_2, bool showMsgs)
mpr("You sense a holy aura.");
break;
+ case SPWPN_RETURNING:
+ mpr("It wiggles slightly.");
+ break;
+
case SPWPN_PAIN:
mpr("A searing pain shoots up your arm!");
break;
@@ -1367,6 +1371,7 @@ bool throw_it(struct bolt &pbolt, int throw_2, bool teleport, int acc_bonus)
int dice_mult = 100;
bool launched = false; // item is launched
bool thrown = false; // item is sensible thrown item
+ bool returning = false; // item will return to pack
int slayDam = 0;
if (!teleport)
@@ -1790,6 +1795,8 @@ bool throw_it(struct bolt &pbolt, int throw_2, bool teleport, int acc_bonus)
// CALCULATIONS FOR THROWN WEAPONS
if (thrown)
{
+ returning = (get_weapon_brand(item) == SPWPN_RETURNING &&
+ !one_chance_in(you.skills[SK_RANGED_COMBAT]+1));
baseHit = 0;
// since darts/rocks are missiles, they only use inv_plus
@@ -1994,10 +2001,14 @@ bool throw_it(struct bolt &pbolt, int throw_2, bool teleport, int acc_bonus)
{
// Dropping item copy, since the launched item might be different
// (e.g. venom blowgun)
- fire_beam( pbolt, &item );
+ fire_beam(pbolt, returning ? NULL : &item);
}
- dec_inv_item_quantity( throw_2, 1 );
+ if ( returning )
+ msg::stream << item.name(DESC_CAP_THE) << " returns to your pack!"
+ << std::endl;
+ else
+ dec_inv_item_quantity( throw_2, 1 );
// throwing and blowguns are silent
if (launched && lnchType != WPN_BLOWGUN)
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index c9344ea041..c1c12dba56 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -301,6 +301,7 @@ static const char* weapon_brand_name(const item_def& item, bool terse)
case SPWPN_PAIN: return ((terse) ? " (pain)" : " of pain");
case SPWPN_DISTORTION: return ((terse) ? " (distort)" : " of distortion");
case SPWPN_REACHING: return ((terse) ? " (reach)" : " of reaching");
+ case SPWPN_RETURNING: return ((terse) ? " (return)" : " of returning");
case SPWPN_VAMPIRICISM:
return ((terse) ? " (vamp)" : ""); // non-terse already handled
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index f11995ae42..b65ee8991a 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -1324,6 +1324,9 @@ int items( int allow_uniques, // not just true-false,
case WPN_DAGGER:
+ if (one_chance_in(4))
+ set_weapon_special(p, SPWPN_RETURNING);
+
if (one_chance_in(10))
set_weapon_special(p, SPWPN_PAIN);
@@ -1434,6 +1437,10 @@ int items( int allow_uniques, // not just true-false,
if (one_chance_in(10))
set_weapon_special(p, SPWPN_VAMPIRICISM);
+ if (mitm[p].sub_type == WPN_HAND_AXE &&
+ one_chance_in(10))
+ set_weapon_special(p, SPWPN_RETURNING);
+
if (got_distortion_roll(item_level))
set_weapon_special(p, SPWPN_DISTORTION);
@@ -1504,6 +1511,9 @@ int items( int allow_uniques, // not just true-false,
if (one_chance_in(10))
set_weapon_special(p, SPWPN_VAMPIRICISM);
+ if (mitm[p].sub_type == WPN_SPEAR && one_chance_in(6))
+ set_weapon_special(p, SPWPN_RETURNING);
+
if (got_distortion_roll(item_level))
set_weapon_special(p, SPWPN_DISTORTION);
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 1f9fe7951b..7cfbcb5cc0 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -1980,6 +1980,10 @@ bool mons_has_ranged_attack( const monsters *mon )
const int weapon = mon->inv[MSLOT_WEAPON];
const int ammo = mon->inv[MSLOT_MISSILE];
+ if ( weapon != NON_ITEM &&
+ get_weapon_brand(mitm[weapon]) == SPWPN_RETURNING )
+ return true;
+
const int lnchClass = (weapon != NON_ITEM) ? mitm[weapon].base_type : -1;
const int lnchType = (weapon != NON_ITEM) ? mitm[weapon].sub_type : 0;
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index dd00ba6fef..4ca9b40d29 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -3274,7 +3274,22 @@ static bool handle_throw(monsters *monster, bolt & beem)
if (mons_itemuse(monster->type) < MONUSE_OPEN_DOORS)
return (false);
- const int mon_item = monster->inv[MSLOT_MISSILE];
+ int mon_item;
+ const int mon_wpn = monster->inv[MSLOT_WEAPON];
+ bool returning = false;
+
+ // weapons of returning can be thrown
+ if ( mon_wpn != NON_ITEM &&
+ get_weapon_brand(mitm[mon_wpn]) == SPWPN_RETURNING )
+ {
+ mon_item = mon_wpn;
+ returning = true;
+ }
+ else
+ {
+ mon_item = monster->inv[MSLOT_MISSILE];
+ }
+
if (mon_item == NON_ITEM || !is_valid_item( mitm[mon_item] ))
return (false);
@@ -3308,7 +3323,7 @@ static bool handle_throw(monsters *monster, bolt & beem)
throw_type( lnchClass, lnchType, wepClass, wepType, launched, thrown );
- if (!launched && !thrown)
+ if (!launched && !thrown && !returning)
return (false);
// ok, we'll try it.
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 41edcb93c0..03444dfd20 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -1006,11 +1006,10 @@ void throw_type( int lnchClass, int lnchType, int wepClass, int wepType,
bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
{
- // this was assumed during cleanup down below:
- ASSERT( hand_used == monster->inv[MSLOT_MISSILE] );
-
// XXX: ugly hack, but avoids adding dynamic allocation to this code
- static char throw_buff[ ITEMNAME_SIZE ];
+ char throw_buff[ ITEMNAME_SIZE ];
+
+ bool returning = (get_weapon_brand(mitm[hand_used]) == SPWPN_RETURNING);
int baseHit = 0, baseDam = 0; // from thrown or ammo
int ammoHitBonus = 0, ammoDamBonus = 0; // from thrown or ammo
@@ -1048,6 +1047,11 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
// figure out if we're thrown or launched
throw_type( lnchClass, lnchType, wepClass, wepType, launched, thrown );
+ if (returning)
+ {
+ launched = false;
+ thrown = true;
+ }
// extract launcher bonuses due to magic
if (launched)
@@ -1280,11 +1284,24 @@ bool mons_throw(struct monsters *monster, struct bolt &pbolt, int hand_used)
scale_dice(pbolt.damage);
// decrease inventory
- fire_beam( pbolt, &item );
+ bool really_returns;
+ if ( returning && !one_chance_in(mons_power(monster->type) + 3) )
+ really_returns = true;
+ else
+ really_returns = false;
+
+ fire_beam( pbolt, really_returns ? NULL : &item );
- if (dec_mitm_item_quantity( hand_used, 1 ))
- monster->inv[MSLOT_MISSILE] = NON_ITEM;
+ if ( really_returns )
+ {
+ msg::stream << "The weapon returns to "
+ << monster->name(DESC_NOCAP_THE)
+ << "'s hand!" << std::endl;
+ }
+ if ( !really_returns )
+ if (dec_mitm_item_quantity( hand_used, 1 ))
+ monster->inv[returning ? MSLOT_WEAPON : MSLOT_MISSILE] = NON_ITEM;
return (true);
} // end mons_throw()