added some explanatory tooltips for some unit attributes on sidebar
This commit is contained in:
parent
7b2d7fb9cd
commit
541e1bc669
9 changed files with 164 additions and 58 deletions
|
@ -145,15 +145,21 @@ height=600
|
|||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_traits]
|
||||
[unit_status]
|
||||
[unit_abilities]
|
||||
font_size=14
|
||||
rect=897,514,1024,530
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_abilities]
|
||||
[unit_status]
|
||||
font_size=14
|
||||
rect=897,530,1024,546
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_status]
|
||||
[unit_moves]
|
||||
font_size=14
|
||||
rect=897,530,1024,546
|
||||
rect=897,546,1024,562
|
||||
prefix=movement
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
|
@ -161,7 +167,7 @@ height=600
|
|||
[/unit_moves]
|
||||
[unit_hp]
|
||||
font_size=14
|
||||
rect=897,546,1024,562
|
||||
rect=897,562,1024,578
|
||||
prefix=hp
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
|
@ -169,7 +175,7 @@ height=600
|
|||
[/unit_hp]
|
||||
[unit_xp]
|
||||
font_size=14
|
||||
rect=897,562,1024,578
|
||||
rect=897,578,1024,594
|
||||
prefix=xp
|
||||
prefix_literal=": "
|
||||
xanchor=right
|
||||
|
@ -177,7 +183,7 @@ height=600
|
|||
[/unit_xp]
|
||||
[unit_weapons]
|
||||
font_size=12
|
||||
rect=897,578,1024,690
|
||||
rect=897,594,1024,706
|
||||
xanchor=right
|
||||
yanchor=fixed
|
||||
[/unit_weapons]
|
||||
|
|
|
@ -125,6 +125,58 @@ EASY="Fighter (easy)"
|
|||
NORMAL="*Hero (medium)"
|
||||
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."
|
||||
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."
|
||||
|
|
|
@ -751,6 +751,8 @@ void display::draw_report(reports::TYPE report_num)
|
|||
|
||||
tooltips::clear_tooltips(rect);
|
||||
|
||||
SDL_Rect area = rect;
|
||||
|
||||
if(report.text.empty() == false) {
|
||||
std::string str = item->prefix();
|
||||
|
||||
|
@ -764,7 +766,11 @@ void display::draw_report(reports::TYPE report_num)
|
|||
|
||||
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) {
|
||||
|
@ -816,7 +822,6 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
|||
if(teams_.empty())
|
||||
return;
|
||||
|
||||
|
||||
tooltips::clear_tooltips(description_rect);
|
||||
|
||||
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"] << " "
|
||||
<< u.type().level() << ")\n"
|
||||
<< status << "\n"
|
||||
<< unit_type::alignment_description(u.type().alignment())
|
||||
<< translate_string(unit_type::alignment_description(u.type().alignment()))
|
||||
<< "\n"
|
||||
<< u.traits_description() << "\n";
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
namespace {
|
||||
const std::string report_names[] = { "unit_description", "unit_type", "unit_level",
|
||||
"unit_traits","unit_status","unit_alignment","unit_hp","unit_xp","unit_moves",
|
||||
"unit_weapons","unit_image","unit_profile","time_of_day",
|
||||
"unit_traits","unit_status","unit_alignment","unit_abilities","unit_hp","unit_xp",
|
||||
"unit_moves","unit_weapons","unit_image","unit_profile","time_of_day",
|
||||
"turn","gold","villages","num_units","upkeep", "expenses",
|
||||
"income", "terrain", "position" };
|
||||
}
|
||||
|
@ -46,24 +46,55 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
switch(type) {
|
||||
case UNIT_DESCRIPTION:
|
||||
return report(u->second.description());
|
||||
case UNIT_TYPE:
|
||||
return report(u->second.type().language_name());
|
||||
case UNIT_TYPE: {
|
||||
report res(u->second.type().language_name());
|
||||
res.tooltip = u->second.type().unit_description();
|
||||
return res;
|
||||
}
|
||||
case UNIT_LEVEL:
|
||||
str << u->second.type().level();
|
||||
break;
|
||||
case UNIT_TRAITS:
|
||||
return report(u->second.traits_description());
|
||||
case UNIT_STATUS:
|
||||
if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y])))
|
||||
return report("@" + string_table["invisible"]);
|
||||
else if(u->second.has_flag("slowed"))
|
||||
return report("#" + string_table["slowed"]);
|
||||
else if(u->second.has_flag("poisoned"))
|
||||
case UNIT_STATUS: {
|
||||
std::string status = "healthy", prefix = "";
|
||||
if(map.on_board(loc) && u->second.invisible(map.underlying_terrain(map[loc.x][loc.y]))) {
|
||||
status = "invisible";
|
||||
prefix = "@";
|
||||
} else if(u->second.has_flag("slowed")) {
|
||||
status = "slowed";
|
||||
prefix = "#";
|
||||
return report("#" + string_table["poisoned"]);
|
||||
else
|
||||
return report(string_table["healthy"]);
|
||||
case UNIT_ALIGNMENT:
|
||||
return report(unit_type::alignment_description(u->second.type().alignment()));
|
||||
} else if(u->second.has_flag("poisoned")) {
|
||||
status = "poisoned";
|
||||
prefix = "#";
|
||||
}
|
||||
|
||||
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:
|
||||
if(u->second.hitpoints() <= u->second.max_hitpoints()/3)
|
||||
str << "#";
|
||||
|
@ -118,8 +149,20 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
return report("",u->second.type().image());
|
||||
case UNIT_PROFILE:
|
||||
return report("",u->second.type().image_profile());
|
||||
case TIME_OF_DAY:
|
||||
return report("",timeofday_at(status,units,mouseover).image);
|
||||
case TIME_OF_DAY: {
|
||||
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:
|
||||
str << status.turn() << "/" << status.number_of_turns() << "\n";
|
||||
break;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
namespace reports {
|
||||
|
||||
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,
|
||||
TURN, GOLD, VILLAGES, NUM_UNITS, UPKEEP, EXPENSES, INCOME, TERRAIN, POSITION,
|
||||
NUM_REPORTS};
|
||||
|
@ -28,9 +28,9 @@ namespace reports {
|
|||
explicit report(const std::string& text) : text(text) {}
|
||||
report(const std::string& text, const std::string& image) : text(text), image(image) {}
|
||||
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); }
|
||||
std::string text, image;
|
||||
std::string text, image, tooltip;
|
||||
};
|
||||
|
||||
report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
||||
|
|
|
@ -180,6 +180,27 @@ void draw_solid_tinted_rectangle(int x, int y, int w, int h,
|
|||
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,
|
||||
const std::string& caption, const std::string& msg,
|
||||
DIALOG_TYPE type,
|
||||
|
@ -229,29 +250,11 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
menu menu_(disp,menu_items,type == MESSAGE);
|
||||
|
||||
const int border_size = 6;
|
||||
int nlines = 1;
|
||||
int longest_line = 0;
|
||||
int cur_line = 0;
|
||||
|
||||
const int max_line_length = 58;
|
||||
|
||||
std::string message = msg;
|
||||
for(std::string::iterator message_it = message.begin();
|
||||
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;
|
||||
}
|
||||
}
|
||||
const size_t longest_line = text_to_lines(message,max_line_length);
|
||||
|
||||
SDL_Rect text_size = { 0, 0, 0, 0 };
|
||||
if(!message.empty()) {
|
||||
|
@ -324,9 +327,6 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
button_heights += button_height_padding;
|
||||
}
|
||||
|
||||
if(cur_line > longest_line)
|
||||
longest_line = cur_line;
|
||||
|
||||
int check_button_height = 0;
|
||||
int check_button_width = 0;
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ struct check_item {
|
|||
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
|
||||
//index of the selection otherwise. If no menu is given, returns the index
|
||||
//of the button that was pressed
|
||||
|
|
|
@ -24,7 +24,9 @@ display* display_ = NULL;
|
|||
struct tooltip
|
||||
{
|
||||
tooltip(const SDL_Rect& r, const std::string& msg) : rect(r), message(msg)
|
||||
{}
|
||||
{
|
||||
gui::text_to_lines(message,60);
|
||||
}
|
||||
SDL_Rect rect;
|
||||
std::string message;
|
||||
};
|
||||
|
@ -143,7 +145,7 @@ void clear_tooltips()
|
|||
|
||||
void clear_tooltips(const SDL_Rect& rect)
|
||||
{
|
||||
clear_tooltips();
|
||||
clear_tooltip();
|
||||
for(std::vector<tooltip>::iterator i = tips.begin(); i != tips.end(); ) {
|
||||
if(rectangles_overlap(i->rect,rect)) {
|
||||
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)
|
||||
{
|
||||
for(std::vector<tooltip>::const_iterator i = tips.begin();
|
||||
i != tips.end(); ++i) {
|
||||
for(std::vector<tooltip>::const_iterator i = tips.begin(); i != tips.end(); ++i) {
|
||||
if(mousex > i->rect.x && mousey > i->rect.y &&
|
||||
mousex < i->rect.x + i->rect.w && mousey < i->rect.y + i->rect.h) {
|
||||
show_tooltip(*i);
|
||||
|
|
|
@ -611,11 +611,7 @@ unit_type::ALIGNMENT unit_type::alignment() const
|
|||
const std::string& unit_type::alignment_description(unit_type::ALIGNMENT align)
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
double unit_type::alpha() const
|
||||
|
|
Loading…
Add table
Reference in a new issue