/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 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. Warzone 2100 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 Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * MultiMenu.c * Handles the In Game MultiPlayer Screen, alliances etc... * Also the selection of disk files.. */ #ifndef WIN32 #include #endif //above line not needed for win32. --Qamly #include "lib/framework/frame.h" #include "lib/widget/widget.h" #include "display3d.h" #include "intdisplay.h" #include "text.h" // FIXME Direct iVis implementation include! #include "lib/ivis_common/rendmode.h" #include "lib/ivis_common/piedef.h" #include "lib/gamelib/gtime.h" #include "lib/ivis_common/geo.h" #include "levels.h" #include "objmem.h" //for droid lists. #include "component.h" // for disaplycomponentobj. #include "hci.h" // for wFont def.& intmode. //#include "intfac.h" // for images. #include "power.h" #include "loadsave.h" // for drawbluebox #include "console.h" #include "ai.h" #include "csnap.h" #include "frend.h" #include "lib/netplay/netplay.h" #include "multiplay.h" #include "multistat.h" #include "multimenu.h" #include "multiint.h" #include "multigifts.h" #include "multijoin.h" #include "scores.h" // //////////////////////////////////////////////////////////////////////////// // defines W_SCREEN *psRScreen; // requester stuff. extern char MultiCustomMapsPath[255]; extern CURSORSNAP InterfaceSnap; //extern W_SCREEN *psWScreen; extern IMAGEFILE *FrontImages; extern void displayMultiBut(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours); BOOL MultiMenuUp = FALSE; BOOL ClosingMultiMenu = FALSE; static UDWORD context = 0; static UDWORD current_tech = 0; static UDWORD current_numplayers = 0; #define MULTIMENU_FORM_X 10 + D_W #define MULTIMENU_FORM_Y 23 + D_H #define MULTIMENU_FORM_W 620 #define MULTIMENU_FORM_H 295 #define MULTIMENU_PLAYER_H 32 #define MULTIMENU_FONT_OSET 20 #define MULTIMENU_C1 30 #define MULTIMENU_C2 (MULTIMENU_C1+30) #define MULTIMENU_C0 (MULTIMENU_C2+95) #define MULTIMENU_C3 (MULTIMENU_C0+36) #define MULTIMENU_C4 (MULTIMENU_C3+36) #define MULTIMENU_C5 (MULTIMENU_C4+32) #define MULTIMENU_C6 (MULTIMENU_C5+32) #define MULTIMENU_C7 (MULTIMENU_C6+32) #define MULTIMENU_C8 (MULTIMENU_C7+45) #define MULTIMENU_C9 (MULTIMENU_C8+95) #define MULTIMENU_C10 (MULTIMENU_C9+50) #define MULTIMENU_C11 (MULTIMENU_C10+45) #define MULTIMENU_CLOSE (MULTIMENU+1) #define MULTIMENU_PLAYER (MULTIMENU+2) #define MULTIMENU_ALLIANCE_BASE (MULTIMENU_PLAYER +MAX_PLAYERS) #define MULTIMENU_GIFT_RAD (MULTIMENU_ALLIANCE_BASE +MAX_PLAYERS) #define MULTIMENU_GIFT_RES (MULTIMENU_GIFT_RAD +MAX_PLAYERS) #define MULTIMENU_GIFT_DRO (MULTIMENU_GIFT_RES +MAX_PLAYERS) #define MULTIMENU_GIFT_POW (MULTIMENU_GIFT_DRO +MAX_PLAYERS) #define MULTIMENU_CHANNEL (MULTIMENU_GIFT_POW +MAX_PLAYERS) #define MULTIMENU_STOPS 50 #define MULTIMENU_MIDPOS (MULTIMENU_STOPS/2) #define MULTIMENU_MULTIPLIER ((100/MULTIMENU_STOPS)*2) /// requester stuff. #define M_REQUEST_CLOSE (MULTIMENU+49) #define M_REQUEST (MULTIMENU+50) #define M_REQUEST_TAB (MULTIMENU+51) #define M_REQUEST_C1 (MULTIMENU+61) #define M_REQUEST_C2 (MULTIMENU+62) #define M_REQUEST_C3 (MULTIMENU+63) #define M_REQUEST_AP (MULTIMENU+70) #define M_REQUEST_2P (MULTIMENU+71) #define M_REQUEST_4P (MULTIMENU+72) #define M_REQUEST_8P (MULTIMENU+73) #define M_REQUEST_BUT (MULTIMENU+100) // allow loads of buttons. #define M_REQUEST_BUTM (MULTIMENU+1100) #define M_REQUEST_X MULTIOP_PLAYERSX #define M_REQUEST_Y MULTIOP_PLAYERSY #define M_REQUEST_W MULTIOP_PLAYERSW #define M_REQUEST_H MULTIOP_PLAYERSH #define R_BUT_W 105//112 #define R_BUT_H 30 BOOL multiRequestUp = FALSE; //multimenu is up. static BOOL giftsUp[MAX_PLAYERS] = {TRUE}; //gift buttons for player are up. // //////////////////////////////////////////////////////////////////////////// // Map / force / name load save stuff. // //////////////////////////////////////////////////////////////////////////// // enumerates maps in the gamedesc file. // returns only maps that are valid the right 'type' BOOL enumerateMultiMaps(STRING *found, UDWORD *players,BOOL first, UBYTE camToUse, UBYTE numPlayers) { static LEVEL_DATASET *lev; UBYTE cam; if(first) { lev = psLevels; } while(lev) { // if(game.type == DMATCH) // { // if(lev->type == DMATCH) // { // strcpy(found,lev->pName); // *players = lev->players; // lev = lev->psNext; // return TRUE; // } // } // else if(game.type == SKIRMISH) { if(lev->type == MULTI_SKIRMISH2) { cam = 2; } else if(lev->type == MULTI_SKIRMISH3) { cam = 3; } // else if(lev->type == MULTI_SKIRMISHA) // { // cam = 0; // } else { cam = 1; } if((lev->type == SKIRMISH || lev->type == MULTI_SKIRMISH2 || lev->type == MULTI_SKIRMISH3) // || lev->type == MULTI_SKIRMISHA) && (numPlayers == 0 || numPlayers == lev->players) && cam == camToUse ) { strcpy(found,lev->pName); *players = lev->players; lev = lev->psNext; return TRUE; } } else // campaign, teamplay { // 'service pack 1' if(lev->type == MULTI_CAMPAIGN2) { cam = 2; } else if(lev->type == MULTI_CAMPAIGN3) { cam = 3; } // else if(lev->type == MULTI_CAMPAIGNA) // { // cam = 0; // } else { cam = 1; } // end of service pack if ((lev->type == CAMPAIGN || lev->type == MULTI_CAMPAIGN2 || lev->type == MULTI_CAMPAIGN3) // ||lev->type == MULTI_CAMPAIGNA) && (numPlayers == 0 || numPlayers == lev->players) && cam == camToUse ) { strcpy(found,lev->pName); *players = lev->players; lev = lev->psNext; return TRUE; } } lev = lev->psNext; } return FALSE; } // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// void displayRequestOption(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours) { UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; // UWORD im = (UWORD)UNPACKDWORD_TRI_B((UDWORD)psWidget->pUserData); // UWORD im2= (UWORD)(UNPACKDWORD_TRI_C((UDWORD)psWidget->pUserData)); UDWORD count; STRING butString[255]; strcpy(butString,((W_BUTTON *)psWidget)->pTip); drawBlueBox(x,y,psWidget->width,psWidget->height); //draw box iV_SetFont(WFont); // font iV_SetTextColour(-1); //colour while(iV_GetTextWidth(butString) > psWidget->width -10 ) { butString[strlen(butString)-1]='\0'; } iV_DrawText(butString, x + 6, y + 12); //draw text // if map, then draw no. of players. for(count=0;count<(UDWORD)psWidget->pUserData;count++) { iV_DrawTransImage(FrontImages,IMAGE_WEE_GUY,(x+(6*count)+6),y+16); } AddCursorSnap(&InterfaceSnap, (SWORD)(x+5),(SWORD)(y+5),psWidget->formID,psWidget->id,NULL); } // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// void displayCamTypeBut(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours) { UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; char buffer[8]; drawBlueBox(x,y,psWidget->width,psWidget->height); //draw box sprintf(buffer, "T%i", (int)(psWidget->UserData)); if ((int)(psWidget->UserData) == current_tech) { iV_SetTextColour(PIE_TEXT_WHITE); } else { iV_SetTextColour(PIE_TEXT_LIGHTBLUE); } pie_DrawText(buffer, x+2, y+12); } void displayNumPlayersBut(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours) { UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; char buffer[8]; drawBlueBox(x,y,psWidget->width,psWidget->height); //draw box if ((int)(psWidget->UserData) == current_numplayers) { iV_SetTextColour(PIE_TEXT_WHITE); } else { iV_SetTextColour(PIE_TEXT_LIGHTBLUE); } if ((int)(psWidget->UserData) == 0) { sprintf(buffer, " *"); } else { sprintf(buffer, "%iP", (int)(psWidget->UserData)); } pie_DrawText(buffer, x+2, y+12); } #define NBTIPS 512 unsigned int check_tip_index(unsigned int i) { if (i < NBTIPS) { return i; } else { debug(LOG_MAIN, "Tip window index too high (%ud)", i); return NBTIPS-1; } } // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// // FIXME: what is this, and why is there some code that only works in win32 // here? - Per VOID addMultiRequest(STRING *ToFindb,UDWORD mode, UBYTE mapCam, UBYTE numPlayers) { W_FORMINIT sFormInit; W_BUTINIT sButInit; UDWORD players,numButtons,butPerForm,i; #ifdef WIN32 WIN32_FIND_DATAA found; HANDLE dir; UDWORD count; STRING ToFind[255]; #endif STRING sTemp[64]; static STRING tips[NBTIPS][MAX_STR_SIZE]; numButtons = 0; context = mode; current_tech = mapCam; current_numplayers = numPlayers; #ifdef WIN32 if(GetCurrentDirectoryA(255,(char*)&ToFind) == 0) // What is this doing actually? { return; } strcat(ToFind,ToFindb); // count buttons. dir = FindFirstFileA(ToFind,&found); if(dir != INVALID_HANDLE_VALUE) { while( TRUE ) { numButtons++; if(! FindNextFileA(dir,&found ) ) { break; } } } FindClose(dir); #endif if(mode == MULTIOP_MAP) // if its a map, also look in the predone stuff. { if(enumerateMultiMaps(tips[0],&players, TRUE,mapCam,numPlayers)) { numButtons++; while(enumerateMultiMaps(tips[0],&players, FALSE,mapCam,numPlayers)) { numButtons++; } } } widgCreateScreen(&psRScreen); /// move this to intinit or somewhere like that.. (close too.) widgSetTipFont(psRScreen,WFont); /* Calculate how many buttons will go on a single form */ butPerForm = ((M_REQUEST_W - 0 - 4) / (R_BUT_W +4)) * ((M_REQUEST_H - 0- 4) / (R_BUT_H+ 4)); /* add a form to place the tabbed form on */ memset(&sFormInit, 0, sizeof(W_FORMINIT)); sFormInit.formID = 0; sFormInit.id = M_REQUEST; sFormInit.style = WFORM_PLAIN; sFormInit.x = (SWORD)(M_REQUEST_X+D_W); sFormInit.y = (SWORD)(M_REQUEST_Y+D_H); sFormInit.width = M_REQUEST_W; sFormInit.height = M_REQUEST_H; sFormInit.disableChildren = TRUE; sFormInit.pDisplay = intOpenPlainForm; widgAddForm(psRScreen, &sFormInit); /* Add the tabs */ memset(&sFormInit, 0, sizeof(W_FORMINIT)); sFormInit.formID = M_REQUEST; sFormInit.id = M_REQUEST_TAB; sFormInit.style = WFORM_TABBED; sFormInit.x = 2; sFormInit.y = 2; sFormInit.width = M_REQUEST_W; sFormInit.height = M_REQUEST_H-4; sFormInit.numMajor = numForms(numButtons, butPerForm); if (sFormInit.numMajor > 8) { sFormInit.numMajor = 8; } sFormInit.majorPos = WFORM_TABTOP; sFormInit.minorPos = WFORM_TABNONE; sFormInit.majorSize = OBJ_TABWIDTH+2; sFormInit.majorOffset = OBJ_TABOFFSET; sFormInit.tabVertOffset = (OBJ_TABHEIGHT/2); sFormInit.tabMajorThickness = OBJ_TABHEIGHT; sFormInit.pFormDisplay = intDisplayObjectForm; sFormInit.pUserData = (void*)&StandardTab; sFormInit.pTabDisplay = intDisplayTab; for (i=0; i< sFormInit.numMajor; i++) { sFormInit.aNumMinors[i] = 2; } widgAddForm(psRScreen, &sFormInit); // Add the close button. memset(&sButInit, 0, sizeof(W_BUTINIT)); sButInit.formID = M_REQUEST; sButInit.id = M_REQUEST_CLOSE; sButInit.style = WBUT_PLAIN; sButInit.x = M_REQUEST_W - CLOSE_WIDTH; sButInit.y = 0; sButInit.width = CLOSE_WIDTH; sButInit.height = CLOSE_HEIGHT; sButInit.pTip = strresGetString(psStringRes, STR_MISC_CLOSE); sButInit.FontID = WFont; sButInit.pDisplay = intDisplayImageHilight; sButInit.pUserData = (void*)PACKDWORD_TRI(0,IMAGE_CLOSEHILIGHT , IMAGE_CLOSE); widgAddButton(psRScreen, &sButInit); /* Put the buttons on it *//* Set up the button struct */ memset(&sButInit, 0, sizeof(W_BUTINIT)); sButInit.formID = M_REQUEST_TAB; sButInit.id = M_REQUEST_BUT; sButInit.style = WBUT_PLAIN; sButInit.x = 22; sButInit.y = 4; sButInit.width = R_BUT_W; sButInit.height = R_BUT_H; sButInit.pUserData = (void*)0; sButInit.pDisplay = displayRequestOption; sButInit.FontID = WFont; #ifdef WIN32 dir = FindFirstFileA(ToFind,&found); if(dir != INVALID_HANDLE_VALUE) { count=0; while( count < (butPerForm*4) ) { unsigned int tip_index = check_tip_index(sButInit.id-M_REQUEST_BUT); /* Set the tip and add the button */ // use MALLOC, and do it dynamically found.cFileName[strlen(found.cFileName) -4 ] = '\0'; // chop extension strcpy(tips[tip_index],found.cFileName); //need to store one! sButInit.pTip = tips[tip_index]; sButInit.pText = tips[tip_index]; if(mode == MULTIOP_MAP) // if its a map, set player flag. { sButInit.pUserData = (void*)( found.cFileName[0]-'0' ); // if(game.type == DMATCH) // { // if( found.cFileName[1] != 'd') // { // goto nextone; // } // } // else // { if( found.cFileName[1] != 'c') { goto nextone; } // } strcpy(sTemp, strrchr(found.cFileName,'-')+1 ); //chop off description // add number of players to string, choping of description // sprintf(tips[sButInit.id-M_REQUEST_BUT], "%d)%s", // sButInit.pUserData, // sTemp ); sprintf(tips[tip_index], "%s", sTemp ); } count++; widgAddButton(psRScreen, &sButInit); /* Update the init struct for the next button */ sButInit.id += 1; sButInit.x = (SWORD)(sButInit.x + (R_BUT_W+ 4)); if (sButInit.x + R_BUT_W+ 2 > M_REQUEST_W) { sButInit.x = 17; sButInit.y = (SWORD)(sButInit.y +R_BUT_H + 4); } if (sButInit.y +R_BUT_H + 4 > M_REQUEST_H) { sButInit.y = 4; sButInit.majorID += 1; } nextone: if(!FindNextFile(dir,&found ) ) /* find next one*/ { break; } } } FindClose(dir); #endif if(mode == MULTIOP_MAP) { if(enumerateMultiMaps( sTemp,&players,TRUE,mapCam,numPlayers)) { do{ unsigned int tip_index = check_tip_index(sButInit.id-M_REQUEST_BUT); // add number of players to string. sprintf(tips[tip_index],"%s",sTemp ); sButInit.pTip = tips[tip_index]; sButInit.pText = tips[tip_index]; sButInit.pUserData = (void*)players; widgAddButton(psRScreen, &sButInit); sButInit.id += 1; sButInit.x = (SWORD)(sButInit.x + (R_BUT_W+ 4)); if (sButInit.x + R_BUT_W+ 2 > M_REQUEST_W) { sButInit.x = 22; sButInit.y = (SWORD)(sButInit.y +R_BUT_H + 4); } if (sButInit.y +R_BUT_H + 4 > M_REQUEST_H) { sButInit.y = 4; sButInit.majorID += 1; } }while(enumerateMultiMaps(sTemp,&players,FALSE,mapCam,numPlayers)); } } multiRequestUp = TRUE; // if it's map select then add the cam style buttons. if(mode == MULTIOP_MAP) { memset(&sButInit, 0, sizeof(W_BUTINIT)); sButInit.formID = M_REQUEST; sButInit.id = M_REQUEST_C1; sButInit.style = WBUT_PLAIN; sButInit.x = 4; sButInit.y = 258; sButInit.width = 17; sButInit.height = 17; sButInit.UserData = 1; sButInit.FontID = WFont; sButInit.pTip = "Tech:1"; sButInit.pDisplay = displayCamTypeBut; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_C2; sButInit.y += 22; sButInit.UserData = 2; sButInit.pTip = "Tech:2"; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_C3; sButInit.y += 22; sButInit.UserData = 3; sButInit.pTip = "Tech:3"; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_AP; sButInit.y = 17; sButInit.UserData = 0; sButInit.pTip = "Any number of players"; sButInit.pDisplay = displayNumPlayersBut; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_2P; sButInit.y += 22; sButInit.UserData = 2; sButInit.pTip = "2 players"; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_4P; sButInit.y += 22; sButInit.UserData = 4; sButInit.pTip = "4 players"; widgAddButton(psRScreen, &sButInit); sButInit.id = M_REQUEST_8P; sButInit.y += 22; sButInit.UserData = 8; sButInit.pTip = "8 players"; widgAddButton(psRScreen, &sButInit); } } void closeMultiRequester() { widgDelete(psRScreen,M_REQUEST); multiRequestUp = FALSE; widgReleaseScreen(psRScreen); // move this to the frontend shutdown... return; } BOOL runMultiRequester(UDWORD id,UDWORD *mode, STRING *chosen,UDWORD *chosenValue) { char tmp[255]; if( id==M_REQUEST_CLOSE) // close { closeMultiRequester(); return TRUE; } if( id>=M_REQUEST_BUT && id<=M_REQUEST_BUTM) // chose a file. { strcpy(chosen,((W_BUTTON *)widgGetFromID(psRScreen,id))->pText ); // if(context == MULTIOP_MAP) // chop off the number of players. // { // strcpy(chosen, strrchr(chosen,')')+1 ); // } *chosenValue = (UDWORD) ((W_BUTTON *)widgGetFromID(psRScreen,id))->pUserData ; closeMultiRequester(); *mode = context; return TRUE; } strcpy(tmp,MultiCustomMapsPath); strcat(tmp,"*.wrf"); if( id == M_REQUEST_C1) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,1,current_numplayers); } if( id == M_REQUEST_C2) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,2,current_numplayers); } if( id == M_REQUEST_C3) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,3,current_numplayers); } if( id == M_REQUEST_AP) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,current_tech,0); } if( id == M_REQUEST_2P) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,current_tech,2); } if( id == M_REQUEST_4P) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,current_tech,4); } if( id == M_REQUEST_8P) { closeMultiRequester(); addMultiRequest(tmp,MULTIOP_MAP,current_tech,8); } // if( id == M_REQUEST_CA) // { // closeMultiRequester(); // addMultiRequest("/multiplay/custommaps/*.wrf",MULTIOP_MAP,0); // } return FALSE; } // //////////////////////////////////////////////////////////////////////////// // Multiplayer in game menu stuff // //////////////////////////////////////////////////////////////////////////// // Display Functions void displayExtraGubbins(UDWORD height) { char str[128]; // draw timer getAsciiTime(str,gameTime); iV_DrawText(str, MULTIMENU_FORM_X+MULTIMENU_C2 ,MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET) ; //draw grid iV_Line(MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y+height, iV_COL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y+height, iV_COL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y+height, iV_COL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y+height, iV_COL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y+height, iV_COL_BLACK); iV_Line(MULTIMENU_FORM_X , MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, MULTIMENU_FORM_X+MULTIMENU_FORM_W, MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, iV_COL_BLACK); //draw titles. iV_SetFont(WFont); // font iV_SetTextColour(-1); //colour iV_DrawText(strresGetString(psStringRes, STR_MUL_ALLIANCES), MULTIMENU_FORM_X+MULTIMENU_C0, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(strresGetString(psStringRes, STR_MUL_SCORE), MULTIMENU_FORM_X+MULTIMENU_C8, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(strresGetString(psStringRes, STR_MUL_KILLS), MULTIMENU_FORM_X+MULTIMENU_C9, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(strresGetString(psStringRes, STR_MUL_PING), MULTIMENU_FORM_X+MULTIMENU_C10, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(strresGetString(psStringRes, STR_MUL_PLAY), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); #ifdef DEBUG sprintf(str,"Traf:%d/%d",NETgetBytesSent(),NETgetBytesRecvd()); iV_DrawText(str, MULTIMENU_FORM_X, MULTIMENU_FORM_Y+MULTIMENU_FORM_H); sprintf(str,"Pack:%d/%d",NETgetPacketsSent(), NETgetPacketsRecvd()); iV_DrawText(str, MULTIMENU_FORM_X+80, MULTIMENU_FORM_Y+MULTIMENU_FORM_H); #endif return; } void displayMultiPlayer(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours) { char str[128]; UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; UDWORD player;//,pl2; iVector Rotation,Position; player = (int)psWidget->pUserData; //get the in game player number. if( responsibleFor(player,0) ) { displayExtraGubbins(widgGetFromID(psWScreen,MULTIMENU_FORM)->height); } iV_SetFont(WFont); // font iV_SetTextColour(-1); //colour if(isHumanPlayer(player) || (game.type == SKIRMISH && player= (MULTIMENU_C0-MULTIMENU_C2-10) ) { str[strlen(str)-1]='\0'; } iV_DrawText(str, x+MULTIMENU_C2, y+MULTIMENU_FONT_OSET); //c3-7 alliance //manage buttons by showing or hiding them. gifts only in campaign, // if(game.type != DMATCH) { if(game.alliance != NO_ALLIANCES) { if(alliances[selectedPlayer][player] == ALLIANCE_FORMED) { if(player != selectedPlayer && !giftsUp[player] ) { widgReveal(psWScreen,MULTIMENU_GIFT_RAD+ player); widgReveal(psWScreen,MULTIMENU_GIFT_RES+ player); widgReveal(psWScreen,MULTIMENU_GIFT_DRO+ player); widgReveal(psWScreen,MULTIMENU_GIFT_POW+ player); giftsUp[player] = TRUE; } } else { if(player != selectedPlayer && giftsUp[player]) { widgHide(psWScreen,MULTIMENU_GIFT_RAD+ player); widgHide(psWScreen,MULTIMENU_GIFT_RES+ player); widgHide(psWScreen,MULTIMENU_GIFT_DRO+ player); widgHide(psWScreen,MULTIMENU_GIFT_POW+ player); giftsUp[player] = FALSE; } } } } } if(isHumanPlayer(player)) { //c8:score, sprintf(str,"%d",getMultiStats(player,TRUE).recentScore); iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); //c9:kills, // if(game.type == DMATCH) // { // sprintf(str,"%d",getMultiStats(player,TRUE).recentKills); // } // else // { sprintf(str,"%d",getMultiStats(player,TRUE).recentKills); // } iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); //c10:ping if(player != selectedPlayer) { if(ingame.PingTimes[player] >2000) { sprintf(str,"***"); } else { sprintf(str,"%d",ingame.PingTimes[player]); } iV_DrawText(str, x+MULTIMENU_C10, y+MULTIMENU_FONT_OSET); } //c11:played sprintf(str,"%d",getMultiStats(player,TRUE).played); iV_DrawText(str, x+MULTIMENU_C11, y+MULTIMENU_FONT_OSET); } else { // estimate of score. sprintf(str,"%d",ingame.skScores[player][0]); iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); // estimated kills sprintf(str,"%d",ingame.skScores[player][1]); iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); } // a droid of theirs. if(apsDroidLists[player]) { pie_SetGeometricOffset( MULTIMENU_FORM_X+MULTIMENU_C1 ,y+MULTIMENU_PLAYER_H); Rotation.x = -15; Rotation.y = 45; Rotation.z = 0; Position.x = 0; Position.y = 0; Position.z = 2000; //scale them! displayComponentButtonObject(apsDroidLists[player],&Rotation,&Position,FALSE, 100); } // clean up widgets if player leaves while menu is up. if(!isHumanPlayer(player) && !(game.type == SKIRMISH && playerpUserData; switch(alliances[selectedPlayer][player]) { case ALLIANCE_BROKEN: a = 0; b = IMAGE_MULTI_NOAL_HI; c = IMAGE_MULTI_NOAL; // replace with real gfx break; case ALLIANCE_FORMED: a = 0; b = IMAGE_MULTI_AL_HI; c = IMAGE_MULTI_AL; // replace with real gfx break; case ALLIANCE_REQUESTED: case ALLIANCE_INVITATION: a = 0; b = IMAGE_MULTI_OFFAL_HI; c = IMAGE_MULTI_OFFAL; // replace with real gfx break; default: a = 0; b = IMAGE_MULTI_NOAL_HI; c = IMAGE_MULTI_NOAL; break; } psWidget->pUserData = (VOID *)PACKDWORD_TRI(a,b,c); intDisplayImageHilight(psWidget, xOffset, yOffset, pColours); psWidget->pUserData = (VOID *)player; } void displayChannelState(struct _widget *psWidget, UDWORD xOffset, UDWORD yOffset, UDWORD *pColours) { UDWORD a,b,c,player; player = (UDWORD) psWidget->pUserData; switch(openchannels[player]) { case 1: a = 0; b = IMAGE_MULTI_CHAN; c = IMAGE_MULTI_CHAN; break; case 0: default: a = 0; b = IMAGE_MULTI_NOCHAN; c = IMAGE_MULTI_NOCHAN; break; } psWidget->pUserData = (VOID *)PACKDWORD_TRI(a,b,c); intDisplayImageHilight(psWidget, xOffset, yOffset, pColours); psWidget->pUserData = (VOID *)player; } // //////////////////////////////////////////////////////////////////////////// void addMultiPlayer(UDWORD player,UDWORD pos) { UDWORD y,id; W_BUTINIT sButInit; W_FORMINIT sFormInit; y = MULTIMENU_PLAYER_H*(pos+1); // this is the top of the pos. id = MULTIMENU_PLAYER+player; // add the whole thing. memset(&sFormInit, 0, sizeof(W_FORMINIT)); sFormInit.formID = MULTIMENU_FORM; sFormInit.id = id; sFormInit.style = WFORM_PLAIN; sFormInit.x = 2; sFormInit.y = (short)y; sFormInit.width = MULTIMENU_FORM_W -4; sFormInit.height = MULTIMENU_PLAYER_H; sFormInit.pDisplay = displayMultiPlayer; sFormInit.pUserData = (VOID *)player; widgAddForm(psWScreen, &sFormInit); //name, //score, //kills, //ping //ALL DONE IN THE DISPLAY FUNC. // add channel opener. if(player != selectedPlayer) { memset(&sButInit, 0, sizeof(W_BUTINIT)); sButInit.formID = id; sButInit.style = WBUT_PLAIN; sButInit.x = MULTIMENU_C0; sButInit.y = 5; sButInit.width = 35; sButInit.height = 24; sButInit.FontID = WFont; sButInit.id = MULTIMENU_CHANNEL + player; sButInit.pTip = "channel"; sButInit.pDisplay = displayChannelState; sButInit.pUserData = (VOID*)player; widgAddButton(psWScreen, &sButInit); } if(game.alliance!=NO_ALLIANCES && player!=selectedPlayer) { //alliance sButInit.x = MULTIMENU_C3; sButInit.y = 5; sButInit.width = 35; sButInit.height = 24; sButInit.FontID = WFont; sButInit.id = MULTIMENU_ALLIANCE_BASE + player; sButInit.pTip = strresGetString(psStringRes,STR_ALLI_STATE); sButInit.pDisplay = displayAllianceState; sButInit.pUserData = (VOID*)player; widgAddButton(psWScreen, &sButInit); sButInit.pDisplay = intDisplayImageHilight; // if(game.type != DMATCH) // { // add the gift buttons. sButInit.y += 1; // move down a wee bit. sButInit.id = MULTIMENU_GIFT_RAD+ player; sButInit.x = MULTIMENU_C4; sButInit.pTip = strresGetString(psStringRes,STR_ALLI_VIS); sButInit.pUserData = (void*)PACKDWORD_TRI(0,IMAGE_MULTI_VIS_HI, IMAGE_MULTI_VIS); widgAddButton(psWScreen, &sButInit); sButInit.id = MULTIMENU_GIFT_RES + player; sButInit.x = MULTIMENU_C5; sButInit.pTip = strresGetString(psStringRes,STR_ALLI_TEC); sButInit.pUserData = (void*)PACKDWORD_TRI(0,IMAGE_MULTI_TEK_HI , IMAGE_MULTI_TEK); widgAddButton(psWScreen, &sButInit); sButInit.id = MULTIMENU_GIFT_DRO + player; sButInit.x = MULTIMENU_C6; sButInit.pTip = strresGetString(psStringRes,STR_ALLI_DRO); sButInit.pUserData = (void*)PACKDWORD_TRI(0,IMAGE_MULTI_DRO_HI , IMAGE_MULTI_DRO); widgAddButton(psWScreen, &sButInit); sButInit.id = MULTIMENU_GIFT_POW + player; sButInit.x = MULTIMENU_C7; sButInit.pTip = strresGetString(psStringRes,STR_ALLI_POW); sButInit.pUserData = (void*)PACKDWORD_TRI(0,IMAGE_MULTI_POW_HI , IMAGE_MULTI_POW); widgAddButton(psWScreen, &sButInit); giftsUp[player] = TRUE; // note buttons are up! // } } } BOOL intAddMultiMenu(VOID) { W_FORMINIT sFormInit; W_BUTINIT sButInit; UDWORD i,pos = 0,formHeight=0; //check for already open. if(widgGetFromID(psWScreen,MULTIMENU_FORM)) { intCloseMultiMenu(); return TRUE; } intResetScreen(FALSE); // calculate required height. formHeight = MULTIMENU_PLAYER_H+7; for(i=0;idisplay = intClosePlainForm; Form->pUserData = (void*)0; // Used to signal when the close anim has finished. Form->disableChildren = TRUE; ClosingMultiMenu = TRUE; MultiMenuUp = FALSE; } //intCloseMultiMenuNoAnim(); intMode = INT_NORMAL; return TRUE; } // //////////////////////////////////////////////////////////////////////////// // In Game Options house keeping stuff. BOOL intRunMultiMenu(VOID) { return TRUE; } // //////////////////////////////////////////////////////////////////////////// BOOL intCheckAllianceValid( UBYTE player1, UBYTE player2 ) { UBYTE i, iAlliances, iHumanPlayers; /* only interested in teamplay */ if ( bMultiPlayer && game.type != TEAMPLAY ) { return TRUE; } /* throw out currently allied or human/computer alliances */ if ( (player1 == player2) || aiCheckAlliances( player1, player2 ) || !(isHumanPlayer(player1) && isHumanPlayer(player2)) ) { return FALSE; } /* get num human players */ iHumanPlayers = 0; for( i=0;i= iHumanPlayers-2 ) { return FALSE; } return TRUE; } // //////////////////////////////////////////////////////////////////////////// // process clicks made by user. VOID intProcessMultiMenu(UDWORD id) { UBYTE i; //close if (id == MULTIMENU_CLOSE) { intCloseMultiMenu(); } //alliance button if(id >=MULTIMENU_ALLIANCE_BASE && id=MULTIMENU_CHANNEL && id= MULTIMENU_GIFT_RAD && id< MULTIMENU_GIFT_RAD +MAX_PLAYERS) { sendGift(RADAR_GIFT, id - MULTIMENU_GIFT_RAD); } // research gift if(id >= MULTIMENU_GIFT_RES && id= MULTIMENU_GIFT_DRO && id< MULTIMENU_GIFT_DRO +MAX_PLAYERS) { sendGift(DROID_GIFT, id - MULTIMENU_GIFT_DRO); } //power gift if(id >= MULTIMENU_GIFT_POW && id< MULTIMENU_GIFT_POW +MAX_PLAYERS) { sendGift(POWER_GIFT, id - MULTIMENU_GIFT_POW); } } ////////////////////////////////////////////////////////////////////////////// /* void intDisplayMiniMultiMenu(void) { SDWORD sc[MAX_PLAYERS]; SDWORD scp[MAX_PLAYERS]; UDWORD j,i,temp; UDWORD x = RADTLX; UDWORD y = RADTLY - 60; UDWORD w = RADWIDTH; UDWORD h = 50; UDWORD players = 0; STRING sTmp[64]; if( ingame.localJoiningInProgress) { RenderWindowFrame(&FrameNormal,x, y ,w, h); // draw a wee blu box. // display how far done.. sprintf(sTmp,"%d%%", PERCENT(arenaPlayersReceived,MAX_PLAYERS) ); iV_DrawText(sTmp, x+(w/2)-10, y+(h/2)+3); } else { for(i=0;ii;--j) { if (sc[j-1] > sc[j]) { temp = sc[j]; sc[j] = sc[j-1]; sc[j-1] = temp; temp = scp[j]; scp[j] = scp[j-1]; scp[j-1] = temp; // swap players too. } } } for(j=0;(scp[j] != (SDWORD)selectedPlayer) && (j= RADWIDTH-20 ) { sTmp[strlen(sTmp)-1]='\0'; } iV_DrawText(sTmp, x + 16, y + 13); if(players >1) { iV_DrawText("2",x+5,y+26); strcpy(sTmp,getPlayerName(scp[6])); while(iV_GetTextWidth(sTmp) >= RADWIDTH-20 ) { sTmp[strlen(sTmp)-1]='\0'; } iV_DrawText(sTmp, x + 16, y + 26); } if(players >2) { if(j!=7 && j!=6) { sprintf(sTmp,"%d",8-j); iV_DrawText(sTmp, x + 5, y + 39); strcpy(sTmp,getPlayerName(scp[selectedPlayer])); while(iV_GetTextWidth(sTmp) >= RADWIDTH-20 ) { sTmp[strlen(sTmp)-1]='\0'; } iV_DrawText(sTmp, x + 16, y + 39); } else { iV_DrawText("3",x+5,y+39); strcpy(sTmp,getPlayerName(scp[5])); while(iV_GetTextWidth(sTmp) >= RADWIDTH-20 ) { sTmp[strlen(sTmp)-1]='\0'; } iV_DrawText(sTmp, x + 16, y + 39); } } } return; } */