void CUIHelper::CreateClassInfoCargo (CShipClass *pClass, const CDeviceDescList &Devices, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoCargo // // Creates info about the ship class' cargo { const CVisualPalette &VI = m_HI.GetVisuals(); CDeviceClass *pCargoExtension = Devices.GetNamedDevice(devCargo); int iCargoSpace = pClass->GetCargoSpace(); if (pCargoExtension) iCargoSpace += pCargoExtension->GetCargoSpace(); // Icon CItemType *pItemIcon = (pCargoExtension ? pCargoExtension->GetItemType() : g_pUniverse->FindItemType(CARGO_HOLD_EXPANSION_UNID)); // Text CString sText = strPatternSubst(CONSTLIT("{/rtf {/f:LargeBold;/c:%d; %s} {/f:MediumBold;/c:%d; %s}\n{/f:Medium;/c:%d; %s}}"), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), strFromInt(iCargoSpace, TRUE), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogInput)), (pCargoExtension ? strPatternSubst(CONSTLIT("ton %s"), CTextBlock::Escape(pCargoExtension->GetItemType()->GetNounPhrase(nounActual))) : CONSTLIT("ton cargo hold")), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), (iCargoSpace < pClass->GetMaxCargoSpace() ? strPatternSubst(CONSTLIT("optional expansion up to %d tons"), pClass->GetMaxCargoSpace()) : CONSTLIT("cargo space cannot be expanded"))); CreateClassInfoSpecialItem(pItemIcon, sText, x, y, cxWidth, dwOptions, retcyHeight, retpInfo); }
void CUIHelper::CreateClassInfoReactor (CShipClass *pClass, const CDeviceDescList &Devices, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoReactor // // Creates info about the ship class' reactor { const CVisualPalette &VI = m_HI.GetVisuals(); // Get reactor info from the ship class const ReactorDesc *pReactorDesc = pClass->GetReactorDesc(); if (pReactorDesc == NULL) { if (retcyHeight) *retcyHeight = 0; CAniSequencer::Create(CVector(x, y), (CAniSequencer **)retpInfo); return; } CDeviceClass *pReactor = Devices.GetNamedDevice(devReactor); if (pReactor) pReactorDesc = pReactor->GetReactorDesc(); // Get the icon (OK if this is NULL) CItemType *pItemIcon = (pReactor ? pReactor->GetItemType() : g_pUniverse->FindItemType(NOVA25_REACTOR_UNID)); // Create the info CString sText = strPatternSubst(CONSTLIT("{/rtf {/f:LargeBold;/c:%d; %s} {/f:MediumBold;/c:%d; %s}}"), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), CTextBlock::Escape(ReactorPower2String(pReactorDesc->iMaxPower)), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogInput)), (pReactor ? CTextBlock::Escape(pReactor->GetItemType()->GetNounPhrase()) : strPatternSubst(CONSTLIT("%s reactor"), CTextBlock::Escape(pClass->GetShortName())))); CreateClassInfoSpecialItem(pItemIcon, sText, x, y, cxWidth, dwOptions, retcyHeight, retpInfo); }
void PaintWeaponFrames (CG32bitImage &Image, CItemType *pType, CShip *pPlatform, int iFrames, int x, int y, int cxCell, int cyCell) { int i, j; Metric rFireDist = 18.0 * LIGHT_SECOND; // Make sure we're refueled and in position pPlatform->Place(CVector(-rFireDist, 0.0)); pPlatform->Refuel(pPlatform->GetMaxFuel()); CItemListManipulator ItemList(pPlatform->GetItemList()); // Get the device and weapon fire desc for this item. The call will do the // right thing if this is a missile. CDeviceClass *pWeapon; int iVariant; CWeaponFireDesc *pDesc; if (!CDeviceClass::FindWeaponFor(pType, &pWeapon, &iVariant, &pDesc)) { printf("ERROR: Unable to find weapon for ammo.\n"); return; } // Compute the number of ticks that we need to cover the distance Metric rDist = rFireDist - (60 * g_KlicksPerPixel); Metric rSpeed = pDesc->GetRatedSpeed(); Metric rTime = (rSpeed > 0.0 ? (rDist / pDesc->GetRatedSpeed()) : 0.0); int iFrameToSkip = iFrames / 4; int iTicksToHit = (int)(rTime / STD_SECONDS_PER_UPDATE) - iFrameToSkip - 4; // If the item is a missile, create one to fire CItemType *pAmmoType = pDesc->GetAmmoType(); if (pAmmoType) { CItem MissileItem(pAmmoType, 1); ItemList.AddItem(MissileItem); pPlatform->OnComponentChanged(comCargo); pPlatform->ItemsModified(); pPlatform->InvalidateItemListAddRemove(); } // Install the appropriate weapon on the platform CItem WeaponItem(pWeapon->GetItemType(), 1); ItemList.AddItem(WeaponItem); pPlatform->OnComponentChanged(comCargo); pPlatform->ItemsModified(); pPlatform->InvalidateItemListAddRemove(); pPlatform->InstallItemAsDevice(ItemList); // Select the weapon (we rely on the fact that this is the current // item in the list). DeviceNames iDev = pPlatform->SelectWeapon(ItemList.GetItemAtCursor().GetInstalled(), iVariant); CInstalledDevice *pInstalledDevice = pPlatform->GetNamedDevice(iDev); if (pInstalledDevice == NULL || pInstalledDevice->GetClass()->GetUNID() != pWeapon->GetUNID()) { printf("ERROR: Failed to install %s.\n", pWeapon->GetItemType()->GetNounPhrase(0).GetASCIIZPointer()); return; } // Fire the weapon pInstalledDevice->SetTimeUntilReady(0); pPlatform->SetWeaponTriggered(iDev); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; // Now loop over the appropriate number of frames int xDest = x; int yDest = y; for (i = 0; i < iFrames; i++) { // Update the universe g_pUniverse->Update(Ctx); if (pPlatform->IsDestroyed()) printf("Platform destroyed.\n"); // Paint RECT rcView; rcView.left = xDest; rcView.top = yDest; rcView.right = xDest + (iFrames * cxCell * 2); rcView.bottom = yDest + cyCell; g_pUniverse->PaintPOV(Image, rcView, CSystem::VWP_NO_STAR_FIELD); // Next pPlatform->ClearAllTriggered(); // At the half-way mark, update until the missile hits if (i == iFrameToSkip) { for (j = 0; j < iTicksToHit; j++) g_pUniverse->Update(Ctx); } yDest += cyCell; } // Skip for a while for (j = 0; j < 100; j++) { g_pUniverse->Update(Ctx); if (pPlatform->IsDestroyed()) printf("Platform destroyed.\n"); } // Uninstall weapon ItemList.Refresh(CItem::NullItem()); while (ItemList.MoveCursorForward() && ItemList.GetItemAtCursor().GetType() != pWeapon->GetItemType()) ; pPlatform->RemoveItemAsDevice(ItemList); }
void CUIHelper::CreateClassInfoDrive (CShipClass *pClass, const CDeviceDescList &Devices, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoDrive // // Creates info about the ship class' drive { const CVisualPalette &VI = m_HI.GetVisuals(); const DriveDesc *pDriveDesc = pClass->GetHullDriveDesc(); if (pDriveDesc == NULL) { if (retcyHeight) *retcyHeight = 0; CAniSequencer::Create(CVector(x, y), (CAniSequencer **)retpInfo); return; } // Base speed and thrust Metric rMaxSpeed = pDriveDesc->rMaxSpeed; int iThrust = pDriveDesc->iThrust; // If we have a drive upgrade, we account for it here CDeviceClass *pDrive = Devices.GetNamedDevice(devDrive); if (pDrive) { pDriveDesc = pDrive->GetDriveDesc(); rMaxSpeed = Max(rMaxSpeed, pDriveDesc->rMaxSpeed); iThrust += pDriveDesc->iThrust; } // Icon CItemType *pItemIcon = (pDrive ? pDrive->GetItemType() : g_pUniverse->FindItemType(TRITIUM_PROPULSION_UPGRADE_UNID)); // Add speed box CString sSpeedNumber = strPatternSubst(CONSTLIT(".%02dc"), (int)((100.0 * rMaxSpeed / LIGHT_SECOND) + 0.5)); CString sSpeedHeader = (pDrive ? pDrive->GetItemType()->GetNounPhrase(nounActual) : CONSTLIT("main drive")); // Add thrust/mass ratio Metric rMass = pClass->CalcMass(Devices); int iRatio = (int)((200.0 * (rMass > 0.0 ? iThrust / rMass : 0.0)) + 0.5); CString sThrustNumber = strPatternSubst(CONSTLIT("%d.%d"), iRatio / 100, ((iRatio % 100) + 5) / 10); // Add maneuver speed int iManeuver = pClass->GetManeuverability() * pClass->GetRotationRange() / STD_ROTATION_COUNT; if (iManeuver <= 0) iManeuver = 1; CString sManeuverNumber = strPatternSubst(CONSTLIT("%d.%d"), 30 / iManeuver, (10 * (30 % iManeuver) + (iManeuver / 2)) / iManeuver); // Compose the text CString sText = strPatternSubst(CONSTLIT( "{/rtf/f:Medium;/c:%d; {/f:LargeBold;/c:%d; %s} {/f:MediumBold;/c:%d; %s}\n" "(max speed as fraction of light-speed)\n" "{/f:LargeBold;/c:%d; %s} thrust//mass ratio\n" "(thrust as proportion of total mass)\n" "{/f:LargeBold;/c:%d; %s} maneuverability\n" "(turning speed)}"), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), sSpeedNumber, CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogInput)), sSpeedHeader, CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), sThrustNumber, CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), sManeuverNumber); CreateClassInfoSpecialItem(pItemIcon, sText, x, y, cxWidth, dwOptions, retcyHeight, retpInfo); }
void CNewGameSession::SetShipClass (CShipClass *pClass, int x, int y, int cxWidth) // SetShipClass // // Sets the ship class { int i; const CPlayerSettings *pPlayerSettings = pClass->GetPlayerSettings(); const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumBoldFont = VI.GetFont(fontMediumBold); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); // Ship class name SetShipClassName(pClass->GetName(), x, y, cxWidth); SetShipClassDesc(pPlayerSettings->GetDesc(), x, y, cxWidth); // Offset int yOffset = SMALL_BUTTON_HEIGHT + SMALL_SPACING_VERT + MediumBoldFont.GetHeight() + 2 * SubTitleFont.GetHeight(); // Ship class image SetShipClassImage(pClass, x, y + yOffset, cxWidth); // Delete previous info DeleteElement(ID_SHIP_CLASS_INFO); // Create a sequencer for all class info components CAniSequencer *pClassInfo; CAniSequencer::Create(CVector(x, y + yOffset + SubTitleFont.GetHeight()), &pClassInfo); pClassInfo->SetID(ID_SHIP_CLASS_INFO); // Generate default devices for the ship class CDeviceDescList Devices; pClass->GenerateDevices(1, Devices); // Generate list of all weapons, sorted by level and name TSortMap<CString, CItem> RightSide; for (i = 0; i < Devices.GetCount(); i++) { CDeviceClass *pDevice = Devices.GetDeviceClass(i); if (pDevice->GetCategory() == itemcatWeapon || pDevice->GetCategory() == itemcatLauncher) RightSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 1, pDevice->GetLevel(), pDevice->GetName()), CItem(pDevice->GetItemType(), 1)); } // Add shields TSortMap<CString, CItem> LeftSide; CDeviceClass *pShields = Devices.GetNamedDevice(devShields); if (pShields) RightSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 2, pShields->GetLevel(), pShields->GetName()), CItem(pShields->GetItemType(), 1)); // Add armor RightSide.Insert(CONSTLIT("03"), CItem(g_pUniverse->GetItemType(0), SPECIAL_ARMOR)); // Add reactor LeftSide.Insert(CONSTLIT("01"), CItem(g_pUniverse->GetItemType(0), SPECIAL_REACTOR)); // Add engines LeftSide.Insert(CONSTLIT("02"), CItem(g_pUniverse->GetItemType(0), SPECIAL_DRIVE)); // Add cargo LeftSide.Insert(CONSTLIT("03"), CItem(g_pUniverse->GetItemType(0), SPECIAL_CARGO)); // Add misc devices for (i = 0; i < Devices.GetCount(); i++) { CDeviceClass *pDevice = Devices.GetDeviceClass(i); if (pDevice->GetCategory() == itemcatMiscDevice) LeftSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 4, pDevice->GetLevel(), pDevice->GetName()), CItem(pDevice->GetItemType(), 1)); } // Add device slots LeftSide.Insert(CONSTLIT("05"), CItem(g_pUniverse->GetItemType(0), SPECIAL_DEVICE_SLOTS)); // Set the ship class info. All weapons go to the right of the ship image int xPos = (cxWidth / 2) + (SHIP_IMAGE_RECT_WIDTH / 2); int yPos = 0; int cxInfo = (cxWidth - xPos); for (i = 0; i < RightSide.GetCount(); i++) { int cyInfo; IAnimatron *pInfo; AddClassInfo(pClass, Devices, RightSide[i], xPos, yPos, cxInfo, 0, &cyInfo, &pInfo); pClassInfo->AddTrack(pInfo, 0); yPos += cyInfo + ITEM_INFO_PADDING_VERT; } // Misc devices go on the left xPos = (cxWidth / 2) - (SHIP_IMAGE_RECT_WIDTH / 2); yPos = 0; cxInfo = xPos; for (i = 0; i < LeftSide.GetCount(); i++) { int cyInfo; IAnimatron *pInfo; AddClassInfo(pClass, Devices, LeftSide[i], xPos, yPos, cxInfo, CUIHelper::OPTION_ITEM_RIGHT_ALIGN, &cyInfo, &pInfo); pClassInfo->AddTrack(pInfo, 0); yPos += cyInfo + ITEM_INFO_PADDING_VERT; } m_pRoot->AddLine(pClassInfo); }