コード例 #1
0
ファイル: IntroScreen.cpp プロジェクト: alanhorizon/Transport
void CTranscendenceWnd::OnCharIntro (char chChar, DWORD dwKeyData)

//	OnCharIntro
//
//	Handle WM_CHAR

	{
	if (m_bOverwriteGameDlg)
		{
		return;
		}

	if (m_PlayerDisplay.OnChar(chChar))
		return;

	if (m_ButtonBarDisplay.OnChar(chChar))
		return;

	switch (chChar)
		{
		case 'N':
		case 'n':
			{
			CShip *pShip = m_Universe.GetPOV()->AsShip();
			if (pShip)
				{
				m_dwIntroShipClass = pShip->GetClass()->GetUNID();

				pShip->Destroy(removedFromSystem, NULL);
				}
			break;
			}
		}
	}
コード例 #2
0
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());
	}
コード例 #3
0
void CPlayerGameStats::OnObjDestroyedByPlayer (const SDestroyCtx &Ctx, CSpaceObject *pPlayer)

//	OnDestroyedByPlayer
//
//	Object destroyed by player

	{
	bool bIsEnemy = Ctx.pObj->IsEnemy(pPlayer);

	//	Is this a ship?

	CShip *pShip;
	if (Ctx.pObj->GetCategory() == CSpaceObject::catShip && (pShip = Ctx.pObj->AsShip()))
		{
		CShipClass *pClass = pShip->GetClass();
		SShipClassStats *pStats = GetShipStats(pClass->GetUNID());

		if (bIsEnemy)
			{
			pStats->iEnemyDestroyed++;

			m_iScore += pClass->GetScore();
			}
		else
			pStats->iFriendDestroyed++;
		}

	//	Is this a station?

	else if (Ctx.pObj->GetCategory() == CSpaceObject::catStation)
		{
		if (Ctx.pObj->HasAttribute(CONSTLIT("populated")))
			{
			SStationTypeStats *pStats = GetStationStats(Ctx.pObj->GetType()->GetUNID());

			pStats->iDestroyed++;
			}
		}
	}
コード例 #4
0
ALERROR CTargetDisplay::Init (CPlayerShipController *pPlayer, const RECT &rcRect, DWORD dwLocation)

//	Init
//
//	Initializes display

	{
	CleanUp();

	m_pPlayer = pPlayer;

	//	Create the painter

	CShip *pShip = m_pPlayer->GetShip();

	SDesignLoadCtx Ctx;
	m_pHUDPainter = IHUDPainter::Create(Ctx, pShip->GetClass(), hudTargeting);
	if (m_pHUDPainter)
		m_pHUDPainter->SetLocation(rcRect, dwLocation);

	return NOERROR;
	}
コード例 #5
0
void CGSelectorArea::SetRegionsFromWeapons (CSpaceObject *pSource)

//	SetRegionsFromWeapons
//
//	Creates regions based on installed weapons.

	{
	int i;
	ASSERT(pSource);
	if (pSource == NULL)
		return;

	CShip *pShip = pSource->AsShip();
	if (pShip == NULL)
		return;

	CShipClass *pClass = pShip->GetClass();

	//	Keep track of layouts that have already been used.

	TArray<bool> SlotStatus;
	SlotStatus.InsertEmpty(MISC_DEVICES_LAYOUT_COUNT);
	for (i = 0; i < MISC_DEVICES_LAYOUT_COUNT; i++)
		SlotStatus[i] = true;

	//	If we don't have a launcher, we place the launcher slot first because we
	//	want it to take precedence (position-wise).

	int iIndex;
	bool bHasLauncher = (pShip->GetNamedDevice(devMissileWeapon) != NULL);
	if (!bHasLauncher)
		{
		//	See if we can figure out the proper position for the launcher based
		//	on the class slots

		CVector vLauncherPos;
		SDeviceDesc DeviceDesc;
		if (pClass->FindDeviceSlotDesc(devMissileWeapon, &DeviceDesc))
			vLauncherPos = pClass->GetPosOffset(DeviceDesc.iPosAngle, DeviceDesc.iPosRadius, DeviceDesc.iPosZ, DeviceDesc.b3DPosition);

		//	Find a layout

		if (FindLayoutForPos(vLauncherPos, SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devMissileWeapon;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}

	//	Create a region for each weapon.

	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty() 
				|| (pDevice->GetCategory() != itemcatWeapon 
					&& pDevice->GetCategory() != itemcatLauncher))
			continue;

		if (pDevice->GetCategory() == itemcatLauncher)
			bHasLauncher = true;

		//	If the device already has a position index, then use that (assuming
		//	it's free).

		iIndex = pDevice->GetSlotPosIndex();
		if (iIndex < 0 || iIndex >= SlotStatus.GetCount() || !SlotStatus[iIndex])
			iIndex = -1;

		//	If we don't have an assigned slot, figure it out.

		if (iIndex == -1)
			{
			if (!FindLayoutForPos(pDevice->GetPosOffset(pShip), SlotStatus, &iIndex))
				continue;

			//	Remember so we stay in this location.

			pDevice->SetSlotPosIndex(iIndex);
			}

		//	Create the region

		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeInstalledItem;
		pEntry->pItemCtx = new CItemCtx(pShip, pDevice);

		pEntry->iSlotPosIndex = iIndex;
		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

		//	Mark the layout as used

		SlotStatus[iIndex] = false;
		}

	//	Figure out how many empty weapon slots we should create. We add one 
	//	empty slot for each weapon slot, but we subtract one if we don't have
	//	a launcher and we always have at least 1 empty slot, in case the player
	//	finds a slot-less weapon.

#ifdef SINGLE_FREE_SLOT
	int iEmptySlots = 1;
#else
	int iWeaponSlotsInUse;
	int iTotalSlotsInUse = pShip->CalcDeviceSlotsInUse(&iWeaponSlotsInUse);
	int iEmptySlots = Max(1, Min((pClass->GetMaxDevices() - iTotalSlotsInUse), (pClass->GetMaxWeapons() - iWeaponSlotsInUse)) - (bHasLauncher ? 0 : 1));
#endif

	//	Try to position the empty slots

	CVector vWeaponPos;
	SDeviceDesc DeviceDesc;
	if (pClass->FindDeviceSlotDesc(devPrimaryWeapon, &DeviceDesc))
		vWeaponPos = pClass->GetPosOffset(DeviceDesc.iPosAngle, DeviceDesc.iPosRadius, DeviceDesc.iPosZ, DeviceDesc.b3DPosition);

	for (i = 0; i < iEmptySlots; i++)
		{
		//	Find a position

		if (FindLayoutForPos(vWeaponPos, SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devPrimaryWeapon;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}
	}
コード例 #6
0
void CGSelectorArea::SetRegionsFromMiscDevices (CSpaceObject *pSource)

//	SetRegionsFromMiscDevices
//
//	Generates regions showing misc devices (including reactor, drive, 
//	and cargo hold).

	{
	int i;
	ASSERT(pSource);
	if (pSource == NULL)
		return;

	CShip *pShip = pSource->AsShip();
	if (pShip == NULL)
		return;

	CShipClass *pClass = pShip->GetClass();

	//	Keep track of layouts that have already been used.

	TArray<bool> SlotStatus;
	SlotStatus.InsertEmpty(MISC_DEVICES_LAYOUT_COUNT);
	for (i = 0; i < MISC_DEVICES_LAYOUT_COUNT; i++)
		SlotStatus[i] = true;

	//	Reserve the slots for named device types

	SlotStatus[REACTOR_SLOT_INDEX] = false;
	SlotStatus[DRIVE_SLOT_INDEX] = false;
	SlotStatus[CARGO_SLOT_INDEX] = false;

	//	Count the number of miscellaneous devices with 0
	//	slots (because we may need to bump them).

	int iSlottedDevices = 0;
	int iNonSlotDevices = 0;
	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty() || pDevice->GetCategory() != itemcatMiscDevice)
			continue;

		if (pDevice->GetClass()->GetSlotsRequired() > 0)
			iSlottedDevices++;
		else
			iNonSlotDevices++;
		}

	//	We try to fit all other devices (and placeholders) before we add a
	//	non-slotted device.

	int iNonSlotDeviceSlotsAvail = Max(0, MISC_DEVICES_LAYOUT_COUNT - 4 - iSlottedDevices);

	//	Create a region for each device.

	int iIndex = -1;
	bool bHasReactor = false;
	bool bHasDrive = false;
	bool bHasCargo = false;
	int iNextUnamedSlot = FIRST_UNNAMED_SLOT_INDEX;
	for (i = 0; i < pShip->GetDeviceCount(); i++)
		{
		CInstalledDevice *pDevice = pShip->GetDevice(i);
		if (pDevice->IsEmpty())
			continue;

		//	Figure out the layout descriptor

		iIndex = -1;
		const SLayoutDesc *pLayout = NULL;
		switch (pDevice->GetCategory())
			{
			case itemcatCargoHold:
				pLayout = &g_MiscDevicesLayout[CARGO_SLOT_INDEX];
				bHasCargo = true;
				break;

			case itemcatDrive:
				pLayout = &g_MiscDevicesLayout[DRIVE_SLOT_INDEX];
				bHasDrive = true;
				break;

			case itemcatMiscDevice:
				{
				//	If this is a 0-slot device and we have no more room for
				//	0-slot devices, then we skip it.

				if (pDevice->GetClass()->GetSlotsRequired() == 0
						&& iNonSlotDeviceSlotsAvail <= 0)
					continue;

				//	If the device already has a position index, then use that (assuming
				//	it's free).

				iIndex = pDevice->GetSlotPosIndex();
				if (iIndex < 0 || iIndex >= SlotStatus.GetCount() || !SlotStatus[iIndex])
					iIndex = -1;

				//	If we don't have an assigned slot, figure it out.

				if (iIndex == -1)
					{
					//	Look for a new position

					if (!FindLayoutForPos(pDevice->GetPosOffset(pShip), SlotStatus, &iIndex))
						continue;

					//	Remember so we stay in this location.

					pDevice->SetSlotPosIndex(iIndex);
					}

				//	Remember the layout and mark it as used.

				pLayout = &g_MiscDevicesLayout[iIndex];
				SlotStatus[iIndex] = false;
				break;
				}

			case itemcatReactor:
				pLayout = &g_MiscDevicesLayout[REACTOR_SLOT_INDEX];
				bHasReactor = true;
				break;
			}

		//	Create the region (but only if we have a layout position
		//	for it).

		if (pLayout)
			{
			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeInstalledItem;
			pEntry->pItemCtx = new CItemCtx(pShip, pDevice);

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
			}
		}

	//	Add empty slots, if necessary

	if (!bHasReactor)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[REACTOR_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devReactor;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	if (!bHasDrive)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[DRIVE_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devDrive;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	if (!bHasCargo)
		{
		const SLayoutDesc *pLayout = &g_MiscDevicesLayout[CARGO_SLOT_INDEX];

		SEntry *pEntry = m_Regions.Insert();
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devCargo;

		pEntry->rcRect.left = pLayout->xLeft;
		pEntry->rcRect.top = pLayout->yTop;
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	//	Figure out how many empty weapon slots we should create. We add one 
	//	empty slot for each weapon slot, but we subtract one if we don't have
	//	a launcher and we always have at least 1 empty slot, in case the player
	//	finds a slot-less weapon.

#ifdef SINGLE_FREE_SLOT
	int iEmptySlots = 1;
#else
	int iNonWeaponSlotsInUse;
	int iTotalSlotsInUse = pShip->CalcDeviceSlotsInUse(NULL, &iNonWeaponSlotsInUse);
	int iEmptySlots = Max(1, Min((pClass->GetMaxDevices() - iTotalSlotsInUse), (pClass->GetMaxNonWeapons() - iNonWeaponSlotsInUse)) - (bHasReactor ? 0 : 1) - (bHasDrive ? 0 : 1) - (bHasCargo ? 0 : 1));
#endif

	for (i = 0; i < iEmptySlots; i++)
		{
		if (FindLayoutForPos(CVector(), SlotStatus, &iIndex))
			{
			const SLayoutDesc *pLayout = &g_MiscDevicesLayout[iIndex];

			SEntry *pEntry = m_Regions.Insert();
			pEntry->iType = typeEmptySlot;
			pEntry->iSlotType = devNone;

			pEntry->iSlotPosIndex = iIndex;
			pEntry->rcRect.left = pLayout->xLeft;
			pEntry->rcRect.top = pLayout->yTop;
			pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
			pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;

			SlotStatus[iIndex] = false;
			}
		}
	}
コード例 #7
0
void CGSelectorArea::SetRegionsFromArmor (CSpaceObject *pSource)

//	SetRegionsFromArmor
//
//	Generates regions showing armor and shields for the given ship.

	{
	int i;
	ASSERT(pSource);
	if (pSource == NULL)
		return;

	CShip *pShip = pSource->AsShip();
	if (pShip == NULL)
		return;

	CShipClass *pClass = pShip->GetClass();

	//	Compute some metrics.
	//
	//	We place the shield generator in the center and the armor segments in a
	//	circle around it.

	const RECT &rcRect = GetRect();
	int cxArea = RectWidth(rcRect);
	int cyArea = RectHeight(rcRect);

	const int iRadius = WIDE_COLUMN_SPACING;

	//	Now add all the armor segments

	for (i = 0; i < pShip->GetArmorSectionCount(); i++)
		{
		SEntry *pEntry = m_Regions.Insert();
		CInstalledArmor *pArmor = pShip->GetArmorSection(i);

		pEntry->iType = typeInstalledItem;
		pEntry->pItemCtx = new CItemCtx(pShip, pArmor);

		//	Position the armor segment in a circle (add 90 degrees because the
		//	ship image points up).

        const CShipArmorSegmentDesc &Section = pClass->GetHullSection(i);
        int iCenterAngle = 90 + Section.GetCenterAngle();

		int xCenter;
		int yCenter;
		IntPolarToVector(iCenterAngle, iRadius, &xCenter, &yCenter);

		pEntry->rcRect.left = xCenter - (ITEM_ENTRY_WIDTH / 2);
		pEntry->rcRect.top = -yCenter - (ITEM_ENTRY_HEIGHT / 2);
		pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
		pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
		}

	//	Add the shield generator last

	SEntry *pEntry = m_Regions.Insert();
	CInstalledDevice *pShields = pShip->GetNamedDevice(devShields);
	if (pShields)
		{
		pEntry->iType = typeInstalledItem;
		pEntry->pItemCtx = new CItemCtx(pShip, pShields);
		}
	else
		{
		pEntry->iType = typeEmptySlot;
		pEntry->iSlotType = devShields;
		}

	pEntry->rcRect.left = -ITEM_ENTRY_WIDTH / 2;
	pEntry->rcRect.top = -ITEM_ENTRY_HEIGHT / 2;
	pEntry->rcRect.right = pEntry->rcRect.left + ITEM_ENTRY_WIDTH;
	pEntry->rcRect.bottom = pEntry->rcRect.top + ITEM_ENTRY_HEIGHT;
	}
コード例 #8
0
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);
				}
			}
		}
	}
コード例 #9
0
void CReactorDisplay::Update (void)

//	Update
//
//	Updates the buffer from data

	{
	if (m_pPlayer == NULL)
		return;

	CShip *pShip = m_pPlayer->GetShip();
	const CPlayerSettings *pSettings = pShip->GetClass()->GetPlayerSettings();
	const SReactorImageDesc &ReactorDesc = pSettings->GetReactorDesc();

	int yOffset = (RectHeight(m_rcRect) - RectHeight(ReactorDesc.ReactorImage.GetImageRect())) / 2;

	//	Paint the background

	ReactorDesc.ReactorImage.PaintImageUL(m_Buffer, 0, yOffset, 0, 0);

	//	Calculate fuel values

	int iFuelLeft = pShip->GetFuelLeft();
	int iMaxFuel = pShip->GetMaxFuel();
	int iFuelLevel = (iMaxFuel > 0 ? (Min((iFuelLeft * 100 / iMaxFuel) + 1, 100)) : 0);

	//	Paint the fuel level

	CG16bitImage *pFuelImage = NULL;
	RECT rcSrcRect;
	bool bBlink;
	if (iFuelLevel < 15)
		{
		pFuelImage = &ReactorDesc.FuelLowLevelImage.GetImage(NULL_STR);
		rcSrcRect = ReactorDesc.FuelLowLevelImage.GetImageRect();
		bBlink = true;
		}
	else
		{
		pFuelImage = &ReactorDesc.FuelLevelImage.GetImage(NULL_STR);
		rcSrcRect = ReactorDesc.FuelLevelImage.GetImageRect();
		bBlink = false;
		}

	if (!bBlink || ((m_iTickCount % 2) == 0))
		{
		int cxFuelLevel = RectWidth(rcSrcRect) * iFuelLevel / 100;
		m_Buffer.ColorTransBlt(rcSrcRect.left,
				rcSrcRect.top,
				cxFuelLevel,
				RectHeight(rcSrcRect),
				255,
				*pFuelImage,
				ReactorDesc.xFuelLevelImage,
				yOffset + ReactorDesc.yFuelLevelImage);
		}

	//	Paint fuel level text

	m_Buffer.Fill(ReactorDesc.rcFuelLevelText.left,
			yOffset + ReactorDesc.rcFuelLevelText.top,
			RectWidth(ReactorDesc.rcFuelLevelText),
			RectHeight(ReactorDesc.rcFuelLevelText),
			DEFAULT_TRANSPARENT_COLOR);

	CString sFuelLevel = strPatternSubst(CONSTLIT("fuel"));
	int cxWidth = m_pFonts->Small.MeasureText(sFuelLevel);
	m_pFonts->Small.DrawText(m_Buffer,
			ReactorDesc.rcFuelLevelText.left,
			yOffset + ReactorDesc.rcFuelLevelText.top,
			m_pFonts->wHelpColor,
			sFuelLevel,
			0);

	//	Calculate the power level

	int iPowerUsage = pShip->GetPowerConsumption();
	int iMaxPower = pShip->GetMaxPower();
	int iPowerLevel;
	if (iMaxPower)
		iPowerLevel = Min((iPowerUsage * 100 / iMaxPower) + 1, 120);
	else
		iPowerLevel = 0;

	if (iPowerLevel >= 100)
		m_iOverloading++;
	else
		m_iOverloading = 0;

	bBlink = (m_iOverloading > 0);

	//	Paint the power level

	if (!bBlink || ((m_iOverloading % 2) == 1))
		{
		CG16bitImage *pPowerImage = &ReactorDesc.PowerLevelImage.GetImage(NULL_STR);
		rcSrcRect = ReactorDesc.PowerLevelImage.GetImageRect();
		int cxPowerLevel = RectWidth(rcSrcRect) * iPowerLevel / 120;
		m_Buffer.ColorTransBlt(rcSrcRect.left,
				rcSrcRect.top,
				cxPowerLevel,
				RectHeight(rcSrcRect),
				255,
				*pPowerImage,
				ReactorDesc.xPowerLevelImage,
				yOffset + ReactorDesc.yPowerLevelImage);
		}

	//	Paint power level text

	m_Buffer.Fill(ReactorDesc.rcPowerLevelText.left,
			yOffset + ReactorDesc.rcPowerLevelText.top,
			RectWidth(ReactorDesc.rcPowerLevelText),
			RectHeight(ReactorDesc.rcPowerLevelText),
			DEFAULT_TRANSPARENT_COLOR);

	CString sPowerLevel = strPatternSubst(CONSTLIT("power usage"));
	int cyHeight;
	cxWidth = m_pFonts->Small.MeasureText(sPowerLevel, &cyHeight);
	m_pFonts->Small.DrawText(m_Buffer,
			ReactorDesc.rcPowerLevelText.left,
			yOffset + ReactorDesc.rcPowerLevelText.bottom - cyHeight,
			m_pFonts->wHelpColor,
			sPowerLevel,
			0);

	//	Paint the reactor name (we paint on top of the levels)

	WORD wColor;
	if (pShip->GetReactorDesc()->fDamaged)
		wColor = DAMAGED_TEXT_COLOR;
	else
		wColor = m_pFonts->wTitleColor;

	CString sReactorName = strPatternSubst(CONSTLIT("%s (%s)"), 
			pShip->GetReactorName(),
			ReactorPower2String(iMaxPower));

	m_pFonts->Medium.DrawText(m_Buffer,
			ReactorDesc.rcReactorText.left,
			yOffset + ReactorDesc.rcReactorText.top,
			wColor,
			sReactorName,
			0);

	m_iTickCount++;
	}