made it possible to delete saved games, and delete units from the recall list

This commit is contained in:
Dave White 2004-03-23 19:32:34 +00:00
parent 1b4149d5e1
commit d2c585faec
15 changed files with 213 additions and 9 deletions

View File

@ -192,6 +192,16 @@ your_turn="It is now your turn"
leader="Leader"
delete_unit="Dismiss Unit"
delete_save="Delete Save"
really_delete_save="Do you really want to delete this game?"
dont_ask_again="Don't ask me again!"
really_delete_veteran_unit="My lord, this unit is an experienced one, having advanced levels! Do you really want to dismiss $noun?"
really_delete_xp_unit="My lord, this unit is close to advancing a level! Do you really want to dismiss $noun?"
noun_male="him"
noun_female="her"
#fighting statistics
action_statistics="Statistics"
base_damage="base damage"

View File

@ -1,6 +1,7 @@
[unit]
name=Elvish Druid
race=elf
gender=female
image=elvish-druid.png
image_defensive=elvish-druid-defend.png
hitpoints=36

View File

@ -1,6 +1,7 @@
[unit]
name=Elvish Shyde
race=elf
gender=female
image=elvish-shyde.png
hitpoints=46
movement_type=woodlandfloat

View File

@ -14,10 +14,12 @@
#include "dialogs.hpp"
#include "font.hpp"
#include "language.hpp"
#include "preferences.hpp"
#include "replay.hpp"
#include "show_dialog.hpp"
#include "util.hpp"
#include <cstdio>
#include <map>
#include <sstream>
#include <string>
@ -125,9 +127,65 @@ int get_save_name(display & disp,const std::string& caption, const std::string&
return res;
}
//a class to handle deleting a saved game
namespace {
class delete_save : public gui::dialog_button_action
{
public:
delete_save(display& disp, std::vector<save_info>& saves) : disp_(disp), saves_(saves) {}
private:
gui::dialog_button_action::RESULT button_pressed(int menu_selection);
display& disp_;
std::vector<save_info>& saves_;
};
gui::dialog_button_action::RESULT delete_save::button_pressed(int menu_selection)
{
const size_t index = size_t(menu_selection);
if(index < saves_.size()) {
//see if we should ask the user for deletion confirmation
if(preferences::ask_delete_saves()) {
std::vector<gui::check_item> options;
options.push_back(gui::check_item(string_table["dont_ask_again"],false));
const int res = gui::show_dialog(disp_,NULL,"",string_table["really_delete_save"],gui::YES_NO,
NULL,NULL,"",NULL,NULL,&options);
//see if the user doesn't want to be asked this again
assert(options.empty() == false);
if(options.front().checked) {
preferences::set_ask_delete_saves(false);
}
if(res != 0) {
return gui::dialog_button_action::NO_EFFECT;
}
}
//delete the file
delete_game(saves_[index].name);
//remove it from the list of saves
saves_.erase(saves_.begin() + index);
return gui::dialog_button_action::DELETE_ITEM;
} else {
return gui::dialog_button_action::NO_EFFECT;
}
}
} //end anon namespace
std::string load_game_dialog(display& disp, bool* show_replay)
{
const std::vector<save_info>& games = get_saves_list();
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,
@ -162,7 +220,7 @@ std::string load_game_dialog(display& disp, bool* show_replay)
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);
gui::OK_CANCEL,&items,NULL,"",NULL,NULL,&options,-1,-1,NULL,&buttons);
if(res == -1)
return "";

View File

@ -258,6 +258,15 @@ bool save_game_exists(const std::string& name)
return file_exists(get_saves_dir() + "/" + fname);
}
void delete_game(const std::string& name)
{
std::string modified_name = name;
std::replace(modified_name.begin(),modified_name.end(),' ','_');
remove((get_saves_dir() + "/" + name).c_str());
remove((get_saves_dir() + "/" + modified_name).c_str());
}
void load_game(game_data& data, const std::string& name, game_state& state)
{
log_scope("load_game");

View File

@ -134,5 +134,7 @@ void load_game(game_data& data, const std::string& name, game_state& state);
//throws gamestatus::save_game_failed
void save_game(const game_state& state);
//function to delete a save
void delete_game(const std::string& name);
#endif

View File

@ -422,13 +422,13 @@ public:
: disp_(disp), stats_(stats)
{}
void button_pressed(int selection);
RESULT button_pressed(int selection);
private:
display& disp_;
std::vector<battle_stats>& stats_;
};
void attack_calculations_displayer::button_pressed(int selection)
gui::dialog_button_action::RESULT attack_calculations_displayer::button_pressed(int selection)
{
const size_t index = size_t(selection);
if(index < stats_.size()) {
@ -464,6 +464,8 @@ void attack_calculations_displayer::button_pressed(int selection)
gui::show_dialog(disp_,NULL,"",string_table["damage_calculations"],gui::OK_ONLY,&calcs);
}
return NO_EFFECT;
}
}
@ -1466,6 +1468,59 @@ void turn_info::repeat_recruit()
do_recruit(last_recruit_);
}
//a class to handle deleting an item from the recall list
namespace {
class delete_recall_unit : public gui::dialog_button_action
{
public:
delete_recall_unit(display& disp, std::vector<unit>& units) : disp_(disp), units_(units) {}
private:
gui::dialog_button_action::RESULT button_pressed(int menu_selection);
display& disp_;
std::vector<unit>& units_;
};
gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_selection)
{
const size_t index = size_t(menu_selection);
if(index < units_.size()) {
const unit& u = units_[index];
//if the unit is of level > 1, or is close to advancing, we warn the player
//about it
std::string message = "";
if(u.type().level() > 1) {
message = string_table["really_delete_veteran_unit"];
} else if(u.experience() > u.max_experience()/2) {
message = string_table["really_delete_xp_unit"];
}
if(message != "") {
const std::string replace_str("$noun");
const std::string::iterator itor = std::search(message.begin(),message.end(),replace_str.begin(),replace_str.end());
if(itor != message.end()) {
const std::string::size_type index = itor - message.begin();
message.erase(itor,itor+replace_str.size());
message.insert(index,string_table[u.type().gender() == unit_race::MALE ? "noun_male" : "noun_female"]);
}
const int res = gui::show_dialog(disp_,NULL,"",message,gui::YES_NO);
if(res != 0) {
return gui::dialog_button_action::NO_EFFECT;
}
}
units_.erase(units_.begin() + index);
return gui::dialog_button_action::DELETE_ITEM;
} else {
return gui::dialog_button_action::NO_EFFECT;
}
}
} //end anon namespace
void turn_info::recall()
{
if(browse_)
@ -1511,10 +1566,16 @@ void turn_info::recall()
options.push_back(option.str());
}
delete_recall_unit recall_deleter(gui_,state_of_game_.available_units);
gui::dialog_button delete_button(&recall_deleter,string_table["delete_unit"]);
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,
&state_of_game_.available_units);
&state_of_game_.available_units,"",NULL,
NULL,NULL,-1,-1,NULL,&buttons);
if(res >= 0) {
const std::string err = recruit_unit(map_,team_num_,
units_,state_of_game_.available_units[res],

View File

@ -350,6 +350,16 @@ bool show_side_colours()
return prefs["show_side_colours"] == "yes";
}
void set_ask_delete_saves(bool value)
{
prefs["ask_delete"] = value ? "yes" : "no";
}
bool ask_delete_saves()
{
return prefs["ask_delete"] != "no";
}
std::string client_type()
{
if(prefs["client_type"] == "ai")

View File

@ -79,6 +79,9 @@ namespace preferences {
void set_show_side_colours(bool value);
bool show_side_colours();
void set_ask_delete_saves(bool value);
bool ask_delete_saves();
std::string client_type();
void set_theme(const std::string& theme);

View File

@ -645,7 +645,13 @@ int show_dialog(display& disp, SDL_Surface* image,
const size_t options_size = options == NULL ? 0 : options->size();
assert(action_buttons != NULL && action_buttons->size() > n - options_size);
(*action_buttons)[n - options_size].handler->button_pressed(menu_.selection());
const dialog_button_action::RESULT res = (*action_buttons)[n - options_size].handler->button_pressed(menu_.selection());
if(res == dialog_button_action::DELETE_ITEM) {
menu_.erase_item(menu_.selection());
if(menu_.nitems() == 0) {
return -1;
}
}
}
}

View File

@ -63,7 +63,9 @@ class dialog_button_action
public:
virtual ~dialog_button_action() {}
virtual void button_pressed(int menu_selection) = 0;
enum RESULT { DELETE_ITEM, NO_EFFECT };
virtual RESULT button_pressed(int menu_selection) = 0;
};
struct dialog_button

View File

@ -384,6 +384,8 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
const race_map& races, const std::vector<config*>& traits)
: cfg_(cfg), alpha_(1.0), possibleTraits_(traits), movementType_(cfg)
{
gender_ = cfg["gender"] == "female" ? unit_race::FEMALE : unit_race::MALE;
const race_map::const_iterator race_it = races.find(cfg["race"]);
if(race_it != races.end()) {
race_ = &race_it->second;
@ -692,6 +694,8 @@ const std::vector<config*>& unit_type::possible_traits() const
return possibleTraits_;
}
unit_race::GENDER unit_type::gender() const { return gender_; }
game_data::game_data(const config& cfg)
{
static const std::vector<config*> dummy_traits;

View File

@ -189,6 +189,8 @@ public:
const std::vector<config*>& possible_traits() const;
unit_race::GENDER gender() const;
private:
const config& cfg_;
@ -210,6 +212,8 @@ private:
unit_movement_type movementType_;
const std::vector<config*>& possibleTraits_;
unit_race::GENDER gender_;
};
struct game_data

View File

@ -143,6 +143,22 @@ void menu::change_item(int pos1, int pos2,std::string str)
items_[pos1][pos2] = str;
}
void menu::erase_item(size_t index)
{
if(index < items_.size()) {
clear_item(items_.size()-1);
items_.erase(items_.begin() + index);
itemRects_.clear();
if(size_t(selected_) >= items_.size()) {
selected_ = int(items_.size()-1);
}
calculate_position();
drawn_ = false;
}
}
size_t menu::max_items_onscreen() const
{
if(max_items_ != -1) {
@ -176,7 +192,9 @@ void menu::calculate_position()
if(selected_ < first_item_on_screen_) {
first_item_on_screen_ = selected_;
itemRects_.clear();
} else if(selected_ >= first_item_on_screen_ + int(max_items_onscreen())) {
}
if(selected_ >= first_item_on_screen_ + int(max_items_onscreen())) {
first_item_on_screen_ = selected_ - (max_items_onscreen() - 1);
itemRects_.clear();
}
@ -438,7 +456,7 @@ const std::vector<int>& menu::column_widths() const
return column_widths_;
}
void menu::draw_item(int item)
void menu::clear_item(int item)
{
SDL_Rect rect = get_item_rect(item);
if(rect.w == 0) {
@ -452,6 +470,16 @@ void menu::draw_item(int item)
SDL_BlitSurface(buffer_,&srcrect,
display_->video().getSurface(),&dstrect);
}
}
void menu::draw_item(int item)
{
SDL_Rect rect = get_item_rect(item);
if(rect.w == 0) {
return;
}
clear_item(item);
gui::draw_solid_tinted_rectangle(x_,rect.y,width()-scrollbar_.get_width(),rect.h,
item == selected_ ? 150:0,0,0,

View File

@ -33,6 +33,10 @@ public:
// allows user to change_item while running (dangerous)
void change_item(int pos1,int pos2,std::string str);
void erase_item(size_t index);
size_t nitems() const { return items_.size(); }
int process(int x, int y, bool button,bool up_arrow,bool down_arrow,
bool page_up, bool page_down, int select_item=-1);
@ -75,6 +79,7 @@ private:
const std::vector<int>& column_widths() const;
void draw_item(int item);
void clear_item(int item);
void draw();
int hit(int x, int y) const;