codeclean, whitespace changes only (line endings and spaces at end of lines)
This commit is contained in:
parent
35b99383a4
commit
13bb34761d
31 changed files with 2042 additions and 2042 deletions
|
@ -706,7 +706,7 @@ void attack(display& gui, const gamemap& map,
|
|||
|
||||
int orig_attacks = stats.nattacks;
|
||||
int orig_defends = stats.ndefends;
|
||||
|
||||
|
||||
int to_the_death = stats.to_the_death ? 30 : 0;
|
||||
bool slow_affects_attacker = a->second.has_flag("slowed");
|
||||
bool slow_affects_defender = d->second.has_flag("slowed");
|
||||
|
@ -2103,7 +2103,7 @@ bool backstab_check(const gamemap::location& attacker_loc,
|
|||
const std::map<gamemap::location,unit>::const_iterator defender =
|
||||
units.find(defender_loc);
|
||||
if(defender == units.end()) return false; // No defender
|
||||
|
||||
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(defender_loc, adj);
|
||||
int i;
|
||||
|
|
|
@ -185,7 +185,7 @@ void ai::do_attack_analysis(
|
|||
//so we only check for 'concrete' backstab opportunities.
|
||||
//That would also break backstab_check, since it
|
||||
//assumes the defender is in place.
|
||||
if(itor != units_.end() &&
|
||||
if(itor != units_.end() &&
|
||||
backstab_check(tiles[j], loc, units_, teams_)) {
|
||||
if(backstab) {
|
||||
backstab_bonus = 2;
|
||||
|
|
|
@ -9,14 +9,14 @@ namespace dfool {
|
|||
bool found=false;
|
||||
std::string unit_id=(**a)["unit_id"];
|
||||
for(unit_map::const_iterator i = my_units.begin(); i != my_units.end(); ++i) {
|
||||
|
||||
|
||||
LOG_STREAM(info, ai)<<"\t\tcomparing "<<i->second.underlying_description() <<" to "<<(**a)["unit_id"] << " \n";
|
||||
|
||||
|
||||
if(i->second.underlying_description()==unit_id){
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
LOG_STREAM(info, ai)<<"\tfound an existing assignments\n";
|
||||
unit_assignment[unit_id]=(**a)["order"];
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace dfool {
|
|||
std::map<std::string, std::string>unit_assignment;
|
||||
};
|
||||
|
||||
//an ai that keeps track of what it has "seen" and does not target units
|
||||
//an ai that keeps track of what it has "seen" and does not target units
|
||||
//that it has not "seen" or recruit based on unseen units.
|
||||
class dfool_ai : public ai_interface {
|
||||
public:
|
||||
|
@ -36,14 +36,14 @@ namespace dfool {
|
|||
// sprintf(buf,"%d,%s",count,ai_mem["test"].c_str());
|
||||
// ai_mem["test"]=buf;
|
||||
// current_team().set_ai_memory(ai_mem);
|
||||
|
||||
|
||||
|
||||
|
||||
config side_filter;
|
||||
char buf[80];
|
||||
sprintf(buf,"%d",team_num);
|
||||
side_filter["side"]=buf;
|
||||
unit_map my_units=filter_units(info_.units,side_filter);
|
||||
|
||||
|
||||
//make sure previously assigned units still exist
|
||||
config::child_list order_assignments;
|
||||
assignment_list.clear();
|
||||
|
@ -57,14 +57,14 @@ namespace dfool {
|
|||
LOG_STREAM(info, ai)<<"\t\tchecking for existing assignments\n";
|
||||
bool found=false;
|
||||
for(unit_map::const_iterator i = my_units.begin(); i != my_units.end(); ++i) {
|
||||
|
||||
|
||||
LOG_STREAM(info, ai)<<"\t\tcomparing "<<i->second.underlying_description() <<" to "<<(**a)["unit_id"] << " \n";
|
||||
|
||||
|
||||
if(i->second.underlying_description()==(**a)["unit_id"]){
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
LOG_STREAM(info, ai)<<"\tfound an existing assignments\n";
|
||||
order_assignments.push_back(*a);
|
||||
|
@ -73,8 +73,8 @@ namespace dfool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const unit_map& v_units=visible_units(info_.units);
|
||||
LOG_STREAM(info, ai)<<"dfool sees:"<<std::endl;
|
||||
for(unit_map::const_iterator ui = v_units.begin(); ui != v_units.end(); ++ui) {
|
||||
|
@ -90,12 +90,12 @@ namespace dfool {
|
|||
bool pers=(id.size()>0);
|
||||
LOG_STREAM(info, ai)<<"dfool order("<<(pers?id:"")<<"): "<<num<<(num==1?" unit":" units")<<" with priority "<<prior<<std::endl;
|
||||
const config::child_list& filter = (**o).get_children("filter");
|
||||
|
||||
|
||||
const config::child_list& clear_assign = (**o).get_children("clear_assignment");
|
||||
unit_map matching_units;
|
||||
unit_map assigned_units;
|
||||
int count=num;
|
||||
|
||||
|
||||
assigned_units.clear();
|
||||
//find units assigned to this order;
|
||||
for(config::child_list::const_iterator at = order_assignments.begin(); at != order_assignments.end(); ++at) {
|
||||
|
@ -116,7 +116,7 @@ namespace dfool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
matching_units.clear();
|
||||
//find units that match any filter. If no filters then accept all units.
|
||||
if(filter.size()){
|
||||
|
@ -139,22 +139,22 @@ namespace dfool {
|
|||
matching_units.insert(*i);
|
||||
LOG_STREAM(info, ai)<<"\t\tmatching: "<<i->second.underlying_description()<<" to order: "<<id<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
matching_units=my_units;
|
||||
}
|
||||
|
||||
|
||||
//should add sorting functionality here in future
|
||||
//bring assigned units up to maximum number
|
||||
for(unit_map::const_iterator mu = matching_units.begin(); mu != matching_units.end() && order_assignments.size()<num; ++mu) {
|
||||
assigned_units.insert(*mu);
|
||||
LOG_STREAM(info, ai)<<"\tassigned unit:\t"<<mu->second.underlying_description()<<"\n";
|
||||
}
|
||||
|
||||
|
||||
if(order_assignments.size()){
|
||||
LOG_STREAM(info, ai)<<"\t "<<assigned_units.size()<<(assigned_units.size()==1?" unit assigned":" units assigned")<<std::endl;
|
||||
|
||||
|
||||
const config::child_list& commands = (**o).get_children("command");
|
||||
for(config::child_list::const_iterator com = commands.begin(); com != commands.end(); ++com) {
|
||||
std::string type=(**com)["type"];
|
||||
|
@ -164,7 +164,7 @@ namespace dfool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//save assignments into memory
|
||||
if(id.size()){
|
||||
for(unit_map::const_iterator au = assigned_units.begin(); au != assigned_units.end(); ++au) {
|
||||
|
@ -185,7 +185,7 @@ namespace dfool {
|
|||
unit_map visible_units_;
|
||||
unit_map my_units_;
|
||||
config assignment_list;
|
||||
|
||||
|
||||
bool clear_assignment(const location& loc, const config::child_list& clear,const gamemap& map)
|
||||
{
|
||||
for(config::child_list::const_iterator cl=clear.begin();cl<clear.end();cl++)
|
||||
|
@ -200,7 +200,7 @@ namespace dfool {
|
|||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
const unit_map& visible_units(const unit_map& units_)
|
||||
{
|
||||
visible_units_.clear();
|
||||
|
@ -214,23 +214,23 @@ namespace dfool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOG_STREAM(info, ai) << "number of visible units: " << visible_units_.size() << "\n";
|
||||
//still need to deal with invisible units not in fog.
|
||||
return visible_units_;
|
||||
}
|
||||
|
||||
|
||||
unit_map filter_units(const unit_map& units_,const config& filter)
|
||||
{
|
||||
unit_map filtered_units_;
|
||||
for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
|
||||
if(i->second.matches_filter(filter)) {
|
||||
filtered_units_.insert(*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filtered_units_;
|
||||
}
|
||||
|
||||
|
||||
void moveto(config::child_list::const_iterator o, unit_map matching_units){
|
||||
location target(atoi((**o)["target_x"].c_str())-1,atoi((**o)["target_y"].c_str())-1);
|
||||
LOG_STREAM(info, ai)<<"\tmoving to:("<<target.x<<","<<target.y<<")"<<std::endl;
|
||||
|
@ -239,10 +239,10 @@ namespace dfool {
|
|||
std::map<location,paths> possible_moves;
|
||||
move_map srcdst, dstsrc;
|
||||
calculate_possible_moves(possible_moves,srcdst,dstsrc,false);
|
||||
|
||||
|
||||
int closest_distance = -1;
|
||||
std::pair<location,location> closest_move;
|
||||
|
||||
|
||||
//this undoubtedly could be done more cleanly
|
||||
for(move_map::const_iterator i = dstsrc.begin(); i != dstsrc.end(); ++i) {
|
||||
//must restrict move_map to only unit that is moving.
|
||||
|
|
|
@ -1,188 +1,188 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include "config_adapter.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "preferences.hpp"
|
||||
|
||||
#define LOG_NG LOG_STREAM(info, engine)
|
||||
|
||||
std::string get_unique_saveid(const config& cfg, std::set<std::string>& seen_save_ids){
|
||||
std::string save_id = cfg["save_id"];
|
||||
|
||||
if(save_id.empty()) {
|
||||
save_id=cfg["description"];
|
||||
}
|
||||
|
||||
if(save_id.empty()) {
|
||||
save_id="Unknown";
|
||||
}
|
||||
|
||||
//make sure the 'save_id' is unique
|
||||
while(seen_save_ids.count(save_id)) {
|
||||
save_id += "_";
|
||||
}
|
||||
|
||||
return save_id;
|
||||
}
|
||||
|
||||
void get_player_info(const config& cfg, game_state& gamestate, std::string save_id, std::vector<team>& teams, const config& level, const game_data& gameinfo, gamemap& map, unit_map& units){
|
||||
player_info *player = NULL;
|
||||
|
||||
if(cfg["controller"] == "human" ||
|
||||
cfg["controller"] == "network" ||
|
||||
cfg["persistent"] == "1") {
|
||||
player = gamestate.get_player(save_id);
|
||||
|
||||
if(player == NULL && !save_id.empty()) {
|
||||
player = &gamestate.players[save_id];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_NG << "initializing team...\n";
|
||||
|
||||
std::string gold = cfg["gold"];
|
||||
if(gold.empty())
|
||||
gold = "100";
|
||||
|
||||
LOG_NG << "found gold: '" << gold << "'\n";
|
||||
|
||||
int ngold = lexical_cast_default<int>(gold);
|
||||
if(player != NULL && player->gold >= ngold) {
|
||||
ngold = player->gold;
|
||||
}
|
||||
|
||||
LOG_NG << "set gold to '" << ngold << "'\n";
|
||||
|
||||
teams.push_back(team(cfg,ngold));
|
||||
|
||||
//update/fix the recall list for this side, by setting the
|
||||
//"side" of each unit in it to be the "side" of the player.
|
||||
int side = lexical_cast_default<int>(cfg["side"], 1);
|
||||
if(player != NULL) {
|
||||
for(std::vector<unit>::iterator it = player->available_units.begin(); it != player->available_units.end(); ++it) {
|
||||
it->set_side(side);
|
||||
}
|
||||
}
|
||||
|
||||
//if this team has no objectives, set its objectives to the
|
||||
//level-global "objectives"
|
||||
if(teams.back().objectives().empty())
|
||||
teams.back().set_objectives(level["objectives"]);
|
||||
|
||||
//if this side tag describes the leader of the side
|
||||
if(cfg["no_leader"] != "yes" && cfg["controller"] != "null") {
|
||||
unit new_unit(gameinfo, cfg);
|
||||
|
||||
//search the recall list for leader units, and if there is
|
||||
//one, use it in place of the config-described unit
|
||||
if(player != NULL) {
|
||||
for(std::vector<unit>::iterator it = player->available_units.begin(); it != player->available_units.end(); ++it) {
|
||||
if(it->can_recruit()) {
|
||||
new_unit = *it;
|
||||
player->available_units.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//see if the side specifies its location. Otherwise start it at the map-given
|
||||
//starting position
|
||||
gamemap::location start_pos(cfg);
|
||||
|
||||
if(map.empty()) {
|
||||
throw game::load_game_failed("Map not found");
|
||||
}
|
||||
if(cfg["x"].empty() && cfg["y"].empty()) {
|
||||
start_pos = map.starting_position(side);
|
||||
}
|
||||
|
||||
if(!start_pos.valid() || !map.on_board(start_pos)) {
|
||||
throw game::load_game_failed(
|
||||
"Invalid starting position (" +
|
||||
lexical_cast<std::string>(start_pos.x+1) +
|
||||
"," + lexical_cast<std::string>(start_pos.y+1) +
|
||||
") for the leader of side " +
|
||||
lexical_cast<std::string>(side) + ".");
|
||||
}
|
||||
|
||||
new_unit.new_turn();
|
||||
units.insert(std::pair<gamemap::location,unit>(
|
||||
map.starting_position(new_unit.side()), new_unit));
|
||||
LOG_NG << "initializing side '" << cfg["side"] << "' at "
|
||||
<< start_pos << '\n';
|
||||
}
|
||||
|
||||
//if the game state specifies units that can be recruited for the player
|
||||
//then add them
|
||||
if(player != NULL && player->can_recruit.empty() == false) {
|
||||
std::copy(player->can_recruit.begin(),player->can_recruit.end(),
|
||||
std::inserter(teams.back().recruits(),teams.back().recruits().end()));
|
||||
}
|
||||
|
||||
if(player != NULL) {
|
||||
player->can_recruit = teams.back().recruits();
|
||||
}
|
||||
|
||||
//if there are additional starting units on this side
|
||||
const config::child_list& starting_units = cfg.get_children("unit");
|
||||
for(config::child_list::const_iterator su = starting_units.begin(); su != starting_units.end(); ++su) {
|
||||
unit new_unit(gameinfo,**su);
|
||||
|
||||
new_unit.set_side(side);
|
||||
|
||||
const std::string& x = (**su)["x"];
|
||||
const std::string& y = (**su)["y"];
|
||||
|
||||
const gamemap::location loc(**su);
|
||||
if(x.empty() && y.empty()) {
|
||||
if(player) {
|
||||
player->available_units.push_back(new_unit);
|
||||
LOG_NG << "inserting unit on recall list for side " << new_unit.side() << "\n";
|
||||
} else {
|
||||
throw game::load_game_failed(
|
||||
"Attempt to create a unit on the recall list for side " +
|
||||
lexical_cast<std::string>(side) +
|
||||
", which does not have a recall list.");
|
||||
}
|
||||
} else if(!loc.valid() || !map.on_board(loc)) {
|
||||
throw game::load_game_failed(
|
||||
"Invalid starting position (" +
|
||||
lexical_cast<std::string>(loc.x+1) +
|
||||
"," + lexical_cast<std::string>(loc.y+1) +
|
||||
") for a unit on side " +
|
||||
lexical_cast<std::string>(side) + ".");
|
||||
} else {
|
||||
units.insert(std::pair<gamemap::location,unit>(loc,new_unit));
|
||||
LOG_NG << "inserting unit for side " << new_unit.side() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_first_human_team(const config::child_list::const_iterator& cfg, const config::child_list& unit_cfg){
|
||||
int result = -1;
|
||||
const std::string& controller = (**cfg)["controller"];
|
||||
if (controller == preferences::client_type() && (**cfg)["description"] == preferences::login()) {
|
||||
result = cfg - unit_cfg.begin();
|
||||
} else if(result == -1 && ((**cfg)["controller"] == "human" || (**cfg)["persistent"] == "1")) {
|
||||
result = cfg - unit_cfg.begin();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const config* get_theme(const config& game_config, std::string theme_name){
|
||||
const config* theme_cfg = NULL;
|
||||
if(theme_name != "") {
|
||||
theme_cfg = game_config.find_child("theme","name",theme_name);
|
||||
}
|
||||
|
||||
if(theme_cfg == NULL) {
|
||||
theme_cfg = game_config.find_child("theme","name",preferences::theme());
|
||||
}
|
||||
if (theme_cfg == NULL){
|
||||
theme_cfg = new config();
|
||||
}
|
||||
return theme_cfg;
|
||||
}
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include "config_adapter.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "preferences.hpp"
|
||||
|
||||
#define LOG_NG LOG_STREAM(info, engine)
|
||||
|
||||
std::string get_unique_saveid(const config& cfg, std::set<std::string>& seen_save_ids){
|
||||
std::string save_id = cfg["save_id"];
|
||||
|
||||
if(save_id.empty()) {
|
||||
save_id=cfg["description"];
|
||||
}
|
||||
|
||||
if(save_id.empty()) {
|
||||
save_id="Unknown";
|
||||
}
|
||||
|
||||
//make sure the 'save_id' is unique
|
||||
while(seen_save_ids.count(save_id)) {
|
||||
save_id += "_";
|
||||
}
|
||||
|
||||
return save_id;
|
||||
}
|
||||
|
||||
void get_player_info(const config& cfg, game_state& gamestate, std::string save_id, std::vector<team>& teams, const config& level, const game_data& gameinfo, gamemap& map, unit_map& units){
|
||||
player_info *player = NULL;
|
||||
|
||||
if(cfg["controller"] == "human" ||
|
||||
cfg["controller"] == "network" ||
|
||||
cfg["persistent"] == "1") {
|
||||
player = gamestate.get_player(save_id);
|
||||
|
||||
if(player == NULL && !save_id.empty()) {
|
||||
player = &gamestate.players[save_id];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_NG << "initializing team...\n";
|
||||
|
||||
std::string gold = cfg["gold"];
|
||||
if(gold.empty())
|
||||
gold = "100";
|
||||
|
||||
LOG_NG << "found gold: '" << gold << "'\n";
|
||||
|
||||
int ngold = lexical_cast_default<int>(gold);
|
||||
if(player != NULL && player->gold >= ngold) {
|
||||
ngold = player->gold;
|
||||
}
|
||||
|
||||
LOG_NG << "set gold to '" << ngold << "'\n";
|
||||
|
||||
teams.push_back(team(cfg,ngold));
|
||||
|
||||
//update/fix the recall list for this side, by setting the
|
||||
//"side" of each unit in it to be the "side" of the player.
|
||||
int side = lexical_cast_default<int>(cfg["side"], 1);
|
||||
if(player != NULL) {
|
||||
for(std::vector<unit>::iterator it = player->available_units.begin(); it != player->available_units.end(); ++it) {
|
||||
it->set_side(side);
|
||||
}
|
||||
}
|
||||
|
||||
//if this team has no objectives, set its objectives to the
|
||||
//level-global "objectives"
|
||||
if(teams.back().objectives().empty())
|
||||
teams.back().set_objectives(level["objectives"]);
|
||||
|
||||
//if this side tag describes the leader of the side
|
||||
if(cfg["no_leader"] != "yes" && cfg["controller"] != "null") {
|
||||
unit new_unit(gameinfo, cfg);
|
||||
|
||||
//search the recall list for leader units, and if there is
|
||||
//one, use it in place of the config-described unit
|
||||
if(player != NULL) {
|
||||
for(std::vector<unit>::iterator it = player->available_units.begin(); it != player->available_units.end(); ++it) {
|
||||
if(it->can_recruit()) {
|
||||
new_unit = *it;
|
||||
player->available_units.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//see if the side specifies its location. Otherwise start it at the map-given
|
||||
//starting position
|
||||
gamemap::location start_pos(cfg);
|
||||
|
||||
if(map.empty()) {
|
||||
throw game::load_game_failed("Map not found");
|
||||
}
|
||||
if(cfg["x"].empty() && cfg["y"].empty()) {
|
||||
start_pos = map.starting_position(side);
|
||||
}
|
||||
|
||||
if(!start_pos.valid() || !map.on_board(start_pos)) {
|
||||
throw game::load_game_failed(
|
||||
"Invalid starting position (" +
|
||||
lexical_cast<std::string>(start_pos.x+1) +
|
||||
"," + lexical_cast<std::string>(start_pos.y+1) +
|
||||
") for the leader of side " +
|
||||
lexical_cast<std::string>(side) + ".");
|
||||
}
|
||||
|
||||
new_unit.new_turn();
|
||||
units.insert(std::pair<gamemap::location,unit>(
|
||||
map.starting_position(new_unit.side()), new_unit));
|
||||
LOG_NG << "initializing side '" << cfg["side"] << "' at "
|
||||
<< start_pos << '\n';
|
||||
}
|
||||
|
||||
//if the game state specifies units that can be recruited for the player
|
||||
//then add them
|
||||
if(player != NULL && player->can_recruit.empty() == false) {
|
||||
std::copy(player->can_recruit.begin(),player->can_recruit.end(),
|
||||
std::inserter(teams.back().recruits(),teams.back().recruits().end()));
|
||||
}
|
||||
|
||||
if(player != NULL) {
|
||||
player->can_recruit = teams.back().recruits();
|
||||
}
|
||||
|
||||
//if there are additional starting units on this side
|
||||
const config::child_list& starting_units = cfg.get_children("unit");
|
||||
for(config::child_list::const_iterator su = starting_units.begin(); su != starting_units.end(); ++su) {
|
||||
unit new_unit(gameinfo,**su);
|
||||
|
||||
new_unit.set_side(side);
|
||||
|
||||
const std::string& x = (**su)["x"];
|
||||
const std::string& y = (**su)["y"];
|
||||
|
||||
const gamemap::location loc(**su);
|
||||
if(x.empty() && y.empty()) {
|
||||
if(player) {
|
||||
player->available_units.push_back(new_unit);
|
||||
LOG_NG << "inserting unit on recall list for side " << new_unit.side() << "\n";
|
||||
} else {
|
||||
throw game::load_game_failed(
|
||||
"Attempt to create a unit on the recall list for side " +
|
||||
lexical_cast<std::string>(side) +
|
||||
", which does not have a recall list.");
|
||||
}
|
||||
} else if(!loc.valid() || !map.on_board(loc)) {
|
||||
throw game::load_game_failed(
|
||||
"Invalid starting position (" +
|
||||
lexical_cast<std::string>(loc.x+1) +
|
||||
"," + lexical_cast<std::string>(loc.y+1) +
|
||||
") for a unit on side " +
|
||||
lexical_cast<std::string>(side) + ".");
|
||||
} else {
|
||||
units.insert(std::pair<gamemap::location,unit>(loc,new_unit));
|
||||
LOG_NG << "inserting unit for side " << new_unit.side() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_first_human_team(const config::child_list::const_iterator& cfg, const config::child_list& unit_cfg){
|
||||
int result = -1;
|
||||
const std::string& controller = (**cfg)["controller"];
|
||||
if (controller == preferences::client_type() && (**cfg)["description"] == preferences::login()) {
|
||||
result = cfg - unit_cfg.begin();
|
||||
} else if(result == -1 && ((**cfg)["controller"] == "human" || (**cfg)["persistent"] == "1")) {
|
||||
result = cfg - unit_cfg.begin();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const config* get_theme(const config& game_config, std::string theme_name){
|
||||
const config* theme_cfg = NULL;
|
||||
if(theme_name != "") {
|
||||
theme_cfg = game_config.find_child("theme","name",theme_name);
|
||||
}
|
||||
|
||||
if(theme_cfg == NULL) {
|
||||
theme_cfg = game_config.find_child("theme","name",preferences::theme());
|
||||
}
|
||||
if (theme_cfg == NULL){
|
||||
theme_cfg = new config();
|
||||
}
|
||||
return theme_cfg;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
/* $Id: config.hpp 8785 2005-11-08 22:23:03Z jhinrichs $ */
|
||||
/*
|
||||
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#ifndef CONFIG_ADAPTER_HPP_INCLUDED
|
||||
#define CONFIG_ADAPTER_HPP_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
|
||||
class unit;
|
||||
|
||||
//This module is responsible for constructing objects like 'team'
|
||||
//or 'unit' out of config-information, that is based on WML.
|
||||
|
||||
std::string get_unique_saveid(const config& cfg, std::set<std::string>& seen_save_ids);
|
||||
int get_first_human_team(const config::child_list::const_iterator& cfg, const config::child_list& unit_cfg);
|
||||
void get_player_info(const config& cfg, game_state& gamestate, std::string save_id, std::vector<team>& teams, const config& level, const game_data& gameinfo, gamemap& map, std::map<gamemap::location,unit>& units);
|
||||
const config* get_theme(const config& game_config, std::string theme_name);
|
||||
|
||||
#endif
|
||||
/* $Id: config.hpp 8785 2005-11-08 22:23:03Z jhinrichs $ */
|
||||
/*
|
||||
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#ifndef CONFIG_ADAPTER_HPP_INCLUDED
|
||||
#define CONFIG_ADAPTER_HPP_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
|
||||
class unit;
|
||||
|
||||
//This module is responsible for constructing objects like 'team'
|
||||
//or 'unit' out of config-information, that is based on WML.
|
||||
|
||||
std::string get_unique_saveid(const config& cfg, std::set<std::string>& seen_save_ids);
|
||||
int get_first_human_team(const config::child_list::const_iterator& cfg, const config::child_list& unit_cfg);
|
||||
void get_player_info(const config& cfg, game_state& gamestate, std::string save_id, std::vector<team>& teams, const config& level, const game_data& gameinfo, gamemap& map, std::map<gamemap::location,unit>& units);
|
||||
const config* get_theme(const config& game_config, std::string theme_name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1000,7 +1000,7 @@ void display::draw_report(reports::TYPE report_num)
|
|||
int red = (RGB & 0x00FF0000)>>16;
|
||||
int green = (RGB & 0x0000FF00)>>8;
|
||||
int blue = (RGB & 0x000000FF);
|
||||
|
||||
|
||||
std::string c_start="<";
|
||||
std::string c_sep=",";
|
||||
std::string c_end=">";
|
||||
|
@ -1058,7 +1058,7 @@ void display::draw_report(reports::TYPE report_num)
|
|||
|
||||
if(rect.w + rect.x - x < img->w && image_count){
|
||||
//we have more than one image, and this one doesn't fit.
|
||||
img=surface(image::get_image(game_config::ellipsis_image,image::UNSCALED));
|
||||
img=surface(image::get_image(game_config::ellipsis_image,image::UNSCALED));
|
||||
used_ellipsis=true;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1070,7 @@ void display::draw_report(reports::TYPE report_num)
|
|||
|
||||
image_count++;
|
||||
if(area.h > tallest) tallest = area.h;
|
||||
|
||||
|
||||
if(! used_ellipsis){
|
||||
x += area.w;
|
||||
}else{
|
||||
|
@ -1343,7 +1343,7 @@ void display::draw_unit_on_tile(int x, int y, surface unit_image_override,
|
|||
}
|
||||
|
||||
const fixed_t bar_alpha = highlight_ratio < ftofxp(1.0) && blend_with == 0 ? highlight_ratio : (loc == mouseoverHex_ ? ftofxp(1.0): ftofxp(0.6));
|
||||
|
||||
|
||||
if(energy_file != NULL) {
|
||||
draw_bar(*energy_file,xpos,ypos,(u.max_hitpoints()*2)/3,unit_energy,energy_colour,bar_alpha);
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ public:
|
|||
//Setting the reach_map clears the paths_list, and vice-versa.
|
||||
typedef std::map<gamemap::location,unsigned int> reach_map;
|
||||
void set_reach_map(const reach_map *reach_map);
|
||||
|
||||
|
||||
//sets the route along which footsteps are drawn to show movement of a
|
||||
//unit. If NULL, no route is displayed.
|
||||
//route does not have to remain valid after being set
|
||||
|
|
|
@ -1495,7 +1495,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOG_NG << "done handling command...\n";
|
||||
|
||||
return rval;
|
||||
|
|
|
@ -166,7 +166,7 @@ locator& locator::operator=(const locator &a)
|
|||
}
|
||||
|
||||
locator::value::value(const locator::value& a) :
|
||||
type_(a.type_), filename_(a.filename_), loc_(a.loc_),
|
||||
type_(a.type_), filename_(a.filename_), loc_(a.loc_),
|
||||
new_color(a.new_color), swap_colors(a.swap_colors)
|
||||
{
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ surface locator::load_image_sub_file() const
|
|||
|
||||
surface tmp(cut_surface(mother_surface, srcrect));
|
||||
surf=mask_surface(tmp, mask);
|
||||
}
|
||||
}
|
||||
if(val_.swap_colors.size()){
|
||||
surf=recolor_image(surf,get_new_color(),get_swap_colors());
|
||||
}
|
||||
|
|
|
@ -65,15 +65,15 @@ namespace image {
|
|||
type type_;
|
||||
std::string filename_;
|
||||
gamemap::location loc_;
|
||||
Uint32 new_color;
|
||||
std::vector<Uint32> swap_colors;
|
||||
Uint32 new_color;
|
||||
std::vector<Uint32> swap_colors;
|
||||
};
|
||||
|
||||
// Constructing locators is somewhat slow, accessing image
|
||||
// through locators is fast. The idea is that calling functions
|
||||
// should store locators, and not strings to construct locators
|
||||
// (the second will work, of course, but will be slower)
|
||||
locator();
|
||||
locator();
|
||||
locator(const locator &a);
|
||||
locator(const char *filename);
|
||||
locator(const char *filename, Uint32 new_rgb, std::vector<Uint32> swap_rgb);
|
||||
|
|
|
@ -225,13 +225,13 @@ const language_def& get_language() { return current_language; }
|
|||
const language_def& get_locale()
|
||||
{
|
||||
//TODO: Add in support for querying the locale on Windows
|
||||
|
||||
|
||||
wassert(known_languages.size() != 0);
|
||||
|
||||
const std::string& prefs_locale = preferences::language();
|
||||
if(prefs_locale.empty() == false) {
|
||||
wesnoth_setlocale(LC_MESSAGES, prefs_locale);
|
||||
for(std::vector<language_def>::const_iterator i = known_languages.begin();
|
||||
for(std::vector<language_def>::const_iterator i = known_languages.begin();
|
||||
i != known_languages.end(); ++i) {
|
||||
if (prefs_locale == i->localename)
|
||||
return *i;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
namespace font {
|
||||
|
||||
const char LARGE_TEXT='*', SMALL_TEXT='`', GOOD_TEXT='@', BAD_TEXT='#',
|
||||
NORMAL_TEXT='{', BLACK_TEXT='}', BOLD_TEXT='~', IMAGE='&',
|
||||
NORMAL_TEXT='{', BLACK_TEXT='}', BOLD_TEXT='~', IMAGE='&',
|
||||
COLOR_TEXT='<', NULL_MARKUP='^';
|
||||
|
||||
namespace {
|
||||
|
@ -84,8 +84,8 @@ std::string::const_iterator parse_markup(std::string::const_iterator i1, std::st
|
|||
case COLOR_TEXT:
|
||||
{
|
||||
//very primitive parsing for rgb value
|
||||
//should look like <213,14,151>
|
||||
//but no checking on commas or end '>',
|
||||
//should look like <213,14,151>
|
||||
//but no checking on commas or end '>',
|
||||
//could be any non-# char
|
||||
++i1;
|
||||
Uint8 red=0, green=0, blue=0, temp=0;
|
||||
|
@ -123,7 +123,7 @@ std::string::const_iterator parse_markup(std::string::const_iterator i1, std::st
|
|||
default:
|
||||
return i1;
|
||||
}
|
||||
|
||||
|
||||
++i1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,409 +1,409 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include "dialogs.hpp"
|
||||
#include "display.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "help.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
#include "menu_events.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "unit_types.hpp"
|
||||
#include "wml_separators.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace events{
|
||||
|
||||
bool is_illegal_file_char(char c)
|
||||
{
|
||||
return c == '/' || c == '\\' || c == ':';
|
||||
}
|
||||
|
||||
void menu_handler::objectives(display& gui, const config& level, team& current_team)
|
||||
{
|
||||
dialogs::show_objectives(gui, level, current_team.objectives());
|
||||
current_team.reset_objectives_changed();
|
||||
}
|
||||
|
||||
void menu_handler::show_statistics(display& gui, const game_data& gameinfo)
|
||||
{
|
||||
const statistics::stats& stats = statistics::calculate_stats(0,gui.viewing_team()+1);
|
||||
std::vector<std::string> items;
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Recruits") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.recruits);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Recalls") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.recalls);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Advancements") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.advanced_to);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Losses") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.deaths);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Kills") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.killed);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Inflicted") << COLUMN_SEPARATOR << stats.damage_inflicted;
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Taken") << COLUMN_SEPARATOR << stats.damage_taken;
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Inflicted (EV)") << COLUMN_SEPARATOR
|
||||
<< (stats.expected_damage_inflicted / 100.0);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Taken (EV)") << COLUMN_SEPARATOR
|
||||
<< (stats.expected_damage_taken / 100.0);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
const int res = gui::show_dialog(gui, NULL, _("Statistics"), "", gui::OK_CANCEL, &items);
|
||||
std::string title;
|
||||
std::vector<std::string> items_sub;
|
||||
|
||||
switch(res) {
|
||||
case 0:
|
||||
items_sub = create_unit_table(stats.recruits, gameinfo);
|
||||
title = _("Recruits");
|
||||
break;
|
||||
case 1:
|
||||
items_sub = create_unit_table(stats.recalls, gameinfo);
|
||||
title = _("Recalls");
|
||||
break;
|
||||
case 2:
|
||||
items_sub = create_unit_table(stats.advanced_to, gameinfo);
|
||||
title = _("Advancements");
|
||||
break;
|
||||
case 3:
|
||||
items_sub = create_unit_table(stats.deaths, gameinfo);
|
||||
title = _("Losses");
|
||||
break;
|
||||
case 4:
|
||||
items_sub = create_unit_table(stats.killed, gameinfo);
|
||||
title = _("Kills");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (items_sub.empty() == false)
|
||||
gui::show_dialog(gui, NULL, "", title, gui::OK_ONLY, &items_sub);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> menu_handler::create_unit_table(const statistics::stats::str_int_map& m, const game_data& gameinfo)
|
||||
{
|
||||
std::vector<std::string> table;
|
||||
for(statistics::stats::str_int_map::const_iterator i = m.begin(); i != m.end(); ++i) {
|
||||
const game_data::unit_type_map::const_iterator type = gameinfo.unit_types.find(i->first);
|
||||
if(type == gameinfo.unit_types.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
str << IMAGE_PREFIX << type->second.image() << COLUMN_SEPARATOR
|
||||
<< type->second.language_name() << COLUMN_SEPARATOR << i->second << "\n";
|
||||
table.push_back(str.str());
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void menu_handler::unit_list(const unit_map& units, display& gui, const gamemap& map)
|
||||
{
|
||||
const std::string heading = std::string(1,HEADING_PREFIX) +
|
||||
_("Type") + COLUMN_SEPARATOR +
|
||||
_("Name") + COLUMN_SEPARATOR +
|
||||
_("HP") + COLUMN_SEPARATOR +
|
||||
_("XP") + COLUMN_SEPARATOR +
|
||||
_("Traits") + COLUMN_SEPARATOR +
|
||||
_("Moves") + COLUMN_SEPARATOR +
|
||||
_("Location");
|
||||
|
||||
gui::menu::basic_sorter sorter;
|
||||
sorter.set_alpha_sort(0).set_alpha_sort(1).set_numeric_sort(2).set_numeric_sort(3)
|
||||
.set_alpha_sort(4).set_numeric_sort(5).set_numeric_sort(6);
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(heading);
|
||||
|
||||
std::vector<gamemap::location> locations_list;
|
||||
std::vector<unit> units_list;
|
||||
for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() != (gui.viewing_team()+1))
|
||||
continue;
|
||||
|
||||
std::stringstream row;
|
||||
row << i->second.type().language_name() << COLUMN_SEPARATOR
|
||||
<< i->second.description() << COLUMN_SEPARATOR
|
||||
<< i->second.hitpoints() << "/" << i->second.max_hitpoints() << COLUMN_SEPARATOR
|
||||
<< i->second.experience() << "/";
|
||||
|
||||
if(i->second.can_advance() == false)
|
||||
row << "-";
|
||||
else
|
||||
row << i->second.max_experience();
|
||||
|
||||
row << COLUMN_SEPARATOR
|
||||
<< i->second.traits_description() << COLUMN_SEPARATOR
|
||||
<< i->second.movement_left() << "/"
|
||||
<< i->second.total_movement() << COLUMN_SEPARATOR
|
||||
<< i->first;
|
||||
|
||||
items.push_back(row.str());
|
||||
|
||||
locations_list.push_back(i->first);
|
||||
units_list.push_back(i->second);
|
||||
}
|
||||
|
||||
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,_("Unit List"),"",
|
||||
gui::OK_ONLY,&items,&preview_panes,
|
||||
"",NULL,0,NULL,NULL,-1,-1,NULL,NULL,"",&sorter);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::status_table(std::vector<team>& teams, display& gui, const unit_map& units)
|
||||
{
|
||||
std::stringstream heading;
|
||||
heading << HEADING_PREFIX << _("Leader") << COLUMN_SEPARATOR << ' ' << COLUMN_SEPARATOR
|
||||
<< _("Gold") << COLUMN_SEPARATOR
|
||||
<< _("Villages") << COLUMN_SEPARATOR
|
||||
<< _("Units") << COLUMN_SEPARATOR
|
||||
<< _("Upkeep") << COLUMN_SEPARATOR
|
||||
<< _("Income");
|
||||
|
||||
gui::menu::basic_sorter sorter;
|
||||
sorter.set_redirect_sort(0,1).set_alpha_sort(1).set_numeric_sort(2).set_numeric_sort(3)
|
||||
.set_numeric_sort(4).set_numeric_sort(5).set_numeric_sort(6).set_numeric_sort(7);
|
||||
|
||||
if(game_config::debug)
|
||||
heading << COLUMN_SEPARATOR << _("Gold");
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(heading.str());
|
||||
|
||||
const team& viewing_team = teams[gui.viewing_team()];
|
||||
|
||||
//if the player is under shroud or fog, they don't get to see
|
||||
//details about the other sides, only their own side, allied sides and a ??? is
|
||||
//shown to demonstrate lack of information about the other sides
|
||||
bool fog = false;
|
||||
for(size_t n = 0; n != teams.size(); ++n) {
|
||||
if(teams[n].is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool known = viewing_team.knows_about_team(n);
|
||||
const bool enemy = viewing_team.is_enemy(n+1);
|
||||
if(!known) {
|
||||
fog = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const team_data data = calculate_team_data(teams[n],n+1,units);
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
const unit_map::const_iterator leader = team_leader(n+1,units);
|
||||
//output the number of the side first, and this will
|
||||
//cause it to be displayed in the correct colour
|
||||
if(leader != units.end()) {
|
||||
str << IMAGE_PREFIX << leader->second.type().image() << COLUMN_SEPARATOR
|
||||
<< "\033[3" << lexical_cast<char, size_t>(n+1) << 'm' << leader->second.description() << COLUMN_SEPARATOR;
|
||||
} else {
|
||||
str << ' ' << COLUMN_SEPARATOR << "\033[3" << lexical_cast<char, size_t>(n+1) << "m-" << COLUMN_SEPARATOR;
|
||||
}
|
||||
|
||||
if(enemy) {
|
||||
str << ' ' << COLUMN_SEPARATOR;
|
||||
} else {
|
||||
str << data.gold << COLUMN_SEPARATOR;
|
||||
}
|
||||
str << data.villages << COLUMN_SEPARATOR
|
||||
<< data.units << COLUMN_SEPARATOR << data.upkeep << COLUMN_SEPARATOR
|
||||
<< (data.net_income < 0 ? font::BAD_TEXT : font::NULL_MARKUP) << data.net_income;
|
||||
|
||||
if(game_config::debug)
|
||||
str << COLUMN_SEPARATOR << teams[n].gold();
|
||||
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
if(fog)
|
||||
items.push_back(IMAGE_PREFIX + std::string("random-enemy.png") + COLUMN_SEPARATOR +
|
||||
IMAGE_PREFIX + "random-enemy.png");
|
||||
|
||||
gui::show_dialog(gui,NULL,"","",gui::CLOSE_ONLY,&items,
|
||||
NULL,"",NULL,0,NULL,NULL,-1,-1,NULL,NULL,"",&sorter);
|
||||
}
|
||||
|
||||
void menu_handler::save_game(const std::string& message, gui::DIALOG_TYPE dialog_type,
|
||||
const game_state& gamestate, const gamestatus& status, display& gui, const config& level,
|
||||
std::vector<team>& teams, const unit_map& units, const gamemap& map)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
const std::string ellipsed_name = font::make_text_ellipsis(gamestate.label,
|
||||
font::SIZE_NORMAL, 200);
|
||||
stream << ellipsed_name << " " << _("Turn")
|
||||
<< " " << status.turn();
|
||||
std::string label = stream.str();
|
||||
if(dialog_type == gui::NULL_DIALOG && message != "") {
|
||||
label = message;
|
||||
}
|
||||
|
||||
label.erase(std::remove_if(label.begin(),label.end(),is_illegal_file_char),label.end());
|
||||
|
||||
const int res = dialog_type == gui::NULL_DIALOG ? 0 : dialogs::get_save_name(gui,message,_("Name:"),&label,dialog_type);
|
||||
|
||||
if(std::count_if(label.begin(),label.end(),is_illegal_file_char)) {
|
||||
gui::show_dialog(gui,NULL,_("Error"),_("Save names may not contain colons, slashes, or backslashes. Please choose a different name."),gui::OK_ONLY);
|
||||
save_game(message,dialog_type, gamestate, status, gui, level, teams, units, map);
|
||||
return;
|
||||
}
|
||||
|
||||
if(res == 0) {
|
||||
config snapshot;
|
||||
write_game_snapshot(snapshot, level, gui, teams, units, status, gamestate, map);
|
||||
try {
|
||||
recorder.save_game(label, snapshot, gamestate.starting_pos);
|
||||
if(dialog_type != gui::NULL_DIALOG) {
|
||||
gui::show_dialog(gui,NULL,_("Saved"),_("The game has been saved"), gui::OK_ONLY);
|
||||
}
|
||||
} catch(game::save_game_failed&) {
|
||||
gui::show_dialog(gui,NULL,_("Error"),_("The game could not be saved"),gui::MESSAGE);
|
||||
//do not bother retrying, since the user can just try to save the game again
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::write_game_snapshot(config& start, const config& level, display& gui,
|
||||
std::vector<team>& teams, const unit_map& units, const gamestatus& status,
|
||||
const game_state& gamestate, const gamemap& map) const
|
||||
{
|
||||
start.values = level.values;
|
||||
|
||||
start["snapshot"] = "yes";
|
||||
|
||||
std::stringstream buf;
|
||||
buf << gui.playing_team();
|
||||
start["playing_team"] = buf.str();
|
||||
|
||||
for(std::vector<team>::const_iterator t = teams.begin(); t != teams.end(); ++t) {
|
||||
const int side_num = t - teams.begin() + 1;
|
||||
|
||||
config& side = start.add_child("side");
|
||||
t->write(side);
|
||||
side["no_leader"] = "yes";
|
||||
buf.str(std::string());
|
||||
buf << side_num;
|
||||
side["side"] = buf.str();
|
||||
|
||||
for(std::map<gamemap::location,unit>::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() == side_num) {
|
||||
config& u = side.add_child("unit");
|
||||
i->first.write(u);
|
||||
i->second.write(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status.write(start);
|
||||
game_events::write_events(start);
|
||||
|
||||
// Write terrain_graphics data in snapshot, too
|
||||
const config::child_list& terrains = level.get_children("terrain_graphics");
|
||||
for(config::child_list::const_iterator tg = terrains.begin();
|
||||
tg != terrains.end(); ++tg) {
|
||||
|
||||
start.add_child("terrain_graphics", **tg);
|
||||
}
|
||||
|
||||
write_game(gamestate,start,WRITE_SNAPSHOT_ONLY);
|
||||
|
||||
// Clobber gold values to make sure the snapshot uses the values
|
||||
// in [side] instead.
|
||||
const config::child_list& players=start.get_children("player");
|
||||
for(config::child_list::const_iterator pi=players.begin();
|
||||
pi!=players.end(); ++pi) {
|
||||
(**pi)["gold"] = "-1000000";
|
||||
}
|
||||
|
||||
//write out the current state of the map
|
||||
start["map_data"] = map.write();
|
||||
|
||||
gui.labels().write(start);
|
||||
}
|
||||
|
||||
void menu_handler::load_game(display& gui, const config& terrain_config, const game_data& gameinfo){
|
||||
bool show_replay = false;
|
||||
const std::string game = dialogs::load_game_dialog(gui,terrain_config,gameinfo,&show_replay);
|
||||
if(game != "") {
|
||||
throw game::load_game_exception(game,show_replay);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::preferences(display& gui, const config& terrain_config)
|
||||
{
|
||||
preferences::show_preferences_dialog(gui,terrain_config);
|
||||
gui.redraw_everything();
|
||||
}
|
||||
|
||||
void menu_handler::show_chat_log(std::vector<team>& teams, display& gui)
|
||||
{
|
||||
std::string text = recorder.build_chat_log(teams[gui.viewing_team()].team_name());
|
||||
gui::show_dialog(gui,NULL,_("Chat Log"),"",gui::CLOSE_ONLY,NULL,NULL,"",&text);
|
||||
}
|
||||
|
||||
void menu_handler::show_help(display& gui)
|
||||
{
|
||||
help::show_help(gui);
|
||||
}
|
||||
}
|
||||
#include "global.hpp"
|
||||
|
||||
#include "dialogs.hpp"
|
||||
#include "display.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "help.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
#include "menu_events.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "unit_types.hpp"
|
||||
#include "wml_separators.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace events{
|
||||
|
||||
bool is_illegal_file_char(char c)
|
||||
{
|
||||
return c == '/' || c == '\\' || c == ':';
|
||||
}
|
||||
|
||||
void menu_handler::objectives(display& gui, const config& level, team& current_team)
|
||||
{
|
||||
dialogs::show_objectives(gui, level, current_team.objectives());
|
||||
current_team.reset_objectives_changed();
|
||||
}
|
||||
|
||||
void menu_handler::show_statistics(display& gui, const game_data& gameinfo)
|
||||
{
|
||||
const statistics::stats& stats = statistics::calculate_stats(0,gui.viewing_team()+1);
|
||||
std::vector<std::string> items;
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Recruits") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.recruits);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Recalls") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.recalls);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Advancements") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.advanced_to);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Losses") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.deaths);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Kills") << COLUMN_SEPARATOR << statistics::sum_str_int_map(stats.killed);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Inflicted") << COLUMN_SEPARATOR << stats.damage_inflicted;
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Taken") << COLUMN_SEPARATOR << stats.damage_taken;
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Inflicted (EV)") << COLUMN_SEPARATOR
|
||||
<< (stats.expected_damage_inflicted / 100.0);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream str;
|
||||
str << _("Damage Taken (EV)") << COLUMN_SEPARATOR
|
||||
<< (stats.expected_damage_taken / 100.0);
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
const int res = gui::show_dialog(gui, NULL, _("Statistics"), "", gui::OK_CANCEL, &items);
|
||||
std::string title;
|
||||
std::vector<std::string> items_sub;
|
||||
|
||||
switch(res) {
|
||||
case 0:
|
||||
items_sub = create_unit_table(stats.recruits, gameinfo);
|
||||
title = _("Recruits");
|
||||
break;
|
||||
case 1:
|
||||
items_sub = create_unit_table(stats.recalls, gameinfo);
|
||||
title = _("Recalls");
|
||||
break;
|
||||
case 2:
|
||||
items_sub = create_unit_table(stats.advanced_to, gameinfo);
|
||||
title = _("Advancements");
|
||||
break;
|
||||
case 3:
|
||||
items_sub = create_unit_table(stats.deaths, gameinfo);
|
||||
title = _("Losses");
|
||||
break;
|
||||
case 4:
|
||||
items_sub = create_unit_table(stats.killed, gameinfo);
|
||||
title = _("Kills");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (items_sub.empty() == false)
|
||||
gui::show_dialog(gui, NULL, "", title, gui::OK_ONLY, &items_sub);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> menu_handler::create_unit_table(const statistics::stats::str_int_map& m, const game_data& gameinfo)
|
||||
{
|
||||
std::vector<std::string> table;
|
||||
for(statistics::stats::str_int_map::const_iterator i = m.begin(); i != m.end(); ++i) {
|
||||
const game_data::unit_type_map::const_iterator type = gameinfo.unit_types.find(i->first);
|
||||
if(type == gameinfo.unit_types.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
str << IMAGE_PREFIX << type->second.image() << COLUMN_SEPARATOR
|
||||
<< type->second.language_name() << COLUMN_SEPARATOR << i->second << "\n";
|
||||
table.push_back(str.str());
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void menu_handler::unit_list(const unit_map& units, display& gui, const gamemap& map)
|
||||
{
|
||||
const std::string heading = std::string(1,HEADING_PREFIX) +
|
||||
_("Type") + COLUMN_SEPARATOR +
|
||||
_("Name") + COLUMN_SEPARATOR +
|
||||
_("HP") + COLUMN_SEPARATOR +
|
||||
_("XP") + COLUMN_SEPARATOR +
|
||||
_("Traits") + COLUMN_SEPARATOR +
|
||||
_("Moves") + COLUMN_SEPARATOR +
|
||||
_("Location");
|
||||
|
||||
gui::menu::basic_sorter sorter;
|
||||
sorter.set_alpha_sort(0).set_alpha_sort(1).set_numeric_sort(2).set_numeric_sort(3)
|
||||
.set_alpha_sort(4).set_numeric_sort(5).set_numeric_sort(6);
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(heading);
|
||||
|
||||
std::vector<gamemap::location> locations_list;
|
||||
std::vector<unit> units_list;
|
||||
for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() != (gui.viewing_team()+1))
|
||||
continue;
|
||||
|
||||
std::stringstream row;
|
||||
row << i->second.type().language_name() << COLUMN_SEPARATOR
|
||||
<< i->second.description() << COLUMN_SEPARATOR
|
||||
<< i->second.hitpoints() << "/" << i->second.max_hitpoints() << COLUMN_SEPARATOR
|
||||
<< i->second.experience() << "/";
|
||||
|
||||
if(i->second.can_advance() == false)
|
||||
row << "-";
|
||||
else
|
||||
row << i->second.max_experience();
|
||||
|
||||
row << COLUMN_SEPARATOR
|
||||
<< i->second.traits_description() << COLUMN_SEPARATOR
|
||||
<< i->second.movement_left() << "/"
|
||||
<< i->second.total_movement() << COLUMN_SEPARATOR
|
||||
<< i->first;
|
||||
|
||||
items.push_back(row.str());
|
||||
|
||||
locations_list.push_back(i->first);
|
||||
units_list.push_back(i->second);
|
||||
}
|
||||
|
||||
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,_("Unit List"),"",
|
||||
gui::OK_ONLY,&items,&preview_panes,
|
||||
"",NULL,0,NULL,NULL,-1,-1,NULL,NULL,"",&sorter);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::status_table(std::vector<team>& teams, display& gui, const unit_map& units)
|
||||
{
|
||||
std::stringstream heading;
|
||||
heading << HEADING_PREFIX << _("Leader") << COLUMN_SEPARATOR << ' ' << COLUMN_SEPARATOR
|
||||
<< _("Gold") << COLUMN_SEPARATOR
|
||||
<< _("Villages") << COLUMN_SEPARATOR
|
||||
<< _("Units") << COLUMN_SEPARATOR
|
||||
<< _("Upkeep") << COLUMN_SEPARATOR
|
||||
<< _("Income");
|
||||
|
||||
gui::menu::basic_sorter sorter;
|
||||
sorter.set_redirect_sort(0,1).set_alpha_sort(1).set_numeric_sort(2).set_numeric_sort(3)
|
||||
.set_numeric_sort(4).set_numeric_sort(5).set_numeric_sort(6).set_numeric_sort(7);
|
||||
|
||||
if(game_config::debug)
|
||||
heading << COLUMN_SEPARATOR << _("Gold");
|
||||
|
||||
std::vector<std::string> items;
|
||||
items.push_back(heading.str());
|
||||
|
||||
const team& viewing_team = teams[gui.viewing_team()];
|
||||
|
||||
//if the player is under shroud or fog, they don't get to see
|
||||
//details about the other sides, only their own side, allied sides and a ??? is
|
||||
//shown to demonstrate lack of information about the other sides
|
||||
bool fog = false;
|
||||
for(size_t n = 0; n != teams.size(); ++n) {
|
||||
if(teams[n].is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool known = viewing_team.knows_about_team(n);
|
||||
const bool enemy = viewing_team.is_enemy(n+1);
|
||||
if(!known) {
|
||||
fog = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const team_data data = calculate_team_data(teams[n],n+1,units);
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
const unit_map::const_iterator leader = team_leader(n+1,units);
|
||||
//output the number of the side first, and this will
|
||||
//cause it to be displayed in the correct colour
|
||||
if(leader != units.end()) {
|
||||
str << IMAGE_PREFIX << leader->second.type().image() << COLUMN_SEPARATOR
|
||||
<< "\033[3" << lexical_cast<char, size_t>(n+1) << 'm' << leader->second.description() << COLUMN_SEPARATOR;
|
||||
} else {
|
||||
str << ' ' << COLUMN_SEPARATOR << "\033[3" << lexical_cast<char, size_t>(n+1) << "m-" << COLUMN_SEPARATOR;
|
||||
}
|
||||
|
||||
if(enemy) {
|
||||
str << ' ' << COLUMN_SEPARATOR;
|
||||
} else {
|
||||
str << data.gold << COLUMN_SEPARATOR;
|
||||
}
|
||||
str << data.villages << COLUMN_SEPARATOR
|
||||
<< data.units << COLUMN_SEPARATOR << data.upkeep << COLUMN_SEPARATOR
|
||||
<< (data.net_income < 0 ? font::BAD_TEXT : font::NULL_MARKUP) << data.net_income;
|
||||
|
||||
if(game_config::debug)
|
||||
str << COLUMN_SEPARATOR << teams[n].gold();
|
||||
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
if(fog)
|
||||
items.push_back(IMAGE_PREFIX + std::string("random-enemy.png") + COLUMN_SEPARATOR +
|
||||
IMAGE_PREFIX + "random-enemy.png");
|
||||
|
||||
gui::show_dialog(gui,NULL,"","",gui::CLOSE_ONLY,&items,
|
||||
NULL,"",NULL,0,NULL,NULL,-1,-1,NULL,NULL,"",&sorter);
|
||||
}
|
||||
|
||||
void menu_handler::save_game(const std::string& message, gui::DIALOG_TYPE dialog_type,
|
||||
const game_state& gamestate, const gamestatus& status, display& gui, const config& level,
|
||||
std::vector<team>& teams, const unit_map& units, const gamemap& map)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
const std::string ellipsed_name = font::make_text_ellipsis(gamestate.label,
|
||||
font::SIZE_NORMAL, 200);
|
||||
stream << ellipsed_name << " " << _("Turn")
|
||||
<< " " << status.turn();
|
||||
std::string label = stream.str();
|
||||
if(dialog_type == gui::NULL_DIALOG && message != "") {
|
||||
label = message;
|
||||
}
|
||||
|
||||
label.erase(std::remove_if(label.begin(),label.end(),is_illegal_file_char),label.end());
|
||||
|
||||
const int res = dialog_type == gui::NULL_DIALOG ? 0 : dialogs::get_save_name(gui,message,_("Name:"),&label,dialog_type);
|
||||
|
||||
if(std::count_if(label.begin(),label.end(),is_illegal_file_char)) {
|
||||
gui::show_dialog(gui,NULL,_("Error"),_("Save names may not contain colons, slashes, or backslashes. Please choose a different name."),gui::OK_ONLY);
|
||||
save_game(message,dialog_type, gamestate, status, gui, level, teams, units, map);
|
||||
return;
|
||||
}
|
||||
|
||||
if(res == 0) {
|
||||
config snapshot;
|
||||
write_game_snapshot(snapshot, level, gui, teams, units, status, gamestate, map);
|
||||
try {
|
||||
recorder.save_game(label, snapshot, gamestate.starting_pos);
|
||||
if(dialog_type != gui::NULL_DIALOG) {
|
||||
gui::show_dialog(gui,NULL,_("Saved"),_("The game has been saved"), gui::OK_ONLY);
|
||||
}
|
||||
} catch(game::save_game_failed&) {
|
||||
gui::show_dialog(gui,NULL,_("Error"),_("The game could not be saved"),gui::MESSAGE);
|
||||
//do not bother retrying, since the user can just try to save the game again
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::write_game_snapshot(config& start, const config& level, display& gui,
|
||||
std::vector<team>& teams, const unit_map& units, const gamestatus& status,
|
||||
const game_state& gamestate, const gamemap& map) const
|
||||
{
|
||||
start.values = level.values;
|
||||
|
||||
start["snapshot"] = "yes";
|
||||
|
||||
std::stringstream buf;
|
||||
buf << gui.playing_team();
|
||||
start["playing_team"] = buf.str();
|
||||
|
||||
for(std::vector<team>::const_iterator t = teams.begin(); t != teams.end(); ++t) {
|
||||
const int side_num = t - teams.begin() + 1;
|
||||
|
||||
config& side = start.add_child("side");
|
||||
t->write(side);
|
||||
side["no_leader"] = "yes";
|
||||
buf.str(std::string());
|
||||
buf << side_num;
|
||||
side["side"] = buf.str();
|
||||
|
||||
for(std::map<gamemap::location,unit>::const_iterator i = units.begin(); i != units.end(); ++i) {
|
||||
if(i->second.side() == side_num) {
|
||||
config& u = side.add_child("unit");
|
||||
i->first.write(u);
|
||||
i->second.write(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status.write(start);
|
||||
game_events::write_events(start);
|
||||
|
||||
// Write terrain_graphics data in snapshot, too
|
||||
const config::child_list& terrains = level.get_children("terrain_graphics");
|
||||
for(config::child_list::const_iterator tg = terrains.begin();
|
||||
tg != terrains.end(); ++tg) {
|
||||
|
||||
start.add_child("terrain_graphics", **tg);
|
||||
}
|
||||
|
||||
write_game(gamestate,start,WRITE_SNAPSHOT_ONLY);
|
||||
|
||||
// Clobber gold values to make sure the snapshot uses the values
|
||||
// in [side] instead.
|
||||
const config::child_list& players=start.get_children("player");
|
||||
for(config::child_list::const_iterator pi=players.begin();
|
||||
pi!=players.end(); ++pi) {
|
||||
(**pi)["gold"] = "-1000000";
|
||||
}
|
||||
|
||||
//write out the current state of the map
|
||||
start["map_data"] = map.write();
|
||||
|
||||
gui.labels().write(start);
|
||||
}
|
||||
|
||||
void menu_handler::load_game(display& gui, const config& terrain_config, const game_data& gameinfo){
|
||||
bool show_replay = false;
|
||||
const std::string game = dialogs::load_game_dialog(gui,terrain_config,gameinfo,&show_replay);
|
||||
if(game != "") {
|
||||
throw game::load_game_exception(game,show_replay);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_handler::preferences(display& gui, const config& terrain_config)
|
||||
{
|
||||
preferences::show_preferences_dialog(gui,terrain_config);
|
||||
gui.redraw_everything();
|
||||
}
|
||||
|
||||
void menu_handler::show_chat_log(std::vector<team>& teams, display& gui)
|
||||
{
|
||||
std::string text = recorder.build_chat_log(teams[gui.viewing_team()].team_name());
|
||||
gui::show_dialog(gui,NULL,_("Chat Log"),"",gui::CLOSE_ONLY,NULL,NULL,"",&text);
|
||||
}
|
||||
|
||||
void menu_handler::show_help(display& gui)
|
||||
{
|
||||
help::show_help(gui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
#ifndef MENU_EVENTS_H_INCLUDED
|
||||
#define MENU_EVENTS_H_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "dialogs.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
namespace events{
|
||||
|
||||
class menu_handler{
|
||||
public:
|
||||
void objectives(display& gui, const config& level, team& current_team);
|
||||
void show_statistics(display& gui, const game_data& gameinfo);
|
||||
void unit_list(const unit_map& units, display& gui, const gamemap& map);
|
||||
void status_table(std::vector<team>& teams, display& gui, const unit_map& units);
|
||||
void save_game(const std::string& message, gui::DIALOG_TYPE dialog_type,
|
||||
const game_state& gamestate, const gamestatus& status, display& gui,
|
||||
const config& level, std::vector<team>& teams, const unit_map& units, const gamemap& map);
|
||||
void load_game(display& gui, const config& terrain_config, const game_data& gameinfo);
|
||||
void preferences(display& gui, const config& terrain_config);
|
||||
void show_chat_log(std::vector<team>& teams, display& gui);
|
||||
void show_help(display& gui);
|
||||
private:
|
||||
std::vector<std::string> create_unit_table(const statistics::stats::str_int_map& m, const game_data& gameinfo);
|
||||
void write_game_snapshot(config& start, const config& level, display& gui,
|
||||
std::vector<team>& teams, const unit_map& units, const gamestatus& status,
|
||||
const game_state& gamestate, const gamemap& map) const;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
#ifndef MENU_EVENTS_H_INCLUDED
|
||||
#define MENU_EVENTS_H_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "dialogs.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
namespace events{
|
||||
|
||||
class menu_handler{
|
||||
public:
|
||||
void objectives(display& gui, const config& level, team& current_team);
|
||||
void show_statistics(display& gui, const game_data& gameinfo);
|
||||
void unit_list(const unit_map& units, display& gui, const gamemap& map);
|
||||
void status_table(std::vector<team>& teams, display& gui, const unit_map& units);
|
||||
void save_game(const std::string& message, gui::DIALOG_TYPE dialog_type,
|
||||
const game_state& gamestate, const gamestatus& status, display& gui,
|
||||
const config& level, std::vector<team>& teams, const unit_map& units, const gamemap& map);
|
||||
void load_game(display& gui, const config& terrain_config, const game_data& gameinfo);
|
||||
void preferences(display& gui, const config& terrain_config);
|
||||
void show_chat_log(std::vector<team>& teams, display& gui);
|
||||
void show_help(display& gui);
|
||||
private:
|
||||
std::vector<std::string> create_unit_table(const statistics::stats::str_int_map& m, const game_data& gameinfo);
|
||||
void write_game_snapshot(config& start, const config& level, display& gui,
|
||||
std::vector<team>& teams, const unit_map& units, const gamestatus& status,
|
||||
const game_state& gamestate, const gamemap& map) const;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,422 +1,422 @@
|
|||
#include "mouse_events.hpp"
|
||||
|
||||
#include "cursor.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "wassert.hpp"
|
||||
|
||||
namespace events{
|
||||
|
||||
int commands_disabled = 0;
|
||||
|
||||
bool command_active()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return (SDL_GetModState()&KMOD_META) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
mouse_handler::mouse_handler(display* gui, std::vector<team>& teams, const unit_map& units, gamemap& map,
|
||||
gamestatus& status, const game_data& gameinfo):
|
||||
gui_(gui), teams_(teams), units_(units), map_(map), status_(status), gameinfo_(gameinfo)
|
||||
{
|
||||
minimap_scrolling_ = false;
|
||||
last_nearest_ = gamemap::location::NORTH;
|
||||
last_second_nearest_ = gamemap::location::NORTH;
|
||||
enemy_paths_ = false;
|
||||
browse_ = false;
|
||||
path_turns_ = 0;
|
||||
}
|
||||
|
||||
bool mouse_handler::browse(){
|
||||
return browse_;
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_motion(const SDL_MouseMotionEvent& event, const int player_number)
|
||||
{
|
||||
team_num_ = player_number;
|
||||
mouse_motion(event.x,event.y);
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_motion(int x, int y)
|
||||
{
|
||||
if(minimap_scrolling_) {
|
||||
//if the game is run in a window, we could miss a LMB/MMB up event
|
||||
// if it occurs outside our window.
|
||||
// thus, we need to check if the LMB/MMB is still down
|
||||
minimap_scrolling_ = ((SDL_GetMouseState(NULL,NULL) & (SDL_BUTTON(1) | SDL_BUTTON(2))) != 0);
|
||||
if(minimap_scrolling_) {
|
||||
const gamemap::location& loc = (*gui_).minimap_location_on(x,y);
|
||||
if(loc.valid()) {
|
||||
if(loc != last_hex_) {
|
||||
last_hex_ = loc;
|
||||
(*gui_).scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
}
|
||||
} else {
|
||||
// clicking outside of the minimap will end minimap scrolling
|
||||
minimap_scrolling_ = false;
|
||||
}
|
||||
}
|
||||
if(minimap_scrolling_) return;
|
||||
}
|
||||
|
||||
gamemap::location::DIRECTION nearest_hex = gamemap::location::NDIRECTIONS;
|
||||
gamemap::location::DIRECTION second_nearest_hex = gamemap::location::NDIRECTIONS;
|
||||
const gamemap::location new_hex = (*gui_).hex_clicked_on(x,y,&nearest_hex,&second_nearest_hex);
|
||||
|
||||
if(new_hex != last_hex_ || nearest_hex != last_nearest_ || second_nearest_hex != last_second_nearest_) {
|
||||
if(new_hex.valid() == false) {
|
||||
current_route_.steps.clear();
|
||||
(*gui_).set_route(NULL);
|
||||
}
|
||||
|
||||
(*gui_).highlight_hex(new_hex);
|
||||
|
||||
|
||||
//see if we should show the normal cursor, the movement cursor, or
|
||||
//the attack cursor
|
||||
|
||||
const unit_map::const_iterator selected_unit = find_unit(selected_hex_);
|
||||
const unit_map::const_iterator mouseover_unit = find_unit(new_hex);
|
||||
|
||||
gamemap::location attack_from;
|
||||
if(selected_unit != units_.end() && mouseover_unit != units_.end()) {
|
||||
attack_from = current_unit_attacks_from(new_hex, nearest_hex, second_nearest_hex);
|
||||
}
|
||||
|
||||
if(selected_unit != units_.end() && (current_paths_.routes.count(new_hex) ||
|
||||
attack_from.valid())) {
|
||||
if(mouseover_unit == units_.end()) {
|
||||
cursor::set(cursor::MOVE);
|
||||
} else if(current_team().is_enemy(mouseover_unit->second.side()) && !mouseover_unit->second.stone()) {
|
||||
cursor::set(cursor::ATTACK);
|
||||
} else {
|
||||
cursor::set(cursor::NORMAL);
|
||||
}
|
||||
} else {
|
||||
cursor::set(cursor::NORMAL);
|
||||
}
|
||||
|
||||
if(enemy_paths_) {
|
||||
enemy_paths_ = false;
|
||||
current_paths_ = paths();
|
||||
(*gui_).set_paths(NULL);
|
||||
}
|
||||
|
||||
const gamemap::location& dest = attack_from.valid() ? attack_from : new_hex;
|
||||
const unit_map::const_iterator dest_un = find_unit(dest);
|
||||
if(dest == selected_hex_ || dest_un != units_.end()) {
|
||||
current_route_.steps.clear();
|
||||
(*gui_).set_route(NULL);
|
||||
} else if(!current_paths_.routes.empty() && map_.on_board(selected_hex_) &&
|
||||
map_.on_board(new_hex)) {
|
||||
|
||||
unit_map::const_iterator un = find_unit(selected_hex_);
|
||||
|
||||
if((new_hex != last_hex_ || attack_from.valid()) && un != units_.end() && !un->second.stone()) {
|
||||
const shortest_path_calculator calc(un->second,current_team(), visible_units(),teams_,map_,status_);
|
||||
const bool can_teleport = un->second.type().teleports();
|
||||
|
||||
const std::set<gamemap::location>* teleports = NULL;
|
||||
|
||||
std::set<gamemap::location> allowed_teleports;
|
||||
if(can_teleport) {
|
||||
allowed_teleports = vacant_villages(current_team().villages(),units_);
|
||||
teleports = &allowed_teleports;
|
||||
if(current_team().villages().count(un->first))
|
||||
allowed_teleports.insert(un->first);
|
||||
}
|
||||
|
||||
current_route_ = a_star_search(selected_hex_, dest, 10000.0, &calc, map_.x(), map_.y(), teleports);
|
||||
|
||||
current_route_.move_left = route_turns_to_complete(un->second,map_,current_route_);
|
||||
|
||||
if(!browse_) {
|
||||
(*gui_).set_route(¤t_route_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unit_map::const_iterator un = find_unit(new_hex);
|
||||
|
||||
if(un != units_.end() && /* un->second.side() != player_number && */
|
||||
current_paths_.routes.empty() && !(*gui_).fogged(un->first.x,un->first.y)) {
|
||||
//Quick-Hack because of problems with passing a constant Reference
|
||||
unit un2 = un->second;
|
||||
unit_movement_resetter move_reset(un2);
|
||||
|
||||
const bool ignore_zocs = un->second.type().is_skirmisher();
|
||||
const bool teleport = un->second.type().teleports();
|
||||
current_paths_ = paths(map_,status_,gameinfo_,units_,new_hex,teams_,
|
||||
ignore_zocs,teleport,path_turns_);
|
||||
(*gui_).set_paths(¤t_paths_);
|
||||
enemy_paths_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
last_hex_ = new_hex;
|
||||
last_nearest_ = nearest_hex;
|
||||
last_second_nearest_ = second_nearest_hex;
|
||||
}
|
||||
|
||||
unit_map::const_iterator mouse_handler::find_unit(const gamemap::location& hex)
|
||||
{
|
||||
if ((*gui_).fogged(hex.x,hex.y)) {
|
||||
return units_.end();
|
||||
}
|
||||
|
||||
return find_visible_unit(units_,hex,map_,status_.get_time_of_day().lawful_bonus,teams_,viewing_team());
|
||||
}
|
||||
|
||||
gamemap::location mouse_handler::current_unit_attacks_from(const gamemap::location& loc, const gamemap::location::DIRECTION preferred, const gamemap::location::DIRECTION second_preferred)
|
||||
{
|
||||
const unit_map::const_iterator current = find_unit(selected_hex_);
|
||||
if(current == units_.end() || current->second.side() != team_num_) {
|
||||
return gamemap::location();
|
||||
}
|
||||
|
||||
const unit_map::const_iterator enemy = find_unit(loc);
|
||||
if(enemy == units_.end() || current_team().is_enemy(enemy->second.side()) == false) {
|
||||
return gamemap::location();
|
||||
}
|
||||
|
||||
int best_rating = 100;//smaller is better
|
||||
gamemap::location res;
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(loc,adj);
|
||||
for(size_t n = 0; n != 6; ++n) {
|
||||
if(map_.on_board(adj[n]) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(adj[n] == selected_hex_) {
|
||||
return selected_hex_;
|
||||
}
|
||||
|
||||
if(find_unit(adj[n]) != units_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(current_paths_.routes.count(adj[n])) {
|
||||
static const size_t NDIRECTIONS = gamemap::location::NDIRECTIONS;
|
||||
int difference = abs(int(preferred - n));
|
||||
if(difference > NDIRECTIONS/2) {
|
||||
difference = NDIRECTIONS - difference;
|
||||
}
|
||||
int second_difference = abs(int(second_preferred - n));
|
||||
if(second_difference > NDIRECTIONS/2) {
|
||||
second_difference = NDIRECTIONS - second_difference;
|
||||
}
|
||||
const int rating = difference * 2 + (second_difference > difference);
|
||||
if(rating < best_rating || res.valid() == false) {
|
||||
best_rating = rating;
|
||||
res = adj[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const unit_map& mouse_handler::visible_units()
|
||||
{
|
||||
if(viewing_team().uses_shroud() == false && viewing_team().uses_fog() == false) {
|
||||
LOG_STREAM(info, engine) << "all units are visible...\n";
|
||||
return units_;
|
||||
}
|
||||
|
||||
visible_units_.clear();
|
||||
for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
|
||||
if((*gui_).fogged(i->first.x,i->first.y) == false) {
|
||||
visible_units_.insert(*i);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_STREAM(info, engine) << "number of visible units: " << visible_units_.size() << "\n";
|
||||
|
||||
return visible_units_;
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_press(const SDL_MouseButtonEvent& event, const int player_number)
|
||||
{
|
||||
team_num_ = player_number;
|
||||
mouse_motion(event.x, event.y);
|
||||
|
||||
if(is_left_click(event) && event.state == SDL_RELEASED) {
|
||||
minimap_scrolling_ = false;
|
||||
} else if(is_middle_click(event) && event.state == SDL_RELEASED) {
|
||||
minimap_scrolling_ = false;
|
||||
} else if(is_left_click(event) && event.state == SDL_PRESSED) {
|
||||
left_click(event);
|
||||
} else if(is_right_click(event) && event.state == SDL_PRESSED) {
|
||||
if(!current_paths_.routes.empty()) {
|
||||
selected_hex_ = gamemap::location();
|
||||
gui_->select_hex(gamemap::location());
|
||||
gui_->set_paths(NULL);
|
||||
current_paths_ = paths();
|
||||
current_route_.steps.clear();
|
||||
gui_->set_route(NULL);
|
||||
|
||||
cursor::set(cursor::NORMAL);
|
||||
} else {
|
||||
gui_->draw(); // redraw highlight (and maybe some more)
|
||||
const theme::menu* const m = gui_->get_theme().context_menu();
|
||||
if (m != NULL)
|
||||
;//show_menu(m->items(),event.x,event.y,true);
|
||||
else
|
||||
LOG_STREAM(warn, display) << "no context menu found...\n";
|
||||
}
|
||||
} else if(is_middle_click(event) && event.state == SDL_PRESSED) {
|
||||
// clicked on a hex on the minimap? then initiate minimap scrolling
|
||||
const gamemap::location& loc = gui_->minimap_location_on(event.x,event.y);
|
||||
minimap_scrolling_ = false;
|
||||
if(loc.valid()) {
|
||||
minimap_scrolling_ = true;
|
||||
last_hex_ = loc;
|
||||
gui_->scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
return;
|
||||
} else {
|
||||
const SDL_Rect& rect = gui_->map_area();
|
||||
const int centerx = (rect.x + rect.w)/2;
|
||||
const int centery = (rect.y + rect.h)/2;
|
||||
|
||||
const int xdisp = event.x - centerx;
|
||||
const int ydisp = event.y - centery;
|
||||
|
||||
gui_->scroll(xdisp,ydisp);
|
||||
}
|
||||
} else if((event.button == SDL_BUTTON_WHEELUP ||
|
||||
event.button == SDL_BUTTON_WHEELDOWN) && !commands_disabled) {
|
||||
const int speed = preferences::scroll_speed() *
|
||||
(event.button == SDL_BUTTON_WHEELUP ? -1:1);
|
||||
|
||||
const int centerx = gui_->mapx()/2;
|
||||
const int centery = gui_->y()/2;
|
||||
|
||||
const int xdisp = abs(centerx - event.x);
|
||||
const int ydisp = abs(centery - event.y);
|
||||
|
||||
if(xdisp > ydisp)
|
||||
gui_->scroll(speed,0);
|
||||
else
|
||||
gui_->scroll(0,speed);
|
||||
}
|
||||
}
|
||||
|
||||
bool mouse_handler::is_left_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_LEFT && !command_active();
|
||||
}
|
||||
|
||||
bool mouse_handler::is_middle_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_MIDDLE;
|
||||
}
|
||||
|
||||
bool mouse_handler::is_right_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_RIGHT || event.button == SDL_BUTTON_LEFT && command_active();
|
||||
}
|
||||
|
||||
void mouse_handler::left_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
if(commands_disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clicked on a hex on the minimap? then initiate minimap scrolling
|
||||
const gamemap::location& loc = gui_->minimap_location_on(event.x,event.y);
|
||||
minimap_scrolling_ = false;
|
||||
if(loc.valid()) {
|
||||
minimap_scrolling_ = true;
|
||||
last_hex_ = loc;
|
||||
gui_->scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
return;
|
||||
}
|
||||
|
||||
gamemap::location::DIRECTION nearest_hex, second_nearest_hex;
|
||||
gamemap::location hex = gui_->hex_clicked_on(event.x,event.y,&nearest_hex,&second_nearest_hex);
|
||||
|
||||
unit_map::const_iterator u = find_unit(selected_hex_);
|
||||
|
||||
//if the unit is selected and then itself clicked on,
|
||||
//any goto command is cancelled
|
||||
if(u != units_.end() && !browse_ && selected_hex_ == hex && u->second.side() == team_num_) {
|
||||
((unit) u->second).set_goto(gamemap::location());
|
||||
}
|
||||
|
||||
//if we can move to that tile
|
||||
std::map<gamemap::location,paths::route>::const_iterator
|
||||
route = enemy_paths_ ? current_paths_.routes.end() :
|
||||
current_paths_.routes.find(hex);
|
||||
|
||||
unit_map::const_iterator enemy = find_unit(hex);
|
||||
|
||||
const gamemap::location src = selected_hex_;
|
||||
paths orig_paths = current_paths_;
|
||||
|
||||
{
|
||||
gui_->set_paths(NULL);
|
||||
current_paths_ = paths();
|
||||
|
||||
selected_hex_ = hex;
|
||||
gui_->select_hex(hex);
|
||||
current_route_.steps.clear();
|
||||
gui_->set_route(NULL);
|
||||
|
||||
unit_map::const_iterator it = find_unit(hex);
|
||||
|
||||
if(it != units_.end() && it->second.side() == team_num_ && !gui_->fogged(it->first.x,it->first.y)) {
|
||||
const bool ignore_zocs = it->second.type().is_skirmisher();
|
||||
const bool teleport = it->second.type().teleports();
|
||||
current_paths_ = paths(map_,status_,gameinfo_,units_,hex,teams_,
|
||||
ignore_zocs,teleport,path_turns_);
|
||||
|
||||
next_unit_ = it->first;
|
||||
|
||||
show_attack_options(it);
|
||||
|
||||
gui_->set_paths(¤t_paths_);
|
||||
|
||||
unit u = it->second;
|
||||
const gamemap::location go_to = u.get_goto();
|
||||
if(map_.on_board(go_to)) {
|
||||
const shortest_path_calculator calc(u,current_team(),
|
||||
visible_units(),teams_,map_,status_);
|
||||
|
||||
const std::set<gamemap::location>* teleports = NULL;
|
||||
|
||||
std::set<gamemap::location> allowed_teleports;
|
||||
if(u.type().teleports()) {
|
||||
allowed_teleports = vacant_villages(current_team().villages(),units_);
|
||||
teleports = &allowed_teleports;
|
||||
if(current_team().villages().count(it->first))
|
||||
allowed_teleports.insert(it->first);
|
||||
|
||||
}
|
||||
|
||||
paths::route route = a_star_search(it->first, go_to, 10000.0, &calc, map_.x(), map_.y(), teleports);
|
||||
route.move_left = route_turns_to_complete(it->second,map_,route);
|
||||
gui_->set_route(&route);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mouse_handler::show_attack_options(unit_map::const_iterator u)
|
||||
{
|
||||
team& current_team = teams_[team_num_-1];
|
||||
|
||||
if(u == units_.end() || u->second.can_attack() == false)
|
||||
return;
|
||||
|
||||
for(unit_map::const_iterator target = units_.begin(); target != units_.end(); ++target) {
|
||||
if(current_team.is_enemy(target->second.side()) &&
|
||||
distance_between(target->first,u->first) == 1 && !target->second.stone()) {
|
||||
current_paths_.routes[target->first] = paths::route();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#include "mouse_events.hpp"
|
||||
|
||||
#include "cursor.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "wassert.hpp"
|
||||
|
||||
namespace events{
|
||||
|
||||
int commands_disabled = 0;
|
||||
|
||||
bool command_active()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return (SDL_GetModState()&KMOD_META) != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
mouse_handler::mouse_handler(display* gui, std::vector<team>& teams, const unit_map& units, gamemap& map,
|
||||
gamestatus& status, const game_data& gameinfo):
|
||||
gui_(gui), teams_(teams), units_(units), map_(map), status_(status), gameinfo_(gameinfo)
|
||||
{
|
||||
minimap_scrolling_ = false;
|
||||
last_nearest_ = gamemap::location::NORTH;
|
||||
last_second_nearest_ = gamemap::location::NORTH;
|
||||
enemy_paths_ = false;
|
||||
browse_ = false;
|
||||
path_turns_ = 0;
|
||||
}
|
||||
|
||||
bool mouse_handler::browse(){
|
||||
return browse_;
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_motion(const SDL_MouseMotionEvent& event, const int player_number)
|
||||
{
|
||||
team_num_ = player_number;
|
||||
mouse_motion(event.x,event.y);
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_motion(int x, int y)
|
||||
{
|
||||
if(minimap_scrolling_) {
|
||||
//if the game is run in a window, we could miss a LMB/MMB up event
|
||||
// if it occurs outside our window.
|
||||
// thus, we need to check if the LMB/MMB is still down
|
||||
minimap_scrolling_ = ((SDL_GetMouseState(NULL,NULL) & (SDL_BUTTON(1) | SDL_BUTTON(2))) != 0);
|
||||
if(minimap_scrolling_) {
|
||||
const gamemap::location& loc = (*gui_).minimap_location_on(x,y);
|
||||
if(loc.valid()) {
|
||||
if(loc != last_hex_) {
|
||||
last_hex_ = loc;
|
||||
(*gui_).scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
}
|
||||
} else {
|
||||
// clicking outside of the minimap will end minimap scrolling
|
||||
minimap_scrolling_ = false;
|
||||
}
|
||||
}
|
||||
if(minimap_scrolling_) return;
|
||||
}
|
||||
|
||||
gamemap::location::DIRECTION nearest_hex = gamemap::location::NDIRECTIONS;
|
||||
gamemap::location::DIRECTION second_nearest_hex = gamemap::location::NDIRECTIONS;
|
||||
const gamemap::location new_hex = (*gui_).hex_clicked_on(x,y,&nearest_hex,&second_nearest_hex);
|
||||
|
||||
if(new_hex != last_hex_ || nearest_hex != last_nearest_ || second_nearest_hex != last_second_nearest_) {
|
||||
if(new_hex.valid() == false) {
|
||||
current_route_.steps.clear();
|
||||
(*gui_).set_route(NULL);
|
||||
}
|
||||
|
||||
(*gui_).highlight_hex(new_hex);
|
||||
|
||||
|
||||
//see if we should show the normal cursor, the movement cursor, or
|
||||
//the attack cursor
|
||||
|
||||
const unit_map::const_iterator selected_unit = find_unit(selected_hex_);
|
||||
const unit_map::const_iterator mouseover_unit = find_unit(new_hex);
|
||||
|
||||
gamemap::location attack_from;
|
||||
if(selected_unit != units_.end() && mouseover_unit != units_.end()) {
|
||||
attack_from = current_unit_attacks_from(new_hex, nearest_hex, second_nearest_hex);
|
||||
}
|
||||
|
||||
if(selected_unit != units_.end() && (current_paths_.routes.count(new_hex) ||
|
||||
attack_from.valid())) {
|
||||
if(mouseover_unit == units_.end()) {
|
||||
cursor::set(cursor::MOVE);
|
||||
} else if(current_team().is_enemy(mouseover_unit->second.side()) && !mouseover_unit->second.stone()) {
|
||||
cursor::set(cursor::ATTACK);
|
||||
} else {
|
||||
cursor::set(cursor::NORMAL);
|
||||
}
|
||||
} else {
|
||||
cursor::set(cursor::NORMAL);
|
||||
}
|
||||
|
||||
if(enemy_paths_) {
|
||||
enemy_paths_ = false;
|
||||
current_paths_ = paths();
|
||||
(*gui_).set_paths(NULL);
|
||||
}
|
||||
|
||||
const gamemap::location& dest = attack_from.valid() ? attack_from : new_hex;
|
||||
const unit_map::const_iterator dest_un = find_unit(dest);
|
||||
if(dest == selected_hex_ || dest_un != units_.end()) {
|
||||
current_route_.steps.clear();
|
||||
(*gui_).set_route(NULL);
|
||||
} else if(!current_paths_.routes.empty() && map_.on_board(selected_hex_) &&
|
||||
map_.on_board(new_hex)) {
|
||||
|
||||
unit_map::const_iterator un = find_unit(selected_hex_);
|
||||
|
||||
if((new_hex != last_hex_ || attack_from.valid()) && un != units_.end() && !un->second.stone()) {
|
||||
const shortest_path_calculator calc(un->second,current_team(), visible_units(),teams_,map_,status_);
|
||||
const bool can_teleport = un->second.type().teleports();
|
||||
|
||||
const std::set<gamemap::location>* teleports = NULL;
|
||||
|
||||
std::set<gamemap::location> allowed_teleports;
|
||||
if(can_teleport) {
|
||||
allowed_teleports = vacant_villages(current_team().villages(),units_);
|
||||
teleports = &allowed_teleports;
|
||||
if(current_team().villages().count(un->first))
|
||||
allowed_teleports.insert(un->first);
|
||||
}
|
||||
|
||||
current_route_ = a_star_search(selected_hex_, dest, 10000.0, &calc, map_.x(), map_.y(), teleports);
|
||||
|
||||
current_route_.move_left = route_turns_to_complete(un->second,map_,current_route_);
|
||||
|
||||
if(!browse_) {
|
||||
(*gui_).set_route(¤t_route_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unit_map::const_iterator un = find_unit(new_hex);
|
||||
|
||||
if(un != units_.end() && /* un->second.side() != player_number && */
|
||||
current_paths_.routes.empty() && !(*gui_).fogged(un->first.x,un->first.y)) {
|
||||
//Quick-Hack because of problems with passing a constant Reference
|
||||
unit un2 = un->second;
|
||||
unit_movement_resetter move_reset(un2);
|
||||
|
||||
const bool ignore_zocs = un->second.type().is_skirmisher();
|
||||
const bool teleport = un->second.type().teleports();
|
||||
current_paths_ = paths(map_,status_,gameinfo_,units_,new_hex,teams_,
|
||||
ignore_zocs,teleport,path_turns_);
|
||||
(*gui_).set_paths(¤t_paths_);
|
||||
enemy_paths_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
last_hex_ = new_hex;
|
||||
last_nearest_ = nearest_hex;
|
||||
last_second_nearest_ = second_nearest_hex;
|
||||
}
|
||||
|
||||
unit_map::const_iterator mouse_handler::find_unit(const gamemap::location& hex)
|
||||
{
|
||||
if ((*gui_).fogged(hex.x,hex.y)) {
|
||||
return units_.end();
|
||||
}
|
||||
|
||||
return find_visible_unit(units_,hex,map_,status_.get_time_of_day().lawful_bonus,teams_,viewing_team());
|
||||
}
|
||||
|
||||
gamemap::location mouse_handler::current_unit_attacks_from(const gamemap::location& loc, const gamemap::location::DIRECTION preferred, const gamemap::location::DIRECTION second_preferred)
|
||||
{
|
||||
const unit_map::const_iterator current = find_unit(selected_hex_);
|
||||
if(current == units_.end() || current->second.side() != team_num_) {
|
||||
return gamemap::location();
|
||||
}
|
||||
|
||||
const unit_map::const_iterator enemy = find_unit(loc);
|
||||
if(enemy == units_.end() || current_team().is_enemy(enemy->second.side()) == false) {
|
||||
return gamemap::location();
|
||||
}
|
||||
|
||||
int best_rating = 100;//smaller is better
|
||||
gamemap::location res;
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(loc,adj);
|
||||
for(size_t n = 0; n != 6; ++n) {
|
||||
if(map_.on_board(adj[n]) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(adj[n] == selected_hex_) {
|
||||
return selected_hex_;
|
||||
}
|
||||
|
||||
if(find_unit(adj[n]) != units_.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(current_paths_.routes.count(adj[n])) {
|
||||
static const size_t NDIRECTIONS = gamemap::location::NDIRECTIONS;
|
||||
int difference = abs(int(preferred - n));
|
||||
if(difference > NDIRECTIONS/2) {
|
||||
difference = NDIRECTIONS - difference;
|
||||
}
|
||||
int second_difference = abs(int(second_preferred - n));
|
||||
if(second_difference > NDIRECTIONS/2) {
|
||||
second_difference = NDIRECTIONS - second_difference;
|
||||
}
|
||||
const int rating = difference * 2 + (second_difference > difference);
|
||||
if(rating < best_rating || res.valid() == false) {
|
||||
best_rating = rating;
|
||||
res = adj[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const unit_map& mouse_handler::visible_units()
|
||||
{
|
||||
if(viewing_team().uses_shroud() == false && viewing_team().uses_fog() == false) {
|
||||
LOG_STREAM(info, engine) << "all units are visible...\n";
|
||||
return units_;
|
||||
}
|
||||
|
||||
visible_units_.clear();
|
||||
for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
|
||||
if((*gui_).fogged(i->first.x,i->first.y) == false) {
|
||||
visible_units_.insert(*i);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_STREAM(info, engine) << "number of visible units: " << visible_units_.size() << "\n";
|
||||
|
||||
return visible_units_;
|
||||
}
|
||||
|
||||
void mouse_handler::mouse_press(const SDL_MouseButtonEvent& event, const int player_number)
|
||||
{
|
||||
team_num_ = player_number;
|
||||
mouse_motion(event.x, event.y);
|
||||
|
||||
if(is_left_click(event) && event.state == SDL_RELEASED) {
|
||||
minimap_scrolling_ = false;
|
||||
} else if(is_middle_click(event) && event.state == SDL_RELEASED) {
|
||||
minimap_scrolling_ = false;
|
||||
} else if(is_left_click(event) && event.state == SDL_PRESSED) {
|
||||
left_click(event);
|
||||
} else if(is_right_click(event) && event.state == SDL_PRESSED) {
|
||||
if(!current_paths_.routes.empty()) {
|
||||
selected_hex_ = gamemap::location();
|
||||
gui_->select_hex(gamemap::location());
|
||||
gui_->set_paths(NULL);
|
||||
current_paths_ = paths();
|
||||
current_route_.steps.clear();
|
||||
gui_->set_route(NULL);
|
||||
|
||||
cursor::set(cursor::NORMAL);
|
||||
} else {
|
||||
gui_->draw(); // redraw highlight (and maybe some more)
|
||||
const theme::menu* const m = gui_->get_theme().context_menu();
|
||||
if (m != NULL)
|
||||
;//show_menu(m->items(),event.x,event.y,true);
|
||||
else
|
||||
LOG_STREAM(warn, display) << "no context menu found...\n";
|
||||
}
|
||||
} else if(is_middle_click(event) && event.state == SDL_PRESSED) {
|
||||
// clicked on a hex on the minimap? then initiate minimap scrolling
|
||||
const gamemap::location& loc = gui_->minimap_location_on(event.x,event.y);
|
||||
minimap_scrolling_ = false;
|
||||
if(loc.valid()) {
|
||||
minimap_scrolling_ = true;
|
||||
last_hex_ = loc;
|
||||
gui_->scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
return;
|
||||
} else {
|
||||
const SDL_Rect& rect = gui_->map_area();
|
||||
const int centerx = (rect.x + rect.w)/2;
|
||||
const int centery = (rect.y + rect.h)/2;
|
||||
|
||||
const int xdisp = event.x - centerx;
|
||||
const int ydisp = event.y - centery;
|
||||
|
||||
gui_->scroll(xdisp,ydisp);
|
||||
}
|
||||
} else if((event.button == SDL_BUTTON_WHEELUP ||
|
||||
event.button == SDL_BUTTON_WHEELDOWN) && !commands_disabled) {
|
||||
const int speed = preferences::scroll_speed() *
|
||||
(event.button == SDL_BUTTON_WHEELUP ? -1:1);
|
||||
|
||||
const int centerx = gui_->mapx()/2;
|
||||
const int centery = gui_->y()/2;
|
||||
|
||||
const int xdisp = abs(centerx - event.x);
|
||||
const int ydisp = abs(centery - event.y);
|
||||
|
||||
if(xdisp > ydisp)
|
||||
gui_->scroll(speed,0);
|
||||
else
|
||||
gui_->scroll(0,speed);
|
||||
}
|
||||
}
|
||||
|
||||
bool mouse_handler::is_left_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_LEFT && !command_active();
|
||||
}
|
||||
|
||||
bool mouse_handler::is_middle_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_MIDDLE;
|
||||
}
|
||||
|
||||
bool mouse_handler::is_right_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
return event.button == SDL_BUTTON_RIGHT || event.button == SDL_BUTTON_LEFT && command_active();
|
||||
}
|
||||
|
||||
void mouse_handler::left_click(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
if(commands_disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clicked on a hex on the minimap? then initiate minimap scrolling
|
||||
const gamemap::location& loc = gui_->minimap_location_on(event.x,event.y);
|
||||
minimap_scrolling_ = false;
|
||||
if(loc.valid()) {
|
||||
minimap_scrolling_ = true;
|
||||
last_hex_ = loc;
|
||||
gui_->scroll_to_tile(loc.x,loc.y,display::WARP,false);
|
||||
return;
|
||||
}
|
||||
|
||||
gamemap::location::DIRECTION nearest_hex, second_nearest_hex;
|
||||
gamemap::location hex = gui_->hex_clicked_on(event.x,event.y,&nearest_hex,&second_nearest_hex);
|
||||
|
||||
unit_map::const_iterator u = find_unit(selected_hex_);
|
||||
|
||||
//if the unit is selected and then itself clicked on,
|
||||
//any goto command is cancelled
|
||||
if(u != units_.end() && !browse_ && selected_hex_ == hex && u->second.side() == team_num_) {
|
||||
((unit) u->second).set_goto(gamemap::location());
|
||||
}
|
||||
|
||||
//if we can move to that tile
|
||||
std::map<gamemap::location,paths::route>::const_iterator
|
||||
route = enemy_paths_ ? current_paths_.routes.end() :
|
||||
current_paths_.routes.find(hex);
|
||||
|
||||
unit_map::const_iterator enemy = find_unit(hex);
|
||||
|
||||
const gamemap::location src = selected_hex_;
|
||||
paths orig_paths = current_paths_;
|
||||
|
||||
{
|
||||
gui_->set_paths(NULL);
|
||||
current_paths_ = paths();
|
||||
|
||||
selected_hex_ = hex;
|
||||
gui_->select_hex(hex);
|
||||
current_route_.steps.clear();
|
||||
gui_->set_route(NULL);
|
||||
|
||||
unit_map::const_iterator it = find_unit(hex);
|
||||
|
||||
if(it != units_.end() && it->second.side() == team_num_ && !gui_->fogged(it->first.x,it->first.y)) {
|
||||
const bool ignore_zocs = it->second.type().is_skirmisher();
|
||||
const bool teleport = it->second.type().teleports();
|
||||
current_paths_ = paths(map_,status_,gameinfo_,units_,hex,teams_,
|
||||
ignore_zocs,teleport,path_turns_);
|
||||
|
||||
next_unit_ = it->first;
|
||||
|
||||
show_attack_options(it);
|
||||
|
||||
gui_->set_paths(¤t_paths_);
|
||||
|
||||
unit u = it->second;
|
||||
const gamemap::location go_to = u.get_goto();
|
||||
if(map_.on_board(go_to)) {
|
||||
const shortest_path_calculator calc(u,current_team(),
|
||||
visible_units(),teams_,map_,status_);
|
||||
|
||||
const std::set<gamemap::location>* teleports = NULL;
|
||||
|
||||
std::set<gamemap::location> allowed_teleports;
|
||||
if(u.type().teleports()) {
|
||||
allowed_teleports = vacant_villages(current_team().villages(),units_);
|
||||
teleports = &allowed_teleports;
|
||||
if(current_team().villages().count(it->first))
|
||||
allowed_teleports.insert(it->first);
|
||||
|
||||
}
|
||||
|
||||
paths::route route = a_star_search(it->first, go_to, 10000.0, &calc, map_.x(), map_.y(), teleports);
|
||||
route.move_left = route_turns_to_complete(it->second,map_,route);
|
||||
gui_->set_route(&route);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mouse_handler::show_attack_options(unit_map::const_iterator u)
|
||||
{
|
||||
team& current_team = teams_[team_num_-1];
|
||||
|
||||
if(u == units_.end() || u->second.can_attack() == false)
|
||||
return;
|
||||
|
||||
for(unit_map::const_iterator target = units_.begin(); target != units_.end(); ++target) {
|
||||
if(current_team.is_enemy(target->second.side()) &&
|
||||
distance_between(target->first,u->first) == 1 && !target->second.stone()) {
|
||||
current_paths_.routes[target->first] = paths::route();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,66 +1,66 @@
|
|||
#ifndef MOUSE_EVENTS_H_INCLUDED
|
||||
#define MOUSE_EVENTS_H_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "display.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "pathfind.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
namespace events{
|
||||
|
||||
class mouse_handler{
|
||||
public:
|
||||
mouse_handler(display* gui, std::vector<team>& teams, const unit_map& units, gamemap& map, gamestatus& status, const game_data& gameinfo);
|
||||
bool browse();
|
||||
void mouse_motion(const SDL_MouseMotionEvent& event, const int player_number);
|
||||
void mouse_press(const SDL_MouseButtonEvent& event, const int player_number);
|
||||
void set_gui(display* gui) { gui_ = gui; }
|
||||
private:
|
||||
team& viewing_team() { return teams_[(*gui_).viewing_team()]; }
|
||||
team& current_team() { return teams_[team_num_-1]; }
|
||||
|
||||
void mouse_motion(int x, int y);
|
||||
bool is_left_click(const SDL_MouseButtonEvent& event);
|
||||
bool is_middle_click(const SDL_MouseButtonEvent& event);
|
||||
bool is_right_click(const SDL_MouseButtonEvent& event);
|
||||
void left_click(const SDL_MouseButtonEvent& event);
|
||||
void show_attack_options(unit_map::const_iterator u);
|
||||
gamemap::location current_unit_attacks_from(const gamemap::location& loc, const gamemap::location::DIRECTION preferred, const gamemap::location::DIRECTION second_preferred);
|
||||
unit_map::const_iterator find_unit(const gamemap::location& hex);
|
||||
const unit_map& visible_units();
|
||||
|
||||
display* gui_;
|
||||
std::vector<team>& teams_;
|
||||
const unit_map& units_;
|
||||
gamemap& map_;
|
||||
gamestatus& status_;
|
||||
const game_data& gameinfo_;
|
||||
|
||||
bool minimap_scrolling_;
|
||||
gamemap::location last_hex_;
|
||||
gamemap::location selected_hex_;
|
||||
gamemap::location::DIRECTION last_nearest_, last_second_nearest_;
|
||||
gamemap::location next_unit_;
|
||||
paths::route current_route_;
|
||||
paths current_paths_;
|
||||
bool enemy_paths_;
|
||||
bool browse_;
|
||||
mutable unit_map visible_units_;
|
||||
int path_turns_;
|
||||
int team_num_;
|
||||
undo_list undo_stack_;
|
||||
undo_list redo_stack_;
|
||||
|
||||
//cached value indicating whether any enemy units are visible.
|
||||
//computed with enemies_visible()
|
||||
bool enemies_visible_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef MOUSE_EVENTS_H_INCLUDED
|
||||
#define MOUSE_EVENTS_H_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "display.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "pathfind.hpp"
|
||||
#include "unit.hpp"
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
namespace events{
|
||||
|
||||
class mouse_handler{
|
||||
public:
|
||||
mouse_handler(display* gui, std::vector<team>& teams, const unit_map& units, gamemap& map, gamestatus& status, const game_data& gameinfo);
|
||||
bool browse();
|
||||
void mouse_motion(const SDL_MouseMotionEvent& event, const int player_number);
|
||||
void mouse_press(const SDL_MouseButtonEvent& event, const int player_number);
|
||||
void set_gui(display* gui) { gui_ = gui; }
|
||||
private:
|
||||
team& viewing_team() { return teams_[(*gui_).viewing_team()]; }
|
||||
team& current_team() { return teams_[team_num_-1]; }
|
||||
|
||||
void mouse_motion(int x, int y);
|
||||
bool is_left_click(const SDL_MouseButtonEvent& event);
|
||||
bool is_middle_click(const SDL_MouseButtonEvent& event);
|
||||
bool is_right_click(const SDL_MouseButtonEvent& event);
|
||||
void left_click(const SDL_MouseButtonEvent& event);
|
||||
void show_attack_options(unit_map::const_iterator u);
|
||||
gamemap::location current_unit_attacks_from(const gamemap::location& loc, const gamemap::location::DIRECTION preferred, const gamemap::location::DIRECTION second_preferred);
|
||||
unit_map::const_iterator find_unit(const gamemap::location& hex);
|
||||
const unit_map& visible_units();
|
||||
|
||||
display* gui_;
|
||||
std::vector<team>& teams_;
|
||||
const unit_map& units_;
|
||||
gamemap& map_;
|
||||
gamestatus& status_;
|
||||
const game_data& gameinfo_;
|
||||
|
||||
bool minimap_scrolling_;
|
||||
gamemap::location last_hex_;
|
||||
gamemap::location selected_hex_;
|
||||
gamemap::location::DIRECTION last_nearest_, last_second_nearest_;
|
||||
gamemap::location next_unit_;
|
||||
paths::route current_route_;
|
||||
paths current_paths_;
|
||||
bool enemy_paths_;
|
||||
bool browse_;
|
||||
mutable unit_map visible_units_;
|
||||
int path_turns_;
|
||||
int team_num_;
|
||||
undo_list undo_stack_;
|
||||
undo_list redo_stack_;
|
||||
|
||||
//cached value indicating whether any enemy units are visible.
|
||||
//computed with enemies_visible()
|
||||
bool enemies_visible_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -130,7 +130,7 @@ void gamebrowser::draw_item(size_t index) const {
|
|||
video().blit_surface(xpos, ypos, dimensions_text);
|
||||
|
||||
xpos += dimensions_text->w + 2 * h_padding_;
|
||||
|
||||
|
||||
// draw gold icon
|
||||
const surface gold_icon(image::get_image(gold_icon_locator_, image::UNSCALED));
|
||||
ypos = item_rect.y + item_rect.h - margin_ - gold_icon->h;
|
||||
|
|
|
@ -2102,7 +2102,7 @@ void turn_info::recall()
|
|||
redo_stack_.clear();
|
||||
|
||||
clear_shroud();
|
||||
|
||||
|
||||
recall_list.erase(recall_list.begin()+res);
|
||||
gui_.invalidate_game_status();
|
||||
gui_.invalidate_all();
|
||||
|
|
|
@ -812,7 +812,7 @@ void encounter_recallable_units(game_state& gamestate){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void encounter_map_terrain(gamemap& map){
|
||||
for (int map_x = 0; map_x < map.x(); map_x++) {
|
||||
for (int map_y = 0; map_y < map.y(); map_y++) {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <string>
|
||||
|
||||
namespace preferences {
|
||||
|
||||
|
||||
display* disp = NULL;
|
||||
|
||||
display_manager::display_manager(display* d)
|
||||
|
@ -286,7 +286,7 @@ preferences_dialog::preferences_dialog(display& disp, const config& game_cfg)
|
|||
|
||||
show_lobby_joins_button_.set_check(lobby_joins());
|
||||
show_lobby_joins_button_.set_help_string(_("Show messages about players joining the multiplayer lobby"));
|
||||
|
||||
|
||||
show_floating_labels_button_.set_check(show_floating_labels());
|
||||
show_floating_labels_button_.set_help_string(_("Show text above a unit when it is hit to display damage inflicted"));
|
||||
|
||||
|
@ -789,7 +789,7 @@ void show_hotkeys_dialog (display & disp, config *save_config)
|
|||
bool show_theme_dialog(display& disp)
|
||||
{
|
||||
int action = 0;
|
||||
std::vector<std::string> options = disp.get_theme().get_known_themes();
|
||||
std::vector<std::string> options = disp.get_theme().get_known_themes();
|
||||
if(options.size()){
|
||||
std::string current_theme=_("Saved Theme Preference: ")+preferences::theme();
|
||||
action = gui::show_dialog(disp,NULL,"",current_theme,gui::OK_CANCEL,&options);
|
||||
|
@ -803,11 +803,11 @@ bool show_theme_dialog(display& disp)
|
|||
}else{
|
||||
gui::show_dialog(disp,NULL,"",_("No known themes. Try changing from within an existing game."),gui::MESSAGE);
|
||||
}
|
||||
return(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,117 +1,117 @@
|
|||
/* $Id: replay_controller.hpp 7396 2005-07-02 21:37:20Z ott $ */
|
||||
/*
|
||||
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#ifndef REPLAY_CONTROLLER_H_INCLUDED
|
||||
#define REPLAY_CONTROLLER_H_INCLUDED
|
||||
|
||||
#include "display.hpp"
|
||||
#include "font.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "help.hpp"
|
||||
#include "hotkeys.hpp"
|
||||
#include "menu_events.hpp"
|
||||
#include "mouse_events.hpp"
|
||||
#include "playlevel.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "tooltips.hpp"
|
||||
#include "wml_separators.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class replay_controller : public hotkey::command_executor, public events::handler
|
||||
{
|
||||
public:
|
||||
replay_controller(const config& level, const game_data& gameinfo, game_state& state_of_game,
|
||||
const int ticks, const int num_turns, const config& game_config, CVideo& video,
|
||||
const std::vector<config*>& story);
|
||||
~replay_controller();
|
||||
|
||||
void handle_event(const SDL_Event& event);
|
||||
void replay_slice();
|
||||
bool can_execute_command(hotkey::HOTKEY_COMMAND command) const;
|
||||
|
||||
std::vector<team>& get_teams();
|
||||
unit_map get_units();
|
||||
display& get_gui();
|
||||
gamemap& get_map();
|
||||
const gamestatus& get_status();
|
||||
const int get_player_number();
|
||||
const bool is_loading_game();
|
||||
|
||||
//event handlers
|
||||
void objectives();
|
||||
void show_statistics();
|
||||
void unit_list();
|
||||
void status_table();
|
||||
void save_game();
|
||||
void load_game();
|
||||
void preferences();
|
||||
void show_chat_log();
|
||||
void show_help();
|
||||
void play_replay();
|
||||
void reset_replay();
|
||||
void stop_replay();
|
||||
void replay_next_turn();
|
||||
void replay_next_side();
|
||||
void replay_switch_fog();
|
||||
void replay_switch_shroud();
|
||||
void replay_skip_animation();
|
||||
|
||||
std::vector<team> teams_, teams_start_;
|
||||
private:
|
||||
void init(CVideo& video, const std::vector<config*>& story);
|
||||
void init_managers();
|
||||
void play_turn();
|
||||
void play_side(const int team_index);
|
||||
void update_teams();
|
||||
void update_gui();
|
||||
|
||||
//managers
|
||||
const verification_manager verify_manager_;
|
||||
teams_manager team_manager_;
|
||||
halo::manager* halo_manager_;
|
||||
font::floating_label_context labels_manager_;
|
||||
preferences::display_manager* prefs_disp_manager_;
|
||||
tooltips::manager* tooltips_manager_;
|
||||
game_events::manager* events_manager_;
|
||||
help::help_manager help_manager_;
|
||||
|
||||
const config& level_;
|
||||
const config& game_config_;
|
||||
const game_data& gameinfo_;
|
||||
game_state& gamestate_, gamestate_start_;
|
||||
display* gui_;
|
||||
gamestatus status_, status_start_;
|
||||
gamemap map_;
|
||||
unit_map units_, units_start_;
|
||||
events::mouse_handler mouse_handler_;
|
||||
events::menu_handler menu_handler_;
|
||||
|
||||
const int ticks_;
|
||||
int player_number_;
|
||||
int first_player_;
|
||||
bool loading_game_;
|
||||
int delay_;
|
||||
bool is_playing_;
|
||||
int current_turn_;
|
||||
const int xp_modifier_;
|
||||
};
|
||||
|
||||
|
||||
LEVEL_RESULT play_replay_level(const game_data& gameinfo, const config& terrain_config,
|
||||
const config* level, CVideo& video,
|
||||
game_state& state_of_game,
|
||||
const std::vector<config*>& story);
|
||||
|
||||
#endif
|
||||
/* $Id: replay_controller.hpp 7396 2005-07-02 21:37:20Z ott $ */
|
||||
/*
|
||||
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#ifndef REPLAY_CONTROLLER_H_INCLUDED
|
||||
#define REPLAY_CONTROLLER_H_INCLUDED
|
||||
|
||||
#include "display.hpp"
|
||||
#include "font.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "help.hpp"
|
||||
#include "hotkeys.hpp"
|
||||
#include "menu_events.hpp"
|
||||
#include "mouse_events.hpp"
|
||||
#include "playlevel.hpp"
|
||||
#include "preferences_display.hpp"
|
||||
#include "tooltips.hpp"
|
||||
#include "wml_separators.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class replay_controller : public hotkey::command_executor, public events::handler
|
||||
{
|
||||
public:
|
||||
replay_controller(const config& level, const game_data& gameinfo, game_state& state_of_game,
|
||||
const int ticks, const int num_turns, const config& game_config, CVideo& video,
|
||||
const std::vector<config*>& story);
|
||||
~replay_controller();
|
||||
|
||||
void handle_event(const SDL_Event& event);
|
||||
void replay_slice();
|
||||
bool can_execute_command(hotkey::HOTKEY_COMMAND command) const;
|
||||
|
||||
std::vector<team>& get_teams();
|
||||
unit_map get_units();
|
||||
display& get_gui();
|
||||
gamemap& get_map();
|
||||
const gamestatus& get_status();
|
||||
const int get_player_number();
|
||||
const bool is_loading_game();
|
||||
|
||||
//event handlers
|
||||
void objectives();
|
||||
void show_statistics();
|
||||
void unit_list();
|
||||
void status_table();
|
||||
void save_game();
|
||||
void load_game();
|
||||
void preferences();
|
||||
void show_chat_log();
|
||||
void show_help();
|
||||
void play_replay();
|
||||
void reset_replay();
|
||||
void stop_replay();
|
||||
void replay_next_turn();
|
||||
void replay_next_side();
|
||||
void replay_switch_fog();
|
||||
void replay_switch_shroud();
|
||||
void replay_skip_animation();
|
||||
|
||||
std::vector<team> teams_, teams_start_;
|
||||
private:
|
||||
void init(CVideo& video, const std::vector<config*>& story);
|
||||
void init_managers();
|
||||
void play_turn();
|
||||
void play_side(const int team_index);
|
||||
void update_teams();
|
||||
void update_gui();
|
||||
|
||||
//managers
|
||||
const verification_manager verify_manager_;
|
||||
teams_manager team_manager_;
|
||||
halo::manager* halo_manager_;
|
||||
font::floating_label_context labels_manager_;
|
||||
preferences::display_manager* prefs_disp_manager_;
|
||||
tooltips::manager* tooltips_manager_;
|
||||
game_events::manager* events_manager_;
|
||||
help::help_manager help_manager_;
|
||||
|
||||
const config& level_;
|
||||
const config& game_config_;
|
||||
const game_data& gameinfo_;
|
||||
game_state& gamestate_, gamestate_start_;
|
||||
display* gui_;
|
||||
gamestatus status_, status_start_;
|
||||
gamemap map_;
|
||||
unit_map units_, units_start_;
|
||||
events::mouse_handler mouse_handler_;
|
||||
events::menu_handler menu_handler_;
|
||||
|
||||
const int ticks_;
|
||||
int player_number_;
|
||||
int first_player_;
|
||||
bool loading_game_;
|
||||
int delay_;
|
||||
bool is_playing_;
|
||||
int current_turn_;
|
||||
const int xp_modifier_;
|
||||
};
|
||||
|
||||
|
||||
LEVEL_RESULT play_replay_level(const game_data& gameinfo, const config& terrain_config,
|
||||
const config* level, CVideo& video,
|
||||
game_state& state_of_game,
|
||||
const std::vector<config*>& story);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
const std::string report_names[] = { "unit_description", "unit_type",
|
||||
const std::string report_names[] = { "unit_description", "unit_type",
|
||||
"unit_level","unit_amla","unit_traits","unit_status",
|
||||
"unit_alignment","unit_abilities","unit_hp","unit_xp",
|
||||
"unit_advancement_options","unit_moves","unit_weapons",
|
||||
|
@ -181,7 +181,7 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
str << "<0,200,0>";
|
||||
else
|
||||
str << "<200,200,0>";
|
||||
|
||||
|
||||
|
||||
str << u->second.hitpoints()
|
||||
<< "/" << u->second.max_hitpoints();
|
||||
|
@ -235,7 +235,7 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
str << "<245,230,193>";
|
||||
str << at_it->damage() << "-" ;
|
||||
str << at_it->num_swarm_attacks(u->second.hitpoints(), u->second.max_hitpoints());
|
||||
str << " " << at_it->name();
|
||||
str << " " << at_it->name();
|
||||
tooltip << at_it->name() << "\n";
|
||||
tooltip << at_it->damage() << " " << _("damage") << ", ";
|
||||
tooltip << at_it->num_swarm_attacks(u->second.hitpoints(), u->second.max_hitpoints());
|
||||
|
@ -243,7 +243,7 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
|
||||
str<<"\n";
|
||||
res.add_text(str,tooltip);
|
||||
|
||||
|
||||
str << "<166,146,117> ";
|
||||
std::string range = (at_it->range() == attack_type::SHORT_RANGE ?
|
||||
_("melee") :
|
||||
|
@ -364,11 +364,11 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
if(owner == 0 || current_team.fogged(mouseover.x,mouseover.y)) {
|
||||
str << _("Village");
|
||||
} else if(owner == current_side) {
|
||||
str << _("Owned village");
|
||||
str << _("Owned village");
|
||||
} else if(current_team.is_enemy(owner)) {
|
||||
str << _("Enemy village");
|
||||
str << _("Enemy village");
|
||||
} else {
|
||||
str << _("Allied village");
|
||||
str << _("Allied village");
|
||||
}
|
||||
str << " ";
|
||||
} else {
|
||||
|
@ -376,12 +376,12 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
}
|
||||
|
||||
if(underlying.size() != 1 || underlying[0] != terrain) {
|
||||
str << "(";
|
||||
str << "(";
|
||||
|
||||
for(std::string::const_iterator i = underlying.begin(); i != underlying.end(); ++i) {
|
||||
str << map.get_terrain_info(*i).name();
|
||||
if(i+1 != underlying.end()) {
|
||||
str << ",";
|
||||
str << ",";
|
||||
}
|
||||
}
|
||||
str << ")";
|
||||
|
|
|
@ -30,12 +30,12 @@ namespace reports {
|
|||
|
||||
enum TYPE { UNIT_DESCRIPTION, UNIT_TYPE, UNIT_LEVEL, UNIT_AMLA,
|
||||
UNIT_TRAITS, UNIT_STATUS,
|
||||
UNIT_ALIGNMENT, UNIT_ABILITIES, UNIT_HP, UNIT_XP,
|
||||
UNIT_ALIGNMENT, UNIT_ABILITIES, UNIT_HP, UNIT_XP,
|
||||
UNIT_ADVANCEMENT_OPTIONS, 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,
|
||||
SIDE_PLAYING, OBSERVERS, REPORT_CLOCK,
|
||||
SIDE_PLAYING, OBSERVERS, REPORT_CLOCK,
|
||||
SELECTED_TERRAIN, EDIT_LEFT_BUTTON_FUNCTION,
|
||||
NUM_REPORTS};
|
||||
|
||||
|
|
|
@ -327,14 +327,14 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
// parallel input vectors chosen to prevent need to include SDL structures
|
||||
// elsewhere in code or create new rgb structure. It might be better to
|
||||
// just pass a vector of SDL colors instead...
|
||||
|
||||
|
||||
Uint16 new_red =(new_rgb & 0x00FF0000)>>16;
|
||||
Uint16 new_green=(new_rgb & 0x0000FF00)>>8;
|
||||
Uint16 new_blue =(new_rgb & 0x000000FF);
|
||||
|
||||
if(surf == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
surface nsurf(make_neutral_surface(surf));
|
||||
if(nsurf == NULL) {
|
||||
std::cerr << "failed to make neutral surface\n";
|
||||
|
@ -348,7 +348,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
const Uint16 new_avg = (Uint16)(((Uint16) new_red +
|
||||
(Uint16) new_green +
|
||||
(Uint16) new_blue) / 3);
|
||||
|
||||
|
||||
{
|
||||
for(std::vector<Uint32>::const_iterator temp_rgb = old_rgb.begin();
|
||||
temp_rgb!=old_rgb.end();temp_rgb++)
|
||||
|
@ -362,7 +362,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
//conversion. ok, this is no big deal :)
|
||||
//the correct formula being:
|
||||
//gray=0.299red+0.587green+0.114blue
|
||||
|
||||
|
||||
//get grey level of old color
|
||||
// const Uint16 old_grey = (Uint16)((77*(Uint16) old_r +
|
||||
// 150*(Uint16)old_g +
|
||||
|
@ -374,7 +374,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
if (old_grey>old_avg){
|
||||
old_avg = old_grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -384,12 +384,12 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
int old_r=((*temp_rgb) & 0X00FF0000)>>16;
|
||||
int old_g=((*temp_rgb) & 0X0000FF00)>>8;
|
||||
int old_b=((*temp_rgb) & 0X000000FF);
|
||||
|
||||
|
||||
// std::cout<<"recolor:"<<old_r<<","<<old_g<<","<<old_b<<"\n";
|
||||
surface_lock lock(nsurf);
|
||||
Uint32* beg = lock.pixels();
|
||||
Uint32* end = beg + nsurf->w*surf->h;
|
||||
|
||||
|
||||
//const Uint16 old_grey = (Uint16)((77*(Uint16) old_r +
|
||||
// 150*(Uint16)old_g +
|
||||
// 29*(Uint16)old_b) / 256);
|
||||
|
@ -399,7 +399,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
(Uint16)old_b) / 3);
|
||||
//calculate new color
|
||||
Uint8 new_r, new_g, new_b;
|
||||
|
||||
|
||||
// std::cout<<"recolor new vs old:"<<new_avg <<","<< old_avg<<"\n";
|
||||
// std::cout<<"recolor new:"<<new_red<<"\n";
|
||||
if(0 != new_avg){
|
||||
|
@ -411,7 +411,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
new_g=old_avg;
|
||||
new_b=old_avg;
|
||||
}
|
||||
|
||||
|
||||
while(beg != end) {
|
||||
Uint8 red, green, blue, alpha;
|
||||
SDL_GetRGBA(*beg,nsurf->format,&red,&green,&blue,&alpha);
|
||||
|
@ -422,7 +422,7 @@ surface recolor_image(surface surf, Uint32 new_rgb, std::vector<Uint32> old_rgb)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return create_optimized_surface(nsurf);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ team::team_info::team_info(const config& cfg)
|
|||
}else{
|
||||
team_rgb_.erase(side);
|
||||
}
|
||||
|
||||
|
||||
flag = cfg["flag"];
|
||||
|
||||
description = cfg["description"];
|
||||
|
@ -911,7 +911,7 @@ const Uint32 team::get_side_rgb(int side){
|
|||
if(p != team_rgb_.end()){
|
||||
return(p->second);
|
||||
}
|
||||
size_t index = size_t(get_side_colour_index(side) - 1);
|
||||
size_t index = size_t(get_side_colour_index(side) - 1);
|
||||
|
||||
static const Uint32 sides[] = { 0x00FF0000,
|
||||
0x000000FF,
|
||||
|
@ -931,13 +931,13 @@ const Uint32 team::get_side_rgb(int side){
|
|||
return sides[index];
|
||||
} else {
|
||||
return sides[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SDL_Color team::get_side_colour(int side)
|
||||
{
|
||||
Uint32 rgb=get_side_rgb(side);
|
||||
SDL_Color color={ (0x00FF0000 & rgb)>>16,
|
||||
SDL_Color color={ (0x00FF0000 & rgb)>>16,
|
||||
(0x0000FF00 & rgb)>>8,
|
||||
(0x000000FF & rgb),
|
||||
0} ;
|
||||
|
|
10
src/unit.cpp
10
src/unit.cpp
|
@ -1027,7 +1027,7 @@ std::map<std::string,std::string> unit::advancement_icons() const
|
|||
std::stringstream tooltip;
|
||||
image=game_config::level_image;
|
||||
std::vector<std::string> adv=type().advances_to();
|
||||
for(std::vector<std::string>::const_iterator i=adv.begin();i!=adv.end();i++){
|
||||
for(std::vector<std::string>::const_iterator i=adv.begin();i!=adv.end();i++){
|
||||
if((*i).size()){
|
||||
tooltip<<(*i).c_str()<<"\n";
|
||||
}
|
||||
|
@ -1035,7 +1035,7 @@ std::map<std::string,std::string> unit::advancement_icons() const
|
|||
temp[image]=tooltip.str();
|
||||
}
|
||||
const config::child_list mods=get_modification_advances();
|
||||
for(config::child_list::const_iterator i = mods.begin(); i != mods.end(); ++i) {
|
||||
for(config::child_list::const_iterator i = mods.begin(); i != mods.end(); ++i) {
|
||||
image=(**i)["image"];
|
||||
if(image.size()){
|
||||
std::stringstream tooltip;
|
||||
|
@ -1046,7 +1046,7 @@ std::map<std::string,std::string> unit::advancement_icons() const
|
|||
}
|
||||
temp[image]=tooltip.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(temp);
|
||||
}
|
||||
|
@ -1060,9 +1060,9 @@ std::vector<std::pair<std::string,std::string> > unit::amla_icons() const
|
|||
for(config::child_list::const_iterator i = advances.begin(); i != advances.end(); ++i) {
|
||||
icon.first=(**i)["image"];
|
||||
icon.second=(**i)["description"];
|
||||
|
||||
|
||||
for(int j=0;j<(modification_count("advance",(**i)["id"]));j++) {
|
||||
|
||||
|
||||
temp.push_back(icon);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
bool is_flying() const;
|
||||
|
||||
bool can_advance() const;
|
||||
|
||||
|
||||
std::map<std::string,std::string> advancement_icons() const;
|
||||
std::vector<std::pair<std::string,std::string> > amla_icons() const;
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ void move_unit_between(display& disp, const gamemap& map, const gamemap::locatio
|
|||
} else {
|
||||
unit_loc = image::locator(*unit_image,u.team_rgb(),u.type().flag_rgb());
|
||||
}
|
||||
|
||||
|
||||
surface image(image::get_image(unit_loc));
|
||||
if (!face_left) {
|
||||
image.assign(image::reverse_image(image));
|
||||
|
@ -395,7 +395,7 @@ bool unit_attack_ranged(display& disp, unit_map& units,
|
|||
const bool hits = damage > 0;
|
||||
const int begin_at = attack_anim.get_first_frame_time(unit_animation::UNIT_FRAME);
|
||||
// more damage shown for longer, but 1s at most for this factor
|
||||
const int end_at = maximum<int>(minimum<int>((damage+1)*time_resolution+missile_impact, 1000),
|
||||
const int end_at = maximum<int>(minimum<int>((damage+1)*time_resolution+missile_impact, 1000),
|
||||
maximum(attack_anim.get_last_frame_time(),real_last_missile));
|
||||
|
||||
const double xsrc = disp.get_location_x(a);
|
||||
|
|
|
@ -533,7 +533,7 @@ unit_type::unit_type(const unit_type& o)
|
|||
alignment_(o.alignment_),
|
||||
movementType_(o.movementType_), possibleTraits_(o.possibleTraits_),
|
||||
genders_(o.genders_), defensive_animations_(o.defensive_animations_),
|
||||
teleport_animations_(o.teleport_animations_), extra_animations_(o.extra_animations_),
|
||||
teleport_animations_(o.teleport_animations_), extra_animations_(o.extra_animations_),
|
||||
death_animations_(o.death_animations_), flag_rgb_(o.flag_rgb_)
|
||||
{
|
||||
gender_types_[0] = o.gender_types_[0] != NULL ? new unit_type(*o.gender_types_[0]) : NULL;
|
||||
|
@ -712,7 +712,7 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
|
|||
//construct rgb values;
|
||||
{
|
||||
for(int i = 0; i != flag_red_.size(); i++){
|
||||
//stolen from display.cpp, but don't want to include header
|
||||
//stolen from display.cpp, but don't want to include header
|
||||
//for such a simple function
|
||||
flag_rgb_.push_back(Uint32 (0xFF000000 | (flag_red_[i] << 16) | (flag_green_[i] << 8) | flag_blue_[i]) );
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue