added animated on-map items. New attack dialog. New load game dialog
This commit is contained in:
parent
6bd6f4a75e
commit
1949e00955
18 changed files with 656 additions and 279 deletions
|
@ -62,7 +62,7 @@ Defeat:
|
|||
side=2
|
||||
canrecruit=1
|
||||
recruit=Orcish Grunt,Wolf Rider,Orcish Archer,Troll Whelp,Saurian
|
||||
{GOLD 40 120 180}
|
||||
{GOLD 40 100 180}
|
||||
enemy=1
|
||||
[ai]
|
||||
recruitment_pattern=scout,scout,fighter,fighter,archer
|
||||
|
|
|
@ -312,7 +312,7 @@ Defeat:
|
|||
[message]
|
||||
id=msg5_23
|
||||
description=Delfador
|
||||
message="During the reign of Garard I, your uncle's father, the dwarves of Knalga agreed to make the king a magnificent scepter. It took their finest smiths years to make it. But soon after it was completed, Orcs invaded the tunnels of Knalga. Now Knalga is in chaos, and, though some Dwarves still live in parts of it, at constant war with the Orcs, the Scepter was lost somewhere in the great caverns."
|
||||
message="During the reign of Garard I, your grandfather, the dwarves of Knalga agreed to make the king a magnificent scepter. It took their finest smiths years to make it. But soon after it was completed, Orcs invaded the tunnels of Knalga. Now Knalga is in chaos, and, though some Dwarves still live in parts of it, at constant war with the Orcs, the Scepter was lost somewhere in the great caverns."
|
||||
[/message]
|
||||
|
||||
[message]
|
||||
|
|
|
@ -630,6 +630,8 @@ see_also="See Also..."
|
|||
|
||||
attack_type="Attack Type"
|
||||
|
||||
attack_enemy="Attack Enemy"
|
||||
|
||||
attacks="attacks"
|
||||
damage="damage"
|
||||
hexes="hexes"
|
||||
|
|
|
@ -762,13 +762,13 @@ void ai_interface::attack_enemy(const location& u, const location& target, int w
|
|||
|
||||
attack(info_.disp,info_.map,info_.teams,u,target,weapon,info_.units,info_.state,info_.gameinfo,false);
|
||||
check_victory(info_.units,info_.teams);
|
||||
dialogs::advance_unit(info_.gameinfo,info_.units,u,info_.disp,true);
|
||||
dialogs::advance_unit(info_.gameinfo,info_.map,info_.units,u,info_.disp,true);
|
||||
|
||||
const unit_map::const_iterator defender = info_.units.find(target);
|
||||
if(defender != info_.units.end()) {
|
||||
const size_t defender_team = size_t(defender->second.side()) - 1;
|
||||
if(defender_team < info_.teams.size()) {
|
||||
dialogs::advance_unit(info_.gameinfo,info_.units,target,info_.disp,!info_.teams[defender_team].is_human());
|
||||
dialogs::advance_unit(info_.gameinfo,info_.map,info_.units,target,info_.disp,!info_.teams[defender_team].is_human());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
531
src/dialogs.cpp
531
src/dialogs.cpp
|
@ -14,6 +14,7 @@
|
|||
#include "dialogs.hpp"
|
||||
#include "events.hpp"
|
||||
#include "font.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "language.hpp"
|
||||
#include "log.hpp"
|
||||
#include "preferences.hpp"
|
||||
|
@ -34,6 +35,7 @@ namespace dialogs
|
|||
{
|
||||
|
||||
void advance_unit(const game_data& info,
|
||||
const gamemap& map,
|
||||
std::map<gamemap::location,unit>& units,
|
||||
gamemap::location loc,
|
||||
display& gui, bool random_choice)
|
||||
|
@ -62,9 +64,14 @@ void advance_unit(const game_data& info,
|
|||
res = rand()%options.size();
|
||||
} else if(options.size() > 1) {
|
||||
|
||||
const events::event_context dialog_events_context;
|
||||
unit_preview_pane unit_preview(gui,&map,sample_units);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
res = gui::show_dialog(gui,NULL,string_table["advance_unit_heading"],
|
||||
string_table["advance_unit_message"],
|
||||
gui::OK_ONLY, &lang_options, &sample_units);
|
||||
gui::OK_ONLY, &lang_options, &preview_panes);
|
||||
}
|
||||
|
||||
recorder.choose_option(res);
|
||||
|
@ -156,12 +163,13 @@ namespace {
|
|||
class delete_save : public gui::dialog_button_action
|
||||
{
|
||||
public:
|
||||
delete_save(display& disp, std::vector<save_info>& saves) : disp_(disp), saves_(saves) {}
|
||||
delete_save(display& disp, std::vector<save_info>& saves, std::vector<config*>& save_summaries) : disp_(disp), saves_(saves), summaries_(save_summaries) {}
|
||||
private:
|
||||
gui::dialog_button_action::RESULT button_pressed(int menu_selection);
|
||||
|
||||
display& disp_;
|
||||
std::vector<save_info>& saves_;
|
||||
std::vector<config*>& summaries_;
|
||||
};
|
||||
|
||||
gui::dialog_button_action::RESULT delete_save::button_pressed(int menu_selection)
|
||||
|
@ -193,23 +201,173 @@ gui::dialog_button_action::RESULT delete_save::button_pressed(int menu_selection
|
|||
|
||||
//remove it from the list of saves
|
||||
saves_.erase(saves_.begin() + index);
|
||||
|
||||
if(index < summaries_.size()) {
|
||||
summaries_.erase(summaries_.begin() + index);
|
||||
}
|
||||
|
||||
return gui::dialog_button_action::DELETE_ITEM;
|
||||
} else {
|
||||
return gui::dialog_button_action::NO_EFFECT;
|
||||
}
|
||||
}
|
||||
|
||||
static const SDL_Rect save_preview_pane_area = {-200,-400,200,400};
|
||||
static const int save_preview_border = 10;
|
||||
|
||||
class save_preview_pane : public gui::preview_pane
|
||||
{
|
||||
public:
|
||||
save_preview_pane(display& disp, const config& game_config, gamemap* map, const game_data& data,
|
||||
const std::vector<save_info>& info, const std::vector<config*>& summaries)
|
||||
: gui::preview_pane(disp), game_config_(&game_config), map_(map), data_(&data), info_(&info), summaries_(&summaries), index_(0)
|
||||
{
|
||||
set_location(save_preview_pane_area);
|
||||
}
|
||||
|
||||
void draw();
|
||||
void set_selection(int index) {
|
||||
index_ = index;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
bool left_side() const { return true; }
|
||||
|
||||
private:
|
||||
const config* game_config_;
|
||||
gamemap* map_;
|
||||
const game_data* data_;
|
||||
const std::vector<save_info>* info_;
|
||||
const std::vector<config*>* summaries_;
|
||||
int index_;
|
||||
std::map<std::string,shared_sdl_surface> map_cache_;
|
||||
};
|
||||
|
||||
void save_preview_pane::draw()
|
||||
{
|
||||
if(!dirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bg_restore();
|
||||
|
||||
if(index_ < 0 || index_ >= int(summaries_->size()) || info_->size() != summaries_->size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const config& summary = *(*summaries_)[index_];
|
||||
|
||||
SDL_Surface* const screen = disp().video().getSurface();
|
||||
|
||||
const SDL_Rect area = { location().x+save_preview_border, location().y+save_preview_border,
|
||||
location().w-save_preview_border*2, location().h-save_preview_border*2 };
|
||||
SDL_Rect clip_area = area;
|
||||
const clip_rect_setter clipper(screen,clip_area);
|
||||
|
||||
int ypos = area.y;
|
||||
|
||||
const game_data::unit_type_map::const_iterator leader = data_->unit_types.find(summary["leader"]);
|
||||
if(leader != data_->unit_types.end()) {
|
||||
const scoped_sdl_surface image(image::get_image(leader->second.image(),image::UNSCALED));
|
||||
if(image != NULL) {
|
||||
SDL_Rect image_rect = {area.x,area.y,image->w,image->h};
|
||||
ypos += image_rect.y + image_rect.h + save_preview_border;
|
||||
|
||||
SDL_BlitSurface(image,NULL,screen,&image_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string map_data = summary["map_data"];
|
||||
if(map_data.empty()) {
|
||||
const config* const scenario = game_config_->find_child(summary["campaign_type"],"id",summary["scenario"]);
|
||||
if(scenario != NULL) {
|
||||
map_data = (*scenario)["map_data"];
|
||||
if(map_data.empty() && (*scenario)["map"].empty() == false) {
|
||||
try {
|
||||
map_data = read_map((*scenario)["map"]);
|
||||
} catch(io_exception& e) {
|
||||
std::cerr << "could not read map '" << (*scenario)["map"] << "': " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* map_surf = NULL;
|
||||
|
||||
if(map_data.empty() == false) {
|
||||
const std::map<std::string,shared_sdl_surface>::const_iterator itor = map_cache_.find(map_data);
|
||||
if(itor != map_cache_.end()) {
|
||||
map_surf = itor->second;
|
||||
} else if(map_ != NULL) {
|
||||
try {
|
||||
map_->read(map_data);
|
||||
|
||||
map_surf = image::getMinimap(100,100,*map_,0,NULL);
|
||||
if(map_surf != NULL) {
|
||||
map_cache_.insert(std::pair<std::string,shared_sdl_surface>(map_data,shared_sdl_surface(map_surf)));
|
||||
}
|
||||
} catch(gamemap::incorrect_format_exception&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(map_surf != NULL) {
|
||||
SDL_Rect map_rect = {area.x + area.w - map_surf->w,area.y,map_surf->w,map_surf->h};
|
||||
ypos = maximum<int>(ypos,map_rect.y + map_rect.h + save_preview_border);
|
||||
SDL_BlitSurface(map_surf,NULL,screen,&map_rect);
|
||||
}
|
||||
|
||||
char time_buf[256];
|
||||
const size_t res = strftime(time_buf,sizeof(time_buf),string_table["date_format"].c_str(),localtime(&((*info_)[index_].time_modified)));
|
||||
if(res == 0) {
|
||||
time_buf[0] = 0;
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
// escape all special characters in filenames
|
||||
std::string name = (*info_)[index_].name;
|
||||
str << font::BOLD_TEXT << config::escape(name) << "\n" << time_buf;
|
||||
|
||||
if(summary["corrupt"] == "yes") {
|
||||
str << "\n" << string_table["save_invalid"];
|
||||
} else if(summary["campaign_type"] != "") {
|
||||
str << "\n";
|
||||
|
||||
const std::string& campaign_type = summary["campaign_type"];
|
||||
if(campaign_type == "scenario") {
|
||||
str << translate_string("campaign_button");
|
||||
} else if(campaign_type == "multiplayer") {
|
||||
str << translate_string("multiplayer_button");
|
||||
} else if(campaign_type == "tutorial") {
|
||||
str << translate_string("tutorial_button");
|
||||
} else {
|
||||
str << translate_string(campaign_type);
|
||||
}
|
||||
|
||||
str << "\n";
|
||||
|
||||
if(summary["snapshot"] == "no" && summary["replay"] == "yes") {
|
||||
str << translate_string("replay");
|
||||
} else if(summary["turn"] != "") {
|
||||
str << translate_string("turn") << " " << summary["turn"];
|
||||
} else {
|
||||
str << string_table["scenario_start"];
|
||||
}
|
||||
|
||||
str << "\n" << translate_string("difficulty") << ": " << translate_string(summary["difficulty"]);
|
||||
}
|
||||
|
||||
font::draw_text(&disp(),area,12,font::NORMAL_COLOUR,str.str(),area.x,ypos,NULL,true);
|
||||
}
|
||||
|
||||
} //end anon namespace
|
||||
|
||||
std::string load_game_dialog(display& disp, const config& game_config, const game_data& data, bool* show_replay)
|
||||
{
|
||||
std::vector<save_info> games = get_saves_list();
|
||||
|
||||
delete_save save_deleter(disp,games);
|
||||
gui::dialog_button delete_button(&save_deleter,string_table["delete_save"]);
|
||||
std::vector<gui::dialog_button> buttons;
|
||||
buttons.push_back(delete_button);
|
||||
|
||||
if(games.empty()) {
|
||||
gui::show_dialog(disp,NULL,
|
||||
string_table["no_saves_heading"],
|
||||
|
@ -230,6 +388,11 @@ std::string load_game_dialog(display& disp, const config& game_config, const gam
|
|||
summaries.push_back(&cfg);
|
||||
}
|
||||
|
||||
delete_save save_deleter(disp,games,summaries);
|
||||
gui::dialog_button delete_button(&save_deleter,string_table["delete_save"]);
|
||||
std::vector<gui::dialog_button> buttons;
|
||||
buttons.push_back(delete_button);
|
||||
|
||||
bool generate_summaries = !no_summary.empty();
|
||||
|
||||
//if there are more than 5 saves without a summary, it may take a substantial
|
||||
|
@ -300,106 +463,20 @@ std::string load_game_dialog(display& disp, const config& game_config, const gam
|
|||
write_save_index();
|
||||
}
|
||||
|
||||
util::scoped_ptr<gamemap> map_ptr(NULL);
|
||||
string_map map_cache;
|
||||
|
||||
std::vector<std::string> items;
|
||||
for(i = games.begin(); i != games.end(); ++i) {
|
||||
std::string name = i->name;
|
||||
name.resize(minimum<size_t>(name.size(),40));
|
||||
|
||||
char time_buf[256];
|
||||
const size_t res = strftime(time_buf,sizeof(time_buf),string_table["date_format"].c_str(),localtime(&(i->time_modified)));
|
||||
if(res == 0)
|
||||
time_buf[0] = 0;
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
config& summary = *summaries[i - games.begin()];
|
||||
const game_data::unit_type_map::const_iterator leader = data.unit_types.find(summary["leader"]);
|
||||
if(leader != data.unit_types.end()) {
|
||||
str << "&" << leader->second.image() << ",";
|
||||
} else {
|
||||
str << ",";
|
||||
}
|
||||
|
||||
// escape all special characters in filenames
|
||||
str << font::BOLD_TEXT << config::escape(name) << "\n" << time_buf;
|
||||
|
||||
if(summary["corrupt"] == "yes") {
|
||||
str << "\n" << string_table["save_invalid"];
|
||||
} else if(summary["campaign_type"] != "") {
|
||||
str << "\n";
|
||||
|
||||
const std::string& campaign_type = summary["campaign_type"];
|
||||
if(campaign_type == "scenario") {
|
||||
str << translate_string("campaign_button");
|
||||
} else if(campaign_type == "multiplayer") {
|
||||
str << translate_string("multiplayer_button");
|
||||
} else if(campaign_type == "tutorial") {
|
||||
str << translate_string("tutorial_button");
|
||||
} else {
|
||||
str << translate_string(campaign_type);
|
||||
}
|
||||
|
||||
str << "\n";
|
||||
|
||||
if(summary["snapshot"] == "no" && summary["replay"] == "yes") {
|
||||
str << translate_string("replay");
|
||||
} else if(summary["turn"] != "") {
|
||||
str << translate_string("turn") << " " << summary["turn"];
|
||||
} else {
|
||||
str << string_table["scenario_start"];
|
||||
}
|
||||
|
||||
str << "\n" << translate_string("difficulty") << ": " << translate_string(summary["difficulty"]);
|
||||
|
||||
std::string map_data = summary["map_data"];
|
||||
if(map_data.empty()) {
|
||||
const config* const scenario = game_config.find_child(summary["campaign_type"],"id",summary["scenario"]);
|
||||
if(scenario != NULL) {
|
||||
map_data = (*scenario)["map_data"];
|
||||
if(map_data.empty() && (*scenario)["map"].empty() == false) {
|
||||
try {
|
||||
map_data = read_map((*scenario)["map"]);
|
||||
} catch(io_exception& e) {
|
||||
std::cerr << "could not read map '" << (*scenario)["map"] << "': " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(map_data.empty() == false) {
|
||||
const string_map::const_iterator itor = map_cache.find(map_data);
|
||||
if(itor != map_cache.end()) {
|
||||
str << ",&" << itor->second;
|
||||
} else {
|
||||
|
||||
try {
|
||||
if(map_ptr == NULL) {
|
||||
map_ptr.assign(new gamemap(game_config,map_data));
|
||||
} else {
|
||||
map_ptr->read(map_data);
|
||||
}
|
||||
|
||||
SDL_Surface* const minimap = image::getMinimap(72,72,*map_ptr,0,NULL);
|
||||
if(minimap != NULL) {
|
||||
const std::string id = "_map_image_" + name;
|
||||
image::register_image(id,minimap);
|
||||
str << ",&" << id;
|
||||
|
||||
map_cache[map_data] = id;
|
||||
}
|
||||
} catch(gamemap::incorrect_format_exception& e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
items.push_back(str.str());
|
||||
items.push_back(name);
|
||||
}
|
||||
|
||||
gamemap map_obj(game_config,"");
|
||||
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
save_preview_pane save_preview(disp,game_config,&map_obj,data,games,summaries);
|
||||
preview_panes.push_back(&save_preview);
|
||||
|
||||
//create an option for whether the replay should be shown or not
|
||||
std::vector<gui::check_item> options;
|
||||
|
||||
|
@ -409,7 +486,7 @@ std::string load_game_dialog(display& disp, const config& game_config, const gam
|
|||
const int res = gui::show_dialog(disp,NULL,
|
||||
string_table["load_game_heading"],
|
||||
string_table["load_game_message"],
|
||||
gui::OK_CANCEL,&items,NULL,"",NULL,NULL,&options,-1,-1,NULL,&buttons);
|
||||
gui::OK_CANCEL,&items,&preview_panes,"",NULL,NULL,&options,-1,-1,NULL,&buttons);
|
||||
|
||||
if(res == -1)
|
||||
return "";
|
||||
|
@ -505,4 +582,254 @@ int show_file_chooser_dialog(display &disp, std::string &filename,
|
|||
}
|
||||
}
|
||||
|
||||
} //end namespace dialogs
|
||||
namespace {
|
||||
static const SDL_Rect unit_preview_size = {-150,-350,150,350};
|
||||
static const int unit_preview_border = 10;
|
||||
}
|
||||
|
||||
unit_preview_pane::unit_preview_pane(display& disp, const gamemap* map, const unit& u, bool on_left_side)
|
||||
: gui::preview_pane(disp), details_button_(disp,string_table["action_describeunit"]),
|
||||
map_(map), units_(&unit_store_), index_(0), left_(on_left_side)
|
||||
{
|
||||
set_location(unit_preview_size);
|
||||
unit_store_.push_back(u);
|
||||
}
|
||||
|
||||
unit_preview_pane::unit_preview_pane(display& disp, const gamemap* map, const std::vector<unit>& units, bool on_left_side)
|
||||
: gui::preview_pane(disp), details_button_(disp,string_table["action_describeunit"]),
|
||||
map_(map), units_(&units), index_(0), left_(on_left_side)
|
||||
{
|
||||
set_location(unit_preview_size);
|
||||
}
|
||||
|
||||
bool unit_preview_pane::left_side() const
|
||||
{
|
||||
return left_;
|
||||
}
|
||||
|
||||
void unit_preview_pane::set_selection(int index)
|
||||
{
|
||||
index = minimum<int>(int(units_->size()-1),index);
|
||||
if(index != index_ && index >= 0) {
|
||||
index_ = index;
|
||||
set_dirty();
|
||||
if(map_ != NULL) {
|
||||
details_button_.set_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unit_preview_pane::draw()
|
||||
{
|
||||
if(!dirty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bg_restore();
|
||||
|
||||
if(index_ < 0 || index_ >= int(units_->size())) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unit& u = (*units_)[index_];
|
||||
|
||||
set_dirty(false);
|
||||
|
||||
SDL_Surface* const screen = disp().video().getSurface();
|
||||
|
||||
const SDL_Rect area = { location().x+unit_preview_border, location().y+unit_preview_border,
|
||||
location().w-unit_preview_border*2, location().h-unit_preview_border*2 };
|
||||
SDL_Rect clip_area = area;
|
||||
const clip_rect_setter clipper(screen,clip_area);
|
||||
|
||||
scoped_sdl_surface unit_image(image::get_image(u.type().image(),image::UNSCALED));
|
||||
if(left_side() == false && unit_image != NULL) {
|
||||
unit_image.assign(image::reverse_image(unit_image));
|
||||
}
|
||||
|
||||
if(unit_image != NULL) {
|
||||
SDL_Rect image_rect = {area.x,area.y,unit_image->w,unit_image->h};
|
||||
SDL_BlitSurface(unit_image,NULL,screen,&image_rect);
|
||||
}
|
||||
|
||||
std::stringstream details;
|
||||
details << font::BOLD_TEXT << u.description() << "\n"
|
||||
<< font::BOLD_TEXT << u.type().language_name()
|
||||
<< "\n" << font::SMALL_TEXT << "(" << string_table["level"] << " "
|
||||
<< u.type().level() << ")\n"
|
||||
<< translate_string(unit_type::alignment_description(u.type().alignment()))
|
||||
<< "\n"
|
||||
<< u.traits_description() << "\n";
|
||||
|
||||
const std::vector<std::string>& abilities = u.type().abilities();
|
||||
for(std::vector<std::string>::const_iterator a = abilities.begin(); a != abilities.end(); ++a) {
|
||||
details << translate_string_default("ability_" + *a, *a) << "\n";
|
||||
}
|
||||
|
||||
//display in green/white/red depending on hitpoints
|
||||
if(u.hitpoints() <= u.max_hitpoints()/3)
|
||||
details << font::BAD_TEXT;
|
||||
else if(u.hitpoints() > 2*(u.max_hitpoints()/3))
|
||||
details << font::GOOD_TEXT;
|
||||
|
||||
details << string_table["hp"] << ": " << u.hitpoints()
|
||||
<< "/" << u.max_hitpoints() << "\n";
|
||||
|
||||
if(u.type().advances_to().empty()) {
|
||||
details << string_table["xp"] << ": " << u.experience() << "/-";
|
||||
} else {
|
||||
//if killing a unit the same level as us would level us up,
|
||||
//then display in green
|
||||
if(u.max_experience() - u.experience() < game_config::kill_experience) {
|
||||
details << font::GOOD_TEXT;
|
||||
}
|
||||
|
||||
details << string_table["xp"] << ": " << u.experience() << "/" << u.max_experience();
|
||||
}
|
||||
|
||||
details << "\n"
|
||||
<< string_table["moves"] << ": " << u.movement_left() << "/"
|
||||
<< u.total_movement()
|
||||
<< "\n";
|
||||
|
||||
const std::vector<attack_type>& attacks = u.attacks();
|
||||
for(std::vector<attack_type>::const_iterator at_it = attacks.begin();
|
||||
at_it != attacks.end(); ++at_it) {
|
||||
|
||||
const std::string& lang_weapon = string_table["weapon_name_" + at_it->name()];
|
||||
const std::string& lang_type = string_table["weapon_type_" + at_it->type()];
|
||||
const std::string& lang_special = string_table["weapon_special_" + at_it->special()];
|
||||
details << "\n"
|
||||
<< (lang_weapon.empty() ? at_it->name():lang_weapon) << " ("
|
||||
<< (lang_type.empty() ? at_it->type():lang_type) << ")\n"
|
||||
<< (lang_special.empty() ? at_it->special():lang_special)<<"\n"
|
||||
<< at_it->damage() << "-" << at_it->num_attacks() << " -- "
|
||||
<< (at_it->range() == attack_type::SHORT_RANGE ?
|
||||
string_table["short_range"] :
|
||||
string_table["long_range"]);
|
||||
|
||||
if(at_it->hexes() > 1) {
|
||||
details << " (" << at_it->hexes() << ")";
|
||||
}
|
||||
|
||||
details << "\n\n";
|
||||
}
|
||||
|
||||
const SDL_Rect& text_area = font::draw_text(&disp(),area,12,font::NORMAL_COLOUR,details.str(),
|
||||
area.x,area.y + (unit_image != NULL ? unit_image->h : 0) + unit_preview_border);
|
||||
if(map_ != NULL) {
|
||||
const SDL_Rect button_loc = {area.x + unit_preview_border,area.y + area.h - details_button_.location().h - unit_preview_border,
|
||||
details_button_.location().w,details_button_.location().h};
|
||||
details_button_.set_location(button_loc);
|
||||
}
|
||||
}
|
||||
|
||||
void unit_preview_pane::process()
|
||||
{
|
||||
if(map_ != NULL && details_button_.pressed() && index_ >= 0 && index_ < int(units_->size())) {
|
||||
|
||||
show_unit_description(disp(),*map_,(*units_)[index_]);
|
||||
}
|
||||
}
|
||||
|
||||
void show_unit_description(display& disp, const gamemap& map, const unit& u)
|
||||
{
|
||||
const std::string description = u.unit_description()
|
||||
+ "\n\n" + string_table["see_also"];
|
||||
|
||||
std::vector<std::string> options;
|
||||
|
||||
options.push_back(string_table["terrain_info"]);
|
||||
options.push_back(string_table["attack_resistance"]);
|
||||
options.push_back(string_table["close_window"]);
|
||||
|
||||
const scoped_sdl_surface profile(image::get_image(u.type().image_profile(),image::SCALED));
|
||||
|
||||
const int res = gui::show_dialog(disp, profile, u.type().language_name(),
|
||||
description,gui::MESSAGE, &options);
|
||||
if(res == 0) {
|
||||
show_unit_terrain_table(disp,map,u);
|
||||
} else if(res == 1) {
|
||||
show_unit_resistance(disp,u);
|
||||
}
|
||||
}
|
||||
|
||||
void show_unit_resistance(display& disp, const unit& u)
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
items.push_back(string_table["attack_type"] + "," + string_table["attack_resistance"]);
|
||||
const std::map<std::string,std::string>& table = u.type().movement_type().damage_table();
|
||||
for(std::map<std::string,std::string>::const_iterator i = table.begin(); i != table.end(); ++i) {
|
||||
int resistance = 100 - atoi(i->second.c_str());
|
||||
|
||||
//if resistance is less than 0, display in red
|
||||
const char prefix = resistance < 0 ? font::BAD_TEXT : font::NULL_MARKUP;
|
||||
|
||||
const std::string& lang_weapon = string_table["weapon_type_" + i->first];
|
||||
const std::string& weap = lang_weapon.empty() ? i->first : lang_weapon;
|
||||
|
||||
std::stringstream str;
|
||||
str << weap << "," << prefix << resistance << "%";
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(disp,NULL,u);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
gui::show_dialog(disp,NULL,
|
||||
u.type().language_name(),
|
||||
string_table["unit_resistance_table"],
|
||||
gui::MESSAGE,&items,&preview_panes);
|
||||
}
|
||||
|
||||
void show_unit_terrain_table(display& disp, const gamemap& map, const unit& u)
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
items.push_back(string_table["terrain"] + "," +
|
||||
string_table["movement"] + "," +
|
||||
string_table["defense"]);
|
||||
|
||||
const unit_type& type = u.type();
|
||||
const unit_movement_type& move_type = type.movement_type();
|
||||
const std::vector<gamemap::TERRAIN>& terrains = map.get_terrain_precedence();
|
||||
for(std::vector<gamemap::TERRAIN>::const_iterator t =
|
||||
terrains.begin(); t != terrains.end(); ++t) {
|
||||
|
||||
//exclude fog and shroud
|
||||
if(*t == gamemap::FOGGED || *t == gamemap::VOID_TERRAIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const terrain_type& info = map.get_terrain_info(*t);
|
||||
if(!info.is_alias()) {
|
||||
const std::string& name = map.terrain_name(*t);
|
||||
const std::string& lang_name = string_table[name];
|
||||
const int moves = move_type.movement_cost(map,*t);
|
||||
|
||||
std::stringstream str;
|
||||
str << lang_name << ",";
|
||||
if(moves < 100)
|
||||
str << moves;
|
||||
else
|
||||
str << "--";
|
||||
|
||||
const int defense = 100 - move_type.defense_modifier(map,*t);
|
||||
str << "," << defense << "%";
|
||||
|
||||
items.push_back(str.str());
|
||||
}
|
||||
}
|
||||
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(disp,NULL,u);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
gui::show_dialog(disp,NULL,u.type().language_name(),
|
||||
string_table["terrain_info"],
|
||||
gui::MESSAGE,&items,&preview_panes);
|
||||
}
|
||||
|
||||
} //end namespace dialogs
|
|
@ -16,9 +16,12 @@
|
|||
#include "actions.hpp"
|
||||
#include "config.hpp"
|
||||
#include "display.hpp"
|
||||
#include "map.hpp"
|
||||
#include "show_dialog.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
#include "widgets/button.hpp"
|
||||
|
||||
namespace dialogs
|
||||
{
|
||||
//function to handle an advancing unit. If there is only one choice to advance
|
||||
|
@ -28,7 +31,7 @@ namespace dialogs
|
|||
//
|
||||
//note that 'loc' is not a reference, because deleting an item from the units map
|
||||
//(when replacing the unit that is being advanced) will possibly invalidate the reference
|
||||
void advance_unit(const game_data& info,unit_map& units, gamemap::location loc,
|
||||
void advance_unit(const game_data& info, const gamemap& map,unit_map& units, gamemap::location loc,
|
||||
display& gui, bool random_choice=false);
|
||||
|
||||
bool animate_unit_advancement(const game_data& info,unit_map& units, gamemap::location loc, display& gui, size_t choice);
|
||||
|
@ -57,6 +60,32 @@ void unit_speak(const config& message_info, display& disp, const unit_map& units
|
|||
int show_file_chooser_dialog(display &displ, std::string &filename,
|
||||
const std::string title="Choose a File",
|
||||
int xloc=-1, int yloc=-1);
|
||||
|
||||
class unit_preview_pane : public gui::preview_pane
|
||||
{
|
||||
public:
|
||||
unit_preview_pane(display& disp, const gamemap* map, const unit& u, bool left_side=true);
|
||||
unit_preview_pane(display& disp, const gamemap* map, const std::vector<unit>& units, bool left_side=true);
|
||||
|
||||
bool left_side() const;
|
||||
void set_selection(int index);
|
||||
|
||||
private:
|
||||
void draw();
|
||||
void process();
|
||||
|
||||
gui::button details_button_;
|
||||
const gamemap* map_;
|
||||
const std::vector<unit>* units_;
|
||||
std::vector<unit> unit_store_;
|
||||
int index_;
|
||||
bool left_;
|
||||
};
|
||||
|
||||
void show_unit_description(display& disp, const gamemap& map, const unit& u);
|
||||
void show_unit_resistance(display& disp, const unit& u);
|
||||
void show_unit_terrain_table(display& disp, const gamemap& map, const unit& u);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2089,14 +2089,23 @@ void display::invalidate_game_status()
|
|||
invalidateGameStatus_ = true;
|
||||
}
|
||||
|
||||
void display::add_overlay(const gamemap::location& loc, const std::string& img)
|
||||
void display::add_overlay(const gamemap::location& loc, const std::string& img, const std::string& halo)
|
||||
{
|
||||
overlays_.insert(std::pair<gamemap::location,std::string>(loc,img));
|
||||
halo_overlays_.insert(std::pair<gamemap::location,int>(loc,halo::add(get_location_x(loc)+hex_size()/2,get_location_y(loc)+hex_size()/2,halo)));
|
||||
}
|
||||
|
||||
void display::remove_overlay(const gamemap::location& loc)
|
||||
{
|
||||
overlays_.erase(loc);
|
||||
typedef std::multimap<gamemap::location,int>::const_iterator Itor;
|
||||
std::pair<Itor,Itor> itors = halo_overlays_.equal_range(loc);
|
||||
while(itors.first != itors.second) {
|
||||
halo::remove(itors.first->second);
|
||||
++itors.first;
|
||||
}
|
||||
|
||||
halo_overlays_.erase(loc);
|
||||
}
|
||||
|
||||
void display::write_overlays(config& cfg) const
|
||||
|
|
|
@ -224,7 +224,7 @@ public:
|
|||
//functions to add and remove overlays from locations. An overlay is an
|
||||
//image that is displayed on top of the tile. One tile may have multiple
|
||||
//overlays. remove_overlay will remove all overlays on a tile.
|
||||
void add_overlay(const gamemap::location& loc, const std::string& image);
|
||||
void add_overlay(const gamemap::location& loc, const std::string& image, const std::string& halo="");
|
||||
void remove_overlay(const gamemap::location& loc);
|
||||
|
||||
//function to serialize overlay data
|
||||
|
@ -422,6 +422,7 @@ private:
|
|||
bool invalidateGameStatus_;
|
||||
|
||||
std::multimap<gamemap::location,std::string> overlays_;
|
||||
std::multimap<gamemap::location,int> halo_overlays_;
|
||||
|
||||
bool panelsDrawn_;
|
||||
|
||||
|
|
|
@ -128,16 +128,20 @@ std::deque<context> event_contexts;
|
|||
|
||||
} //end anon namespace
|
||||
|
||||
event_context::event_context()
|
||||
event_context::event_context(bool create) : create_(create)
|
||||
{
|
||||
event_contexts.push_back(context());
|
||||
if(create_) {
|
||||
event_contexts.push_back(context());
|
||||
}
|
||||
}
|
||||
|
||||
event_context::~event_context()
|
||||
{
|
||||
assert(event_contexts.empty() == false);
|
||||
if(create_) {
|
||||
assert(event_contexts.empty() == false);
|
||||
|
||||
event_contexts.pop_back();
|
||||
event_contexts.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
handler::handler() : unicode_(SDL_EnableUNICODE(1))
|
||||
|
|
|
@ -61,8 +61,11 @@ bool has_focus(const handler* ptr);
|
|||
//before their context is destroyed
|
||||
struct event_context
|
||||
{
|
||||
event_context();
|
||||
event_context(bool create=true);
|
||||
~event_context();
|
||||
|
||||
private:
|
||||
bool create_;
|
||||
};
|
||||
|
||||
//causes events to be dispatched to all handler objects.
|
||||
|
|
|
@ -883,9 +883,12 @@ int play_game(int argc, char** argv)
|
|||
defines_map["MEDIUM"] = preproc_define();
|
||||
}
|
||||
}
|
||||
|
||||
state.campaign_define = campaign["define"];
|
||||
} else if(res == gui::MULTIPLAYER) {
|
||||
state.campaign_type = "multiplayer";
|
||||
state.scenario = "";
|
||||
state.campaign_define = "MULTIPLAYER";
|
||||
|
||||
std::vector<std::string> host_or_join;
|
||||
host_or_join.push_back(string_table["join_game"]);
|
||||
|
@ -968,6 +971,10 @@ int play_game(int argc, char** argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(state.campaign_define.empty() == false) {
|
||||
defines_map[state.campaign_define] = preproc_define();
|
||||
}
|
||||
|
||||
//make a new game config item based on the difficulty level
|
||||
std::vector<line_source> line_src;
|
||||
config game_config;
|
||||
|
|
|
@ -657,8 +657,9 @@ bool event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
else if(cmd == "item") {
|
||||
gamemap::location loc(cfg);
|
||||
const std::string& img = cfg["image"];
|
||||
if(!img.empty()) {
|
||||
screen->add_overlay(loc,img);
|
||||
const std::string& halo = cfg["halo"];
|
||||
if(!img.empty() || !halo.empty()) {
|
||||
screen->add_overlay(loc,img,cfg["halo"]);
|
||||
screen->draw_tile(loc.x,loc.y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,6 +205,8 @@ game_state read_game(const game_data& data, const config* cfg)
|
|||
if(res.difficulty.empty())
|
||||
res.difficulty = "NORMAL";
|
||||
|
||||
res.campaign_define = (*cfg)["campaign_define"];
|
||||
|
||||
res.campaign_type = (*cfg)["campaign_type"];
|
||||
if(res.campaign_type.empty())
|
||||
res.campaign_type = "scenario";
|
||||
|
@ -272,6 +274,8 @@ void write_game(const game_state& game, config& cfg, WRITE_GAME_MODE mode)
|
|||
|
||||
cfg["difficulty"] = game.difficulty;
|
||||
|
||||
cfg["campaign_define"] = game.campaign_define;
|
||||
|
||||
cfg.add_child("variables",game.variables);
|
||||
|
||||
for(std::vector<unit>::const_iterator i = game.available_units.begin();
|
||||
|
|
|
@ -131,6 +131,8 @@ struct game_state
|
|||
|
||||
std::set<std::string> can_recruit; //units the player has the ability to recruit
|
||||
|
||||
std::string campaign_define; //if there is a define the campaign uses to customize data
|
||||
|
||||
//if the game is saved mid-level, we have a series of replay steps to
|
||||
//take the game up to the position it was saved at.
|
||||
config replay_data;
|
||||
|
|
|
@ -252,9 +252,6 @@ void gamemap::read(const std::string& data)
|
|||
}
|
||||
}
|
||||
|
||||
if(tiles_.empty())
|
||||
throw incorrect_format_exception("empty map");
|
||||
|
||||
for(size_t n = 0; n != tiles_.size(); ++n) {
|
||||
if(tiles_[n].size() != size_t(this->y())) {
|
||||
std::cerr << "Map is not rectangular!\n";
|
||||
|
|
198
src/playturn.cpp
198
src/playturn.cpp
|
@ -576,8 +576,6 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
const std::vector<attack_type>& attacks = u->second.attacks();
|
||||
std::vector<std::string> items;
|
||||
|
||||
std::vector<unit> units_list;
|
||||
|
||||
const int range = distance_between(u->first,enemy->first);
|
||||
std::vector<int> attacks_in_range;
|
||||
|
||||
|
@ -642,7 +640,6 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
<< "%,&" << stats.back().defend_icon;
|
||||
|
||||
items.push_back(att.str());
|
||||
units_list.push_back(enemy->second);
|
||||
}
|
||||
|
||||
if (best_weapon_index >= 0) {
|
||||
|
@ -659,10 +656,21 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
std::vector<gui::dialog_button> buttons;
|
||||
buttons.push_back(gui::dialog_button(&calc_displayer,string_table["damage_calculations"]));
|
||||
|
||||
int res = gui::show_dialog(gui_,NULL,"",
|
||||
string_table["choose_weapon"]+":\n",
|
||||
gui::OK_CANCEL,&items,&units_list,"",NULL,NULL,NULL,-1,-1,
|
||||
NULL,&buttons);
|
||||
int res = 0;
|
||||
|
||||
{
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane attacker_preview(gui_,&map_,u->second,true);
|
||||
dialogs::unit_preview_pane defender_preview(gui_,&map_,enemy->second,false);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&attacker_preview);
|
||||
preview_panes.push_back(&defender_preview);
|
||||
|
||||
res = gui::show_dialog(gui_,NULL,string_table["attack_enemy"],
|
||||
string_table["choose_weapon"]+":\n",
|
||||
gui::OK_CANCEL,&items,&preview_panes,"",NULL,NULL,NULL,-1,-1,
|
||||
NULL,&buttons);
|
||||
}
|
||||
|
||||
cursor::set(cursor::NORMAL);
|
||||
|
||||
|
@ -701,13 +709,13 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
} catch(end_level_exception&) {
|
||||
//if the level ends due to a unit being killed, still see if
|
||||
//either the attacker or defender should advance
|
||||
dialogs::advance_unit(gameinfo_,units_,selected_hex_,gui_);
|
||||
dialogs::advance_unit(gameinfo_,units_,hex,gui_,!defender_human);
|
||||
dialogs::advance_unit(gameinfo_,map_,units_,selected_hex_,gui_);
|
||||
dialogs::advance_unit(gameinfo_,map_,units_,hex,gui_,!defender_human);
|
||||
throw;
|
||||
}
|
||||
|
||||
dialogs::advance_unit(gameinfo_,units_,selected_hex_,gui_);
|
||||
dialogs::advance_unit(gameinfo_,units_,hex,gui_,!defender_human);
|
||||
dialogs::advance_unit(gameinfo_,map_,units_,selected_hex_,gui_);
|
||||
dialogs::advance_unit(gameinfo_,map_,units_,hex,gui_,!defender_human);
|
||||
|
||||
selected_hex_ = gamemap::location();
|
||||
current_route_.steps.clear();
|
||||
|
@ -1339,117 +1347,25 @@ void turn_info::terrain_table()
|
|||
{
|
||||
unit_map::const_iterator un = current_unit();
|
||||
|
||||
if(un == units_.end()) {
|
||||
return;
|
||||
if(un != units_.end()) {
|
||||
dialogs::show_unit_terrain_table(gui_,map_,un->second);
|
||||
}
|
||||
|
||||
gui_.draw();
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(string_table["terrain"] + "," +
|
||||
string_table["movement"] + "," +
|
||||
string_table["defense"]);
|
||||
|
||||
const unit_type& type = un->second.type();
|
||||
const unit_movement_type& move_type = type.movement_type();
|
||||
const std::vector<gamemap::TERRAIN>& terrains =
|
||||
map_.get_terrain_precedence();
|
||||
for(std::vector<gamemap::TERRAIN>::const_iterator t =
|
||||
terrains.begin(); t != terrains.end(); ++t) {
|
||||
|
||||
//exclude fog and shroud
|
||||
if(*t == gamemap::FOGGED || *t == gamemap::VOID_TERRAIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const terrain_type& info = map_.get_terrain_info(*t);
|
||||
if(!info.is_alias()) {
|
||||
const std::string& name = map_.terrain_name(*t);
|
||||
const std::string& lang_name = string_table[name];
|
||||
const int moves = move_type.movement_cost(map_,*t);
|
||||
|
||||
std::stringstream str;
|
||||
str << lang_name << ",";
|
||||
if(moves < 100)
|
||||
str << moves;
|
||||
else
|
||||
str << "--";
|
||||
|
||||
const int defense = 100 - move_type.defense_modifier(map_,*t);
|
||||
str << "," << defense << "%";
|
||||
|
||||
items.push_back(str.str());
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<unit> units_list(items.size(),un->second);
|
||||
const scoped_sdl_surface unit_image(image::get_image(un->second.type().image_profile(),image::UNSCALED));
|
||||
gui::show_dialog(gui_,unit_image,un->second.type().language_name(),
|
||||
string_table["terrain_info"],
|
||||
gui::MESSAGE,&items,&units_list);
|
||||
}
|
||||
|
||||
void turn_info::attack_resistance()
|
||||
{
|
||||
const unit_map::const_iterator un = current_unit();
|
||||
if(un == units_.end())
|
||||
return;
|
||||
|
||||
gui_.draw();
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(string_table["attack_type"] + "," +
|
||||
string_table["attack_resistance"]);
|
||||
const std::map<std::string,std::string>& table =
|
||||
un->second.type().movement_type().damage_table();
|
||||
for(std::map<std::string,std::string>::const_iterator i
|
||||
= table.begin(); i != table.end(); ++i) {
|
||||
int resistance = 100 - atoi(i->second.c_str());
|
||||
|
||||
//if resistance is less than 0, display in red
|
||||
const char prefix = resistance < 0 ? font::BAD_TEXT : font::NULL_MARKUP;
|
||||
|
||||
const std::string& lang_weapon = string_table["weapon_type_" + i->first];
|
||||
const std::string& weap = lang_weapon.empty() ? i->first : lang_weapon;
|
||||
|
||||
std::stringstream str;
|
||||
str << weap << "," << prefix << resistance << "%";
|
||||
items.push_back(str.str());
|
||||
if(un != units_.end()) {
|
||||
dialogs::show_unit_resistance(gui_,un->second);
|
||||
}
|
||||
|
||||
const std::vector<unit> units_list(items.size(), un->second);
|
||||
const scoped_sdl_surface unit_image(image::get_image(un->second.type().image_profile(),image::UNSCALED));
|
||||
gui::show_dialog(gui_,unit_image,
|
||||
un->second.type().language_name(),
|
||||
string_table["unit_resistance_table"],
|
||||
gui::MESSAGE,&items,&units_list);
|
||||
}
|
||||
|
||||
void turn_info::unit_description()
|
||||
{
|
||||
const unit_map::const_iterator un = current_unit();
|
||||
if(un == units_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string description = un->second.unit_description()
|
||||
+ "\n\n" + string_table["see_also"];
|
||||
|
||||
std::vector<std::string> options;
|
||||
|
||||
options.push_back(string_table["terrain_info"]);
|
||||
options.push_back(string_table["attack_resistance"]);
|
||||
options.push_back(string_table["close_window"]);
|
||||
|
||||
const scoped_sdl_surface unit_image(image::get_image(un->second.type().image_profile(), image::UNSCALED));
|
||||
|
||||
const int res = gui::show_dialog(gui_,unit_image,
|
||||
un->second.type().language_name(),
|
||||
description,gui::MESSAGE, &options);
|
||||
if(res == 0) {
|
||||
terrain_table();
|
||||
} else if(res == 1) {
|
||||
attack_resistance();
|
||||
if(un != units_.end()) {
|
||||
dialogs::show_unit_description(gui_,map_,un->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,9 +1573,19 @@ void turn_info::recruit()
|
|||
return;
|
||||
}
|
||||
|
||||
const int recruit_res = gui::show_dialog(gui_,NULL,"",
|
||||
string_table["recruit_unit"] + ":\n",
|
||||
gui::OK_CANCEL,&items,&sample_units);
|
||||
int recruit_res = 0;
|
||||
|
||||
{
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(gui_,&map_,sample_units);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
recruit_res = gui::show_dialog(gui_,NULL,"",
|
||||
string_table["recruit_unit"] + ":\n",
|
||||
gui::OK_CANCEL,&items,&preview_panes);
|
||||
}
|
||||
|
||||
if(recruit_res != -1) {
|
||||
do_recruit(item_keys[recruit_res]);
|
||||
}
|
||||
|
@ -1814,11 +1740,21 @@ void turn_info::recall()
|
|||
std::vector<gui::dialog_button> buttons;
|
||||
buttons.push_back(delete_button);
|
||||
|
||||
const int res = gui::show_dialog(gui_,NULL,"",
|
||||
string_table["select_unit"] + ":\n",
|
||||
gui::OK_CANCEL,&options,
|
||||
&recall_list,"",NULL,
|
||||
NULL,NULL,-1,-1,NULL,&buttons);
|
||||
int res = 0;
|
||||
|
||||
{
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(gui_,&map_,recall_list);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
res = gui::show_dialog(gui_,NULL,"",
|
||||
string_table["select_unit"] + ":\n",
|
||||
gui::OK_CANCEL,&options,
|
||||
&preview_panes,"",NULL,
|
||||
NULL,NULL,-1,-1,NULL,&buttons);
|
||||
}
|
||||
|
||||
if(res >= 0) {
|
||||
unit& un = recall_list[res];
|
||||
gamemap::location loc = last_hex_;
|
||||
|
@ -1899,8 +1835,18 @@ void turn_info::create_unit()
|
|||
unit_choices.back().new_turn();
|
||||
}
|
||||
|
||||
const int choice = gui::show_dialog(gui_,NULL,"","Create unit (debug):",
|
||||
gui::OK_CANCEL,&options,&unit_choices);
|
||||
int choice = 0;
|
||||
|
||||
{
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(gui_,&map_,unit_choices);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
choice = gui::show_dialog(gui_,NULL,"","Create unit (debug):",
|
||||
gui::OK_CANCEL,&options,&preview_panes);
|
||||
}
|
||||
|
||||
if(choice >= 0 && choice < unit_choices.size()) {
|
||||
units_.erase(last_hex_);
|
||||
units_.insert(std::pair<gamemap::location,unit>(last_hex_,unit_choices[choice]));
|
||||
|
@ -1967,8 +1913,18 @@ void turn_info::unit_list()
|
|||
units_list.push_back(i->second);
|
||||
}
|
||||
|
||||
const int selected = gui::show_dialog(gui_,NULL,string_table["unit_list"],"",
|
||||
gui::OK_ONLY,&items,&units_list);
|
||||
int selected = 0;
|
||||
|
||||
{
|
||||
const events::event_context dialog_events_context;
|
||||
dialogs::unit_preview_pane unit_preview(gui_,&map_,units_list);
|
||||
std::vector<gui::preview_pane*> preview_panes;
|
||||
preview_panes.push_back(&unit_preview);
|
||||
|
||||
selected = gui::show_dialog(gui_,NULL,string_table["unit_list"],"",
|
||||
gui::OK_ONLY,&items,&preview_panes);
|
||||
}
|
||||
|
||||
if(selected > 0 && selected < int(locations_list.size())) {
|
||||
const gamemap::location& loc = locations_list[selected];
|
||||
gui_.scroll_to_tile(loc.x,loc.y,display::WARP);
|
||||
|
|
|
@ -316,7 +316,7 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
const std::string& caption, const std::string& msg,
|
||||
DIALOG_TYPE type,
|
||||
const std::vector<std::string>* menu_items_ptr,
|
||||
const std::vector<unit>* units_ptr,
|
||||
const std::vector<preview_pane*>* preview_panes,
|
||||
const std::string& text_widget_label,
|
||||
std::string* text_widget_text,
|
||||
dialog_action* action, std::vector<check_item>* options, int xloc, int yloc,
|
||||
|
@ -327,7 +327,10 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
|
||||
std::cerr << "showing dialog '" << caption << "' '" << msg << "'\n";
|
||||
|
||||
const events::event_context dialog_events_context;
|
||||
//create the event context, but only activate it if we don't have preview panes.
|
||||
//the presence of preview panes indicates that the caller will create the context,
|
||||
//so that their preview panes may fall inside it.
|
||||
const events::event_context dialog_events_context(preview_panes == NULL);
|
||||
const dialog_manager manager;
|
||||
|
||||
const events::resize_lock prevent_resizing;
|
||||
|
@ -335,9 +338,6 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
const std::vector<std::string>& menu_items =
|
||||
(menu_items_ptr == NULL) ? std::vector<std::string>() : *menu_items_ptr;
|
||||
|
||||
const std::vector<unit> empty_units;
|
||||
const std::vector<unit>& units = (units_ptr == NULL) ? empty_units : *units_ptr;
|
||||
|
||||
static const int message_font_size = 16;
|
||||
static const int caption_font_size = 18;
|
||||
|
||||
|
@ -459,6 +459,19 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
}
|
||||
}
|
||||
|
||||
size_t preview_pane_height = 0, left_preview_pane_width = 0, right_preview_pane_width = 0;
|
||||
if(preview_panes != NULL) {
|
||||
for(std::vector<preview_pane*>::const_iterator i = preview_panes->begin(); i != preview_panes->end(); ++i) {
|
||||
const SDL_Rect& rect = (**i).location();
|
||||
preview_pane_height = maximum<size_t>(rect.h,preview_pane_height);
|
||||
if((**i).left_side()) {
|
||||
left_preview_pane_width += rect.w;
|
||||
} else {
|
||||
right_preview_pane_width += rect.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int left_padding = 10;
|
||||
const int right_padding = 10;
|
||||
const int image_h_padding = image != NULL ? 10 : 0;
|
||||
|
@ -489,45 +502,62 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
padding_height + menu_.height() +
|
||||
text_widget_height + check_button_height;
|
||||
|
||||
if(xloc <= -1 || yloc <= -1) {
|
||||
xloc = scr->w/2 - total_width/2;
|
||||
yloc = scr->h/2 - total_height/2;
|
||||
}
|
||||
|
||||
int unitx = 0;
|
||||
int unity = 0;
|
||||
//if we are showing a dialog with unit details, then we have
|
||||
//to make more room for it
|
||||
if(!units.empty()) {
|
||||
xloc += scr->w/10;
|
||||
unitx = xloc - 300;
|
||||
if(unitx < 10)
|
||||
unitx = 10;
|
||||
|
||||
unity = yloc;
|
||||
}
|
||||
|
||||
const int border_padding = 10;
|
||||
const int frame_width = total_width + border_padding*2;
|
||||
const int frame_height = total_height + border_padding*2;
|
||||
int frame_width = total_width + border_padding*2;
|
||||
int xframe = maximum<int>(0,xloc >= 0 ? xloc : scr->w/2 - (frame_width + left_preview_pane_width + right_preview_pane_width)/2);
|
||||
|
||||
const int frame_height = maximum<int>(int(preview_pane_height),total_height + border_padding*2);
|
||||
|
||||
if(xloc <= -1 || yloc <= -1) {
|
||||
xloc = xframe + left_preview_pane_width;
|
||||
yloc = scr->h/2 - frame_height/2;
|
||||
}
|
||||
|
||||
if(xloc + frame_width > scr->w) {
|
||||
xloc = scr->w - frame_width;
|
||||
if(xloc < xframe) {
|
||||
xframe = xloc;
|
||||
}
|
||||
}
|
||||
|
||||
if(yloc + frame_height > scr->h) {
|
||||
yloc = scr->h - frame_height;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<button*> buttons_ptr;
|
||||
for(std::vector<button>::iterator bt = buttons.begin(); bt != buttons.end(); ++bt) {
|
||||
buttons_ptr.push_back(&*bt);
|
||||
}
|
||||
|
||||
frame_width += left_preview_pane_width + right_preview_pane_width;
|
||||
|
||||
surface_restorer restorer;
|
||||
|
||||
const std::string& title = image == NULL ? caption : "";
|
||||
draw_dialog(xloc,yloc,total_width,total_height,disp,title,dialog_style,&buttons_ptr,&restorer);
|
||||
draw_dialog(xframe,yloc,frame_width,frame_height,disp,title,dialog_style,&buttons_ptr,&restorer);
|
||||
|
||||
//calculate the positions of the preview panes to the sides of the dialog
|
||||
if(preview_panes != NULL) {
|
||||
|
||||
frame_width += left_preview_pane_width + right_preview_pane_width;
|
||||
|
||||
int left_preview_pane = xframe;
|
||||
int right_preview_pane = xframe + total_width + left_preview_pane_width;
|
||||
|
||||
for(std::vector<preview_pane*>::const_iterator i = preview_panes->begin(); i != preview_panes->end(); ++i) {
|
||||
SDL_Rect area = (**i).location();
|
||||
area.y = yloc;
|
||||
if((**i).left_side()) {
|
||||
area.x = left_preview_pane;
|
||||
left_preview_pane += area.w;
|
||||
} else {
|
||||
area.x = right_preview_pane;
|
||||
right_preview_pane += area.w;
|
||||
}
|
||||
|
||||
(**i).set_location(area);
|
||||
}
|
||||
}
|
||||
|
||||
const int menu_xpos = xloc+total_image_width+left_padding+image_h_padding;
|
||||
const int menu_ypos = yloc+top_padding+text_and_image_height+menu_hpadding;
|
||||
|
@ -664,16 +694,10 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
selection = 0;
|
||||
}
|
||||
|
||||
if(size_t(selection) < units.size()) {
|
||||
draw_dialog_frame(unitx,unity,unitw,unith,disp);
|
||||
|
||||
SDL_Rect clip_rect = { unitx, unity, unitw, unith };
|
||||
|
||||
disp.draw_unit_details(unitx+left_padding,
|
||||
unity+top_padding+60, gamemap::location(), units[selection],
|
||||
unit_details_rect, unitx+left_padding, unity+top_padding,
|
||||
&clip_rect);
|
||||
disp.update_display();
|
||||
if(preview_panes != NULL) {
|
||||
for(std::vector<preview_pane*>::const_iterator i = preview_panes->begin(); i != preview_panes->end(); ++i) {
|
||||
(**i).set_selection(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,7 +706,7 @@ int show_dialog(display& disp, SDL_Surface* image,
|
|||
if(menu_.height() > 0) {
|
||||
const int res = menu_.process(mousex,mousey,new_left_button,
|
||||
!up_arrow && new_up_arrow,
|
||||
!down_arrow && new_down_arrow,
|
||||
!down_arrow && new_down_arrow,
|
||||
!page_up && new_page_up,
|
||||
!page_down && new_page_down,
|
||||
select_item);
|
||||
|
|
|
@ -112,6 +112,17 @@ struct check_item {
|
|||
bool checked;
|
||||
};
|
||||
|
||||
//an interface for a 'preview pane'. A preview pane is shown beside a dialog created
|
||||
//by 'show_dialog' and shows information about the selection.
|
||||
class preview_pane : public widget {
|
||||
public:
|
||||
preview_pane(display& disp) : widget(disp) {}
|
||||
virtual ~preview_pane() {}
|
||||
|
||||
virtual bool left_side() const = 0;
|
||||
virtual void set_selection(int index) = 0;
|
||||
};
|
||||
|
||||
//function to chop up one long string of text into lines
|
||||
size_t text_to_lines(std::string& text, size_t max_length);
|
||||
|
||||
|
@ -122,7 +133,7 @@ int show_dialog(display& screen, SDL_Surface* image,
|
|||
const std::string& caption, const std::string& message,
|
||||
DIALOG_TYPE type=MESSAGE,
|
||||
const std::vector<std::string>* menu_items=NULL,
|
||||
const std::vector<unit>* units=NULL,
|
||||
const std::vector<preview_pane*>* preview_panes=NULL,
|
||||
const std::string& text_widget_label="",
|
||||
std::string* text_widget_text=NULL,
|
||||
dialog_action* action=NULL,
|
||||
|
|
Loading…
Add table
Reference in a new issue