Implemented 'Ready' button for the lobby. The game starts when all players have clicked on it.
git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@4555 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
3c749e2ee3
commit
78f4b01231
|
@ -88,6 +88,7 @@ typedef enum
|
|||
NET_PLAYER_JOINED, //55 notice about player joining
|
||||
NET_PLAYER_LEFT, //56 notice about player leaving
|
||||
NET_GAME_FLAGS, //57 game flags
|
||||
NET_READY_REQUEST, //58 player ready to start an mp game
|
||||
NUM_GAME_PACKETS
|
||||
} MESSAGE_TYPES;
|
||||
|
||||
|
|
254
src/multiint.c
254
src/multiint.c
|
@ -113,6 +113,8 @@ static BOOL safeSearch = false; // allow auto game finding.
|
|||
|
||||
static UDWORD hideTime=0;
|
||||
|
||||
BOOL bPlayerReadyGUI[MAX_PLAYERS] = {false};
|
||||
|
||||
#define DEFAULTCAMPAIGNMAP "Rush"
|
||||
#define DEFAULTSKIRMISHMAP "Sk-Rush"
|
||||
|
||||
|
@ -132,6 +134,7 @@ void intDisplayFeBox (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIEL
|
|||
void displayRemoteGame (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
|
||||
void displayPlayer (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
|
||||
void displayTeamChooser (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
|
||||
void displayMultiReady (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
|
||||
void displayMultiEditBox (WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
|
||||
void setLockedTeamsMode (void);
|
||||
|
||||
|
@ -147,7 +150,6 @@ void runConnectionScreen (void);
|
|||
BOOL startConnectionScreen (void);
|
||||
|
||||
// Game option functions
|
||||
static void addOkBut (void);
|
||||
static void addGameOptions (BOOL bRedo); // options (rhs) boxV
|
||||
UDWORD addPlayerBox (BOOL); // players (mid) box
|
||||
static void addChatBox (void);
|
||||
|
@ -167,6 +169,7 @@ static void closeTeamChooser (void);
|
|||
static BOOL SendColourRequest (UBYTE player, UBYTE col,UBYTE chosenPlayer);
|
||||
static BOOL safeToUseColour (UDWORD player,UDWORD col);
|
||||
BOOL chooseColour (UDWORD);
|
||||
static BOOL changeReadyStatus (UBYTE player, BOOL bReady);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// map previews..
|
||||
|
@ -923,6 +926,9 @@ static void addColourChooser(UDWORD player)
|
|||
// detele team chooser botton
|
||||
widgDelete(psWScreen,MULTIOP_TEAMS_START+player);
|
||||
|
||||
// detele 'ready' button
|
||||
widgDelete(psWScreen,MULTIOP_READY_START+player);
|
||||
|
||||
// add form.
|
||||
addBlueForm(MULTIOP_PLAYERS,MULTIOP_COLCHOOSER_FORM,"",
|
||||
10,
|
||||
|
@ -1026,6 +1032,60 @@ BOOL recvTeamRequest()
|
|||
return true;
|
||||
}
|
||||
|
||||
static BOOL SendReadyRequest(UBYTE player, BOOL bReady)
|
||||
{
|
||||
if(NetPlay.bHost) // do or request the change.
|
||||
{
|
||||
return changeReadyStatus(player, bReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
NETbeginEncode(NET_READY_REQUEST, NET_ALL_PLAYERS);
|
||||
NETuint8_t(&player);
|
||||
NETbool(&bReady);
|
||||
NETend();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL recvReadyRequest()
|
||||
{
|
||||
UBYTE player;
|
||||
BOOL bReady;
|
||||
|
||||
if(!NetPlay.bHost) //only host should act.
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
NETbeginDecode(NET_READY_REQUEST);
|
||||
NETuint8_t(&player);
|
||||
NETbool(&bReady);
|
||||
NETend();
|
||||
|
||||
if (player > MAX_PLAYERS)
|
||||
{
|
||||
debug(LOG_ERROR, "Invalid NET_READY_REQUEST from player %d: player id = %d",
|
||||
NETgetSource(), (int)player);
|
||||
return false;
|
||||
}
|
||||
|
||||
return changeReadyStatus((UBYTE)player, bReady);
|
||||
}
|
||||
|
||||
static BOOL changeReadyStatus(UBYTE player, BOOL bReady)
|
||||
{
|
||||
unsigned int playerGUI_ID;
|
||||
|
||||
for(playerGUI_ID=0;(playerGUI_ID <= game.maxPlayers) &&
|
||||
(player2dpid[player] != NetPlay.players[playerGUI_ID].dpid);playerGUI_ID++);
|
||||
|
||||
bPlayerReadyGUI[playerGUI_ID] = bReady;
|
||||
sendOptions(player2dpid[player], player); // tell everyone && update requesting player.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static BOOL changeColour(UBYTE player, UBYTE col, UBYTE chosenPlayer)
|
||||
{
|
||||
if(chosenPlayer == UBYTE_MAX)
|
||||
|
@ -1128,6 +1188,9 @@ static void addTeamChooser(UDWORD player)
|
|||
// delete that players box
|
||||
widgDelete(psWScreen,MULTIOP_PLAYER_START+player);
|
||||
|
||||
// delete 'ready' button
|
||||
widgDelete(psWScreen,MULTIOP_READY_START+player);
|
||||
|
||||
// add form.
|
||||
addBlueForm(MULTIOP_PLAYERS,MULTIOP_TEAMCHOOSER_FORM,"",
|
||||
10,
|
||||
|
@ -1263,7 +1326,7 @@ UDWORD addPlayerBox(BOOL players)
|
|||
sButInit.style = WBUT_PLAIN;
|
||||
sButInit.x = 10 + MULTIOP_TEAMSWIDTH;
|
||||
sButInit.y = (UWORD)(( (MULTIOP_PLAYERHEIGHT+5)*i)+4);
|
||||
sButInit.width = MULTIOP_PLAYERWIDTH - MULTIOP_TEAMSWIDTH;
|
||||
sButInit.width = MULTIOP_PLAYERWIDTH - MULTIOP_TEAMSWIDTH - MULTIOP_READY_WIDTH;
|
||||
sButInit.height = MULTIOP_PLAYERHEIGHT;
|
||||
sButInit.pTip = NULL;//Players[i].name;
|
||||
sButInit.FontID = font_regular;
|
||||
|
@ -1280,6 +1343,29 @@ UDWORD addPlayerBox(BOOL players)
|
|||
widgAddButton(psWScreen, &sButInit);
|
||||
}
|
||||
|
||||
// add 'ready' button
|
||||
memset(&sButInit, 0, sizeof(W_BUTINIT));
|
||||
sButInit.formID = MULTIOP_PLAYERS;
|
||||
sButInit.id = MULTIOP_READY_START+i;
|
||||
sButInit.style = WBUT_PLAIN;
|
||||
sButInit.x = 10 + MULTIOP_PLAYERWIDTH - MULTIOP_READY_WIDTH;
|
||||
sButInit.y = (UWORD)(( (MULTIOP_PLAYERHEIGHT+5)*i)+4);
|
||||
sButInit.width = MULTIOP_READY_WIDTH;
|
||||
sButInit.height = MULTIOP_READY_HEIGHT;
|
||||
sButInit.FontID = font_regular;
|
||||
sButInit.pDisplay = displayMultiReady;
|
||||
sButInit.UserData = i;
|
||||
|
||||
if(bPlayerReadyGUI[i])
|
||||
{
|
||||
sButInit.pTip = "Ready";
|
||||
}
|
||||
else
|
||||
{
|
||||
sButInit.pTip = "Click when ready";
|
||||
}
|
||||
|
||||
widgAddButton(psWScreen, &sButInit);
|
||||
}
|
||||
else if(game.type == SKIRMISH) // skirmish player
|
||||
{
|
||||
|
@ -1330,16 +1416,6 @@ void kickPlayer(uint32_t player_id)
|
|||
NETend();
|
||||
}
|
||||
|
||||
|
||||
static void addOkBut(void)
|
||||
{
|
||||
addMultiBut(psWScreen, MULTIOP_OPTIONS,CON_OK,
|
||||
MULTIOP_OKX,MULTIOP_OKY,
|
||||
iV_GetImageWidth(FrontImages,IMAGE_BIGOK),
|
||||
iV_GetImageHeight(FrontImages,IMAGE_BIGOK),
|
||||
_("Accept Settings"),IMAGE_BIGOK,IMAGE_BIGOK,false);
|
||||
}
|
||||
|
||||
static void addChatBox(void)
|
||||
{
|
||||
W_FORMINIT sFormInit;
|
||||
|
@ -1616,7 +1692,6 @@ static void processMultiopWidgets(UDWORD id)
|
|||
{
|
||||
sendOptions(0,0);
|
||||
disableMultiButs();
|
||||
addOkBut();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1627,7 +1702,6 @@ static void processMultiopWidgets(UDWORD id)
|
|||
{
|
||||
disableMultiButs();
|
||||
sendOptions(0,0);
|
||||
addOkBut();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1638,7 +1712,6 @@ static void processMultiopWidgets(UDWORD id)
|
|||
{
|
||||
sendOptions(0,0);
|
||||
disableMultiButs();
|
||||
addOkBut();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1762,7 +1835,6 @@ static void processMultiopWidgets(UDWORD id)
|
|||
|
||||
addGameOptions(false); // update game options box.
|
||||
addChatBox();
|
||||
addOkBut();
|
||||
|
||||
disableMultiButs();
|
||||
|
||||
|
@ -1797,42 +1869,6 @@ static void processMultiopWidgets(UDWORD id)
|
|||
widgSetString(psWScreen, MULTIOP_CHATEDIT, ""); // clear box
|
||||
break;
|
||||
|
||||
case CON_OK:
|
||||
decideWRF(); // set up swrf & game.map
|
||||
bMultiPlayer = true;
|
||||
|
||||
if(NetPlay.bHost)
|
||||
{
|
||||
|
||||
///////////
|
||||
//
|
||||
if(game.type == SKIRMISH)
|
||||
{
|
||||
chooseSkirmishColours();
|
||||
sendOptions(0,0);
|
||||
}
|
||||
// end of skirmish col choose
|
||||
////////
|
||||
|
||||
NEThaltJoining(); // stop new players entering.
|
||||
SendFireUp(); //bcast a fireup message
|
||||
}
|
||||
|
||||
// set the fog correctly..
|
||||
setRevealStatus(game.fog);
|
||||
war_SetFog(!game.fog);
|
||||
|
||||
changeTitleMode(STARTGAME);
|
||||
|
||||
bHosted = false;
|
||||
|
||||
if(NetPlay.bHost)
|
||||
{
|
||||
sendTextMessage(_("Host is Starting Game"),true);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
|
||||
case CON_CANCEL:
|
||||
stopJoining();
|
||||
break;
|
||||
|
@ -1894,6 +1930,23 @@ static void processMultiopWidgets(UDWORD id)
|
|||
}
|
||||
}
|
||||
|
||||
// 'ready' button
|
||||
if((id >= MULTIOP_READY_START) && (id <= MULTIOP_READY_END)) // clicked on a player
|
||||
{
|
||||
UBYTE player = (UBYTE)(id-MULTIOP_READY_START);
|
||||
if(NetPlay.players[player].dpid == player2dpid[selectedPlayer] )
|
||||
{
|
||||
SendReadyRequest(selectedPlayer, !bPlayerReadyGUI[player]);
|
||||
|
||||
// if hosting try to start the game if everyone is ready
|
||||
if(NetPlay.bHost && multiplayPlayersReady(false))
|
||||
{
|
||||
startMultiplayerGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if((id >= MULTIOP_PLAYER_START) && (id <= MULTIOP_PLAYER_END)) // clicked on a player
|
||||
{
|
||||
if(NetPlay.players[id-MULTIOP_PLAYER_START].dpid == player2dpid[selectedPlayer] )
|
||||
|
@ -1971,6 +2024,38 @@ static void processMultiopWidgets(UDWORD id)
|
|||
|
||||
}
|
||||
|
||||
/* Start a multiplayer or skirmish game */
|
||||
void startMultiplayerGame(void)
|
||||
{
|
||||
decideWRF(); // set up swrf & game.map
|
||||
bMultiPlayer = true;
|
||||
|
||||
if(NetPlay.bHost)
|
||||
{
|
||||
if(game.type == SKIRMISH)
|
||||
{
|
||||
chooseSkirmishColours();
|
||||
sendOptions(0,0);
|
||||
}
|
||||
|
||||
NEThaltJoining(); // stop new players entering.
|
||||
SendFireUp(); //bcast a fireup message
|
||||
}
|
||||
|
||||
// set the fog correctly..
|
||||
setRevealStatus(game.fog);
|
||||
war_SetFog(!game.fog);
|
||||
|
||||
changeTitleMode(STARTGAME);
|
||||
|
||||
bHosted = false;
|
||||
|
||||
if(NetPlay.bHost)
|
||||
{
|
||||
sendTextMessage(_("Host is Starting Game"),true);
|
||||
}
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// Net message handling
|
||||
|
||||
|
@ -2014,6 +2099,16 @@ void frontendMultiMessages(void)
|
|||
recvTeamRequest();
|
||||
break;
|
||||
|
||||
case NET_READY_REQUEST:
|
||||
recvReadyRequest();
|
||||
|
||||
// if hosting try to start the game if everyone is ready
|
||||
if(NetPlay.bHost && multiplayPlayersReady(false))
|
||||
{
|
||||
startMultiplayerGame();
|
||||
}
|
||||
break;
|
||||
|
||||
case NET_PING: // diagnostic ping msg.
|
||||
recvPing();
|
||||
break;
|
||||
|
@ -2301,7 +2396,6 @@ BOOL startMultiOptions(BOOL bReenter)
|
|||
if(bReenter && bHosted)
|
||||
{
|
||||
disableMultiButs();
|
||||
addOkBut();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2433,6 +2527,21 @@ static UDWORD bestPlayer(UDWORD player)
|
|||
return count;
|
||||
}
|
||||
|
||||
void displayMultiReady(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
|
||||
{
|
||||
UDWORD x = xOffset+psWidget->x;
|
||||
UDWORD y = yOffset+psWidget->y;
|
||||
BOOL Hilight = false;
|
||||
|
||||
if( ((W_BUTTON*)psWidget)->state & (WBUTS_HILITE| WCLICK_DOWN | WCLICK_LOCKED | WCLICK_CLICKLOCK))
|
||||
{
|
||||
Hilight = true;
|
||||
}
|
||||
|
||||
//bluboxes.
|
||||
drawBlueBox(x,y,psWidget->width,psWidget->height); // right
|
||||
}
|
||||
|
||||
void displayTeamChooser(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
|
||||
{
|
||||
UDWORD x = xOffset+psWidget->x;
|
||||
|
@ -2674,6 +2783,18 @@ void displayPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *p
|
|||
//unknown bugfix
|
||||
// game.skirmishPlayers[i] =true; // don't clear this one!
|
||||
game.skDiff[i]=UBYTE_MAX; // don't clear this one!
|
||||
|
||||
// draw 'ready' button state
|
||||
if(bPlayerReadyGUI[i])
|
||||
{
|
||||
iV_DrawImage(FrontImages,IMAGE_OK,x+MULTIOP_READY_IMG_OFFSET_X,
|
||||
y+MULTIOP_READY_IMG_OFFSET_Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
iV_DrawImage(FrontImages,IMAGE_NO,x+MULTIOP_READY_IMG_OFFSET_X,
|
||||
y+MULTIOP_READY_IMG_OFFSET_Y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2901,3 +3022,30 @@ void setLockedTeamsMode(void)
|
|||
sendOptions(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if all human players clicked on the 'ready' button */
|
||||
bool multiplayPlayersReady(bool bNotifyStatus)
|
||||
{
|
||||
unsigned int player,playerID;
|
||||
bool bReady;
|
||||
|
||||
bReady = true;
|
||||
|
||||
for(player = 0; player < game.maxPlayers; player++)
|
||||
{
|
||||
// check if this human player is ready, ignore AIs
|
||||
if(NetPlay.players[player].dpid && !bPlayerReadyGUI[player])
|
||||
{
|
||||
if(bNotifyStatus)
|
||||
{
|
||||
for(playerID=0;(playerID <= game.maxPlayers) && (player2dpid[playerID] != NetPlay.players[player].dpid);playerID++);
|
||||
|
||||
console("%s is not ready", getPlayerName(playerID));
|
||||
}
|
||||
|
||||
bReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
return bReady;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ extern BOOL addMultiBut(W_SCREEN *screen, UDWORD formid, UDWORD id, UDWORD x, UD
|
|||
extern char sPlayer[128];
|
||||
extern SDWORD playerTeamGUI[MAX_PLAYERS];
|
||||
extern SDWORD playerTeam[MAX_PLAYERS];
|
||||
extern BOOL bPlayerReadyGUI[MAX_PLAYERS];
|
||||
|
||||
void kickPlayer (uint32_t dpid);
|
||||
UDWORD addPlayerBox (BOOL); // players (mid) box
|
||||
|
@ -143,6 +144,14 @@ void loadMapPreview(void);
|
|||
#define MULTIOP_TEAMCHOOSER 102810
|
||||
#define MULTIOP_TEAMCHOOSER_END 102817
|
||||
|
||||
// 'Ready' button
|
||||
#define MULTIOP_READY_START 102900
|
||||
#define MULTIOP_READY_WIDTH 41
|
||||
#define MULTIOP_READY_HEIGHT 36
|
||||
#define MULTIOP_READY_IMG_OFFSET_X 158
|
||||
#define MULTIOP_READY_IMG_OFFSET_Y 8
|
||||
#define MULTIOP_READY_END 102907
|
||||
|
||||
#define MULTIOP_PLAYERWIDTH 230
|
||||
#define MULTIOP_PLAYERHEIGHT 36
|
||||
|
||||
|
|
|
@ -288,6 +288,8 @@ BOOL MultiPlayerJoin(UDWORD dpid)
|
|||
setupNewPlayer(dpid,i); // setup all the guff for that player.
|
||||
sendOptions(dpid,i);
|
||||
|
||||
bPlayerReadyGUI[dpid] = false;
|
||||
|
||||
// if skirmish and game full, then kick...
|
||||
if(game.type == SKIRMISH && NetPlay.playercount > game.maxPlayers )
|
||||
{
|
||||
|
|
|
@ -135,6 +135,12 @@ void sendOptions(uint32_t dest, uint32_t play)
|
|||
NETuint8_t(&ingame.pStructureLimits[i].limit);
|
||||
}
|
||||
|
||||
// Send ready status of all players
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
NETbool(&bPlayerReadyGUI[i]);
|
||||
}
|
||||
|
||||
NETend();
|
||||
}
|
||||
|
||||
|
@ -248,6 +254,12 @@ void recvOptions()
|
|||
NETuint8_t(&ingame.pStructureLimits[i].limit);
|
||||
}
|
||||
|
||||
// Receive ready status of all players
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
NETbool(&bPlayerReadyGUI[i]);
|
||||
}
|
||||
|
||||
NETend();
|
||||
|
||||
// Post process
|
||||
|
@ -335,6 +347,8 @@ BOOL hostCampaign(char *sGame, char *sPlayer)
|
|||
setMultiStats(NetPlay.dpidPlayer,playerStats,false);
|
||||
setMultiStats(NetPlay.dpidPlayer,playerStats,true);
|
||||
|
||||
bPlayerReadyGUI[0] = false;
|
||||
|
||||
if(!NetPlay.bComms)
|
||||
{
|
||||
NETplayerInfo();
|
||||
|
|
|
@ -111,6 +111,9 @@ static BOOL recvBeacon(void);
|
|||
static BOOL recvDestroyTemplate(void);
|
||||
static BOOL recvResearch(void);
|
||||
|
||||
bool multiplayPlayersReady (bool bNotifyStatus);
|
||||
void startMultiplayerGame (void);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////////
|
||||
// temporarily disable multiplayer mode.
|
||||
BOOL turnOffMultiMsg(BOOL bDoit)
|
||||
|
@ -750,6 +753,15 @@ BOOL recvMessage(void)
|
|||
case NET_TEAMREQUEST:
|
||||
recvTeamRequest();
|
||||
break;
|
||||
case NET_READY_REQUEST:
|
||||
recvReadyRequest();
|
||||
|
||||
// if hosting try to start the game if everyone is ready
|
||||
if(NetPlay.bHost && multiplayPlayersReady(false))
|
||||
{
|
||||
startMultiplayerGame();
|
||||
}
|
||||
break;
|
||||
case NET_ARTIFACTS:
|
||||
recvMultiPlayerRandomArtifacts();
|
||||
break;
|
||||
|
|
|
@ -214,4 +214,7 @@ extern BOOL msgStackGetDroid(DROID **ppsDroid);
|
|||
extern BOOL sendBeacon(int32_t locX, int32_t locY, int32_t forPlayer, int32_t sender, const char* pStr);
|
||||
extern BOOL msgStackFireTop(void);
|
||||
|
||||
extern bool multiplayPlayersReady(bool bNotifyStatus);
|
||||
extern void startMultiplayerGame(void);
|
||||
|
||||
#endif // __INCLUDED_SRC_MULTIPLAY_H__
|
||||
|
|
|
@ -65,5 +65,6 @@ extern BOOL recvMapFileRequested (void);
|
|||
|
||||
extern BOOL recvTextMessageAI (void); //AI multiplayer message
|
||||
extern BOOL recvTeamRequest (void);
|
||||
extern BOOL recvReadyRequest (void);
|
||||
|
||||
#endif // __INCLUDED_SRC_MULTIRECV_H__
|
||||
|
|
Loading…
Reference in New Issue