diff options
-rw-r--r-- | crawl-ref/source/debug.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 21 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 16 | ||||
-rw-r--r-- | crawl-ref/source/mapmark.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 74 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 15 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 153 | ||||
-rw-r--r-- | crawl-ref/source/monspeak.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 59 |
11 files changed, 238 insertions, 129 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index d38b849866..68dad70bbc 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -438,7 +438,11 @@ void create_spec_monster_name(int x, int y) mons_spec mspec = mlist.get_monster(0); if (!force_place && mspec.mid != -1) { - coord_def place = find_newmons_square(mspec.mid, coord_def(x, y)); + int type = mspec.mid; + if (mons_class_is_zombified(mspec.mid)) + type = mspec.monbase; + + coord_def place = find_newmons_square(type, coord_def(x, y)); if (in_bounds(place)) { x = place.x; @@ -453,11 +457,11 @@ void create_spec_monster_name(int x, int y) if (!dgn_place_monster(mspec, you.your_level, x, y, false)) { - mpr("Unable to place monster"); + mpr("Unable to place monster."); return; } - // Need to set a name for the player ghost + // Need to set a name for the player ghost. if (mspec.mid == MONS_PLAYER_GHOST) { unsigned short mid = mgrd[x][y]; @@ -485,7 +489,7 @@ void create_spec_monster_name(int x, int y) ghost.name = "John Doe"; char input_str[80]; - mpr( "Make player ghost which species? (case-sensitive) ", MSGCH_PROMPT ); + mpr("Make player ghost which species? (case-sensitive) ", MSGCH_PROMPT); get_input_line( input_str, sizeof( input_str ) ); int sp_id = get_species_by_abbrev(input_str); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 7855e3db40..5ab12f34b2 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -4102,7 +4102,7 @@ bool dgn_place_map(int map, bool generating_level, bool clobber, const map_def *mdef = map_by_index(map); bool did_map = false; - bool fixup = false; + bool fixup = false; if (mdef->orient == MAP_ENCOMPASS && !generating_level) { @@ -4119,6 +4119,7 @@ bool dgn_place_map(int map, bool generating_level, bool clobber, mprf(MSGCH_DIAGNOSTICS, "Cannot generate encompass map '%s' without clobber=true", mdef->name.c_str()); + return (false); } } @@ -4538,7 +4539,7 @@ bool dgn_place_monster(mons_spec &mspec, { if (mspec.mid != -1) { - const int mid = mspec.mid; + const int mid = mspec.mid; const bool m_generate_awake = (generate_awake || mspec.generate_awake); const bool m_patrolling = (patrolling || mspec.patrolling); @@ -4555,10 +4556,15 @@ bool dgn_place_monster(mons_spec &mspec, if (mid != RANDOM_MONSTER && mid < NUM_MONSTERS) { + // Don't place a unique monster a second time. + // (Boris is handled specially.) if (mons_is_unique(mid) && you.unique_creatures[mid]) return (false); - const habitat_type habitat = mons_habitat_by_type(mid); + const int type = mons_class_is_zombified(mid) ? mspec.monbase + : mid; + + const habitat_type habitat = mons_habitat_by_type(type); if (habitat != HT_LAND) grd[vx][vy] = habitat2grid(habitat); } @@ -7286,6 +7292,9 @@ static void _build_river( dungeon_feature_type river_type ) //mv } else grd[i][j] = river_type; + + // Override existing markers. + env.markers.remove_markers_at(coord_def(i, j), MAT_ANY); } } } @@ -7306,7 +7315,6 @@ static void _build_lake(dungeon_feature_type lake_type) //mv y1 = 5 + random2(GYM - 30); x2 = x1 + 4 + random2(16); y2 = y1 + 8 + random2(12); - // mpr("lake"); for (j = y1; j < y2; j++) { @@ -7337,7 +7345,12 @@ static void _build_lake(dungeon_feature_type lake_type) //mv // So we'll avoid the silliness of monsters and items // on lava and deep water grids. -- bwr if (!one_chance_in(200) && _may_overwrite_pos(i,j)) + { grd[i][j] = lake_type; + + // Override markers. (No underwater portals, please.) + env.markers.remove_markers_at(coord_def(i, j), MAT_ANY); + } } } } diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index d330a6e666..135da21ca1 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -1950,9 +1950,9 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec) if (mspec.genweight == TAG_UNFOUND || mspec.genweight <= 0) mspec.genweight = 10; - mspec.fix_mons = strip_tag(mon_str, "fix_mons"); + mspec.fix_mons = strip_tag(mon_str, "fix_mons"); mspec.generate_awake = strip_tag(mon_str, "generate_awake"); - mspec.patrolling = strip_tag(mon_str, "patrolling"); + mspec.patrolling = strip_tag(mon_str, "patrolling"); std::string colour = strip_tag_prefix(mon_str, "col:"); if (!colour.empty()) @@ -1985,9 +1985,9 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec) return (slot); } - mspec.mid = nspec.mid; + mspec.mid = nspec.mid; mspec.monbase = nspec.monbase; - mspec.number = nspec.number; + mspec.number = nspec.number; } if (mspec.items.size() > 0) @@ -2056,10 +2056,10 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const // This order must match zombie_types, indexed from one. static const monster_type zombie_montypes[][2] = - { - { MONS_PROGRAM_BUG, MONS_PROGRAM_BUG }, - { MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE }, - { MONS_SKELETON_SMALL, MONS_SKELETON_LARGE }, + { // small // large + { MONS_PROGRAM_BUG, MONS_PROGRAM_BUG }, + { MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE }, + { MONS_SKELETON_SMALL, MONS_SKELETON_LARGE }, { MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_LARGE } }; diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc index 1041470e6e..75ffcab11e 100644 --- a/crawl-ref/source/mapmark.cc +++ b/crawl-ref/source/mapmark.cc @@ -340,8 +340,10 @@ void map_lua_marker::notify_dgn_event(const dgn_event &e) push_fn_args("event"); clua_push_dgn_event(dlua, &e); if (!dlua.callfn("dlua_marker_method", 4, 0)) + { mprf(MSGCH_ERROR, "notify_dgn_event: Lua error: %s", dlua.error.c_str()); + } } std::string map_lua_marker::call_str_fn(const char *fn) const diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index a41e4b6f3f..0f609174c8 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -3707,7 +3707,7 @@ 0, 14, MONS_PANDEMONIUM_DEMON, MONS_PANDEMONIUM_DEMON, MH_DEMONIC, -5, { {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, { 4, 2, 3, 0 }, - 1, 2, MST_GHOST, CE_NOCORPSE, Z_NOZOMBIE, S_RANDOM, I_HIGH, + 1, 2, MST_GHOST, CE_NOCORPSE, Z_NOZOMBIE, S_DEMON_TAUNT, I_HIGH, HT_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, SIZE_LARGE }, diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 9a20ca6164..9bc7092d78 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -583,12 +583,51 @@ int get_shout_noise_level(const shout_type shout) } } -shout_type mons_shouts(int mc) +// Only the beast uses S_RANDOM for noise type. +// Pandemonium lords can also get here but they can use almost anything. +static bool _shout_fits_monster(int type, int shout) +{ + if (shout == NUM_SHOUTS || shout >= NUM_LOUDNESS) + return (false); + + // For demon lords almost everything is fair game. + // It's only used for the shouting verb ("say", "whine", "roar", ...) + // anyway. + if (type != MONS_BEAST) + return (shout != S_BUZZ && shout != S_WHINE); + + switch (shout) + { + // 2-headed ogres, bees or mosquitos never fit. + case S_SHOUT2: + case S_BUZZ: + case S_WHINE: + // The beast cannot speak. + case S_DEMON_TAUNT: + // Silent is boring. + case S_SILENT: + return (false); + default: + return (true); + } +} + +// If demon_shout is true, we're trying to find a random loudness for +// a pandemonium lord trying to shout. +shout_type mons_shouts(int mc, bool demon_shout) { shout_type u = smc->shouts; - if (u == S_RANDOM) - u = static_cast<shout_type>(random2(NUM_SHOUTS)); + // Pandemonium lords use this to get the noises. + if (u == S_RANDOM || demon_shout && u == S_DEMON_TAUNT) + { + const int max_shout = (u == S_RANDOM ? NUM_SHOUTS : NUM_LOUDNESS); + do + { + u = static_cast<shout_type>(random2(max_shout)); + } + while (!_shout_fits_monster(mc, u)); + } return (u); } @@ -6208,13 +6247,14 @@ static std::string _pluralise_player_genus() // Replaces the "@foo@" strings in monster shout and monster speak // definitions. std::string do_mon_str_replacements(const std::string &in_msg, - const monsters* monster) + const monsters* monster, int s_type) { std::string msg = in_msg; description_level_type nocap = DESC_NOCAP_THE, cap = DESC_CAP_THE; std::string name = monster->is_named()? monster->name(DESC_CAP_THE) : ""; + if (!name.empty() && player_monster_visible(monster)) { msg = replace_all(msg, "@the_something@", name); @@ -6306,7 +6346,7 @@ std::string do_mon_str_replacements(const std::string &in_msg, msg = replace_all(msg, "@possessive@", monster->pronoun(PRONOUN_NOCAP_POSSESSIVE)); - // replace with "you are" for atheists + // Replace with "you are" for atheists. msg = replace_all(msg, "@god_is@", _replace_god_name(true, false)); msg = replace_all(msg, "@God_is@", _replace_god_name(true, true)); @@ -6314,7 +6354,7 @@ std::string do_mon_str_replacements(const std::string &in_msg, msg = replace_all(msg, "@player_god@", _replace_god_name(false, false)); msg = replace_all(msg, "@Player_god@", _replace_god_name(false, true)); - // replace with species specific insults + // Replace with species specific insults. if (msg.find("@species_insult_") != std::string::npos) { msg = replace_all(msg, "@species_insult_adj1@", @@ -6341,21 +6381,27 @@ std::string do_mon_str_replacements(const std::string &in_msg, "croaks", "growls", "hisses", - "breathes", // S_VERY_SOFT - "whispers", // S_SOFT - "says", // S_NORMAL - "shouts", // S_LOUD - "screams" // S_VERY_LOUD + "sneers", // S_DEMON_TAUNT + "buggily says", // NUM_SHOUTS + "breathes", // S_VERY_SOFT + "whispers", // S_SOFT + "says", // S_NORMAL + "shouts", // S_LOUD + "screams" // S_VERY_LOUD }; - if (mons_shouts(monster->type) >= NUM_SHOUTS) + if (s_type < 0 || s_type >= NUM_LOUDNESS || s_type == NUM_SHOUTS) + s_type = mons_shouts(monster->type); + + if (s_type < 0 || s_type >= NUM_LOUDNESS || s_type == NUM_SHOUTS) { mpr("Invalid @says@ type.", MSGCH_DIAGNOSTICS); msg = replace_all(msg, "@says@", "buggily says"); } else - msg = replace_all(msg, "@says@", - sound_list[mons_shouts(monster->type)]); + { + msg = replace_all(msg, "@says@", sound_list[s_type]); + } // The proper possessive for a word ending in an "s" is to // put an apostrophe after the "s": "Chris" -> "Chris'", diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 0dbc4dc974..e8d01f48ad 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -217,14 +217,16 @@ enum shout_type S_SHOUT2, // shout twice (e.g. two-headed ogres) S_ROAR, // roar S_SCREAM, // scream - S_BELLOW, // bellow (?) + S_BELLOW, // bellow (yaks) S_SCREECH, // screech S_BUZZ, // buzz S_MOAN, // moan - S_WHINE, // irritating whine (mosquito) + S_WHINE, // irritating whine (mosquitos) S_CROAK, // frog croak S_GROWL, // for bears S_HISS, // for snakes and lizards + S_DEMON_TAUNT, // for pandemonium lords + NUM_SHOUTS, // Loudness setting for shouts that are only defined in dat/shout.txt S_VERY_SOFT, @@ -233,7 +235,7 @@ enum shout_type S_LOUD, S_VERY_LOUD, - NUM_SHOUTS, + NUM_LOUDNESS, S_RANDOM }; @@ -420,7 +422,7 @@ bool mons_player_visible( const monsters *mon ); * called from: view * *********************************************************************** */ int get_shout_noise_level(const shout_type shout); -shout_type mons_shouts(int mclass); +shout_type mons_shouts(int mclass, bool demon_shout = false); bool mons_is_unique(int mclass); @@ -684,9 +686,10 @@ void init_mon_name_cache(); monster_type get_monster_by_name(std::string name, bool exact = false); std::string do_mon_str_replacements(const std::string &msg, - const monsters* monster); + const monsters* monster, int s_type = -1); -enum mon_body_shape { +enum mon_body_shape +{ MON_SHAPE_HUMANOID, MON_SHAPE_HUMANOID_WINGED, MON_SHAPE_HUMANOID_TAILED, diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index fb5dec3f53..0df2f1f352 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -389,15 +389,19 @@ static monster_type resolve_monster_type(monster_type mon_type, || drac_colour_incompatible(mon_type, base_type))); } else if (mon_type == RANDOM_BASE_DRACONIAN) + { mon_type = static_cast<monster_type>( random_range(MONS_BLACK_DRACONIAN, MONS_PALE_DRACONIAN)); + } else if (mon_type == RANDOM_NONBASE_DRACONIAN) + { mon_type = static_cast<monster_type>( random_range(MONS_DRACONIAN_CALLER, MONS_DRACONIAN_SCORCHER)); + } - // (2) take care of non-drac random monsters + // (2) Take care of non-draconian random monsters. if (mon_type == RANDOM_MONSTER) { level_id place = level_id::current(); @@ -417,29 +421,30 @@ static monster_type resolve_monster_type(monster_type mon_type, if (!unforbidden( pos, mmask )) continue; - // don't generate monsters on top of teleport traps + // Don't generate monsters on top of teleport traps. int trap = trap_at_xy(pos.x, pos.y); if (trap >= 0) { if (!can_place_on_trap(mon_type, env.trap[trap].type)) - continue; + continue; } - // check whether there's a stair - // and whether it leads to another branch - pval = near_stairs(pos, 1, - *stair_type, place.branch); + // Check whether there's a stair + // and whether it leads to another branch. + pval = near_stairs(pos, 1, *stair_type, place.branch); - // no monsters spawned in the Temple + // No monsters spawned in the Temple. if (branches[place.branch].id == BRANCH_ECUMENICAL_TEMPLE) continue; - // found a position near the stairs! + // Found a position near the stairs! if (pval > 0) break; } + if (tries > 320) - { // give up and try somewhere else + { + // Give up and try somewhere else. proximity = PROX_AWAY_FROM_PLAYER; } else @@ -448,11 +453,11 @@ static monster_type resolve_monster_type(monster_type mon_type, ++*lev_mons; else if (*stair_type == DCHAR_STAIRS_UP) // higher level { - // monsters don't come from outside the dungeon + // Monsters don't come from outside the dungeon. if (*lev_mons <= 0) { proximity = PROX_AWAY_FROM_PLAYER; - // in that case lev_mons stays as it is + // In that case lev_mons stays as it is. } else --*lev_mons; @@ -464,36 +469,64 @@ static monster_type resolve_monster_type(monster_type mon_type, mon_type = MONS_DANCING_WEAPON; else { - // now pick a monster of the given branch and level + // Now pick a monster of the given branch and level. mon_type = pick_random_monster(place, *lev_mons, *lev_mons); } } return (mon_type); } +// A short function to check the results of near_stairs(). +// Returns 0 if the point is not near stairs. +// Returns 1 if the point is near unoccupied stairs. +// Returns 2 if the point is near player-occupied stairs. +static int _is_near_stairs(coord_def &p) +{ + int result = 0; + for (int i = -1; i <= 1; i++) + for (int j = -1; j <= 1; j++) + { + if (!in_bounds(p)) + continue; + + const dungeon_feature_type feat = grd(p); + if (is_stair(feat)) + { + // Shouldn't matter for escape hatches. + if (grid_is_escape_hatch(feat)) + continue; + + // Should there be several stairs, don't overwrite the + // player on stairs info. + if (result < 2) + result = (p == you.pos()? 2 : 1); + } + } + + return result; +} + int place_monster(mgen_data mg) { int band_size = 0; monster_type band_monsters[BIG_BAND]; // band monster types int tries = 0; - int pval = 0; dungeon_char_type stair_type = NUM_DCHAR_TYPES; int id = -1; - // (1) early out (summoned to occupied grid) + // (1) Early out (summoned to occupied grid). if (mg.use_position() && mgrd(mg.pos) != NON_MONSTER) return (false); - mg.cls = - resolve_monster_type(mg.cls, mg.proximity, mg.base_type, - mg.pos, mg.map_mask, - &stair_type, &mg.power); + mg.cls = resolve_monster_type(mg.cls, mg.proximity, mg.base_type, + mg.pos, mg.map_mask, + &stair_type, &mg.power); if (mg.cls == MONS_PROGRAM_BUG) return (false); - // (3) decide on banding (good lord!) + // (3) Decide on banding (good lord!) band_size = 1; band_monsters[0] = mg.cls; @@ -505,11 +538,13 @@ int place_monster(mgen_data mg) band_monsters[i] = _band_member( band, mg.power ); } + // Returns 2 if the monster is placed near player-occupied stairs. + int pval = _is_near_stairs(mg.pos); if (mg.proximity == PROX_NEAR_STAIRS) { - // for some cases disallow monsters on stairs + // For some cases disallow monsters on stairs. if (mons_class_is_stationary( mg.cls ) - || (pval == 2 + || (pval == 2 // Stairs occupied by player. && (mons_speed(mg.cls) == 0 || grd(mg.pos) == DNGN_LAVA || grd(mg.pos) == DNGN_DEEP_WATER))) { @@ -517,18 +552,18 @@ int place_monster(mgen_data mg) } } - // (4) for first monster, choose location. This is pretty intensive. + // (4) For first monster, choose location. This is pretty intensive. bool proxOK; bool close_to_player; - // player shoved out of the way? + // Player shoved out of the way? bool shoved = false; if (!mg.use_position()) { tries = 0; - // try to pick px, py that is + // Try to pick px, py that is // a) not occupied // b) compatible // c) in the 'correct' proximity to the player @@ -541,7 +576,7 @@ int place_monster(mgen_data mg) if (tries++ >= 45) return (false); - // placement already decided for PROX_NEAR_STAIRS + // Placement already decided for PROX_NEAR_STAIRS. if (mg.proximity != PROX_NEAR_STAIRS) mg.pos = random_in_bounds(); @@ -558,8 +593,8 @@ int place_monster(mgen_data mg) if (!unforbidden( mg.pos, mg.map_mask )) continue; - // don't generate monsters on top of teleport traps - // (how did they get there?) + // Don't generate monsters on top of teleport traps. + // (How did they get there?) int trap = trap_at_xy(mg.pos.x, mg.pos.y); if (trap >= 0) { @@ -567,7 +602,7 @@ int place_monster(mgen_data mg) continue; } - // check proximity to player + // Check proximity to player. proxOK = true; switch (mg.proximity) @@ -602,10 +637,10 @@ int place_monster(mgen_data mg) proxOK = false; break; } - // swap the monster and the player spots, unless the + // Swap the monster and the player spots, unless the // monster was generated in lava or deep water. - if (grd(mg.pos) == DNGN_LAVA || - grd(mg.pos) == DNGN_DEEP_WATER) + if (grd(mg.pos) == DNGN_LAVA + || grd(mg.pos) == DNGN_DEEP_WATER) { proxOK = false; break; @@ -633,7 +668,7 @@ int place_monster(mgen_data mg) if (id == -1) return (id); - // message to player from stairwell/gate appearance? + // Message to player from stairwell/gate appearance? if (see_grid(mg.pos) && mg.proximity == PROX_NEAR_STAIRS) { std::string msg; @@ -663,12 +698,13 @@ int place_monster(mgen_data mg) mpr(msg.c_str()); } - // special case: must update the view for monsters created in player LOS + // Special case: must update the view for monsters created + // in player LOS. viewwindow(true, false); } - // now, forget about banding if the first placement failed, or there's too - // many monsters already, or we successfully placed by stairs + // Now, forget about banding if the first placement failed, or there are + // too many monsters already, or we successfully placed by stairs. if (id >= MAX_MONSTERS - 30 || mg.proximity == PROX_NEAR_STAIRS) return (id); @@ -677,20 +713,19 @@ int place_monster(mgen_data mg) menv[id].flags |= MF_BAND_MEMBER; mgen_data band_template = mg; - // (5) for each band monster, loop call to place_monster_aux(). + // (5) For each band monster, loop call to place_monster_aux(). for (int i = 1; i < band_size; i++) { if (band_monsters[i] == MONS_PROGRAM_BUG) break; band_template.cls = band_monsters[i]; - const int band_id = - _place_monster_aux( band_template, false ); + const int band_id = _place_monster_aux( band_template, false ); if (band_id != -1 && band_id != NON_MONSTER) menv[band_id].flags |= MF_BAND_MEMBER; } - // placement of first monster, at least, was a success. + // Placement of first monster, at least, was a success. return (id); } @@ -1760,7 +1795,7 @@ int mons_place( mgen_data mg ) if (you.char_direction == GDT_ASCENDING && mg.cls == RANDOM_MONSTER && you.level_type == LEVEL_DUNGEON && !mg.summoned()) { - mg.cls = pick_zot_exit_defender(); + mg.cls = pick_zot_exit_defender(); mg.flags |= MG_PERMIT_BANDS; } @@ -1769,7 +1804,7 @@ int mons_place( mgen_data mg ) int mid = -1; - // translate level_type + // Translate level_type. switch (mg.level_type) { case LEVEL_PANDEMONIUM: @@ -1809,7 +1844,7 @@ int mons_place( mgen_data mg ) if (!(mg.flags & MG_FORCE_BEH)) player_angers_monster(creation); - // make summoned being aware of player's presence + // Make summoned being aware of player's presence. behaviour_event(creation, ME_ALERT, MHITYOU); if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3)) @@ -1824,8 +1859,10 @@ int mons_place( mgen_data mg ) static dungeon_feature_type _monster_habitat_feature(int mtype) { - return ((mtype == RANDOM_MONSTER) ? DNGN_FLOOR - : habitat2grid( mons_habitat_by_type(mtype) )); + if (mtype == RANDOM_MONSTER) + return DNGN_FLOOR; + + return habitat2grid( mons_habitat_by_type(mtype) ); } class newmons_square_find : public travel_pathfind @@ -1913,7 +1950,7 @@ coord_def find_newmons_square(int mons_class, const coord_def &p) // Might be better if we chose a space and tried to match the monster // to it in the case of RANDOM_MONSTER, that way if the target square - // is surrounded by water of lava this function would work. -- bwr + // is surrounded by water or lava this function would work. -- bwr if (empty_surrounds( p.x, p.y, spcw, 2, true, empty )) { pos.x = empty[0]; @@ -1967,25 +2004,28 @@ bool player_angers_monster(monsters *mon, bool actual) int create_monster( mgen_data mg ) { int summd = -1; - if (!(mg.force_place() - && in_bounds(mg.pos) - && mons_class_can_pass(mg.cls, grd(mg.pos)) - && mgrd(mg.pos) == NON_MONSTER - && mg.pos != you.pos())) + int type = (mons_class_is_zombified(mg.cls) ? mg.base_type + : mg.cls); + + if (!mg.force_place() + || !in_bounds(mg.pos) + || mgrd(mg.pos) != NON_MONSTER + || mg.pos == you.pos() + || !mons_class_can_pass(type, grd(mg.pos))) { - mg.pos = find_newmons_square(mg.cls, mg.pos); + mg.pos = find_newmons_square(type, mg.pos); } if (in_bounds(mg.pos)) summd = mons_place( mg ); - // determine whether creating a monster is successful (summd != -1) {dlb}: - // then handle the outcome {dlb}: + // Determine whether creating a monster is successful (summd != -1) {dlb}: + // then handle the outcome. {dlb}: if (summd == -1 && see_grid( mg.pos )) mpr("You see a puff of smoke."); - // the return value is either -1 (failure of some sort) - // or the index of the monster placed (if I read things right) {dlb} + // The return value is either -1 (failure of some sort) + // or the index of the monster placed (if I read things right). {dlb} return (summd); } @@ -1995,6 +2035,7 @@ bool empty_surrounds(int emx, int emy, dungeon_feature_type spc_wanted, FixedVector < char, 2 > &empty) { bool success; + // Assume all player summoning originates from player x,y. bool playerSummon = (emx == you.x_pos && emy == you.y_pos); diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/monspeak.cc index 42b5ece123..dde4db4341 100644 --- a/crawl-ref/source/monspeak.cc +++ b/crawl-ref/source/monspeak.cc @@ -204,7 +204,7 @@ static std::string _player_ghost_speak_str(const monsters *monster, return msg; } -// returns true if something is said +// Returns true if something is said. bool mons_speaks(const monsters *monster) { // Invisible monster tries to remain unnoticed. Unless they're diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index c17d4bf1fb..2c30a5d7d9 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -1417,10 +1417,9 @@ int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage) return val + random2avg(lfuzz + hfuzz + 1, naverage) - lfuzz; } -// returns 0 if the point is not near stairs -// returns 1 if the point is near unoccupied stairs -// returns 2 if the point is near player-occupied stairs - +// Returns 0 if the point is not near stairs. +// Returns 1 if the point is near unoccupied stairs. +// Returns 2 if the point is near player-occupied stairs. int near_stairs(const coord_def &p, int max_dist, dungeon_char_type &stair_type, branch_type &branch) @@ -1437,13 +1436,13 @@ int near_stairs(const coord_def &p, int max_dist, const dungeon_feature_type feat = grd(np); if (is_stair(feat)) { - // shouldn't happen for escape hatches + // Shouldn't happen for escape hatches. if (grid_is_escape_hatch(feat)) continue; stair_type = get_feature_dchar(feat); - // is it a branch stair? + // Is it a branch stair? for (int i = 0; i < NUM_BRANCHES; ++i) { if (branches[i].entry_stairs == feat) diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 0ccaa3aa98..97fef59e95 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -864,34 +864,32 @@ static void _handle_seen_interrupt(monsters* monster) void handle_monster_shouts(monsters* monster, bool force) { - if (!force - && (!you.turn_is_over || random2(30) < you.skills[SK_STEALTH])) - { + if (!force && (!you.turn_is_over || random2(30) < you.skills[SK_STEALTH])) + return; + + // Friendly or neutral monsters don't shout. + if (!force && (mons_friendly(monster) || mons_neutral(monster))) return; - } // Get it once, since monster might be S_RANDOM, in which case // mons_shouts() will return a different value every time. - const shout_type type = mons_shouts(monster->type); + shout_type s_type = mons_shouts(monster->type, false); // Silent monsters can give noiseless "visual shouts" if the // player can see them, in which case silence isn't checked for. - if (!force && (mons_friendly(monster) || mons_neutral(monster)) - || (type == S_SILENT && !player_monster_visible(monster)) - || (type != S_SILENT && (silenced(you.x_pos, you.y_pos) - || silenced(monster->x, monster->y)))) + if (s_type == S_SILENT && !player_monster_visible(monster) + || s_type != S_SILENT && (silenced(you.x_pos, you.y_pos) + || silenced(monster->x, monster->y))) { return; } - int noise_level = get_shout_noise_level(type); - std::string default_msg_key; + std::string default_msg_key = ""; - switch (type) + switch (s_type) { - case NUM_SHOUTS: - case S_RANDOM: - default_msg_key = "__BUGGY"; + case S_SILENT: + // No default message. break; case S_SHOUT: default_msg_key = "__SHOUT"; @@ -932,19 +930,17 @@ void handle_monster_shouts(monsters* monster, bool force) case S_HISS: default_msg_key = "__HISS"; break; + case S_DEMON_TAUNT: + default_msg_key = "__DEMON_TAUNT"; + break; default: - default_msg_key = ""; + default_msg_key = "__BUGGY"; } - // Use get_monster_data(monster->type) to bypass mon_shouts() - // replacing S_RANDOM with a random value. - if (mons_is_demon( monster->type ) && coinflip() - && (type != S_SILENT || - get_monster_data(monster->type)->shouts == S_RANDOM)) - { - noise_level = 8; - default_msg_key = "__DEMON_TAUNT"; - } + // Now that we have the message key, get a random verb and noise level + // for pandemonium lords. + if (s_type == S_DEMON_TAUNT) + s_type = mons_shouts(monster->type, true); std::string msg, suffix; std::string key = mons_type_name(monster->type, DESC_PLAIN); @@ -993,16 +989,20 @@ void handle_monster_shouts(monsters* monster, bool force) } if (default_msg_key == "__BUGGY") + { msg::streams(MSGCH_SOUND) << "You hear something buggy!" << std::endl; - else if ((msg == "" || msg == "__NONE") - && mons_shouts(monster->type) == S_SILENT) + } + else if (s_type == S_SILENT && (msg == "" || msg == "__NONE")) + { ; // No "visual shout" defined for silent monster, do nothing + } else if (msg == "") { msg::streams(MSGCH_DIAGNOSTICS) << "No shout entry for default shout type '" << default_msg_key << "'" << std::endl; + msg::streams(MSGCH_SOUND) << "You hear something buggy!" << std::endl; } @@ -1016,7 +1016,7 @@ void handle_monster_shouts(monsters* monster, bool force) } else { - msg = do_mon_str_replacements(msg, monster); + msg = do_mon_str_replacements(msg, monster, s_type); msg_channel_type channel = MSGCH_TALK; std::string param = ""; @@ -1028,7 +1028,7 @@ void handle_monster_shouts(monsters* monster, bool force) msg = msg.substr(pos + 1); } - if (mons_shouts(monster->type) == S_SILENT || param == "VISUAL") + if (s_type == S_SILENT || param == "VISUAL") channel = MSGCH_TALK_VISUAL; else if (param == "SOUND") channel = MSGCH_SOUND; @@ -1049,6 +1049,7 @@ void handle_monster_shouts(monsters* monster, bool force) msg::streams(channel) << msg << std::endl; } + const int noise_level = get_shout_noise_level(s_type); if (noise_level > 0) noisy(noise_level, monster->x, monster->y); } |