summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/fight.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-22 23:45:08 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-22 23:45:08 +0000
commitfd8a1db3054ba396dcb149898891d739a06e4fac (patch)
tree5b1ff087345c2576eb2f281323addb2829bfe1c9 /crawl-ref/source/fight.cc
parent342644a1df21f8426a0786b114833342847784cd (diff)
downloadcrawl-ref-fd8a1db3054ba396dcb149898891d739a06e4fac.tar.gz
crawl-ref-fd8a1db3054ba396dcb149898891d739a06e4fac.zip
Implement another new unique, this time of my own coding: Maurice the thief.
Equipment: a cloak, a dagger or short sword, and some gold. Spells : Blink, Invisibility, Teleport Self Most importantly, in melee combat Maurice will try to steal items from the player. Due to technical limitations he can only steal item types monsters can carry and only if said item slot is still free. All applicable items get weighted by item value, and if nothing is applicable he will steal some gold instead. If even that isn't possible, he'll complain a bit and teleport away. Maurice is placed in the same depth as Gastronok. He's not actually hard (except for the occasional weapon brand or wand), but rather annoying. :p Stealing from monsters hasn't been implemented, and I don't think it's as interesting. Maurice is currently prevented from stealing items the player has equipped, though I'm considering allowing him to steal a wielded weapon, at least. The limitations of monsters' inventories means that Maurice will never attempt to steal armour (slot already filled) or jewellery (missing slot). Maybe we could try to force valuable items into inappropriate but rarely used slots, e.g. MSLOT_MISC. Other than in the FR (see 2838375) Maurice does not disappear from the level, so you can still hunt him down. He also doesn't get a crossbow or blowgun yet, though that's an interesting idea. However, handing out a secondary weapon would mean that he couldn't steal weapons either. Doesn't have a tile yet, and I have no image of him in my head either. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10776 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/fight.cc')
-rw-r--r--crawl-ref/source/fight.cc159
1 files changed, 158 insertions, 1 deletions
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index c7df516e7c..35a7a34926 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -49,6 +49,7 @@ REVISION("$Rev$");
#include "ouch.h"
#include "player.h"
#include "religion.h"
+#include "shopping.h"
#include "skills.h"
#include "spells1.h"
#include "spells3.h"
@@ -4508,6 +4509,150 @@ void melee_attack::splash_defender_with_acid(int strength)
splash_monster_with_acid(strength);
}
+static void _steal_item_from_player(monsters *mon)
+{
+ int steal_what = -1;
+ int total_value = 0;
+ for (int m = 0; m < ENDOFPACK; ++m)
+ {
+ if (!is_valid_item(you.inv[m]))
+ continue;
+
+ // Cannot unequip player.
+ // TODO: Allow stealing of the wielded weapon?
+ // Needs to be unwielded properly and should never lead to
+ // fatal stat loss.
+ if (item_is_equipped(you.inv[m]))
+ continue;
+
+ mon_inv_type monslot = item_to_mslot(you.inv[m]);
+ if (monslot == NUM_MONSTER_SLOTS)
+ continue;
+
+ // Only try to steal stuff we can still store somewhere.
+ if (mon->inv[monslot] != NON_ITEM)
+ {
+ if (monslot == MSLOT_WEAPON
+ && mon->inv[MSLOT_ALT_WEAPON] == NON_ITEM)
+ {
+ monslot = MSLOT_ALT_WEAPON;
+ }
+ else
+ continue;
+ }
+
+ // Candidate for stealing.
+ const int value = item_value(you.inv[m], true);
+ total_value += value;
+
+ if (x_chance_in_y(value, total_value))
+ steal_what = m;
+ }
+
+ if (steal_what == -1 || you.gold > 0 && one_chance_in(10))
+ {
+ // Found no item worth stealing, try gold.
+ if (you.gold == 0)
+ {
+ if (silenced(mon->pos()))
+ return;
+
+ std::string complaint = getSpeakString("Maurice nonstealing");
+ if (!complaint.empty())
+ {
+ complaint = replace_all(complaint, "@The_monster@",
+ mon->name(DESC_CAP_THE));
+ mpr(complaint.c_str(), MSGCH_TALK);
+ }
+
+ bolt beem;
+ beem.source = mon->pos();
+ beem.target = mon->pos();
+ beem.beam_source = mon->mindex();
+
+ // Try to teleport away.
+ if (mon->has_ench(ENCH_TP))
+ {
+ mons_cast_noise(mon, beem, SPELL_BLINK);
+ monster_blink(mon);
+ }
+ else
+ mons_cast(mon, beem, SPELL_TELEPORT_SELF);
+
+ return;
+ }
+
+ const int stolen_amount = std::min(20 + random2(800), you.gold);
+ if (mon->inv[MSLOT_GOLD] != NON_ITEM)
+ {
+ // If Maurice already's got some gold, simply increase the amount.
+ mitm[mon->inv[MSLOT_GOLD]].quantity += stolen_amount;
+ }
+ else
+ {
+ // Else create a new item for this pile of gold.
+ const int idx = items(0, OBJ_GOLD, OBJ_RANDOM, true, 0, 0);
+ if (idx == NON_ITEM)
+ return;
+
+ item_def &new_item = mitm[idx];
+ new_item.base_type = OBJ_GOLD;
+ new_item.sub_type = 0;
+ new_item.plus = 0;
+ new_item.plus2 = 0;
+ new_item.special = 0;
+ new_item.flags = 0;
+ new_item.link = NON_ITEM;
+ new_item.quantity = stolen_amount;
+ new_item.pos.reset();
+ item_colour(new_item);
+
+ unlink_item(idx);
+
+ mon->inv[MSLOT_GOLD] = idx;
+ new_item.set_holding_monster(mon->mindex());
+ }
+ mprf("%s steals %s your gold!",
+ mon->name(DESC_CAP_THE).c_str(),
+ stolen_amount == you.gold ? "all" : "some of");
+
+ you.attribute[ATTR_GOLD_FOUND] -= stolen_amount;
+ you.gold -= stolen_amount;
+ return;
+ }
+
+ ASSERT(steal_what != -1);
+
+ // Create new item.
+ int index = get_item_slot(10);
+ if (index == NON_ITEM)
+ return;
+
+ item_def &new_item = mitm[index];
+
+ // Copy item.
+ new_item = you.inv[steal_what];
+
+ // Set quantity, and set the item as unlinked.
+ new_item.quantity -= random2(new_item.quantity);
+ new_item.pos.reset();
+ new_item.link = NON_ITEM;
+
+ const mon_inv_type mslot = item_to_mslot(new_item);
+
+ mprf("%s steals %s!",
+ mon->name(DESC_CAP_THE).c_str(),
+ new_item.name(DESC_NOCAP_YOUR).c_str());
+
+ unlink_item(index);
+ mon->inv[mslot] = index;
+ new_item.set_holding_monster(mon->mindex());
+ mon->equip(new_item, mslot, true);
+
+ // Item is gone from player's inventory.
+ dec_inv_item_quantity(steal_what, new_item.quantity);
+}
+
void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
{
// Most of this is from BWR 4.1.2.
@@ -4764,6 +4909,14 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
chaos_affects_defender();
break;
+ case AF_STEAL:
+ // Ignore monsters, for now.
+ if (defender->atype() != ACT_PLAYER)
+ break;
+
+ _steal_item_from_player(attacker_as_monster());
+ break;
+
case AF_STEAL_FOOD:
// Monsters don't carry food.
if (defender->atype() != ACT_PLAYER)
@@ -4918,7 +5071,8 @@ void melee_attack::mons_perform_attack_rounds()
// Monsters attacking themselves don't get attack flavour.
// The message sequences look too weird.
- if (attacker != defender)
+ // Also, stealing attacks aren't handled until after the damage msg.
+ if (attacker != defender && attk.flavour != AF_STEAL)
mons_apply_attack_flavour(attk);
if (!special_damage_message.empty())
@@ -5005,6 +5159,9 @@ void melee_attack::mons_perform_attack_rounds()
// Miscast might have killed the attacker.
if (!attacker->alive())
break;
+
+ if (attk.flavour == AF_STEAL)
+ mons_apply_attack_flavour(attk);
}
item_def *weap = attacker_as_monster()->mslot_item(MSLOT_WEAPON);