diff options
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/arena.cc | 32 | ||||
-rw-r--r-- | crawl-ref/source/arena.map | 70 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/monplace.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 103 |
7 files changed, 179 insertions, 39 deletions
diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index fdd0cc40e9..aefd29729d 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -52,6 +52,8 @@ namespace arena std::string arena_type = ""; faction faction_a(true); faction faction_b(false); + coord_def place_a, place_b; + FILE *file = NULL; int message_pos = 0; level_id place; @@ -75,6 +77,17 @@ namespace arena } } } + + for (int i = 0; i < MAX_MONSTERS; i++) + { + monsters *mon = &menv[i]; + if (!mon->alive()) + continue; + + const bool friendly = mons_friendly(mon); + // Set target to the opposite faction's home base. + mon->target = friendly ? place_b : place_a; + } } void alert_faction(bool friendly) @@ -264,6 +277,10 @@ namespace arena if (arena_type.empty()) arena_type = "default"; + const int arena_delay = strip_number_tag(spec, "delay:"); + if (arena_delay >= 0 && arena_delay < 2000) + Options.arena_delay = arena_delay; + std::string arena_place = strip_tag_prefix(spec, "arena_place:"); if (!arena_place.empty()) { @@ -313,8 +330,8 @@ namespace arena unwind_var< FixedVector<bool, NUM_MONSTERS> > uniq(you.unique_creatures); - coord_def place_a(dgn_find_feature_marker(DNGN_STONE_STAIRS_UP_I)); - coord_def place_b(dgn_find_feature_marker(DNGN_STONE_STAIRS_DOWN_I)); + place_a = dgn_find_feature_marker(DNGN_STONE_STAIRS_UP_I); + place_b = dgn_find_feature_marker(DNGN_STONE_STAIRS_DOWN_I); faction_a.place_at(place_a); faction_b.place_at(place_b); adjust_monsters(); @@ -515,8 +532,15 @@ namespace arena cursor_control coff(false); while (fight_is_on()) { - if (kbhit() && getch() == ESCAPE) - end(0, false, "Canceled contest at user request"); + if (kbhit()) + { + const int ch = getch(); + if (ch == ESCAPE || tolower(ch) == 'q' || + ch == CONTROL('G')) + { + end(0, false, "Canceled contest at user request"); + } + } viewwindow(true, false); unwind_var<coord_def> pos(you.position); diff --git a/crawl-ref/source/arena.map b/crawl-ref/source/arena.map new file mode 100644 index 0000000000..5c29a0769f --- /dev/null +++ b/crawl-ref/source/arena.map @@ -0,0 +1,70 @@ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################{{{{...{{{{{{{{################################# +################################.{{{.{{{.{.{{{{################################# +################################{{{{.{.{{{{{{{{################################# +################################{{{{{{{{{{.{{.{################################# +################################{{.{{.{{{{{{{{{################################# +################################{{{{.{{{{{{{{{{################################# +################################.{{{{{{{.{{{{{{################################# +################################.{.{{{{{{{{{{{{################################# +################################{{{{{{{.{{{{{{.################################# +################################{{{{{.{{{{{{{{{################################# +################################..{{{{{{{{.{{{{################################# +################################{.{{{{{{{{{{{{{################################# +################################{{{{.{{{{{{{{.{################################# +################################{{{{.{{{.{{{{{{################################# +################################.{{.{..{{{{{{{{################################# +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 871395b42f..afbdd7e52f 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3167,7 +3167,7 @@ const char *mons_pronoun(monster_type mon_type, pronoun_type variant, // Checks if the monster can use smiting/torment to attack without // unimpeded LOS to the player. -static bool _mons_can_smite(const monsters *monster) +bool mons_has_smite_attack(const monsters *monster) { if (monster->type == MONS_FIEND) return (true); @@ -3214,7 +3214,7 @@ bool monster_shover(const monsters *m) return (false); // Smiters profit from staying back and smiting. - if (_mons_can_smite(m)) + if (mons_has_smite_attack(m)) return (false); int mchar = me->showchar; diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index b69d594470..a7c2da68b7 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -775,9 +775,10 @@ monster_type mons_genus(int mc); monster_type mons_species(int mc); bool mons_looks_stabbable(const monsters *m); - bool mons_looks_distracted(const monsters *m); +bool mons_has_smite_attack(const monsters *monster); + bool check_mons_resist_magic(const monsters *monster, int pow); bool mons_class_is_confusable(int mc); diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index dfbdd9eb94..20d5c5f88a 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -2598,6 +2598,11 @@ void monster_pathfind::set_range(int r) range = r; } +coord_def monster_pathfind::next_pos(const coord_def &c) const +{ + return c + Compass[prev[c.x][c.y]]; +} + // The main method in the monster_pathfind class. // Returns true if a path was found, else false. bool monster_pathfind::init_pathfind(monsters *mon, coord_def dest, bool diag, diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h index 0d633aca64..8d98254c17 100644 --- a/crawl-ref/source/monplace.h +++ b/crawl-ref/source/monplace.h @@ -362,6 +362,7 @@ public: // public methods void set_range(int r); + coord_def next_pos(const coord_def &p) const; bool init_pathfind(monsters *mon, coord_def dest, bool diag = true, bool msg = false, bool pass_unmapped = false); diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index dcadfc5910..6258f57a18 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -3479,6 +3479,42 @@ static bool _handle_monster_patrolling(monsters *mon) return (false); } +static void _check_wander_target(monsters *mon, bool isPacified = false, + dungeon_feature_type can_move = DNGN_UNSEEN) +{ + // default wander behaviour + if (mon->pos() == mon->target + || mons_is_batty(mon) || !isPacified && one_chance_in(20)) + { + bool need_target = true; + + if (!can_move) + can_move = (mons_amphibious(mon)) + ? DNGN_DEEP_WATER : DNGN_SHALLOW_WATER; + + if (mon->is_travelling()) + need_target = _handle_monster_travelling(mon, can_move); + + // If we still need a target because we're not travelling + // (any more), check for patrol routes instead. + if (need_target && mon->is_patrolling()) + need_target = _handle_monster_patrolling(mon); + + // XXX: This is really dumb wander behaviour... instead of + // changing the goal square every turn, better would be to + // have the monster store a direction and have the monster + // head in that direction for a while, then shift the + // direction to the left or right. We're changing this so + // wandering monsters at least appear to have some sort of + // attention span. -- bwr + if (need_target) + { + mon->target.set(10 + random2(GXM - 10), + 10 + random2(GYM - 10)); + } + } +} + static void _arena_set_foe(monsters *mons) { const int mind = monster_index(mons); @@ -3495,7 +3531,9 @@ static void _arena_set_foe(monsters *mons) continue; const int distance = grid_distance(mons->pos(), other->pos()); - if (best_distance == -1 || distance < best_distance) + if ((best_distance == -1 || distance < best_distance) + && mons->can_see(other)) + { best_distance = distance; nearest = i; @@ -3506,12 +3544,16 @@ static void _arena_set_foe(monsters *mons) { mons->foe = nearest; mons->target = menv[nearest].pos(); + mons->behaviour = BEH_SEEK; } else { mons->foe = MHITNOT; - mons->target = mons->pos(); + mons->behaviour = BEH_WANDER; } + + if (mons->behaviour == BEH_WANDER) + _check_wander_target(mons); } //--------------------------------------------------------------- @@ -3566,8 +3608,6 @@ static void _handle_behaviour(monsters *mon) mon->foe = MHITNOT; if (mon->foe == MHITNOT || mon->foe == MHITYOU) _arena_set_foe(mon); - if (mon->behaviour == BEH_WANDER) - mon->behaviour = BEH_SEEK; return; } @@ -3584,6 +3624,7 @@ static void _handle_behaviour(monsters *mon) const dungeon_feature_type can_move = (mons_amphibious(mon)) ? DNGN_DEEP_WATER : DNGN_SHALLOW_WATER; + // Validate current target exists. if (mon->foe != MHITNOT && mon->foe != MHITYOU && !menv[mon->foe].alive()) @@ -3921,32 +3962,7 @@ static void _handle_behaviour(monsters *mon) break; } - // default wander behaviour - if (mon->pos() == mon->target - || mons_is_batty(mon) || !isPacified && one_chance_in(20)) - { - bool need_target = true; - if (mon->is_travelling()) - need_target = _handle_monster_travelling(mon, can_move); - - // If we still need a target because we're not travelling - // (any more), check for patrol routes instead. - if (need_target && patrolling) - need_target = _handle_monster_patrolling(mon); - - // XXX: This is really dumb wander behaviour... instead of - // changing the goal square every turn, better would be to - // have the monster store a direction and have the monster - // head in that direction for a while, then shift the - // direction to the left or right. We're changing this so - // wandering monsters at least appear to have some sort of - // attention span. -- bwr - if (need_target) - { - mon->target.set(10 + random2(GXM - 10), - 10 + random2(GYM - 10)); - } - } + _check_wander_target(mon, isPacified, can_move); // During their wanderings, monsters will eventually relax // their guard (stupid ones will do so faster, smart @@ -4375,6 +4391,28 @@ static void _handle_movement(monsters *monster) else { delta = monster->target - monster->pos(); + + if (crawl_state.arena) + { + const bool ranged = + mons_has_ranged_attack(monster) + || mons_has_ranged_spell(monster); + + // Smiters are happy if they have clear visibility through glass, + // but other monsters must go around. + const bool glass_ok = mons_has_smite_attack(monster); + + // Monsters in the arena are smarter than the norm and + // always pathfind to their targets. + if (delta.abs() > 2 + && (!ranged || + !monster->mon_see_grid(monster->target, !glass_ok))) + { + monster_pathfind mp; + if (mp.init_pathfind(monster, monster->target)) + delta = mp.next_pos(monster->pos()) - monster->pos(); + } + } } // Move the monster. @@ -6010,7 +6048,8 @@ static bool _handle_spell(monsters *monster, bolt &beem) // beam-type spells requiring tracers if (spell_needs_tracer(spell_cast)) { - const bool explode = spell_is_direct_explosion(spell_cast); + const bool explode = + spell_is_direct_explosion(spell_cast); fire_tracer(monster, beem, explode); // Good idea? if (mons_should_fire(beem)) @@ -6844,7 +6883,7 @@ static void _handle_monster_move(int i, monsters *monster) { // Prevents unfriendlies from nuking you from offscreen. // How nice! - if (mons_friendly(monster) || mons_near(monster)) + if (mons_friendly(monster) || mons_near(monster, monster->foe)) { // [ds] Special abilities shouldn't overwhelm spellcasting // in monsters that have both. This aims to give them both |