diff options
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/dat/database/monspeak.txt | 49 | ||||
-rw-r--r-- | crawl-ref/source/dat/descript/monsters.txt | 4 | ||||
-rw-r--r-- | crawl-ref/source/debug.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 159 | ||||
-rw-r--r-- | crawl-ref/source/makeitem.cc | 47 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 11 | ||||
-rw-r--r-- | crawl-ref/source/mon-spll.h | 12 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/shopping.cc | 4 |
13 files changed, 286 insertions, 21 deletions
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index d6285ef88c..9056c2d759 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -2138,6 +2138,55 @@ _Maud_rare_ ## END Maud ## %%%% +############ MAURICE ### A thief. +Maurice + +@_Maurice_common_@ + +w:6 +@_Maurice_medium_@ + +w:2 +@_Maurice_rare_@ +%%%% +_Maurice_common_ + +VISUAL:@The_monster@ tries to hide in the shadows. + +@The_monster@ shouts, "HAHA!" + +@The_monster@ says, "Nice gear. Can I borrow some?" + +@The_monster@ shouts, "Mine, all mine!" + +%%%% +_Maurice_medium_ + +VISUAL:@The_monster@ looks sneaky. + +@The_monster@ says, "Lost something?" + +@The_monster@ says, "Very interesting." + +@The_monster@ says, "Have you got some gold to spare?" +%%%% +_Maurice_rare_ + +@The_monster@ says, "Betcha didn't see that coming, eh?" + +@The_monster@ says to @foe@, "Money or life? Never mind, I think I'll take both." + +@The_monster@ says, "Killing adventurers and taking their stuff. It's what I do." +%%%% +# Triggered when Maurice tries to steal something, but doesn't find anything. +Maurice nonstealing + +@The_monster@ grunts, "Curses!" + +@The_monster@ mutters, "Now where did you hide it?" + +@The_monster@ groans, "What are you, a monk?" +%%%% ############ MENKAURE ### A mummy whose rest you've disturbed Menkaure diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index 8e1b566dd0..e457220656 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -216,6 +216,10 @@ Maud A mysterious warrior princess from a far-off kingdom, on a quest to retrieve the legendary sword 'Entarex'. Countless have been the admirers who, thinking about Maud, forgot everything else. %%%% +Maurice + +A sly, conniving thief +%%%% Michael A powerful spellcaster, dressed in a long robe. diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 72c2e356a6..55a6068257 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -5545,6 +5545,7 @@ void wizard_give_monster_item(monsters *mon) mon->equip(mitm[old_eq], mon_slot, 1); } unlink_item(index); + destroy_item(item); return; } diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index ae86128d50..5d8842a95e 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -3304,13 +3304,14 @@ static monster_type _choose_unique_by_depth(int step) case 2: // depth <= 9 ret = random_choose(MONS_BLORK_THE_ORC, MONS_EDMUND, MONS_PSYCHE, MONS_EROLCHA, MONS_PRINCE_RIBBIT, MONS_GRUM, - MONS_GASTRONOK, -1); + MONS_GASTRONOK, MONS_MAURICE, -1); break; case 3: // depth <= 13 ret = random_choose(MONS_PSYCHE, MONS_EROLCHA, MONS_DONALD, MONS_URUG, MONS_MICHAEL, MONS_EUSTACHIO, MONS_SONJA, MONS_GRUM, MONS_JOSEPH, MONS_ERICA, MONS_JOSEPHINE, MONS_JOZEF, - MONS_HAROLD, MONS_NORBERT, MONS_GASTRONOK, -1); + MONS_HAROLD, MONS_NORBERT, MONS_GASTRONOK, + MONS_MAURICE, -1); break; case 4: // depth <= 16 ret = random_choose(MONS_URUG, MONS_MICHAEL, MONS_EUSTACHIO, MONS_SONJA, diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index a4d91768b2..f8fa4f225c 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -2082,9 +2082,10 @@ enum monster_type // (int) menv[].type MONS_GRUM, MONS_PURGY, MONS_MENKAURE, - MONS_DUVESSA, + MONS_DUVESSA, // 465 MONS_DOWAN, MONS_GASTRONOK, + MONS_MAURICE, // Testing monsters MONS_TEST_SPAWNER, @@ -2307,6 +2308,7 @@ enum mon_spellbook_type MST_JESSICA, MST_BERSERK_ESCAPE, // 165 MST_GASTRONOK, + MST_MAURICE, MST_TEST_SPAWNER = 170, NUM_MSTYPES, 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); diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 047dec0917..1ce351d738 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -3456,7 +3456,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, if (!melee_only && one_chance_in(9)) { item.base_type = OBJ_WEAPONS; - item.sub_type = WPN_CROSSBOW; + item.sub_type = WPN_CROSSBOW; break; } // deliberate fall-through @@ -3748,7 +3748,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, case MONS_AGNES: item.base_type = OBJ_WEAPONS; - item.sub_type = WPN_LAJATANG; + item.sub_type = WPN_LAJATANG; if (!one_chance_in(3)) level = MAKE_GOOD_ITEM; break; @@ -3762,9 +3762,9 @@ static item_make_species_type _give_weapon(monsters *mon, int level, break; } force_item = true; - item_race = MAKE_ITEM_NO_RACE; + item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; - item.sub_type = coinflip() ? WPN_DAGGER : WPN_SHORT_SWORD; + item.sub_type = coinflip() ? WPN_DAGGER : WPN_SHORT_SWORD; set_item_ego_type(item, OBJ_WEAPONS, random_choose_weighted(3, SPWPN_DISTORTION, 2, SPWPN_VENOM, @@ -3772,10 +3772,16 @@ static item_make_species_type _give_weapon(monsters *mon, int level, 0)); break; + case MONS_MAURICE: + item_race = MAKE_ITEM_NO_RACE; + item.base_type = OBJ_WEAPONS; + item.sub_type = coinflip() ? WPN_DAGGER : WPN_SHORT_SWORD; + break; + case MONS_EUSTACHIO: item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; - item.sub_type = (one_chance_in(3) ? WPN_FALCHION : WPN_SABRE); + item.sub_type = (one_chance_in(3) ? WPN_FALCHION : WPN_SABRE); break; case MONS_CEREBOV: @@ -4329,8 +4335,16 @@ void give_armour(monsters *mon, int level) item.sub_type = ARM_WIZARD_HAT; break; + case MONS_MAURICE: + item_race = MAKE_ITEM_NO_RACE; + item.base_type = OBJ_ARMOUR; + item.sub_type = ARM_CLOAK; + force_colour = DARKGREY; + break; + case MONS_DOWAN: item_race = MAKE_ITEM_ELVEN; + // intentional fall-through case MONS_DONALD: case MONS_JESSICA: case MONS_KOBOLD_DEMONOLOGIST: @@ -4357,13 +4371,13 @@ void give_armour(monsters *mon, int level) if (item_race == MAKE_ITEM_RANDOM_RACE) item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_ARMOUR; - item.sub_type = ARM_ROBE; + item.sub_type = ARM_ROBE; break; case MONS_TIAMAT: item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_ARMOUR; - item.sub_type = ARM_GOLD_DRAGON_ARMOUR; + item.sub_type = ARM_GOLD_DRAGON_ARMOUR; break; case MONS_ORC_WIZARD: @@ -4371,7 +4385,7 @@ void give_armour(monsters *mon, int level) case MONS_NERGALLE: item_race = MAKE_ITEM_ORCISH; item.base_type = OBJ_ARMOUR; - item.sub_type = ARM_ROBE; + item.sub_type = ARM_ROBE; break; case MONS_BORIS: @@ -4383,8 +4397,8 @@ void give_armour(monsters *mon, int level) case MONS_NECROMANCER: case MONS_VAMPIRE_MAGE: item.base_type = OBJ_ARMOUR; - item.sub_type = ARM_ROBE; - force_colour = DARKGREY; //mv: always darkgrey + item.sub_type = ARM_ROBE; + force_colour = DARKGREY; //mv: always darkgrey break; case MONS_EUSTACHIO: @@ -4396,8 +4410,8 @@ void give_armour(monsters *mon, int level) case MONS_NESSOS: item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_ARMOUR; - item.sub_type = ARM_CENTAUR_BARDING; - force_colour = DARKGREY; + item.sub_type = ARM_CENTAUR_BARDING; + force_colour = DARKGREY; break; default: @@ -4427,10 +4441,19 @@ void give_armour(monsters *mon, int level) mitm[thing_created].colour = force_colour; } +static void _give_gold(monsters *mon, int level) +{ + const int idx = items(0, OBJ_GOLD, 0, true, level, 0); + _give_monster_item(mon, idx); +} + void give_item(int mid, int level_number, bool mons_summoned) { monsters *mons = &menv[mid]; + if (mons->type == MONS_MAURICE) + _give_gold(mons, level_number); + _give_scroll(mons, level_number); _give_wand(mons, level_number); _give_potion(mons, level_number); diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 1bfb0fc92f..6cc1464014 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -4549,6 +4549,17 @@ static monsterentry mondata[] = { HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, MONEAT_NOTHING, SIZE_MEDIUM }, +{ + MONS_MAURICE, '@', DARKGREY, "Maurice", + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, + MR_NO_FLAGS, + 550, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4, + { {AT_HIT, AF_STEAL, 9}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 5, 0, 0, 60 }, + 1, 13, MST_MAURICE, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH, + HT_LAND, 11, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, MONEAT_NOTHING, SIZE_MEDIUM +}, + // unique major demons ('&') { MONS_MNOLEG, '&', LIGHTGREEN, "Mnoleg", diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h index 559d56b8da..4a7af5cff0 100644 --- a/crawl-ref/source/mon-spll.h +++ b/crawl-ref/source/mon-spll.h @@ -1112,6 +1112,18 @@ } }, + { MST_MAURICE, + { + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_INVISIBILITY, + SPELL_BLINK, + SPELL_NO_SPELL, + SPELL_TELEPORT_SELF, + } + }, + + // demon lords { MST_GERYON, { diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 50ef978332..28455a09f1 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -4999,7 +4999,7 @@ bool monsters::pickup_armour(item_def &item, int near, bool force) equipment_type eq = EQ_NONE; - // Hack to allow nagas/centaurs to wear bardings. (jpeg) + // HACK to allow nagas/centaurs to wear bardings. (jpeg) switch (item.sub_type) { case ARM_NAGA_BARDING: @@ -5013,11 +5013,15 @@ bool monsters::pickup_armour(item_def &item, int near, bool force) eq = EQ_BODY_ARMOUR; } break; + // And another hack or two... case ARM_WIZARD_HAT: - // HACK. if (this->type == MONS_GASTRONOK) eq = EQ_BODY_ARMOUR; break; + case ARM_CLOAK: + if (this->type == MONS_MAURICE) + eq = EQ_BODY_ARMOUR; + break; default: eq = get_armour_slot(item); } diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 1754e1bd67..16cfbf78c6 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -83,6 +83,7 @@ enum mon_attack_flavour AF_RAGE, AF_NAPALM, AF_CHAOS, + AF_STEAL, AF_STEAL_FOOD }; diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 1cca39083e..097c6b6737 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -6967,7 +6967,7 @@ static bool _handle_spell(monsters *monster, bolt &beem) spellOK = false; } else if (monster->type == MONS_DAEVA - && monster->god == GOD_SHINING_ONE) + && monster->god == GOD_SHINING_ONE) { const monsters *mon = &menv[monster->foe]; diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index dfcdd0306a..51dccf3f4f 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -632,8 +632,8 @@ unsigned int item_value( item_def item, bool ident ) // copy to mangle as necessary. item.flags = (ident) ? (item.flags | ISFLAG_IDENT_MASK) : (item.flags); - if (is_unrandom_artefact( item ) && - item_ident( item, ISFLAG_KNOW_PROPERTIES )) + if (is_unrandom_artefact( item ) + && item_ident( item, ISFLAG_KNOW_PROPERTIES )) { const unrandart_entry *entry = get_unrand_entry(item.special); if (entry->value != 0) |