void ArrangeByCell (CSymbolTable &Table, int cxDesiredWidth, CPaintMap &Map)
	{
	int i;

	//	Compute the size of each image cell

	int cxCell = 32;
	int cyCell = 32;

	//	Compute the number of rows & columns

	int iInitCols = (cxDesiredWidth / cxCell) + ((cxDesiredWidth % cxCell) ? 1 : 0);
	int iInitRows = AlignUp(20 * Table.GetCount(), iInitCols) / iInitCols;

	//	Create an array that keeps track of which cells we've used up

	CCellMap CellMap(iInitCols, iInitRows);

	//	Figure out where to place all the ships

	for (i = 0; i < Table.GetCount(); i++)
		{
		CShipClass *pClass = (CShipClass *)Table.GetValue(i);

		//	Figure out how many cells we need

		int cxSize = RectWidth(pClass->GetImage().GetImageRect());
		int iCellsNeeded = AlignUp(cxSize, cxCell) / cxCell;
		int cxAreaSize = iCellsNeeded * cxCell;

		//	Position the ship

		int x, y;
		if (CellMap.GetSpace(iCellsNeeded, &x, &y))
			Map.Place(i,
				x * cxCell + (cxAreaSize - cxSize) / 2,
				y * cyCell + (cxAreaSize - cxSize) / 2,
				cxSize,
				cxSize);
		}
	}
void CExternalEntityTable::AddTable (CSymbolTable &Table)

//	AddTable
//
//	Adds all entities in the given table

	{
	int i;

	for (i = 0; i < Table.GetCount(); i++)
		m_Entities.Insert(Table.GetKey(i), *(CString *)Table.GetValue(i));
	}
ALERROR OutputItemTable (CSymbolTable &AllSystems, int iSystemSample)
	{
	ALERROR error;
	int i, j;
	CSymbolTable AllItems(TRUE, TRUE);

	for (i = 0; i < AllSystems.GetCount(); i++)
		{
		SystemInfo *pSystemEntry = (SystemInfo *)AllSystems.GetValue(i);

		for (j = 0; j < pSystemEntry->Items.GetCount(); j++)
			{
			ItemInfo *pEntry = (ItemInfo *)pSystemEntry->Items.GetValue(j);

			CString sKey = strFromInt(pEntry->pType->GetUNID(), false);

			ItemInfo *pDestEntry;
			if (error = AllItems.Lookup(sKey, (CObject **)&pDestEntry))
				{
				pDestEntry = new ItemInfo;
				pDestEntry->pType = pEntry->pType;
				pDestEntry->rTotalCount = ((double)pEntry->iTotalCount / (double)iSystemSample);

				AllItems.AddEntry(sKey, pDestEntry);
				}
			else
				pDestEntry->rTotalCount += ((double)pEntry->iTotalCount / (double)iSystemSample);
			}
		}

	//	Output all items to a well-known file

	CTextFileLog Output(ITEM_COUNT_FILENAME);
	if (error = Output.Create(FALSE))
		{
		printf("ERROR: Unable to create output file: %s\n", ITEM_COUNT_FILENAME.GetASCIIZPointer());
		return error;
		}

	for (i = 0; i < AllItems.GetCount(); i++)
		{
		ItemInfo *pEntry = (ItemInfo *)AllItems.GetValue(i);
		Output.LogOutput(0, "0x%x\t%d", pEntry->pType->GetUNID(), (int)((pEntry->rTotalCount * 1000) + 0.5));
		}

	if (error = Output.Close())
		{
		printf("ERROR: Unable to create output file: %s\n", ITEM_COUNT_FILENAME.GetASCIIZPointer());
		return error;
		}

	return NOERROR;
	}
Beispiel #4
0
void CUIHelper::PaintReferenceDamageAdj (CG16bitImage &Dest, int x, int y, int iLevel, int iHP, const int *iDamageAdj) const

//	PaintReferenceDamageAdj
//
//	Takes an array of damage type adj values and displays them

	{
	int i;
	bool bSortByDamageType = true;
	bool bOptionShowDamageAdjAsHP = false;

	const CVisualPalette &VI = m_HI.GetVisuals();
	const CG16bitFont &Small = VI.GetFont(fontSmall);
	const CG16bitFont &Medium = VI.GetFont(fontMedium);
	WORD wColorRef = VI.GetColor(colorTextHighlight);

	//	Must have positive HP

	if (iHP == 0)
		return;

	//	Sort damage types from highest to lowest

	CSymbolTable Sorted;
	int iLengthEstimate = 0;
	int iImmuneCount = 0;
	for (i = 0; i < damageCount; i++)
		{
		//	Skip if this damage type is not appropriate to our level

		int iDamageLevel = GetDamageTypeLevel((DamageTypes)i);
		if (iDamageLevel < iLevel - 5 || iDamageLevel > iLevel + 3)
			continue;

		//	Skip if the damage adj is 100%

		if (iDamageAdj[i] == iHP)
			continue;

		//	Figure out the sort order

		CString sKey;
		if (bSortByDamageType)
			sKey = strPatternSubst(CONSTLIT("%02d"), i);
		else
			{
			DWORD dwHighToLow = (iDamageAdj[i] == -1 ? 0 : 1000000 - iDamageAdj[i]);
			sKey = strPatternSubst(CONSTLIT("%08x %02d"), dwHighToLow, i);
			}

		//	Add to list

		DWORD dwValue = MAKELONG((WORD)i, (WORD)(short)iDamageAdj[i]);

		Sorted.AddEntry(sKey, (CObject *)dwValue);

		//	Estimate how many entries we will have (so we can decide the font size)
		//	We assume that immune entries get collapsed.

		if (iDamageAdj[i] != -1)
			iLengthEstimate++;
		else
			iImmuneCount++;
		}

	//	If we have six or more icons, then we need to paint smaller

	iLengthEstimate += Min(2, iImmuneCount);
	const CG16bitFont &TheFont = (iLengthEstimate >= 6 ? Small : Medium);
	int cyOffset = (Medium.GetHeight() - TheFont.GetHeight()) / 2;
	
	//	Paint the icons

	for (i = 0; i < Sorted.GetCount(); i++)
		{
		DWORD dwValue = (DWORD)Sorted.GetValue(i);
		int iDamageType = LOWORD(dwValue);
		int iDamageAdj = (int)(short)HIWORD(dwValue);
		int iPercentAdj = (100 * (iDamageAdj - iHP) / iHP);

		//	Prettify the % by rounding to a number divisible by 5

		int iPrettyPercent = 5 * ((iPercentAdj + 2 * Sign(iPercentAdj)) / 5);

		//	Skip if prettify results in 0%

		if (bOptionShowDamageAdjAsHP && iPrettyPercent == 0)
			continue;

		//	Draw icon

		g_pHI->GetVisuals().DrawDamageTypeIcon(Dest, x, y, (DamageTypes)iDamageType);
		x += DAMAGE_TYPE_ICON_WIDTH + DAMAGE_ADJ_ICON_SPACING_X;

		//	If we have a bunch of entries with "immune", then compress them

		if (i < (Sorted.GetCount() - 1)
				&& iDamageAdj == -1
				&& (iDamageAdj == (int)(short)HIWORD((DWORD)Sorted.GetValue(i + 1))))
			continue;

		//	Figure out how to display damage adj

		CString sStat;
		if (iDamageAdj == -1)
			sStat = CONSTLIT("immune");
		else if (bOptionShowDamageAdjAsHP)
			sStat = strFromInt(iDamageAdj);
		else
			sStat = strPatternSubst(CONSTLIT("%s%d%%"), (iPrettyPercent > 0 ? CONSTLIT("+") : NULL_STR), iPrettyPercent);
		
		//	Draw

		Dest.DrawText(x,
				y + cyOffset,
				TheFont,
				wColorRef,
				sStat,
				0,
				&x);

		x += DAMAGE_ADJ_SPACING_X;
		}
	}
void ArrangeByRow (CSymbolTable &Table, SArrangeDesc &Desc, CPaintMap &Map)
	{
	int iNext = 0;
	int y = 0;
	int cyHeader = Desc.pHeader->GetHeight();

	int cxInternalSpacing = 8;
	int cyInternalSpacing = 2 * Desc.pHeader->GetHeight();
	int cyNameSpacing = Desc.pHeader->GetHeight() / 2;

	while (iNext < Table.GetCount())
		{
		int i;
		int cxWidthLeft = Desc.cxDesiredWidth;
		int cyRowHeight = 0;
		int iStart = iNext;

		//	First figure out how many ships will fit
		
		while (iNext < Table.GetCount())
			{
			CShipClass *pClass = (CShipClass *)Table.GetValue(iNext);
			int cxSize = RectWidth(pClass->GetImage().GetImageRect());
			if (cxSize > cxWidthLeft && iStart != iNext)
				break;

			int cxCell = Max(cxSize + cxInternalSpacing, Desc.cxSpacing);

			cxWidthLeft -= cxCell;
			if (cxSize > cyRowHeight)
				cyRowHeight = cxSize;

			iNext++;
			}

		//	Compute the total width

		int cxRowWidth = Min(Desc.cxDesiredWidth - cxWidthLeft, Desc.cxDesiredWidth);
		int xOffset = (Desc.cxDesiredWidth - cxRowWidth) / 2;

		//	See if any of the ships overlap the text from the previous ships
		//	If so, we increase y a little bit

		int x = Desc.cxSpacing + Desc.cxExtraMargin;
		for (i = iStart; i < iNext; i++)
			{
			CShipClass *pClass = (CShipClass *)Table.GetValue(i);
			int cxSize = RectWidth(pClass->GetImage().GetImageRect());
			int yOffset = (cyRowHeight - cxSize) / 2;

			int xPoint = x + xOffset + cxSize / 2;
			int yPoint = y + yOffset;

			for (int j = 0; j < iStart; j++)
				{
				int xText = Map.GetTextX(j);
				int yText = Map.GetTextY(j);
				int cxText = Map.GetTextWidth(j);
				int cyText = Map.GetTextHeight(j) + cyInternalSpacing;

				if (xPoint >= xText && xPoint < xText + cxText && yPoint < yText + cyText)
					y = yText + cyText + cyInternalSpacing;
				}

			int cxCell = Max(cxSize + cxInternalSpacing, Desc.cxSpacing);
			x += cxCell;
			}

		//	Place the ships

		x = Desc.cxSpacing + Desc.cxExtraMargin;
		int yOverlapOffset = 0;
		for (i = iStart; i < iNext; i++)
			{
			CShipClass *pClass = (CShipClass *)Table.GetValue(i);
			int cxSize = RectWidth(pClass->GetImage().GetImageRect());
			int cxCell = Max(cxSize + cxInternalSpacing, Desc.cxSpacing);

			//	Center vertically

			int yOffset = (cyRowHeight - cxSize) / 2;

			//	Place

			Map.Place(i, x + xOffset, y + yOffset, cxSize, cxSize);

			//	Figure out the position of the text

			int cyName;
			int cxName = Desc.pHeader->MeasureText(pClass->GetNounPhrase(0), &cyName);
			if (cxName <= cxSize)
				{
				int yText = y + yOffset + cxSize + cyNameSpacing;
				Map.PlaceText(i,
						x + xOffset + (cxSize - cxName) / 2,
						yText,
						cxName,
						cyName);

				yOverlapOffset = yText + cyName + cyNameSpacing;
				}
			else
				{
				//	See if the name fits above the previous name

				int yText;
				if (yOverlapOffset > 0 
						&& i > iStart 
						&& (x + xOffset + cxSize - (Map.GetX(i - 1) + Map.GetWidth(i - 1) / 2)) > cxName + 8)
					{
					yText = y + yOffset + cxSize + cyNameSpacing;
					if (yText < Map.GetY(i - 1) + Map.GetHeight(i - 1))
						yText = Map.GetY(i - 1) + Map.GetHeight(i - 1) + cyNameSpacing;

					if (yText > Map.GetTextY(i - 1) - (cyName + cyNameSpacing))
						yText = yOverlapOffset;
					}

				//	Otherwise, use the overlap, if it exits

				else if (yOverlapOffset == 0)
					yText = y + yOffset + cxSize + cyNameSpacing;
				else
					yText = yOverlapOffset;

				Map.PlaceText(i,
						x + xOffset + cxSize - cxName,
						yText,
						cxName,
						cyName);

				yOverlapOffset = yText + cyName + cyNameSpacing;
				}

			x += cxCell;
			}

		y += cyRowHeight;
		}

	//	Add a margin to the right and bottom

	Map.AddMargin(Desc.cxSpacing + Desc.cxExtraMargin, cyInternalSpacing);
	}