// Post: the NetState for all players is NetState_interBattle static BOOLEAN GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships) { COUNT playerI; BOOLEAN ok; GETMELEE_STATE gmstate; TimeCount now; COUNT i; #ifdef NETPLAY for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn; if ((playerMask & (1 << playerI)) == 0) continue; // XXX: This does not have to be done per connection. conn = netConnections[playerI]; if (conn != NULL) { BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData (conn); battleStateData->getMeleeState = &gmstate; } } #endif ok = true; now = GetTimeCounter (); gmstate.InputFunc = DoGetMelee; gmstate.Initialized = FALSE; for (i = 0; i < NUM_PLAYERS; ++i) { // We have to use TFB_Random() results in specific order playerI = GetPlayerOrder (i); gmstate.player[playerI].selecting = (playerMask & (1 << playerI)) != 0; gmstate.player[playerI].ships_left = battle_counter[playerI]; // We determine in advance which ship would be chosen if the player // wants a random ship, to keep it simple to keep network parties // synchronised. gmstate.player[playerI].randomIndex = (COUNT)TFB_Random () % gmstate.player[playerI].ships_left; gmstate.player[playerI].done = FALSE; if (!gmstate.player[playerI].selecting) continue; gmstate.player[playerI].timeIn = now; gmstate.player[playerI].row = 0; gmstate.player[playerI].col = NUM_PICKMELEE_COLUMNS; #ifdef NETPLAY gmstate.player[playerI].remoteSelected = FALSE; #endif gmstate.player[playerI].flashContext = Flash_createHighlight (ScreenContext, NULL); Flash_setMergeFactors (gmstate.player[playerI].flashContext, 2, 3, 2); Flash_setFrameTime (gmstate.player[playerI].flashContext, ONE_SECOND / 16); #ifdef NETPLAY if (PlayerControl[playerI] & NETWORK_CONTROL) Flash_setSpeed (gmstate.player[playerI].flashContext, ONE_SECOND / 2, 0, ONE_SECOND / 2, 0); else #endif { Flash_setSpeed (gmstate.player[playerI].flashContext, 0, ONE_SECOND / 16, 0, ONE_SECOND / 16); } PickMelee_ChangedSelection (&gmstate, playerI); Flash_start (gmstate.player[playerI].flashContext); } #ifdef NETPLAY { // NB. gmstate.player[].randomIndex and gmstate.player[].done must // be initialised before negotiateReadyConnections is completed, to // ensure that they are initialised when the SelectShip packet // arrives. bool allOk = negotiateReadyConnections (true, NetState_selectShip); if (!allOk) { // Some network connection has been reset. ok = false; } } #endif SetDefaultMenuRepeatDelay (); SetContext (OffScreenContext); DoInput (&gmstate, FALSE); WaitForSoundEnd (0); for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { if (!gmstate.player[playerI].selecting) continue; if (gmstate.player[playerI].done) { // Flash rectangle is already terminated. ships[playerI] = gmstate.player[playerI].hBattleShip; } else { Flash_terminate (gmstate.player[playerI].flashContext); gmstate.player[playerI].flashContext = NULL; ok = false; } } #ifdef NETPLAY if (ok) { if (!negotiateReadyConnections (true, NetState_interBattle)) ok = false; } else setStateConnections (NetState_interBattle); #endif if (!ok) { // Aborting. GLOBAL (CurrentActivity) &= ~IN_BATTLE; } #ifdef NETPLAY for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn; if ((playerMask & (1 << playerI)) == 0) continue; // XXX: This does not have to be done per connection. conn = netConnections[playerI]; if (conn != NULL && NetConnection_isConnected (conn)) { BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData (conn); battleStateData->getMeleeState = NULL; } } #endif return ok; }
static BOOLEAN RestartMenu (MENU_STATE *pMS) { TimeCount TimeOut; ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); SetContext (ScreenContext); GLOBAL (CurrentActivity) |= CHECK_ABORT; if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP) && !GET_GAME_STATE (UTWIG_BOMB)) { // player blew himself up with Utwig bomb SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); SleepThreadUntil (FadeScreen (FadeAllToWhite, ONE_SECOND / 8) + ONE_SECOND / 60); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); ClearDrawable (); FlushColorXForms (); TimeOut = ONE_SECOND / 8; } else { TimeOut = ONE_SECOND / 2; if (LOBYTE (LastActivity) == WON_LAST_BATTLE) { GLOBAL (CurrentActivity) = WON_LAST_BATTLE; Victory (); Credits (TRUE); FreeGameData (); GLOBAL (CurrentActivity) = CHECK_ABORT; } } LastActivity = 0; NextActivity = 0; // TODO: This fade is not always necessary, especially after a splash // screen. It only makes a user wait. SleepThreadUntil (FadeScreen (FadeAllToBlack, TimeOut)); if (TimeOut == ONE_SECOND / 8) SleepThread (ONE_SECOND * 3); pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); DrawRestartMenuGraphic (pMS); GLOBAL (CurrentActivity) &= ~CHECK_ABORT; SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT); SetDefaultMenuRepeatDelay (); DoInput (pMS, TRUE); StopMusic (); if (pMS->hMusic) { DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } Flash_terminate (pMS->flashContext); pMS->flashContext = 0; DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); pMS->CurFrame = 0; if (GLOBAL (CurrentActivity) == (ACTIVITY)~0) return (FALSE); // timed out if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); // quit TimeOut = FadeScreen (FadeAllToBlack, ONE_SECOND / 2); SleepThreadUntil (TimeOut); FlushColorXForms (); SeedRandomNumbers (); return (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE); }
/* TODO: Include player timeouts */ static BOOLEAN DoGetMelee (GETMELEE_STATE *gms) { BOOLEAN done; COUNT playerI; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); if (!gms->Initialized) { gms->Initialized = TRUE; return TRUE; } for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { if (!gms->player[playerI].selecting) continue; if (!gms->player[playerI].done) Flash_process (gms->player[playerI].flashContext); } SleepThread (ONE_SECOND / 120); #ifdef NETPLAY netInput (); if (!allConnected ()) goto aborted; #endif if (GLOBAL (CurrentActivity) & CHECK_ABORT) goto aborted; done = TRUE; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { if (!gms->player[playerI].selecting) continue; if (!gms->player[playerI].done) { if (!PlayerInput[playerI]->handlers->selectShip ( PlayerInput[playerI], gms)) goto aborted; if (gms->player[playerI].done) { Flash_terminate (gms->player[playerI].flashContext); gms->player[playerI].flashContext = NULL; } else done = FALSE; } } #ifdef NETPLAY flushPacketQueues (); #endif return !done; aborted: #ifdef NETPLAY flushPacketQueues (); #endif for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { if (!gms->player[playerI].selecting) continue; gms->player[playerI].choice = 0; gms->player[playerI].hBattleShip = 0; } GLOBAL (CurrentActivity) &= ~CHECK_ABORT; return FALSE; }