void CTranscendenceWnd::DestroyIntroShips (void) // DestroyIntroShips // // Destroys all ships of the same class as the POV { int i; CShip *pShip = g_pUniverse->GetPOV()->AsShip(); if (pShip == NULL) return; // Destroy all ships of the current class CSystem *pSystem = pShip->GetSystem(); CShipClass *pClassToDestroy = pShip->GetClass(); TArray<CSpaceObject *> ShipsToDestroy; CSpaceObject *pOtherShip = NULL; for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); CShip *pShip; if (pObj && !pObj->IsInactive() && !pObj->IsVirtual() && (pShip = pObj->AsShip())) { if (pShip->GetClass() == pClassToDestroy) ShipsToDestroy.Insert(pObj); else if (pOtherShip == NULL) pOtherShip = pObj; } } // Destroy ships for (i = 0; i < ShipsToDestroy.GetCount(); i++) ShipsToDestroy[i]->Destroy(removedFromSystem, CDamageSource()); }
void CTranscendenceWnd::Animate (bool bTopMost) // Animate // // Called on each frame { bool bFailed = false; CG16bitImage &TheScreen = g_pHI->GetScreen(); try { SetProgramState(psAnimating); // Do the appropriate thing switch (m_State) { case gsIntro: AnimateIntro(bTopMost); break; case gsProlog: AnimateProlog(bTopMost); break; case gsInGame: case gsDestroyed: { DWORD dwStartTimer; if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) dwStartTimer = ::GetTickCount(); // Figure out some stats bool bBlind = false; bool bSRSEnhanced = false; bool bShowMapHUD = false; CShip *pShip = NULL; if (GetPlayer()) { pShip = GetPlayer()->GetShip(); bBlind = pShip->IsBlind(); bSRSEnhanced = pShip->IsSRSEnhanced(); bShowMapHUD = GetPlayer()->IsMapHUDActive(); } // Update some displays if ((m_iTick % 7) == 0) { SetProgramState(psUpdatingReactorDisplay); m_ReactorDisplay.Update(); SetProgramState(psAnimating); } // If we're showing damage flash, fill the screen if (m_iDamageFlash > 0 && (m_iDamageFlash % 2) == 0) { TheScreen.Fill(0, 0, g_cxScreen, g_cyScreen, CG16bitImage::RGBValue(128,0,0)); if (pShip && pShip->GetSystem()) { if (m_bShowingMap) g_pUniverse->PaintObjectMap(TheScreen, m_rcMainScreen, pShip); else g_pUniverse->PaintObject(TheScreen, m_rcMainScreen, pShip); } } // Otherwise, if we're in map mode, paint the map else if (m_bShowingMap) { SetProgramState(psPaintingMap); PaintMap(); SetProgramState(psAnimating); } // Otherwise, if we're blind, paint scramble else if (bBlind && (m_iTick % (20 + (((m_iTick / 100) * pShip->GetDestiny()) % 100))) > 15) PaintSRSSnow(); // Otherwise, paint the normal SRS screen else { SetProgramState(psPaintingSRS); g_pUniverse->PaintPOV(TheScreen, m_rcMainScreen, bSRSEnhanced); SetProgramState(psAnimating); PaintMainScreenBorder(); } if (m_iDamageFlash > 0) m_iDamageFlash--; // Paint various displays SetProgramState(psPaintingLRS); PaintLRS(); if (!m_bShowingMap || bShowMapHUD) { SetProgramState(psPaintingArmorDisplay); m_ArmorDisplay.Paint(TheScreen); SetProgramState(psPaintingReactorDisplay); m_ReactorDisplay.Paint(TheScreen); SetProgramState(psPaintingTargetDisplay); m_TargetDisplay.Paint(TheScreen); SetProgramState(psPaintingDeviceDisplay); m_DeviceDisplay.Paint(TheScreen); } if (m_CurrentPicker == pickNone) { SetProgramState(psPaintingMessageDisplay); m_MessageDisplay.Paint(TheScreen); } SetProgramState(psAnimating); if (m_CurrentMenu != menuNone) m_MenuDisplay.Paint(TheScreen); if (m_CurrentPicker != pickNone) m_PickerDisplay.Paint(TheScreen); if (m_bDebugConsole) m_DebugConsole.Paint(TheScreen); #ifdef DEBUG_LINE_OF_FIRE if (GetPlayer()) { if (!GetPlayer()->GetShip()->IsLineOfFireClear(GetPlayer()->GetShip()->GetPos(), NULL, GetPlayer()->GetShip()->GetRotation())) g_pUniverse->DebugOutput("line of fire blocked"); } #endif #ifdef DEBUG PaintDebugLines(); #endif // Figure out how long it took to paint if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) { DWORD dwNow = ::GetTickCount(); m_iPaintTime[m_iFrameCount % FRAME_RATE_COUNT] = dwNow - dwStartTimer; dwStartTimer = dwNow; } // Some debug information if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) PaintFrameRate(); // Update the screen if (bTopMost) g_pHI->GetScreenMgr().Blt(); // Figure out how long it took to blt if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) { DWORD dwNow = ::GetTickCount(); m_iBltTime[m_iFrameCount % FRAME_RATE_COUNT] = dwNow - dwStartTimer; dwStartTimer = dwNow; } // Update the universe if (!m_bPaused || m_bPausedStep) { SetProgramState(psUpdating); g_pUniverse->Update(g_SecondsPerUpdate); if (m_bAutopilot) { g_pUniverse->Update(g_SecondsPerUpdate); g_pUniverse->Update(g_SecondsPerUpdate); g_pUniverse->Update(g_SecondsPerUpdate); g_pUniverse->Update(g_SecondsPerUpdate); } SetProgramState(psAnimating); if (GetPlayer()) GetPlayer()->Update(m_iTick); if (GetPlayer() && GetPlayer()->GetSelectedTarget()) m_TargetDisplay.Invalidate(); m_iTick++; m_bPausedStep = false; } m_MessageDisplay.Update(); // Figure out how long it took to update if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) { DWORD dwNow = ::GetTickCount(); m_iUpdateTime[m_iFrameCount % FRAME_RATE_COUNT] = dwNow - dwStartTimer; dwStartTimer = dwNow; } // Destroyed? if (m_State == gsDestroyed) { if (!m_bPaused || m_bPausedStep) { if (--m_iCountdown == 0) g_pHI->HICommand(CONSTLIT("gameEndDestroyed")); m_bPausedStep = false; } } break; } case gsDocked: { // Paint the screen m_pCurrentScreen->Paint(TheScreen); m_pCurrentScreen->Update(); PaintMainScreenBorder(); m_ArmorDisplay.Paint(TheScreen); m_TargetDisplay.Paint(TheScreen); // Debug console if (m_bDebugConsole) m_DebugConsole.Paint(TheScreen); // We don't paint the LRS because the player doesn't need it and // because it overwrites the credits/cargo space display //PaintLRS(); // Update the screen if (bTopMost) g_pHI->GetScreenMgr().Blt(); // Update the universe (at 1/4 rate) if ((m_iTick % 4) == 0) g_pUniverse->Update(g_SecondsPerUpdate); m_MessageDisplay.Update(); m_CurrentDock.Update(m_iTick); m_iTick++; // Invalidate areas of the screen that are overlapped by // the displays. Note that we need to convert to main screen // coordinates. if (m_pCurrentScreen) { RECT rcRect = m_ArmorDisplay.GetRect(); ::OffsetRect(&rcRect, -m_rcMainScreen.left, -m_rcMainScreen.top); m_pCurrentScreen->Invalidate(rcRect); rcRect = m_TargetDisplay.GetRect(); ::OffsetRect(&rcRect, -m_rcMainScreen.left, -m_rcMainScreen.top); m_pCurrentScreen->Invalidate(rcRect); rcRect = m_rcLRS; ::OffsetRect(&rcRect, -m_rcMainScreen.left, -m_rcMainScreen.top); m_pCurrentScreen->Invalidate(rcRect); if (m_bDebugConsole) { rcRect = m_DebugConsole.GetRect(); ::OffsetRect(&rcRect, -m_rcMainScreen.left, -m_rcMainScreen.top); m_pCurrentScreen->Invalidate(rcRect); } } break; } case gsEnteringStargate: { // Update some displays if ((m_iTick % 10) == 0) m_ReactorDisplay.Update(); // Tell the universe to paint g_pUniverse->PaintPOV(TheScreen, m_rcMainScreen, false); PaintMainScreenBorder(); PaintLRS(); m_ArmorDisplay.Paint(TheScreen); m_MessageDisplay.Paint(TheScreen); m_ReactorDisplay.Paint(TheScreen); m_TargetDisplay.Paint(TheScreen); m_DeviceDisplay.Paint(TheScreen); // Debug information if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) PaintFrameRate(); #ifdef DEBUG PaintDebugLines(); #endif // Update the screen if (bTopMost) g_pHI->GetScreenMgr().Blt(); // Update the universe g_pUniverse->Update(g_SecondsPerUpdate); m_MessageDisplay.Update(); m_iTick++; if (--m_iCountdown == 0) EnterStargate(); break; } case gsLeavingStargate: { // Update some displays if ((m_iTick % 10) == 0) m_ReactorDisplay.Update(); // Tell the universe to paint g_pUniverse->PaintPOV(TheScreen, m_rcMainScreen, false); PaintMainScreenBorder(); PaintLRS(); m_ArmorDisplay.Paint(TheScreen); m_MessageDisplay.Paint(TheScreen); m_ReactorDisplay.Paint(TheScreen); m_TargetDisplay.Paint(TheScreen); m_DeviceDisplay.Paint(TheScreen); // Debug information if (m_pTC->GetOptionBoolean(CGameSettings::debugVideo)) PaintFrameRate(); #ifdef DEBUG PaintDebugLines(); #endif // Update the screen if (bTopMost) g_pHI->GetScreenMgr().Blt(); // Update the universe g_pUniverse->Update(g_SecondsPerUpdate); m_MessageDisplay.Update(); m_iTick++; if (--m_iCountdown == 0) LeaveStargate(); break; } } // Flip if (bTopMost) g_pHI->GetScreenMgr().Flip(); SetProgramState(psUnknown); } catch (...) { bFailed = true; } // Deal with errors/crashes if (bFailed) { g_pHI->GetScreenMgr().StopDX(); ReportCrash(); } }
void CDockingPorts::UpdateAll (CSpaceObject *pOwner) // UpdateAll // // UpdateAll { int i, j; for (i = 0; i < m_iPortCount; i++) { if (m_pPort[i].iStatus == psDocking) { CShip *pShip = m_pPort[i].pObj->AsShip(); ASSERT(pShip); if (pShip == NULL) continue; CVector vDest = pOwner->GetPos() + m_pPort[i].vPos; CVector vDestVel = pOwner->GetVel(); // Figure out how far we are from where we want to be CVector vDelta = vDest - pShip->GetPos(); // Figure out if we're aligned int iFinalRotation = pShip->AlignToRotationAngle(m_pPort[i].iRotation); // If the docking object is within the appropriate threshold // of the port, then complete the docking sequence. Metric rDelta2 = vDelta.Length2(); if (rDelta2 < DOCKING_THRESHOLD2 && (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation())) { pShip->Place(vDest); pShip->UnfreezeControls(); IShipController *pController = pShip->GetController(); pController->SetManeuver(IShipController::NoRotation); m_pPort[i].iStatus = psInUse; // Tell the owner that somone has docked with it first // (We do this because sometimes we want to handle stuff // in OnObjDocked before we show the player a dock screen) if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip) pOwner->OnObjDocked(pShip, pOwner); // Dock pShip->OnDocked(pOwner); // Tell all objects in the system that a ship has docked CSystem *pSystem = pShip->GetSystem(); for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj && pObj->HasOnObjDockedEvent() && pObj != pShip && pObj != pOwner) pObj->OnObjDocked(pShip, pOwner); } } // Otherwise accelerate the ship towards the docking port else { Metric rMaxSpeed = pShip->GetMaxSpeed(); Metric rMinSpeed = rMaxSpeed / 10.0; // We slow down as we get closer Metric rSpeed; if (rDelta2 < FINAL_DOCKING2) rSpeed = rMinSpeed; else if (rDelta2 < FINAL_APPROACH2) { Metric rSpeedRange = rMaxSpeed - rMinSpeed; Metric rDelta = sqrt(rDelta2); rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING)); } else rSpeed = rMaxSpeed; // Figure out the ideal velocity vector that we want to // be following. CVector vIdealVel = vDelta.Normal() * rSpeed; // Calculate the delta v that we need CVector vDeltaV = vIdealVel - pShip->GetVel(); // Rotate if (pShip != g_pUniverse->GetPlayer()) { IShipController *pController = pShip->GetController(); // If we're close enough, align to rotation angle if (rDelta2 < FINAL_APPROACH2) pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle())); // Otherwise, align along delta v else pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle())); } // Accelerate pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate); pShip->ClipSpeed(rSpeed); } } } }