void App::ShutdownCurrentGame() { // // Stop the MetaServer registration if( MetaServer_IsRegisteringOverLAN() ) { MetaServer_StopRegisteringOverLAN(); } if( MetaServer_IsRegisteringOverWAN() ) { MetaServer_StopRegisteringOverWAN(); } if( m_gameRunning ) { EclRemoveAllWindows(); } // // If there is a client, shut it down now if( m_world ) { delete m_world; m_world = NULL; } if( m_clientToServer->IsConnected() ) { m_clientToServer->ClientLeave(true); } else { m_clientToServer->ClientLeave(false); } // // If there is a server, shut it down now if( m_server ) { m_server->Shutdown(); delete m_server; m_server = NULL; } if( m_tutorial ) { delete m_tutorial; m_tutorial = NULL; } m_gameRunning = false; delete m_game; m_game = new Game(); g_startTime = FLT_MAX; g_gameTime = 0.0f; g_advanceTime = 0.0f; g_lastServerAdvance = 0.0f; g_predictionTime = 0.0f; g_lastProcessedSequenceId = -2; // -2=not yet ready to begin. -1=ready for first update (id=0) g_soundSystem->StopAllSounds( SoundObjectId(), "StartMusic StartMusic" ); g_app->GetMapRenderer()->m_renderEverything = false; m_gameStartTimer = -1.0f; GetInterface()->SetMouseCursor(); SetMousePointerVisible(true); }
bool Nuke::Update() { // // Are we disarmed? if( m_currentState == 1 && m_stateTimer <= 0 ) { if( m_teamId == g_app->GetWorld()->m_myTeamId ) { char message[64]; sprintf( message, LANGUAGEPHRASE("message_disarmed") ); g_app->GetWorld()->AddWorldMessage( m_longitude, m_latitude, m_teamId, message, WorldMessage::TypeObjectState ); } return true; } // // Is our waypoint changing? Fixed timePerUpdate = SERVER_ADVANCE_PERIOD * g_app->GetWorld()->GetTimeScaleFactor(); if( m_newLongitude != 0 || m_newLatitude != 0 ) { Fixed factor1 = m_turnRate * timePerUpdate * 2; Fixed factor2 = 1 - factor1; m_targetLongitude = ( m_newLongitude * factor1 ) + ( m_targetLongitude * factor2 ); m_targetLatitude = ( m_newLatitude * factor1 ) + ( m_targetLatitude * factor2 ); if( ( m_targetLongitude - m_newLongitude ).abs() < 1 && ( m_targetLatitude - m_newLatitude ).abs() < 1 ) { SetWaypoint( m_newLongitude, m_newLatitude ); m_newLongitude = 0; m_newLatitude = 0; } } // // Move towards target Vector3<Fixed> target( m_targetLongitude, m_targetLatitude, 0 ); Vector3<Fixed> pos( m_longitude, m_latitude, 0 ); Fixed remainingDistance = (target - pos).Mag(); Fixed fractionDistance = 1 - remainingDistance / m_totalDistance; Vector3<Fixed> front = (target - pos).Normalise(); Fixed fractionNorth = 5 * m_latitude.abs() / ( 200 / 2 ); fractionNorth = max( fractionNorth, 3 ); front.RotateAroundZ( Fixed::PI / (fractionNorth * m_curveDirection) ); front.RotateAroundZ( fractionDistance * (-m_curveDirection * Fixed::PI/fractionNorth) ); if( pos.y > 85 ) { // We are dangerously far north // Make sure we dont go off the top of the world Fixed extremeFractionNorth = (pos.y - 85) / 15; Clamp( extremeFractionNorth, Fixed(0), Fixed(1) ); front.y *= ( 1 - extremeFractionNorth ); front.Normalise(); } m_vel = Vector3<Fixed>(front * (m_speed/2 + m_speed/2 * fractionDistance * fractionDistance)); Fixed newLongitude = m_longitude + m_vel.x * timePerUpdate; Fixed newLatitude = m_latitude + m_vel.y * timePerUpdate; Fixed newDistance = g_app->GetWorld()->GetDistance( newLongitude, newLatitude, m_targetLongitude, m_targetLatitude); if( newLongitude <= -180 || newLongitude >= 180 ) { m_longitude = newLongitude; CrossSeam(); newLongitude = m_longitude; newDistance = g_app->GetWorld()->GetDistance( newLongitude, newLatitude, m_targetLongitude, m_targetLatitude ); } if( newDistance < 2 && newDistance >= remainingDistance ) { m_targetLongitude = 0; m_targetLatitude = 0; m_vel.Zero(); g_app->GetWorld()->CreateExplosion( m_teamId, m_longitude, m_latitude, 100 ); g_soundSystem->TriggerEvent( SoundObjectId(m_objectId), "Detonate" ); return true; } else { m_range -= Vector3<Fixed>( m_vel.x * Fixed(timePerUpdate), m_vel.y * Fixed(timePerUpdate), 0 ).Mag(); if( m_range <= 0 ) { m_life = 0; m_lastHitByTeamId = -1; g_app->GetWorld()->AddOutOfFueldMessage( m_objectId ); } m_longitude = newLongitude; m_latitude = newLatitude; } return MovingObject::Update(); }
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 ); } } } } }