diff options
author | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-03-29 14:12:00 +0000 |
---|---|---|
committer | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-03-29 14:12:00 +0000 |
commit | ce89a07e4802691aa3a164ed1e332163f4dd8246 (patch) | |
tree | 5c47b9708d7f344081a341926d0572a4697e42c2 /crawl-ref/source | |
parent | b7861f247d877def85b5efb072fba62fab079eb7 (diff) | |
download | crawl-ref-ce89a07e4802691aa3a164ed1e332163f4dd8246.tar.gz crawl-ref-ce89a07e4802691aa3a164ed1e332163f4dd8246.zip |
Finally allow ranged attacks (BEAM_MISSILE) and spells (BEAM_MMISSILE only)
to also saturate the blood with floor.
Add a basic blood scent effect: all hounds, vampires, and the mosquito get
M_BLOOD_SCENT which will let them wake up when blood is spilled in their
vicinity. smell_blood() is rather similar to noisy(), so monsters will try
to seek the origin of the blood spilled.
Player vampires now get a message if blood is spilled outside their LOS,
"You smell fresh blood" with a distance estimate ("near-by", "in the distance")
added for vampires that are (near) bloodless. Also, the radius a vampire will
be capable of smelling blood will increase the thirstier he is.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3936 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/beam.cc | 71 | ||||
-rw-r--r-- | crawl-ref/source/misc.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 20 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 18 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 102 | ||||
-rw-r--r-- | crawl-ref/source/view.h | 1 |
8 files changed, 187 insertions, 46 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index a1116db1f6..bbbf6ce749 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -1610,15 +1610,14 @@ int mons_adjust_flavoured( monsters *monster, bolt &pbolt, { case BEAM_FIRE: case BEAM_STEAM: - hurted = - resist_adjust_damage( + hurted + = resist_adjust_damage( monster, pbolt.flavour, - pbolt.flavour == BEAM_FIRE - ? monster->res_fire() - : monster->res_steam(), - hurted, - true); + (pbolt.flavour == BEAM_FIRE) ? monster->res_fire() + : monster->res_steam(), + hurted, true); + if (!hurted) { if (doFlavouredEffects) @@ -1728,9 +1727,8 @@ int mons_adjust_flavoured( monsters *monster, bolt &pbolt, } } else if (doFlavouredEffects) - { poison_monster( monster, _whose_kill(pbolt), 4 ); - } + break; case BEAM_NEG: @@ -1761,7 +1759,7 @@ int mons_adjust_flavoured( monsters *monster, bolt &pbolt, } monster->max_hit_points -= 2 + random2(3); - monster->hit_points -= 2 + random2(3); + monster->hit_points -= 2 + random2(3); if (monster->hit_points >= monster->max_hit_points) monster->hit_points = monster->max_hit_points; @@ -2298,10 +2296,10 @@ void fire_tracer(const monsters *monster, bolt &pbolt) pbolt.is_tracer = true; pbolt.source_x = monster->x; // always safe to do. pbolt.source_y = monster->y; - pbolt.beam_source = monster_index(monster); + pbolt.beam_source = monster_index(monster); pbolt.can_see_invis = (mons_see_invis(monster) != 0); - pbolt.smart_monster = (mons_intel(monster->type) == I_HIGH || - mons_intel(monster->type) == I_NORMAL); + pbolt.smart_monster = (mons_intel(monster->type) == I_HIGH + || mons_intel(monster->type) == I_NORMAL); pbolt.attitude = mons_attitude(monster); // init tracer variables @@ -3485,10 +3483,11 @@ static int _affect_player( bolt &beam ) const bool engulfs = (beam.is_explosion || beam.is_big_cloud); mprf( "The %s %s you!", - beam.name.c_str(), (engulfs) ? "engulfs" : "hits" ); + beam.name.c_str(), (engulfs) ? "engulfs" : "hits" ); int hurted = 0; - int burn_power = (beam.is_explosion) ? 5 : ((beam.is_beam) ? 3 : 2); + int burn_power = (beam.is_explosion) ? 5 : + (beam.is_beam) ? 3 : 2; // Roll the damage hurted += roll_dice( beam.damage ); @@ -3529,6 +3528,18 @@ static int _affect_player( bolt &beam ) if (hurted < 0) hurted = 0; + // if the beam is an actual missile or of the MMISSILE type (Earth magic) + // might bleed on the floor + if (!engulfs + && (beam.flavour == BEAM_MISSILE || beam.flavour == BEAM_MMISSILE)) + { + int blood = hurted/2; // assumes DVORP_PIERCING, factor: 0.5 + if (blood > you.hp) + blood = you.hp; + + bleed_onto_floor(you.x_pos, you.y_pos, -1, blood, true); + } + hurted = check_your_resists( hurted, beam.flavour ); if (beam.flavour == BEAM_MIASMA && hurted > 0) @@ -3856,8 +3867,10 @@ static int _affect_monster(bolt &beam, monsters *mon) if (beam.flavour == BEAM_ELECTRICITY) { if (see_grid(mon->x, mon->y)) + { mprf("The %s arcs harmlessly into the water.", beam.name.c_str()); + } return (BEAM_STOP); } @@ -4006,6 +4019,7 @@ static int _affect_monster(bolt &beam, monsters *mon) mprf("%s blocks the %s.", mon->name(DESC_CAP_THE).c_str(), beam.name.c_str()); + mon->shield_block_succeeded(); return (BEAM_STOP); } @@ -4022,17 +4036,18 @@ static int _affect_monster(bolt &beam, monsters *mon) mprf("The %s %s %s.", beam.name.c_str(), engulfs? "engulfs" : "hits", - player_monster_visible(&menv[tid])? - mon->name(DESC_NOCAP_THE).c_str() - : "something"); + player_monster_visible(&menv[tid]) ? + mon->name(DESC_NOCAP_THE).c_str() : "something"); } else { // the player might hear something, // if _they_ fired a missile (not beam) if (!silenced(you.x_pos, you.y_pos) && beam.flavour == BEAM_MISSILE - && YOU_KILL(beam.thrower)) + && YOU_KILL(beam.thrower)) + { mprf(MSGCH_SOUND, "The %s hits something.", beam.name.c_str()); + } } if (beam.name.find("throwing net") != std::string::npos) @@ -4043,9 +4058,22 @@ static int _affect_monster(bolt &beam, monsters *mon) // doFlavouredEffects = false above) hurt_final = mons_adjust_flavoured(mon, beam, raw_damage); + // if the beam is an actual missile or of the MMISSILE type (Earth magic) + // might bleed on the floor + if (!engulfs + && (beam.flavour == BEAM_MISSILE || beam.flavour == BEAM_MMISSILE)) + { + // using raw_damage instead of the flavoured one! + int blood = raw_damage/2; // assumes DVORP_PIERCING, factor: 0.5 + if (blood > mon->hit_points) + blood = mon->hit_points; + + bleed_onto_floor(mon->x, mon->y, mon->type, blood, true); + } + // now hurt monster hurt_monster( mon, hurt_final ); - + if (mon->hit_points < 1) { _monster_die(mon, beam); @@ -4069,8 +4097,7 @@ static int _affect_monster(bolt &beam, monsters *mon) } - /* looks for missiles which aren't poison but - are poison*ed* */ + /* looks for missiles which aren't poison but are poison*ed* */ if (beam.name.find("poisoned") != std::string::npos && beam.flavour != BEAM_POISON && beam.flavour != BEAM_POISON_ARROW) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index 0f8ec8a42b..f676640646 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -341,6 +341,12 @@ static void maybe_bloodify_square(int x, int y, int amount, bool spatter = false #endif if (allow_bleeding_on_square(x,y)) env.map[x][y].property = FPROP_BLOODY; + + // if old or new blood on square, the smell reaches further + if (env.map[x][y].property == FPROP_BLOODY) + blood_smell(12, x, y); + else // still allow a lingering smell + blood_smell(7, x, y); if (spatter) { diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 460bf14772..92baf40a27 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -674,7 +674,7 @@ // hounds ('h') { MONS_JACKAL, 'h', BROWN, "jackal", - M_WARM_BLOOD, + M_WARM_BLOOD | M_BLOOD_SCENT, MR_NO_FLAGS, 200, 10, MONS_HOUND, MONS_JACKAL, MH_NATURAL, -1, { {AT_BITE, AF_PLAIN, 3}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -685,7 +685,7 @@ { MONS_HOUND, 'h', YELLOW, "hound", - M_SENSE_INVIS | M_WARM_BLOOD, + M_SENSE_INVIS | M_WARM_BLOOD | M_BLOOD_SCENT, MR_NO_FLAGS, 300, 10, MONS_HOUND, MONS_HOUND, MH_NATURAL, -3, { {AT_BITE, AF_PLAIN, 6}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -696,7 +696,7 @@ { MONS_WARG, 'h', WHITE, "warg", - M_SENSE_INVIS | M_WARM_BLOOD, + M_SENSE_INVIS | M_WARM_BLOOD | M_BLOOD_SCENT, MR_RES_POISON, 600, 12, MONS_HOUND, MONS_WARG, MH_NATURAL, -6, { {AT_BITE, AF_PLAIN, 12}, {AT_CLAW, AF_PLAIN, 3}, {AT_CLAW, AF_PLAIN, 3}, AT_NO_ATK }, @@ -707,7 +707,7 @@ { MONS_WOLF, 'h', LIGHTGREY, "wolf", - M_WARM_BLOOD | M_SENSE_INVIS, + M_WARM_BLOOD | M_SENSE_INVIS | M_BLOOD_SCENT, MR_NO_FLAGS, 450, 10, MONS_HOUND, MONS_WOLF, MH_NATURAL, -3, { {AT_BITE, AF_PLAIN, 8}, {AT_CLAW, AF_PLAIN, 2}, {AT_CLAW, AF_PLAIN, 2}, AT_NO_ATK }, @@ -718,7 +718,7 @@ { MONS_WAR_DOG, 'h', CYAN, "war dog", - M_SENSE_INVIS | M_WARM_BLOOD, + M_SENSE_INVIS | M_WARM_BLOOD | M_BLOOD_SCENT, MR_NO_FLAGS, 350, 10, MONS_HOUND, MONS_WAR_DOG, MH_NATURAL, -3, { {AT_BITE, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -740,7 +740,7 @@ { MONS_HELL_HOUND, 'h', LIGHTCYAN, "hell hound", - M_SENSE_INVIS | M_EVIL | M_SPECIAL_ABILITY, + M_SENSE_INVIS | M_EVIL | M_SPECIAL_ABILITY | M_BLOOD_SCENT, MR_RES_POISON | MR_RES_HELLFIRE | MR_VUL_COLD, 0, 10, MONS_HOUND, MONS_HELL_HOUND, MH_DEMONIC, -3, { {AT_BITE, AF_PLAIN, 13}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -1452,7 +1452,7 @@ { MONS_GIANT_MOSQUITO, 'y', WHITE, "giant mosquito", - M_FLIES, + M_FLIES | M_BLOOD_SCENT, MR_VUL_POISON, 100, 10, MONS_GIANT_MOSQUITO, MONS_GIANT_MOSQUITO, MH_NATURAL, -3, { {AT_BITE, AF_DISEASE, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -2601,7 +2601,7 @@ // vampires ('V') { MONS_VAMPIRE, 'V', RED, "vampire", - M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS, + M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS | M_BLOOD_SCENT, MR_RES_POISON | MR_RES_COLD, 0, 11, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6, { {AT_BITE, AF_VAMPIRIC, 22}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -2612,7 +2612,7 @@ { MONS_VAMPIRE_KNIGHT, 'V', CYAN, "vampire knight", - M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS, + M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS | M_BLOOD_SCENT, MR_RES_POISON | MR_RES_COLD, 0, 13, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6, { {AT_HIT, AF_PLAIN, 33}, {AT_BITE, AF_VAMPIRIC, 15}, AT_NO_ATK, AT_NO_ATK }, @@ -2623,7 +2623,7 @@ { MONS_VAMPIRE_MAGE, 'V', MAGENTA, "vampire mage", - M_SPELLCASTER | M_SEE_INVIS | M_FLIES | M_EVIL | M_SPEAKS, + M_SPELLCASTER | M_SEE_INVIS | M_FLIES | M_EVIL | M_SPEAKS | M_BLOOD_SCENT, MR_RES_POISON | MR_RES_COLD, 0, 15, MONS_VAMPIRE, MONS_VAMPIRE, MH_UNDEAD, -6, { {AT_BITE, AF_VAMPIRIC, 22}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 44949915ae..757c31c663 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3737,9 +3737,10 @@ void monsters::rot(actor *agent, int rotlevel, int immed_rot) if (damage > 0) { if (mons_near(this) && player_monster_visible(this)) - mprf("%s %s!", - name(DESC_CAP_THE).c_str(), + { + mprf("%s %s!", name(DESC_CAP_THE).c_str(), rotlevel == 0? "looks less resilient" : "rots"); + } hurt(agent, damage); if (alive()) { @@ -4102,8 +4103,10 @@ void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet) case ENCH_SUBMERGED: if (type == MONS_AIR_ELEMENTAL && mons_near(this) && !quiet) + { mprf("%s merges itself into the air.", name(DESC_CAP_A, true).c_str() ); + } break; case ENCH_CHARM: @@ -4189,7 +4192,7 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet) if (mons_class_flag(type, M_INVIS)) add_ench( mon_enchant(ENCH_INVIS) ); else if (mons_near(this) && !player_see_invis() - && !has_ench( ENCH_SUBMERGED )) + && !has_ench( ENCH_SUBMERGED )) { if (!quiet) mprf("%s appears!", name(DESC_CAP_A, true).c_str() ); @@ -4222,8 +4225,10 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet) if (player_monster_visible(this)) simple_monster_message(this, " stops glowing."); else if (has_ench(ENCH_INVIS) && mons_near(this)) + { mprf("%s stops glowing and disappears.", name(DESC_CAP_THE, true).c_str()); + } } break; @@ -5118,8 +5123,10 @@ bool monsters::do_shaft() if (mons_near(this)) { if (player_monster_visible(this)) + { mprf("A shaft briefly opens up underneath %s!", name(DESC_NOCAP_THE).c_str()); + } else mpr("A shaft briefly opens up in the floor!"); } diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 277fb85d86..ae69af7e15 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -104,7 +104,7 @@ enum mons_class_flags M_SPLITS = (1<<12), // monster can split M_AMPHIBIOUS = (1<<13), // monster can swim in water, M_THICK_SKIN = (1<<14), // monster has more effective AC, - M_RESERVED = (1<<15), // currently UNUSED + M_BLOOD_SCENT = (1<<15), // monster can smell blood M_COLD_BLOOD = (1<<16), // susceptible to cold M_WARM_BLOOD = (1<<17), // no effect currently M_REGEN = (1<<18), // regenerates quickly diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index c67df32f00..e76070df59 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -654,8 +654,8 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) update_beholders(monster, true); const int monster_killed = monster_index(monster); - bool death_message = - !silent && mons_near(monster) && player_monster_visible(monster); + bool death_message + = !silent && mons_near(monster) && player_monster_visible(monster); bool in_transit = false; const bool hard_reset = testbits(monster->flags, MF_HARD_RESET); bool drop_items = !hard_reset; @@ -1452,7 +1452,7 @@ bool monster_polymorph( monsters *monster, monster_type targetc, // If old monster is visible to the player, and is interesting, // then note why the interesting monster went away. if (player_monster_visible(monster) && mons_near(monster) - && MONST_INTERESTING(monster)) + && MONST_INTERESTING(monster)) { take_note(Note(NOTE_POLY_MONSTER, monster->type, 0, monster->name(DESC_CAP_A, true).c_str())); @@ -1964,9 +1964,11 @@ void behaviour_event( monsters *mon, int event, int src, // will alert monster to <src> and turn them // against them, unless they have a current foe. // it won't turn friends hostile either. - if (mon->behaviour != BEH_CORNERED && mon->behaviour != BEH_PANIC && - mon->behaviour != BEH_FLEE) + if (mon->behaviour != BEH_CORNERED && mon->behaviour != BEH_PANIC + && mon->behaviour != BEH_FLEE) + { mon->behaviour = BEH_SEEK; + } if (mon->foe == MHITNOT) mon->foe = src; @@ -3516,8 +3518,8 @@ static bool _handle_wand(monsters *monster, bolt &beem) { bool niceWand = false; bool zap = false; - bool was_visible = - mons_near(monster) && player_monster_visible(monster); + bool was_visible + = mons_near(monster) && player_monster_visible(monster); item_def &wand(mitm[monster->inv[MSLOT_WAND]]); @@ -3936,7 +3938,7 @@ static bool _enemies_around(const monsters *monster) static bool _handle_spell( monsters *monster, bolt & beem ) { bool monsterNearby = mons_near(monster); - bool finalAnswer = false; // as in: "Is that your...?" {dlb} + bool finalAnswer = false; // as in: "Is that your...?" {dlb} const spell_type draco_breath = _get_draconian_breath_spell(monster); // yes, there is a logic to this ordering {dlb}: diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 0dc5492496..3acbe87da6 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -1488,7 +1488,6 @@ void cloud_grid(void) // Returns true if the PC heard the noise. bool noisy( int loudness, int nois_x, int nois_y, const char *msg ) { - int p; struct monsters *monster = 0; // NULL {dlb} bool ret = false; @@ -1520,7 +1519,7 @@ bool noisy( int loudness, int nois_x, int nois_y, const char *msg ) ret = true; } - for (p = 0; p < MAX_MONSTERS; p++) + for (int p = 0; p < MAX_MONSTERS; p++) { monster = &menv[p]; @@ -1542,6 +1541,105 @@ bool noisy( int loudness, int nois_x, int nois_y, const char *msg ) return (ret); } // end noisy() +static const char* _player_vampire_smells_blood(int dist) +{ + // non-hungry vampires get no clear indication of how close the smell is + if (you.hunger_state > HS_HUNGRY) + return ""; + + if (dist < 16) // 4*4 + return " near-by"; + + if (you.hunger_state <= HS_NEAR_STARVING && dist > 64) // 8*8 + return " in the distance"; + + return ""; +} + +void blood_smell( int strength, int blood_x, int blood_y ) +{ + struct monsters *monster = 0; // NULL {dlb} + + const int range = strength * strength; +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, + "blood stain at (%d, %d), range of smell = %d", + blood_x, blood_y, range); +#endif + + // of the player species, only vampires can smell blood + if (you.species == SP_VAMPIRE) + { + // whether they actually do so, depends on their hunger state + int vamp_strength = strength - 2 * (you.hunger_state - 1); + if (vamp_strength > 0) + { + int vamp_range = vamp_strength * vamp_strength; + + const int player_distance + = distance( you.x_pos, you.y_pos, blood_x, blood_y ); + + if (player_distance <= vamp_range) + { +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, + "Player smells blood, pos: (%d, %d), dist = %d)", + you.x_pos, you.y_pos, player_distance); +#endif + you.check_awaken(range - player_distance); + // don't message if you can see the square + if (!see_grid(blood_x, blood_y)) + { + mprf("You smell fresh blood%s.", + _player_vampire_smells_blood(player_distance)); + } + } + } + } + + for (int p = 0; p < MAX_MONSTERS; p++) + { + monster = &menv[p]; + + if (monster->type < 0) + continue; + + if (!mons_class_flag(monster->type, M_BLOOD_SCENT)) + continue; + + if (distance(monster->x, monster->y, blood_x, blood_y) <= range) + { + // let sleeping hounds lie + if (mons_is_sleeping(monster) + && mons_species(monster->type) != MONS_VAMPIRE) + { + // 33% chance of sleeping on + // 33% of being disturbed (start BEH_WANDER) + // 33% of being alerted (start BEH_SEEK) + if (!one_chance_in(3)) + { + if (coinflip()) + { +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "disturbing %s (%d, %d)", + monster->name(DESC_PLAIN).c_str(), + monster->x, monster->y); +#endif + behaviour_event( monster, ME_DISTURB, MHITNOT, + blood_x, blood_y ); + } + continue; + } + } +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "alerting %s (%d, %d)", + monster->name(DESC_PLAIN).c_str(), monster->x, monster->y); +#endif + behaviour_event( monster, ME_ALERT, MHITNOT, blood_x, blood_y ); + } + } +} // end blood_smell() + /* The LOS code now uses raycasting -- haranp */ #define LONGSIZE (sizeof(unsigned long)*8) diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index 3bad8ec7c5..93d0c9f746 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -114,6 +114,7 @@ bool magic_mapping(int map_radius, int proportion, bool suppress_msg, * spells - spells3 - spells4 * *********************************************************************** */ bool noisy( int loudness, int nois_x, int nois_y, const char *msg = NULL ); +void blood_smell( int strength, int blood_x, int blood_y); void handle_monster_shouts(monsters* monster, bool force = false); // last updated 12may2000 {dlb} |