From 13089bbb1b6ca36c9acad9007a887cfa44b1e30f Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Wed, 7 May 2008 07:39:15 +0000 Subject: Disallow monsters from picking up missiles for which they don't have the necessary launcher, but allow upgrading of missiles for ones with higher pluses or branded ones. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4906 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 2 +- crawl-ref/source/describe.cc | 2 +- crawl-ref/source/initfile.cc | 13 ++++--- crawl-ref/source/itemprop.cc | 13 +++---- crawl-ref/source/itemprop.h | 2 +- crawl-ref/source/makeitem.cc | 81 ++++++++++++++++++++------------------------ crawl-ref/source/misc.cc | 1 + crawl-ref/source/mon-util.cc | 66 ++++++++++++++++++++++++++++++------ crawl-ref/source/monstuff.cc | 11 +++--- 9 files changed, 117 insertions(+), 74 deletions(-) (limited to 'crawl-ref/source') diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 20651e33b8..ce21e2f30f 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -4031,7 +4031,7 @@ static bool _initialise(void) // set vision radius to player's current vision setLOSRadius( you.current_vision ); - if (newc) + if (newc) // start a new game { Options.friendly_pickup = Options.default_friendly_pickup; diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index efc3a0eeb3..2a0928b164 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -1094,7 +1094,7 @@ static std::string _describe_ammo( const item_def &item ) if (get_equip_race(item) != ISFLAG_NO_RACE) { bool can_launch = has_launcher(item); - bool can_throw = is_throwable(item); + bool can_throw = is_throwable(item); description += "$"; if (need_new_line) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index bf37c491d2..bc14c9545f 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -611,10 +611,10 @@ void game_options::reset_options() mouse_input = false; - view_max_width = 33; - view_max_height = 21; + view_max_width = 33; + view_max_height = 21; mlist_min_height = 5; - msg_max_height = 10; + msg_max_height = 10; mlist_allow_alternate_layout = false; classic_hud = false; @@ -629,7 +629,6 @@ void game_options::reset_options() autopickup_on = true; autoprayer_on = false; default_friendly_pickup = 0; // allies may only pickup items - friendly_pickup = 0; // dropped by allies show_more_prompt = true; show_gold_turns = false; @@ -1806,11 +1805,11 @@ void game_options::read_option_line(const std::string &str, bool runscript) else if (key == "default_friendly_pickup") { if (field == "none") - friendly_pickup = -1; + default_friendly_pickup = -1; else if (field == "all") - friendly_pickup = 1; + default_friendly_pickup = 1; else if (field == "friend") - friendly_pickup = 0; + default_friendly_pickup = 0; } else BOOL_OPTION(show_inventory_weights); else BOOL_OPTION(suppress_startup_errors); diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index 4108fb0738..ffa7a24a71 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -2024,7 +2024,7 @@ missile_type fires_ammo_type( weapon_type wtype ) { item_def wpn; wpn.base_type = OBJ_WEAPONS; - wpn.sub_type = wtype; + wpn.sub_type = wtype; return (fires_ammo_type(wpn)); } @@ -2065,18 +2065,19 @@ const char *ammo_name(missile_type ammo) : Missile_prop[ Missile_index[ammo] ].name); } -const char * ammo_name( const item_def &bow ) +const char *ammo_name( const item_def &bow ) { ASSERT( is_range_weapon( bow ) ); return ammo_name(fires_ammo_type( bow )); } // returns true if item has an associated launcher -bool has_launcher( const item_def &wpn ) +bool has_launcher( const item_def &ammo ) { - return (wpn.sub_type != MI_LARGE_ROCK && - wpn.sub_type != MI_JAVELIN && - wpn.sub_type != MI_THROWING_NET); + ASSERT(ammo.base_type == OBJ_MISSILES); + return (ammo.sub_type != MI_LARGE_ROCK + && ammo.sub_type != MI_JAVELIN + && ammo.sub_type != MI_THROWING_NET); } // returns true if item can be reasonably thrown without a launcher diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h index d24246a64d..b27c2573f1 100644 --- a/crawl-ref/source/itemprop.h +++ b/crawl-ref/source/itemprop.h @@ -694,7 +694,7 @@ missile_type fires_ammo_type( const item_def &item ); missile_type fires_ammo_type( weapon_type wtype ); const char * ammo_name( const item_def &bow ); const char * ammo_name( missile_type mtyp ); -bool has_launcher( const item_def &wpn ); +bool has_launcher( const item_def &ammo ); bool is_throwable( const item_def &wpn, size_type bodysize = SIZE_MEDIUM ); launch_retval is_launched(actor *actor, const item_def *launcher, diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index bf0a595bb2..e3dd651184 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -1325,17 +1325,14 @@ static brand_type _determine_weapon_brand(const item_def& item, int item_level) if (one_chance_in(10)) rc = SPWPN_VAMPIRICISM; - if (item.sub_type == WPN_HAND_AXE && - one_chance_in(10)) + if (item.sub_type == WPN_HAND_AXE && one_chance_in(10)) rc = SPWPN_RETURNING; if (_got_distortion_roll(item_level)) rc = SPWPN_DISTORTION; if (one_chance_in(3) && (rc == SPWPN_NORMAL || one_chance_in(5))) - { rc = SPWPN_VORPAL; - } if (one_chance_in(4)) rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING; @@ -1554,7 +1551,7 @@ static void _generate_weapon_item(item_def& item, bool allow_uniques, item.sub_type = WPN_LONG_SWORD; } - item.plus = 0; + item.plus = 0; item.plus2 = 0; set_equip_race(item, _determine_weapon_race(item, item_race)); @@ -1588,7 +1585,7 @@ static void _generate_weapon_item(item_def& item, bool allow_uniques, item.plus2 += 2 + random2(3); } - const int chance = force_good ? 200 : item_level; + const int chance = (force_good ? 200 : item_level); // odd-looking, but this is how the algorithm compacts {dlb}: for (int i = 0; i < 4; ++i) @@ -1675,8 +1672,7 @@ static item_status_flag_type _determine_missile_race(const item_def& item, // Dwarves don't make arrows, sling bullets, javelins, or // throwing nets - if ((item.sub_type == MI_DART - || item.sub_type == MI_BOLT) + if ((item.sub_type == MI_DART || item.sub_type == MI_BOLT) && one_chance_in(6)) { rc = ISFLAG_DWARVEN; @@ -1741,8 +1737,8 @@ static special_missile_type _determine_missile_brand(const item_def& item, // Un-poison sling bullets; un-flame and un-ice javelins; unbrand // throwing nets. if ((item.sub_type == MI_SLING_BULLET && rc == SPMSL_POISONED) - || (item.sub_type == MI_JAVELIN - && (rc == SPMSL_FLAME || rc == SPMSL_ICE)) + || item.sub_type == MI_JAVELIN + && (rc == SPMSL_FLAME || rc == SPMSL_ICE) || item.sub_type == MI_THROWING_NET) { rc = SPMSL_NORMAL; @@ -1754,7 +1750,7 @@ static special_missile_type _determine_missile_brand(const item_def& item, static void _generate_missile_item(item_def& item, int force_type, int item_level, int item_race) { - const bool no_brand = item.special == SPMSL_FORBID_BRAND; + const bool no_brand = (item.special == SPMSL_FORBID_BRAND); if (no_brand) item.special = SPMSL_NORMAL; @@ -1784,7 +1780,7 @@ static void _generate_missile_item(item_def& item, int force_type, } else if (item.sub_type == MI_STONE) { - item.quantity = 1+ random2(9) + random2(12) + random2(15) + random2(12); + item.quantity = 1^+ random2(9) + random2(12) + random2(15) + random2(12); return; } else if (item.sub_type == MI_THROWING_NET) // no fancy nets, either @@ -1811,7 +1807,7 @@ static void _generate_missile_item(item_def& item, int force_type, else if (get_ammo_brand( item ) != SPMSL_NORMAL) item.quantity = 1 + random2(9) + random2(12) + random2(12); else - item.quantity = 1+ random2(9) + random2(12) + random2(12) + random2(15); + item.quantity = 1 + random2(9) + random2(12) + random2(12) + random2(15); if (10 + item_level >= random2(100)) item.plus += random2(5); @@ -1827,7 +1823,7 @@ static void _generate_missile_item(item_def& item, int force_type, static bool _try_make_armour_artefact(item_def& item, int force_type, int item_level) { - if ( item_level > 2 && random2(4000) <= (100 + item_level * 3)) + if (item_level > 2 && random2(4000) <= (100 + item_level * 3)) { // Make a randart or unrandart. @@ -2114,8 +2110,8 @@ static void _generate_armour_item(item_def& item, bool allow_uniques, item.plus++; const bool force_good = (item_level == MAKE_GOOD_ITEM); - const bool forced_ego = item.special > 0; - const bool no_ego = item.special == SPARM_FORBID_EGO; + const bool forced_ego = (item.special > 0); + const bool no_ego = (item.special == SPARM_FORBID_EGO); if (no_ego) item.special = SPARM_NORMAL; @@ -2141,7 +2137,7 @@ static void _generate_armour_item(item_def& item, bool allow_uniques, _determine_armour_ego(item, force_type, item_level)); - if ( get_armour_ego_type(item) == SPARM_PONDEROUSNESS ) + if (get_armour_ego_type(item) == SPARM_PONDEROUSNESS) item.plus += 3 + random2(4); } } @@ -2817,7 +2813,10 @@ int items( int allow_uniques, // not just true-false, default: item.base_type = OBJ_GOLD; if (force_good) - item.quantity = 150+ random2(150) + random2(random2(random2(2000))); + { + item.quantity = 150 + random2(150) + + random2(random2(random2(2000))); + } else item.quantity = 1 + random2avg(19, 2) + random2(item_level); break; @@ -3031,8 +3030,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, } // moved setting of quantity here to keep it in mind {dlb} - int iquan = 1; - // I wonder if this is even used, given calls to item() {dlb} + item.quantity = 1; switch (mon->type) { @@ -3104,7 +3102,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, { force_item = true; item_race = MAKE_ITEM_NO_RACE; - item.plus += 1 + random2(3); + item.plus += 1 + random2(3); item.plus2 += 1 + random2(3); if (one_chance_in(5)) @@ -3347,8 +3345,8 @@ static item_make_species_type _give_weapon(monsters *mon, int level, if (one_chance_in(10) || mon->type == MONS_ETTIN) { - item.sub_type = ((one_chance_in(10)) ? WPN_DIRE_FLAIL - : WPN_GREAT_MACE); + item.sub_type = (one_chance_in(10) ? WPN_DIRE_FLAIL + : WPN_GREAT_MACE); } break; @@ -3394,21 +3392,21 @@ static item_make_species_type _give_weapon(monsters *mon, int level, } break; - case MONS_MERMAID: + case MONS_MERFOLK: if (one_chance_in(3)) { item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; - item.sub_type = WPN_SPEAR; + item.sub_type = WPN_TRIDENT; + break; } - break; - - case MONS_MERFOLK: + // intentionally fall through + case MONS_MERMAID: if (one_chance_in(3)) { item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; - item.sub_type = WPN_TRIDENT; + item.sub_type = WPN_SPEAR; } break; @@ -3417,8 +3415,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; item.sub_type = WPN_BOW; - if (mon->type == MONS_CENTAUR_WARRIOR - && one_chance_in(3)) + if (mon->type == MONS_CENTAUR_WARRIOR && one_chance_in(3)) item.sub_type = WPN_LONGBOW; break; @@ -3435,7 +3432,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; item.sub_type = WPN_SCIMITAR; - item.plus = random2(5); + item.plus = random2(5); item.plus2 = random2(5); item.colour = RED; // forced by force_item above {dlb} set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING ); @@ -3458,7 +3455,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, item.sub_type = WPN_LONG_SWORD; } - item.plus = 1 + random2(3); + item.plus = 1 + random2(3); item.plus2 = 1 + random2(3); break; @@ -3473,7 +3470,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, set_equip_desc( item, ISFLAG_GLOWING ); set_item_ego_type( item, OBJ_WEAPONS, SPWPN_HOLY_WRATH ); - item.plus = 1 + random2(3); + item.plus = 1 + random2(3); item.plus2 = 1 + random2(3); break; @@ -3518,7 +3515,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, : SPWPN_SPEED) ); } - item.plus += random2(6); + item.plus += random2(6); item.plus2 += random2(6); item.colour = RED; // forced by force_item above {dlb} @@ -3533,7 +3530,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, force_item = true; item.base_type = OBJ_WEAPONS; item.sub_type = WPN_GREAT_SWORD; - item.plus = 0; + item.plus = 0; item.plus2 = 0; set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING ); @@ -3548,7 +3545,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, force_item = true; item.base_type = OBJ_WEAPONS; item.sub_type = WPN_BATTLEAXE; - item.plus = 0; + item.plus = 0; item.plus2 = 0; set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FREEZING ); @@ -3621,7 +3618,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, else set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING ); - item.plus = random2(5); + item.plus = random2(5); item.plus2 = random2(5); item.colour = RED; // forced by force_item above {dlb} break; @@ -3642,9 +3639,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, item.y = 0; item.link = NON_ITEM; - if (force_item) - item.quantity = iquan; - else if (mons_is_unique( mon->type )) + if (!force_item && mons_is_unique( mon->type )) { if (random2(100) <= 9 + mon->hit_dice) level = MAKE_GOOD_ITEM; @@ -3675,9 +3670,6 @@ static item_make_species_type _give_weapon(monsters *mon, int level, if (force_item) item_set_appearance(i); - if (iquan > 1 && !force_item) - i.quantity = iquan; - _give_monster_item(mon, thing_created, force_item); if (give_aux_melee && (i.base_type != OBJ_WEAPONS || is_range_weapon(i))) @@ -3814,6 +3806,7 @@ static void _give_ammo(monsters *mon, int level, const int thing_created = items( 0, weap_class, weap_type, true, level, item_race ); + if (thing_created != NON_ITEM) { mitm[thing_created].quantity = qty; diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index 0c1dd4faa9..b7fdba8714 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -2121,6 +2121,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, if (newlevel) { + // When entering a new level, reset friendly_pickup to default. Options.friendly_pickup = Options.default_friendly_pickup; switch(you.level_type) diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index ab35bf2ab1..7d43b91891 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -2916,9 +2916,9 @@ bool monsters::has_spell_of_type(unsigned disciplines) const bool monsters::can_use_missile(const item_def &item) const { - // Pretty simplistic at the moment. We allow monsters to pick up - // missiles without the corresponding launcher, assuming that sufficient - // wandering may get them to stumble upon the launcher. + // Don't allow monsters to pick up missiles without the corresponding + // launcher. The opposite is okay, and sufficient wandering will + // hopefully take the monster to a stack of appropriate missiles. // Prevent monsters that have conjurations / summonings from // grabbing missiles. @@ -2941,7 +2941,20 @@ bool monsters::can_use_missile(const item_def &item) const if (item.sub_type == MI_LARGE_ROCK && !can_throw_rocks()) return (false); - return (true); + // These don't need any launcher, and always okay. + if (item.sub_type == MI_STONE || item.sub_type == MI_DART) + return (true); + + item_def *launch; + for (int i = MSLOT_WEAPON; i <= MSLOT_ALT_WEAPON; ++i) + { + launch = mslot_item(static_cast(i)); + if (launch && fires_ammo_type(*launch) == item.sub_type) + return (true); + } + + // no fitting launcher in inventory + return (false); } void monsters::swap_slots(mon_inv_type a, mon_inv_type b) @@ -3378,7 +3391,7 @@ bool monsters::pickup_throwable_weapon(item_def &item, int near) // If occupied, don't pick up a throwable weapons if it would just // stack with an existing one. (Upgrading is possible.) if (mslot_item(MSLOT_MISSILE) - && behaviour == BEH_WANDER + && (behaviour == BEH_WANDER || mons_friendly(this) && foe == MHITYOU) && pickup(item, MSLOT_MISSILE, near, true)) { return (true); @@ -3584,10 +3597,6 @@ bool monsters::pickup_weapon(item_def &item, int near, bool force) bool monsters::pickup_missile(item_def &item, int near, bool force) { - // XXX: Missile pickup could get a lot smarter if we allow monsters to - // drop their existing missiles and pick up new stuff, but that's too - // much work for now. - const item_def *miss = missiles(); if (item.sub_type == MI_THROWING_NET) @@ -3604,7 +3613,7 @@ bool monsters::pickup_missile(item_def &item, int near, bool force) // Monsters in a fight will only pick up missiles if doing so // is worthwhile. - if (behaviour != BEH_WANDER + if (behaviour != BEH_WANDER && (!mons_friendly(this) || foe != MHITYOU) && (item.quantity < 5 || miss && miss->quantity >= 7)) { return (false); @@ -3616,6 +3625,43 @@ bool monsters::pickup_missile(item_def &item, int near, bool force) if (!force && !can_use_missile(item)) return (false); + if (miss) + { + item_def *launch; + for (int i = MSLOT_WEAPON; i <= MSLOT_ALT_WEAPON; ++i) + { + launch = mslot_item(static_cast(i)); + if (launch) + { + // If this ammunition is better, drop the old ones. + if (fires_ammo_type(*launch) == item.sub_type + && (fires_ammo_type(*launch) != miss->sub_type + || item.plus > miss->plus + || item.plus == miss->plus + && get_ammo_brand(*miss) == SPMSL_NORMAL + && get_ammo_brand(item) != SPMSL_NORMAL)) + { + if (!drop_item(MSLOT_MISSILE, near)) + return (false); + break; + } + } + } + + // Darts don't absolutely need a launcher - still allow upgrading. + if (item.sub_type == miss->sub_type + && item.sub_type == MI_DART + && (item.plus > miss->plus + || item.plus == miss->plus + && get_ammo_brand(*miss) == SPMSL_NORMAL + && get_ammo_brand(item) != SPMSL_NORMAL)) + { + if (!drop_item(MSLOT_MISSILE, near)) + return (false); + } + + } + return pickup(item, MSLOT_MISSILE, near); } diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 3073e5d492..8677061f73 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -4850,8 +4850,10 @@ static void _handle_monster_move(int i, monsters *monster) || monster->type == MONS_NECROPHAGE || monster->type == MONS_GHOUL)) { - // keep neutral and charmed monsters from picking up stuff - if (!mons_neutral(monster) && !monster->has_ench(ENCH_CHARM)) + // Keep neutral and charmed monsters from picking up stuff. + // Same for friendlies if friendly_pickup is set to -1. + if (!mons_neutral(monster) && !monster->has_ench(ENCH_CHARM) + && (!mons_friendly(monster) || Options.friendly_pickup >= 0)) { if (_handle_pickup(monster)) { @@ -5292,16 +5294,17 @@ static bool _handle_pickup(monsters *monster) // Note: Monsters only look at stuff near the top of stacks. + bool success = false; for (item = igrd[monster->x][monster->y]; item != NON_ITEM; ) { item_def &topickup = mitm[item]; item = topickup.link; if (monster->pickup_item(topickup, monsterNearby)) - return (true); + success = true; if (coinflip()) break; } - return (false); + return (success); } // end handle_pickup() static void _jelly_grows(monsters *monster) -- cgit v1.2.3-54-g00ecf