From 5e887cdbaca92e5706d363c22fafbe10c0de669b Mon Sep 17 00:00:00 2001 From: dshaligram Date: Tue, 24 Jul 2007 09:02:38 +0000 Subject: [1749272] Fixed view update issues: - Redraw view when entering a new level before allowing monsters on the level to act. - Monsters are redrawn on the view as and when they move, instead of postponing the view update to the end of turn. - Beam animations and monster redraws force a view update if the view is stale (such as when a beam is shown during travel and travel_delay = -1). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1925 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 2 +- crawl-ref/source/beam.cc | 5 +- crawl-ref/source/direct.h | 5 + crawl-ref/source/externs.h | 5 + crawl-ref/source/files.cc | 2 + crawl-ref/source/mon-util.cc | 25 ++++ crawl-ref/source/mon-util.h | 2 + crawl-ref/source/monstuff.cc | 17 ++- crawl-ref/source/player.cc | 3 +- crawl-ref/source/view.cc | 342 ++++++++++++++++++++++++++----------------- crawl-ref/source/view.h | 16 +- 11 files changed, 264 insertions(+), 160 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index fd23b5e1dc..efa025d4fc 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -2170,7 +2170,7 @@ static void world_reacts() // If you're wielding a rod, it'll gradually recharge. recharge_rods(); - viewwindow(1, true); + viewwindow(true, true); handle_monsters(); check_banished(); diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index fbd4c8407f..3b2975a0fb 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -170,14 +170,11 @@ void zap_animation( int colour, const monsters *mon, bool force ) if (in_los_bounds(drawx, drawy)) { + view_update(); textcolor( colour ); gotoxy( drawx, drawy ); putch( SYM_ZAP ); - -#ifdef UNIX update_screen(); -#endif - delay(50); } } diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h index 5a71ce68c0..f8ac7beafd 100644 --- a/crawl-ref/source/direct.h +++ b/crawl-ref/source/direct.h @@ -105,4 +105,9 @@ inline coord_def view2show(const coord_def &pos) return (pos - crawl_view.vlos1 + coord_def(1, 1)); } +inline coord_def grid2show(const coord_def &pos) +{ + return (view2show(grid2view(pos))); +} + #endif diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 5bdb476cbc..ceb0f5c0bc 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -769,6 +769,8 @@ public: long real_time; // real time played (in seconds) long num_turns; // number of turns taken + long last_view_update; // what turn was the view last updated? + int old_hunger; // used for hunger delta-meter (see output.cc) // Set when the character is going to a new level, to guard against levgen @@ -1023,6 +1025,9 @@ public: std::auto_ptr ghost; // Ghost information. public: + bool has_action_energy() const; + void check_redraw(const coord_def &oldpos) const; + kill_category kill_alignment() const; int foe_distance() const; diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index d2ec409aca..2b64064856 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -81,6 +81,7 @@ #include "tags.h" #include "travel.h" #include "tutorial.h" +#include "view.h" void save_level(int level_saved, level_area_type lt, branch_type where_were_you); @@ -960,6 +961,7 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode, if (timeval > 0) { you.time_taken = timeval; + viewwindow(true, false); handle_monsters(); } } diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index aee81286ff..1dc3d462fd 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -259,6 +259,12 @@ unsigned long get_mons_resists(const monsters *mon) return (resists); } +monsters *monster_at(const coord_def &pos) +{ + const int mindex = mgrd(pos); + return (mindex != NON_MONSTER? &menv[mindex] : NULL); +} + int mons_piety(const monsters *mon) { if (mon->god == GOD_NO_GOD) @@ -4200,6 +4206,25 @@ bool monsters::is_icy() const return (mons_is_icy(type)); } +bool monsters::has_action_energy() const +{ + return (speed_increment >= 80); +} + +void monsters::check_redraw(const coord_def &old) const +{ + const bool see_new = see_grid(pos()); + const bool see_old = see_grid(old); + if ((see_new || see_old) && !view_update()) + { + if (see_new) + view_update_at(pos()); + if (see_old) + view_update_at(old); + update_screen(); + } +} + ///////////////////////////////////////////////////////////////////////// // mon_enchant diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index a5802ba51a..2b69ebd91d 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -78,6 +78,8 @@ monsterentry *get_monster_data(int p_monsterid); void init_monsters( FixedVector& colour ); void init_monster_symbols(); +monsters *monster_at(const coord_def &pos); + // this is the old moname() std::string mons_type_name(int type, description_level_type desc ); diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index ff41163450..539bfe8198 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -842,9 +842,17 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) } } + const coord_def mwhere = monster->pos(); if (!hard_reset) monster_drop_ething(monster, YOU_KILL(killer) || pet_kill); monster_cleanup(monster); + + // Force redraw for monsters that die. + if (see_grid(mwhere)) + { + view_update_at(mwhere); + update_screen(); + } } // end monster_die void monster_cleanup(monsters *monster) @@ -3556,7 +3564,7 @@ static void handle_monster_move(int i, monsters *monster) monster->check_speed(); - while (monster->speed_increment >= 80) + while (monster->has_action_energy()) { // The continues & breaks are WRT this. if (!monster->alive()) break; @@ -3580,7 +3588,7 @@ static void handle_monster_move(int i, monsters *monster) } } - if (monster->type == MONS_TIAMAT && one_chance_in(3) ) + if (monster->type == MONS_TIAMAT && one_chance_in(3)) { int cols[] = { RED, WHITE, DARKGREY, GREEN, MAGENTA }; int newcol = cols[random2(sizeof(cols) / sizeof(cols[0]))]; @@ -4122,6 +4130,8 @@ static bool monster_swaps_places( monsters *mon, int mx, int my ) mgrd[cx][cy] = m2i; immobile_monster[m2i] = true; + mon->check_redraw(coord_def(cx, cy)); + mons_trap(mon); mons_trap(m2); @@ -4175,6 +4185,8 @@ static void do_move_monster(monsters *monster, int xi, int yi) items (eg ammunition) identical to those it's carrying. */ mgrd[monster->x][monster->y] = monster_index(monster); + monster->check_redraw(monster->pos() - coord_def(xi, yi)); + // monsters stepping on traps: mons_trap(monster); @@ -4576,7 +4588,6 @@ static void monster_move(monsters *monster) } } - // now, if a monster can't move in its intended direction, try // either side. If they're both good, move in whichever dir // gets it closer(farther for fleeing monsters) to its target. diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 04c9d4a776..d78516ff5f 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -4707,7 +4707,8 @@ void player::init() { birth_time = time( NULL ); real_time = 0; - num_turns = 0; + num_turns = 0L; + last_view_update = 0L; #ifdef WIZARD wizard = (Options.wiz_mode == WIZ_YES) ? true : false; diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 37efba43b8..85e780d42d 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -617,14 +617,18 @@ static bool mons_was_seen_this_turn(const monsters *mons) monsters_seen_this_turn.end()); } -static void beogh_follower_convert(monsters *monster) +inline static void beogh_follower_convert(monsters *monster) { + if (you.species != SP_HILL_ORC) + return; + + const bool is_orc = mons_species(monster->type) == MONS_ORC; // for followers of Beogh, decide whether orcs will join you - if (mons_species(monster->type) == MONS_ORC - && you.religion == GOD_BEOGH - && !(monster->flags & MF_CONVERT_ATTEMPT) - // && !mons_is_unique(monster->type) // does not work on Blork + if (you.religion == GOD_BEOGH && monster->foe == MHITYOU + && !(monster->flags & MF_CONVERT_ATTEMPT) + && is_orc + && !mons_friendly(monster) && mons_player_visible(monster) && !mons_is_sleeping(monster) && !mons_is_confused(monster) && !mons_is_paralysed(monster)) { @@ -702,10 +706,8 @@ static void beogh_follower_convert(monsters *monster) behaviour_event(monster, ME_ALERT, MHITYOU); } } - else if (mons_species(monster->type) == MONS_ORC - && you.species == SP_HILL_ORC + else if (is_orc && !(you.religion == GOD_BEOGH) -// && monster->foe == MHITYOU && monster->attitude == ATT_FRIENDLY && (monster->flags & MF_CONVERT_ATTEMPT) && (monster->flags & MF_GOD_GIFT) @@ -817,6 +819,34 @@ static void handle_monster_shouts(monsters* monster) } } +inline static bool update_monster_grid(const monsters *monster) +{ + const int ex = monster->x - you.x_pos + 9; + const int ey = monster->y - you.y_pos + 9; + + if (!player_monster_visible( monster )) + { + // ripple effect? + if (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER + && !mons_flies(monster) + && env.cgrid(monster->pos()) == EMPTY_CLOUD) + { + set_show_backup(ex, ey); + env.show[ex][ey] = DNGN_INVIS_EXPOSED; + env.show_col[ex][ey] = BLUE; + } + return (false); + } + + // mimics are always left on map + if (!mons_is_mimic( monster->type )) + set_show_backup(ex, ey); + + env.show[ex][ey] = monster->type + DNGN_START_OF_MONSTERS; + env.show_col[ex][ey] = get_mons_colour( monster ); + return (true); +} + void monster_grid(bool do_updates) { monsters *monster = NULL; @@ -836,27 +866,9 @@ void monster_grid(bool do_updates) handle_monster_shouts(monster); } - const int ex = monster->x - you.x_pos + 9; - const int ey = monster->y - you.y_pos + 9; - - if (!player_monster_visible( monster )) - { - // ripple effect? - if (grd[monster->x][monster->y] == DNGN_SHALLOW_WATER - && !mons_flies(monster) - && env.cgrid(monster->pos()) == EMPTY_CLOUD) - { - set_show_backup(ex, ey); - env.show[ex][ey] = DNGN_INVIS_EXPOSED; - env.show_col[ex][ey] = BLUE; - } + if (!update_monster_grid(monster)) continue; - } - - // mimics are always left on map - if (!mons_is_mimic( monster->type )) - set_show_backup(ex, ey); - + if (player_monster_visible(monster) && !mons_is_submerged(monster) && !mons_friendly(monster) @@ -866,9 +878,6 @@ void monster_grid(bool do_updates) monsters_seen_this_turn.insert(monster); } - env.show[ex][ey] = monster->type + DNGN_START_OF_MONSTERS; - env.show_col[ex][ey] = get_mons_colour( monster ); - beogh_follower_convert(monster); } } @@ -1010,46 +1019,42 @@ static int get_item_dngn_code(const item_def &item) } } -void item_grid() +inline static void update_item_grid(const coord_def &gp, const coord_def &ep) { - char count_x, count_y; + const item_def &eitem = mitm[igrd(gp)]; + unsigned short &ecol = env.show_col(ep); - for (count_y = (you.y_pos - 8); (count_y < you.y_pos + 9); count_y++) + const dungeon_feature_type grid = grd(gp); + if (Options.stair_item_brand && is_stair(grid)) + ecol |= COLFLAG_STAIR_ITEM; + else { - for (count_x = (you.x_pos - 8); (count_x < you.x_pos + 9); count_x++) + ecol = (grid == DNGN_SHALLOW_WATER)? CYAN : eitem.colour; + if (eitem.link != NON_ITEM) + ecol |= COLFLAG_ITEM_HEAP; + env.show(ep) = get_item_dngn_code( eitem ); + } +} + +void item_grid() +{ + coord_def gp; + for (gp.y = (you.y_pos - 8); (gp.y < you.y_pos + 9); gp.y++) + { + for (gp.x = (you.x_pos - 8); (gp.x < you.x_pos + 9); gp.x++) { - if (count_x >= 0 && count_x < GXM && count_y >= 0 && count_y < GYM) + if (in_bounds(gp)) { - if (igrd[count_x][count_y] != NON_ITEM) + if (igrd(gp) != NON_ITEM) { - const int ix = count_x - you.x_pos + 9; - const int iy = count_y - you.y_pos + 9; - if (env.show[ix][iy]) - { - const item_def &eitem = mitm[igrd[count_x][count_y]]; - unsigned short &ecol = env.show_col[ix][iy]; - - const dungeon_feature_type grid = grd[count_x][count_y]; - if (Options.stair_item_brand && is_stair(grid)) - ecol |= COLFLAG_STAIR_ITEM; - else - { - ecol = (grid == DNGN_SHALLOW_WATER)? - CYAN - : eitem.colour; - - if (eitem.link != NON_ITEM) - { - ecol |= COLFLAG_ITEM_HEAP; - } - env.show[ix][iy] = get_item_dngn_code( eitem ); - } - } + const coord_def ep = gp - you.pos() + coord_def(9, 9); + if (env.show(ep)) + update_item_grid(gp, ep); } } - } // end of "for count_y, count_x" + } } -} // end item() +} void get_item_glyph( const item_def *item, unsigned *glych, unsigned short *glycol ) @@ -1065,94 +1070,94 @@ void get_mons_glyph( const monsters *mons, unsigned *glych, get_symbol( 0, 0, mons->type + DNGN_START_OF_MONSTERS, glych, glycol ); } +inline static void update_cloud_grid(int cloudno) +{ + int which_colour = LIGHTGREY; + const int ex = env.cloud[cloudno].x - you.x_pos + 9; + const int ey = env.cloud[cloudno].y - you.y_pos + 9; + + switch (env.cloud[cloudno].type) + { + case CLOUD_FIRE: + if (env.cloud[cloudno].decay <= 20) + which_colour = RED; + else if (env.cloud[cloudno].decay <= 40) + which_colour = LIGHTRED; + else if (one_chance_in(4)) + which_colour = RED; + else if (one_chance_in(4)) + which_colour = LIGHTRED; + else + which_colour = YELLOW; + break; + + case CLOUD_STINK: + which_colour = GREEN; + break; + + case CLOUD_COLD: + if (env.cloud[cloudno].decay <= 20) + which_colour = BLUE; + else if (env.cloud[cloudno].decay <= 40) + which_colour = LIGHTBLUE; + else if (one_chance_in(4)) + which_colour = BLUE; + else if (one_chance_in(4)) + which_colour = LIGHTBLUE; + else + which_colour = WHITE; + break; + + case CLOUD_POISON: + which_colour = (one_chance_in(3) ? LIGHTGREEN : GREEN); + break; + + case CLOUD_BLUE_SMOKE: + which_colour = LIGHTBLUE; + break; + + case CLOUD_PURP_SMOKE: + which_colour = MAGENTA; + break; + + case CLOUD_MIASMA: + case CLOUD_BLACK_SMOKE: + which_colour = DARKGREY; + break; + + case CLOUD_MIST: + which_colour = EC_MIST; + break; + + default: + which_colour = LIGHTGREY; + break; + } + + set_show_backup(ex, ey); + env.show[ex][ey] = DNGN_CLOUD; + env.show_col[ex][ey] = which_colour; +} + void cloud_grid(void) { int mnc = 0; - // btw, this is also the 'default' color {dlb} - unsigned char which_colour = LIGHTGREY; - for (int s = 0; s < MAX_CLOUDS; s++) { // can anyone explain this??? {dlb} // its an optimization to avoid looking past the last cloud -bwr - if (mnc > env.cloud_no) + if (mnc >= env.cloud_no) break; if (env.cloud[s].type != CLOUD_NONE) { mnc++; - if (see_grid(env.cloud[s].x, env.cloud[s].y)) - { - const int ex = env.cloud[s].x - you.x_pos + 9; - const int ey = env.cloud[s].y - you.y_pos + 9; - - switch (env.cloud[s].type) - { - case CLOUD_FIRE: - if (env.cloud[s].decay <= 20) - which_colour = RED; - else if (env.cloud[s].decay <= 40) - which_colour = LIGHTRED; - else if (one_chance_in(4)) - which_colour = RED; - else if (one_chance_in(4)) - which_colour = LIGHTRED; - else - which_colour = YELLOW; - break; - - case CLOUD_STINK: - which_colour = GREEN; - break; - - case CLOUD_COLD: - if (env.cloud[s].decay <= 20) - which_colour = BLUE; - else if (env.cloud[s].decay <= 40) - which_colour = LIGHTBLUE; - else if (one_chance_in(4)) - which_colour = BLUE; - else if (one_chance_in(4)) - which_colour = LIGHTBLUE; - else - which_colour = WHITE; - break; - - case CLOUD_POISON: - which_colour = (one_chance_in(3) ? LIGHTGREEN : GREEN); - break; - - case CLOUD_BLUE_SMOKE: - which_colour = LIGHTBLUE; - break; - - case CLOUD_PURP_SMOKE: - which_colour = MAGENTA; - break; - - case CLOUD_MIASMA: - case CLOUD_BLACK_SMOKE: - which_colour = DARKGREY; - break; - - case CLOUD_MIST: - which_colour = EC_MIST; - break; - - default: - which_colour = LIGHTGREY; - break; - } - - set_show_backup(ex, ey); - env.show[ex][ey] = DNGN_CLOUD; - env.show_col[ex][ey] = which_colour; - } - } // end 'if != CLOUD_NONE' - } // end 'for s' loop -} // end cloud_grid() + update_cloud_grid(s); + } + } +} // Noisy now has a messenging service for giving messages to the // player is appropriate. @@ -3928,6 +3933,67 @@ static int viewmap_flash_colour() return (BLACK); } +static void update_env_show(const coord_def &gp, const coord_def &ep) +{ + // The sequence is grid, items, clouds, monsters. + env.show(ep) = grd(gp); + env.show_col(ep) = 0; + + if (igrd(gp) != NON_ITEM) + update_item_grid(gp, ep); + + const int cloud = env.cgrid(gp); + if (cloud != EMPTY_CLOUD && env.cloud[cloud].type != CLOUD_NONE) + update_cloud_grid(cloud); + + const monsters *mons = monster_at(gp); + if (mons && mons->alive()) + update_monster_grid(mons); +} + +// Updates one square of the view area. Should only be called for square +// in LOS. +void view_update_at(const coord_def &pos) +{ + if (pos == you.pos()) + return; + + const coord_def vp = grid2view(pos); + const coord_def ep = view2show(vp); + update_env_show(pos, ep); + + int object = env.show(ep); + + if (!object) + return; + + unsigned short colour = env.show_col(ep); + unsigned ch = 0; + + if (object == DNGN_SECRET_DOOR) + object = grid_secret_door_appearance( pos.x, pos.y ); + + get_symbol( pos.x, pos.y, object, &ch, &colour ); + + int flash_colour = you.flash_colour; + if (flash_colour == BLACK) + flash_colour = viewmap_flash_colour(); + + gotoxy(vp.x, vp.y); + textcolor(flash_colour? flash_colour : colour); + putwch(ch); +} + +bool view_update() +{ + if (you.num_turns > you.last_view_update) + { + viewwindow(true, false); + return (true); + } + return (false); +} + //--------------------------------------------------------------- // // viewwindow -- now unified and rolled into a single pass @@ -3961,6 +4027,7 @@ void viewwindow(bool draw_it, bool do_updates) cursor_control cs(false); const bool map = player_in_mappable_area(); + const bool draw = !you.running || Options.travel_delay > -1; int bufcount = 0; int flash_colour = you.flash_colour; @@ -4129,8 +4196,9 @@ void viewwindow(bool draw_it, bool do_updates) you.flash_colour = BLACK; // avoiding unneeded draws when running - if (!you.running || (Options.travel_delay > -1)) + if (draw) { + you.last_view_update = you.num_turns; bufcount = 0; for (count_y = 0; count_y < crawl_view.viewsz.y; count_y++) { diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index 5b6145d68b..19f0cedbd5 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -78,20 +78,6 @@ bool noisy( int loudness, int nois_x, int nois_y, const char *msg = NULL ); * *********************************************************************** */ void show_map( FixedVector& spec_place, bool travel_mode ); - -// last updated 12may2000 {dlb} -/* *********************************************************************** - * called from: acr - * *********************************************************************** */ -void viewwindow2(char draw_it, bool do_updates); - - -// last updated 12may2000 {dlb} -/* *********************************************************************** - * called from: acr - * *********************************************************************** */ -void viewwindow3(char draw_it, bool do_updates); // non-IBM graphics - // last updated 19jun2000 (gdl) /* *********************************************************************** * called from: acr view @@ -157,6 +143,8 @@ std::string screenshot(bool fullscreen = false); unsigned get_sightmap_char(int feature); unsigned get_magicmap_char(int feature); +bool view_update(); +void view_update_at(const coord_def &pos); void viewwindow(bool draw_it, bool do_updates); void fire_monster_alerts(); -- cgit v1.2.3-54-g00ecf