Skip to content

Commit

Permalink
Merge pull request #74700 from ehughsbaird/cleaner-overmap-drawing
Browse files Browse the repository at this point in the history
Clean up overmap drawing code and consolidate to one function
  • Loading branch information
Maleclypse authored Jun 28, 2024
2 parents d18e0a0 + 7ef7a79 commit d054031
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 484 deletions.
98 changes: 17 additions & 81 deletions src/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,74 +1104,6 @@ std::pair<std::string, nc_color> display::overmap_note_symbol_color( const std::
return std::make_pair( ter_sym, ter_color );
}

// Return an overmap tile symbol and color for an omt relatively near the avatar's position.
// The edge_tile flag says this omt is at the edge of the map and may point to an off-map mission.
// The found_mi (reference) is set to true to tell the calling function if a mission marker was found.
std::pair<std::string, nc_color> display::overmap_tile_symbol_color( const avatar &u,
const tripoint_abs_omt &omt, const bool edge_tile, bool &found_mi )
{
std::string ter_sym;
nc_color ter_color = c_light_gray;

// Terrain color and symbol to use for this point
const bool seen = overmap_buffer.seen( omt );
if( overmap_buffer.has_note( omt ) ) {
const std::string &note_text = overmap_buffer.note( omt );
std::pair<std::string, nc_color> sym_color = display::overmap_note_symbol_color( note_text );
ter_sym = sym_color.first;
ter_color = sym_color.second;
} else if( !seen ) {
// Always gray # for unseen
ter_sym = "#";
ter_color = c_dark_gray;
} else if( overmap_buffer.has_vehicle( omt ) ) {
ter_color = c_cyan;
ter_sym = overmap_buffer.get_vehicle_ter_sym( omt );
} else {
// Otherwise, get symbol and color appropriate for the terrain
const oter_id &cur_ter = overmap_buffer.ter( omt );
ter_sym = cur_ter->get_symbol();
if( overmap_buffer.is_explored( omt ) ) {
ter_color = c_dark_gray;
} else {
ter_color = cur_ter->get_color();
}
}
const tripoint_abs_omt target = u.get_active_mission_target();
const tripoint_abs_omt u_loc = u.global_omt_location();

// Check if there is a valid mission target, and avatar is not there already
if( target != overmap::invalid_tripoint && target.xy() != u_loc.xy() ) {
// highlight it with a red background (if on-map)
// or point towards it with a red asterisk (if off-map)
if( target.xy() == omt.xy() ) {
ter_color = red_background( ter_color );
found_mi = true;
} else if( edge_tile ) {
std::vector<tripoint_abs_omt> plist = line_to( u_loc, target );
if( std::find( plist.begin(), plist.end(), omt ) != plist.end() ) {
ter_color = c_red;
ter_sym = "*";
found_mi = true;
}
}
}

// Show hordes on minimap, leaving a one-tile space around the player
if( std::abs( u_loc.x() - omt.x() ) > 1 || std::abs( u_loc.y() - omt.y() ) > 1 ) {
const int horde_size = overmap_buffer.get_horde_size( omt );
const int sight_points = u.overmap_sight_range( g->light_level( u.posz() ) );
if( horde_size >= HORDE_VISIBILITY_SIZE && overmap_buffer.seen( omt ) &&
u.overmap_los( omt, sight_points ) ) {
// Draw green Z or z
ter_sym = horde_size > HORDE_VISIBILITY_SIZE * 2 ? 'Z' : 'z';
ter_color = c_green;
}
}

return std::make_pair( ter_sym, ter_color );
}

std::string display::colorized_overmap_text( const avatar &u, const int width, const int height )
{
std::string overmap_text;
Expand All @@ -1185,33 +1117,37 @@ std::string display::colorized_overmap_text( const avatar &u, const int width, c
return disp_om_cache.get_val();
}

// Remember when mission indicator is found, so we don't draw it more than once
bool found_mi = false;
// Figure out extents of the map area, so we know where the edges are
const int left = -( width / 2 );
const int right = width + left - 1;
const int top = -( height / 2 );
const int bottom = height + top - 1;

oter_display_options opts( center_xyz, u.overmap_sight_range( g->light_level( u.posz() ) ) );
opts.showhordes = true;
if( mission_xyz != overmap::invalid_tripoint ) {
opts.mission_target = mission_xyz;
}
opts.mission_inbounds = ( mission_xyz.x() >= center_xyz.x() + left &&
mission_xyz.x() <= center_xyz.x() + right &&
mission_xyz.y() >= center_xyz.y() + top &&
mission_xyz.y() <= center_xyz.y() + bottom );
opts.hilite_pc = true;
opts.hilite_mission = true;

// Scan each row of overmap tiles
for( int row = top; row <= bottom; row++ ) {
// Scan across the width of the row
for( int col = left; col <= right; col++ ) {
// Is this point along the border of the overmap text area we have to work with?
// If so, overmap_tile_symbol_color may draw a mission indicator at this point.
const bool edge = !found_mi && !( mission_xyz.x() >= center_xyz.x() + left &&
mission_xyz.x() <= center_xyz.x() + right &&
mission_xyz.y() >= center_xyz.y() + top &&
mission_xyz.y() <= center_xyz.y() + bottom ) &&
( row == top || row == bottom || col == left || col == right );
// Get colorized symbol for this point
const tripoint_abs_omt omt( center_xyz.xy() + point( col, row ), here.get_abs_sub().z() );
std::pair<std::string, nc_color> sym_color = display::overmap_tile_symbol_color( u, omt, edge,
found_mi );

// Highlight player character location in the center
if( row == 0 && col == 0 ) {
sym_color.second = hilite( sym_color.second );
}
oter_display_args args( overmap_buffer.seen( omt ) );
args.edge_tile = ( row == top || row == bottom || col == left || col == right );

std::pair<std::string, nc_color> sym_color = oter_symbol_and_color( omt, args, opts );

// Append the colorized symbol for this point to the map
overmap_text += colorize( sym_color.first, sym_color.second );
Expand Down
206 changes: 0 additions & 206 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4223,212 +4223,6 @@ void game::draw_veh_dir_indicator( bool next )
}
}

void game::draw_minimap()
{

// Draw the box
werase( w_minimap );
draw_border( w_minimap );

const tripoint_abs_omt curs = u.global_omt_location();
const point_abs_omt curs2( curs.xy() );
const tripoint_abs_omt targ = u.get_active_mission_target();
bool drew_mission = targ == overmap::invalid_tripoint;

const int levz = m.get_abs_sub().z();
for( int i = -2; i <= 2; i++ ) {
for( int j = -2; j <= 2; j++ ) {
const point_abs_omt om( curs2 + point( i, j ) );
nc_color ter_color;
tripoint_abs_omt omp( om, levz );
std::string ter_sym;
const bool seen = overmap_buffer.seen( omp );
if( overmap_buffer.has_note( omp ) ) {

const std::string &note_text = overmap_buffer.note( omp );

ter_color = c_yellow;
ter_sym = "N";

int symbolIndex = note_text.find( ':' );
int colorIndex = note_text.find( ';' );

bool symbolFirst = symbolIndex < colorIndex;

if( colorIndex > -1 && symbolIndex > -1 ) {
if( symbolFirst ) {
if( colorIndex > 4 ) {
colorIndex = -1;
}
if( symbolIndex > 1 ) {
symbolIndex = -1;
colorIndex = -1;
}
} else {
if( symbolIndex > 4 ) {
symbolIndex = -1;
}
if( colorIndex > 2 ) {
colorIndex = -1;
}
}
} else if( colorIndex > 2 ) {
colorIndex = -1;
} else if( symbolIndex > 1 ) {
symbolIndex = -1;
}

if( symbolIndex > -1 ) {
int symbolStart = 0;
if( colorIndex > -1 && !symbolFirst ) {
symbolStart = colorIndex + 1;
}
ter_sym = note_text.substr( symbolStart, symbolIndex - symbolStart ).c_str()[0];
}

if( colorIndex > -1 ) {

int colorStart = 0;

if( symbolIndex > -1 && symbolFirst ) {
colorStart = symbolIndex + 1;
}

std::string sym = note_text.substr( colorStart, colorIndex - colorStart );

if( sym.length() == 2 ) {
if( sym == "br" ) {
ter_color = c_brown;
} else if( sym == "lg" ) {
ter_color = c_light_gray;
} else if( sym == "dg" ) {
ter_color = c_dark_gray;
}
} else {
char colorID = sym.c_str()[0];
if( colorID == 'r' ) {
ter_color = c_light_red;
} else if( colorID == 'R' ) {
ter_color = c_red;
} else if( colorID == 'g' ) {
ter_color = c_light_green;
} else if( colorID == 'G' ) {
ter_color = c_green;
} else if( colorID == 'b' ) {
ter_color = c_light_blue;
} else if( colorID == 'B' ) {
ter_color = c_blue;
} else if( colorID == 'W' ) {
ter_color = c_white;
} else if( colorID == 'C' ) {
ter_color = c_cyan;
} else if( colorID == 'c' ) {
ter_color = c_light_cyan;
} else if( colorID == 'P' ) {
ter_color = c_pink;
} else if( colorID == 'm' ) {
ter_color = c_magenta;
}
}
}
} else if( !seen ) {
ter_sym = " ";
ter_color = c_black;
} else if( overmap_buffer.has_vehicle( omp ) ) {
ter_color = c_cyan;
ter_sym = overmap_buffer.get_vehicle_ter_sym( omp );
} else {
const oter_id &cur_ter = overmap_buffer.ter( omp );
ter_sym = cur_ter->get_symbol();
if( overmap_buffer.is_explored( omp ) ) {
ter_color = c_dark_gray;
} else {
ter_color = cur_ter->get_color();
}
}
if( !drew_mission && targ.xy() == omp.xy() ) {
// If there is a mission target, and it's not on the same
// overmap terrain as the player character, mark it.
// TODO: Inform player if the mission is above or below
drew_mission = true;
if( i != 0 || j != 0 ) {
ter_color = red_background( ter_color );
}
}
if( i == 0 && j == 0 ) {
mvwputch_hi( w_minimap, point( 3, 3 ), ter_color, ter_sym );
} else {
mvwputch( w_minimap, point( 3 + i, 3 + j ), ter_color, ter_sym );
}
}
}

// Print arrow to mission if we have one!
if( !drew_mission ) {
double slope = curs2.x() != targ.x() ?
static_cast<double>( targ.y() - curs2.y() ) / ( targ.x() - curs2.x() ) : 4;

if( curs2.x() == targ.x() || std::fabs( slope ) > 3.5 ) { // Vertical slope
if( targ.y() > curs2.y() ) {
mvwputch( w_minimap, point( 3, 6 ), c_red, "*" );
} else {
mvwputch( w_minimap, point( 3, 0 ), c_red, "*" );
}
} else {
point arrow( point_north_west );
if( std::fabs( slope ) >= 1. ) { // y diff is bigger!
arrow.y = targ.y() > curs2.y() ? 6 : 0;
arrow.x =
static_cast<int>( 3 + 3 * ( targ.y() > curs2.y() ? slope : ( 0 - slope ) ) );
if( arrow.x < 0 ) {
arrow.x = 0;
}
if( arrow.x > 6 ) {
arrow.x = 6;
}
} else {
arrow.x = targ.x() > curs2.x() ? 6 : 0;
arrow.y = static_cast<int>( 3 + 3 * ( targ.x() > curs2.x() ? slope : -slope ) );
if( arrow.y < 0 ) {
arrow.y = 0;
}
if( arrow.y > 6 ) {
arrow.y = 6;
}
}
char glyph = '*';
if( targ.z() > u.posz() ) {
glyph = '^';
} else if( targ.z() < u.posz() ) {
glyph = 'v';
}

mvwputch( w_minimap, arrow, c_red, glyph );
}
}

Character &player_character = get_player_character();
const int sight_points = player_character.overmap_sight_range( g->light_level(
player_character.posz() ) );
for( int i = -3; i <= 3; i++ ) {
for( int j = -3; j <= 3; j++ ) {
if( i > -3 && i < 3 && j > -3 && j < 3 ) {
continue; // only do hordes on the border, skip inner map
}
const tripoint_abs_omt omp( curs2 + point( i, j ), levz );
if( overmap_buffer.get_horde_size( omp ) >= HORDE_VISIBILITY_SIZE ) {
if( overmap_buffer.seen( omp )
&& player_character.overmap_los( omp, sight_points ) ) {
mvwputch( w_minimap, point( i + 3, j + 3 ), c_green,
overmap_buffer.get_horde_size( omp ) > HORDE_VISIBILITY_SIZE * 2 ? 'Z' : 'z' );
}
}
}
}

wnoutrefresh( w_minimap );
}

float game::natural_light_level( const int zlev ) const
{
// ignore while underground or above limits
Expand Down
1 change: 0 additions & 1 deletion src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,6 @@ class game
bool is_game_over(); // Returns true if the player quit or died
void bury_screen() const;// Bury a dead character (record their last words)
void death_screen(); // Display our stats, "GAME OVER BOO HOO"
void draw_minimap(); // Draw the 5x5 minimap
public:
/**
* If there is a robot (that can be disabled), query the player
Expand Down
Loading

0 comments on commit d054031

Please sign in to comment.