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:
John B. Messerly 2004-05-09 05:14:50 +00:00
parent a367e9c394
commit 283370720d
9 changed files with 97 additions and 45 deletions

View file

@ -615,6 +615,7 @@ race="Race"
team="Team"
color="Color"
error_no_mp_sides="No multiplayer sides."
shared_vision="Shared Vision"
#Races
elves="Elves"

View file

@ -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);

View file

@ -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_;

View file

@ -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"];

View file

@ -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();

View file

@ -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);

View file

@ -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) {

View file

@ -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");
}
}
}

View file

@ -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_;