- reworking the player config dialog

This commit is contained in:
uid68698 2004-01-05 05:27:04 +00:00
parent 40fe52c2e7
commit 654f6fc85c
6 changed files with 653 additions and 451 deletions

View file

@ -47,6 +47,7 @@ wesnoth_SOURCES = about.cpp \
mouse.cpp \
multiplayer.cpp \
multiplayer_client.cpp \
multiplayer_connect.cpp \
multiplayer_lobby.cpp \
network.cpp \
pathfind.cpp \
@ -98,6 +99,7 @@ wesnoth_SOURCES = about.cpp \
mouse.hpp \
multiplayer.hpp \
multiplayer_client.hpp \
multiplayer_connect.hpp \
multiplayer_lobby.hpp \
network.hpp \
pathfind.hpp \

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# Makefile.in generated by automake 1.7.6 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
@ -183,6 +183,7 @@ wesnoth_SOURCES = about.cpp \
mouse.cpp \
multiplayer.cpp \
multiplayer_client.cpp \
multiplayer_connect.cpp \
multiplayer_lobby.cpp \
network.cpp \
pathfind.cpp \
@ -234,6 +235,7 @@ wesnoth_SOURCES = about.cpp \
mouse.hpp \
multiplayer.hpp \
multiplayer_client.hpp \
multiplayer_connect.hpp \
multiplayer_lobby.hpp \
network.hpp \
pathfind.hpp \
@ -373,15 +375,15 @@ am_wesnoth_OBJECTS = about.$(OBJEXT) actions.$(OBJEXT) ai.$(OBJEXT) \
intro.$(OBJEXT) key.$(OBJEXT) language.$(OBJEXT) log.$(OBJEXT) \
map.$(OBJEXT) mapgen.$(OBJEXT) mouse.$(OBJEXT) \
multiplayer.$(OBJEXT) multiplayer_client.$(OBJEXT) \
multiplayer_lobby.$(OBJEXT) network.$(OBJEXT) \
pathfind.$(OBJEXT) playlevel.$(OBJEXT) playturn.$(OBJEXT) \
preferences.$(OBJEXT) race.$(OBJEXT) replay.$(OBJEXT) \
reports.$(OBJEXT) sdl_utils.$(OBJEXT) show_dialog.$(OBJEXT) \
sound.$(OBJEXT) team.$(OBJEXT) terrain.$(OBJEXT) \
theme.$(OBJEXT) tooltips.$(OBJEXT) unit.$(OBJEXT) \
unit_types.$(OBJEXT) video.$(OBJEXT) button.$(OBJEXT) \
combo.$(OBJEXT) menu.$(OBJEXT) slider.$(OBJEXT) \
textbox.$(OBJEXT) widget.$(OBJEXT)
multiplayer_connect.$(OBJEXT) multiplayer_lobby.$(OBJEXT) \
network.$(OBJEXT) pathfind.$(OBJEXT) playlevel.$(OBJEXT) \
playturn.$(OBJEXT) preferences.$(OBJEXT) race.$(OBJEXT) \
replay.$(OBJEXT) reports.$(OBJEXT) sdl_utils.$(OBJEXT) \
show_dialog.$(OBJEXT) sound.$(OBJEXT) team.$(OBJEXT) \
terrain.$(OBJEXT) theme.$(OBJEXT) tooltips.$(OBJEXT) \
unit.$(OBJEXT) unit_types.$(OBJEXT) video.$(OBJEXT) \
button.$(OBJEXT) combo.$(OBJEXT) menu.$(OBJEXT) \
slider.$(OBJEXT) textbox.$(OBJEXT) widget.$(OBJEXT)
wesnoth_OBJECTS = $(am_wesnoth_OBJECTS)
wesnoth_LDADD = $(LDADD)
wesnoth_DEPENDENCIES =
@ -425,6 +427,7 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mapgen.Po ./$(DEPDIR)/menu.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mouse.Po ./$(DEPDIR)/multiplayer.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/multiplayer_client.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/multiplayer_connect.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/multiplayer_lobby.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/network.Po ./$(DEPDIR)/pathfind.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/playlevel.Po ./$(DEPDIR)/playturn.Po \
@ -453,7 +456,7 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
DIST_COMMON = Makefile.am Makefile.in
DIST_SUBDIRS = . server tools
SOURCES = $(wesnoth_SOURCES) $(wesnoth_editor_SOURCES)
@ -533,6 +536,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mouse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiplayer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiplayer_client.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiplayer_connect.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiplayer_lobby.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pathfind.Po@am__quote@
@ -556,6 +560,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/video.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/widget.Po@am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.cpp.o:
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@ -919,7 +926,7 @@ install-am: all-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
@ -927,7 +934,7 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@ -937,10 +944,9 @@ clean: clean-recursive
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-tags
dvi: dvi-recursive
@ -961,8 +967,7 @@ install-man:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
@ -983,10 +988,10 @@ uninstall-info: uninstall-info-recursive
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
clean-binPROGRAMS clean-generic clean-recursive ctags \
ctags-recursive distclean distclean-compile distclean-generic \
distclean-recursive distclean-tags distdir dvi dvi-am \
dvi-recursive info info-am info-recursive install install-am \
install-binPROGRAMS install-data install-data-am \
ctags-recursive distclean distclean-compile distclean-depend \
distclean-generic distclean-recursive distclean-tags distdir \
dvi dvi-am dvi-recursive info info-am info-recursive install \
install-am install-binPROGRAMS install-data install-data-am \
install-data-recursive install-exec install-exec-am \
install-exec-recursive install-info install-info-am \
install-info-recursive install-man install-recursive \

View file

@ -18,6 +18,7 @@
#include "image.hpp"
#include "mapgen.hpp"
#include "multiplayer.hpp"
#include "multiplayer_connect.hpp"
#include "multiplayer_client.hpp"
#include "network.hpp"
#include "playlevel.hpp"
@ -387,444 +388,42 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
if(launch_game.process(mousex,mousey,left_button)) {
if(name_entry.text().empty() == false) {
//Connector
mp_connect connector(disp, name_entry.text(), cfg, units_data, state);
// Send Initial information
config response;
config& create_game = response.add_child("create_game");
create_game["name"] = name_entry.text();
network::send_data(response);
// Setup the game
int res = maps_menu.selection();
if(res == -1)
break;
bool show_replay = false;
//if we're loading a saved game
config loaded_level;
bool loading = false;
if(size_t(res) == options.size()-1) {
loading = true;
const std::string game = dialogs::load_game_dialog(disp,&show_replay);
if(game == "")
break;
load_game(units_data,game,state);
if(state.campaign_type != "multiplayer") {
gui::show_dialog(disp,NULL,"",string_table["not_multiplayer_save_message"],gui::OK_ONLY);
break;
}
if(state.version != game_config::version) {
const int res = gui::show_dialog(disp,NULL,"",string_table["version_save_message"],gui::YES_NO);
if(res == 1)
break;
}
loaded_level = state.starting_pos;
level_ptr = &loaded_level;
//make all sides untaken
for(config::child_itors i = level_ptr->child_range("side");
i.first != i.second; ++i.first) {
(**i.first)["taken"] = "";
//tell clients not to change their race
(**i.first)["allow_changes"] = "no";
}
recorder = replay(state.replay_data);
//if this is a snapshot save, we don't want to use the replay data
if(loaded_level["snapshot"] == "yes")
recorder.set_to_end();
//add the replay data under the level data so clients can
//receive it
level_ptr->clear_children("replay");
level_ptr->add_child("replay") = state.replay_data;
} else { //creating a new game
level_ptr = levels[res];
//set the number of turns here
std::stringstream turns;
turns << cur_turns;
(*level_ptr)["turns"] = turns.str();
}
assert(level_ptr != NULL);
config& level = *level_ptr;
state.label = level.values["name"];
state.scenario = res_to_id[res];
const config::child_itors sides = level.child_range("side");
const config::child_list& possible_sides = cfg.get_children("multiplayer_side");
if(sides.first == sides.second || possible_sides.empty()) {
std::cerr << "no multiplayer sides found\n";
connector.load_map(maps_menu.selection(), cur_turns, cur_villagegold, fog_game.checked(), shroud_game.checked());
if (connector.gui_do() == 1)
{
const network::manager net_manager;
const network::server_manager server_man(15000,server);
config level = connector.get_level();
const bool network_state = accept_network_connections(disp,level);
if(network_state == false)
return -1;
}
config::child_iterator sd;
for(sd = sides.first; sd != sides.second; ++sd) {
if(!loading)
{
std::stringstream village_gold;
village_gold << cur_villagegold;
(**sd)["village_gold"] = village_gold.str();
}
if((**sd)["fog"].empty())
(**sd)["fog"] = fog_game.checked() ? "yes" : "no";
if((**sd)["shroud"].empty())
(**sd)["shroud"] = shroud_game.checked() ? "yes" : "no";
if((**sd)["name"].empty())
(**sd)["name"] = (*possible_sides.front())["name"];
if((**sd)["type"].empty())
(**sd)["type"] = (*possible_sides.front())["type"];
if((**sd)["recruit"].empty())
(**sd)["recruit"] = (*possible_sides.front())["recruit"];
if((**sd)["music"].empty())
(**sd)["music"] = (*possible_sides.front())["music"];
if((**sd)["recruitment_pattern"].empty())
(**sd)["recruitment_pattern"] =
possible_sides.front()->values["recruitment_pattern"];
if((**sd)["description"].empty())
(**sd)["description"] = preferences::login();
}
state.starting_pos = level;
// Wait to players, Configure players
gui::draw_dialog_frame((disp.x()-width)/2, (disp.y()-height)/2,
width+30, height, disp);
recorder.set_save_info(state);
//Buttons
gui::button launch2_game(disp,string_table["im_ready"]);
gui::button cancel2_game(disp,string_table["cancel"]);
launch2_game.set_xy((disp.x()/2)-launch2_game.width()/2-100,(disp.y()-height)/2+height-29);
cancel2_game.set_xy((disp.x()/2)-launch2_game.width()/2+100,(disp.y()-height)/2+height-29);
//Title and labels
SDL_Rect labelr;
font::draw_text(&disp,disp.screen_area(),24,font::NORMAL_COLOUR,
string_table["game_lobby"],-1,(disp.y()-height)/2+5);
labelr.x=0; labelr.y=0; labelr.w=disp.x(); labelr.h=disp.y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["player_type"],0,0);
font::draw_text(&disp,disp.screen_area(),14,font::GOOD_COLOUR,
string_table["player_type"],((disp.x()-width)/2+30)+(launch2_game.width()/2)-(labelr.w/2),
(disp.y()-height)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp.x(); labelr.h=disp.y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["race"],0,0);
font::draw_text(&disp,disp.screen_area(),14,font::GOOD_COLOUR,
string_table["race"],((disp.x()-width)/2+145)+(launch2_game.width()/2)-(labelr.w/2),
(disp.y()-height)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp.x(); labelr.h=disp.y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["team"],0,0);
font::draw_text(&disp,disp.screen_area(),14,font::GOOD_COLOUR,
string_table["team"],((disp.x()-width)/2+260)+(launch2_game.width()/2)-(labelr.w/2),
(disp.y()-height)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp.x(); labelr.h=disp.y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["color"],0,0);
font::draw_text(&disp,disp.screen_area(),14,font::GOOD_COLOUR,
string_table["color"],((disp.x()-width)/2+375)+(launch2_game.width()/2)-(labelr.w/2),
(disp.y()-height)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp.x(); labelr.h=disp.y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["gold"],0,0);
font::draw_text(&disp,disp.screen_area(),14,font::GOOD_COLOUR,
string_table["gold"],((disp.x()-width)/2+480)+(launch2_game.width()/2)-(labelr.w/2),
(disp.y()-height)/2+35);
//Options
std::vector<std::string> player_type;
player_type.push_back(preferences::login());
player_type.push_back(string_table["network_controlled"]);
player_type.push_back(string_table["ai_controlled"]);
player_type.push_back(string_table["human_controlled"]);
//player_race is a list of the names of possible races in the current locale.
//internal_player_race is a list of the internally used races that have
//to be saved to work properly.
std::vector<std::string> player_race, internal_player_race;
for(std::vector<config*>::const_iterator race = possible_sides.begin(); race != possible_sides.end(); ++race) {
internal_player_race.push_back((**race)["name"]);
player_race.push_back(translate_string((**race)["name"]));
}
std::vector<std::string> player_team;
for(sd = sides.first; sd != sides.second; ++sd) {
const int team_num = sd - sides.first;
std::stringstream str;
str << string_table["team"] << " " << team_num+1;
player_team.push_back(str.str());
}
std::vector<std::string> player_color;
player_color.push_back(string_table["red"]);
player_color.push_back(string_table["blue"]);
player_color.push_back(string_table["green"]);
player_color.push_back(string_table["yellow"]);
player_color.push_back(string_table["pink"]);
player_color.push_back(string_table["purple"]);
//Players
std::vector<std::string> sides_list;
std::vector<gui::combo> combo_type;
std::vector<gui::combo> combo_race;
std::vector<gui::combo> combo_team;
std::vector<gui::combo> combo_color;
std::vector<gui::slider> slider_gold;
for(sd = sides.first; sd != sides.second; ++sd) {
const int side_num = sd - sides.first;
font::draw_text(&disp,disp.screen_area(),24,font::GOOD_COLOUR,
(*sd)->values["side"],(disp.x()-width)/2+10,
(disp.y()-height)/2+53+(30*side_num));
combo_type.push_back(gui::combo(disp,player_type));
combo_type.back().set_xy((disp.x()-width)/2+30,
(disp.y()-height)/2+55+(30*side_num));
if(loading) {
if((**sd)["controller"] == "network") {
if((**sd)["description"] == "") {
combo_type.back().set_selected(1);
}else{
player_type.push_back((**sd)["description"]);
combo_type.back().set_items(player_type);
combo_type.back().set_selected(player_type.size());
}
}else if((**sd)["controller"] == "human") {
if((**sd)["description"] == preferences::login())
{
combo_type.back().set_selected(0);
}else{
combo_type.back().set_selected(3);
}
}else if((**sd)["controller"] == "ai") {
combo_type.back().set_selected(2);
}
//see if we should show the replay of the game so far
if(!recorder.empty()) {
if(false) {
recorder.set_skip(0);
} else {
if(side_num > 0) {
(**sd)["controller"] = "network";
(**sd)["description"] = "";
combo_type.back().set_selected(1);
} else {
(**sd)["controller"] = "human";
(**sd)["description"] = preferences::login();
}
std::cerr << "skipping...\n";
recorder.set_skip(-1);
}
combo_race.push_back(gui::combo(disp,player_race));
combo_race.back().set_xy((disp.x()-width)/2+145,
(disp.y()-height)/2+55+(30*side_num));
//if the race is specified in the configuration, set it
//to the default of the combo box
const std::string& race_name = (**sd)["name"];
if(race_name != "") {
const size_t race_pos = std::find(
internal_player_race.begin(),
internal_player_race.end(),
race_name) -
internal_player_race.begin();
if(race_pos != internal_player_race.size())
combo_race.back().set_selected(race_pos);
}
combo_team.push_back(gui::combo(disp,player_team));
combo_team.back().set_xy((disp.x()-width)/2+260,
(disp.y()-height)/2+55+(30*side_num));
combo_team.back().set_selected(side_num);
combo_color.push_back(gui::combo(disp,player_color));
combo_color.back().set_xy((disp.x()-width)/2+375,
(disp.y()-height)/2+55+(30*side_num));
combo_color.back().set_selected(side_num);
//Player Gold
rect.x = (disp.x()-width)/2+490;
rect.y = (disp.y()-height)/2+55+(30*side_num);
rect.w = launch2_game.width()-5;
rect.h = launch2_game.height();
int intgold;
if(loading) {
intgold = atoi ((**sd)["gold"].c_str());
} else {
intgold = 100;
(**sd)["gold"] = "100";
}
slider_gold.push_back(gui::slider(disp,rect,0.0+((intgold-20.0)/979.0)));
rect.w = 30;
rect.x = (disp.x()-width)/2+603;
village_bg=get_surface_portion(disp.video().getSurface(), rect);
font::draw_text(&disp,disp.screen_area(),12,font::GOOD_COLOUR,
(**sd)["gold"],rect.x,rect.y);
}
update_whole_screen();
for(;;) {
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
for(size_t n = 0; n != combo_type.size(); ++n) {
//FIXME: the locals player should not be able to
// change the combo_type of another network
// player that has already joined the game.
config& side = **(sides.first+n);
if(side["allow_changes"] != "no"){
if(combo_type[n].process(mousex,mousey,left_button)) {
if(combo_type[n].selected() == 0) {
side["controller"] = "human";
side["description"] = preferences::login();
for(size_t m = 0; m != combo_type.size(); ++m) {
if(m != n) {
if(combo_type[m].selected() == 0){
combo_type[m].set_selected(1);
config& si = **(sides.first+m);
si["controller"] = "network";
si["description"] = "";
}
}
}
}else if(combo_type[n].selected() == 1){
side["controller"] = "network";
side["description"] = "";
}else if(combo_type[n].selected() == 2){
side["controller"] = "ai";
side["description"] = string_table["ai_controlled"];
}else if(combo_type[n].selected() == 3){
side["controller"] = "human";
side["description"] = "";
}else {
side["controller"] = "network";
side["description"] = "";
}
}
}else{
combo_type[n].draw();
}
if(side["allow_changes"] != "no"){
if(combo_race[n].process(mousex,mousey,left_button))
{
const string_map& values = possible_sides[combo_race[n].selected()]->values;
for(string_map::const_iterator i = values.begin(); i != values.end(); ++i) {
side[i->first] = i->second;
}
}
}else{
combo_race[n].draw();
}
if(combo_team[n].process(mousex,mousey,left_button))
{
const size_t nsides = sides.second - sides.first;
for(size_t t = 0; t != nsides; ++t) {
std::stringstream myenemy;
for(size_t m = 0; m != nsides; ++m) {
if(combo_team[m].selected() != combo_team[t].selected()) {
myenemy << (*sides.first[m])["side"];
if(m != nsides-1)
myenemy << ",";
}
}
myenemy << "\n";
(*sides.first[t])["enemy"] = myenemy.str();
}
}
combo_color[n].process(mousex,mousey,left_button);
if(side["allow_changes"] != "no"){
int check_playergold = 20+int(979*slider_gold[n].process(mousex,mousey,left_button));
if(abs(check_playergold) == check_playergold)
new_playergold=check_playergold;
if(new_playergold != cur_playergold) {
cur_playergold = new_playergold;
std::stringstream playergold;
playergold << cur_playergold;
(*sides.first[n])["gold"] = playergold.str();
rect.x = (disp.x()-width)/2+603;
rect.y = (disp.y()-height)/2+55+(30*n);
rect.w = 30;
rect.h = launch2_game.height();
SDL_BlitSurface(village_bg, NULL, disp.video().getSurface(), &rect);
font::draw_text(&disp,disp.screen_area(),12,font::GOOD_COLOUR,
(*sides.first[n])["gold"],rect.x,rect.y);
update_rect(rect);
}
}else{
slider_gold[n].draw();
}
}
if(launch2_game.process(mousex,mousey,left_button))
{
const network::manager net_manager;
const network::server_manager server_man(15000,server);
const bool network_state = accept_network_connections(disp,level);
if(network_state == false)
return -1;
state.starting_pos = level;
recorder.set_save_info(state);
//see if we should show the replay of the game so far
if(!recorder.empty()) {
if(show_replay) {
recorder.set_skip(0);
} else {
std::cerr << "skipping...\n";
recorder.set_skip(-1);
}
}
//any replay data isn't meant to hang around under the level,
//it was just there to tell clients about the replay data
level.clear_children("replay");
std::vector<config*> story;
play_level(units_data,cfg,&level,disp.video(),state,story);
recorder.clear();
return -1;
}
if(cancel2_game.process(mousex,mousey,left_button))
{
return -1;
}
events::pump();
disp.video().flip();
SDL_Delay(20);
//any replay data isn't meant to hang around under the level,
//it was just there to tell clients about the replay data
level.clear_children("replay");
std::vector<config*> story;
play_level(units_data,cfg,&level,disp.video(),state,story);
recorder.clear();
}
return -1;
} else {
rect.x=(disp.x()-width)/2;
rect.y=(disp.y()-height)/2;

519
src/multiplayer_connect.cpp Normal file
View file

@ -0,0 +1,519 @@
/* $Id$ */
/*
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
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.
*/
#include "events.hpp"
#include "font.hpp"
#include "language.hpp"
#include "log.hpp"
#include "image.hpp"
#include "mapgen.hpp"
#include "multiplayer.hpp"
#include "multiplayer_client.hpp"
#include "multiplayer_connect.hpp"
#include "network.hpp"
#include "playlevel.hpp"
#include "preferences.hpp"
#include "replay.hpp"
#include "show_dialog.hpp"
#include "widgets/textbox.hpp"
#include "widgets/button.hpp"
#include "widgets/combo.hpp"
#include "widgets/menu.hpp"
#include "widgets/slider.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
mp_connect::mp_connect(display& disp, std::string game_name,
config &cfg, game_data& data, game_state& state,
bool join) :
disp_(&disp), cfg_(&cfg), data_(&data), state_(&state),
show_replay_(false), save_(false), status_(0), join_(join),
player_types_(), player_races_(), player_teams_(),
player_colors_(), combos_type_(), combos_race_(),
combos_team_(), combos_color_(), sliders_gold_(),
launch_(gui::button(disp, string_table["im_ready"])),
cancel_(gui::button(disp, string_table["cancel"])),
gold_bg_(NULL), width_(630), height_(290)
{
// Send Initial information
config response;
config& create_game = response.add_child("create_game");
create_game["name"] = game_name;
network::send_data(response);
}
int mp_connect::load_map(int map, int num_turns, int village_gold,
bool fog_game, bool shroud_game)
{
// Setup the game
config loaded_level;
config* level_ptr;
const config::child_list& levels = cfg_->get_children("multiplayer");
if(map == levels.size() )
{
//Load a saved game
save_ = true;
bool show_replay = false;
const std::string game = dialogs::load_game_dialog(*disp_, &show_replay);
if(game == "")
{
status_ = -1;
return status_;
}
load_game(*data_, game, *state_);
if(state_->campaign_type != "multiplayer") {
gui::show_dialog(*disp_, NULL, "",
string_table["not_multiplayer_save_message"],
gui::OK_ONLY);
status_ = -1;
return status_;
}
if(state_->version != game_config::version) {
const int res = gui::show_dialog(*disp_, NULL, "",
string_table["version_save_message"],
gui::YES_NO);
if(res == 1) {
status_ = -1;
return status_;
}
}
loaded_level = state_->starting_pos;
level_ptr= &loaded_level;
//make all sides untaken
for(config::child_itors i = level_ptr->child_range("side");
i.first != i.second; ++i.first) {
(**i.first)["taken"] = "";
//tell clients not to change their race
(**i.first)["allow_changes"] = "no";
}
recorder = replay(state_->replay_data);
//if this is a snapshot save, we don't want to use the replay data
if(loaded_level["snapshot"] == "yes")
recorder.set_to_end();
//add the replay data under the level data so clients can
//receive it
level_ptr->clear_children("replay");
level_ptr->add_child("replay") = state_->replay_data;
}else{
//Load a new map
level_ptr = levels[map];
//set the number of turns here
std::stringstream turns;
turns << num_turns;
(*level_ptr)["turns"] = turns.str();
}
assert(level_ptr != NULL);
level_ = level_ptr;
state_->label = level_->values["name"];
std::map<int,std::string> res_to_id;
for(config::child_list::const_iterator i = levels.begin(); i != levels.end(); ++i){
const std::string& id = (**i)["id"];
res_to_id[i - levels.begin()] = id;
}
state_->scenario = res_to_id[map];
const config::child_itors sides = level_->child_range("side");
const config::child_list& possible_sides = cfg_->get_children("multiplayer_side");
if(sides.first == sides.second || possible_sides.empty()) {
std::cerr << "no multiplayer sides found\n";
status_ = -1;
return status_;
}
config::child_iterator sd;
for(sd = sides.first; sd != sides.second; ++sd) {
if(!save_)
{
std::stringstream svillage_gold;
svillage_gold << village_gold;
(**sd)["village_gold"] = svillage_gold.str();
(**sd)["gold"] = "100";
}
if((**sd)["fog"].empty())
(**sd)["fog"] = fog_game ? "yes" : "no";
if((**sd)["shroud"].empty())
(**sd)["shroud"] = shroud_game ? "yes" : "no";
if((**sd)["name"].empty())
(**sd)["name"] = (*possible_sides.front())["name"];
if((**sd)["type"].empty())
(**sd)["type"] = (*possible_sides.front())["type"];
if((**sd)["recruit"].empty())
(**sd)["recruit"] = (*possible_sides.front())["recruit"];
if((**sd)["music"].empty())
(**sd)["music"] = (*possible_sides.front())["music"];
if((**sd)["recruitment_pattern"].empty())
(**sd)["recruitment_pattern"] =
possible_sides.front()->values["recruitment_pattern"];
if((**sd)["description"].empty())
(**sd)["controller"] = "network";
}
lists_init();
gui_init();
status_ = 0;
return status_;
}
void mp_connect::lists_init()
{
//Options
player_types_.push_back(string_table["network_controlled"]);
player_types_.push_back(string_table["human_controlled"]);
player_types_.push_back(string_table["ai_controlled"]);
player_types_.push_back("-----");
player_types_.push_back(preferences::login());
//Races
const config::child_itors sides = level_->child_range("side");
const config::child_list& possible_sides = cfg_->get_children("multiplayer_side");
for(std::vector<config*>::const_iterator race = possible_sides.begin();
race != possible_sides.end(); ++race) {
player_races_.push_back(translate_string((**race)["name"]));
}
//Teams
config::child_iterator sd;
for(sd = sides.first; sd != sides.second; ++sd) {
const int team_num = sd - sides.first;
std::stringstream str;
str << string_table["team"] << " " << team_num+1;
player_teams_.push_back(str.str());
}
//Colors
player_colors_.push_back(string_table["red"]);
player_colors_.push_back(string_table["blue"]);
player_colors_.push_back(string_table["green"]);
player_colors_.push_back(string_table["yellow"]);
player_colors_.push_back(string_table["pink"]);
player_colors_.push_back(string_table["purple"]);
}
void mp_connect::gui_init()
{
// Wait to players, Configure players
gui::draw_dialog_frame((disp_->x()-width_)/2, (disp_->y()-height_)/2,
width_, height_, *disp_);
//Buttons
launch_.set_xy((disp_->x()/2)-launch_.width()/2-100,
(disp_->y()-height_)/2+height_-29);
cancel_.set_xy((disp_->x()/2)-launch_.width()/2+100,
(disp_->y()-height_)/2+height_-29);
//Title and labels
SDL_Rect labelr;
font::draw_text(disp_,disp_->screen_area(),24,font::NORMAL_COLOUR,
string_table["game_lobby"],-1,(disp_->y()-height_)/2+5);
labelr.x=0; labelr.y=0; labelr.w=disp_->x(); labelr.h=disp_->y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["player_type"],0,0);
font::draw_text(disp_,disp_->screen_area(),14,font::GOOD_COLOUR,
string_table["player_type"],((disp_->x()-width_)/2+30)+(launch_.width()/2)-(labelr.w/2),
(disp_->y()-height_)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp_->x(); labelr.h=disp_->y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["race"],0,0);
font::draw_text(disp_,disp_->screen_area(),14,font::GOOD_COLOUR,
string_table["race"],((disp_->x()-width_)/2+145)+(launch_.width()/2)-(labelr.w/2),
(disp_->y()-height_)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp_->x(); labelr.h=disp_->y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["team"],0,0);
font::draw_text(disp_,disp_->screen_area(),14,font::GOOD_COLOUR,
string_table["team"],((disp_->x()-width_)/2+260)+(launch_.width()/2)-(labelr.w/2),
(disp_->y()-height_)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp_->x(); labelr.h=disp_->y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["color"],0,0);
font::draw_text(disp_,disp_->screen_area(),14,font::GOOD_COLOUR,
string_table["color"],((disp_->x()-width_)/2+375)+(launch_.width()/2)-(labelr.w/2),
(disp_->y()-height_)/2+35);
labelr.x=0; labelr.y=0; labelr.w=disp_->x(); labelr.h=disp_->y();
labelr = font::draw_text(NULL,labelr,14,font::GOOD_COLOUR,
string_table["gold"],0,0);
font::draw_text(disp_,disp_->screen_area(),14,font::GOOD_COLOUR,
string_table["gold"],((disp_->x()-width_)/2+480)+(launch_.width()/2)-(labelr.w/2),
(disp_->y()-height_)/2+35);
//Per player settings
const config::child_itors sides = level_->child_range("side");
const config::child_list& possible_sides = cfg_->get_children("multiplayer_side");
config::child_iterator sd;
SDL_Rect rect;
for(sd = sides.first; sd != sides.second; ++sd) {
const int side_num = sd - sides.first;
//Player number
font::draw_text(disp_,disp_->screen_area(), 24, font::GOOD_COLOUR,
(*sd)->values["side"], (disp_->x()-width_)/2+10,
(disp_->y()-height_)/2+53+(30*side_num));
//Player type
combos_type_.push_back(gui::combo(*disp_, player_types_));
combos_type_.back().set_xy((disp_->x()-width_)/2+30,
(disp_->y()-height_)/2+55+(30*side_num));
//Player race
combos_race_.push_back(gui::combo(*disp_, player_races_));
combos_race_.back().set_xy((disp_->x()-width_)/2+145,
(disp_->y()-height_)/2+55+(30*side_num));
//Player team
combos_team_.push_back(gui::combo(*disp_, player_teams_));
combos_team_.back().set_xy((disp_->x()-width_)/2+260,
(disp_->y()-height_)/2+55+(30*side_num));
combos_team_.back().set_selected(side_num);
//Player color
combos_color_.push_back(gui::combo(*disp_, player_colors_));
combos_color_.back().set_xy((disp_->x()-width_)/2+375,
(disp_->y()-height_)/2+55+(30*side_num));
combos_color_.back().set_selected(side_num);
//Player gold
rect.x = (disp_->x()-width_)/2+490;
rect.y = (disp_->y()-height_)/2+55+(30*side_num);
rect.w = launch_.width()-5;
rect.h = launch_.height();
sliders_gold_.push_back(gui::slider(*disp_, rect, 0.0+((80.0)/979.0)));
rect.w = 30;
rect.x = (disp_->x()-width_)/2+603;
gold_bg_ = get_surface_portion(disp_->video().getSurface(), rect);
font::draw_text(disp_, disp_->screen_area(), 12, font::GOOD_COLOUR,
"100", rect.x, rect.y);
}
update_whole_screen();
}
void mp_connect::gui_update()
{
//Update the GUI based on current config settings.
//Settings may change based on other networked
//players.
const config::child_list& possible_sides = cfg_->get_children("multiplayer_side");
const config::child_itors sides = level_->child_range("side");
for(size_t n = 0; n != combos_type_.size(); ++n) {
config& side = **(sides.first+n);
//Player type
if (side["controller"] == "network") {
combos_type_[n].set_selected(0);
} else if (side["controller"] == "human") {
if (side["description"] == preferences::login()) {
combos_type_[n].set_selected(4);
} else {
combos_type_[n].set_selected(1);
}
} else if (side["controller"] == "ai") {
combos_type_[n].set_selected(2);
}
//Player Race
for (size_t m = 0; m != player_races_.size(); ++m) {
if (translate_string(side["name"]) == player_races_[m]) {
combos_race_[n].set_selected(m);
}
}
//Player Team
//Player Color
//Player Gold
}
}
int mp_connect::gui_do()
{
SDL_Rect rect;
const config::child_list& possible_sides = cfg_->get_children("multiplayer_side");
const config::child_itors sides = level_->child_range("side");
int new_playergold;
int cur_playergold;
for(;;) {
int mousex, mousey;
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
for(size_t n = 0; n != combos_type_.size(); ++n) {
config& side = **(sides.first+n);
//Player type
//Don't let user change this if a player is sitting
if(!save_) {
if(combos_type_[n].selected() < 4) {
int old_select = combos_type_[n].selected();
if(combos_type_[n].process(mousex, mousey, left_button)) {
if(combos_type_[n].selected() == 0) {
side["controller"] = "network";
side["description"] = "";
}else if(combos_type_[n].selected() == 1){
side["controller"] = "human";
side["description"] = "";
}else if(combos_type_[n].selected() == 2){
side["controller"] = "ai";
side["description"] = string_table["ai_controlled"];
}else if(combos_type_[n].selected() == 3){
combos_type_[n].set_selected(old_select);
}else if(combos_type_[n].selected() == 4){
side["controller"] = "human";
side["description"] = preferences::login();
for(size_t m = 0; m != combos_type_.size(); ++m) {
if(m != n) {
if(combos_type_[m].selected() == 4){
combos_type_[m].set_selected(0);
config& si = **(sides.first+m);
si["controller"] = "network";
si["description"] = "";
}
}
}
}else{
side["controller"] = "network";
side["description"] = "";
}
}
}
} else {
combos_type_[n].draw();
}
//Player race
if(!save_) {
if(combos_race_[n].process(mousex, mousey, left_button)) {
const string_map& values =
possible_sides[combos_race_[n].selected()]->values;
for(string_map::const_iterator i = values.begin(); i != values.end(); ++i) {
side[i->first] = i->second;
}
}
} else {
combos_race_[n].draw();
}
//Player team
if(!save_) {
if(combos_team_[n].process(mousex, mousey, left_button)) {
const size_t nsides = sides.second - sides.first;
for(size_t t = 0; t != nsides; ++t) {
std::stringstream myenemy;
for(size_t m = 0; m != nsides; ++m) {
if(combos_team_[m].selected() != combos_team_[t].selected()) {
myenemy << (*sides.first[m])["side"];
if(m != nsides-1)
myenemy << ",";
}
}
myenemy << "\n";
(*sides.first[t])["enemy"] = myenemy.str();
}
}
} else {
combos_team_[n].draw();
}
//Player color
if(!save_) {
if(combos_color_[n].process(mousex, mousey, left_button)) {
}
} else {
combos_color_[n].draw();
}
if(!save_){
int check_playergold = 20 + int(979 *
sliders_gold_[n].process(mousex, mousey, left_button));
if(abs(check_playergold) == check_playergold)
new_playergold = check_playergold;
if(new_playergold != cur_playergold) {
cur_playergold = new_playergold;
std::stringstream playergold;
playergold << cur_playergold;
side["gold"] = playergold.str();
rect.x = (disp_->x() - width_) / 2 + 603;
rect.y = (disp_->y() - height_) / 2 + 55 + (30 * n);
rect.w = 30;
rect.h = launch_.height();
SDL_BlitSurface(gold_bg_, NULL,
disp_->video().getSurface(), &rect);
font::draw_text(disp_, disp_->screen_area(), 12,
font::GOOD_COLOUR,
(*sides.first[n])["gold"],
rect.x, rect.y);
update_rect(rect);
}
}else{
sliders_gold_[n].draw();
}
}
if(cancel_.process(mousex,mousey,left_button)) {
status_ = 0;
return status_;
}
if(launch_.process(mousex,mousey,left_button)) {
status_ = 1;
return status_;
}
gui_update();
events::pump();
disp_->video().flip();
SDL_Delay(20);
}
return status_;
}
config &mp_connect::get_level()
{
return *level_;
}

View file

@ -0,0 +1,76 @@
/* $Id$ */
/*
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
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 MULTIPLAYER_CONNECT_H_INCLUDED
#define MULTIPLAYER_CONNECT_H_INCLUDED
#include "widgets/textbox.hpp"
#include "widgets/button.hpp"
#include "widgets/combo.hpp"
#include "widgets/menu.hpp"
#include "widgets/slider.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
class mp_connect
{
public:
mp_connect (display& disp, std::string game_name,
config &cfg, game_data& units_data,
game_state& state, bool join = false);
int load_map(int map, int num_turns, int village_gold,
bool fog_game, bool shroud_game);
int gui_do();
config &get_level();
private:
void lists_init();
void gui_init();
void gui_update();
display *disp_;
config *cfg_;
game_data *data_;
game_state *state_;
config *level_;
bool show_replay_;
bool save_;
int status_;
bool join_;
int width_;
int height_;
std::vector<std::string> player_types_;
std::vector<std::string> player_races_;
std::vector<std::string> player_teams_;
std::vector<std::string> player_colors_;
std::vector<gui::combo> combos_type_;
std::vector<gui::combo> combos_race_;
std::vector<gui::combo> combos_team_;
std::vector<gui::combo> combos_color_;
std::vector<gui::slider> sliders_gold_;
gui::button launch_;
gui::button cancel_;
SDL_Surface *gold_bg_;
};
#endif

View file

@ -19,6 +19,7 @@
#include <string>
#include <vector>
#include <string>
class display;