static void ReplaceStringFlagWindowed( char *caption, char flag, bool windowed ) { if( windowed ) { LPREPLACESTRINGFLAG( flag, LANGUAGEPHRASE("dialog_windowed"), caption ); } else { LPREPLACESTRINGFLAG( flag, LANGUAGEPHRASE("dialog_fullscreen"), caption ); } }
void ConnectingWindow::RenderTimeRemaining( float _fractionDone ) { static float s_timeRemaining = 0; static float s_timer = 0; float timeNow = GetHighResTime(); if( timeNow > s_timer + 0.5f ) { s_timer = timeNow; float timeSoFar = timeNow - m_stageStartTime; float timeForOnePercent = timeSoFar/_fractionDone; float percentRemaining = 1.0f - _fractionDone; s_timeRemaining = percentRemaining * timeForOnePercent; } if( s_timeRemaining > 0 && s_timeRemaining < 100000 ) { int minutes = int(s_timeRemaining / 60.0f); int seconds = s_timeRemaining - minutes * 60; char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_state_time_remaining") ); LPREPLACEINTEGERFLAG( 'M', minutes, caption ); char number[32]; sprintf( number, "%02d", seconds ); LPREPLACESTRINGFLAG( 'S', number, caption ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + m_h - 60, White, 14, caption ); } }
static void ReplaceStringFlagColorBit( char *caption, char flag, int colourDepth ) { if( colourDepth == 16 ) { LPREPLACESTRINGFLAG( flag, LANGUAGEPHRASE("dialog_colourdepth_16"), caption ); } else if( colourDepth == 24 ) { LPREPLACESTRINGFLAG( flag, LANGUAGEPHRASE("dialog_colourdepth_24"), caption ); } else if( colourDepth == 32 ) { LPREPLACESTRINGFLAG( flag, LANGUAGEPHRASE("dialog_colourdepth_32"), caption ); } else { char numberBit[128]; sprintf( numberBit, LANGUAGEPHRASE("dialog_colourdepth_X") ); LPREPLACEINTEGERFLAG( 'C', colourDepth, numberBit ); LPREPLACESTRINGFLAG( flag, numberBit, caption ); } }
void CasualtiesWindow::Render( bool hasFocus ) { InterfaceWindow::Render( hasFocus ); g_renderer->SetClip( m_x, m_y+20, m_w, m_h-20 ); int x = m_x + 10; int y = m_y + 30; int titleSize = 18; int textSize = 13; y-= m_scrollbar->m_currentValue; g_renderer->TextSimple( x, y, White, titleSize, LANGUAGEPHRASE("dialog_casualties_city") ); g_renderer->TextSimple( x+200, y, White, titleSize, LANGUAGEPHRASE("dialog_casualties_strikes") ); g_renderer->TextSimple( x+300, y, White, titleSize, LANGUAGEPHRASE("dialog_casualties_deaths") ); y+=20; int numEntries = 0; for( int i = 0; i < g_app->GetWorld()->m_cities.Size(); ++i ) { if( g_app->GetWorld()->m_cities.ValidIndex(i) ) { City *city = g_app->GetWorld()->m_cities[i]; if( city->m_dead > 0 ) { char strikes[64]; char deaths[64]; sprintf( strikes, "%d", city->m_numStrikes ); sprintf( deaths, LANGUAGEPHRASE("dialog_casualties_in_million") ); char number[32]; sprintf( number, "%.1f", city->m_dead / 1000000.0f ); LPREPLACESTRINGFLAG( 'C', number, deaths ); g_renderer->TextSimple( x, y+=18, White, textSize, LANGUAGEPHRASEADDITIONAL(city->m_name) ); g_renderer->TextSimple( x+200, y, White, textSize, strikes ); g_renderer->TextSimple( x+300, y, White, textSize, deaths ); ++numEntries; } } } g_renderer->ResetClip(); m_scrollbar->SetNumRows( (numEntries+1) * 18 ); }
void CeaseFireWindow::Render( bool hasFocus ) { InterfaceWindow::Render( hasFocus ); char msg[1024]; char *helpMessage = NULL; if( g_app->GetWorld()->GetMyTeam()->m_ceaseFire[m_teamId] ) { strcpy( msg, LANGUAGEPHRASE("dialog_declarewar")); LPREPLACESTRINGFLAG('T', g_app->GetWorld()->GetTeam( m_teamId )->GetTeamName(), msg ); helpMessage = LANGUAGEPHRASE("tooltip_ceasefire_disable" ); } else { strcpy( msg, LANGUAGEPHRASE("dialog_ceasefire")); LPREPLACESTRINGFLAG('T', g_app->GetWorld()->GetTeam( m_teamId )->GetTeamName(), msg ); helpMessage = LANGUAGEPHRASE("tooltip_ceasefire_enable" ); } g_renderer->TextCentreSimple( m_x+m_w/2, m_y+25, White, 17, msg ); // // Render tooltip float xPos = m_x + 30; float yPos = m_y + 40; float w = m_w - 60; MultiLineText wrapped( helpMessage, w, 11 ); for( int i = 0; i < wrapped.Size(); ++i ) { char *thisString = wrapped[i]; g_renderer->TextSimple( xPos, yPos+=13, White, 11, thisString ); } }
void Interface::Render() { g_renderer->SetBlendMode( Renderer::BlendModeNormal ); g_renderer->SetFont( "kremlin" ); bool connectionScrewed = EclGetWindow("Connection Status"); if( !connectionScrewed ) { // // Network warning messages int myClientId = g_app->GetClientToServer()->m_clientId; if( !g_app->GetClientToServer()->IsSynchronised( myClientId ) ) { Colour col( 255, 50, 50, 255 ); float size = ( g_windowManager->WindowW() / 20.0f ); float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.2f; g_renderer->TextCentreSimple( xPos, yPos, col, size, LANGUAGEPHRASE("dialog_synchronisation_error") ); if( !EclGetWindow("Resynchronise" )) { EclRegisterWindow( new ResynchroniseWindow() ); } } if( g_app->GetClientToServer()->IsConnected() && g_app->GetClientToServer()->m_connectionState == ClientToServer::StateConnected ) { Colour col( 255, 50, 50, 255 ); float size = ( g_windowManager->WindowW() / 20.0f ); float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.3f; float yPos2 = g_windowManager->WindowH()*0.4f; static int s_connectionProblem = 0; // 0=no, 1=yes, 2=recovery static float s_maxLatency = 0.0f; static float s_connProblemDetected = -1.0f; float estimatedLatency = g_app->GetClientToServer()->GetEstimatedLatency(); if( !g_app->m_gameRunning ) s_connProblemDetected = -1.0f; if( s_connectionProblem == 0 && estimatedLatency > 5.0f ) { // Connection problem beginning s_connectionProblem = 1; s_maxLatency = 5.0f; } else if( s_connectionProblem == 1 ) { if( estimatedLatency < 1.0f ) { s_connectionProblem = 0; } else { // Connection problem getting worse float timeNow = GetHighResTime(); if( s_connProblemDetected < 0.0f ) s_connProblemDetected = timeNow; if( timeNow-s_connProblemDetected > 2.0f ) { col.m_a = 255.0f * min( 1.0f, timeNow-s_connProblemDetected-2.0f ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_connection_problem_seconds") ); LPREPLACEINTEGERFLAG( 'S', int(estimatedLatency), caption ); g_renderer->TextCentreSimple( xPos, yPos, col, size, caption ); } s_maxLatency = max( s_maxLatency, estimatedLatency ); float maxLat = s_maxLatency; float estLat = estimatedLatency; if( estimatedLatency < s_maxLatency - 1.0f ) { s_connectionProblem = 2; if( !EclGetWindow("Connection Status") ) { EclRegisterWindow( new ConnectingWindow() ); } } } } else if( s_connectionProblem == 2 ) { if( estimatedLatency < 1.0f ) { s_connectionProblem = 0; } else { // Connection problem recovering if( estimatedLatency > s_maxLatency + 3 ) { s_connectionProblem = 1; } else if( !EclGetWindow( "Connection Status") ) { s_connectionProblem = 0; s_maxLatency = 0.0f; } } } if( !g_app->GetServer() ) { int packetLoss = g_app->GetClientToServer()->CountPacketLoss(); int totalBad = packetLoss * 4 + estimatedLatency * 10; Clamp( totalBad, 0, 20 ); int red = totalBad*12; int green = 255 - red; col.Set(red,green,0,255); g_renderer->RectFill( 5, 5, 13, 13, col ); g_renderer->SetFont(); float yPos = 20; if( estimatedLatency > 1.0f ) { g_renderer->Text( 5, yPos, Colour(255,0,0,255), 12, LANGUAGEPHRASE("dialog_high_latency") ); yPos += 13; } if( packetLoss > 2 ) { g_renderer->Text( 5, yPos, Colour(255,0,0,255), 12, LANGUAGEPHRASE("dialog_high_packet_loss") ); } g_renderer->SetFont( "kremlin" ); } } if( m_message ) { float timeOnScreen = GetHighResTime() - m_messageTimer; if( timeOnScreen < 5.0f ) { char msg[256]; sprintf( msg, m_message ); float fractionShown = timeOnScreen/1.5f; if( fractionShown < 1.0f ) msg[ int(strlen(msg) * fractionShown) ] = '\x0'; float alpha = 1.0f; if( timeOnScreen > 4.0f ) alpha = 5.0f - timeOnScreen; alpha = max(alpha, 0.0f); alpha *= 255; Colour col( 255, 255, 255, alpha ); float size = ( g_windowManager->WindowW() / 12.0f ); float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.8f; float textWidth = g_renderer->TextWidth( m_message, size ); if( textWidth > g_windowManager->WindowW() ) { // message is longer than the window size, rescale it size *= g_windowManager->WindowW() / textWidth * 0.95f; textWidth = g_renderer->TextWidth( m_message, size ); } g_renderer->TextSimple( xPos-textWidth/2.0f, yPos, col, size, msg ); } else { delete m_message; m_message = NULL; } } // // Render Defcon counter (if applicable) if( g_app->m_gameRunning && g_app->GetWorld()->GetDefcon() > 1 && !m_message ) { int currentDefcon = g_app->GetWorld()->GetDefcon(); int minutes = g_app->GetWorld()->m_defconTime[ currentDefcon-1 ] - (g_app->GetWorld()->m_theDate.GetMinutes() + 1); int seconds = 60 - g_app->GetWorld()->m_theDate.GetSeconds(); if( seconds == 60 ) { minutes += 1; seconds = 0; } char msg[256]; sprintf( msg, LANGUAGEPHRASE("dialog_defcon_x_in_x_time") ); LPREPLACEINTEGERFLAG( 'D', currentDefcon - 1, msg ); LPREPLACEINTEGERFLAG( 'M', minutes, msg ); char number[32]; sprintf( number, "%02d", seconds ); LPREPLACESTRINGFLAG( 'S', number, msg ); float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.8f; float size = ( g_windowManager->WindowW() / 30.0f ); g_renderer->TextCentre(xPos, yPos, Colour(255,0,0,255), size, msg ); // If Defcon 3 is nearly here and we still have units left, give us some prompting if( currentDefcon == 4 ) { Team *myTeam = g_app->GetWorld()->GetMyTeam(); if( myTeam ) { int totalUnits = 0; for( int i = 0; i < WorldObject::NumObjectTypes; ++i ) { totalUnits += myTeam->m_unitsAvailable[i]; } if( totalUnits > 0 ) { yPos += size; size *= 0.35f; g_renderer->TextCentre( xPos, yPos, Colour(255,0,0,255), size, LANGUAGEPHRASE("message_placeunits") ); } } } } // // Render victory timer (if applicable) float victoryTimer = g_app->GetGame()->m_victoryTimer.DoubleValue(); if( victoryTimer > 0.0f ) { int minutes = victoryTimer / 60; int seconds = victoryTimer - minutes * 60; float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.75f; float size = ( g_windowManager->WindowW() / 30.0f ); char caption[256]; sprintf( caption, LANGUAGEPHRASE("dialog_time_remaining") ); LPREPLACEINTEGERFLAG( 'M', minutes, caption ); char number[32]; sprintf( number, "%02d", seconds ); LPREPLACESTRINGFLAG( 'S', number, caption ); g_renderer->TextCentre( xPos, yPos, Colour(255,0,0,255), size, caption ); } else if( victoryTimer == 0.0f ) { float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.75f; float size = ( g_windowManager->WindowW() / 30.0f ); g_renderer->TextCentre( xPos, yPos, Colour(255,0,0,255), size, LANGUAGEPHRASE("dialog_gameover") ); } if( g_app->m_gameRunning ) { if( g_app->GetWorld()->GetTimeScaleFactor() == 0 && g_app->GetGame()->m_winner == -1 ) { float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.5f; float size = ( g_windowManager->WindowW() / 20.0f ); g_renderer->TextCentreSimple( xPos, yPos, White, size, LANGUAGEPHRASE("dialog_paused") ); } } if( g_app->m_gameRunning && g_app->GetMapRenderer()->GetAutoCam() ) { g_renderer->TextSimple( 10.0f, 10.0f, White, 20, LANGUAGEPHRASE("dialog_autocam") ); } } // // Test Bed stuff #ifdef TESTBED if( g_app->GetServer() ) { float xPos = g_windowManager->WindowW()/2.0f; float yPos = g_windowManager->WindowH()*0.4f; float size = ( g_windowManager->WindowW() / 12.0f ); char *modPath = g_preferences->GetString( "ModPath" ); g_renderer->TextCentreSimple( xPos, yPos, White, size, "SERVER" ); g_renderer->TextCentreSimple( xPos, yPos+size, White, size/3, modPath ); ProfiledElement *element = g_profiler->m_rootElement->m_children.GetData( "Server Main Loop" ); if( element && element->m_lastNumCalls > 0 ) { float percent = element->m_lastNumCalls * 10.0f; g_renderer->TextCentre( xPos, yPos + size*3, White, size, "%d%%", (int)percent ); } } #endif // // Version //if( !g_app->m_gameRunning ) //{ // char caption[256]; // sprintf( caption, "%s %s", APP_NAME, APP_VERSION ); // float width = g_renderer->TextWidth( caption, 12 ); // g_renderer->RectFill( 18, 3, 4+width, 15, Colour(0,0,0,150) ); // g_renderer->SetFont(); // g_renderer->TextSimple( 20, 5, White, 12, caption ); // g_renderer->SetFont( "kremlin" ); //} #ifdef NON_PLAYABLE g_renderer->Text( 10, 40,Colour(255,50,50,255), 20, LANGUAGEPHRASE("dialog_non_playable_demo") ); #endif if( g_preferences->GetInt( PREFS_NETWORKTRACKSYNCRAND )) { g_renderer->Text( 10, 60, Colour(255,50,50,255), 20, LANGUAGEPHRASE("dialog_tracking_synchronisation") ); } g_renderer->SetFont(); }
void Render( int realX, int realY, bool highlighted, bool clicked ) { AlliancesWindow *parent = (AlliancesWindow *)m_parent; int voteId = parent->m_votes[m_voteIndex]; Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote( voteId ); Team *myTeam = g_app->GetWorld()->GetMyTeam(); if( vote ) { g_renderer->RectFill( realX, realY, m_w, m_h, Colour(10,10,50,200) ); Colour borderCol(255,255,255,100); if( highlighted || clicked ) { borderCol.m_a = 255; g_renderer->RectFill( realX, realY, m_w, m_h, Colour(100,100,150,100) ); } g_renderer->Rect( realX, realY, m_w, m_h, borderCol ); switch( vote->m_voteType ) { case Vote::VoteTypeJoinAlliance: if( myTeam->m_teamId == vote->m_createTeamId ) { char *allianceName = g_app->GetWorld()->GetAllianceName(vote->m_voteData); g_renderer->TextSimple( realX+10, realY+5, White, 14, LANGUAGEPHRASE("dialog_you_requested_alliance_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_alliance_2") ); LPREPLACESTRINGFLAG( 'A', allianceName, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 14, caption ); } else { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_alliance_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextSimple( realX+10, realY+5, White, 15, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, LANGUAGEPHRASE("dialog_requested_alliance_2") ); } break; case Vote::VoteTypeKickPlayer: { Team *kickTeam = g_app->GetWorld()->GetTeam(vote->m_voteData); if( myTeam->m_teamId == vote->m_createTeamId ) { g_renderer->TextSimple( realX+10, realY+5, White, 15, LANGUAGEPHRASE("dialog_you_requested_kick_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, caption ); } else { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextSimple( realX+10, realY+5, White, 15, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, caption ); } break; } } int yes, no, abstain; vote->GetCurrentVote( &yes, &no, &abstain ); g_renderer->Text( realX + 190, realY + 12, White, 17, "%ds", int(vote->m_timer) ); g_renderer->TextSimple( realX + m_w - 70, realY + 5, White, 10, LANGUAGEPHRASE("dialog_vote_yes") ); g_renderer->TextSimple( realX + m_w - 70, realY + 15, White, 10, LANGUAGEPHRASE("dialog_vote_no") ); g_renderer->TextSimple( realX + m_w - 70, realY + 25, White, 10, LANGUAGEPHRASE("dialog_vote_abstain") ); g_renderer->Text( realX + m_w - 20, realY + 5, White, 10, "%d", yes ); g_renderer->Text( realX + m_w - 20, realY + 15, White, 10, "%d", no ); g_renderer->Text( realX + m_w - 20, realY + 25, White, 10, "%d", abstain ); } }
void VotingWindow::Render( bool _hasFocus ) { InterfaceWindow::Render( _hasFocus ); Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote(m_voteId); if( vote ) { Team *myTeam = g_app->GetWorld()->GetMyTeam(); switch( vote->m_voteType ) { case Vote::VoteTypeJoinAlliance: if( myTeam->m_teamId == vote->m_createTeamId ) { char *allianceName = g_app->GetWorld()->GetAllianceName(vote->m_voteData); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, LANGUAGEPHRASE("dialog_you_requested_alliance_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_alliance_2") ); LPREPLACESTRINGFLAG( 'A', allianceName, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } else if( myTeam->m_allianceId == vote->m_voteData ) { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_alliance_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, LANGUAGEPHRASE("dialog_requested_alliance_2") ); } break; case Vote::VoteTypeKickPlayer: { Team *kickTeam = g_app->GetWorld()->GetTeam(vote->m_voteData); if( myTeam->m_teamId == vote->m_createTeamId ) { g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, LANGUAGEPHRASE("dialog_you_requested_kick_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } else if( myTeam->m_allianceId == kickTeam->m_allianceId && myTeam->m_teamId != kickTeam->m_teamId ) { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } break; } } g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 90, White, 20, LANGUAGEPHRASE("dialog_vote_yes") ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 120, White, 20, LANGUAGEPHRASE("dialog_vote_no") ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 150, White, 20, LANGUAGEPHRASE("dialog_vote_abstain") ); g_renderer->SetFont(); int yes, no, abstain; vote->GetCurrentVote( &yes, &no, &abstain ); g_renderer->Text( m_x + m_w - 40, m_y + 90, White, 20, "%d", yes ); g_renderer->Text( m_x + m_w - 40, m_y + 120, White, 20, "%d", no ); g_renderer->Text( m_x + m_w - 40, m_y + 150, White, 20, "%d", abstain ); if( vote->m_result == Vote::VoteUnknown ) { char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_vote_seconds_to_vote") ); LPREPLACEINTEGERFLAG( 'S', (int) vote->m_timer, caption ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + m_h - 70, White, 15, caption ); int votesRequired = vote->GetVotesRequired(); sprintf( caption, LANGUAGEPHRASE("dialog_vote_number_votes_required") ); LPREPLACEINTEGERFLAG( 'V', votesRequired, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 50, White, 15, caption ); } else if( vote->m_result == Vote::VoteYes ) { g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 70, White, 30, LANGUAGEPHRASE("dialog_vote_succeeded") ); g_renderer->SetFont(); } else if( vote->m_result == Vote::VoteNo ) { g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 70, White, 30, LANGUAGEPHRASE("dialog_vote_failed") ); g_renderer->SetFont(); } } }
void Vote::Finish( int _result ) { GetCurrentVote( &m_resultYes, &m_resultNo, &m_resultAbstain ); m_result = _result; if( m_result == VoteYes ) { Team *team = NULL; char msg[512]; switch( m_voteType ) { case VoteTypeJoinAlliance: { team = g_app->GetWorld()->GetTeam( m_createTeamId ); team->m_allianceId = m_voteData; team->m_alwaysSolo = false; sprintf( msg, LANGUAGEPHRASE("message_alliance_join") ); LPREPLACESTRINGFLAG('P', team->GetTeamName(), msg); char *allianceName = g_app->GetWorld()->GetAllianceName(m_voteData); LPREPLACESTRINGFLAG('N', allianceName, msg ); break; } case VoteTypeKickPlayer: { team = g_app->GetWorld()->GetTeam( m_voteData ); sprintf( msg, LANGUAGEPHRASE("message_alliance_kicked") ); LPREPLACESTRINGFLAG('P', team->GetTeamName(), msg); char *allianceName = g_app->GetWorld()->GetAllianceName(team->m_allianceId); LPREPLACESTRINGFLAG('N', allianceName, msg ); team->m_allianceId = g_app->GetWorld()->FindFreeAllianceId(); break; } case VoteTypeLeaveAlliance: { team = g_app->GetWorld()->GetTeam( m_voteData ); sprintf( msg, LANGUAGEPHRASE("message_alliance_leave") ); LPREPLACESTRINGFLAG('P', team->GetTeamName(), msg); char *allianceName = g_app->GetWorld()->GetAllianceName(team->m_allianceId); LPREPLACESTRINGFLAG('N', allianceName, msg ); for( int i = 0; i < MAX_TEAMS; ++i ) { Team *allianceTeam = g_app->GetWorld()->GetTeam( i ); if( allianceTeam ) { if( team->m_allianceId == allianceTeam->m_allianceId ) { team->m_leftAllianceTimer[i] = GetHighResTime(); } } } team->m_allianceId = g_app->GetWorld()->FindFreeAllianceId(); break; } } strupr( msg ); g_app->GetInterface()->ShowMessage( 0, 0, -1, msg, true ); if( g_app->m_hidden ) { g_app->GetStatusIcon()->SetCaption( msg ); g_app->GetStatusIcon()->SetSubIcon( STATUS_ICON_EVENT ); } g_resource->DeleteDisplayList( "MapCountryControl" ); // // Update everyones CeaseFire status // Update everyones radar sharing // Note : we only ever turn off radar sharing. We never turn it on by default for(int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *thisTeam = g_app->GetWorld()->m_teams[i]; bool isAFriend = thisTeam->m_teamId != team->m_teamId && g_app->GetWorld()->IsFriend( team->m_teamId, thisTeam->m_teamId ); team->m_ceaseFire[thisTeam->m_teamId] = isAFriend; thisTeam->m_ceaseFire[team->m_teamId] = isAFriend; if( !isAFriend ) { team->m_sharingRadar[thisTeam->m_teamId] = isAFriend; thisTeam->m_sharingRadar[team->m_teamId] = isAFriend; } } } }
void NetworkWindow::Render( bool hasFocus ) { InterfaceWindow::Render( hasFocus ); int y = m_y+15; int h = 15; if( g_app->GetServer() ) { char caption[128]; char number[32]; sprintf( caption, LANGUAGEPHRASE("dialog_network_server_seqid") ); LPREPLACEINTEGERFLAG( 'S', g_app->GetServer()->m_sequenceId, caption ); g_renderer->TextSimple( m_x + 10, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_server_send") ); sprintf( number, "%2.1f", g_app->GetServer()->m_sendRate/1024.0f ); LPREPLACESTRINGFLAG( 'R', number, caption ); g_renderer->TextSimple( m_x + 10, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_server_receive") ); sprintf( number, "%2.1f", g_app->GetServer()->m_receiveRate/1024.0f ); LPREPLACESTRINGFLAG( 'R', number, caption ); g_renderer->TextSimple( m_x + 10, y+=h, White, 12, caption ); g_renderer->Line( m_x + 10, y + 20, m_x + m_w - 10, y + 20, White, 1 ); int clientX = m_x + 20; int ipX = clientX + 60; int seqX = ipX + 140; int playerX = seqX + 60; int lagX = playerX + 150; int syncX = lagX + 90; y+=h*2; g_renderer->TextSimple( clientX, y, White, 14, LANGUAGEPHRASE("dialog_network_id") ); g_renderer->TextSimple( ipX, y, White, 14, LANGUAGEPHRASE("dialog_network_ip_port") ); g_renderer->TextSimple( seqX, y, White, 14, LANGUAGEPHRASE("dialog_network_seqid") ); g_renderer->TextSimple( playerX, y, White, 14, LANGUAGEPHRASE("dialog_network_name") ); g_renderer->TextSimple( lagX, y, White, 14, LANGUAGEPHRASE("dialog_network_status") ); y+=h*2; int maxClients = g_app->GetGame()->GetOptionValue("MaxTeams") + g_app->GetGame()->GetOptionValue("MaxSpectators"); for( int i = 0; i < maxClients; ++i ) { if( g_app->GetServer()->m_clients.ValidIndex(i) ) { ServerToClient *sToc = g_app->GetServer()->m_clients[i]; char netLocation[256]; sprintf( netLocation, "%s:%d", sToc->m_ip, sToc->m_port); char caption[256]; Colour col; float timeBehind = GetHighResTime() - sToc->m_lastMessageReceived; if( timeBehind > 2.0f ) { col.Set( 255, 0, 0, 255 ); sprintf( caption, LANGUAGEPHRASE("dialog_network_lost_con") ); LPREPLACEINTEGERFLAG( 'S', (int)timeBehind, caption ); } else if( !sToc->m_caughtUp ) { col.Set( 200, 200, 30, 255 ); int percent = 100 * (sToc->m_lastKnownSequenceId / (float)g_app->GetServer()->m_sequenceId); sprintf( caption, LANGUAGEPHRASE("dialog_network_synching") ); LPREPLACEINTEGERFLAG( 'P', percent, caption ); } else { float latency = (g_app->GetServer()->m_sequenceId - sToc->m_lastKnownSequenceId); float latencyMs = latency * 100.0f; sprintf( caption, LANGUAGEPHRASE("dialog_network_ping") ); LPREPLACEINTEGERFLAG( 'P', (int)latencyMs, caption ); int red = std::min(255,(int) latency*20); int green = 255 - red; col.Set(red,green,0,255); } Colour normalCol(200,200,255,200); char *playerName = NULL; if( sToc->m_spectator ) { for( int j = 0; j < g_app->GetWorld()->m_spectators.Size(); ++j ) { Spectator *thisTeam = g_app->GetWorld()->m_spectators[j]; if( thisTeam->m_clientId == sToc->m_clientId ) { playerName = thisTeam->m_name; break; } } } else { for( int j = 0; j < g_app->GetWorld()->m_teams.Size(); ++j ) { Team *thisTeam = g_app->GetWorld()->m_teams[j]; if( thisTeam->m_clientId == sToc->m_clientId ) { playerName = thisTeam->m_name; break; } } } g_renderer->Text( clientX, y, normalCol, 12, "%d", sToc->m_clientId ); if( playerName ) { g_renderer->TextSimple( playerX, y, normalCol, 12, playerName ); } g_renderer->TextSimple( ipX, y, normalCol, 12, netLocation ); g_renderer->Text( seqX, y, normalCol, 12, "%d", sToc->m_lastKnownSequenceId ); g_renderer->TextSimple( lagX, y, col, 12, caption ); if( sToc->m_spectator ) { g_renderer->TextSimple( clientX+10, y, normalCol, 12, LANGUAGEPHRASE("dialog_network_spec") ); } if( sToc->m_syncErrorSeqId != -1 ) { g_renderer->Text( syncX, y, Colour(255,0,0,255), 12, LANGUAGEPHRASE("dialog_worldstatus_out_of_sync_2") ); } } else { g_renderer->Text( clientX, y, Colour(255,255,255,50), 12, LANGUAGEPHRASE("dialog_network_empty") ); } y += 20; } } // // Show which packets are queued up if we're a client if( g_app->GetClientToServer() && g_lastProcessedSequenceId >= 0 ) { float yPos = m_y + m_h - 25; g_renderer->TextSimple( m_x + 10, yPos-25, White, 13, LANGUAGEPHRASE("dialog_network_sequence_msg_queue") ); float xPos = m_x + 10; float width = (m_w - 120) / 10; float gap = width * 0.2f; for( int i = 0; i <= 10; ++i ) { if( i != 0 ) { g_renderer->RectFill( xPos, yPos-5, width-gap, 20, Colour(20,20,50,255) ); if( g_app->GetClientToServer()->IsSequenceIdInQueue( g_lastProcessedSequenceId+i ) ) { g_renderer->RectFill( xPos, yPos-5, width-gap, 20, Colour(0,255,0,255) ); } g_renderer->Rect( xPos, yPos-5, width-gap, 20, Colour(255,255,255,100) ); } if( i == 0 ) { char caption[128]; sprintf( caption, LANGUAGEPHRASE("dialog_network_seqid_number") ); LPREPLACEINTEGERFLAG( 'S', g_lastProcessedSequenceId, caption ); g_renderer->TextSimple( xPos, yPos, White, 13, caption ); xPos += width * 1; } xPos += width; } } if( g_app->GetClientToServer() ) { char caption[128]; char number[32]; if( !g_app->GetServer() ) { sprintf( caption, LANGUAGEPHRASE("dialog_network_svr_known_seqid") ); LPREPLACEINTEGERFLAG( 'S', g_app->GetClientToServer()->m_serverSequenceId, caption ); g_renderer->TextSimple( m_x + 10, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_svr_estimated_seqid") ); LPREPLACEINTEGERFLAG( 'S', g_app->GetClientToServer()->GetEstimatedServerSeqId(), caption ); g_renderer->TextSimple( m_x + 10, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_estimated_latency") ); sprintf( number, "%2.1f", g_app->GetClientToServer()->GetEstimatedLatency() ); LPREPLACESTRINGFLAG( 'L', number, caption ); g_renderer->TextCentreSimple( m_x + m_w/2, y+40, White, 15, caption ); } y = m_y + 15; sprintf( caption, LANGUAGEPHRASE("dialog_network_client_seqid") ); LPREPLACEINTEGERFLAG( 'S', g_app->GetClientToServer()->m_lastValidSequenceIdFromServer, caption ); g_renderer->TextSimple( m_x + 250, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_client_send") ); sprintf( number, "%2.1f", g_app->GetClientToServer()->m_sendRate/1024.0f ); LPREPLACESTRINGFLAG( 'R', number, caption ); g_renderer->TextSimple( m_x + 250, y+=h, White, 12, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_network_client_receive") ); sprintf( number, "%2.1f", g_app->GetClientToServer()->m_receiveRate/1024.0f ); LPREPLACESTRINGFLAG( 'R', number, caption ); g_renderer->TextSimple( m_x + 250, y+=h, White, 12, caption ); } }
bool ProcessServerLetters( Directory *letter ) { if( strcmp( letter->m_name, NET_DEFCON_MESSAGE ) != 0 || !letter->HasData( NET_DEFCON_COMMAND ) ) { AppDebugOut( "Client received bogus message, discarded (4)\n" ); return true; } char *cmd = letter->GetDataString( NET_DEFCON_COMMAND ); if( strcmp( cmd, NET_DEFCON_CLIENTHELLO ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); if( clientId == g_app->GetClientToServer()->m_clientId ) { g_app->GetClientToServer()->m_connectionState = ClientToServer::StateConnected; AppDebugOut( "CLIENT : Received HelloClient from Server\n" ); if( !g_app->GetTutorial() ) { g_app->GetClientToServer()->RequestTeam( Team::TypeLocalPlayer ); } } // If this is a Demo client, make a note of that if( letter->HasData( NET_DEFCON_CLIENTISDEMO ) ) { g_app->GetClientToServer()->SetClientDemo( clientId ); } // This might be a client rejoining the game // Need to give him his teams back g_app->GetWorld()->ReassignTeams( clientId ); return true; } else if( strcmp( cmd, NET_DEFCON_CLIENTGOODBYE ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); int reason = letter->GetDataInt(NET_DEFCON_DISCONNECT); AppDebugOut( "CLIENT : Client %d left the game\n", clientId ); g_app->GetWorld()->RemoveTeams( clientId, reason ); g_app->GetWorld()->RemoveSpectator( clientId ); g_app->GetClientToServer()->SetSyncState( clientId, true ); return true; } else if( strcmp( cmd, NET_DEFCON_CLIENTID ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); AppDebugOut( "CLIENT : Received ClientID of %d\n", clientId ); if( g_app->GetClientToServer()->m_clientId != -1 ) { AppAssert( g_app->GetClientToServer()->m_clientId == clientId ); return true; } g_app->GetClientToServer()->m_clientId = clientId; g_app->GetClientToServer()->m_connectionState = ClientToServer::StateHandshaking; g_lastProcessedSequenceId = -1; if( letter->HasData( NET_DEFCON_VERSION, DIRECTORY_TYPE_STRING ) ) { char *serverVersion = letter->GetDataString( NET_DEFCON_VERSION ); strcpy( g_app->GetClientToServer()->m_serverVersion, serverVersion ); AppDebugOut( "CLIENT : Server version is %s\n", serverVersion ); } if( !VersionManager::DoesSupportModSystem( g_app->GetClientToServer()->m_serverVersion ) ) { // This server is too old to support Mods, so make sure we de-activate any critical ones g_modSystem->DeActivateAllCriticalMods(); if( g_modSystem->CommitRequired() ) { g_modSystem->Commit(); g_app->RestartAmbienceMusic(); } } return true; } else if( strcmp( cmd, NET_DEFCON_TEAMASSIGN ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); int teamId = letter->GetDataInt(NET_DEFCON_TEAMID); int teamType = letter->GetDataInt(NET_DEFCON_TEAMTYPE); if( teamType != Team::TypeAI && clientId != g_app->GetClientToServer()->m_clientId ) { teamType = Team::TypeRemotePlayer; } g_app->GetWorld()->InitialiseTeam(teamId, teamType, clientId ); return true; } else if( strcmp( cmd, NET_DEFCON_SPECTATORASSIGN ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); g_app->GetWorld()->InitialiseSpectator(clientId); if( clientId == g_app->GetClientToServer()->m_clientId ) { AppDebugOut( "CLIENT: I am a spectator\n" ); } return true; } else if( strcmp( cmd, NET_DEFCON_NETSYNCERROR ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); AppDebugOut( "SYNCERROR Server informed us that Client %d is out of Sync\n", clientId ); g_app->GetClientToServer()->SetSyncState( clientId, false ); char *syncId = letter->GetDataString( NET_DEFCON_SYNCERRORID ); DumpSyncLogs(syncId); return true; } else if( strcmp( cmd, NET_DEFCON_NETSYNCFIXED ) == 0 ) { int clientId = letter->GetDataInt(NET_DEFCON_CLIENTID); AppDebugOut( "SYNCFIXED Server informed us that Client %d has repaired his Sync Error\n", clientId ); g_app->GetClientToServer()->SetSyncState( clientId, true ); return true; } else if( strcmp( cmd, NET_DEFCON_DISCONNECT ) == 0 ) { if( g_app->GetClientToServer()->m_connectionState > ClientToServer::StateDisconnected ) { g_app->ShutdownCurrentGame(); if ( EclGetWindow("LOBBY") ) EclRemoveWindow( "LOBBY" ); if ( EclGetWindow("Comms Window") ) EclRemoveWindow( "Comms Window" ); if ( EclGetWindow("Preparing Game...") ) EclRemoveWindow("Preparing Game..." ); g_app->GetInterface()->OpenSetupWindows(); char *reason; char *reasonLanguagePhrase; int reasonDisconnectInt = letter->GetDataInt(NET_DEFCON_DISCONNECT); switch( reasonDisconnectInt ) { case Disconnect_ClientLeave: reason = "You have left the game"; reasonLanguagePhrase = "dialog_disconnect_client_leave"; break; case Disconnect_ServerShutdown: reason = "The server has shutdown"; reasonLanguagePhrase = "dialog_disconnect_server_shutdown"; break; case Disconnect_InvalidKey: reason = "You are using an invalid key"; reasonLanguagePhrase = "dialog_disconnect_invalid_key"; break; case Disconnect_DuplicateKey: reason = "You are using a duplicate key"; reasonLanguagePhrase = "dialog_disconnect_duplicate_key"; break; case Disconnect_KeyAuthFailed: reason = "Key authentication failed"; reasonLanguagePhrase = "dialog_disconnect_key_auth_failed"; break; case Disconnect_BadPassword: reason = "Invalid Password Entered"; reasonLanguagePhrase = "dialog_disconnect_bad_password"; break; case Disconnect_GameFull: reason = "Game is already full"; reasonLanguagePhrase = "dialog_disconnect_game_full"; break; case Disconnect_KickedFromGame: reason = "Kicked by the Server"; reasonLanguagePhrase = "dialog_disconnect_kicked_from_game"; break; case Disconnect_DemoFull: reason = "Too many Demo Players already"; reasonLanguagePhrase = "dialog_disconnect_demo_full"; break; default: reason = "Unknown"; reasonLanguagePhrase = "dialog_disconnect_unknown"; break; } if( reasonDisconnectInt == Disconnect_KeyAuthFailed || reasonDisconnectInt == Disconnect_InvalidKey || reasonDisconnectInt == Disconnect_DuplicateKey ) { char authKey[256]; if( Authentication_IsKeyFound() ) { Authentication_GetKey( authKey ); } else { sprintf( authKey, LANGUAGEPHRASE("dialog_authkey_not_found") ); } BadKeyWindow *badKey = new BadKeyWindow(); sprintf( badKey->m_extraMessage, LANGUAGEPHRASE("dialog_auth_error") ); LPREPLACESTRINGFLAG( 'E', LANGUAGEPHRASE(reasonLanguagePhrase), badKey->m_extraMessage ); LPREPLACESTRINGFLAG( 'K', authKey, badKey->m_extraMessage ); EclRegisterWindow(badKey); } else if( reasonDisconnectInt == Disconnect_DemoFull ) { int maxGameSize; int maxDemoPlayers; bool allowDemoServers; g_app->GetClientToServer()->GetDemoLimitations( maxGameSize, maxDemoPlayers, allowDemoServers ); BadKeyWindow *badKey = new BadKeyWindow(); sprintf( badKey->m_extraMessage, LANGUAGEPHRASE("dialog_server_demo_restricted") ); LPREPLACEINTEGERFLAG( 'N', maxDemoPlayers, badKey->m_extraMessage ); badKey->m_offerDemo = false; EclRegisterWindow(badKey); } else { MessageDialog *dialog = new MessageDialog( "Disconnected", reasonLanguagePhrase, true, "dialog_disconnected", true ); EclRegisterWindow( dialog ); } AppDebugOut( "CLIENT : Received Disconnect from server : %s\n", reason ); #ifdef TESTBED if( letter->GetDataInt(NET_DEFCON_DISCONNECT) == Disconnect_ServerShutdown ) { RestartTestBed(1, "Client Disconnect"); } #endif } return true; } else if( strcmp( cmd, NET_DEFCON_SETMODPATH ) == 0 ) { char *modPath = letter->GetDataString( NET_DEFCON_SETMODPATH ); AppDebugOut( "Server has set the MOD path: '%s'\n", modPath ); if( !g_modSystem->IsCriticalModPathSet( modPath ) ) { if( g_modSystem->CanSetModPath( modPath ) ) { g_modSystem->DeActivateAllCriticalMods(); g_modSystem->SetModPath( modPath ); } else { char reason[8192]; sprintf( reason, LANGUAGEPHRASE("dialog_error_mod_path_caption") ); char modPathCopy[4096]; strcpy( modPathCopy, modPath ); LList<char *> *tokens = g_modSystem->ParseModPath( modPathCopy ); for( int i = 0; i < tokens->Size(); i+=2 ) { char *modName = tokens->GetData(i); char *version = tokens->GetData(i+1); strcat( reason, modName ); strcat( reason, " " ); strcat( reason, version ); if( !g_modSystem->IsModInstalled( modName, version ) ) { strcat( reason, " " ); strcat( reason, LANGUAGEPHRASE("dialog_mod_not_installed") ); } strcat( reason, "\n" ); } delete tokens; MessageDialog *dialog = new MessageDialog( "Error setting MOD path", reason, false, "dialog_error_mod_path_title", true ); EclRegisterWindow( dialog ); } } return true; } else { return false; } }
bool City::NuclearStrike( int causedBy, Fixed intensity, Fixed range, bool directHitPossible ) { if( range <= intensity/50 ) { Fixed intensityEffect = (intensity/100) / 2; Fixed rangeEffect = 1 - range / (intensity/50); int deaths = ( m_population * intensityEffect * rangeEffect ).IntValue(); m_dead += deaths; m_population -= deaths; m_numStrikes ++; Team *owner = g_app->GetWorld()->GetTeam(m_teamId); Team *guilty = g_app->GetWorld()->GetTeam(causedBy); bool trackedStat = false; if( causedBy == g_app->GetWorld()->m_myTeamId || m_teamId == g_app->GetWorld()->m_myTeamId ) { // We shot this nuke, or it was shot at us, so record the deaths trackedStat = true; } if( owner ) owner->m_friendlyDeaths += deaths; if( !owner && guilty ) guilty->m_collatoralDamage += deaths; if( guilty ) { if( g_app->GetWorld()->IsFriend(m_teamId,causedBy) ) { guilty->m_collatoralDamage += deaths; } else { guilty->m_enemyKills += deaths; } } bool directHit = false; char caption[256]; if( rangeEffect >= Fixed::Hundredths(75) && directHitPossible ) { if( deaths > 1000000 ) { bool messageFound = false; for( int i = 0; i < g_app->GetWorld()->m_messages.Size(); ++i ) { WorldMessage *wm = g_app->GetWorld()->m_messages[i]; if( wm->m_messageType == WorldMessage::TypeDirectHit && wm->m_longitude == m_longitude && wm->m_latitude == m_latitude ) { char dead[16]; sprintf( dead, "%.1f", (deaths + wm->m_deaths) / 1000000.0f ); sprintf( caption, "%s", LANGUAGEPHRASE("message_directhit") ); LPREPLACESTRINGFLAG( 'D', dead, caption ); LPREPLACESTRINGFLAG( 'C', LANGUAGEPHRASEADDITIONAL(m_name), caption ); wm->SetMessage( caption ); wm->m_deaths += deaths; wm->m_renderFull = true; wm->m_timer += 5; if( wm->m_timer > 15 ) { wm->m_timer = 15; } messageFound = true; break; } } if( !messageFound ) { char dead[16]; sprintf( dead, "%.1f", deaths / 1000000.0f ); sprintf( caption, "%s", LANGUAGEPHRASE("message_directhit") ); LPREPLACESTRINGFLAG( 'D', dead, caption ); LPREPLACESTRINGFLAG( 'C', LANGUAGEPHRASEADDITIONAL(m_name), caption ); g_app->GetWorld()->AddWorldMessage( m_longitude, m_latitude, m_teamId, caption, WorldMessage::TypeDirectHit ); g_app->GetWorld()->m_messages[ g_app->GetWorld()->m_messages.Size() -1 ]->m_deaths = deaths; } } directHit = true; } if( !directHit && deaths > 1000000 ) { char dead[16]; sprintf( dead, "%.1f", deaths / 1000000.0f ); sprintf( caption, "%s", LANGUAGEPHRASE("message_fallout") ); LPREPLACESTRINGFLAG( 'D', dead, caption ); LPREPLACESTRINGFLAG( 'C', LANGUAGEPHRASEADDITIONAL(m_name), caption ); g_app->GetInterface()->ShowMessage( m_longitude, m_latitude, m_teamId, caption ); } return directHit; } return false; }
void Game::Update() { // // If there is a real-world timer, update it if( m_winner == -1 && m_maxGameTime > 0 ) { m_maxGameTime -= SERVER_ADVANCE_PERIOD; m_maxGameTime = max( m_maxGameTime, 0 ); if( !m_gameTimeWarning && m_maxGameTime <= (10 * 60) && g_app->GetGame()->GetOptionValue("MaxGameRealTime") >= 10 ) { g_app->GetInterface()->ShowMessage( 0, 0, -1, LANGUAGEPHRASE("message_ten_minute_warning"), true ); m_gameTimeWarning = true; if( g_app->m_hidden ) { g_app->GetStatusIcon()->SetSubIcon( STATUS_ICON_TIMER ); g_app->GetStatusIcon()->SetCaption( LANGUAGEPHRASE("tray_icon_ten_minute_warning") ); } } } // Remove all remaining units and calculate total nukes when Defcon 3 hits int defcon = g_app->GetWorld()->GetDefcon(); if( defcon != m_lastKnownDefcon ) { if( !g_app->GetTutorial() || g_app->GetTutorial()->GetCurrentLevel() == 7 ) { if( defcon == 3 ) { for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *team = g_app->GetWorld()->m_teams[i]; team->m_unitCredits = 0; for( int j = 0; j < WorldObject::NumObjectTypes; ++j ) { team->m_unitsAvailable[j] = 0; } } CountNukes(); for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *team = g_app->GetWorld()->m_teams[i]; m_totalNukes[team->m_teamId] = m_nukeCount[team->m_teamId]; } EclRemoveWindow( "Side Panel" ); EclRemoveWindow( "Placement" ); } } m_lastKnownDefcon = defcon; } // // Has somebody won? if( m_winner == -1 ) { // // If the game is counting down... if( m_victoryTimer > 0 ) { m_victoryTimer -= SERVER_ADVANCE_PERIOD * g_app->GetWorld()->GetTimeScaleFactor(); m_victoryTimer = max( m_victoryTimer, 0 ); } m_recalcTimer -= SERVER_ADVANCE_PERIOD; if( m_recalcTimer <= 0 ) { m_recalcTimer = 3; // // Recalculate the scores CountNukes(); CalculateScores(); // // Look at nukes remaining // If there are few enough nukes, start the timer if( !m_lockVictoryTimer && m_victoryTimer < 0 ) { int totalNukeCount = 0; int totalMaxNukeCount = 0; int numTeams = g_app->GetWorld()->m_teams.Size(); for( int t = 0; t < numTeams; ++t ) { Team *team = g_app->GetWorld()->m_teams[t]; totalNukeCount += m_nukeCount[team->m_teamId]; totalMaxNukeCount += m_totalNukes[team->m_teamId]; } float averageNukeCount = totalNukeCount / (float) numTeams; float averageTotalCount = totalMaxNukeCount / (float) numTeams; float victoryNukeCount = averageTotalCount * GetOptionValue("VictoryTrigger") / 100.0f; if( averageNukeCount <= victoryNukeCount ) { m_victoryTimer = GetOptionValue("VictoryTimer"); m_victoryTimer *= 60; //to get it into minutes if( m_victoryTimer > 0 ) { g_app->GetInterface()->ShowMessage( 0, 0, -1, LANGUAGEPHRASE("message_victory_timer"), true ); g_soundSystem->TriggerEvent( "Interface", "DefconChange" ); if( g_app->m_hidden ) { g_app->GetStatusIcon()->SetSubIcon( STATUS_ICON_TIMER ); g_app->GetStatusIcon()->SetCaption( LANGUAGEPHRASE("tray_icon_victory_timer") ); } } } } // // If the countdown has finished // Declare the winner now! if( m_victoryTimer == 0 || m_maxGameTime == 0 ) { CalculateScores(); m_winner = -1; int winningScore = 0; for( int t = 0; t < g_app->GetWorld()->m_teams.Size(); ++t ) { Team *team = g_app->GetWorld()->m_teams[t]; int score = GetScore(team->m_teamId); g_app->GetClientToServer()->SendTeamScore( team->m_teamId, score ); if( score > winningScore ) { winningScore = score; m_winner = team->m_teamId; } } int numPlayers = g_app->GetWorld()->m_teams.Size(); char msg[128]; if( m_winner != -1 ) { strcpy(msg, LANGUAGEPHRASE("message_victory")); LPREPLACESTRINGFLAG( 'T', g_app->GetWorld()->GetTeam(m_winner)->GetTeamName(), msg ); if( m_winner == g_app->GetWorld()->m_myTeamId && numPlayers > 1 ) { } } else { strcpy(msg, LANGUAGEPHRASE("message_stalemate")); m_winner = 999; } strupr(msg); g_app->GetInterface()->ShowMessage( 0, 0, m_winner, msg, true ); g_app->GetMapRenderer()->m_renderEverything = true; for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { g_app->GetWorld()->m_teams[i]->m_desiredGameSpeed = 0; } if( !EclGetWindow( "Stats" ) ) { EclRegisterWindow( new StatsWindow() ); } g_soundSystem->StopAllSounds( SoundObjectId(), "StartMusic StartMusic" ); g_soundSystem->TriggerEvent( "Interface", "GameOver" ); int specVisible = g_app->GetGame()->GetOptionValue("SpectatorChatChannel"); if( specVisible == 0 && g_app->GetWorld()->m_spectators.Size() ) { g_app->GetWorld()->AddChatMessage( -1, CHATCHANNEL_PUBLIC, LANGUAGEPHRASE("message_spectators_chat_players"), -1, false ); } } } } }