/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OGAMEMP.CPP
//Description : Main Game Object - Multiplayer Game (using Imagic multiplayer SDK)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// --------- Define constant --------//
#define PLAYER_RATIO_CDROM 3
#define PLAYER_RATIO_NOCD -1
#define PLAYER_RATIO_STRING "four"
#define FORCE_MAX_FRAME_DELAY 5
enum { OPTION_BASIC,
OPTION_ADVANCED,
OPTION_ADVANCE2,
OPTION_GOAL,
};
enum { BASIC_OPTION_X_SPACE = 78,
BASIC_OPTION_HEIGHT = 32 };
enum { COLOR_OPTION_X_SPACE = 35,
COLOR_OPTION_HEIGHT = 32 };
enum { SERVICE_OPTION_X_SPACE = 180,
SERVICE_OPTION_HEIGHT = 139 };
static char race_table[MAX_RACE] = // race translation table
#if(MAX_RACE == 10)
{
RACE_CHINESE, RACE_EGYPTIAN, RACE_GREEK, RACE_JAPANESE, RACE_MAYA,
RACE_INDIAN, RACE_NORMAN, RACE_PERSIAN, RACE_VIKING, RACE_ZULU
};
#else
{
RACE_CHINESE, RACE_GREEK, RACE_JAPANESE, RACE_MAYA,
RACE_PERSIAN, RACE_NORMAN, RACE_VIKING
};
#endif
static char reverse_race_table[MAX_RACE] = // race translation table
#if(MAX_RACE == 10)
{
6, 4, 2, 8, 7, 0, 3, 1, 5, 9
};
#else
{
5, 3, 1, 6, 4, 0, 2
};
#endif
static char sub_game_mode; // 0 = new multiplayer game, 1 = load multiplayer game
static void disp_virtual_button(ButtonCustom *, int);
static void disp_virtual_tick(ButtonCustom *, int);
static void disp_scroll_bar_func(SlideVBar *scroll, int);
enum
{
MPMSG_START_GAME = 0x1f5a0001,
MPMSG_ABORT_GAME,
MPMSG_RANDOM_SEED, // see MpStructSeed
MPMSG_RANDOM_SEED_STR,
MPMSG_DECLARE_NATION, // see MpStructNation
MPMSG_END_SETTING,
MPMSG_START_LOAD_GAME,
MPMSG_ACCEPT_DECLARE_NATION, // used in loading multiplayer game
MPMSG_REFUSE_DECLARE_NATION,
MPMSG_SEND_CONFIG,
MPMSG_NEW_PLAYER,
MPMSG_ACCEPT_NEW_PLAYER,
MPMSG_REFUSE_NEW_PLAYER,
MPMSG_ACQUIRE_COLOR,
MPMSG_ACCEPT_COLOR,
MPMSG_REFUSE_COLOR,
MPMSG_ACQUIRE_RACE,
MPMSG_ACCEPT_RACE,
MPMSG_REFUSE_RACE,
MPMSG_PLAYER_READY,
MPMSG_PLAYER_UNREADY,
MPMSG_LOAD_GAME_NEW_PLAYER,
MPMSG_SEND_CHAT_MSG,
// ### patch begin Gilbert 22/1 ######//
// introduced since version 111
MPMSG_SEND_SYNC_TEST_LEVEL,
// ### patch begin Gilbert 22/1 ######//
MPMSG_TEST_LATENCY_SEND,
MPMSG_TEST_LATENCY_ECHO,
MPMSG_SET_PROCESS_FRAME_DELAY,
};
struct MpStructBase
{
DWORD msg_id;
MpStructBase(DWORD msgId) : msg_id(msgId) {}
};
struct MpStructSeed : public MpStructBase
{
long seed;
MpStructSeed(long s) : MpStructBase(MPMSG_RANDOM_SEED), seed(s) {}
};
struct MpStructSeedStr : public MpStructBase
{
enum { RANDOM_SEED_MAX_LEN = 11 };
char seed_str[RANDOM_SEED_MAX_LEN+1];
MpStructSeedStr(char *s) : MpStructBase(MPMSG_RANDOM_SEED_STR)
{
if(s)
strcpy(seed_str, s);
else
seed_str[0] = '\0';
}
MpStructSeedStr(long l) : MpStructBase(MPMSG_RANDOM_SEED_STR)
{
ltoa(l, seed_str, 10);
}
};
struct MpStructNation : public MpStructBase
{
short nation_recno;
DWORD dp_player_id;
short color_scheme;
short race_id;
char player_name[NationArray::HUMAN_NAME_LEN+1];
MpStructNation() : MpStructBase(MPMSG_DECLARE_NATION) {}
MpStructNation(short n, DWORD playerId, short scheme, short race,
char *playerName):
MpStructBase(MPMSG_DECLARE_NATION), nation_recno(n),
dp_player_id(playerId), color_scheme(scheme), race_id(race)
{
strcpy(player_name, playerName);
}
void init(short n, DWORD playerId, short scheme, short race,
char *playerName)
{
msg_id = MPMSG_DECLARE_NATION;
nation_recno = n;
dp_player_id = playerId;
color_scheme = scheme;
race_id = race;
strcpy(player_name, playerName);
}
};
struct MpStructConfig : public MpStructBase
{
Config game_config;
MpStructConfig(Config &c) : MpStructBase(MPMSG_SEND_CONFIG), game_config(c) {}
};
struct MpStructNewPlayer : public MpStructBase
{
PID_TYPE player_id;
short player_balance; // 2 for CD-ROM version, -1 for non CD-ROM version
MpStructNewPlayer(PID_TYPE p, short bal) : MpStructBase(MPMSG_NEW_PLAYER), player_id(p),
player_balance(bal) {}
};
struct MpStructAcceptNewPlayer : public MpStructBase
{
PID_TYPE player_id;
MpStructAcceptNewPlayer(PID_TYPE p) : MpStructBase(MPMSG_ACCEPT_NEW_PLAYER), player_id(p) {}
};
struct MpStructRefuseNewPlayer : public MpStructBase
{
PID_TYPE player_id;
MpStructRefuseNewPlayer(PID_TYPE p) : MpStructBase(MPMSG_REFUSE_NEW_PLAYER), player_id(p) {}
};
struct MpStructAcquireColor : public MpStructBase
{
short color_scheme_id;
MpStructAcquireColor(short c) : MpStructBase(MPMSG_ACQUIRE_COLOR), color_scheme_id(c) {}
};
struct MpStructAcceptColor : public MpStructBase
{
PID_TYPE request_player_id;
short color_scheme_id;
MpStructAcceptColor(PID_TYPE p,short c) : MpStructBase(MPMSG_ACCEPT_COLOR),
request_player_id(p), color_scheme_id(c) {}
};
struct MpStructRefuseColor : public MpStructBase
{
PID_TYPE request_player_id;
short color_scheme_id;
MpStructRefuseColor(PID_TYPE p, short c) : MpStructBase(MPMSG_REFUSE_COLOR),
request_player_id(p), color_scheme_id(c) {}
};
struct MpStructAcquireRace : public MpStructBase
{
short race_id;
MpStructAcquireRace(short raceId) : MpStructBase(MPMSG_ACQUIRE_RACE), race_id(raceId) {}
};
struct MpStructAcceptRace : public MpStructBase
{
PID_TYPE request_player_id;
short race_id;
MpStructAcceptRace(PID_TYPE p,short raceId) : MpStructBase(MPMSG_ACCEPT_RACE),
request_player_id(p), race_id(raceId) {}
};
struct MpStructRefuseRace : public MpStructBase
{
PID_TYPE request_player_id;
short race_id;
MpStructRefuseRace(PID_TYPE p, short raceId) : MpStructBase(MPMSG_REFUSE_RACE),
request_player_id(p), race_id(raceId) {}
};
struct MpStructPlayerReady : public MpStructBase
{
PID_TYPE player_id;
MpStructPlayerReady(PID_TYPE p) : MpStructBase(MPMSG_PLAYER_READY), player_id(p) {}
};
struct MpStructPlayerUnready : public MpStructBase
{
PID_TYPE player_id;
MpStructPlayerUnready(PID_TYPE p) : MpStructBase(MPMSG_PLAYER_UNREADY), player_id(p) {}
};
struct MpStructLoadGameNewPlayer : public MpStructBase
{
PID_TYPE player_id;
short nation_recno;
short color_scheme_id;
short race_id;
DWORD frame_count; // detail to test save game from the same game
long random_seed;
short player_balance;
MpStructLoadGameNewPlayer(PID_TYPE p, Nation *n, DWORD frame, long seed, short bal) :
MpStructBase(MPMSG_LOAD_GAME_NEW_PLAYER), player_id(p),
nation_recno(n->nation_recno), color_scheme_id(n->color_scheme_id),
race_id(n->race_id), frame_count(frame), random_seed(seed), player_balance(bal)
{
}
};
struct MpStructChatMsg : public MpStructBase
{
enum { MSG_LENGTH = 60 };
char sender[MP_FRIENDLY_NAME_LEN+1];
char content[MSG_LENGTH+1];
MpStructChatMsg(char *fromName, char *message) : MpStructBase(MPMSG_SEND_CHAT_MSG)
{
if( fromName )
strcpy(sender, fromName);
else
sender[0] = '\0';
if( message )
strcpy(content, message);
else
content[0] = '\0';
}
};
struct MpStructSyncLevel : public MpStructBase
{
char sync_test_level;
MpStructSyncLevel(char syncLevel) : MpStructBase(MPMSG_SEND_SYNC_TEST_LEVEL), sync_test_level(syncLevel)
{
}
};
struct MpStructLatencySend : public MpStructBase
{
int test_id;
DWORD send_time;
MpStructLatencySend(int testId, DWORD sendTime) : MpStructBase(MPMSG_TEST_LATENCY_SEND),
test_id(testId), send_time(sendTime)
{
}
};
struct MpStructLatencyReturn : public MpStructLatencySend
{
MpStructLatencyReturn(const MpStructLatencySend &ls) : MpStructLatencySend(ls)
{
msg_id = MPMSG_TEST_LATENCY_ECHO;
}
};
struct MpStructProcessFrameDelay : public MpStructBase
{
int common_process_frame_delay;
MpStructProcessFrameDelay(int newFrameDelay) : MpStructBase(MPMSG_SET_PROCESS_FRAME_DELAY),
common_process_frame_delay(newFrameDelay)
{
}
};
//--------- Define static functions ------------//
static void pregame_disconnect_handler(DWORD playerId);
static void ingame_disconnect_handler(DWORD playerId);
/*
//--------- Begin of function Game::mp_disp_player ---------//
void Game::mp_disp_players()
{
enum { BUTTON_WIDTH=80, BUTTON_HEIGHT=22, BUTTON_Y_SPACE=26 };
enum { BUTTON_NUM=8, BUTTON_TOP_X=620, BUTTON_TOP_Y=10 };
//--------- display buttons -------//
int x=BUTTON_TOP_X;
int y=BUTTON_TOP_Y;
Button buttonArray[BUTTON_NUM];
mp_obj.poll_players();
for( int i=0 ; ifriendly_name );
}
}
//--------- End of function Game::mp_disp_players ---------//
*/
//-------- Begin of function Game::mp_broadcast_setting --------//
//
// Broadcast the latest game settings from the host to all clients.
// This function should be called by the host only
//
// see also to RemoteMsg::update_game_setting
//
void Game::mp_broadcast_setting()
{
// send (long) random seed
// send (short) no. of nations
// for each nation, send :
// (short) nation recno
// (DWORD) directPlay player id
// (short) color scheme
// (short) race id
//
short i;
int msgSize = sizeof(long) +sizeof(short) +
nation_array.size()*(3*sizeof(short)+sizeof(PID_TYPE));
RemoteMsg *remoteMsg = remote.new_msg( MSG_UPDATE_GAME_SETTING, msgSize );
char* dataPtr = remoteMsg->data_buf;
*(long*)dataPtr = m.get_random_seed();
dataPtr += sizeof(long);
*(short*)dataPtr = nation_array.size();
dataPtr += sizeof(short);
for( i=1 ; i<=nation_array.size() ; i++)
{
*(short *)dataPtr = i;
dataPtr += sizeof(short);
*(PID_TYPE *)dataPtr = nation_array[i]->player_id;
dataPtr += sizeof(PID_TYPE);
*(short *)dataPtr = nation_array[i]->color_scheme_id;
dataPtr += sizeof(short);
*(short *)dataPtr = nation_array[i]->race_id;
dataPtr += sizeof(short);
}
err_when(dataPtr - remoteMsg->data_buf > msgSize);
remote.send_free_msg(remoteMsg); // send out the message and free it after finishing sending
}
//--------- End of function Game::mp_broadcast_setting ---------//
//-------- Begin of function pregame_disconnect_handler --------//
//
// Host disconnection handler, called by Remote when one of the players
// disconnects from the game when it's still in multiplayer game setting
// menu.
//
static void pregame_disconnect_handler(DWORD playerId)
{
int i;
for( i=1 ; i<=nation_array.size() ; i++ )
{
if( nation_array[i]->player_id == playerId )
{
((DynArray*)&nation_array)->linkout(i);
break;
}
}
}
//--------- End of function pregame_disconnect_handler ---------//
//-------- Begin of function ingame_disconnect_handler --------//
//
// Host disconnection handler, called by Remote when one of the players
// disconnects from the game after the game has started.
//
static void ingame_disconnect_handler(DWORD playerId)
{
int i;
for( i=1 ; i<=nation_array.size() ; i++ )
{
if( nation_array.is_deleted(i) )
continue;
if( nation_array[i]->player_id == playerId )
{
nation_array[i]->nation_type = NATION_AI; //**BUGHERE, should have a function to set all units, structures of this nation to AI
nation_array.ai_nation_count++;
}
}
}
//--------- End of function ingame_disconnect_handler ---------//
// --------- Begin of static function multi_player_game ----------//
// avoid creating local variable in this function
// ###### begin Gilbert 13/2 #######//
void Game::multi_player_game(char *cmdLine)
// ###### end Gilbert 13/2 #######//
{
sub_game_mode = 0;
info.init_random_seed(0); // initialize the random seed
int choice, p;
mp_obj.pre_init();
// ###### begin Gilbert 13/2 #######//
if( !cmdLine || (mp_obj.init_lobbied(MAX_NATION, cmdLine), !mp_obj.init_flag) )
{ // not launched from lobby
// ###### end Gilbert 13/2 #######//
mp_obj.poll_service_providers();
choice = mp_select_service();
if( !choice )
{
mp_obj.deinit();
return;
}
#ifdef IMAGICMP
mp_obj.init(mp_obj.get_service_provider(choice)->service_id());
#else
switch(choice)
{
case 1: // IPX
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "IPX") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_IPX )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 2: // TCP/IP
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "TCP/IP") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_TCPIP )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 3: // Modem
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "Modem") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_MODEM )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 4: // Serial
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "Serial") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_SERIAL )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
}
#endif
// ####### begin Gilbert 13/2 ########//
}
// ####### end Gilbert 13/2 ########//
// do not call remote.init here, or sys.yield will call remote.poll_msg
if(!mp_obj.init_flag)
{
// BUGHERE : display error message
box.msg("Cannot initialize DirectPlay.");
mp_obj.deinit();
return;
}
// create game or join game
switch( mp_select_mode(NULL) )
{
case 1: // create game
// BUGHERE : enter session name here and player name here
if( mp_obj.create_session(config.player_name, MAX_NATION)
&& mp_obj.create_player(config.player_name, config.player_name) )
{
remote.init(&mp_obj);
remote.create_game();
}
else
{
mp_obj.deinit();
return;
}
break;
case 2: // join game
if( (choice = mp_select_session()) )
{
if( mp_obj.join_session(choice)
&& mp_obj.create_player(config.player_name, config.player_name) )
{
remote.init(&mp_obj);
remote.connect_game();
}
else
{
// can't join session
// BUGHERE : display error message here
mp_obj.deinit();
return;
}
}
else
{
mp_obj.deinit();
return;
}
break;
default: // cancel
mp_obj.deinit();
return;
}
// config game session ...
NewNationPara *nationPara = (NewNationPara *)mem_add(sizeof(NewNationPara)*MAX_NATION);
int mpPlayerCount = 0;
if( !mp_select_option(nationPara, &mpPlayerCount) )
{
mem_del(nationPara);
if( remote.is_host )
mp_obj.close_session();
remote.deinit();
mp_obj.deinit();
return;
}
// assign nation is done is mp_select_option
// ---------- initialize ec_remote --------- //
// find itself
for( p = 0; p < mpPlayerCount; ++p )
{
if( nationPara[p].dp_player_id == mp_obj.my_player_id )
{
ec_remote.init( &mp_obj, char(p+1) );
break;
}
}
err_when( p >= mpPlayerCount );
for( p = 0; p < mpPlayerCount; ++p )
{
if( nationPara[p].dp_player_id != mp_obj.my_player_id )
{
ec_remote.set_dp_id(char(p+1), nationPara[p].dp_player_id );
}
}
//---------- start game now ----------//
// vga_front.bar(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,V_LIGHT_BLUE);
// sys.blt_virtual_buf();
remote.init_start_mp();
// suppose inital sys.frame_count is 1
// find nation_array.player_recno from nationPara
for( p = 0; p < mpPlayerCount; ++p )
{
if( nationPara[p].dp_player_id == mp_obj.my_player_id )
{
// remote.init_send_queue(1, nation_array.player_recno); // but nation_array.player_recno is not set
remote.init_send_queue(1, nationPara[p].nation_recno); // initialize the send queue for later sending
break;
}
}
err_when( p >= mpPlayerCount );
remote.init_receive_queue(1);
init();
remote.handle_vga_lock = 0; // disable lock handling
battle.run(nationPara, mpPlayerCount);
mem_del(nationPara);
remote.deinit();
mp_obj.deinit();
deinit();
}
// --------- End of static function multi_player_game ----------//
// --------- Begin of static function load_mp_game ----------//
// avoid creating local variable in this function
void Game::load_mp_game(char *fileName, char *cmdLine)
{
sub_game_mode = 1;
int nationRecno;
int choice, p;
mp_obj.pre_init();
// ###### begin Gilbert 13/2 #######//
if( !cmdLine || (mp_obj.init_lobbied(MAX_NATION, cmdLine), !mp_obj.init_flag) )
{ // not launched from lobby
// ###### end Gilbert 13/2 #######//
mp_obj.poll_service_providers();
choice = mp_select_service();
if( !choice )
{
mp_obj.deinit();
return;
}
#ifdef IMAGICMP
mp_obj.init(mp_obj.get_service_provider(choice)->service_id());
#else
switch(choice)
{
case 1: // IPX
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "IPX") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_IPX )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 2: // TCP/IP
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "TCP/IP") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_TCPIP )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 3: // Modem
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "Modem") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_MODEM )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
case 4: // Serial
for(p = 1; mp_obj.get_service_provider(p); ++p)
{
if( m.str_str(mp_obj.get_service_provider(p)->description, "Serial") ||
mp_obj.get_service_provider(p)->service_id() == DPSPGUID_SERIAL )
{
mp_obj.init(mp_obj.get_service_provider(p)->service_id());
break;
}
}
break;
}
#endif
// ####### begin Gilbert 13/2 ########//
}
// ####### end Gilbert 13/2 ########//
// do not call remote.init here, or sys.yield will call remote.poll_msg
if(!mp_obj.init_flag)
{
// BUGHERE : display error message
box.msg("Cannot initialize DirectPlay.");
mp_obj.deinit();
return;
}
// load game
//if( !game_file.load_game(fileName) )
//{
// mp_obj.deinit();
// return;
//}
// count required player
int gamePlayerCount = 0;
for(nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno)
if( !nation_array.is_deleted(nationRecno) &&
(nation_array[nationRecno]->is_own() || nation_array[nationRecno]->is_remote()) )
++gamePlayerCount;
// create game or join game
switch( mp_select_mode(fileName) )
{
case 1: // create game
// BUGHERE : enter session name here and player name here
if( mp_obj.create_session(config.player_name, gamePlayerCount) // player name as session name
&& mp_obj.create_player(config.player_name, config.player_name) )
{
remote.init(&mp_obj);
remote.create_game();
}
else
{
mp_obj.deinit();
return;
}
break;
case 2: // join game
if( (choice = mp_select_session()) )
{
// BUGHERE : enter session name here and player name here
if( mp_obj.join_session(choice) && mp_obj.create_player(config.player_name, config.player_name) )
{
// count required player
gamePlayerCount = 0;
for(nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno)
if( !nation_array.is_deleted(nationRecno) && !nation_array[nationRecno]->is_ai() )
++gamePlayerCount;
remote.init(&mp_obj);
remote.connect_game();
}
else
{
// can't join session
// BUGHERE : display error message here
mp_obj.deinit();
return;
}
}
else
{
mp_obj.deinit();
return;
}
break;
default: // cancel
mp_obj.deinit();
return;
}
// config game session ...
if( !mp_select_load_option(fileName) )
{
if( remote.is_host )
mp_obj.close_session();
remote.deinit();
mp_obj.deinit();
return;
}
// assign nation is done is mp_select_load_option
// ---------- initialize ec_remote --------- //
// find itself
ec_remote.init( &mp_obj, (char) (~nation_array)->nation_recno );
for( p = 1; p <= nation_array.size(); ++p )
{
if( !nation_array.is_deleted(p) )
{
Nation *nationPtr = nation_array[p];
if( nationPtr->is_remote() )
{
ec_remote.set_dp_id((char) p, nationPtr->player_id );
}
}
}
//---------- start game now ----------//
// vga_front.bar(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,V_LIGHT_BLUE);
// sys.blt_virtual_buf();
remote.init_start_mp();
remote.init_send_queue(sys.frame_count, nation_array.player_recno); // initialize the send queue for later sending
remote.init_receive_queue(sys.frame_count);
// init();
remote.handle_vga_lock = 0; // disable lock handling
battle.run_loaded(); // 1-multiplayer game
remote.deinit();
mp_obj.deinit();
deinit();
}
// --------- End of static function load_mp_game ----------//
//-------- Begin of function Game::mp_select_service --------//
//
// Select multiplayer mode. Create a new game or connect
// to an existing game ?
//
// return : service selected, starting from 1
//
int Game::mp_select_service()
{
#ifdef IMAGICMP
enum { BUTTON_NUM = 5 };
static short buttonX[BUTTON_NUM] = { 171, 171, 171, 171, 171 };
static short buttonY[BUTTON_NUM] = { 57, 125, 193, 261, 329 };
#define SERVICE_BUTTON_WIDTH 459
#define SERVICE_BUTTON_HEIGHT 67
enum { DESC_MARGIN = 10, DESC_TOP_MARGIN = 6 };
#else
enum { BUTTON_NUM = 4 };
static short buttonX[BUTTON_NUM] = { 206, 412, 206, 412 };
static short buttonY[BUTTON_NUM] = { 94, 94, 254, 254 };
#define SERVICE_BUTTON_WIDTH SERVICE_OPTION_X_SPACE
#define SERVICE_BUTTON_HEIGHT SERVICE_OPTION_HEIGHT
#endif
#define SVOPTION_PAGE 0x00000001
#define SVOPTION_ALL 0x0fffffff
int refreshFlag = SVOPTION_ALL;
// -------- display button ---------//
Button3D returnButton;
returnButton.create(520, 538, "CANCEL-U", "CANCEL-D", 1, 0);
ButtonCustom serviceButton[BUTTON_NUM];
int b;
for( b = 0; b < BUTTON_NUM && mp_obj.get_service_provider(b+1); ++b )
{
serviceButton[b].create(buttonX[b], buttonY[b],
buttonX[b]+SERVICE_BUTTON_WIDTH-1, buttonY[b]+SERVICE_BUTTON_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL,0) );
}
int buttonCount = b;
int choice = 0;
vga_front.unlock_buf();
//-------- detect buttons ---------//
while(1)
{
MSG msg;
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage( &msg, NULL, 0, 0))
{
sys.signal_exit_flag = 1;
// BUGHERE : vga_front is unlocked
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
else if( sys.paused_flag || !sys.active_flag )
{
WaitMessage();
continue;
}
if( sys.need_redraw_flag )
{
refreshFlag = SVOPTION_ALL;
sys.need_redraw_flag = 0;
}
vga_front.lock_buf();
sys.yield();
mouse.get_event();
if( refreshFlag )
{
if( refreshFlag & SVOPTION_PAGE )
{
//--------- display interface screen -------//
image_menu.put_to_buf( &vga_back, "MPG-PG1" );
#ifdef IMAGICMP
// protection : image_menu.put_to_buf( &vga_back, "MPG-PG1");
// ensure the user has the release version (I_MENU.RES)
// image_menu2.put_to_buf( &vga_back, "MPG-PG1") get the real one
image_menu2.put_to_buf( &vga_back, "MPG-PG1");
#endif
image_menu.put_back( 234, 15,
sub_game_mode == 0 ? (char*)"TOP-NMPG" : (char*)"TOP-LMPG" );
vga.blt_buf(0, 0, vga_back.buf_width()-1, vga_back.buf_height()-1, 0);
returnButton.paint();
for( b = 0; b < buttonCount; ++b )
{
#ifdef IMAGICMP
int y = buttonY[b]+DESC_TOP_MARGIN;
// write service name to back buffer
char useBack = vga.use_back_buf;
vga.use_back();
font_bible.center_put(buttonX[b], y,
buttonX[b]+SERVICE_BUTTON_WIDTH-1, y+font_bible.max_font_height-1,
mp_obj.get_service_provider(b+1)->name_str());
y += font_bible.max_font_height;
if( mp_obj.get_service_provider(b+1)->name_str_long() )
{
font_san.put_paragraph(buttonX[b]+DESC_MARGIN, y,
buttonX[b]+SERVICE_BUTTON_WIDTH-DESC_MARGIN-1, buttonY[b]+SERVICE_BUTTON_HEIGHT-1,
mp_obj.get_service_provider(b+1)->name_str_long());
}
if( !useBack )
vga.use_front();
#endif
serviceButton[b].paint();
}
}
refreshFlag = 0;
}
sys.blt_virtual_buf(); // blt the virtual front buffer to the screen
if( config.music_flag )
{
if( !music.is_playing() )
music.play(1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
music.stop();
// ------- detect next button -------//
if( returnButton.detect() )
{
choice = 0;
break;
}
// ------- detect protocol button ---------//
for( b = 0; b < buttonCount; ++b )
{
if( serviceButton[b].detect())
{
// let the button look pushed
serviceButton[b].paint(1);
choice = b+1;
break;
}
}
if( choice)
break;
vga_front.unlock_buf();
}
if( !vga_front.buf_locked )
vga_front.lock_buf();
return choice;
}
//--------- End of function Game::mp_select_service ---------//
//-------- Begin of function Game::mp_select_mode --------//
// return 0 = cancel, 1 = create, 2 = join
int Game::mp_select_mode(char *defSaveFileName)
{
#ifdef IMAGICMP
enum { BUTTON_NUM = 5 };
static short buttonX[BUTTON_NUM] = { 171, 171, 171, 171, 171 };
static short buttonY[BUTTON_NUM] = { 57, 125, 193, 261, 329 };
#define SERVICE_BUTTON_WIDTH 459
#define SERVICE_BUTTON_HEIGHT 67
enum { DESC_MARGIN = 10, DESC_TOP_MARGIN = 6 };
#else
enum { BUTTON_NUM = 4 };
static short buttonX[BUTTON_NUM] = { 206, 412, 206, 412 };
static short buttonY[BUTTON_NUM] = { 94, 94, 254, 254 };
#define SERVICE_BUTTON_WIDTH SERVICE_OPTION_X_SPACE
#define SERVICE_BUTTON_HEIGHT SERVICE_OPTION_HEIGHT
#endif
#define SMOPTION_GETA(n) (1 << n)
#define SMOPTION_GETA_ALL 0x0000000f
#define SMOPTION_PAGE 0x08000000
#define SMOPTION_ALL 0x0fffffff
int refreshFlag = SMOPTION_ALL;
Button3D createButton, joinButton, returnButton;
// ####### begin Gilbert 13/2 ##########//
if( mp_obj.get_lobbied_name() )
{
strncpy(config.player_name, mp_obj.get_lobbied_name(), Config::PLAYER_NAME_LEN );
config.player_name[Config::PLAYER_NAME_LEN] = '\0';
}
createButton.create(120, 538, "CREATE-U", "CREATE-D", 1, 0);
if( mp_obj.is_lobbied() == 2 ) // join only
createButton.enable_flag = 0; // avoid paint();
joinButton.create(320, 538, "JOIN-U", "JOIN-D", 1, 0);
if( mp_obj.is_lobbied() == 1 ) // join only
joinButton.enable_flag = 0; // avoid paint();
// ####### end Gilbert 13/2 ##########//
returnButton.create(520, 538, "CANCEL-U", "CANCEL-D", 1, 0);
//Get get_name;
//get_name.field( 374, 470, config.player_name, Config::PLAYER_NAME_LEN, 574 );
char saveFileName[8+1]; // save game name without path or extension
if( defSaveFileName )
{
int newLen = m.str_str(defSaveFileName, "." );
if( newLen > 1)
m.str_cut(saveFileName, defSaveFileName, 1, newLen-1);
else
err_here();
if( m.str_icmpx(saveFileName, "AUTO") || m.str_icmpx(saveFileName, "AUTO2") )
{
strcpy(saveFileName, "MULTI");
}
}
else
{
strcpy(saveFileName, "MULTI");
}
//GetA getName, getSaveFile;
//getName.init( 319, 423, 582, config.player_name, Config::PLAYER_NAME_LEN, &font_san, 0);
//getName.enable_flag = !sub_game_mode; // disable the first input, all input
//getName.paint();
//getSaveFile.init( 394, 447, 582, saveFileName, 8, &font_san, 0);
//getSaveFile.enable_flag = 0;
//getSaveFile.paint();
GetAGroup keyInField(2);
GetA &getName = keyInField[0];
GetA &getSaveFile = keyInField[1];
getName.init( 319, 423, 582, config.player_name, Config::PLAYER_NAME_LEN, &font_san, 0 ,1);
getSaveFile.init( 394, 447, 582, saveFileName, 8, &font_san, 0, 1);
keyInField.set_focus(0, 0); // 0 in 2nd parameter - don't display
int rc = 0;
vga_front.unlock_buf();
while(1)
{
MSG msg;
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage( &msg, NULL, 0, 0))
{
sys.signal_exit_flag = 1;
// BUGHERE : vga_front is unlocked
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
else if( sys.paused_flag || !sys.active_flag )
{
WaitMessage();
continue;
}
if( sys.need_redraw_flag )
{
refreshFlag = SMOPTION_ALL;
sys.need_redraw_flag = 0;
}
vga_front.lock_buf();
sys.yield();
mouse.get_event();
if( refreshFlag )
{
if( refreshFlag & SMOPTION_PAGE )
{
//--------- display interface screen -------//
image_menu.put_to_buf( &vga_back, "MPG-PG1" );
#ifdef IMAGICMP
// protection : image_menu.put_to_buf( &vga_back, "MPG-PG1");
// ensure the user has the release version (I_MENU.RES)
// image_menu2.put_to_buf( &vga_back, "MPG-PG1") get the real one
image_menu2.put_to_buf( &vga_back, "MPG-PG1");
#endif
image_menu.put_back( 234, 15,
sub_game_mode == 0 ? (char*)"TOP-NMPG" : (char*)"TOP-LMPG" );
#ifdef IMAGICMP
int b = 0;
for( b = 0; mp_obj.get_service_provider(b+1); ++b )
{
int y = buttonY[b]+DESC_TOP_MARGIN;
// write service name to back buffer
char useBack = vga.use_back_buf;
vga.use_back();
font_bible.center_put(buttonX[b], y,
buttonX[b]+SERVICE_BUTTON_WIDTH-1, y+font_bible.max_font_height-1,
mp_obj.get_service_provider(b+1)->name_str());
y += font_bible.max_font_height;
if( mp_obj.get_service_provider(b+1)->name_str_long() )
{
font_san.put_paragraph(buttonX[b]+DESC_MARGIN, y,
buttonX[b]+SERVICE_BUTTON_WIDTH-DESC_MARGIN-1, buttonY[b]+SERVICE_BUTTON_HEIGHT-1,
mp_obj.get_service_provider(b+1)->name_str_long());
}
if( !useBack )
vga.use_front();
}
#endif
vga.blt_buf(0, 0, vga_back.buf_width()-1, vga_back.buf_height()-1, 0);
if( createButton.enable_flag )
createButton.paint();
if( joinButton.enable_flag )
joinButton.paint();
returnButton.paint();
}
if( refreshFlag & SMOPTION_GETA_ALL )
{
keyInField.paint();
}
refreshFlag = 0;
}
sys.blt_virtual_buf(); // blt the virtual front buffer to the screen
if( config.music_flag )
{
if( !music.is_playing() )
music.play(1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
music.stop();
if( keyInField.detect() )
{
// refreshFlag |= SMOPTION_GETA_ALL;
}
else if( returnButton.detect() )
{
rc = 0;
break;
}
else if( createButton.detect() )
{
rc = 1;
}
else if( joinButton.detect() )
{
rc = 2;
}
if( rc )
{
// check saveFileName is AUTO*
if( m.str_icmpx(getSaveFile.input_field, "AUTO") ||
m.str_icmpx(getSaveFile.input_field, "AUTO2") )
{
if( !box.ask("It is not recommended to use this save game file name, do you wish to continue?") )
{
rc = 0;
}
}
}
if( rc )
{
// correct saveFileName
int newLen;
if( (newLen = m.str_str(getSaveFile.input_field, ".")) > 0 )
{
m.str_cut(getSaveFile.input_field, getSaveFile.input_field, 1, newLen-1);
}
if( strlen(getSaveFile.input_field) == 0 )
{
// empty, set back to default save game name
strcpy( getSaveFile.input_field, "MULTI" );
}
strcpy(remote.save_file_name, saveFileName);
strcat(remote.save_file_name, ".SVM");
break;
}
vga_front.unlock_buf();
}
if( !vga_front.buf_locked )
vga_front.lock_buf();
return rc;
}
//-------- End of function Game::mp_select_mode --------//
//-------- Begin of function Game::mp_select_session --------//
int Game::mp_select_session()
{
#define SSOPTION_PAGE 0x00000010
#define SSOPTION_POLL_SESSION 0x00000001
#define SSOPTION_DISP_SESSION 0x00000002
#ifdef AMPLUS
#define SSOPTION_SCROLL_BAR 0x00000004
#endif
#define SSOPTION_ALL 0x7fffffff
enum { JOIN_BUTTON_X = 320, JOIN_BUTTON_Y = 538 };
enum { CANCEL_BUTTON_X = 520, CANCEL_BUTTON_Y = 538 };
#ifdef AMPLUS
enum { SESSION_BUTTON_X1 = 30, SESSION_BUTTON_Y1 = 160 };
enum { SESSION_BUTTON_Y_SPACING = 44, MAX_BUTTON = 8 };
enum { SESSION_BUTTON_X2 = 754,
SESSION_DESC_Y1 = SESSION_BUTTON_Y1+14,
SESSION_DESC_X1 = SESSION_BUTTON_X1 + 14, SESSION_DESC_X2 = SESSION_BUTTON_X2,
SESSION_BUTTON_Y2 = SESSION_BUTTON_Y1 + MAX_BUTTON * SESSION_BUTTON_Y_SPACING-1};
enum { SCROLL_X1=757, SCROLL_Y1 = 176, SCROLL_X2 = 770, SCROLL_Y2 = 493 };
#else
enum { SESSION_BUTTON_X1 = 108, SESSION_BUTTON_Y1 = 125 };
enum { SESSION_BUTTON_Y_SPACING = BASIC_OPTION_HEIGHT, MAX_BUTTON = 6 };
enum { SESSION_BUTTON_X2 = SESSION_BUTTON_X1 + BASIC_OPTION_X_SPACE-1,
SESSION_DESC_Y1 = SESSION_BUTTON_Y1+10,
SESSION_DESC_X1 = SESSION_BUTTON_X2 + 8, SESSION_DESC_X2 = 600,
SESSION_BUTTON_Y2 = SESSION_BUTTON_Y1 + MAX_BUTTON * SESSION_BUTTON_Y_SPACING-1};
#endif
// ####### begin Gilbert 13/2 ########//
if( mp_obj.is_lobbied() == 2 ) // join session, but selected in lobby
{
return 1;
}
// ####### end Gilbert 13/2 ########//
unsigned long refreshTime;
int refreshFlag = SSOPTION_ALL;
int choice = 0;
SessionIdType sessionGuid;
memset(&sessionGuid, 0, sizeof(sessionGuid));
// ------- initialized button -----------//
Button3D joinButton;
joinButton.create(JOIN_BUTTON_X, JOIN_BUTTON_Y, "JOIN-U", "JOIN-D", 1, 0);
joinButton.disable();
Button3D cancelButton;
cancelButton.create(CANCEL_BUTTON_X, CANCEL_BUTTON_Y, "CANCEL-U", "CANCEL-D", 1, 0);
#ifdef AMPLUS
SlideVBar scrollBar;
scrollBar.init_scroll(SCROLL_X1, SCROLL_Y1, SCROLL_X2, SCROLL_Y2,
MAX_BUTTON, disp_scroll_bar_func);
scrollBar.set(1, 1, 1); // assume it has one record
Button3D scrollUp;
scrollUp.create(SCROLL_X1,SCROLL_Y1-17, "SV-UP-U", "SV-UP-D", 1, 0);
Button3D scrollDown;
scrollDown.create(SCROLL_X1,SCROLL_Y2+1, "SV-DW-U", "SV-DW-D", 1, 0);
Blob browseArea[MAX_BUTTON];
#define BASE_SESSION scrollBar.view_recno
#else
#define BASE_SESSION 1
#endif
unsigned long pollTime = 1000;
vga_front.unlock_buf();
while(1)
{
int s;
int b;
MSG msg;
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage( &msg, NULL, 0, 0))
{
sys.signal_exit_flag = 1;
// BUGHERE : vga_front is unlocked
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
else if( sys.paused_flag || !sys.active_flag )
{
WaitMessage();
continue;
}
if( sys.need_redraw_flag )
{
refreshFlag = SSOPTION_ALL;
sys.need_redraw_flag = 0;
}
vga_front.lock_buf();
sys.yield();
mouse.get_event();
if( refreshFlag )
{
if( refreshFlag & SSOPTION_PAGE )
{
// --------- display interface screen -------//
image_menu.put_to_buf( &vga_back, "MPG-PG2" );
#ifdef AMPLUS
image_menu2.put_to_buf( &vga_back, "MPG-PG2" );
#endif
image_menu.put_back( 234, 15,
sub_game_mode == 0 ? (char*)"TOP-NMPG" : (char*)"TOP-LMPG" );
vga.blt_buf(0, 0, vga_back.buf_width()-1, vga_back.buf_height()-1, 0);
#ifdef AMPLUS
scrollBar.paint();
scrollUp.paint();
scrollDown.paint();
// capture into browseArea, scrollArea, textArea
for( b = 0; b < MAX_BUTTON; ++b)
{
browseArea[b].resize(2*sizeof(short) + (SESSION_BUTTON_X2-SESSION_BUTTON_X1+1)*SESSION_BUTTON_Y_SPACING);
vga_front.read_bitmap(
SESSION_BUTTON_X1, b*SESSION_BUTTON_Y_SPACING+SESSION_BUTTON_Y1,
SESSION_BUTTON_X2, (b+1)*SESSION_BUTTON_Y_SPACING+SESSION_BUTTON_Y1-1,
browseArea[b].ptr);
}
#endif
joinButton.paint();
cancelButton.paint();
}
if( refreshFlag & SSOPTION_POLL_SESSION )
{
pollTime = m.get_time();
if( !mp_obj.poll_sessions() )
{
// return fail if poll_sessions fails or cancel the dialogue box
choice = 0;
break;
}
// limit the pollTime between 1 sec to 10 sec
pollTime = m.get_time() - pollTime + 1000;
if( pollTime > 10000 )
pollTime = 10000;
refreshTime = m.get_time();
#ifdef AMPLUS
// ------- sort by name ---------//
mp_obj.sort_sessions(2); // sort by session name
#endif
// ------- update choice ---------- //
choice = 0;
for( s = 1; mp_obj.get_session(s); ++s )
{
if( sessionGuid == mp_obj.get_session(s)->session_id() )
choice = s;
}
if( choice > 0)
joinButton.enable();
else
joinButton.disable();
//------- update scroll bar --------//
// BUGHERE : error if empty
#ifdef AMPLUS
scrollBar.set(1, s-1, scrollBar.view_recno);
refreshFlag |= SSOPTION_SCROLL_BAR;
#endif
refreshFlag |= SSOPTION_DISP_SESSION;
}
if( refreshFlag & SSOPTION_DISP_SESSION )
{
#ifndef AMPLUS
vga.blt_buf(SESSION_BUTTON_X1, SESSION_BUTTON_Y1, SESSION_DESC_X2, SESSION_BUTTON_Y2, 0);
#endif
for( b = 0, s = BASE_SESSION; b < MAX_BUTTON; ++b, ++s )
{
#ifdef AMPLUS
vga_back.put_bitmap(
SESSION_BUTTON_X1, b*SESSION_BUTTON_Y_SPACING+SESSION_BUTTON_Y1,
browseArea[(s-1)%MAX_BUTTON].ptr);
vga.blt_buf(
SESSION_BUTTON_X1, b*SESSION_BUTTON_Y_SPACING+SESSION_BUTTON_Y1,
SESSION_BUTTON_X2, (b+1)*SESSION_BUTTON_Y_SPACING+SESSION_BUTTON_Y1-1, 0);
#endif
if( mp_obj.get_session(s) )
{
// display session description
font_san.put( SESSION_DESC_X1, SESSION_DESC_Y1 + b*SESSION_BUTTON_Y_SPACING,
mp_obj.get_session(s)->name_str(), 0, SESSION_DESC_X2 );
// display cursor
if( s == choice )
{
vga_front.adjust_brightness( SESSION_BUTTON_X1, SESSION_BUTTON_Y1 + b*SESSION_BUTTON_Y_SPACING,
SESSION_BUTTON_X2, SESSION_BUTTON_Y1 + (b+1)*SESSION_BUTTON_Y_SPACING-1, -2);
#ifndef AMPLUS
image_interface.put_front(SESSION_BUTTON_X1, SESSION_BUTTON_Y1 + b*SESSION_BUTTON_Y_SPACING, "BAS_DOWN" );
#endif
}
}
}
}
#ifdef AMPLUS
if( refreshFlag & SSOPTION_SCROLL_BAR )
{
scrollBar.paint();
}
#endif
refreshFlag = 0;
}
sys.blt_virtual_buf(); // blt the virtual front buffer to the screen
if( config.music_flag )
{
if( !music.is_playing() )
music.play(1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
music.stop();
#ifdef AMPLUS
int scrollRc = scrollBar.detect();
if( scrollRc )
{
// refreshFlag |= SSOPTION_SCROLL_BAR;
// dragging scroll bar, don't poll session
refreshFlag &= ~SSOPTION_POLL_SESSION;
// suspend the refreshTime, so session list won't update immediate after release dragging
refreshTime = m.get_time();
if( scrollRc == 1)
refreshFlag |= SSOPTION_DISP_SESSION;
}
else
#endif
{
for( b = 0, s = BASE_SESSION; b < MAX_BUTTON && mp_obj.get_session(s) ; ++b, ++s )
{
if( mouse.single_click( SESSION_BUTTON_X1, SESSION_BUTTON_Y1 + (b)*SESSION_BUTTON_Y_SPACING,
SESSION_DESC_X2, SESSION_BUTTON_Y1 + (b+1)*SESSION_BUTTON_Y_SPACING -1 ) )
{
choice = s;
sessionGuid = mp_obj.get_session(s)->session_id();
refreshFlag |= SSOPTION_DISP_SESSION;
joinButton.enable();
// suspend the refreshTime, so session list won't update immediate after release dragging
refreshTime = m.get_time();
}
}
#ifdef AMPLUS
if( scrollUp.detect() )
{
int oldValue = scrollBar.view_recno;
if( oldValue != scrollBar.set_view_recno(oldValue-1) )
refreshFlag |= SSOPTION_DISP_SESSION | SSOPTION_SCROLL_BAR;
}
if( scrollDown.detect() )
{
int oldValue = scrollBar.view_recno;
if( oldValue != scrollBar.set_view_recno(oldValue+1) )
refreshFlag |= SSOPTION_DISP_SESSION | SSOPTION_SCROLL_BAR;
}
#endif
if( choice > 0 && joinButton.detect() )
break;
if( cancelButton.detect() )
{
choice = 0;
break;
}
if( !(mouse.skey_state & SHIFT_KEY_MASK) && m.get_time() - refreshTime > pollTime )
refreshFlag |= SSOPTION_POLL_SESSION | SSOPTION_DISP_SESSION;
}
vga_front.unlock_buf();
}
if( !vga_front.buf_locked )
vga_front.lock_buf();
return choice;
}
//-------- End of function Game::mp_select_session --------//
// define bit flag for refreshFlag
#define SGOPTION_PAGE 0x40000000
#define SGOPTION_RACE 0x00000001
#define SGOPTION_COLOR 0x00000002
#define SGOPTION_AI_NATION 0x00000004
#define SGOPTION_DIFFICULTY 0x00000008
#define SGOPTION_TERRAIN 0x00000010
#define SGOPTION_LAND_MASS 0x00000020
// #### begin Gilbert 25/10 #######//
// #define SGOPTION_NAME_FIELD 0x00000040
#define SGOPTION_MAP_ID 0x00000080
// #### end Gilbert 25/10 #######//
#define SGOPTION_EXPLORED 0x00000100
#define SGOPTION_FOG 0x00000200
#define SGOPTION_TREASURE 0x00000400
#define SGOPTION_AI_TREASURE 0x00000800
#define SGOPTION_AI_AGGRESSIVE 0x00001000
#define SGOPTION_FRYHTANS 0x00002000
#define SGOPTION_RANDOM_STARTUP 0x00004000
#define SGOPTION_RAW 0x00010000
#define SGOPTION_NEAR_RAW 0x00020000
#define SGOPTION_START_TOWN 0x00040000
#define SGOPTION_TOWN_STRENGTH 0x00080000
#define SGOPTION_TOWN_EMERGE 0x00100000
#define SGOPTION_KINGDOM_EMERGE 0x00200000
#define SGOPTION_RANDOM_EVENT 0x00400000
#define SGOPTION_CLEAR_ENEMY 0x01000000
#define SGOPTION_CLEAR_MONSTER 0x02000000
#define SGOPTION_ENOUGH_PEOPLE 0x04000000
#define SGOPTION_ENOUGH_INCOME 0x08000000
// ##### begin Gilbert 25/10 #######//
#define SGOPTION_ENOUGH_SCORE 0x10000000
#define SGOPTION_TIME_LIMIT 0x20000000
// ##### end Gilbert 25/10 #######//
#define SGOPTION_ALL 0x7fffffff
#define SGOPTION_ALL_OPTIONS (SGOPTION_ALL & ~SGOPTION_PAGE & ~SGOPTION_MAP_ID)
#define MGOPTION_PLAYERS 0x00000001
#define MGOPTION_IN_MESSAGE 0x00000002
#define MGOPTION_OUT_MESSAGE 0x00000004
#define MGOPTION_ALL 0x7fffffff
//-------- Begin of function Game::mp_select_option -----------//
// return 0 = cancel, 1 = ok
int Game::mp_select_option(NewNationPara *nationPara, int *mpPlayerCount)
{
const int offsetY = 212;
char optionMode = OPTION_BASIC;
char menuTitleBitmap[] = "TOP-NMPG";
Config tempConfig = config;
tempConfig.reset_cheat_setting();
// some setting may be modified in the last game
if( tempConfig.difficulty_level != OPTION_CUSTOM )
tempConfig.change_difficulty(tempConfig.difficulty_level);
PID_TYPE from, to;
DWORD recvLen;
int sysMsgCount;
char *recvPtr;
char raceAssigned[MAX_RACE]; // master copy belongs to host's
char colorAssigned[MAX_COLOR_SCHEME]; // master copy belongs to host's
//static short raceX[MAX_RACE] = {390, 313, 236, 467, 390, 236, 313};
//static short raceY[MAX_RACE] = {276, 276, 276, 276, 243, 243, 243};
//const raceWidth = 77;
//const raceHeight = 33;
//static short colorX[MAX_COLOR_SCHEME] = {545, 581, 581, 617, 617, 545, 653};
//static short colorY[MAX_COLOR_SCHEME] = {243, 276, 243, 276, 243, 276, 276};
//const colorWidth = 36;
//const colorHeight = 33;
static short tickX[MAX_NATION] = { 103, 254, 405, 556, 103, 254, 405 };
static short tickY[MAX_NATION] = { 53, 53, 53, 53, 73, 73, 73 };
const int nameOffsetX = 23;
const int nameOffsetY = 3;
DynArray messageList(sizeof(MpStructChatMsg));
MpStructChatMsg typingMsg(tempConfig.player_name, NULL);
memset( raceAssigned, 0, sizeof(raceAssigned) );
memset( colorAssigned, 0, sizeof(colorAssigned) );
PID_TYPE hostPlayerId = 0;
PID_TYPE regPlayerId[MAX_NATION];
memset( regPlayerId, 0, sizeof(regPlayerId) );
char playerReadyFlag[MAX_NATION];
memset( playerReadyFlag, 0, sizeof(playerReadyFlag) );
short playerRace[MAX_NATION]; // host only
memset( playerRace, 0, sizeof(playerRace) );
short playerColor[MAX_NATION]; // host only
memset( playerColor, 0, sizeof(playerColor) );
short playerBalance[MAX_NATION];
memset( playerBalance, 0, sizeof(playerBalance) );
int regPlayerCount = 0;
int selfReadyFlag = 0;
int shareRace = 1; // host only, 0= exclusive race of each player
mp_obj.poll_players();
int p;
for( p = 1; p <= MAX_NATION && mp_obj.get_player(p); ++p )
{
// host only identify himself
if( !remote.is_host || mp_obj.get_player(p)->pid() == mp_obj.my_player_id )
{
regPlayerId[regPlayerCount] = mp_obj.get_player(p)->pid();
playerReadyFlag[regPlayerCount] = 0;
playerColor[regPlayerCount] = 0;
playerRace[regPlayerCount] = 0;
playerBalance[regPlayerCount] = 0;
++regPlayerCount;
}
}
int i;
long refreshFlag = SGOPTION_ALL;
// ####### begin Gilbert 25/10 #####//
long mRefreshFlag = MGOPTION_ALL;
// ####### end Gilbert 25/10 #####//
int retFlag = 0;
// randomly select a race
if( remote.is_host )
{
tempConfig.race_id = char(mp_obj.my_player_id % MAX_RACE + 1);
raceAssigned[tempConfig.race_id-1] = 1;
tempConfig.player_nation_color = 1;
colorAssigned[tempConfig.player_nation_color-1] = 1;
for( p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id; ++p );
if( p < regPlayerCount )
{
playerRace[p] = tempConfig.race_id;
playerColor[p] = tempConfig.player_nation_color;
playerBalance[p] = sys.cdrom_drive ? PLAYER_RATIO_CDROM : PLAYER_RATIO_NOCD;
}
}
else
{
tempConfig.race_id = 0;
tempConfig.player_nation_color = 0;
// ask host for a race and color code
MpStructNewPlayer msgNewPlayer( mp_obj.my_player_id,
sys.cdrom_drive ? PLAYER_RATIO_CDROM : PLAYER_RATIO_NOCD );
mp_obj.send_stream(BROADCAST_PID, &msgNewPlayer, sizeof(msgNewPlayer) );
}
// --------- initialize race button group ---------- //
ButtonCustomGroup raceGroup(MAX_RACE);
for( i = 0; i < MAX_RACE; ++i )
{
#if(MAX_RACE == 10)
raceGroup[i].create(220+(i%5)*BASIC_OPTION_X_SPACE, (i/5)*BASIC_OPTION_HEIGHT+offsetY+70,
220+(i%5+1)*BASIC_OPTION_X_SPACE-1, (i/5+1)*BASIC_OPTION_HEIGHT+offsetY+70-1,
disp_virtual_button, ButtonCustomPara(&raceGroup, race_table[i]), 0, 0);
#define Y_SHIFT_FLAG 1
#else
raceGroup[i].create(118+i*BASIC_OPTION_X_SPACE, offsetY+93,
118+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+93+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&raceGroup, race_table[i]), 0, 0);
#define Y_SHIFT_FLAG 0
#endif
}
// --------- initialize color button group ---------- //
ButtonCustomGroup colorGroup(MAX_COLOR_SCHEME);
for( i = 0; i < MAX_COLOR_SCHEME; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
colorGroup[i].create(195+i*COLOR_OPTION_X_SPACE, offsetY+139+Y_SHIFT,
195+(i+1)*COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&colorGroup, i+1), 0, 0);
#undef Y_SHIFT
}
// ---------- initialize ai_nation_count buttons --------//
ButtonCustom aiNationInc, aiNationDec;
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
aiNationInc.create(595, offsetY+139+Y_SHIFT,
595+COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, +1) );
aiNationDec.create(630, offsetY+139+Y_SHIFT,
630+COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, -1) );
#undef Y_SHIFT
}
// ---------- initialize difficulty_level button group -------//
ButtonCustomGroup diffGroup(6);
for( i = 0; i < 6; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
diffGroup[i].create( 205+i*BASIC_OPTION_X_SPACE, offsetY+184+Y_SHIFT,
205+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+184+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&diffGroup, i), 0, 0);
#undef Y_SHIFT
}
// --------- initialize terrain_set button group -------//
// ##### begin Gilbert 25/10 #######//
ButtonCustomGroup terrainGroup(3);
for( i = 0; i < 3; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
#ifdef AMPLUS
terrainGroup[i].create(166+i*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
166+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&terrainGroup, i+1), 0, 0);
#else
int k = i;
switch(i)
{
case 1: k = 2; break;
case 2: k = 1; break;
}
terrainGroup[i].create(205+k*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
205+(k+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&terrainGroup, i+1), 0, 0);
if( i == 1 )
terrainGroup[i].enable_flag = 0;
#endif
#undef Y_SHIFT
}
// ##### end Gilbert 25/10 #######//
// --------- initialize land_mass button group -------//
ButtonCustomGroup landGroup(3);
for( i = 0; i < 3; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
landGroup[i].create(439+i*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
439+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&landGroup, i+1), 0, 0);
#undef Y_SHIFT
}
GetA messageField;
messageField.init( 190, 116, 700, typingMsg.content,
MpStructChatMsg::MSG_LENGTH, &font_san, 0, 1);
// ###### begin Gilbert 25/10 #######//
// --------- initialize info.random_seed field ----------//
MpStructSeedStr msgSeedStr(info.random_seed);
GetA mapIdField;
#if(defined(SPANISH))
#define MAPID_X1 588
#elif(defined(FRENCH))
#define MAPID_X1 578
#else
#define MAPID_X1 564
#endif
mapIdField.init( MAPID_X1, offsetY+83, 700, msgSeedStr.seed_str, msgSeedStr.RANDOM_SEED_MAX_LEN, &font_san, 0, 1);
#undef MAPID_X1
// ###### end Gilbert 25/10 #######//
// --------- initialize explore_whole_map button group -------//
ButtonCustomGroup exploreGroup(2);
for( i = 0; i < 2; ++i )
{
exploreGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+74,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+74+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&exploreGroup, 1-i), 0, 0);
}
// --------- initialize fog_of_war button group -------//
ButtonCustomGroup fogGroup(2);
for( i = 0; i < 2; ++i )
{
fogGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+106,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+106+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&fogGroup, 1-i), 0, 0);
}
// --------- initialize start_up_cash/start_up_food button group -------//
ButtonCustomGroup treasureGroup(4);
for( i = 0; i < 4; ++i )
{
treasureGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+138,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+138+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&treasureGroup, i+1), 0, 0);
}
// --------- initialize ai_start_up_cash/food button group -------//
ButtonCustomGroup aiTreasureGroup(4);
for( i = 0; i < 4; ++i )
{
aiTreasureGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+170,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+170+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&aiTreasureGroup, i+1), 0, 0);
}
// --------- initialize ai_aggressiveness -------//
ButtonCustomGroup aiAggressiveGroup(4);
for( i = 0; i < 4; ++i )
{
aiAggressiveGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+202,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+202+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&aiAggressiveGroup, i+1), 0, 0);
}
// --------- initialize monster_type -------//
ButtonCustomGroup monsterGroup(3);
for( i = 0; i < 3; ++i )
{
monsterGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+234,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+234+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&monsterGroup, i), 0, 0);
}
// --------- initialize random startup button group -------//
ButtonCustomGroup randomStartUpGroup(2);
for( i = 0; i < 2; ++i )
{
randomStartUpGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+266,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+266+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&randomStartUpGroup, 1-i), 0, 0);
}
// -------- initialize start_up_raw_site buttons --------- //
ButtonCustom rawSiteInc, rawSiteDec;
rawSiteInc.create( 358, offsetY+72,
358+COLOR_OPTION_X_SPACE-1, offsetY+72+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL,0));
rawSiteDec.create( 393, offsetY+72,
393+COLOR_OPTION_X_SPACE-1, offsetY+72+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL,0));
// --------- initialize start_up_has_mine_nearby button group --------//
ButtonCustomGroup nearRawGroup(2);
for( i = 0; i < 2; ++i )
{
nearRawGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+104,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+104+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&nearRawGroup, 1-i), 0, 0);
}
// --------- initialize start_up_independent_town button group --------//
static short startTownArray[3] = { 7, 15, 30 };
ButtonCustomGroup townStartGroup(3);
for( i = 0; i < 3; ++i )
{
townStartGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+136,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+136+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townStartGroup, startTownArray[i]), 0, 0);
}
// --------- initialize independent_town_resistance button group --------//
ButtonCustomGroup townResistGroup(3);
for( i = 0; i < 3; ++i )
{
townResistGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+168,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+168+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townResistGroup, i+1), 0, 0);
}
// --------- initialize new_independent_town_emerge button group --------//
ButtonCustomGroup townEmergeGroup(2);
for( i = 0; i < 2; ++i )
{
townEmergeGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+200,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+200+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townEmergeGroup, 1-i), 0, 0);
}
// --------- initialize new_nation_emerge button group --------//
ButtonCustomGroup nationEmergeGroup(2);
for( i = 0; i < 2; ++i )
{
nationEmergeGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+232,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+232+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&nationEmergeGroup, 1-i), 0, 0);
}
// --------- initialize random_event_frequency button group --------//
ButtonCustomGroup randomEventGroup(4);
for( i = 0; i < 4; ++i )
{
randomEventGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+264,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+264+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&randomEventGroup, i), 0, 0);
}
// ---------- initialize goal buttons ----------//
// ##### begin Gilbert 25/10 #######//
ButtonCustom clearEnemyButton, clearMonsterButton, enoughPeopleButton, enoughIncomeButton, enoughScoreButton, timeLimitButton;
ButtonCustom peopleInc, peopleDec, incomeInc, incomeDec, scoreInc, scoreDec, yearInc, yearDec;
clearEnemyButton.create( 209, offsetY+109, 209+19, offsetY+109+19, // -3
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0, 1);
clearEnemyButton.enable_flag = 0;;
clearMonsterButton.create( 209, offsetY+142, 209+19, offsetY+142+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_destroy_monster);
enoughPeopleButton.create( 209, offsetY+175, 209+19, offsetY+175+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_population_flag);
enoughIncomeButton.create( 209, offsetY+208, 209+19, offsetY+208+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_economic_score_flag);
enoughScoreButton.create( 209, offsetY+241, 209+19, offsetY+241+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_total_score_flag);
timeLimitButton.create( 209, offsetY+273, 209+19, offsetY+273+19, // +29
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_year_limit_flag);
peopleInc.create( 524, offsetY+170,
524+COLOR_OPTION_X_SPACE-1, offsetY+170+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
peopleDec.create( 559, offsetY+170,
559+COLOR_OPTION_X_SPACE-1, offsetY+170+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
incomeInc.create( 524, offsetY+202,
524+COLOR_OPTION_X_SPACE-1, offsetY+202+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
incomeDec.create( 559, offsetY+202,
559+COLOR_OPTION_X_SPACE-1, offsetY+202+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
scoreInc.create( 524, offsetY+234,
524+COLOR_OPTION_X_SPACE-1, offsetY+234+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
scoreDec.create( 559, offsetY+234,
559+COLOR_OPTION_X_SPACE-1, offsetY+234+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
yearInc.create( 524, offsetY+266,
524+COLOR_OPTION_X_SPACE-1, offsetY+266+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
yearDec.create( 559, offsetY+266,
559+COLOR_OPTION_X_SPACE-1, offsetY+266+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
// ##### end Gilbert 25/10 #######//
Button3D startButton, readyButton, returnButton;
readyButton.create(120, 538, "READY-U", "READY-D", 1, 0);
startButton.create(320, 538, "START-U", "START-D", 1, 0);
returnButton.create(520, 538, "CANCEL-U", "CANCEL-D", 1, 0);
// ###### begin Gilbert 24/10 #######//
vga_front.unlock_buf();
// ###### end Gilbert 24/10 #######//
while(1)
{
// ####### begin Gilbert 23/10 #######//
MSG msg;
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage( &msg, NULL, 0, 0))
{
sys.signal_exit_flag = 1;
// BUGHERE : vga_front is unlocked
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
else if( sys.paused_flag || !sys.active_flag )
{
WaitMessage();
continue;
}
if( sys.need_redraw_flag )
{
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
sys.need_redraw_flag = 0;
}
vga_front.lock_buf();
// ####### end Gilbert 23/10 #######//
sys.yield();
mouse.get_event();
// -------- display ----------//
// ##### begin Gilbert 25/10 #####//
if( refreshFlag || mRefreshFlag )
// ##### end Gilbert 25/10 #####//
{
// ------- display basic option ---------//
if( optionMode == OPTION_BASIC )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-BSC");
#if(MAX_RACE == 10)
// protection : image_menu.put_to_buf( &vga_back, "MPG-BSC");
// ensure the user has the release version (I_MENU.RES)
// image_menu2.put_to_buf( &vga_back, "MPG-BSC") get the real one
image_menu2.put_to_buf( &vga_back, "MPG-BSC");
#endif
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_RACE )
raceGroup.paint( reverse_race_table[tempConfig.race_id-1] );
if( refreshFlag & SGOPTION_COLOR )
colorGroup.paint( tempConfig.player_nation_color-1 );
if( refreshFlag & SGOPTION_AI_NATION )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
font_san.center_put(564, offsetY+144+Y_SHIFT, 564+25, offsetY+144+Y_SHIFT+21,
m.format(tempConfig.ai_nation_count), 1);
aiNationInc.paint();
aiNationDec.paint();
#undef Y_SHIFT
}
if( refreshFlag & SGOPTION_DIFFICULTY )
diffGroup.paint(tempConfig.difficulty_level);
if( refreshFlag & SGOPTION_TERRAIN )
terrainGroup.paint(tempConfig.terrain_set-1);
if( refreshFlag & SGOPTION_LAND_MASS )
landGroup.paint(tempConfig.land_mass-1);
}
// ------- display advanced option ---------//
if( optionMode == OPTION_ADVANCED )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-O1");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
// ###### begin Gilbert 25/10 #######//
if( refreshFlag & SGOPTION_MAP_ID )
mapIdField.paint();
// ###### end Gilbert 25/10 #######//
if( refreshFlag & SGOPTION_EXPLORED )
exploreGroup.paint(1-tempConfig.explore_whole_map);
if( refreshFlag & SGOPTION_FOG )
fogGroup.paint(1-tempConfig.fog_of_war);
if( refreshFlag & SGOPTION_TREASURE )
treasureGroup.paint( tempConfig.start_up_cash-1 );
if( refreshFlag & SGOPTION_AI_TREASURE )
aiTreasureGroup.paint( tempConfig.ai_start_up_cash-1 );
if( refreshFlag & SGOPTION_AI_AGGRESSIVE )
aiAggressiveGroup.paint(tempConfig.ai_aggressiveness-1);
if( refreshFlag & SGOPTION_FRYHTANS )
monsterGroup.paint(tempConfig.monster_type);
if( refreshFlag & SGOPTION_RANDOM_STARTUP )
randomStartUpGroup.paint(1-tempConfig.random_start_up);
}
// ------- display advanced option ---------//
if( optionMode == OPTION_ADVANCE2 )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-O2");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_RAW )
{
font_san.center_put(327, offsetY+77, 327+25, offsetY+77+21,
m.format(tempConfig.start_up_raw_site), 1);
rawSiteInc.paint();
rawSiteDec.paint();
}
if( refreshFlag & SGOPTION_NEAR_RAW )
nearRawGroup.paint(1-tempConfig.start_up_has_mine_nearby);
if( refreshFlag & SGOPTION_START_TOWN )
townStartGroup.paint(
tempConfig.start_up_independent_town >= 30 ? 2 :
tempConfig.start_up_independent_town <= 7 ? 0 :
1
);
if( refreshFlag & SGOPTION_TOWN_STRENGTH )
townResistGroup.paint(tempConfig.independent_town_resistance-1);
if( refreshFlag & SGOPTION_TOWN_EMERGE )
townEmergeGroup.paint(1-tempConfig.new_independent_town_emerge);
if( refreshFlag & SGOPTION_KINGDOM_EMERGE )
nationEmergeGroup.paint(1-tempConfig.new_nation_emerge);
if( refreshFlag & SGOPTION_RANDOM_EVENT )
randomEventGroup.paint(tempConfig.random_event_frequency);
}
// ------- display goal option ---------//
if( optionMode == OPTION_GOAL )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-GOAL");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_CLEAR_ENEMY )
clearEnemyButton.paint();
if( refreshFlag & SGOPTION_CLEAR_MONSTER )
clearMonsterButton.paint(tempConfig.goal_destroy_monster);
// ####### begin Gilbert 25/10 ########//
if( refreshFlag & SGOPTION_ENOUGH_PEOPLE )
{
enoughPeopleButton.paint(tempConfig.goal_population_flag);
font_san.center_put( 446, offsetY+176, 446+67, offsetY+176+21,
m.format(tempConfig.goal_population), 1);
peopleInc.paint();
peopleDec.paint();
}
if( refreshFlag & SGOPTION_ENOUGH_INCOME )
{
enoughIncomeButton.paint(tempConfig.goal_economic_score_flag);
font_san.center_put( 446, offsetY+207, 446+67, offsetY+207+21,
m.format(tempConfig.goal_economic_score), 1);
incomeInc.paint();
incomeDec.paint();
}
if( refreshFlag & SGOPTION_ENOUGH_SCORE )
{
enoughScoreButton.paint(tempConfig.goal_total_score_flag);
font_san.center_put( 446, offsetY+239, 446+67, offsetY+239+21,
m.format(tempConfig.goal_total_score), 1);
scoreInc.paint();
scoreDec.paint();
}
if( refreshFlag & SGOPTION_TIME_LIMIT )
{
timeLimitButton.paint(tempConfig.goal_year_limit_flag);
font_san.center_put( 446, offsetY+271, 446+33, offsetY+271+21,
m.format(tempConfig.goal_year_limit), 1);
yearInc.paint();
yearDec.paint();
}
// ####### end Gilbert 25/10 ########//
}
// -------- refresh players in the session --------//
if( mRefreshFlag & MGOPTION_PLAYERS )
{
vga.blt_buf( 96, 46, 702, 100, 0 );
for( p = 0; p < regPlayerCount; ++p)
{
if( playerReadyFlag[p] )
{
image_menu.put_front( tickX[p]+3, tickY[p]+3, "NMPG-RCH" );
}
PlayerDesc *dispPlayer = mp_obj.search_player(regPlayerId[p]);
font_san.put( tickX[p]+nameOffsetX, tickY[p]+nameOffsetY, dispPlayer?dispPlayer->friendly_name_str():(char*)"?anonymous?" );
}
}
// ------------ display chat message --------//
if( mRefreshFlag & MGOPTION_OUT_MESSAGE )
{
messageField.paint();
}
// ------------- display incoming chat message --------//
if( mRefreshFlag & MGOPTION_IN_MESSAGE )
{
vga.blt_buf( 101, 135, 700, 202, 0 );
for( p = 1; p <= 4 && p <= messageList.size() ; ++p)
{
int ny = 136+(p-1)*16;
int nx = font_san.put( 102, ny, ((MpStructChatMsg *)messageList.get(p))->sender );
nx = font_san.put( nx, ny, " : ");
nx = font_san.put( nx, ny, ((MpStructChatMsg *)messageList.get(p))->content, 0, 700);
}
}
// ------- display difficulty -------//
if( (refreshFlag & SGOPTION_DIFFICULTY) || (mRefreshFlag & MGOPTION_PLAYERS) )
{
font_san.center_put( 718, offsetY+74, 780, offsetY+108,
m.format(tempConfig.multi_player_difficulty(regPlayerCount-1)), 1 );
}
// -------- repaint button -------//
if( refreshFlag & SGOPTION_PAGE )
{
if( remote.is_host )
startButton.paint();
readyButton.paint();
returnButton.paint();
}
refreshFlag = 0;
mRefreshFlag = 0;
}
sys.blt_virtual_buf();
if( config.music_flag )
{
if( !music.is_playing() )
music.play(1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
music.stop();
// --------- detect remote message -------//
mp_obj.before_receive();
recvPtr = mp_obj.receive(&from, &to, &recvLen, &sysMsgCount);
mp_obj.after_send();
if( sysMsgCount )
{
// see any player disconnect
for(int q = 0; q < regPlayerCount; ++q)
{
if( !mp_obj.is_player_connecting(regPlayerId[q]) )
{
mRefreshFlag |= MGOPTION_PLAYERS;
memmove( regPlayerId+q, regPlayerId+q+1, (MAX_NATION-1-q)*sizeof(regPlayerId[0]) );
regPlayerId[MAX_NATION-1] = 0;
memmove( playerReadyFlag+q, playerReadyFlag+q+1, (MAX_NATION-1-q)*sizeof(playerReadyFlag[0]) );
playerReadyFlag[MAX_NATION-1] = 0;
short freeColor = playerColor[q];
memmove( playerColor+q, playerColor+q+1, (MAX_NATION-1-q)*sizeof(playerColor[0]) );
playerColor[MAX_NATION-1] = 0;
if(freeColor > 0 && freeColor <= MAX_COLOR_SCHEME)
colorAssigned[freeColor-1] = 0;
short freeRace = playerRace[q];
memmove( playerRace+q, playerRace+q+1, (MAX_NATION-1-q)*sizeof(playerRace[0]) );
playerRace[MAX_NATION-1] = 0;
if(freeRace > 0 && freeRace <= MAX_RACE)
raceAssigned[freeRace-1]--;
memmove( playerBalance+q, playerBalance+q+1, (MAX_NATION-1-q)*sizeof(playerBalance[0]) );
playerBalance[MAX_NATION-1] = 0;
--regPlayerCount;
--q;
}
}
}
if( recvPtr )
{
if( ((MpStructBase *)recvPtr)->msg_id == MPMSG_START_GAME )
{
retFlag = 1;
break; // break while(1) loop
}
else
{
switch( ((MpStructBase *)recvPtr)->msg_id )
{
case MPMSG_ABORT_GAME:
return 0;
case MPMSG_SEND_CONFIG:
tempConfig.change_game_setting( ((MpStructConfig *)recvPtr)->game_config );
refreshFlag |= SGOPTION_ALL_OPTIONS;
break;
case MPMSG_RANDOM_SEED:
info.init_random_seed( ((MpStructSeed *)recvPtr)->seed );
break;
// ####### begin Gilbert 25/10 #######//
case MPMSG_RANDOM_SEED_STR:
msgSeedStr = *(MpStructSeedStr *)recvPtr;
mapIdField.select_whole();
refreshFlag |= SGOPTION_MAP_ID;
break;
// ####### end Gilbert 25/10 #######//
case MPMSG_NEW_PLAYER:
mp_obj.poll_players();
if( remote.is_host )
{
if( regPlayerCount < MAX_NATION )
{
MpStructNewPlayer *newPlayerMsg = (MpStructNewPlayer *)recvPtr;
regPlayerId[regPlayerCount] = newPlayerMsg->player_id;
playerReadyFlag[regPlayerCount] = 0;
// send accept new player to all player
MpStructAcceptNewPlayer msgAccept(from);
mp_obj.send_stream( BROADCAST_PID, &msgAccept, sizeof(msgAccept) );
// assign initial race
int c = m.get_time() % MAX_RACE;
int t;
for( t = 0; t < MAX_RACE; ++t, ++c )
{
c %= MAX_RACE;
if( raceAssigned[c] == 0 )
{
raceAssigned[c]++;
playerRace[regPlayerCount] = c+1;
MpStructAcceptRace msgAcceptRace(from, c+1);
mp_obj.send_stream( from, &msgAcceptRace, sizeof(msgAcceptRace) );
break;
}
}
err_when( t >= MAX_RACE ); // not found
// assign initial color
c = m.get_time() % MAX_COLOR_SCHEME;
for( t = 0; t < MAX_COLOR_SCHEME; ++t, ++c )
{
c %= MAX_COLOR_SCHEME;
if( !colorAssigned[c] )
{
colorAssigned[c]=1;
playerColor[regPlayerCount] = c+1;
MpStructAcceptColor msgAcceptColor(from, c+1);
mp_obj.send_stream( from, &msgAcceptColor, sizeof(msgAcceptColor) );
break;
}
}
err_when( t >= MAX_COLOR_SCHEME ); // not found
// send random seed
// ###### begin Gilbert 25/10 #######//
// MpStructSeed msgRandomSeed(m.get_random_seed());
// mp_obj.send_stream( from, &msgRandomSeed, sizeof(msgRandomSeed) );
mp_obj.send_stream( from, &msgSeedStr, sizeof(msgSeedStr) );
// ###### end Gilbert 25/10 #######//
// send config
MpStructConfig msgConfig( tempConfig );
mp_obj.send_stream( from, &msgConfig, sizeof(msgConfig) );
// send ready flag
for( c = 0; c < regPlayerCount; ++c)
{
if( playerReadyFlag[c] )
{
MpStructPlayerReady msgReady(regPlayerId[c]);
mp_obj.send_stream(from, &msgReady, sizeof(msgReady));
}
}
// ###### patch begin Gilbert 22/1 ######//
// send remote.sync_test_level
MpStructSyncLevel msgSyncTest(remote.sync_test_level);
mp_obj.send_stream( from, &msgSyncTest, sizeof(msgSyncTest) );
// ###### patch end Gilbert 22/1 ######//
// update balance
playerBalance[regPlayerCount] = newPlayerMsg->player_balance;
regPlayerCount++;
mRefreshFlag |= MGOPTION_PLAYERS;
}
else
{
// reply refuse new player
MpStructRefuseNewPlayer msgRefuse(from);
mp_obj.send_stream( BROADCAST_PID, &msgRefuse, sizeof(msgRefuse) );
}
}
break;
case MPMSG_LOAD_GAME_NEW_PLAYER:
{
// incorrect message, reject
MpStructRefuseNewPlayer msgRefuse(from);
mp_obj.send_stream(BROADCAST_PID, &msgRefuse, sizeof(msgRefuse) );
}
break;
case MPMSG_ACCEPT_NEW_PLAYER:
hostPlayerId = from;
if( regPlayerCount < MAX_NATION && ((MpStructAcceptNewPlayer *)recvPtr)->player_id != mp_obj.my_player_id )
{
// search if this player has existed
for( p=0; p < regPlayerCount && regPlayerId[p] != ((MpStructAcceptNewPlayer *)recvPtr)->player_id; ++p );
regPlayerId[p] = ((MpStructAcceptNewPlayer *)recvPtr)->player_id;
playerReadyFlag[p] = 0;
if( p >= regPlayerCount )
{
regPlayerCount++; // now regPlayerCount == p
err_when( p != regPlayerCount );
}
mRefreshFlag |= MGOPTION_PLAYERS;
}
break;
case MPMSG_ACQUIRE_RACE:
if( remote.is_host )
{
short cl = ((MpStructAcquireRace *)recvPtr)->race_id;
if( !cl )
{
for( cl = 1; cl <= MAX_RACE; ++cl)
{
if( raceAssigned[cl-1] == 0 )
break;
}
}
int p;
for( p = 0; p < regPlayerCount && regPlayerId[p] != from; ++p );
if( cl <= MAX_RACE && p < regPlayerCount &&
(shareRace || raceAssigned[cl-1] == 0 ) ) // more than one player can use the same race
{
// unassign current race
if( playerRace[p] > 0)
raceAssigned[playerRace[p]-1]--;
// mark race assigned
raceAssigned[cl-1]++;
playerRace[p] = cl;
// reply accept race
MpStructAcceptRace msgAcceptRace(from, cl );
mp_obj.send_stream( from, &msgAcceptRace, sizeof(msgAcceptRace) );
}
else
{
// reply refuse race
MpStructRefuseRace msgRefuseRace(from, ((MpStructAcquireRace *)recvPtr)->race_id );
mp_obj.send_stream( from, &msgRefuseRace, sizeof(msgRefuseRace) );
}
}
break;
case MPMSG_ACCEPT_RACE:
if( ((MpStructAcceptRace *)recvPtr)->request_player_id == mp_obj.my_player_id )
{
tempConfig.race_id = char(((MpStructAcceptRace *)recvPtr)->race_id);
refreshFlag |= SGOPTION_RACE;
}
break;
case MPMSG_REFUSE_RACE:
if( ((MpStructRefuseRace *)recvPtr)->request_player_id == mp_obj.my_player_id )
{
refreshFlag |= SGOPTION_RACE;
// sound effect here
}
break;
case MPMSG_ACQUIRE_COLOR:
if( remote.is_host )
{
short cl = ((MpStructAcquireColor *)recvPtr)->color_scheme_id;
if( !cl )
{
for( cl = 1; cl <= MAX_COLOR_SCHEME && colorAssigned[cl-1]; ++cl);
}
int p;
for( p = 0; p < regPlayerCount && regPlayerId[p] != from; ++p );
if( cl <= MAX_COLOR_SCHEME && !colorAssigned[cl-1] && p < regPlayerCount )
{
if( playerColor[p] > 0 )
colorAssigned[playerColor[p]-1] = 0;
// mark color assigned
colorAssigned[cl-1] = 1;
playerColor[p] = cl;
// reply accept color
MpStructAcceptColor msgAcceptColor(from, cl );
mp_obj.send_stream( from, &msgAcceptColor, sizeof(msgAcceptColor) );
}
else
{
// reply refuse color
MpStructRefuseColor msgRefuseColor(from, ((MpStructAcquireColor *)recvPtr)->color_scheme_id );
mp_obj.send_stream( from, &msgRefuseColor, sizeof(msgRefuseColor) );
}
}
break;
case MPMSG_ACCEPT_COLOR:
if( ((MpStructAcceptColor *)recvPtr)->request_player_id == mp_obj.my_player_id )
{
tempConfig.player_nation_color = char(((MpStructAcceptColor *)recvPtr)->color_scheme_id);
refreshFlag |= SGOPTION_COLOR;
}
break;
case MPMSG_REFUSE_COLOR:
if( ((MpStructRefuseColor *)recvPtr)->request_player_id == mp_obj.my_player_id )
{
refreshFlag |= SGOPTION_COLOR;
// sound effect here
}
break;
case MPMSG_PLAYER_READY:
{
for( int p = 0; p < regPlayerCount; ++p)
{
if( regPlayerId[p] == ((MpStructPlayerReady *)recvPtr)->player_id )
{
playerReadyFlag[p] = 1;
mRefreshFlag |= MGOPTION_PLAYERS;
}
}
}
break;
case MPMSG_PLAYER_UNREADY:
{
for( int p = 0; p < regPlayerCount; ++p)
{
if( regPlayerId[p] == ((MpStructPlayerUnready *)recvPtr)->player_id )
{
playerReadyFlag[p] = 0;
mRefreshFlag |= MGOPTION_PLAYERS;
}
}
}
break;
case MPMSG_SEND_CHAT_MSG:
while( messageList.size() >= 4 )
messageList.linkout(1);
messageList.linkin(recvPtr);
mRefreshFlag |= MGOPTION_IN_MESSAGE;
break;
// ###### patch begin Gilbert 22/1 ######//
case MPMSG_SEND_SYNC_TEST_LEVEL:
remote.sync_test_level = ((MpStructSyncLevel *)recvPtr)->sync_test_level;
break;
// ###### patch end Gilbert 22/1 ######//
case MPMSG_REFUSE_NEW_PLAYER:
if( ((MpStructRefuseNewPlayer *)recvPtr)->player_id == mp_obj.my_player_id )
{
box.msg("You cannot join the game because the multiplayer saved game you selected is different from those of other human players.");
return 0;
}
break;
default: // if the game is started, any other thing is received
return 0;
}
}
}
// --------- detect basic option -------- //
if( optionMode == OPTION_BASIC )
{
if( !selfReadyFlag )
{
if( raceGroup.detect() >= 0)
{
int r = tempConfig.race_id = raceGroup[raceGroup()].custom_para.value;
if( remote.is_host )
{
int p;
for( p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id ; ++p );
if( r <= MAX_RACE && p < regPlayerCount &&
(shareRace || raceAssigned[r-1] == 0 ) ) // more than one player can use the same race
{
// unassign current race
if( playerRace[p] > 0)
raceAssigned[playerRace[p]-1]--;
// mark race assigned
raceAssigned[r-1]++;
playerRace[p] = r;
tempConfig.race_id = r;
}
refreshFlag |= SGOPTION_RACE;
}
else
{
MpStructAcquireRace msgAcquire(r);
mp_obj.send_stream(hostPlayerId, &msgAcquire, sizeof( msgAcquire) );
}
//refreshFlag |= SGOPTION_RACE;
}
else if( colorGroup.detect() >= 0)
{
int r = colorGroup[colorGroup()].custom_para.value;
if( remote.is_host )
{
if( !colorAssigned[r-1] )
{
int p;
for( p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id; ++p );
if( r <= MAX_COLOR_SCHEME && !colorAssigned[r-1] && p < regPlayerCount )
{
// unmark current color
if( playerColor[p] > 0 )
colorAssigned[playerColor[p]-1] = 0;
// mark color assigned
colorAssigned[r-1] = 1;
playerColor[p] = r;
tempConfig.player_nation_color = r;
}
}
refreshFlag |= SGOPTION_COLOR;
}
else
{
MpStructAcquireColor msgAcquire(r);
mp_obj.send_stream(hostPlayerId, &msgAcquire, sizeof( msgAcquire) );
}
//refreshFlag |= SGOPTION_COLOR;
}
}
}
// -------- detect other option, only host can change ---------//
unsigned keyCode = 0;
if( remote.is_host && !selfReadyFlag)
{
int configChange = 0;
// ------- detect basic option ---------//
if( optionMode == OPTION_BASIC )
{
if( aiNationInc.detect() )
{
tempConfig.ai_nation_count++;
if( tempConfig.ai_nation_count >= MAX_NATION )
tempConfig.ai_nation_count = MAX_NATION-1;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
refreshFlag |= SGOPTION_AI_NATION | SGOPTION_DIFFICULTY;
}
else if( aiNationDec.detect() )
{
tempConfig.ai_nation_count--;
if( tempConfig.ai_nation_count < 0 )
tempConfig.ai_nation_count = 0;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
refreshFlag |= SGOPTION_AI_NATION | SGOPTION_DIFFICULTY;
}
else if( diffGroup.detect() >= 0)
{
if( diffGroup[diffGroup()].custom_para.value != OPTION_CUSTOM )
{
tempConfig.change_difficulty(diffGroup[diffGroup()].custom_para.value);
configChange = 1;
// all but SGOPTION_PAGE;
refreshFlag |= SGOPTION_ALL & ~SGOPTION_PAGE;
}
}
else if( terrainGroup.detect() >= 0)
{
tempConfig.terrain_set = terrainGroup[terrainGroup()].custom_para.value;
static short latitudeArray[3] = { 45, 70, 20 };
err_when( tempConfig.terrain_set <= 0 || tempConfig.terrain_set > 3 );
tempConfig.latitude = latitudeArray[tempConfig.terrain_set-1];
configChange = 1;
//refreshFlag |= SGOPTION_TERRAIN;
}
else if( landGroup.detect() >= 0)
{
tempConfig.land_mass = landGroup[landGroup()].custom_para.value;
configChange = 1;
//refreshFlag |= SGOPTION_LAND_MASS;
}
}
// ------- detect advanced option ---------//
else if( optionMode == OPTION_ADVANCED )
{
// ###### begin Gilbert 24/10 ######//
MpStructSeedStr oldMapStr(msgSeedStr);
if( keyCode = mapIdField.detect() )
{
if( strcmp(oldMapStr.seed_str, msgSeedStr.seed_str) )
mp_obj.send_stream( BROADCAST_PID, &msgSeedStr, sizeof(msgSeedStr) );
refreshFlag |= SGOPTION_MAP_ID;
}
else
// ###### end Gilbert 24/10 ######//
if( exploreGroup.detect() >= 0 )
{
tempConfig.explore_whole_map = exploreGroup[exploreGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_EXPLORED;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( fogGroup.detect() >= 0 )
{
tempConfig.fog_of_war = fogGroup[fogGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_FOG
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( treasureGroup.detect() >= 0 )
{
tempConfig.start_up_cash = treasureGroup[treasureGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_TREASURE;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( aiTreasureGroup.detect() >= 0 )
{
tempConfig.ai_start_up_cash = aiTreasureGroup[aiTreasureGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_AI_TREASURE;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( aiAggressiveGroup.detect() >= 0 )
{
tempConfig.ai_aggressiveness =
aiAggressiveGroup[aiAggressiveGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_AI_AGGRESSIVE;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( monsterGroup.detect() >= 0 )
{
tempConfig.monster_type = monsterGroup[monsterGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_FRYHTANS;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( randomStartUpGroup.detect() >= 0)
{
tempConfig.random_start_up = randomStartUpGroup[randomStartUpGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_RANDOM_STARTUP;
refreshFlag |= SGOPTION_DIFFICULTY;
}
}
// -------- detect advanced option ---------//
else if( optionMode == OPTION_ADVANCE2 )
{
if( rawSiteInc.detect() )
{
if( ++tempConfig.start_up_raw_site > 7 )
tempConfig.start_up_raw_site = 7;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
refreshFlag |= SGOPTION_RAW | SGOPTION_DIFFICULTY;
}
else if( rawSiteDec.detect() )
{
if( --tempConfig.start_up_raw_site < 1 )
tempConfig.start_up_raw_site = 1;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
refreshFlag |= SGOPTION_RAW | SGOPTION_DIFFICULTY;
}
else if( nearRawGroup.detect() >= 0)
{
tempConfig.start_up_has_mine_nearby = nearRawGroup[nearRawGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_NEAR_RAW;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( townStartGroup.detect() >= 0)
{
tempConfig.start_up_independent_town = townStartGroup[townStartGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// resfreshFlag |= SGOPTION_START_TOWN;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( townResistGroup.detect() >= 0)
{
tempConfig.independent_town_resistance = townResistGroup[townResistGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// resfreshFlag |= SGOPTION_TOWN_RESIST;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( townEmergeGroup.detect() >= 0)
{
tempConfig.new_independent_town_emerge = townEmergeGroup[townEmergeGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_TOWN_EMERGE;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( nationEmergeGroup.detect() >= 0)
{
tempConfig.new_nation_emerge = nationEmergeGroup[nationEmergeGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_NATION_EMERGE;
refreshFlag |= SGOPTION_DIFFICULTY;
}
else if( randomEventGroup.detect() >= 0)
{
tempConfig.random_event_frequency = randomEventGroup[randomEventGroup()].custom_para.value;
tempConfig.difficulty_level = OPTION_CUSTOM;
configChange = 1;
// refreshFlag |= SGOPTION_RANDOM_EVENT;
refreshFlag |= SGOPTION_DIFFICULTY;
}
}
// -------- detect goal option ----------//
else if( optionMode == OPTION_GOAL )
{
if( clearEnemyButton.detect() )
{
}
else if( clearMonsterButton.detect() )
{
tempConfig.goal_destroy_monster = clearMonsterButton.pushed_flag;
configChange = 1;
}
else if( enoughPeopleButton.detect() )
{
tempConfig.goal_population_flag = enoughPeopleButton.pushed_flag;
configChange = 1;
}
else if( enoughIncomeButton.detect() )
{
tempConfig.goal_economic_score_flag = enoughIncomeButton.pushed_flag;
configChange = 1;
}
// ##### begin Gilbert 24/10 #######//
else if( enoughScoreButton.detect() )
{
tempConfig.goal_total_score_flag = enoughScoreButton.pushed_flag;
configChange = 1;
}
// ##### end Gilbert 24/10 #######//
else if( timeLimitButton.detect() )
{
tempConfig.goal_year_limit_flag = timeLimitButton.pushed_flag;
configChange = 1;
}
else if( peopleInc.detect() )
{
tempConfig.goal_population += 100;
if( tempConfig.goal_population > 5000 )
tempConfig.goal_population = 5000;
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_PEOPLE;
}
else if( peopleDec.detect() )
{
tempConfig.goal_population -= 100;
if( tempConfig.goal_population < 100 )
tempConfig.goal_population = 100;
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_PEOPLE;
}
// ###### begin Gilbert 24/10 #######//
else if( incomeInc.detect() )
{
tempConfig.goal_economic_score += 100;
if( tempConfig.goal_economic_score > 5000 )
{
tempConfig.goal_economic_score = 5000;
}
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_INCOME;
}
else if( incomeDec.detect() )
{
tempConfig.goal_economic_score -= 100;
if( tempConfig.goal_economic_score < 100 )
{
tempConfig.goal_economic_score = 100;
}
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_INCOME;
}
else if( scoreInc.detect() )
{
if( tempConfig.goal_total_score >= 2000 )
tempConfig.goal_total_score += 500;
else
tempConfig.goal_total_score += 100;
if( tempConfig.goal_total_score > 10000 )
tempConfig.goal_total_score = 10000;
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_SCORE;
}
else if( scoreDec.detect() )
{
if( tempConfig.goal_total_score > 2000 )
tempConfig.goal_total_score -= 500;
else
tempConfig.goal_total_score -= 100;
if( tempConfig.goal_total_score < 100 )
tempConfig.goal_total_score = 100;
configChange = 1;
refreshFlag |= SGOPTION_ENOUGH_SCORE;
}
// ###### end Gilbert 24/10 #######//
else if( yearInc.detect() )
{
if( tempConfig.goal_year_limit >= 20 )
tempConfig.goal_year_limit += 5;
else
tempConfig.goal_year_limit++;
if( tempConfig.goal_year_limit > 100 )
{
tempConfig.goal_year_limit = 100;
}
configChange = 1;
refreshFlag |= SGOPTION_TIME_LIMIT;
}
else if( yearDec.detect() )
{
if( tempConfig.goal_year_limit > 20 )
tempConfig.goal_year_limit -= 5;
else
tempConfig.goal_year_limit--;
if( tempConfig.goal_year_limit < 1 )
{
tempConfig.goal_year_limit = 1;
}
configChange = 1;
refreshFlag |= SGOPTION_TIME_LIMIT;
}
}
if( configChange )
{
MpStructConfig msgConfig(tempConfig);
mp_obj.send_stream( BROADCAST_PID, &msgConfig, sizeof(msgConfig) );
}
}
// --------- detect switch option button ------//
if( mouse.single_click(96, offsetY+12, 218, offsetY+54) )
{
if( optionMode != OPTION_BASIC )
{
optionMode = OPTION_BASIC;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(236, offsetY+12, 363, offsetY+54) )
{
if( optionMode != OPTION_ADVANCED )
{
optionMode = OPTION_ADVANCED;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(380, offsetY+12, 506, offsetY+54) )
{
if( optionMode != OPTION_ADVANCE2 )
{
optionMode = OPTION_ADVANCE2;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(523, offsetY+12, 649, offsetY+54) )
{
if( optionMode != OPTION_GOAL )
{
optionMode = OPTION_GOAL;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
// --------- detect ready button button --------//
if( readyButton.detect() )
{
mRefreshFlag |= MGOPTION_PLAYERS;
for(p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id; ++p);
if( p < regPlayerCount )
{
if( !selfReadyFlag )
{
playerReadyFlag[p] = selfReadyFlag = 1;
MpStructPlayerReady msgReady(mp_obj.my_player_id);
mp_obj.send_stream(BROADCAST_PID, &msgReady, sizeof(msgReady));
}
else
{
// else un-ready this player
playerReadyFlag[p] = selfReadyFlag = 0;
MpStructPlayerUnready msgUnready(mp_obj.my_player_id);
mp_obj.send_stream(BROADCAST_PID, &msgUnready, sizeof(msgUnready));
}
}
}
if( remote.is_host && startButton.detect() && regPlayerCount >= 2 )
{
// see if all player is ready
short sumBalance = 0;
int q;
for( q = 0; q < regPlayerCount && playerReadyFlag[q]; ++q)
{
err_when( playerBalance[q] == 0 );
sumBalance += playerBalance[q];
}
if( q >= regPlayerCount ) // not all playerReadyFlag[p] = 1;
{
#ifdef DEBUG
sumBalance = 0;
#endif
#ifdef BETA
sumBalance = 0;
#endif
if( sumBalance >= 0 )
{
// MpStructBase msgStart(MPMSG_START_GAME);
// mp_obj.send_stream(BROADCAST_PID, &msgStart, sizeof(msgStart));
retFlag = 1;
break; // break while(1)
}
else
{
// too many non-CD version
box.msg("There are not enough Seven Kingdoms CDROMs to start the game. Each CDROM supports "PLAYER_RATIO_STRING" players.");
}
}
}
else if( returnButton.detect() )
{
if( remote.is_host )
{
MpStructBase msgAbort(MPMSG_ABORT_GAME);
mp_obj.send_stream(BROADCAST_PID, &msgAbort, sizeof(msgAbort) );
}
retFlag = 0;
break; // break while(1)
}
else if( !keyCode && (keyCode = messageField.detect()) != 0) // keyCode may be non-zero if after mapIdField.detect()
{
mRefreshFlag |= MGOPTION_OUT_MESSAGE;
if(keyCode == KEY_RETURN && strlen(typingMsg.content) > 0)
{
// send message
mp_obj.send_stream(BROADCAST_PID, &typingMsg, sizeof(typingMsg) );
// clear the string
messageField.clear();
}
else if( keyCode == KEY_ESC )
{
messageField.clear();
}
}
mp_obj.after_send();
// ####### begin Gilbert 24/10 #######//
vga_front.unlock_buf();
// ####### end Gilbert 24/10 #######//
}
// ###### begin Gilbert 24/10 #######//
if( !vga_front.buf_locked )
vga_front.lock_buf();
// ###### end Gilbert 24/10 #######//
mp_obj.after_send();
// ---------- final setup to start multiplayer game --------//
if( retFlag )
{
retFlag = 0;
if( remote.is_host )
mp_obj.disable_join_session();
// mp_obj.poll_players();
nation_array.init();
nation_array.zap();
int trial;
unsigned long startTime;
int playerCount = 0;
if( remote.is_host )
{
VLenQueue setupString;
// ------- put start game string -------//
{
MpStructBase msgStart(MPMSG_START_GAME);
memcpy( setupString.reserve(sizeof(msgStart)), &msgStart, sizeof(msgStart) );
}
// -------- put random seed -------- //
do
{
info.init_random_seed( atol(msgSeedStr.seed_str) );
} while (m.get_random_seed() == 0L);
{
MpStructSeed msgSeed(m.get_random_seed());
memcpy( setupString.reserve(sizeof(msgSeed)), &msgSeed, sizeof(msgSeed) );
}
// -------- send config ------------//
{
MpStructConfig msgConfig(tempConfig);
memcpy( setupString.reserve(sizeof(msgConfig)), &msgConfig, sizeof(msgConfig) );
}
// BUGHERE : terrain_set 2 is not available
#ifndef AMPLUS
if( tempConfig.terrain_set == 2)
tempConfig.terrain_set = 1;
#endif
config = tempConfig; // nation_array.new_nation reads setting from config
// -------- setup nation now ------------ //
info.init();
playerCount = 0;
for( p = 0; p < regPlayerCount; ++p )
{
// ensure it is a valid player
PID_TYPE playerId = regPlayerId[p];
PlayerDesc *player = mp_obj.search_player(playerId);
if( !playerId || !player || !player->connecting )
continue;
nationPara[playerCount].init(playerCount+1, playerId, playerColor[p], playerRace[p], player->friendly_name_str());
((MpStructNation *)setupString.reserve(sizeof(MpStructNation)))->init(
playerCount+1, playerId, playerColor[p], playerRace[p], player->friendly_name_str());
playerCount++;
}
*mpPlayerCount = playerCount;
config.difficulty_rating = config.multi_player_difficulty(playerCount-1);
// ---- force set to the lowest frame delay -------//
#ifdef AMPLUS
remote.set_process_frame_delay(FORCE_MAX_FRAME_DELAY);
{
MpStructProcessFrameDelay msgFrameDelay(remote.get_process_frame_delay());
memcpy( setupString.reserve(sizeof(msgFrameDelay)), &msgFrameDelay, sizeof(msgFrameDelay));
}
#endif
// -------- send sync test level ----------//
{
MpStructSyncLevel msgSyncTest(remote.sync_test_level);
memcpy( setupString.reserve(sizeof(msgSyncTest)), &msgSyncTest, sizeof(msgSyncTest));
}
mp_obj.send_stream(BROADCAST_PID, setupString.queue_buf, setupString.length() );
mp_obj.after_send();
}
else
{
// use the message recving MPMSG_START_GAME
err_when( !recvPtr);
DWORD offset = 0;
int recvStartMsg = 0;
int recvSeed = 0;
int recvConfig = 0;
int ownPlayerFound = 0;
playerCount = 0;
char *oriRecvPtr = recvPtr;
int recvSetFrameDelay = 0;
int recvSyncTestLevel = 0;
// process the string received
while( offset < recvLen )
{
DWORD oldOffset = offset;
recvPtr = oriRecvPtr + offset;
switch( ((MpStructBase *)(recvPtr))->msg_id )
{
case MPMSG_START_GAME:
recvStartMsg = 1;
offset += sizeof( MpStructBase );
break;
case MPMSG_RANDOM_SEED:
err_when( ((MpStructSeed *) recvPtr)->seed == 0L);
info.init_random_seed( ((MpStructSeed *) recvPtr)->seed );
offset += sizeof( MpStructSeed );
++recvSeed;
break;
case MPMSG_SEND_CONFIG:
tempConfig.change_game_setting( ((MpStructConfig *) recvPtr)->game_config );
offset += sizeof( MpStructConfig );
++recvConfig;
#ifndef AMPLUS
if( tempConfig.terrain_set == 2)
tempConfig.terrain_set = 1;
#endif
config = tempConfig; // nation_array.new_nation reads setting from config
break;
case MPMSG_DECLARE_NATION:
{
if( playerCount == 0 )
info.init(); // info.init for the first time
MpStructNation *msgNation = (MpStructNation *)recvPtr;
nationPara[playerCount].init( msgNation->nation_recno,
msgNation->dp_player_id, msgNation->color_scheme,
msgNation->race_id, msgNation->player_name);
if( msgNation->dp_player_id == mp_obj.my_player_id )
ownPlayerFound++;
*mpPlayerCount = ++playerCount;
offset += sizeof( MpStructNation );
config.difficulty_rating = config.multi_player_difficulty(playerCount-1);
}
break;
case MPMSG_SET_PROCESS_FRAME_DELAY:
remote.set_process_frame_delay(((MpStructProcessFrameDelay *)recvPtr)->common_process_frame_delay);
++recvSetFrameDelay;
offset += sizeof( MpStructProcessFrameDelay );
break;
case MPMSG_SEND_SYNC_TEST_LEVEL:
remote.sync_test_level = ((MpStructSyncLevel *)recvPtr)->sync_test_level;
++recvSyncTestLevel;
offset += sizeof( MpStructSyncLevel );
break;
} // end switch
if( !recvStartMsg || offset <= oldOffset )
{
err_here();
box.msg( "Connection string from host is corrupted" );
return 0;
}
} // end while
if( !recvSeed )
{
box.msg( "Cannot get random seeds from the host." );
return 0;
}
err_when( recvSeed > 1 );
if( !recvConfig )
{
box.msg( "Cannot get game configuration info from the host." );
return 0;
}
err_when( recvConfig > 1 );
if( playerCount == 0 )
{
box.msg( "Cannot get kingdom information from the host." );
return 0;
}
err_when( playerCount > MAX_NATION );
if( !ownPlayerFound )
{
box.msg( "The host cannot recognize your machine." );
return 0;
}
err_when( ownPlayerFound > 1 );
if( !recvSetFrameDelay || !recvSyncTestLevel )
{
box.msg("Cannot receive important information from the host");
return 0;
}
err_when( recvSetFrameDelay > 1 );
err_when( recvSyncTestLevel > 1 );
}
if( remote.sync_test_level == 0)
{
remote.set_alternating_send(playerCount > 4 ? 4 : playerCount); // automatic setting
}
{
// ------- broadcast end setting string ------- //
MpStructBase mpEndSetting(MPMSG_END_SETTING);
mp_obj.send_stream( BROADCAST_PID, &mpEndSetting, sizeof(mpEndSetting) );
mp_obj.after_send();
// ------ wait for MPMSG_END_SETTING ----------//
// ---- to filter other all message until MP_MSG_END_SETTING ---//
trial = 5000;
startTime = m.get_time();
int recvEndSetting = 0;
while( --trial > 0 || m.get_time() - startTime < 10000 )
{
if( recvEndSetting >= playerCount-1)
break;
mp_obj.before_receive();
recvPtr = mp_obj.receive( &from, &to, &recvLen);
mp_obj.after_send();
if( recvPtr )
{
trial = max(trial, 1000);
startTime = m.get_time();
if( ((MpStructBase *)recvPtr)->msg_id == MPMSG_END_SETTING )
{
recvEndSetting++;
}
}
}
if( recvEndSetting < playerCount-1 )
{
box.msg("Some player(s) encountered errors when initializing the game.");
// but continue
}
}
retFlag = 1;
} // end if(retFlag)
return retFlag;
}
#ifdef Y_SHIFT
#error
#endif
#undef Y_SHIFT_FLAG
//-------- End of function Game::mp_select_option -----------//
//-------- Begin of function Game::mp_select_load_option -----------//
// return 0 = cancel, 1 = ok
int Game::mp_select_load_option(char *fileName)
{
const int offsetY = 212;
char optionMode = OPTION_BASIC;
char menuTitleBitmap[] = "TOP-LMPG";
Config &tempConfig = config;
PID_TYPE from, to;
DWORD recvLen;
int sysMsgCount;
char *recvPtr;
char raceAssigned[MAX_RACE]; // master copy belongs to host's
char colorAssigned[MAX_COLOR_SCHEME]; // master copy belongs to host's
//static short raceX[MAX_RACE] = {390, 313, 236, 467, 390, 236, 313};
//static short raceY[MAX_RACE] = {276, 276, 276, 276, 243, 243, 243};
//const raceWidth = 77;
//const raceHeight = 33;
//static short colorX[MAX_COLOR_SCHEME] = {545, 581, 581, 617, 617, 545, 653};
//static short colorY[MAX_COLOR_SCHEME] = {243, 276, 243, 276, 243, 276, 276};
//const colorWidth = 36;
//const colorHeight = 33;
static short tickX[MAX_NATION] = { 103, 254, 405, 556, 103, 254, 405 };
static short tickY[MAX_NATION] = { 53, 53, 53, 53, 73, 73, 73 };
const int nameOffsetX = 23;
const int nameOffsetY = 3;
DynArray messageList(sizeof(MpStructChatMsg));
MpStructChatMsg typingMsg(tempConfig.player_name, NULL);
memset( raceAssigned, 0, sizeof(raceAssigned) );
memset( colorAssigned, 0, sizeof(colorAssigned) );
PID_TYPE hostPlayerId = 0;
PID_TYPE regPlayerId[MAX_NATION];
memset( regPlayerId, 0, sizeof(regPlayerId) );
char playerReadyFlag[MAX_NATION];
memset( playerReadyFlag, 0, sizeof(playerReadyFlag) );
short playerRace[MAX_NATION]; // host only
memset( playerRace, 0, sizeof(playerRace) );
short playerColor[MAX_NATION]; // host only
memset( playerColor, 0, sizeof(playerColor) );
short playerBalance[MAX_NATION];
memset( playerBalance, 0, sizeof(playerBalance) );
int regPlayerCount = 0;
int selfReadyFlag = 0;
int maxPlayer;
int shareRace = 1; // host only, 0= exclusive race of each player
mp_obj.poll_players();
int p;
for( p = 1; p <= MAX_NATION && mp_obj.get_player(p); ++p )
{
// host only identify himself
if( !remote.is_host || mp_obj.get_player(p)->pid() == mp_obj.my_player_id )
{
regPlayerId[regPlayerCount] = mp_obj.get_player(p)->pid();
playerReadyFlag[regPlayerCount] = 0;
playerColor[regPlayerCount] = 0;
playerRace[regPlayerCount] = 0;
playerBalance[regPlayerCount] = 0;
++regPlayerCount;
}
}
err_when( tempConfig.race_id != (~nation_array)->race_id );
err_when( tempConfig.player_nation_color != (~nation_array)->color_scheme_id );
int i;
long refreshFlag = SGOPTION_ALL;
long mRefreshFlag = MGOPTION_ALL;
int retFlag = 0;
if( remote.is_host )
{
colorAssigned[tempConfig.player_nation_color-1] = 1;
for( p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id; ++p );
if( p < regPlayerCount )
{
playerColor[p] = tempConfig.player_nation_color;
playerBalance[p] = sys.cdrom_drive ? PLAYER_RATIO_CDROM : PLAYER_RATIO_NOCD;
}
// initialize other colorAssigned, only free for those of the remote players
maxPlayer = 1; // host
for( p = 1; p <= nation_array.size(); ++p )
{
if( !nation_array.is_deleted(p) && nation_array[p]->is_remote() )
{
colorAssigned[nation_array[p]->color_scheme_id-1] = 0;
maxPlayer++;
}
}
err_when( maxPlayer > MAX_NATION );
}
else
{
memset( colorAssigned, 0, sizeof(colorAssigned) ); // assume all color are unassigned
MpStructLoadGameNewPlayer msgNewPlayer( mp_obj.my_player_id, ~nation_array, sys.frame_count,
m.get_random_seed(), sys.cdrom_drive ? PLAYER_RATIO_CDROM : PLAYER_RATIO_NOCD );
mp_obj.send_stream(BROADCAST_PID, &msgNewPlayer, sizeof(msgNewPlayer) );
}
// --------- initialize race button group ---------- //
ButtonCustomGroup raceGroup(MAX_RACE);
for( i = 0; i < MAX_RACE; ++i )
{
#if(MAX_RACE == 10)
raceGroup[i].create(220+(i%5)*BASIC_OPTION_X_SPACE, (i/5)*BASIC_OPTION_HEIGHT+offsetY+70,
220+(i%5+1)*BASIC_OPTION_X_SPACE-1, (i/5+1)*BASIC_OPTION_HEIGHT+offsetY+70-1,
disp_virtual_button, ButtonCustomPara(&raceGroup, race_table[i]), 0, 0);
#define Y_SHIFT_FLAG 1
#else
raceGroup[i].create(118+i*BASIC_OPTION_X_SPACE, offsetY+93,
118+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+93+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&raceGroup, race_table[i]), 0, 0);
#define Y_SHIFT_FLAG 0
#endif
}
// --------- initialize color button group ---------- //
ButtonCustomGroup colorGroup(MAX_COLOR_SCHEME);
for( i = 0; i < MAX_COLOR_SCHEME; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
colorGroup[i].create(195+i*COLOR_OPTION_X_SPACE, offsetY+139+Y_SHIFT,
195+(i+1)*COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&colorGroup, i+1), 0, 0);
#undef Y_SHIFT
}
// ---------- initialize ai_nation_count buttons --------//
ButtonCustom aiNationInc, aiNationDec;
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
aiNationInc.create(595, offsetY+139+Y_SHIFT,
595+COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, +1) );
aiNationDec.create(630, offsetY+139+Y_SHIFT,
630+COLOR_OPTION_X_SPACE-1, offsetY+139+Y_SHIFT+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, -1) );
#undef Y_SHIFT
}
// ---------- initialize difficulty_level button group -------//
ButtonCustomGroup diffGroup(6);
for( i = 0; i < 6; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
diffGroup[i].create( 205+i*BASIC_OPTION_X_SPACE, offsetY+184+Y_SHIFT,
205+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+184+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&diffGroup, i), 0, 0);
#undef Y_SHIFT
}
// --------- initialize terrain_set button group -------//
// ####### begin Gilbert 25/10 #######//
ButtonCustomGroup terrainGroup(3);
for( i = 0; i < 3; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
#ifdef AMPLUS
terrainGroup[i].create(166+i*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
166+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&terrainGroup, i+1), 0, 0);
#else
int k = i;
switch(i)
{
case 1: k = 2; break;
case 2: k = 1; break;
}
terrainGroup[i].create(205+k*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
205+(k+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&terrainGroup, i+1), 0, 0);
if( i == 1 )
terrainGroup[i].enable_flag = 0;
#endif
#undef Y_SHIFT
}
// ####### end Gilbert 25/10 #######//
// --------- initialize land_mass button group -------//
ButtonCustomGroup landGroup(3);
for( i = 0; i < 3; ++i )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 16
#else
#define Y_SHIFT 0
#endif
landGroup[i].create(439+i*BASIC_OPTION_X_SPACE, offsetY+248+Y_SHIFT,
439+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+248+Y_SHIFT+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&landGroup, i+1), 0, 0);
#undef Y_SHIFT
}
GetA messageField;
messageField.init( 190, 116, 700, typingMsg.content,
MpStructChatMsg::MSG_LENGTH, &font_san, 0, 1);
// ###### begin Gilbert 25/10 #######//
// --------- initialize info.random_seed field ----------//
MpStructSeedStr msgSeedStr(info.random_seed);
GetA mapIdField;
#if(defined(SPANISH))
#define MAPID_X1 588
#elif(defined(FRENCH))
#define MAPID_X1 578
#else
#define MAPID_X1 564
#endif
mapIdField.init( MAPID_X1, offsetY+83, 700, msgSeedStr.seed_str, msgSeedStr.RANDOM_SEED_MAX_LEN, &font_san, 0, 1);
#undef MAPID_X1
// ###### end Gilbert 25/10 #######//
// --------- initialize explore_whole_map button group -------//
ButtonCustomGroup exploreGroup(2);
for( i = 0; i < 2; ++i )
{
exploreGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+74,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+74+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&exploreGroup, 1-i), 0, 0);
}
// --------- initialize fog_of_war button group -------//
ButtonCustomGroup fogGroup(2);
for( i = 0; i < 2; ++i )
{
fogGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+106,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+106+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&fogGroup, 1-i), 0, 0);
}
// --------- initialize start_up_cash/start_up_food button group -------//
ButtonCustomGroup treasureGroup(4);
for( i = 0; i < 4; ++i )
{
treasureGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+138,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+138+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&treasureGroup, i+1), 0, 0);
}
// --------- initialize ai_start_up_cash/food button group -------//
ButtonCustomGroup aiTreasureGroup(4);
for( i = 0; i < 4; ++i )
{
aiTreasureGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+170,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+170+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&aiTreasureGroup, i+1), 0, 0);
}
// --------- initialize ai_aggressiveness -------//
ButtonCustomGroup aiAggressiveGroup(4);
for( i = 0; i < 4; ++i )
{
aiAggressiveGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+202,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+202+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&aiAggressiveGroup, i+1), 0, 0);
}
// --------- initialize monster_type -------//
ButtonCustomGroup monsterGroup(3);
for( i = 0; i < 3; ++i )
{
monsterGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+234,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+234+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&monsterGroup, i), 0, 0);
}
// --------- initialize random startup button group -------//
ButtonCustomGroup randomStartUpGroup(2);
for( i = 0; i < 2; ++i )
{
randomStartUpGroup[i].create(335+i*BASIC_OPTION_X_SPACE, offsetY+266,
335+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+266+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&randomStartUpGroup, 1-i), 0, 0);
}
// -------- initialize start_up_raw_site buttons --------- //
ButtonCustom rawSiteInc, rawSiteDec;
rawSiteInc.create( 358, offsetY+72,
358+COLOR_OPTION_X_SPACE-1, offsetY+72+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL,0));
rawSiteDec.create( 393, offsetY+72,
393+COLOR_OPTION_X_SPACE-1, offsetY+72+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL,0));
// --------- initialize start_up_has_mine_nearby button group --------//
ButtonCustomGroup nearRawGroup(2);
for( i = 0; i < 2; ++i )
{
nearRawGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+104,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+104+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&nearRawGroup, 1-i), 0, 0);
}
// --------- initialize start_up_independent_town button group --------//
static short startTownArray[3] = { 7, 15, 30 };
ButtonCustomGroup townStartGroup(3);
for( i = 0; i < 3; ++i )
{
townStartGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+136,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+136+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townStartGroup, startTownArray[i]), 0, 0);
}
// --------- initialize independent_town_resistance button group --------//
ButtonCustomGroup townResistGroup(3);
for( i = 0; i < 3; ++i )
{
townResistGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+168,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+168+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townResistGroup, i+1), 0, 0);
}
// --------- initialize new_independent_town_emerge button group --------//
ButtonCustomGroup townEmergeGroup(2);
for( i = 0; i < 2; ++i )
{
townEmergeGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+200,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+200+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&townEmergeGroup, 1-i), 0, 0);
}
// --------- initialize new_nation_emerge button group --------//
ButtonCustomGroup nationEmergeGroup(2);
for( i = 0; i < 2; ++i )
{
nationEmergeGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+232,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+232+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&nationEmergeGroup, 1-i), 0, 0);
}
// --------- initialize random_event_frequency button group --------//
ButtonCustomGroup randomEventGroup(4);
for( i = 0; i < 4; ++i )
{
randomEventGroup[i].create(322+i*BASIC_OPTION_X_SPACE, offsetY+264,
322+(i+1)*BASIC_OPTION_X_SPACE-1, offsetY+264+BASIC_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(&randomEventGroup, i), 0, 0);
}
// ---------- initialize goal buttons ----------//
// ##### begin Gilbert 25/10 #######//
ButtonCustom clearEnemyButton, clearMonsterButton, enoughPeopleButton, enoughIncomeButton, enoughScoreButton, timeLimitButton;
ButtonCustom peopleInc, peopleDec, incomeInc, incomeDec, scoreInc, scoreDec, yearInc, yearDec;
clearEnemyButton.create( 209, offsetY+109, 209+19, offsetY+109+19, // -3
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0, 1);
clearEnemyButton.enable_flag = 0;;
clearMonsterButton.create( 209, offsetY+142, 209+19, offsetY+142+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_destroy_monster);
enoughPeopleButton.create( 209, offsetY+175, 209+19, offsetY+175+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_population_flag);
enoughIncomeButton.create( 209, offsetY+208, 209+19, offsetY+208+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_economic_score_flag);
enoughScoreButton.create( 209, offsetY+241, 209+19, offsetY+241+19,
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_total_score_flag);
timeLimitButton.create( 209, offsetY+273, 209+19, offsetY+273+19, // +29
disp_virtual_tick, ButtonCustomPara(NULL, 0), 0,
tempConfig.goal_year_limit_flag);
peopleInc.create( 524, offsetY+170,
524+COLOR_OPTION_X_SPACE-1, offsetY+170+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
peopleDec.create( 559, offsetY+170,
559+COLOR_OPTION_X_SPACE-1, offsetY+170+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
incomeInc.create( 524, offsetY+202,
524+COLOR_OPTION_X_SPACE-1, offsetY+202+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
incomeDec.create( 559, offsetY+202,
559+COLOR_OPTION_X_SPACE-1, offsetY+202+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
scoreInc.create( 524, offsetY+234,
524+COLOR_OPTION_X_SPACE-1, offsetY+234+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
scoreDec.create( 559, offsetY+234,
559+COLOR_OPTION_X_SPACE-1, offsetY+234+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
yearInc.create( 524, offsetY+266,
524+COLOR_OPTION_X_SPACE-1, offsetY+266+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
yearDec.create( 559, offsetY+266,
559+COLOR_OPTION_X_SPACE-1, offsetY+266+COLOR_OPTION_HEIGHT-1,
disp_virtual_button, ButtonCustomPara(NULL, 0) );
// ##### end Gilbert 25/10 #######//
Button3D startButton, readyButton, returnButton;
readyButton.create(120, 538, "READY-U", "READY-D", 1, 0);
startButton.create(320, 538, "START-U", "START-D", 1, 0);
returnButton.create(520, 538, "CANCEL-U", "CANCEL-D", 1, 0);
// ###### begin Gilbert 24/10 #######//
vga_front.unlock_buf();
// ###### end Gilbert 24/10 #######//
while(1)
{
// ####### begin Gilbert 23/10 #######//
MSG msg;
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage( &msg, NULL, 0, 0))
{
sys.signal_exit_flag = 1;
// BUGHERE : vga_front is unlocked
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
else if( sys.paused_flag || !sys.active_flag )
{
WaitMessage();
continue;
}
if( sys.need_redraw_flag )
{
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
sys.need_redraw_flag = 0;
}
vga_front.lock_buf();
// ####### begin Gilbert 24/10 ########//
sys.yield();
mouse.get_event();
// -------- display ----------//
if( refreshFlag || mRefreshFlag )
{
// ------- display basic option ---------//
if( optionMode == OPTION_BASIC )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-BSC");
#if(MAX_RACE == 10)
// protection : image_menu.put_to_buf( &vga_back, "MPG-BSC");
// ensure the user has the release version (I_MENU.RES)
// image_menu2.put_to_buf( &vga_back, "MPG-BSC") get the real one
image_menu2.put_to_buf( &vga_back, "MPG-BSC");
#endif
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_RACE )
raceGroup.paint( reverse_race_table[tempConfig.race_id-1] );
if( refreshFlag & SGOPTION_COLOR )
colorGroup.paint( tempConfig.player_nation_color-1 );
if( refreshFlag & SGOPTION_AI_NATION )
{
#if(Y_SHIFT_FLAG)
#define Y_SHIFT 13
#else
#define Y_SHIFT 0
#endif
font_san.center_put(564, offsetY+144+Y_SHIFT, 564+25, offsetY+144+Y_SHIFT+21,
m.format(tempConfig.ai_nation_count), 1);
aiNationInc.paint();
aiNationDec.paint();
#undef Y_SHIFT
}
if( refreshFlag & SGOPTION_DIFFICULTY )
diffGroup.paint(tempConfig.difficulty_level);
if( refreshFlag & SGOPTION_TERRAIN )
terrainGroup.paint(tempConfig.terrain_set-1);
if( refreshFlag & SGOPTION_LAND_MASS )
landGroup.paint(tempConfig.land_mass-1);
}
// ------- display advanced option ---------//
if( optionMode == OPTION_ADVANCED )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-O1");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
// ###### begin Gilbert 24/10 #######//
if( refreshFlag & SGOPTION_MAP_ID )
mapIdField.paint();
// ###### end Gilbert 24/10 #######//
if( refreshFlag & SGOPTION_EXPLORED )
exploreGroup.paint(1-tempConfig.explore_whole_map);
if( refreshFlag & SGOPTION_FOG )
fogGroup.paint(1-tempConfig.fog_of_war);
if( refreshFlag & SGOPTION_TREASURE )
treasureGroup.paint( tempConfig.start_up_cash-1 );
if( refreshFlag & SGOPTION_AI_TREASURE )
aiTreasureGroup.paint( tempConfig.ai_start_up_cash-1 );
if( refreshFlag & SGOPTION_AI_AGGRESSIVE )
aiAggressiveGroup.paint(tempConfig.ai_aggressiveness-1);
if( refreshFlag & SGOPTION_FRYHTANS )
monsterGroup.paint(tempConfig.monster_type);
if( refreshFlag & SGOPTION_RANDOM_STARTUP )
randomStartUpGroup.paint(1-tempConfig.random_start_up);
}
// ------- display advanced option ---------//
if( optionMode == OPTION_ADVANCE2 )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-O2");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_RAW )
{
font_san.center_put(327, offsetY+77, 327+25, offsetY+77+21,
m.format(tempConfig.start_up_raw_site), 1);
rawSiteInc.paint();
rawSiteDec.paint();
}
if( refreshFlag & SGOPTION_NEAR_RAW )
nearRawGroup.paint(1-tempConfig.start_up_has_mine_nearby);
if( refreshFlag & SGOPTION_START_TOWN )
townStartGroup.paint(
tempConfig.start_up_independent_town >= 30 ? 2 :
tempConfig.start_up_independent_town <= 7 ? 0 :
1
);
if( refreshFlag & SGOPTION_TOWN_STRENGTH )
townResistGroup.paint(tempConfig.independent_town_resistance-1);
if( refreshFlag & SGOPTION_TOWN_EMERGE )
townEmergeGroup.paint(1-tempConfig.new_independent_town_emerge);
if( refreshFlag & SGOPTION_KINGDOM_EMERGE )
nationEmergeGroup.paint(1-tempConfig.new_nation_emerge);
if( refreshFlag & SGOPTION_RANDOM_EVENT )
randomEventGroup.paint(tempConfig.random_event_frequency);
}
// ------- display goal option ---------//
if( optionMode == OPTION_GOAL )
{
if( refreshFlag & SGOPTION_PAGE )
{
image_menu.put_to_buf( &vga_back, "MPG-GOAL");
image_menu.put_back( 234, 15, menuTitleBitmap);
vga.blt_buf(0,0,VGA_WIDTH-1,VGA_HEIGHT-1,0);
}
if( refreshFlag & SGOPTION_CLEAR_ENEMY )
clearEnemyButton.paint();
if( refreshFlag & SGOPTION_CLEAR_MONSTER )
clearMonsterButton.paint(tempConfig.goal_destroy_monster);
// ####### begin Gilbert 25/10 ########//
if( refreshFlag & SGOPTION_ENOUGH_PEOPLE )
{
enoughPeopleButton.paint(tempConfig.goal_population_flag);
font_san.center_put( 446, offsetY+176, 446+67, offsetY+176+21,
m.format(tempConfig.goal_population), 1);
peopleInc.paint();
peopleDec.paint();
}
if( refreshFlag & SGOPTION_ENOUGH_INCOME )
{
enoughIncomeButton.paint(tempConfig.goal_economic_score_flag);
font_san.center_put( 446, offsetY+207, 446+67, offsetY+207+21,
m.format(tempConfig.goal_economic_score), 1);
incomeInc.paint();
incomeDec.paint();
}
if( refreshFlag & SGOPTION_ENOUGH_SCORE )
{
enoughScoreButton.paint(tempConfig.goal_total_score_flag);
font_san.center_put( 446, offsetY+239, 446+67, offsetY+239+21,
m.format(tempConfig.goal_total_score), 1);
scoreInc.paint();
scoreDec.paint();
}
if( refreshFlag & SGOPTION_TIME_LIMIT )
{
timeLimitButton.paint(tempConfig.goal_year_limit_flag);
font_san.center_put( 446, offsetY+271, 446+33, offsetY+271+21,
m.format(tempConfig.goal_year_limit), 1);
yearInc.paint();
yearDec.paint();
}
// ####### end Gilbert 25/10 ########//
}
// -------- refresh players in the session --------//
if( mRefreshFlag & MGOPTION_PLAYERS )
{
vga.blt_buf( 96, 46, 702, 100, 0 );
for( p = 0; p < regPlayerCount; ++p)
{
if( playerReadyFlag[p] )
{
image_menu.put_front( tickX[p]+3, tickY[p]+3, "NMPG-RCH" );
}
PlayerDesc *dispPlayer = mp_obj.search_player(regPlayerId[p]);
font_san.put( tickX[p]+nameOffsetX, tickY[p]+nameOffsetY, dispPlayer?dispPlayer->friendly_name_str():(char*)"?anonymous?" );
}
}
// ------------ display chat message --------//
if( mRefreshFlag & MGOPTION_OUT_MESSAGE )
{
messageField.paint();
}
// ------------- display incoming chat message --------//
if( mRefreshFlag & MGOPTION_IN_MESSAGE )
{
vga.blt_buf( 101, 135, 700, 202, 0 );
for( p = 1; p <= 4 && p <= messageList.size() ; ++p)
{
int ny = 136+(p-1)*16;
int nx = font_san.put( 102, ny, ((MpStructChatMsg *)messageList.get(p))->sender );
nx = font_san.put( nx, ny, " : ");
nx = font_san.put( nx, ny, ((MpStructChatMsg *)messageList.get(p))->content, 0, 700);
}
}
// ------- display difficulty -------//
if( (refreshFlag & SGOPTION_DIFFICULTY) || (mRefreshFlag & MGOPTION_PLAYERS) )
{
font_san.center_put( 718, offsetY+84, 774, offsetY+108,
m.format(tempConfig.difficulty_rating), 1 );
}
// -------- repaint button -------//
if( refreshFlag & SGOPTION_PAGE )
{
if( remote.is_host )
startButton.paint();
readyButton.paint();
returnButton.paint();
}
refreshFlag = 0;
mRefreshFlag = 0;
}
sys.blt_virtual_buf();
if( config.music_flag )
{
if( !music.is_playing() )
music.play(1, sys.cdrom_drive ? MUSIC_CD_THEN_WAV : 0 );
}
else
music.stop();
// --------- detect remote message -------//
mp_obj.before_receive();
recvPtr = mp_obj.receive(&from, &to, &recvLen, &sysMsgCount);
mp_obj.after_send();
if( sysMsgCount )
{
// see any player disconnect
for(int q = 0; q < regPlayerCount; ++q)
{
if( !mp_obj.is_player_connecting(regPlayerId[q]) )
{
mRefreshFlag |= MGOPTION_PLAYERS;
memmove( regPlayerId+q, regPlayerId+q+1, (MAX_NATION-1-q)*sizeof(regPlayerId[0]) );
regPlayerId[MAX_NATION-1] = 0;
memmove( playerReadyFlag+q, playerReadyFlag+q+1, (MAX_NATION-1-q)*sizeof(playerReadyFlag[0]) );
playerReadyFlag[MAX_NATION-1] = 0;
short freeColor = playerColor[q];
memmove( playerColor+q, playerColor+q+1, (MAX_NATION-1-q)*sizeof(playerColor[0]) );
playerColor[MAX_NATION-1] = 0;
if(freeColor > 0 && freeColor <= MAX_COLOR_SCHEME)
colorAssigned[freeColor-1] = 0;
short freeRace = playerRace[q];
memmove( playerRace+q, playerRace+q+1, (MAX_NATION-1-q)*sizeof(playerRace[0]) );
playerRace[MAX_NATION-1] = 0;
if(freeRace > 0 && freeRace <= MAX_RACE)
raceAssigned[freeRace-1]--;
memmove( playerBalance+q, playerBalance+q+1, (MAX_NATION-1-q)*sizeof(playerBalance[0]) );
playerBalance[MAX_NATION-1] = 0;
--regPlayerCount;
--q;
}
}
}
if( recvPtr )
{
if( ((MpStructBase *)recvPtr)->msg_id == MPMSG_START_GAME )
{
retFlag = 1;
break; // break while(1) loop
}
else
{
switch( ((MpStructBase *)recvPtr)->msg_id )
{
case MPMSG_ABORT_GAME:
return 0;
case MPMSG_SEND_CONFIG:
tempConfig.change_game_setting( ((MpStructConfig *)recvPtr)->game_config );
refreshFlag |= SGOPTION_ALL_OPTIONS;
break;
case MPMSG_RANDOM_SEED:
info.init_random_seed( ((MpStructSeed *)recvPtr)->seed );
break;
// ####### begin Gilbert 25/10 #######//
case MPMSG_RANDOM_SEED_STR:
msgSeedStr = *(MpStructSeedStr *)recvPtr;
mapIdField.select_whole();
refreshFlag |= SGOPTION_MAP_ID;
break;
// ####### end Gilbert 25/10 #######//
case MPMSG_NEW_PLAYER:
{
// incorrect message, reject
MpStructRefuseNewPlayer msgRefuse(from);
mp_obj.send_stream(BROADCAST_PID, &msgRefuse, sizeof(msgRefuse) );
}
break;
case MPMSG_LOAD_GAME_NEW_PLAYER:
mp_obj.poll_players();
if( remote.is_host )
{
MpStructLoadGameNewPlayer *newPlayerMsg = (MpStructLoadGameNewPlayer *)recvPtr;
if( regPlayerCount < MAX_NATION
&& !nation_array.is_deleted(newPlayerMsg->nation_recno)
&& nation_array[newPlayerMsg->nation_recno]->color_scheme_id == newPlayerMsg->color_scheme_id
&& nation_array[newPlayerMsg->nation_recno]->race_id == newPlayerMsg->race_id
&& !colorAssigned[newPlayerMsg->color_scheme_id-1]
&& newPlayerMsg->frame_count == sys.frame_count
&& newPlayerMsg->random_seed == m.get_random_seed() )
{
regPlayerId[regPlayerCount] = newPlayerMsg->player_id;
playerReadyFlag[regPlayerCount] = 0;
raceAssigned[newPlayerMsg->race_id]++;
playerRace[regPlayerCount] = newPlayerMsg->race_id;
colorAssigned[newPlayerMsg->color_scheme_id-1]=1;
playerColor[regPlayerCount] = newPlayerMsg->color_scheme_id;
// send accept new player to all player
MpStructAcceptNewPlayer msgAccept(from);
mp_obj.send_stream( BROADCAST_PID, &msgAccept, sizeof(msgAccept) );
// send ready flag
for( int c = 0; c < regPlayerCount; ++c)
{
if( playerReadyFlag[c] )
{
MpStructPlayerReady msgReady(regPlayerId[c]);
mp_obj.send_stream(from, &msgReady, sizeof(msgReady));
}
}
// ###### patch begin Gilbert 22/1 ######//
// send remote.sync_test_level
MpStructSyncLevel msgSyncTest(remote.sync_test_level);
mp_obj.send_stream( from, &msgSyncTest, sizeof(msgSyncTest) );
// ###### patch end Gilbert 22/1 ######//
// update balance
playerBalance[regPlayerCount] = newPlayerMsg->player_balance;
regPlayerCount++;
mRefreshFlag |= MGOPTION_PLAYERS;
}
else
{
// reply refuse new player
MpStructRefuseNewPlayer msgRefuse(from);
mp_obj.send_stream( BROADCAST_PID, &msgRefuse, sizeof(msgRefuse) );
}
}
break;
case MPMSG_ACCEPT_NEW_PLAYER:
hostPlayerId = from;
if( regPlayerCount < MAX_NATION && ((MpStructAcceptNewPlayer *)recvPtr)->player_id != mp_obj.my_player_id )
{
// search if this player has existed
for( p=0; p < regPlayerCount && regPlayerId[p] != ((MpStructAcceptNewPlayer *)recvPtr)->player_id; ++p );
regPlayerId[p] = ((MpStructAcceptNewPlayer *)recvPtr)->player_id;
playerReadyFlag[p] = 0;
if( p >= regPlayerCount )
{
regPlayerCount++; // now regPlayerCount == p
err_when( p != regPlayerCount );
}
mRefreshFlag |= MGOPTION_PLAYERS;
}
break;
case MPMSG_PLAYER_READY:
{
for( int p = 0; p < regPlayerCount; ++p)
{
if( regPlayerId[p] == ((MpStructPlayerReady *)recvPtr)->player_id )
{
playerReadyFlag[p] = 1;
mRefreshFlag |= MGOPTION_PLAYERS;
}
}
}
break;
case MPMSG_PLAYER_UNREADY:
{
for( int p = 0; p < regPlayerCount; ++p)
{
if( regPlayerId[p] == ((MpStructPlayerUnready *)recvPtr)->player_id )
{
playerReadyFlag[p] = 0;
mRefreshFlag |= MGOPTION_PLAYERS;
}
}
}
break;
case MPMSG_SEND_CHAT_MSG:
while( messageList.size() >= 4 )
messageList.linkout(1);
messageList.linkin(recvPtr);
mRefreshFlag |= MGOPTION_IN_MESSAGE;
break;
// ###### patch begin Gilbert 22/1 ######//
case MPMSG_SEND_SYNC_TEST_LEVEL:
remote.sync_test_level = ((MpStructSyncLevel *)recvPtr)->sync_test_level;
break;
// ###### patch end Gilbert 22/1 ######//
case MPMSG_REFUSE_NEW_PLAYER:
if( ((MpStructRefuseNewPlayer *)recvPtr)->player_id == mp_obj.my_player_id )
{
box.msg("You cannot join the game because the multiplayer saved game you selected is different from those of other human players.");
return 0;
}
break;
default: // if the game is started, any other thing is received
return 0;
}
}
}
// --------- detect switch option button ------//
if( mouse.single_click(96, offsetY+12, 218, offsetY+54) )
{
if( optionMode != OPTION_BASIC )
{
optionMode = OPTION_BASIC;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(236, offsetY+12, 363, offsetY+54) )
{
if( optionMode != OPTION_ADVANCED )
{
optionMode = OPTION_ADVANCED;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(380, offsetY+12, 506, offsetY+54) )
{
if( optionMode != OPTION_ADVANCE2 )
{
optionMode = OPTION_ADVANCE2;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
else if( mouse.single_click(523, offsetY+12, 649, offsetY+54) )
{
if( optionMode != OPTION_GOAL )
{
optionMode = OPTION_GOAL;
refreshFlag = SGOPTION_ALL;
mRefreshFlag = MGOPTION_ALL;
}
}
// --------- detect ready button button --------//
unsigned keyCode;
if( readyButton.detect() )
{
mRefreshFlag |= MGOPTION_PLAYERS;
for(p = 0; p < regPlayerCount && regPlayerId[p] != mp_obj.my_player_id; ++p);
if( p < regPlayerCount )
{
if( !selfReadyFlag )
{
playerReadyFlag[p] = selfReadyFlag = 1;
MpStructPlayerReady msgReady(mp_obj.my_player_id);
mp_obj.send_stream(BROADCAST_PID, &msgReady, sizeof(msgReady));
}
else
{
// else un-ready this player
playerReadyFlag[p] = selfReadyFlag = 0;
MpStructPlayerUnready msgUnready(mp_obj.my_player_id);
mp_obj.send_stream(BROADCAST_PID, &msgUnready, sizeof(msgUnready));
}
}
}
if( remote.is_host && startButton.detect() )
{
// see if all player is ready
short sumBalance = 0;
int q;
for( q = 0; q < regPlayerCount && playerReadyFlag[q]; ++q)
{
err_when( playerBalance[q] == 0 );
sumBalance += playerBalance[q];
}
if( q >= regPlayerCount ) // not all playerReadyFlag[p] = 1;
{
#ifdef DEBUG
sumBalance = 0;
#endif
#ifdef BETA
sumBalance = 0;
#endif
if( regPlayerCount != maxPlayer )
{
String str;
str = "This multiplayer saved game needs ";
str += maxPlayer;
str += " human players while now there ";
if( regPlayerCount > 1 )
str += " are";
else
str += " is";
str += " only ";
str += regPlayerCount;
if( regPlayerCount > 1 )
str += " human players.";
else
str += " human player.";
str += " The game cannot start.";
box.msg(str);
}
else if( sumBalance < 0 )
{
// too many non-CD version
box.msg("There are not enough Seven Kingdoms CDROMs to start the game. Each CDROM supports "PLAYER_RATIO_STRING" players.");
}
else
{
// MpStructBase msgStart(MPMSG_START_GAME);
// mp_obj.send_stream(BROADCAST_PID, &msgStart, sizeof(msgStart));
retFlag = 1;
break; // break while(1)
}
}
}
else if( returnButton.detect() )
{
if( remote.is_host )
{
MpStructBase msgAbort(MPMSG_ABORT_GAME);
mp_obj.send_stream(BROADCAST_PID, &msgAbort, sizeof(msgAbort) );
}
retFlag = 0;
break; // break while(1)
}
else if( (keyCode = messageField.detect()) != 0 )
{
mRefreshFlag |= MGOPTION_OUT_MESSAGE;
if(keyCode == KEY_RETURN && strlen(typingMsg.content) > 0)
{
// send message
mp_obj.send_stream(BROADCAST_PID, &typingMsg, sizeof(typingMsg) );
// clear the string
messageField.clear();
}
else if( keyCode == KEY_ESC )
{
messageField.clear();
}
}
mp_obj.after_send();
// ####### begin Gilbert 24/10 #######//
vga_front.unlock_buf();
// ####### end Gilbert 24/10 #######//
}
// ###### begin Gilbert 24/10 #######//
if( !vga_front.buf_locked )
vga_front.lock_buf();
// ###### end Gilbert 24/10 #######//
mp_obj.after_send();
// ---------- final setup to start multiplayer game --------//
if( retFlag )
{
retFlag = 0;
if( remote.is_host )
mp_obj.disable_join_session();
// mp_obj.poll_players();
int trial;
unsigned long startTime;
int playerCount = 0;
if( &config != &tempConfig )
config = tempConfig;
if( remote.is_host )
{
// setup nation now
VLenQueue setupString;
// ------- put start game string -------//
{
MpStructBase msgStart(MPMSG_START_GAME);
memcpy( setupString.reserve(sizeof(msgStart)), &msgStart, sizeof(msgStart) );
}
// ------- put nations -------//
playerCount = 0;
for( p = 0; p < regPlayerCount; ++p )
{
PID_TYPE playerId = regPlayerId[p];
PlayerDesc *player = mp_obj.search_player(playerId);
if( !playerId || !player || !player->connecting )
continue;
// match nation color
for( short nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno)
{
Nation *nationPtr;
if( !nation_array.is_deleted(nationRecno) && (nationPtr = nation_array[nationRecno])
&& (nationPtr->is_own() || nationPtr->is_remote())
&& playerColor[p] == nation_array[nationRecno]->color_scheme_id )
{
nationPtr->player_id = playerId;
nationPtr->next_frame_ready = 0;
((MpStructNation *)setupString.reserve(sizeof(MpStructNation)))->init(
nationRecno, nationPtr->player_id,
nationPtr->color_scheme_id, nationPtr->race_id, player->friendly_name_str());
playerCount++;
break;
}
}
}
/*
for( int d = 1; playerCountpid() : 0;
if( !playerId || !player->connecting )
continue;
for( p = 0; p < regPlayerCount && regPlayerId[p] != playerId; ++p);
if( p >= regPlayerCount ) // not found
continue;
// match nation color
for( short nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno)
{
Nation *nationPtr;
if( !nation_array.is_deleted(nationRecno) && (nationPtr = nation_array[nationRecno])
&& (nationPtr->is_own() || nationPtr->is_remote())
&& playerColor[p] == nation_array[nationRecno]->color_scheme_id )
{
nationPtr->player_id = playerId;
nationPtr->next_frame_ready = 0;
((MpStructNation *)setupString.reserve(sizeof(MpStructNation)))->init(
nationRecno, nationPtr->player_id,
nationPtr->color_scheme_id, nationPtr->race_id, player->friendly_name_str());
playerCount++;
break;
}
}
}
*/
//--- if the current number of players < original number of players ---//
if( playerCount < maxPlayer )
{
String str;
str = "This multiplayer saved game needs ";
str += maxPlayer;
str += " human players while now there ";
if( playerCount > 1 )
str += " are";
else
str += " is";
str += " only ";
str += playerCount;
if( playerCount > 1 )
str += " human players.";
else
str += " human player.";
str += " The game cannot start.";
box.msg(str);
return 0;
}
//--- if the current number of players > original number of players ---//
if( playerCount > maxPlayer )
{
String str;
str = "This multiplayer saved game can only support ";
str += maxPlayer;
str += " human players while now there are ";
str += playerCount;
str += " human players. The game cannot start.";
box.msg(str);
return 0;
}
// ---- force set to the lowest frame delay -------//
#ifdef AMPLUS
remote.set_process_frame_delay(FORCE_MAX_FRAME_DELAY);
{
MpStructProcessFrameDelay msgFrameDelay(remote.get_process_frame_delay());
memcpy( setupString.reserve(sizeof(msgFrameDelay)), &msgFrameDelay, sizeof(msgFrameDelay));
}
#endif
// -------- send sync test level ----------//
{
MpStructSyncLevel msgSyncTest(remote.sync_test_level);
memcpy( setupString.reserve(sizeof(msgSyncTest)), &msgSyncTest, sizeof(msgSyncTest));
}
mp_obj.send_stream( BROADCAST_PID, setupString.queue_buf, setupString.length() );
mp_obj.after_send();
}
else
{
// use the message recving MPMSG_START_GAME
err_when( !recvPtr );
DWORD offset = 0;
int recvStartMsg = 0;
int ownPlayerFound = 0;
playerCount = 0;
char *oriRecvPtr = recvPtr;
int recvSetFrameDelay = 0;
int recvSyncTestLevel = 0;
// process the string received
while( offset < recvLen )
{
DWORD oldOffset = offset;
recvPtr = oriRecvPtr + offset;
switch( ((MpStructBase *)(recvPtr))->msg_id )
{
case MPMSG_START_GAME:
recvStartMsg = 1;
offset += sizeof( MpStructBase );
break;
case MPMSG_DECLARE_NATION:
{
MpStructNation *msgNation = (MpStructNation *)recvPtr;
short nationRecno = msgNation->nation_recno;
Nation *nationPtr;
if( nation_array.is_deleted(nationRecno) ||
!(nationPtr = nation_array[nationRecno]) ||
!nationPtr->is_own() && !nationPtr->is_remote() ||
nationPtr->color_scheme_id != msgNation->color_scheme )
{
box.msg( "Incorrect kingdom information received from the host." );
return 0;
}
nationPtr->player_id = msgNation->dp_player_id;
if( nationPtr->is_own() && msgNation->dp_player_id == mp_obj.my_player_id)
{
ownPlayerFound = 1;
}
nationPtr->next_frame_ready = 0;
nation_array.set_human_name(nationRecno, msgNation->player_name);
++playerCount;
offset += sizeof( MpStructNation );
}
break;
case MPMSG_SET_PROCESS_FRAME_DELAY:
remote.set_process_frame_delay(((MpStructProcessFrameDelay *)recvPtr)->common_process_frame_delay);
++recvSetFrameDelay;
offset += sizeof( MpStructProcessFrameDelay );
break;
case MPMSG_SEND_SYNC_TEST_LEVEL:
remote.sync_test_level = ((MpStructSyncLevel *)recvPtr)->sync_test_level;
++recvSyncTestLevel;
offset += sizeof( MpStructSyncLevel );
break;
} // end switch
if( !recvStartMsg || offset <= oldOffset )
{
err_here();
box.msg( "Connection string from host is corrupted" );
return 0;
}
} // end while
if( playerCount == 0 )
{
box.msg( "Cannot get kingdom information from the host." );
return 0;
}
err_when( playerCount > MAX_NATION );
if( !ownPlayerFound )
{
box.msg( "The host cannot recognize your machine." );
return 0;
}
err_when( ownPlayerFound > 1 );
if( !recvSetFrameDelay || !recvSyncTestLevel )
{
box.msg("Cannot receive important information from the host");
return 0;
}
err_when( recvSetFrameDelay > 1 );
err_when( recvSyncTestLevel > 1 );
// ------- send end setting string ------- //
MpStructBase mpEndSetting(MPMSG_END_SETTING);
mp_obj.send_stream( from, &mpEndSetting, sizeof(mpEndSetting) );
mp_obj.after_send();
}
if( remote.sync_test_level == 0)
{
remote.set_alternating_send(playerCount > 4 ? 4 : playerCount); // automatic setting
}
{
// ------- broadcast end setting string ------- //
MpStructBase mpEndSetting(MPMSG_END_SETTING);
mp_obj.send_stream( BROADCAST_PID, &mpEndSetting, sizeof(mpEndSetting) );
mp_obj.after_send();
// ------ wait for MPMSG_END_SETTING ----------//
// ---- to filter other all message until MP_MSG_END_SETTING ---//
trial = 5000;
startTime = m.get_time();
int recvEndSetting = 0;
while( --trial > 0 || m.get_time() - startTime < 10000 )
{
if( recvEndSetting >= playerCount-1)
break;
mp_obj.before_receive();
recvPtr = mp_obj.receive( &from, &to, &recvLen);
mp_obj.after_send();
if( recvPtr )
{
trial = max(trial, 1000);
startTime = m.get_time();
if( ((MpStructBase *)recvPtr)->msg_id == MPMSG_END_SETTING )
{
recvEndSetting++;
}
}
}
if( recvEndSetting < playerCount-1 )
{
box.msg("Some player(s) encountered errors when initializing the game.");
// but continue
}
}
retFlag = 1;
}
return retFlag;
}
#ifdef Y_SHIFT
#error
#endif
#undef Y_SHIFT_FLAG
// --------- End of function Game::mp_select_load_option --------- //
static void disp_virtual_button(ButtonCustom *button, int)
{
mouse.hide_area(button->x1, button->y1, button->x2, button->y2);
if( !button->pushed_flag )
{
// copy from back buffer to front buffer
IMGcopy(vga_front.buf_ptr(), vga_front.buf_pitch(),
vga_back.buf_ptr(), vga_back.buf_pitch(),
button->x1, button->y1, button->x2, button->y2 );
}
else
{
// copy from back buffer to front buffer, but the area is
// darkened by 2 scale
IMGcopyRemap(vga_front.buf_ptr(), vga_front.buf_pitch(),
vga_back.buf_ptr(), vga_back.buf_pitch(),
button->x1, button->y1, button->x2, button->y2,
vga.vga_color_table->get_table(-2) );
// draw black frame
if( button->x2-button->x1+1 == BASIC_OPTION_X_SPACE &&
button->y2-button->y1+1 == BASIC_OPTION_HEIGHT )
{
image_interface.put_front(button->x1, button->y1, "BAS_DOWN");
}
else if( button->x2-button->x1+1 == COLOR_OPTION_X_SPACE &&
button->y2-button->y1+1 == COLOR_OPTION_HEIGHT )
{
image_interface.put_front(button->x1, button->y1, "COL_DOWN");
}
else if( button->x2-button->x1+1 == SERVICE_OPTION_X_SPACE &&
button->y2-button->y1+1 == SERVICE_OPTION_HEIGHT )
{
image_menu.put_front(button->x1, button->y1, "NMPG-1BD");
}
}
mouse.show_area();
}
static void disp_virtual_tick(ButtonCustom *button, int )
{
mouse.hide_area(button->x1, button->y1, button->x2, button->y2);
// copy from back buffer to front buffer
IMGcopy(vga_front.buf_ptr(), vga_front.buf_pitch(),
vga_back.buf_ptr(), vga_back.buf_pitch(),
button->x1, button->y1, button->x2, button->y2 );
if( button->pushed_flag )
image_menu.put_front( button->x1+3, button->y1+3, "NMPG-RCH" );
mouse.show_area();
}
static void disp_scroll_bar_func(SlideVBar *scroll, int)
{
short rectTop = scroll->rect_top();
short rectBottom = scroll->rect_bottom();
vga.blt_buf(scroll->scrn_x1, scroll->scrn_y1, scroll->scrn_x2, scroll->scrn_y2, 0);
vga_front.bar( scroll->scrn_x1, rectTop, scroll->scrn_x2, rectBottom, VGA_YELLOW+1);
if( rectBottom - rectTop > 6 )
{
vga_front.d3_panel_up(scroll->scrn_x1, rectTop, scroll->scrn_x2, rectBottom,2,0);
}
}