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 CArmorDisplay::Update (void) // Update // // Updates buffer from data { int i; if (m_pPlayer == NULL) return; CShip *pShip = m_pPlayer->GetShip(); const CPlayerSettings *pSettings = pShip->GetClass()->GetPlayerSettings(); CItemListManipulator ItemList(pShip->GetItemList()); const CG16bitFont &SmallFont = m_pPlayer->GetTrans()->GetFonts().Small; m_Text.DeleteAll(); // If we've changed ships then we need to delete the painters if (m_dwCachedShipID != pShip->GetID()) { if (m_pShieldPainter) { m_pShieldPainter->Delete(); m_pShieldPainter = NULL; } m_dwCachedShipID = pShip->GetID(); } // Erase everything m_Buffer.Fill(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, DEFAULT_TRANSPARENT_COLOR); // Figure out the status of the shields int iHP = 0; int iMaxHP = 10; CInstalledDevice *pShield = pShip->GetNamedDevice(devShields); if (pShield) pShield->GetStatus(pShip, &iHP, &iMaxHP); // Draw the base ship image, if we have it const SArmorImageDesc &ArmorDesc = pSettings->GetArmorDesc(); if (!ArmorDesc.ShipImage.IsEmpty()) { const RECT &rcShip = ArmorDesc.ShipImage.GetImageRect(); m_Buffer.ColorTransBlt(rcShip.left, rcShip.top, RectWidth(rcShip), RectHeight(rcShip), 255, ArmorDesc.ShipImage.GetImage(NULL_STR), DESCRIPTION_WIDTH + ((SHIELD_IMAGE_WIDTH - RectWidth(rcShip)) / 2), (SHIELD_IMAGE_HEIGHT - RectHeight(rcShip)) / 2); } // Draw the old-style shields const SShieldImageDesc &ShieldDesc = pSettings->GetShieldDesc(); if (!ShieldDesc.pShieldEffect) { int iWhole = (iMaxHP > 0 ? (iHP * 100) / iMaxHP : 100); int iIndex = (100 - iWhole) / 20; const RECT &rcShield = ShieldDesc.Image.GetImageRect(); m_Buffer.ColorTransBlt(rcShield.left, rcShield.top + (RectHeight(rcShield) * iIndex), RectWidth(rcShield), RectHeight(rcShield), 255, ShieldDesc.Image.GetImage(NULL_STR), DESCRIPTION_WIDTH + ((SHIELD_IMAGE_WIDTH - RectWidth(rcShield)) / 2), (SHIELD_IMAGE_HEIGHT - RectHeight(rcShield)) / 2); } if (pShield) { m_Buffer.Fill(SHIELD_HP_DISPLAY_X, SHIELD_HP_DISPLAY_Y, SHIELD_HP_DISPLAY_WIDTH, SHIELD_HP_DISPLAY_HEIGHT, SHIELD_HP_DISPLAY_BACK_COLOR); CString sHP = strFromInt(iHP); int cxWidth = m_pFonts->Medium.MeasureText(sHP, NULL); m_pFonts->Medium.DrawText(m_Buffer, SHIELD_HP_DISPLAY_X + (SHIELD_HP_DISPLAY_WIDTH - cxWidth) / 2, SHIELD_HP_DISPLAY_Y - 1, CG16bitImage::LightenPixel(m_pFonts->wAltGreenColor, 60), sHP); DrawBrokenLine(m_Buffer, 0, SHIELD_HP_DISPLAY_Y, SHIELD_HP_DISPLAY_X, SHIELD_HP_DISPLAY_Y, 0, SHIELD_HP_DISPLAY_LINE_COLOR); WORD wColor; if (pShield->IsEnabled() && !pShield->IsDamaged() && !pShield->IsDisrupted()) wColor = m_pFonts->wAltGreenColor; else wColor = DISABLED_TEXT_COLOR; CString sShieldName = pShield->GetClass()->GetName(); int cyHeight; cxWidth = m_pFonts->Medium.MeasureText(sShieldName, &cyHeight); // Add the shield name to list of text to paint STextPaint *pPaint = m_Text.Insert(); pPaint->sText = sShieldName; pPaint->x = 0; pPaint->y = SHIELD_HP_DISPLAY_Y; pPaint->pFont = &m_pFonts->Medium; pPaint->wColor = wColor; // Paint the modifiers if (pShield->GetMods().IsNotEmpty() || pShield->GetBonus() != 0) { pShip->SetCursorAtNamedDevice(ItemList, devShields); CString sMods = pShield->GetEnhancedDesc(pShip, &ItemList.GetItemAtCursor()); if (!sMods.IsBlank()) { bool bDisadvantage = (*(sMods.GetASCIIZPointer()) == '-'); int cx = SmallFont.MeasureText(sMods); m_Buffer.Fill(SHIELD_HP_DISPLAY_X - cx - 8, SHIELD_HP_DISPLAY_Y, cx + 8, SHIELD_HP_DISPLAY_HEIGHT, (bDisadvantage ? ARMOR_DAMAGED_BACK_COLOR : ARMOR_ENHANCE_BACK_COLOR)); SmallFont.DrawText(m_Buffer, SHIELD_HP_DISPLAY_X - cx - 4, SHIELD_HP_DISPLAY_Y + (SHIELD_HP_DISPLAY_HEIGHT - SmallFont.GetHeight()) / 2, (bDisadvantage ? ARMOR_DAMAGED_TEXT_COLOR : ARMOR_ENHANCE_TEXT_COLOR), sMods); } } } // Draw armor int iArmorCount = Min(pShip->GetArmorSectionCount(), pSettings->GetArmorDescCount()); for (i = 0; i < iArmorCount; i++) { const SArmorSegmentImageDesc *pImage = &pSettings->GetArmorDesc(i); CInstalledArmor *pArmor = pShip->GetArmorSection(i); int iMaxHP = pArmor->GetMaxHP(pShip); int iWhole = (iMaxHP == 0 ? 100 : (pArmor->GetHitPoints() * 100) / iMaxHP); int iIndex = (100 - iWhole) / 20; if (iIndex < 5) { const RECT &rcImage = pImage->Image.GetImageRect(); m_Buffer.ColorTransBlt(rcImage.left, rcImage.top + iIndex * RectHeight(rcImage), RectWidth(rcImage), RectHeight(rcImage), 255, pImage->Image.GetImage(NULL_STR), DESCRIPTION_WIDTH + pImage->xDest, pImage->yDest); } } // Draw the new style shields on top if (ShieldDesc.pShieldEffect) { int x = DESCRIPTION_WIDTH + SHIELD_IMAGE_WIDTH / 2; int y = SHIELD_IMAGE_HEIGHT / 2; SViewportPaintCtx Ctx; Ctx.iTick = g_pUniverse->GetTicks(); Ctx.iVariant = (iMaxHP > 0 ? (iHP * 100) / iMaxHP : 0); Ctx.iDestiny = pShip->GetDestiny(); Ctx.iRotation = 90; if (m_pShieldPainter == NULL) m_pShieldPainter = ShieldDesc.pShieldEffect->CreatePainter(); m_pShieldPainter->Paint(m_Buffer, x, y, Ctx); } // Draw armor names for (i = 0; i < iArmorCount; i++) { const SArmorSegmentImageDesc *pImage = &pSettings->GetArmorDesc(i); CInstalledArmor *pArmor = pShip->GetArmorSection(i); // Paint the HPs if (i == m_iSelection) { m_Buffer.Fill(DESCRIPTION_WIDTH + pImage->xHP - 1, pImage->yHP - 1, HP_DISPLAY_WIDTH + 2, HP_DISPLAY_HEIGHT + 2, CG16bitImage::DarkenPixel(m_pFonts->wSelectBackground, 128)); } else { m_Buffer.Fill(DESCRIPTION_WIDTH + pImage->xHP, pImage->yHP, HP_DISPLAY_WIDTH, HP_DISPLAY_HEIGHT, HP_DISPLAY_BACK_COLOR); } CString sHP = strFromInt(pArmor->GetHitPoints()); int cxWidth = m_pFonts->Medium.MeasureText(sHP, NULL); m_pFonts->Medium.DrawText(m_Buffer, DESCRIPTION_WIDTH + pImage->xHP + (HP_DISPLAY_WIDTH - cxWidth) / 2, pImage->yHP - 1, m_pFonts->wTitleColor, sHP); // Paint the armor name line DrawBrokenLine(m_Buffer, 0, pImage->yName + m_pFonts->Medium.GetHeight(), DESCRIPTION_WIDTH + pImage->xHP + pImage->xNameDestOffset, pImage->yHP + pImage->yNameDestOffset, pImage->cxNameBreak, (i == m_iSelection ? CG16bitImage::DarkenPixel(m_pFonts->wSelectBackground, 128) : ARMOR_LINE_COLOR)); // Paint the armor names CString sName = pArmor->GetClass()->GetShortName(); int cy; int cx = m_pFonts->Medium.MeasureText(sName, &cy) + 4; if (i == m_iSelection) { m_Buffer.Fill(0, pImage->yName, cx, cy, CG16bitImage::DarkenPixel(m_pFonts->wSelectBackground, 128)); } STextPaint *pPaint = m_Text.Insert(); pPaint->sText = sName; pPaint->x = 2; pPaint->y = pImage->yName; pPaint->pFont = &m_pFonts->Medium; pPaint->wColor = m_pFonts->wTitleColor; // Paint the modifiers if (pArmor->GetMods().IsNotEmpty()) { pShip->SetCursorAtArmor(ItemList, i); CString sMods = ItemList.GetItemAtCursor().GetEnhancedDesc(pShip); if (!sMods.IsBlank()) { int cx = SmallFont.MeasureText(sMods); m_Buffer.Fill(ARMOR_ENHANCE_X - cx - 4, pImage->yName + m_pFonts->Medium.GetHeight() - HP_DISPLAY_HEIGHT, cx + 8, HP_DISPLAY_HEIGHT, ARMOR_ENHANCE_BACK_COLOR); SmallFont.DrawText(m_Buffer, ARMOR_ENHANCE_X - cx, pImage->yName + 3, ARMOR_ENHANCE_TEXT_COLOR, sMods); } } } }