Added a "shared vision" option to multiplayer games...
...(and single-player games, via the scenario cfg file). It causes all allied players to be able to see the same fog and shroud. Notable changes by file: * data/translations/english.cfg = added a "Shared Vision" string * src/multiplayer.[ch]pp = added a "Shared Vision" checkbox * src/multiplayer_connect.[ch]pp = added a shared_vision parameter to load_game * src/playlevel.cpp = clear shroud for each team once up front, before the first player's turn * src/replay.cpp = fixed several commands not clearing fog/shroud or refreshing the minimap properly * src/team.[ch]pp = changed shrouded(x,y) and fogged(x,y) methods to return true only if the square is shrouded/fogged for every allied player, if and only if shared vision is turned on for this team.
This commit is contained in:
parent
a367e9c394
commit
283370720d
9 changed files with 97 additions and 45 deletions
|
@ -615,6 +615,7 @@ race="Race"
|
|||
team="Team"
|
||||
color="Color"
|
||||
error_no_mp_sides="No multiplayer sides."
|
||||
shared_vision="Shared Vision"
|
||||
|
||||
#Races
|
||||
elves="Elves"
|
||||
|
|
|
@ -57,7 +57,7 @@ multiplayer_game_setup_dialog::multiplayer_game_setup_dialog(
|
|||
const config& cfg, game_state& state, bool server)
|
||||
: disp_(disp), units_data_(units_data), cfg_(cfg), state_(state), server_(server), level_(NULL), map_selection_(-1),
|
||||
maps_menu_(NULL), turns_slider_(NULL), village_gold_slider_(NULL), xp_modifier_slider_(NULL),
|
||||
fog_game_(NULL), shroud_game_(NULL), observers_game_(NULL),
|
||||
fog_game_(NULL), shroud_game_(NULL), observers_game_(NULL), shared_vision_(NULL),
|
||||
cancel_game_(NULL), launch_game_(NULL), regenerate_map_(NULL), generator_settings_(NULL),
|
||||
era_combo_(NULL), name_entry_(NULL), generator_(NULL)
|
||||
{
|
||||
|
@ -112,6 +112,9 @@ multiplayer_game_setup_dialog::multiplayer_game_setup_dialog(
|
|||
shroud_game_.assign(new gui::button(disp_,string_table["shroud"],gui::button::TYPE_CHECK));
|
||||
shroud_game_->set_check(false);
|
||||
|
||||
shared_vision_.assign(new gui::button(disp_,string_table["shared_vision"],gui::button::TYPE_CHECK));
|
||||
shared_vision_->set_check(true);
|
||||
|
||||
observers_game_.assign(new gui::button(disp_,string_table["observers"],gui::button::TYPE_CHECK));
|
||||
observers_game_->set_check(true);
|
||||
|
||||
|
@ -246,6 +249,11 @@ void multiplayer_game_setup_dialog::set_area(const SDL_Rect& area)
|
|||
|
||||
rect.y += observers_game_->location().h + border_size;
|
||||
|
||||
//Observers
|
||||
shared_vision_->set_location(rect.x,rect.y);
|
||||
|
||||
rect.y += shared_vision_->location().h + border_size;
|
||||
|
||||
std::cerr << "h\n";
|
||||
|
||||
//Buttons
|
||||
|
@ -301,10 +309,10 @@ lobby::RESULT multiplayer_game_setup_dialog::process()
|
|||
key[SDLK_UP],key[SDLK_DOWN],
|
||||
key[SDLK_PAGEUP],key[SDLK_PAGEDOWN]);
|
||||
|
||||
if(cancel_game_->process(mousex,mousey,left_button) || key[SDLK_ESCAPE])
|
||||
if(cancel_game_->pressed() || key[SDLK_ESCAPE])
|
||||
return lobby::QUIT;
|
||||
|
||||
if(launch_game_->process(mousex,mousey,left_button) || maps_menu_->double_clicked()) {
|
||||
if(launch_game_->pressed() || maps_menu_->double_clicked()) {
|
||||
if(name_entry_->text() != "") {
|
||||
return lobby::CREATE;
|
||||
} else {
|
||||
|
@ -312,12 +320,14 @@ lobby::RESULT multiplayer_game_setup_dialog::process()
|
|||
}
|
||||
}
|
||||
|
||||
fog_game_->process(mousex,mousey,left_button);
|
||||
fog_game_->pressed();
|
||||
fog_game_->draw();
|
||||
shroud_game_->process(mousex,mousey,left_button);
|
||||
shroud_game_->pressed();
|
||||
shroud_game_->draw();
|
||||
observers_game_->process(mousex,mousey,left_button);
|
||||
observers_game_->pressed();
|
||||
observers_game_->draw();
|
||||
shared_vision_->pressed();
|
||||
shared_vision_->draw();
|
||||
|
||||
events::raise_process_event();
|
||||
events::raise_draw_event();
|
||||
|
@ -479,7 +489,8 @@ void multiplayer_game_setup_dialog::start_game()
|
|||
const int res = connector.load_map((*era_list[era_combo_->selected()])["id"],
|
||||
maps_menu_->selection(), turns, village_gold_slider_->value(),
|
||||
xp_modifier_slider_->value(), fog_game_->checked(),
|
||||
shroud_game_->checked(), observers_game_->checked());
|
||||
shroud_game_->checked(), observers_game_->checked(),
|
||||
shared_vision_->checked());
|
||||
if(res == -1) {
|
||||
return;
|
||||
}
|
||||
|
@ -496,6 +507,7 @@ void multiplayer_game_setup_dialog::start_game()
|
|||
fog_game_.assign(NULL);
|
||||
shroud_game_.assign(NULL);
|
||||
observers_game_.assign(NULL);
|
||||
shared_vision_.assign(NULL);
|
||||
cancel_game_.assign(NULL);
|
||||
launch_game_.assign(NULL);
|
||||
regenerate_map_.assign(NULL);
|
||||
|
|
|
@ -61,7 +61,7 @@ private:
|
|||
util::scoped_ptr<gui::menu> maps_menu_;
|
||||
util::scoped_ptr<gui::slider> turns_slider_, village_gold_slider_, xp_modifier_slider_;
|
||||
util::scoped_ptr<gui::button> fog_game_, shroud_game_, observers_game_,
|
||||
cancel_game_, launch_game_,
|
||||
cancel_game_, launch_game_, shared_vision_,
|
||||
regenerate_map_, generator_settings_;
|
||||
|
||||
util::scoped_ptr<gui::combo> era_combo_;
|
||||
|
|
|
@ -68,7 +68,7 @@ mp_connect::~mp_connect()
|
|||
}
|
||||
|
||||
int mp_connect::load_map(const std::string& era, int map, int num_turns, int village_gold, int xpmodifier,
|
||||
bool fog_game, bool shroud_game, bool allow_observers)
|
||||
bool fog_game, bool shroud_game, bool allow_observers, bool shared_vision)
|
||||
{
|
||||
log_scope("load_map");
|
||||
// Setup the game
|
||||
|
@ -217,6 +217,12 @@ int mp_connect::load_map(const std::string& era, int map, int num_turns, int vil
|
|||
|
||||
if(side["shroud"].empty())
|
||||
side["shroud"] = shroud_game ? "yes" : "no";
|
||||
|
||||
if(side["share_maps"].empty())
|
||||
side["share_maps"] = shared_vision ? "yes" : "no";
|
||||
|
||||
if(side["share_vision"].empty())
|
||||
side["share_vision"] = shared_vision ? "yes" : "no";
|
||||
|
||||
if(side["name"].empty())
|
||||
side["name"] = (*possible_sides.front())["name"];
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
~mp_connect();
|
||||
|
||||
int load_map(const std::string& era, int map, int num_turns, int village_gold, int xpmodifier,
|
||||
bool fog_game, bool shroud_game, bool allow_observers);
|
||||
bool fog_game, bool shroud_game, bool allow_observers, bool shared_vision);
|
||||
|
||||
void start_game();
|
||||
|
||||
|
|
|
@ -357,6 +357,11 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
|
|||
events::raise_draw_event();
|
||||
game_events::fire("start");
|
||||
gui.draw();
|
||||
|
||||
for(std::vector<team>::iterator t = teams.begin(); t != teams.end(); ++t) {
|
||||
clear_shroud(gui,status,map,gameinfo,units,teams,(t-teams.begin()));
|
||||
}
|
||||
gui.recalculate_minimap();
|
||||
}
|
||||
|
||||
gui.new_turn();
|
||||
|
@ -531,8 +536,6 @@ redo_turn:
|
|||
uit->second.end_turn();
|
||||
}
|
||||
|
||||
team_it->get_shared_maps();
|
||||
|
||||
game_events::pump();
|
||||
|
||||
check_victory(units,teams);
|
||||
|
|
|
@ -641,6 +641,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
statistics::recruit_unit(new_unit);
|
||||
|
||||
current_team.spend_gold(u_type->second.cost());
|
||||
if(clear_shroud(disp,state,map,gameinfo,units,teams,team_num-1))
|
||||
disp.recalculate_minimap();
|
||||
}
|
||||
|
||||
else if((child = cfg->child("recall")) != NULL) {
|
||||
|
@ -662,6 +664,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
std::cerr << "illegal recall\n";
|
||||
throw replay::error();
|
||||
}
|
||||
if(clear_shroud(disp,state,map,gameinfo,units,teams,team_num-1))
|
||||
disp.recalculate_minimap();
|
||||
}
|
||||
|
||||
else if((child = cfg->child("move")) != NULL) {
|
||||
|
@ -740,7 +744,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
game_events::fire("sighted",dst);
|
||||
}
|
||||
|
||||
clear_shroud(disp,state,map,gameinfo,units,teams,team_num-1);
|
||||
if(clear_shroud(disp,state,map,gameinfo,units,teams,team_num-1))
|
||||
disp.recalculate_minimap();
|
||||
}
|
||||
|
||||
else if((child = cfg->child("attack")) != NULL) {
|
||||
|
|
70
src/team.cpp
70
src/team.cpp
|
@ -141,8 +141,12 @@ team::team_info::team_info(const config& cfg)
|
|||
|
||||
use_shroud = (cfg["shroud"] == "yes");
|
||||
use_fog = (cfg["fog"] == "yes");
|
||||
share_maps = (cfg["share_maps"] != "no");
|
||||
share_maps = (cfg["share_maps"] == "yes");
|
||||
share_vision = (cfg["share_vision"] == "yes");
|
||||
|
||||
std::cerr << "use_shroud=" << use_shroud << ",use_fog=" << use_fog;
|
||||
std::cerr << ",share_maps=" << share_maps << ",share_vision=" << share_vision << '\n';
|
||||
|
||||
music = cfg["music"];
|
||||
}
|
||||
|
||||
|
@ -213,6 +217,7 @@ void team::team_info::write(config& cfg) const
|
|||
cfg["shroud"] = use_shroud ? "yes" : "no";
|
||||
cfg["fog"] = use_fog ? "yes" : "no";
|
||||
cfg["share_maps"] = share_maps ? "yes" : "no";
|
||||
cfg["share_vision"] = share_maps ? "yes" : "no";
|
||||
|
||||
if(music.empty() == false)
|
||||
cfg["music"] = music;
|
||||
|
@ -314,28 +319,6 @@ void team::new_turn()
|
|||
gold_ += income();
|
||||
}
|
||||
|
||||
void team::get_shared_maps()
|
||||
{
|
||||
if(teams == NULL || info_.team_name == "" || info_.share_maps == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(std::vector<team>::const_iterator t = teams->begin(); t != teams->end(); ++t) {
|
||||
if(t->info_.team_name != info_.team_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shroud_map& v = t->shroud_;
|
||||
for(size_t x = 0; x != v.size(); ++x) {
|
||||
for(size_t y = 0; y != v[x].size(); ++y) {
|
||||
if(v[x][y]) {
|
||||
clear_shroud(x,y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void team::spend_gold(int amount)
|
||||
{
|
||||
gold_ -= amount;
|
||||
|
@ -471,6 +454,39 @@ bool team::uses_shroud() const
|
|||
}
|
||||
|
||||
bool team::shrouded(size_t x, size_t y) const
|
||||
{
|
||||
bool res = side_shrouded(x,y);
|
||||
|
||||
if(teams == NULL || info_.team_name == "" || info_.share_maps == false || res == false)
|
||||
return res;
|
||||
|
||||
for(std::vector<team>::const_iterator t = teams->begin(); t != teams->end(); ++t) {
|
||||
if(t->info_.team_name != info_.team_name)
|
||||
continue;
|
||||
if(t->side_shrouded(x,y) == false)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool team::fogged(size_t x, size_t y) const
|
||||
{
|
||||
bool res = side_fogged(x,y);
|
||||
|
||||
if(!teams || info_.team_name.empty() || !info_.share_maps || !info_.share_vision || !res ) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for(std::vector<team>::const_iterator t = teams->begin(); t != teams->end(); ++t) {
|
||||
if(t->info_.team_name != info_.team_name)
|
||||
continue;
|
||||
if(t->side_fogged(x,y) == false)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool team::side_shrouded(size_t x, size_t y) const
|
||||
{
|
||||
if(info_.use_shroud == false)
|
||||
return false;
|
||||
|
@ -508,10 +524,10 @@ bool team::uses_fog() const
|
|||
return info_.use_fog;
|
||||
}
|
||||
|
||||
bool team::fogged(size_t x, size_t y) const
|
||||
bool team::side_fogged(size_t x, size_t y) const
|
||||
{
|
||||
if(info_.use_fog == false)
|
||||
return shrouded(x,y);
|
||||
return side_shrouded(x,y);
|
||||
|
||||
if(x >= fog_.size())
|
||||
return true;
|
||||
|
@ -520,7 +536,7 @@ bool team::fogged(size_t x, size_t y) const
|
|||
return true;
|
||||
|
||||
if(fog_[x][y])
|
||||
return shrouded(x,y);
|
||||
return side_shrouded(x,y);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
@ -604,4 +620,4 @@ void validate_side(int side)
|
|||
std::cerr << "invalid side " << side << " throwing game_error\n";
|
||||
throw gamestatus::game_error("invalid side found in unit definition");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/team.hpp
19
src/team.hpp
|
@ -22,6 +22,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//This class stores all the data for a single 'side' (in game nomenclature).
|
||||
//e.g. there is only one leader unit per team.
|
||||
class team
|
||||
{
|
||||
public:
|
||||
|
@ -59,7 +61,7 @@ public:
|
|||
|
||||
std::vector<target> targets;
|
||||
|
||||
bool use_shroud, use_fog, share_maps;
|
||||
bool use_shroud, use_fog, share_maps, share_vision;
|
||||
|
||||
std::string music;
|
||||
};
|
||||
|
@ -111,12 +113,14 @@ public:
|
|||
|
||||
std::vector<target>& targets();
|
||||
|
||||
bool uses_shroud() const;
|
||||
//Returns true if the hex is shrouded/fogged for this side, or
|
||||
//any other ally with shared vision.
|
||||
bool shrouded(size_t x, size_t y) const;
|
||||
bool clear_shroud(size_t x, size_t y);
|
||||
|
||||
bool uses_fog() const;
|
||||
bool fogged(size_t x, size_t y) const;
|
||||
|
||||
bool uses_shroud() const;
|
||||
bool clear_shroud(size_t x, size_t y);
|
||||
bool uses_fog() const;
|
||||
bool clear_fog(size_t x, size_t y);
|
||||
void refog();
|
||||
|
||||
|
@ -128,6 +132,11 @@ public:
|
|||
static int nteams();
|
||||
|
||||
private:
|
||||
//Return true if the hex is shrouded/fogged for this side only
|
||||
//Ignores allied teams.
|
||||
bool side_shrouded(size_t x, size_t y) const;
|
||||
bool side_fogged(size_t x, size_t y) const;
|
||||
|
||||
int gold_;
|
||||
std::set<gamemap::location> villages_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue