未验证 提交 952d25e6 编写于 作者: E Eric Pierce 提交者: GitHub

Move remaining display functions out of panels.cpp (#54432)

上级 62609324
......@@ -9,6 +9,8 @@
#include "map.h"
#include "mood_face.h"
#include "move_mode.h"
#include "mtype.h"
#include "npc.h"
#include "vehicle.h"
#include "vpart_position.h"
#include "weather.h"
......@@ -1373,3 +1375,303 @@ point display::mission_arrow_offset( const avatar &you, int width, int height )
}
}
static std::string get_compass_for_direction( const cardinal_direction dir, int max_width )
{
const int d = static_cast<int>( dir );
const monster_visible_info &mon_visible = get_avatar().get_mon_visible();
std::vector<std::pair<std::string, nc_color>> syms;
for( npc *n : mon_visible.unique_types[d] ) {
switch( n->get_attitude() ) {
case NPCATT_KILL:
syms.emplace_back( "@", c_red );
break;
case NPCATT_FOLLOW:
syms.emplace_back( "@", c_light_green );
break;
default:
syms.emplace_back( "@", c_pink );
break;
}
}
for( const std::pair<const mtype *, int> &m : mon_visible.unique_mons[d] ) {
syms.emplace_back( m.first->sym, m.first->color );
}
std::string ret;
for( int i = 0; i < static_cast<int>( syms.size() ); i++ ) {
if( i >= max_width - 1 ) {
ret += colorize( "+", c_white );
break;
}
ret += colorize( syms[i].first, syms[i].second );
}
return ret;
}
std::string display::colorized_compass_text( const cardinal_direction dir, int width )
{
if( dir == cardinal_direction::num_cardinal_directions ) {
return "";
}
return get_compass_for_direction( dir, width );
}
std::string display::colorized_compass_legend_text( int width, int height )
{
const monster_visible_info &mon_visible = get_avatar().get_mon_visible();
std::vector<std::string> names;
for( const std::vector<npc *> &nv : mon_visible.unique_types ) {
for( const npc *n : nv ) {
std::string name;
switch( n->get_attitude() ) {
case NPCATT_KILL:
name = colorize( "@", c_red );
break;
case NPCATT_FOLLOW:
name = colorize( "@", c_light_green );
break;
default:
name = colorize( "@", c_pink );
break;
}
name = string_format( "%s %s", name, n->name );
names.emplace_back( name );
}
}
std::map<const mtype *, int> mlist;
for( const auto &mv : mon_visible.unique_mons ) {
for( const std::pair<const mtype *, int> &m : mv ) {
mlist[m.first] += m.second;
}
}
for( const auto &m : mlist ) {
nc_color danger = c_dark_gray;
if( m.first->difficulty >= 30 ) {
danger = c_red;
} else if( m.first->difficulty >= 16 ) {
danger = c_light_red;
} else if( m.first->difficulty >= 8 ) {
danger = c_white;
} else if( m.first->agro > 0 ) {
danger = c_light_gray;
}
std::string name = m.second > 1 ? string_format( "%d ", m.second ) : "";
name += m.first->nname( m.second );
name = string_format( "%s %s", colorize( m.first->sym, m.first->color ), colorize( name, danger ) );
names.emplace_back( name );
}
// Split names into X lines, where X = height.
// Lines use the provided width.
// This effectively limits the text to a 'width'x'height' box.
std::string ret;
const int nsize = names.size();
for( int row = 0, nidx = 0; row < height && nidx < nsize; row++ ) {
int wavail = width;
int nwidth = utf8_width( names[nidx], true );
bool startofline = true;
while( nidx < nsize && ( wavail > nwidth || startofline ) ) {
startofline = false;
wavail -= nwidth;
ret += names[nidx];
nidx++;
if( nidx < nsize ) {
nwidth = utf8_width( names[nidx], true );
if( wavail > nwidth ) {
ret += " ";
wavail -= 2;
}
}
}
if( row < height - 1 ) {
ret += "\n";
}
}
return ret;
}
// Print monster info to the given window
void display::print_mon_info( const avatar &u, const catacurses::window &w, int hor_padding,
bool compact )
{
const monster_visible_info &mon_visible = u.get_mon_visible();
const auto &unique_types = mon_visible.unique_types;
const auto &unique_mons = mon_visible.unique_mons;
const auto &dangerous = mon_visible.dangerous;
const int width = getmaxx( w ) - 2 * hor_padding;
const int maxheight = getmaxy( w ) - 1;
const int startrow = 0;
// Print the direction headings
// Reminder:
// 7 0 1 unique_types uses these indices;
// 6 8 2 0-7 are provide by direction_from()
// 5 4 3 8 is used for local monsters (for when we explain them below)
const std::array<std::string, 8> dir_labels = {{
_( "North:" ), _( "NE:" ), _( "East:" ), _( "SE:" ),
_( "South:" ), _( "SW:" ), _( "West:" ), _( "NW:" )
}
};
std::array<int, 8> widths;
for( int i = 0; i < 8; i++ ) {
widths[i] = utf8_width( dir_labels[i] );
}
std::array<int, 8> xcoords;
const std::array<int, 8> ycoords = {{ 0, 0, 1, 2, 2, 2, 1, 0 }};
xcoords[0] = xcoords[4] = width / 3;
xcoords[1] = xcoords[3] = xcoords[2] = ( width / 3 ) * 2;
xcoords[5] = xcoords[6] = xcoords[7] = 0;
//for the alignment of the 1,2,3 rows on the right edge (East - NE)
xcoords[2] -= widths[2] - widths[1];
for( int i = 0; i < 8; i++ ) {
nc_color c = unique_types[i].empty() && unique_mons[i].empty() ? c_dark_gray
: ( dangerous[i] ? c_light_red : c_light_gray );
mvwprintz( w, point( xcoords[i] + hor_padding, ycoords[i] + startrow ), c, dir_labels[i] );
}
// Print the symbols of all monsters in all directions.
for( int i = 0; i < 8; i++ ) {
point pr( xcoords[i] + widths[i] + 1, ycoords[i] + startrow );
// The list of symbols needs a space on each end.
int symroom = ( width / 3 ) - widths[i] - 2;
const int typeshere_npc = unique_types[i].size();
const int typeshere_mon = unique_mons[i].size();
const int typeshere = typeshere_mon + typeshere_npc;
for( int j = 0; j < typeshere && j < symroom; j++ ) {
nc_color c;
std::string sym;
if( symroom < typeshere && j == symroom - 1 ) {
// We've run out of room!
c = c_white;
sym = "+";
} else if( j < typeshere_npc ) {
switch( unique_types[i][j]->get_attitude() ) {
case NPCATT_KILL:
c = c_red;
break;
case NPCATT_FOLLOW:
c = c_light_green;
break;
default:
c = c_pink;
break;
}
sym = "@";
} else {
const mtype &mt = *unique_mons[i][j - typeshere_npc].first;
c = mt.color;
sym = mt.sym;
}
mvwprintz( w, pr, c, sym );
pr.x++;
}
}
// Now we print their full names!
struct nearest_loc_and_cnt {
int nearest_loc;
int cnt;
};
std::map<const mtype *, nearest_loc_and_cnt> all_mons;
for( int loc = 0; loc < 9; loc++ ) {
for( const std::pair<const mtype *, int> &mon : unique_mons[loc] ) {
const auto mon_it = all_mons.find( mon.first );
if( mon_it == all_mons.end() ) {
all_mons.emplace( mon.first, nearest_loc_and_cnt{ loc, mon.second } );
} else {
// 8 being the nearest location (local monsters)
mon_it->second.nearest_loc = std::max( mon_it->second.nearest_loc, loc );
mon_it->second.cnt += mon.second;
}
}
}
std::vector<std::pair<const mtype *, int>> mons_at[9];
for( const std::pair<const mtype *const, nearest_loc_and_cnt> &mon : all_mons ) {
mons_at[mon.second.nearest_loc].emplace_back( mon.first, mon.second.cnt );
}
// Rows 0-2 are for labels.
// Start monster names on row 3
point pr( hor_padding, 3 + startrow );
// In non-compact mode, leave a blank line
if( !compact ) {
pr.y++;
}
// Print monster names, starting with those at location 8 (nearby).
for( int j = 8; j >= 0 && pr.y < maxheight; j-- ) {
// Separate names by some number of spaces (more for local monsters).
int namesep = j == 8 ? 2 : 1;
for( const std::pair<const mtype *, int> &mon : mons_at[j] ) {
const mtype *const type = mon.first;
const int count = mon.second;
if( pr.y >= maxheight ) {
// no space to print to anyway
break;
}
const mtype &mt = *type;
std::string name = mt.nname( count );
// Some languages don't have plural forms, but we want to always
// omit 1.
if( count != 1 ) {
name = string_format( pgettext( "monster count and name", "%1$d %2$s" ),
count, name );
}
// Move to the next row if necessary. (The +2 is for the "Z ").
if( pr.x + 2 + utf8_width( name ) >= width ) {
pr.y++;
pr.x = hor_padding;
}
if( pr.y < maxheight ) { // Don't print if we've overflowed
mvwprintz( w, pr, mt.color, mt.sym );
pr.x += 2; // symbol and space
nc_color danger = c_dark_gray;
if( mt.difficulty >= 30 ) {
danger = c_red;
} else if( mt.difficulty >= 16 ) {
danger = c_light_red;
} else if( mt.difficulty >= 8 ) {
danger = c_white;
} else if( mt.agro > 0 ) {
danger = c_light_gray;
}
mvwprintz( w, pr, danger, name );
pr.x += utf8_width( name ) + namesep;
}
}
}
}
std::pair<std::string, nc_color> display::weather_text_color( const Character &u )
{
if( u.pos().z < 0 ) {
return std::make_pair( _( "Underground" ), c_light_gray );
} else {
weather_manager &weather = get_weather();
std::string weather_text = weather.weather_id->name.translated();
nc_color weather_color = weather.weather_id->color;
return std::make_pair( weather_text, weather_color );
}
}
std::pair<std::string, nc_color> display::wind_text_color( const Character &u )
{
const oter_id &cur_om_ter = overmap_buffer.ter( u.global_omt_location() );
weather_manager &weather = get_weather();
double windpower = get_local_windpower( weather.windspeed, cur_om_ter,
u.pos(), weather.winddirection, g->is_sheltered( u.pos() ) );
// Wind descriptor followed by a directional arrow
const std::string wind_text = get_wind_desc( windpower ) + " " + get_wind_arrow(
weather.winddirection );
return std::make_pair( wind_text, get_wind_color( windpower ) );
}
......@@ -1101,20 +1101,6 @@ static void draw_env_compact( const draw_args &args )
wnoutrefresh( w );
}
std::pair<std::string, nc_color> display::wind_text_color( const Character &u )
{
const oter_id &cur_om_ter = overmap_buffer.ter( u.global_omt_location() );
weather_manager &weather = get_weather();
double windpower = get_local_windpower( weather.windspeed, cur_om_ter,
u.pos(), weather.winddirection, g->is_sheltered( u.pos() ) );
// Wind descriptor followed by a directional arrow
const std::string wind_text = get_wind_desc( windpower ) + " " + get_wind_arrow(
weather.winddirection );
return std::make_pair( wind_text, get_wind_color( windpower ) );
}
static void render_wind( const draw_args &args, const std::string &formatstr )
{
const avatar &u = args._ava;
......@@ -1140,132 +1126,6 @@ static void draw_wind_padding( const draw_args &args )
render_wind( args, " %s: " );
}
std::pair<std::string, nc_color> display::weather_text_color( const Character &u )
{
if( u.pos().z < 0 ) {
return std::make_pair( _( "Underground" ), c_light_gray );
} else {
weather_manager &weather = get_weather();
std::string weather_text = weather.weather_id->name.translated();
nc_color weather_color = weather.weather_id->color;
return std::make_pair( weather_text, weather_color );
}
}
static std::string get_compass_for_direction( const cardinal_direction dir, int max_width )
{
const int d = static_cast<int>( dir );
const monster_visible_info &mon_visible = get_avatar().get_mon_visible();
std::vector<std::pair<std::string, nc_color>> syms;
for( npc *n : mon_visible.unique_types[d] ) {
switch( n->get_attitude() ) {
case NPCATT_KILL:
syms.emplace_back( "@", c_red );
break;
case NPCATT_FOLLOW:
syms.emplace_back( "@", c_light_green );
break;
default:
syms.emplace_back( "@", c_pink );
break;
}
}
for( const std::pair<const mtype *, int> &m : mon_visible.unique_mons[d] ) {
syms.emplace_back( m.first->sym, m.first->color );
}
std::string ret;
for( int i = 0; i < static_cast<int>( syms.size() ); i++ ) {
if( i >= max_width - 1 ) {
ret += colorize( "+", c_white );
break;
}
ret += colorize( syms[i].first, syms[i].second );
}
return ret;
}
std::string display::colorized_compass_text( const cardinal_direction dir, int width )
{
if( dir == cardinal_direction::num_cardinal_directions ) {
return "";
}
return get_compass_for_direction( dir, width );
}
std::string display::colorized_compass_legend_text( int width, int height )
{
const monster_visible_info &mon_visible = get_avatar().get_mon_visible();
std::vector<std::string> names;
for( const std::vector<npc *> &nv : mon_visible.unique_types ) {
for( const npc *n : nv ) {
std::string name;
switch( n->get_attitude() ) {
case NPCATT_KILL:
name = colorize( "@", c_red );
break;
case NPCATT_FOLLOW:
name = colorize( "@", c_light_green );
break;
default:
name = colorize( "@", c_pink );
break;
}
name = string_format( "%s %s", name, n->name );
names.emplace_back( name );
}
}
std::map<const mtype *, int> mlist;
for( const auto &mv : mon_visible.unique_mons ) {
for( const std::pair<const mtype *, int> &m : mv ) {
mlist[m.first] += m.second;
}
}
for( const auto &m : mlist ) {
nc_color danger = c_dark_gray;
if( m.first->difficulty >= 30 ) {
danger = c_red;
} else if( m.first->difficulty >= 16 ) {
danger = c_light_red;
} else if( m.first->difficulty >= 8 ) {
danger = c_white;
} else if( m.first->agro > 0 ) {
danger = c_light_gray;
}
std::string name = m.second > 1 ? string_format( "%d ", m.second ) : "";
name += m.first->nname( m.second );
name = string_format( "%s %s", colorize( m.first->sym, m.first->color ), colorize( name, danger ) );
names.emplace_back( name );
}
// Split names into X lines, where X = height.
// Lines use the provided width.
// This effectively limits the text to a 'width'x'height' box.
std::string ret;
const int nsize = names.size();
for( int row = 0, nidx = 0; row < height && nidx < nsize; row++ ) {
int wavail = width;
int nwidth = utf8_width( names[nidx], true );
bool startofline = true;
while( nidx < nsize && ( wavail > nwidth || startofline ) ) {
startofline = false;
wavail -= nwidth;
ret += names[nidx];
nidx++;
if( nidx < nsize ) {
nwidth = utf8_width( names[nidx], true );
if( wavail > nwidth ) {
ret += " ";
wavail -= 2;
}
}
}
if( row < height - 1 ) {
ret += "\n";
}
}
return ret;
}
static void draw_health_classic( const draw_args &args )
{
const avatar &u = args._ava;
......@@ -1454,166 +1314,6 @@ static void draw_mminimap( const draw_args &args )
}
#endif
// Print monster info to the given window
void display::print_mon_info( const avatar &u, const catacurses::window &w, int hor_padding,
bool compact )
{
const monster_visible_info &mon_visible = u.get_mon_visible();
const auto &unique_types = mon_visible.unique_types;
const auto &unique_mons = mon_visible.unique_mons;
const auto &dangerous = mon_visible.dangerous;
const int width = getmaxx( w ) - 2 * hor_padding;
const int maxheight = getmaxy( w ) - 1;
const int startrow = 0;
// Print the direction headings
// Reminder:
// 7 0 1 unique_types uses these indices;
// 6 8 2 0-7 are provide by direction_from()
// 5 4 3 8 is used for local monsters (for when we explain them below)
const std::array<std::string, 8> dir_labels = {{
_( "North:" ), _( "NE:" ), _( "East:" ), _( "SE:" ),
_( "South:" ), _( "SW:" ), _( "West:" ), _( "NW:" )
}
};
std::array<int, 8> widths;
for( int i = 0; i < 8; i++ ) {
widths[i] = utf8_width( dir_labels[i] );
}
std::array<int, 8> xcoords;
const std::array<int, 8> ycoords = {{ 0, 0, 1, 2, 2, 2, 1, 0 }};
xcoords[0] = xcoords[4] = width / 3;
xcoords[1] = xcoords[3] = xcoords[2] = ( width / 3 ) * 2;
xcoords[5] = xcoords[6] = xcoords[7] = 0;
//for the alignment of the 1,2,3 rows on the right edge (East - NE)
xcoords[2] -= widths[2] - widths[1];
for( int i = 0; i < 8; i++ ) {
nc_color c = unique_types[i].empty() && unique_mons[i].empty() ? c_dark_gray
: ( dangerous[i] ? c_light_red : c_light_gray );
mvwprintz( w, point( xcoords[i] + hor_padding, ycoords[i] + startrow ), c, dir_labels[i] );
}
// Print the symbols of all monsters in all directions.
for( int i = 0; i < 8; i++ ) {
point pr( xcoords[i] + widths[i] + 1, ycoords[i] + startrow );
// The list of symbols needs a space on each end.
int symroom = ( width / 3 ) - widths[i] - 2;
const int typeshere_npc = unique_types[i].size();
const int typeshere_mon = unique_mons[i].size();
const int typeshere = typeshere_mon + typeshere_npc;
for( int j = 0; j < typeshere && j < symroom; j++ ) {
nc_color c;
std::string sym;
if( symroom < typeshere && j == symroom - 1 ) {
// We've run out of room!
c = c_white;
sym = "+";
} else if( j < typeshere_npc ) {
switch( unique_types[i][j]->get_attitude() ) {
case NPCATT_KILL:
c = c_red;
break;
case NPCATT_FOLLOW:
c = c_light_green;
break;
default:
c = c_pink;
break;
}
sym = "@";
} else {
const mtype &mt = *unique_mons[i][j - typeshere_npc].first;
c = mt.color;
sym = mt.sym;
}
mvwprintz( w, pr, c, sym );
pr.x++;
}
}
// Now we print their full names!
struct nearest_loc_and_cnt {
int nearest_loc;
int cnt;
};
std::map<const mtype *, nearest_loc_and_cnt> all_mons;
for( int loc = 0; loc < 9; loc++ ) {
for( const std::pair<const mtype *, int> &mon : unique_mons[loc] ) {
const auto mon_it = all_mons.find( mon.first );
if( mon_it == all_mons.end() ) {
all_mons.emplace( mon.first, nearest_loc_and_cnt{ loc, mon.second } );
} else {
// 8 being the nearest location (local monsters)
mon_it->second.nearest_loc = std::max( mon_it->second.nearest_loc, loc );
mon_it->second.cnt += mon.second;
}
}
}
std::vector<std::pair<const mtype *, int>> mons_at[9];
for( const std::pair<const mtype *const, nearest_loc_and_cnt> &mon : all_mons ) {
mons_at[mon.second.nearest_loc].emplace_back( mon.first, mon.second.cnt );
}
// Rows 0-2 are for labels.
// Start monster names on row 3
point pr( hor_padding, 3 + startrow );
// In non-compact mode, leave a blank line
if( !compact ) {
pr.y++;
}
// Print monster names, starting with those at location 8 (nearby).
for( int j = 8; j >= 0 && pr.y < maxheight; j-- ) {
// Separate names by some number of spaces (more for local monsters).
int namesep = j == 8 ? 2 : 1;
for( const std::pair<const mtype *, int> &mon : mons_at[j] ) {
const mtype *const type = mon.first;
const int count = mon.second;
if( pr.y >= maxheight ) {
// no space to print to anyway
break;
}
const mtype &mt = *type;
std::string name = mt.nname( count );
// Some languages don't have plural forms, but we want to always
// omit 1.
if( count != 1 ) {
name = string_format( pgettext( "monster count and name", "%1$d %2$s" ),
count, name );
}
// Move to the next row if necessary. (The +2 is for the "Z ").
if( pr.x + 2 + utf8_width( name ) >= width ) {
pr.y++;
pr.x = hor_padding;
}
if( pr.y < maxheight ) { // Don't print if we've overflowed
mvwprintz( w, pr, mt.color, mt.sym );
pr.x += 2; // symbol and space
nc_color danger = c_dark_gray;
if( mt.difficulty >= 30 ) {
danger = c_red;
} else if( mt.difficulty >= 16 ) {
danger = c_light_red;
} else if( mt.difficulty >= 8 ) {
danger = c_white;
} else if( mt.agro > 0 ) {
danger = c_light_gray;
}
mvwprintz( w, pr, danger, name );
pr.x += utf8_width( name ) + namesep;
}
}
}
}
static void draw_compass( const draw_args &args )
{
const avatar &u = args._ava;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册