added some explanatory tooltips for some unit attributes on sidebar

This commit is contained in:
uid68803 2003-12-30 17:24:46 +00:00
parent 7b2d7fb9cd
commit 541e1bc669
9 changed files with 164 additions and 58 deletions

View file

@ -145,15 +145,21 @@ height=600
xanchor=right xanchor=right
yanchor=fixed yanchor=fixed
[/unit_traits] [/unit_traits]
[unit_status] [unit_abilities]
font_size=14 font_size=14
rect=897,514,1024,530 rect=897,514,1024,530
xanchor=right xanchor=right
yanchor=fixed yanchor=fixed
[/unit_abilities]
[unit_status]
font_size=14
rect=897,530,1024,546
xanchor=right
yanchor=fixed
[/unit_status] [/unit_status]
[unit_moves] [unit_moves]
font_size=14 font_size=14
rect=897,530,1024,546 rect=897,546,1024,562
prefix=movement prefix=movement
prefix_literal=": " prefix_literal=": "
xanchor=right xanchor=right
@ -161,7 +167,7 @@ height=600
[/unit_moves] [/unit_moves]
[unit_hp] [unit_hp]
font_size=14 font_size=14
rect=897,546,1024,562 rect=897,562,1024,578
prefix=hp prefix=hp
prefix_literal=": " prefix_literal=": "
xanchor=right xanchor=right
@ -169,7 +175,7 @@ height=600
[/unit_hp] [/unit_hp]
[unit_xp] [unit_xp]
font_size=14 font_size=14
rect=897,562,1024,578 rect=897,578,1024,594
prefix=xp prefix=xp
prefix_literal=": " prefix_literal=": "
xanchor=right xanchor=right
@ -177,7 +183,7 @@ height=600
[/unit_xp] [/unit_xp]
[unit_weapons] [unit_weapons]
font_size=12 font_size=12
rect=897,578,1024,690 rect=897,594,1024,706
xanchor=right xanchor=right
yanchor=fixed yanchor=fixed
[/unit_weapons] [/unit_weapons]

View file

@ -125,6 +125,58 @@ EASY="Fighter (easy)"
NORMAL="*Hero (medium)" NORMAL="*Hero (medium)"
HARD="Champion (hard)" HARD="Champion (hard)"
lawful_description="Lawful units fight better at day, and worse at night.
Day: +25% Damage
Night: -25% Damage"
neutral_description="Neutral units are unaffected by day and night, fighting equally well under both conditions."
chaotic_description="Chaotic units fight better at night, and worse at day.
Day: -25% Damage
Night: +25% Damage"
invisible_description="This unit is invisible. It cannot be seen or attacked by enemy units."
slowed_description="This unit has been slowed. It moves at half normal speed and receives one less attack than normal in combat."
poisoned_description="This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the 'cures' ability.
Units cannot be killed by poison alone. The poison will not reduce it below 1 HP."
heals_description="Heals:
Allows the unit to heal adjacent friendly units at the beginning of the turn.
A unit cared for by a healer may heal up to 4 HP per turn.
A healer may heal a total of 8 HP per turn, for all units it cares for.
A poisoned unit cannot be cured of its poison by a healer, and must seek the care of a village or a unit that can cure."
cures_description="Cures:
This unit combines herbal remedies with magic to heal units more quickly than is normally possible on the battlefield.
This unit will care for all adjacent friendly units that are injured at the beginning of the turn.
A unit cared for by a curer may heal up to 8 HP per turn.
A curer may heal a total of 18 HP per turn, for all units it cares for.
A curer can cure a unit of poison, although that unit will receive no additional healing on the turn it is cured of the poison."
teleport_description="Teleport:
This unit may teleport between any two friendly villages instantly."
leadership_description="Leadership:
This unit can lead friendly units that are next to it, making them fight better.
Adjacent friendly units of lower level will do more damage in battle."
ambush_description="Ambush:
This unit can hide in forest, and remain undetected by its enemies.
Enemy units cannot see or attack this unit when it is in forest, except for any turn immediately after this unit has attacked."
illuminates_description="Illuminates:
This unit illuminates the surrounding area, making lawful units fight better, and chaotic units fight worse.
Any units adjacent to this unit will fight as if it were dusk when it is night, and as if it were day when it is dusk."
skirmisher_description="Skirmishes:
This unit is skilled in moving past enemies quickly, and ignores all Enemy Zones of Control."
no_leader_to_recruit="You don't have a leader to recruit with." no_leader_to_recruit="You don't have a leader to recruit with."
leader_not_on_start="You must have your leader on a keep to recruit or recall units." leader_not_on_start="You must have your leader on a keep to recruit or recall units."
no_recruit_location="There are no vacant castle tiles in which to recruit a unit." no_recruit_location="There are no vacant castle tiles in which to recruit a unit."

View file

@ -751,6 +751,8 @@ void display::draw_report(reports::TYPE report_num)
tooltips::clear_tooltips(rect); tooltips::clear_tooltips(rect);
SDL_Rect area = rect;
if(report.text.empty() == false) { if(report.text.empty() == false) {
std::string str = item->prefix(); std::string str = item->prefix();
@ -764,7 +766,11 @@ void display::draw_report(reports::TYPE report_num)
str += report.text.substr(nchop) + item->postfix(); str += report.text.substr(nchop) + item->postfix();
font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,str,rect.x,rect.y); area = font::draw_text(this,rect,item->font_size(),font::NORMAL_COLOUR,str,rect.x,rect.y);
}
if(report.tooltip.empty() == false) {
tooltips::add_tooltip(area,report.tooltip);
} }
if(report.image.empty() == false) { if(report.image.empty() == false) {
@ -816,7 +822,6 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
if(teams_.empty()) if(teams_.empty())
return; return;
tooltips::clear_tooltips(description_rect); tooltips::clear_tooltips(description_rect);
SDL_Rect clipRect = clip_rect != NULL ? *clip_rect : screen_area(); SDL_Rect clipRect = clip_rect != NULL ? *clip_rect : screen_area();
@ -858,7 +863,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
<< "\n-(" << string_table["level"] << " " << "\n-(" << string_table["level"] << " "
<< u.type().level() << ")\n" << u.type().level() << ")\n"
<< status << "\n" << status << "\n"
<< unit_type::alignment_description(u.type().alignment()) << translate_string(unit_type::alignment_description(u.type().alignment()))
<< "\n" << "\n"
<< u.traits_description() << "\n"; << u.traits_description() << "\n";

View file

@ -8,8 +8,8 @@
namespace { namespace {
const std::string report_names[] = { "unit_description", "unit_type", "unit_level", const std::string report_names[] = { "unit_description", "unit_type", "unit_level",
"unit_traits","unit_status","unit_alignment","unit_hp","unit_xp","unit_moves", "unit_traits","unit_status","unit_alignment","unit_abilities","unit_hp","unit_xp",
"unit_weapons","unit_image","unit_profile","time_of_day", "unit_moves","unit_weapons","unit_image","unit_profile","time_of_day",
"turn","gold","villages","num_units","upkeep", "expenses", "turn","gold","villages","num_units","upkeep", "expenses",
"income", "terrain", "position" }; "income", "terrain", "position" };
} }
@ -46,24 +46,55 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
switch(type) { switch(type) {
case UNIT_DESCRIPTION: case UNIT_DESCRIPTION:
return report(u->second.description()); return report(u->second.description());
case UNIT_TYPE: case UNIT_TYPE: {
return report(u->second.type().language_name()); report res(u->second.type().language_name());
res.tooltip = u->second.type().unit_description();
return res;
}
case UNIT_LEVEL: case UNIT_LEVEL:
str << u->second.type().level(); str << u->second.type().level();
break; break;
case UNIT_TRAITS: case UNIT_TRAITS:
return report(u->second.traits_description()); return report(u->second.traits_description());
case UNIT_STATUS: case UNIT_STATUS: {
if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y]))) std::string status = "healthy", prefix = "";
return report("@" + string_table["invisible"]); if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y]))) {
else if(u->second.has_flag("slowed")) status = "invisible";
return report("#" + string_table["slowed"]); prefix = "@";
else if(u->second.has_flag("poisoned")) } else if(u->second.has_flag("slowed")) {
status = "slowed";
prefix = "#";
return report("#" + string_table["poisoned"]); return report("#" + string_table["poisoned"]);
else } else if(u->second.has_flag("poisoned")) {
return report(string_table["healthy"]); status = "poisoned";
case UNIT_ALIGNMENT: prefix = "#";
return report(unit_type::alignment_description(u->second.type().alignment())); }
report res(prefix + string_table[status]);
res.tooltip = string_table[status + "_description"];
return res;
}
case UNIT_ALIGNMENT: {
const std::string& align = unit_type::alignment_description(u->second.type().alignment());
report res(translate_string(align));
res.tooltip = string_table[align + "_description"];
return res;
}
case UNIT_ABILITIES: {
std::stringstream tooltip;
const std::vector<std::string>& abilities = u->second.type().abilities();
for(std::vector<std::string>::const_iterator i = abilities.begin(); i != abilities.end(); ++i) {
str << translate_string(*i);
if(i+1 != abilities.end())
str << ",";
tooltip << string_table[*i + "_description"] << "\n\n";
}
report res(str.str());
res.tooltip = tooltip.str();
return res;
}
case UNIT_HP: case UNIT_HP:
if(u->second.hitpoints() <= u->second.max_hitpoints()/3) if(u->second.hitpoints() <= u->second.max_hitpoints()/3)
str << "#"; str << "#";
@ -118,8 +149,20 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
return report("",u->second.type().image()); return report("",u->second.type().image());
case UNIT_PROFILE: case UNIT_PROFILE:
return report("",u->second.type().image_profile()); return report("",u->second.type().image_profile());
case TIME_OF_DAY: case TIME_OF_DAY: {
return report("",timeofday_at(status,units,mouseover).image); const time_of_day& tod = timeofday_at(status,units,mouseover);
report res("",tod.image);
std::stringstream tooltip;
tooltip << "+" << translate_string_default(tod.id,tod.name) << "\n"
<< translate_string("lawful") << " " << string_table["units"] << ": "
<< (tod.lawful_bonus > 0 ? "+" : "") << tod.lawful_bonus << "%\n"
<< translate_string("neutral") << " " << string_table["units"] << ": " << "0%\n"
<< translate_string("chaotic") << " " << string_table["units"] << ": "
<< (tod.lawful_bonus < 0 ? "+" : "") << (tod.lawful_bonus*-1) << "%";
res.tooltip = tooltip.str();
return res;
}
case TURN: case TURN:
str << status.turn() << "/" << status.number_of_turns() << "\n"; str << status.turn() << "/" << status.number_of_turns() << "\n";
break; break;

View file

@ -13,7 +13,7 @@
namespace reports { namespace reports {
enum TYPE { UNIT_DESCRIPTION, UNIT_TYPE, UNIT_LEVEL, UNIT_TRAITS, UNIT_STATUS, enum TYPE { UNIT_DESCRIPTION, UNIT_TYPE, UNIT_LEVEL, UNIT_TRAITS, UNIT_STATUS,
UNIT_ALIGNMENT, UNIT_HP, UNIT_XP, UNIT_MOVES, UNIT_WEAPONS, UNIT_ALIGNMENT, UNIT_ABILITIES, UNIT_HP, UNIT_XP, UNIT_MOVES, UNIT_WEAPONS,
UNIT_IMAGE, UNIT_PROFILE, TIME_OF_DAY, UNIT_IMAGE, UNIT_PROFILE, TIME_OF_DAY,
TURN, GOLD, VILLAGES, NUM_UNITS, UPKEEP, EXPENSES, INCOME, TERRAIN, POSITION, TURN, GOLD, VILLAGES, NUM_UNITS, UPKEEP, EXPENSES, INCOME, TERRAIN, POSITION,
NUM_REPORTS}; NUM_REPORTS};
@ -28,9 +28,9 @@ namespace reports {
explicit report(const std::string& text) : text(text) {} explicit report(const std::string& text) : text(text) {}
report(const std::string& text, const std::string& image) : text(text), image(image) {} report(const std::string& text, const std::string& image) : text(text), image(image) {}
bool empty() const { return text.empty() && image.empty(); } bool empty() const { return text.empty() && image.empty(); }
bool operator==(const report& o) const { return o.text == text && o.image == image; } bool operator==(const report& o) const { return o.text == text && o.image == image && o.tooltip == tooltip; }
bool operator!=(const report& o) const { return !(o == *this); } bool operator!=(const report& o) const { return !(o == *this); }
std::string text, image; std::string text, image, tooltip;
}; };
report generate_report(TYPE type, const gamemap& map, const unit_map& units, report generate_report(TYPE type, const gamemap& map, const unit_map& units,

View file

@ -180,6 +180,27 @@ void draw_solid_tinted_rectangle(int x, int y, int w, int h,
namespace gui namespace gui
{ {
size_t text_to_lines(std::string& message, size_t max_length)
{
size_t cur_line = 0, longest_line = 0;
for(std::string::iterator i = message.begin(); i != message.end(); ++i) {
if(*i == ' ' && cur_line > max_length)
*i = '\n';
if(*i == '\n' || i+1 == message.end()) {
if(cur_line > longest_line)
longest_line = cur_line;
cur_line = 0;
} else {
++cur_line;
}
}
return longest_line;
}
int show_dialog(display& disp, SDL_Surface* image, int show_dialog(display& disp, SDL_Surface* image,
const std::string& caption, const std::string& msg, const std::string& caption, const std::string& msg,
DIALOG_TYPE type, DIALOG_TYPE type,
@ -229,29 +250,11 @@ int show_dialog(display& disp, SDL_Surface* image,
menu menu_(disp,menu_items,type == MESSAGE); menu menu_(disp,menu_items,type == MESSAGE);
const int border_size = 6; const int border_size = 6;
int nlines = 1;
int longest_line = 0;
int cur_line = 0;
const int max_line_length = 58; const int max_line_length = 58;
std::string message = msg; std::string message = msg;
for(std::string::iterator message_it = message.begin(); const size_t longest_line = text_to_lines(message,max_line_length);
message_it != message.end(); ++message_it) {
if(*message_it == ' ' && cur_line > max_line_length)
*message_it = '\n';
if(*message_it == '\n') {
if(cur_line > longest_line)
longest_line = cur_line;
cur_line = 0;
++nlines;
} else {
++cur_line;
}
}
SDL_Rect text_size = { 0, 0, 0, 0 }; SDL_Rect text_size = { 0, 0, 0, 0 };
if(!message.empty()) { if(!message.empty()) {
@ -324,9 +327,6 @@ int show_dialog(display& disp, SDL_Surface* image,
button_heights += button_height_padding; button_heights += button_height_padding;
} }
if(cur_line > longest_line)
longest_line = cur_line;
int check_button_height = 0; int check_button_height = 0;
int check_button_width = 0; int check_button_width = 0;

View file

@ -63,6 +63,9 @@ struct check_item {
bool checked; bool checked;
}; };
//function to chop up one long string of text into lines
size_t text_to_lines(std::string& text, size_t max_length);
//if a menu is given, then returns -1 if the dialog was cancelled, and the //if a menu is given, then returns -1 if the dialog was cancelled, and the
//index of the selection otherwise. If no menu is given, returns the index //index of the selection otherwise. If no menu is given, returns the index
//of the button that was pressed //of the button that was pressed

View file

@ -24,7 +24,9 @@ display* display_ = NULL;
struct tooltip struct tooltip
{ {
tooltip(const SDL_Rect& r, const std::string& msg) : rect(r), message(msg) tooltip(const SDL_Rect& r, const std::string& msg) : rect(r), message(msg)
{} {
gui::text_to_lines(message,60);
}
SDL_Rect rect; SDL_Rect rect;
std::string message; std::string message;
}; };
@ -143,7 +145,7 @@ void clear_tooltips()
void clear_tooltips(const SDL_Rect& rect) void clear_tooltips(const SDL_Rect& rect)
{ {
clear_tooltips(); clear_tooltip();
for(std::vector<tooltip>::iterator i = tips.begin(); i != tips.end(); ) { for(std::vector<tooltip>::iterator i = tips.begin(); i != tips.end(); ) {
if(rectangles_overlap(i->rect,rect)) { if(rectangles_overlap(i->rect,rect)) {
i = tips.erase(i); i = tips.erase(i);
@ -169,8 +171,7 @@ void add_tooltip(const SDL_Rect& rect, const std::string& message)
void process(int mousex, int mousey, bool lbutton) void process(int mousex, int mousey, bool lbutton)
{ {
for(std::vector<tooltip>::const_iterator i = tips.begin(); for(std::vector<tooltip>::const_iterator i = tips.begin(); i != tips.end(); ++i) {
i != tips.end(); ++i) {
if(mousex > i->rect.x && mousey > i->rect.y && if(mousex > i->rect.x && mousey > i->rect.y &&
mousex < i->rect.x + i->rect.w && mousey < i->rect.y + i->rect.h) { mousex < i->rect.x + i->rect.w && mousey < i->rect.y + i->rect.h) {
show_tooltip(*i); show_tooltip(*i);

View file

@ -611,10 +611,6 @@ unit_type::ALIGNMENT unit_type::alignment() const
const std::string& unit_type::alignment_description(unit_type::ALIGNMENT align) const std::string& unit_type::alignment_description(unit_type::ALIGNMENT align)
{ {
static const std::string aligns[] = { "lawful", "neutral", "chaotic" }; static const std::string aligns[] = { "lawful", "neutral", "chaotic" };
const string_map::const_iterator i = string_table.find(aligns[align]);
if(i != string_table.end())
return i->second;
else
return aligns[align]; return aligns[align];
} }