Exemple #1
0
void SortTable (SItemTableCtx &Ctx, const TArray<CItemType *> &List, SItemTypeList *retSorted)
	{
	int i;

	//	Loop over all items that match and add them to
	//	a sorted table.

	retSorted->DeleteAll();
	for (i = 0; i < List.GetCount(); i++)
		{
		CItemType *pType = List[i];

		//	Add with sort key

		char szBuffer[1024];
		wsprintf(szBuffer, "%02d%s%02d%s", 
				pType->GetLevel(),
				g_szTypeCode[GetItemType(pType)], 
				GetItemFreq(pType), 
				pType->GetNounPhrase().GetASCIIZPointer());
		retSorted->Insert(CString(szBuffer), pType);
		}
	}
void GenerateWeaponEffectChart (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	//	Compute the list of weapons to show, making sure we filter to weapons
	//	and missiles only.

	CItemTypeTable Selection;
	if (!Selection.Filter(pCmdLine->GetAttribute(CRITERIA_ATTRIB))
			|| (Selection.IsAll() && !Selection.Filter(CONSTLIT("wm"))))
		{
		printf("No entries match criteria.\n");
		return;
		}

	Selection.Sort();

	//	Ship to use

	DWORD dwPlatformUNID;
	if (!pCmdLine->FindAttributeInteger(SHIP_UNID_ATTRIB, (int *)&dwPlatformUNID))
		dwPlatformUNID = WEAPON_PLATFORM_UNID;

	//	Compute some metrics

	int iFramesPerItem = 10;
	int cxFrameHorzMargin = 10;
	int cxMaxDistPerTick = (int)(STD_SECONDS_PER_UPDATE * (LIGHT_SECOND / g_KlicksPerPixel));
	int cyFrame = 64;
	int cxFrame = (2 * cxFrameHorzMargin) + (iFramesPerItem * cxMaxDistPerTick);

	int iHitEffectFramesPerItem = 5;
	int cxHitEffect = 128;
	int cyHitEffect = 128;
	
	int cyRowTitle = 20;
	int cyRow = cyRowTitle + Max(ITEM_ICON_HEIGHT, cyFrame * iFramesPerItem);
	int cxRow = ITEM_ICON_WIDTH + cxFrame;

	int iColumns = Max(1, mathSqrt(Selection.GetCount()));
	int iRows = (Selection.GetCount() + (iColumns - 1)) / iColumns;

	int cxImage = cxRow * iColumns;
	int cyImage = cyRow * iRows;

	//	Initialize the output

	COutputChart Output;
	Output.SetContentSize(cxImage, cyImage);
	Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output")));

	//	Initialize fonts

	Output.SetStyleFont(STYLE_TITLE, pCmdLine->GetAttribute(CONSTLIT("font")));
	Output.SetStyleColor(STYLE_TITLE, CG32bitPixel(0xFF, 0xFF, 0xFF));

	//	Prepare the universe

	CSystem *pSystem;
	if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR)
		{
		printf("ERROR: Unable to create empty star system.\n");
		return;
		}

	//	Create a target in the center of the system

	CSpaceObject *pStation;
	CStationType *pTargetType = Universe.FindStationType(TARGET_UNID);
	if (pTargetType == NULL 
			|| pSystem->CreateStation(pTargetType, NULL, CVector(), &pStation) != NOERROR)
		{
		printf("ERROR: Unable to create station.\n");
		return;
		}

	//	Create the weapon platform some distance away

	CSovereign *pPlatformSovereign = Universe.FindSovereign(PLAYER_SOVEREIGN_UNID);
	CShip *pPlatform;
	if (pPlatformSovereign == NULL
				|| pSystem->CreateShip(dwPlatformUNID,
					NULL,
					NULL,
					pPlatformSovereign,
					CVector(-5.0 * LIGHT_SECOND, 0.),
					CVector(),
					0,
					NULL,
					NULL,
					&pPlatform) != NOERROR)
		{
		printf("ERROR: Unable to create weapons platform.\n");
		return;
		}

	//	Set the attacker to hold

	IShipController *pController = pPlatform->GetController();
	if (pController == NULL)
		{
		printf("ERROR: No controller for ship.\n");
		return;
		}

	pController->AddOrder(IShipController::orderHold, NULL, IShipController::SData());
	pPlatform->SetControllerEnabled(false);

	//	Install the largest possible reactor on the ship

	CItemType *pReactorType = Universe.FindItemType(REACTOR_UNID);
	if (pReactorType)
		{
		CItem ReactorItem(pReactorType, 1);

		CItemListManipulator ItemList(pPlatform->GetItemList());
		ItemList.AddItem(ReactorItem);
		pPlatform->OnComponentChanged(comCargo);
		pPlatform->ItemsModified();
		pPlatform->InvalidateItemListAddRemove();

		pPlatform->InstallItemAsDevice(ItemList);
		}

	//	Set the POV

	Universe.SetPOV(pStation);
	pSystem->SetPOVLRS(pStation);

	//	Prepare system

	Universe.UpdateExtended();
	Universe.GarbageCollectLibraryBitmaps();
	Universe.StartGame(true);

	//	Output each weapon

	int xOrigin;
	int yOrigin;
	CG32bitImage &Image = Output.GetOutputImage(&xOrigin, &yOrigin);
	const CG16bitFont &TitleFont = Output.GetStyleFont(STYLE_TITLE);
	CG32bitPixel rgbTitleColor = Output.GetStyleColor(STYLE_TITLE);

	for (i = 0; i < Selection.GetCount(); i++)
		{
		CItemType *pType = Selection.GetItemType(i);

		//	Compute the metrics of this row

		int xRow = xOrigin + (i % iColumns) * cxRow;
		int yRow = yOrigin + (i / iColumns) * cyRow;

		//	Paint the weapon title

		Image.Fill(xRow, yRow, cxRow, cyRow, CG32bitPixel(0x40, 0x40, 0x40));
		TitleFont.DrawText(Image, xRow + 8, yRow, rgbTitleColor, pType->GetNounPhrase());

		//	Paint the frames

		PaintWeaponFrames(Image, pType, pPlatform, iFramesPerItem, 
				xRow + ITEM_ICON_WIDTH + cxFrameHorzMargin,
				yRow + cyRowTitle, 
				cxMaxDistPerTick,
				cyFrame);
		}

	//	Done

	Output.Output();
	}
Exemple #3
0
void OutputByShipClass (SItemTableCtx &Ctx, const SItemTypeList &ItemList, bool bShowUsage)
	{
	int i, j;

	//	Make a map of ship classes for each item

	TSortMap<DWORD, TArray<CShipClass *>> ItemToShipClass;
	for (i = 0; i < g_pUniverse->GetShipClassCount(); i++)
		{
		CShipClass *pClass = g_pUniverse->GetShipClass(i);

		//	Skip non-generic ones

		if (!pClass->HasLiteralAttribute(CONSTLIT("genericClass")))
			continue;

		//	Add the list of types used by the ship

		TSortMap<DWORD, bool> TypesUsed;
		pClass->AddTypesUsed(&TypesUsed);

		//	For each item type, add it to the map

		for (j = 0; j < TypesUsed.GetCount(); j++)
			{
			CDesignType *pType = g_pUniverse->FindDesignType(TypesUsed.GetKey(j));
			if (pType && pType->GetType() == designItemType)
				{
				TArray<CShipClass *> *pList = ItemToShipClass.SetAt(pType->GetUNID());
				pList->Insert(pClass);
				}
			}
		}

	//	If we want to show usage, then we print each item along with the 
	//	ship classes using each item.

	if (bShowUsage)
		{
		for (i = 0; i < ItemList.GetCount(); i++)
			{
			CItemType *pType = ItemList[i];
			printf("%s\n", (LPSTR)pType->GetNounPhrase());

			TArray<CShipClass *> *pList = ItemToShipClass.SetAt(pType->GetUNID());
			for (j = 0; j < pList->GetCount(); j++)
				printf("\t%s\n", (LPSTR)pList->GetAt(j)->GetName());

			if (pList->GetCount() == 0)
				printf("\t(none)\n");

			printf("\n");
			}
		}

	//	Otherwise we categorize by ship class

	else
		{
		//	Now make a list of all ship classes that have our items

		SByShipClassTypeList ByShipClassTable;
		for (i = 0; i < ItemList.GetCount(); i++)
			{
			const CString &sKey = ItemList.GetKey(i);
			CItemType *pType = ItemList[i];

			//	Loop over all ship classes

			TArray<CShipClass *> *pList = ItemToShipClass.SetAt(pType->GetUNID());
			for (j = 0; j < pList->GetCount(); j++)
				{
				CString sClassName = pList->GetAt(j)->GetName();

				bool bNew;
				SShipClassEntry *pEntry = ByShipClassTable.SetAt(sClassName, &bNew);
				if (bNew)
					pEntry->sShipClassName = sClassName;

				pEntry->ItemTable.Insert(sKey, pType);
				}

			//	If no ship class

			if (pList->GetCount() == 0)
				{
				bool bNew;
				SShipClassEntry *pEntry = ByShipClassTable.SetAt(CONSTLIT("(none)"), &bNew);
				if (bNew)
					pEntry->sShipClassName = CONSTLIT("(none)");

				pEntry->ItemTable.Insert(sKey, pType);
				}
			}

		//	Now loop over all attributes

		for (i = 0; i < ByShipClassTable.GetCount(); i++)
			{
			const SShipClassEntry &Entry = ByShipClassTable[i];
			printf("%s\n\n", Entry.sShipClassName.GetASCIIZPointer());

			OutputHeader(Ctx);
			OutputTable(Ctx, Entry.ItemTable);
			printf("\n");
			}
		}
	}
Exemple #4
0
void GenerateImageChart (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	enum OrderTypes
		{
		orderSmallest = 1,
		orderLargest = 2,
		orderName = 3,
		orderLevel = 4,
		orderSovereign = 5,
		orderManufacturer = 6,
		};

	//	Item criteria

	bool bHasItemCriteria;
	CString sCriteria;
	CItemCriteria ItemCriteria;
	if (bHasItemCriteria = pCmdLine->FindAttribute(CONSTLIT("itemCriteria"), &sCriteria))
		CItem::ParseCriteria(sCriteria, &ItemCriteria);
	else
		CItem::InitCriteriaAll(&ItemCriteria);

	//	Get the criteria from the command line.

	CDesignTypeCriteria Criteria;
	if (pCmdLine->FindAttribute(CONSTLIT("criteria"), &sCriteria))
		{
		if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else if (bHasItemCriteria)
		{
		if (CDesignTypeCriteria::ParseCriteria(CONSTLIT("i"), &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else
		{
		printf("ERROR: Expected criteria.\n");
		return;
		}

	bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all"));

	//	Options

	bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly"));
	bool bFieldUNID = pCmdLine->GetAttributeBool(CONSTLIT("unid"));

	//	Figure out what order we want

	CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort"));
	int iOrder;
	if (strEquals(sOrder, CONSTLIT("smallest")))
		iOrder = orderSmallest;
	else if (strEquals(sOrder, CONSTLIT("largest")))
		iOrder = orderLargest;
	else if (strEquals(sOrder, CONSTLIT("level")))
		iOrder = orderLevel;
	else if (strEquals(sOrder, CONSTLIT("sovereign")))
		iOrder = orderSovereign;
	else if (strEquals(sOrder, CONSTLIT("manufacturer")))
		iOrder = orderManufacturer;
	else
		iOrder = orderName;

	bool b3DGrid = pCmdLine->GetAttributeBool(CONSTLIT("3DGrid"));
	bool bDockingPorts = pCmdLine->GetAttributeBool(CONSTLIT("portPos"));
	bool bDevicePos = pCmdLine->GetAttributeBool(CONSTLIT("devicePos"));

	//	Image size

	int cxDesiredWidth;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth))
		cxDesiredWidth = Max(512, cxDesiredWidth);
	else
		cxDesiredWidth = 1280;

	//	Spacing

	int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing"));
	int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin"));
	int cxImageMargin = 2 * pCmdLine->GetAttributeInteger(CONSTLIT("xImageMargin"));

	//	Font for text

	CString sTypeface;
	int iSize;
	bool bBold;
	bool bItalic;

	if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")),
			&sTypeface,
			&iSize,
			&bBold,
			&bItalic))
		{
		sTypeface = CONSTLIT("Arial");
		iSize = 10;
		bBold = false;
		bItalic = false;
		}

	CG16bitFont NameFont;
	NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic);
	CG32bitPixel rgbNameColor = CG32bitPixel(255, 255, 255);

	//	Rotation

	int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation"));

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

	//	Generate a sorted table of types

	TSortMap<CString, SEntryDesc> Table;
	for (i = 0; i < Universe.GetDesignTypeCount(); i++)
		{
		CDesignType *pType = Universe.GetDesignType(i);
		SEntryDesc NewEntry;

		//	Make sure we match the criteria

		if (!pType->MatchesCriteria(Criteria))
			continue;

		//	Figure stuff stuff out based on the specific design type

		switch (pType->GetType())
			{
			case designItemType:
				{
				CItemType *pItemType = CItemType::AsType(pType);
				CItem Item(pItemType, 1);

				//	Skip if not in item criteria

				if (!Item.MatchesCriteria(ItemCriteria))
					continue;

				//	Skip virtual classes

				if (pItemType->IsVirtual())
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pItemType->GetNounPhrase(0);
				NewEntry.pImage = &pItemType->GetImage();
				NewEntry.iSize = RectWidth(NewEntry.pImage->GetImageRect());
				break;
				}

			case designShipClass:
				{
				CShipClass *pClass = CShipClass::AsType(pType);

				//	Skip non-generic classess

				if (!bAll && !pClass->HasLiteralAttribute(CONSTLIT("genericClass")))
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pClass->GetNounPhrase(0);
				NewEntry.iSize = RectWidth(pClass->GetImage().GetImageRect());
				NewEntry.pImage = &pClass->GetImage();
				NewEntry.iRotation = pClass->Angle2Direction(iRotation);
				NewEntry.sSovereignName = (pClass->GetDefaultSovereign() ? pClass->GetDefaultSovereign()->GetTypeNounPhrase() : NULL_STR);
				break;
				}

			case designStationType:
				{
				CStationType *pStationType = CStationType::AsType(pType);

				//	Skip generic classes

				if (!bAll && !pStationType->HasLiteralAttribute(CONSTLIT("generic")))
					continue;

				NewEntry.pType = pType;
				NewEntry.sName = pStationType->GetNounPhrase(0);
				NewEntry.iSize = pStationType->GetSize();
				NewEntry.sSovereignName = (pStationType->GetSovereign() ? pStationType->GetSovereign()->GetTypeNounPhrase() : NULL_STR);

				InitStationTypeImage(NewEntry, pStationType);

				break;
				}

			default:
				//	Don't know how to handle this type
				continue;
				break;
			}

		//	Adjust name

		if (bFieldUNID)
			NewEntry.sName = strPatternSubst(CONSTLIT("%s (%x)"), NewEntry.sName, NewEntry.pType->GetUNID());

		//	Compute the sort key

		char szBuffer[1024];
		switch (iOrder)
			{
			case orderLargest:
				wsprintf(szBuffer, "%09d%s%x",
						1000000 - NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderLevel:
				wsprintf(szBuffer, "%09d%s%x",
						pType->GetLevel(),
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSmallest:
				wsprintf(szBuffer, "%09d%s%x",
						NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSovereign:
				wsprintf(szBuffer, "%s|%s|%x", NewEntry.sSovereignName.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = NewEntry.sSovereignName;
				break;

			case orderManufacturer:
				{
				CString sManufacturer = NewEntry.pType->GetPropertyString(CONSTLIT("manufacturer"));
				wsprintf(szBuffer, "%s|%s|%x", sManufacturer.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = sManufacturer;
				break;
				}

			default:
				wsprintf(szBuffer, "%s%x", NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				break;
			}

		//	Add to list

		Table.Insert(CString(szBuffer), NewEntry);
		}

	//	Allocate an arranger that tracks where to paint each world.

	CImageArranger Arranger;

	//	Settings for the overall arrangement

	CImageArranger::SArrangeDesc Desc;
	Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin)));
	Desc.cxSpacing = cxSpacing;
	Desc.cxExtraMargin = cxExtraMargin;
	Desc.pHeader = &NameFont;

	//	Generate a table of cells for the arranger

	TArray<CCompositeImageSelector> Selectors;
	Selectors.InsertEmpty(Table.GetCount());

	CString sLastCategory;
	TArray<CImageArranger::SCellDesc> Cells;
	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		CImageArranger::SCellDesc *pNewCell = Cells.Insert();
		pNewCell->cxWidth = (Entry.pImage ? RectWidth(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->cyHeight = (Entry.pImage ? RectHeight(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->sText = Entry.sName;

		if (!strEquals(sLastCategory, Entry.sCategorize))
			{
			sLastCategory = Entry.sCategorize;
			pNewCell->bStartNewRow = true;
			}
		}

	//	Arrange

	Arranger.ArrangeByRow(Desc, Cells);

	//	Create a large image

	CG32bitImage Output;
	int cxWidth = Max(cxDesiredWidth, Arranger.GetWidth());
	int cyHeight = Arranger.GetHeight();
	Output.Create(cxWidth, cyHeight);
	printf("Creating %dx%d image.\n", cxWidth, cyHeight);

	//	Paint the images

	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		int x = Arranger.GetX(i);
		int y = Arranger.GetY(i);

		//	Paint

		if (x != -1)
			{
			int xCenter = x + (Arranger.GetWidth(i) / 2);
			int yCenter = y + (Arranger.GetHeight(i) / 2);

			int xOffset;
			int yOffset;
			Entry.pImage->GetImageOffset(0, Entry.iRotation, &xOffset, &yOffset);
			int cxImage = RectWidth(Entry.pImage->GetImageRect());
			int cyImage = RectHeight(Entry.pImage->GetImageRect());

			//	Paint image

			if (!bTextBoxesOnly && Entry.pImage)
				{
				Entry.pImage->PaintImageUL(Output,
						x + (Arranger.GetWidth(i) - cxImage) / 2,
						y + (Arranger.GetHeight(i) - cyImage) / 2,
						0,
						Entry.iRotation);
				}

			//	Paint type specific stuff

			switch (Entry.pType->GetType())
				{
				case designStationType:
					{
					CStationType *pStationType = CStationType::AsType(Entry.pType);
                    int xStationCenter = xCenter - xOffset;
                    int yStationCenter = yCenter - yOffset;

					if (bDockingPorts)
						pStationType->PaintDockPortPositions(Output, xStationCenter, yStationCenter);

					if (bDevicePos)
						pStationType->PaintDevicePositions(Output, xStationCenter, yStationCenter);

                    //  If we have docking or device positions, mark the center of the station

                    if (bDockingPorts || bDevicePos)
                        {
                        const int LINE_HALF_LENGTH = 24;
                        const CG32bitPixel RGB_CENTER_CROSS(255, 255, 0);
                        Output.DrawLine(xStationCenter - LINE_HALF_LENGTH, yStationCenter, xStationCenter + LINE_HALF_LENGTH, yStationCenter, 1, RGB_CENTER_CROSS);
                        Output.DrawLine(xStationCenter, yStationCenter - LINE_HALF_LENGTH, xStationCenter, yStationCenter + LINE_HALF_LENGTH, 1, RGB_CENTER_CROSS);
                        }
					break;
					}
				}

			//	Paint the 3D grid, if necessary

			if (b3DGrid)
				{
				int iScale = Entry.pImage->GetImageViewportSize();
				Metric rMaxRadius = g_KlicksPerPixel * cxImage * 0.5;
				const Metric rGridSize = LIGHT_SECOND;

				Metric rRadius;
				for (rRadius = rGridSize; rRadius <= rMaxRadius; rRadius += rGridSize)
					{
					int iRadius = (int)((rRadius / g_KlicksPerPixel) + 0.5);
					const int iGridAngle = 8;
					int iPrevAngle = 0;
					int iAngle;
					for (iAngle = iGridAngle; iAngle <= 360; iAngle += iGridAngle)
						{
						int xFrom, yFrom;
						C3DConversion::CalcCoord(iScale, iPrevAngle, iRadius, 0, &xFrom, &yFrom);

						int xTo, yTo;
						C3DConversion::CalcCoord(iScale, iAngle, iRadius, 0, &xTo, &yTo);

						Output.DrawLine(xFrom + xCenter, yFrom + yCenter, xTo + xCenter, yTo + yCenter, 1, CG32bitPixel(255, 255, 0));

						iPrevAngle = iAngle;
						}
					}
				}

			//	Paint name

			int xText = Arranger.GetTextX(i);
			int yText = Arranger.GetTextY(i);
			if (xText != -1)
				{
				if (bTextBoxesOnly)
					Output.Fill(xText, yText, Arranger.GetTextWidth(i), Arranger.GetTextHeight(i), 0xffff);

				if (!bTextBoxesOnly)
					{
					Output.FillColumn(xCenter,
							y + Arranger.GetHeight(i),
							yText - (y + Arranger.GetHeight(i)),
							rgbNameColor);

					NameFont.DrawText(Output,
							xText,
							yText,
							rgbNameColor,
							Entry.sName);
					}
				}
			}
		}

	//	Write to file or clipboard

	OutputImage(Output, sFilespec);
	}
void GenerateShieldStats (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	CString sUNID = pCmdLine->GetAttribute(CONSTLIT("unid"));
	DWORD dwUNID = strToInt(sUNID, 0, NULL);
	CItemType *pItem = Universe.FindItemType(dwUNID);
	if (pItem == NULL)
		{
		CItemCriteria Crit;
		CItem::InitCriteriaAll(&Crit);
		CItem Item = CItem::CreateItemByName(sUNID, Crit);
		pItem = Item.GetType();

		if (pItem == NULL)
			{
			printf("ERROR: Unknown item '%s'\n", sUNID.GetASCIIZPointer());
			return;
			}
		}

	if (pItem->GetCategory() != itemcatShields)
		{
		printf("ERROR: Item '%s' is not a shield generator\n", pItem->GetNounPhrase().GetASCIIZPointer());
		return;
		}

	bool bVerbose = pCmdLine->GetAttributeBool(CONSTLIT("verbose"));
	bool bEval = pCmdLine->GetAttributeBool(CONSTLIT("eval"));

	//	Get the stats for the shield

	Metric rHP = (Metric)pItem->GetDataFieldInteger(FIELD_HP);
	Metric rHPRegenPerTick = pItem->GetDataFieldInteger(FIELD_REGEN) / 1000.0;

	int iDamageAdj[damageCount];
	CString sDamageAdj = pItem->GetDataField(CONSTLIT("damageAdj"));
	char *pPos = sDamageAdj.GetASCIIZPointer();
	int iCount = 0;
	while (iCount < damageCount)
		{
		iDamageAdj[iCount] = strParseInt(pPos, 0, &pPos, NULL);
		if (*pPos != '\0')
			pPos++;
		iCount++;
		}

	//	Print header

	printf("%s\n\n", pItem->GetNounPhrase().GetASCIIZPointer());

	//	Loop over all weapons and sort them by level and then name

	CSymbolTable List(FALSE, TRUE);
	for (i = 0; i < Universe.GetItemTypeCount(); i++)
		{
		CItemType *pWeapon = Universe.GetItemType(i);
		if (pWeapon->GetCategory() != itemcatWeapon)
			continue;

		CString sLevel = (pWeapon->GetLevel() < 10 ? strPatternSubst(CONSTLIT("0%d"), pWeapon->GetLevel()) : strFromInt(pWeapon->GetLevel(), FALSE));
		CString sSortName = strPatternSubst(CONSTLIT("%s%s"), sLevel, pWeapon->GetNounPhrase());
		List.AddEntry(sSortName, (CObject *)pWeapon);
		}

	//	Loop over sorted list and output data

	for (i = 0; i < List.GetCount(); i++)
		{
		CItemType *pWeapon = (CItemType *)List.GetValue(i);

		//	Get the data for the weapon

		int iFireDelay = pWeapon->GetDataFieldInteger(CONSTLIT("fireDelay"));
		Metric rAverageDamage = pWeapon->GetDataFieldInteger(CONSTLIT("averageDamage")) / 1000.0;
		int iDamageType = pWeapon->GetDataFieldInteger(CONSTLIT("damageType"));
		if (iDamageType < 0 || iDamageType >= damageCount)
			iDamageType = 0;

		//	Adjust damage for type

		rAverageDamage = rAverageDamage * (iDamageAdj[iDamageType] / 100.0);
		if (rAverageDamage < 1.0)
			rAverageDamage = 0.0;

		//	Calculate how many shots it would take to pierce through the shields

		char szBuffer[256];
		Metric rShotsToDeplete;
		Metric rRegenPerShot = rHPRegenPerTick * (Metric)iFireDelay;
		if (rRegenPerShot >= rAverageDamage)
			{
			rShotsToDeplete = 1000000.0;
			lstrcpy(szBuffer, "ineffective");
			}
		else
			{
			Metric rDrainPerShot = rAverageDamage - rRegenPerShot;
			rShotsToDeplete = rHP / rDrainPerShot;
			sprintf(szBuffer, "%.2f", rShotsToDeplete);
			}

		//	See if this weapon is overpowered or underpowered

		char szEval[256];
		if (bEval)
			{
			lstrcpy(szEval, "\t");
			if (pWeapon->GetLevel() < pItem->GetLevel())
				{
				if (rShotsToDeplete <= 10.0)
					lstrcpy(szEval, "\tOVERpowered");
				}
			else
				{
				if (rShotsToDeplete > 20.0)
					lstrcpy(szEval, "\tUNDERpowered");
				}
			}
		else
			lstrcpy(szEval, "");

		//	Print table

		if (bVerbose)
			{
			printf("%s\t%s\t%s\t(%d ticks; %.2f damage; %.2f regen/shot)%s\n",
					RomanNumeral(pWeapon->GetLevel()),
					pWeapon->GetNounPhrase().GetASCIIZPointer(),
					szBuffer,
					iFireDelay,
					rAverageDamage,
					rRegenPerShot,
					szEval);
			}
		else
			{
			printf("%s\t%s\t%s%s\n",
					RomanNumeral(pWeapon->GetLevel()),
					pWeapon->GetNounPhrase().GetASCIIZPointer(),
					szBuffer,
					szEval);
			}
		}
	}
void CUIHelper::CreateClassInfoItem (const CItem &Item, int x, int y, int cxWidth, DWORD dwOptions, const CString &sExtraDesc, int *retcyHeight, IAnimatron **retpInfo) const

//	CreateClassInfoItem
//
//	Creates an item info animation

	{
	const CVisualPalette &VI = m_HI.GetVisuals();
	const CG16bitFont &MediumFont = VI.GetFont(fontMedium);
	const CG16bitFont &MediumBoldFont = VI.GetFont(fontMediumBold);
	const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle);

	//	Handle some edge conditions

	CItemType *pType = Item.GetType();
	if (pType == NULL)
		{
		if (retcyHeight)
			*retcyHeight = 0;

		CAniSequencer::Create(CVector(x, y), (CAniSequencer **)retpInfo);
		return;
		}

	//	Figure out some dimensions and metrics. Everything is relative to x, y.

	bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false);
	int cxIcon = SMALL_ICON_WIDTH;
	int cyIcon = SMALL_ICON_HEIGHT;
	int xIcon = (bRightAlign ? -cxIcon : 0);
	int yIcon = 0;

	int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ);
	int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ);
	int yText = 0;

	//	Create a sequencer to hold all the controls

	CAniSequencer *pRoot;
	CAniSequencer::Create(CVector(x, y), &pRoot);

	//	Create a small item icon

	const CObjectImageArray &Image = pType->GetImage();
	RECT rcImage = Image.GetImageRect();
	if (!Image.IsEmpty())
		{
		CG16bitImage *pIcon = new CG16bitImage;
		pIcon->CreateFromImageTransformed(Image.GetImage(), 
				rcImage.left, 
				rcImage.top, 
				RectWidth(rcImage), 
				RectHeight(rcImage), 
				(Metric)SMALL_ICON_WIDTH / RectWidth(rcImage),
				(Metric)SMALL_ICON_HEIGHT / RectHeight(rcImage),
				0.0);

		IAnimatron *pImageFrame = new CAniRect;
		pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon));
		pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT));
		pImageFrame->SetFillMethod(new CAniImageFill(pIcon, true));

		pRoot->AddTrack(pImageFrame, 0);
		}

	//	Create text

	int cyText = 0;

	IAnimatron *pName = new CAniText;
	pName->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText));
	pName->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000));
	pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput));
	pName->SetPropertyFont(PROP_FONT, &MediumBoldFont);
	pName->SetPropertyString(PROP_TEXT, pType->GetNounPhrase(nounActual));
	if (bRightAlign)
		pName->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT);

	pRoot->AddTrack(pName, 0);
	cyText += MediumBoldFont.GetHeight();

	//	Add the damage type adjustment

	CItemDataAnimatron *pDamageDesc = new CItemDataAnimatron(VI, Item);
	if (!pDamageDesc->IsEmpty())
		{
		pDamageDesc->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText));
		pDamageDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000));
		if (bRightAlign)
			pDamageDesc->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT);

		pRoot->AddTrack(pDamageDesc, 0);

		RECT rcRect;
		pDamageDesc->GetSpacingRect(&rcRect);
		cyText += RectHeight(rcRect);
		}
	else
		delete pDamageDesc;

	//	Add the reference text

	CItemCtx ItemCtx;
	CString sRef = pType->GetReference(ItemCtx, -1, CItemType::FLAG_ACTUAL_ITEM);
	if (sRef.IsBlank())
		sRef = strPatternSubst(CONSTLIT("Level %s%s"), strLevel(pType->GetLevel()), sExtraDesc);
	else
		sRef = strPatternSubst(CONSTLIT("Level %s — %s%s"), strLevel(pType->GetLevel()), sRef, sExtraDesc);

	IAnimatron *pRef = new CAniText;
	pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText));
	pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000));
	pRef->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel));
	pRef->SetPropertyFont(PROP_FONT, &MediumFont);
	pRef->SetPropertyString(PROP_TEXT, sRef);
	if (bRightAlign)
		pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT);

	pRoot->AddTrack(pRef, 0);

	RECT rcRef;
	pRef->GetSpacingRect(&rcRef);
	cyText += RectHeight(rcRef);

	//	Done

	if (retcyHeight)
		*retcyHeight = Max(cyText, SMALL_ICON_HEIGHT);

	*retpInfo = pRoot;
	}
Exemple #7
0
void GenerateItemTable (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i, j;

	//	Compute the criteria

	CItemCriteria Crit;
	CString sCriteria;
	if (pCmdLine->FindAttribute(CRITERIA_ATTRIB, &sCriteria))
		CItem::ParseCriteria(sCriteria, &Crit);
	else
		CItem::InitCriteriaAll(&Crit);

	//	Generate a table

	CSymbolTable Table(FALSE, TRUE);

	//	Loop over all items that match and add them to
	//	a sorted table.

	for (j = 0; j < Universe.GetItemTypeCount(); j++)
		{
		CItemType *pType = Universe.GetItemType(j);
		CItem Item(pType, 1);

		if (!Item.MatchesCriteria(Crit))
			continue;

		//	Figure out the sort order

		char szBuffer[1024];
		wsprintf(szBuffer, "%02d%s%02d%s", 
				pType->GetLevel(),
				g_szTypeCode[GetItemType(pType)], 
				GetItemFreq(pType), 
				pType->GetNounPhrase().GetASCIIZPointer());
		Table.AddEntry(CString(szBuffer), (CObject *)pType);
		}

	//	If we need to output total count, then load the table

	CSymbolTable TotalCount(TRUE, TRUE);
	if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT))
		{
		if (error = LoadTotalCount(TOTAL_COUNT_FILENAME, TotalCount))
			return;
		}

	//	If we've got any entries in the table, output now

	if (Table.GetCount())
		{
		//	Generate a list of columns to display

		CStringArray Cols;
		Cols.AppendString(FIELD_LEVEL);
		Cols.AppendString(FIELD_TYPE);
		Cols.AppendString(FIELD_FREQUENCY);
		Cols.AppendString(FIELD_NAME);

		//	More columns from command-line

		if (pCmdLine->GetAttributeBool(FIELD_AVERAGE_COUNT))
			Cols.AppendString(FIELD_AVERAGE_COUNT);
		if (pCmdLine->GetAttributeBool(FIELD_BALANCE))
			Cols.AppendString(FIELD_BALANCE);
		if (pCmdLine->GetAttributeBool(FIELD_COST))
			Cols.AppendString(FIELD_COST);
		if (pCmdLine->GetAttributeBool(FIELD_INSTALL_COST))
			Cols.AppendString(FIELD_INSTALL_COST);
		if (pCmdLine->GetAttributeBool(FIELD_MASS))
			Cols.AppendString(FIELD_MASS);
		if (pCmdLine->GetAttributeBool(FIELD_TOTAL_COUNT))
			Cols.AppendString(FIELD_TOTAL_COUNT);
		if (pCmdLine->GetAttributeBool(FIELD_REFERENCE))
			Cols.AppendString(FIELD_REFERENCE);

		if (pCmdLine->GetAttributeBool(FIELD_HP))
			Cols.AppendString(FIELD_HP);
		if (pCmdLine->GetAttributeBool(FIELD_HP_BONUS))
			Cols.AppendString(FIELD_HP_BONUS);
		if (pCmdLine->GetAttributeBool(FIELD_REGEN))
			Cols.AppendString(FIELD_REGEN);
		if (pCmdLine->GetAttributeBool(FIELD_FIRE_DELAY))
			Cols.AppendString(FIELD_FIRE_DELAY);
		if (pCmdLine->GetAttributeBool(FIELD_THRUST))
			Cols.AppendString(FIELD_THRUST);
		if (pCmdLine->GetAttributeBool(FIELD_POWER))
			Cols.AppendString(FIELD_POWER);

		if (pCmdLine->GetAttributeBool(FIELD_POWER_PER_SHOT))
			Cols.AppendString(FIELD_POWER_PER_SHOT);
		if (pCmdLine->GetAttributeBool(FIELD_AVERAGE_DAMAGE))
			Cols.AppendString(FIELD_AVERAGE_DAMAGE);
		if (pCmdLine->GetAttributeBool(FIELD_MAX_SPEED))
			Cols.AppendString(FIELD_MAX_SPEED);

		//	Output the header

		for (j = 0; j < Cols.GetCount(); j++)
			{
			if (j != 0)
				printf("\t");

			printf(Cols.GetStringValue(j).GetASCIIZPointer());
			}

		printf("\n");

		//	Output each row

		for (i = 0; i < Table.GetCount(); i++)
			{
			CItemType *pType = (CItemType *)Table.GetValue(i);

			for (j = 0; j < Cols.GetCount(); j++)
				{
				if (j != 0)
					printf("\t");

				CString sField = Cols.GetStringValue(j);
				CString sValue = pType->GetDataField(sField);

				if (strEquals(sField, FIELD_AVERAGE_DAMAGE) || strEquals(sField, FIELD_POWER_PER_SHOT))
					printf("%.2f", strToInt(sValue, 0, NULL) / 1000.0);
				else if (strEquals(sField, FIELD_POWER))
					printf("%.1f", strToInt(sValue, 0, NULL) / 1000.0);
				else if (strEquals(sField, FIELD_TOTAL_COUNT))
					{
					double rCount = 0.0;

					CString sKey = strFromInt(pType->GetUNID(), FALSE);
					EntryInfo *pEntry;
					if (TotalCount.Lookup(sKey, (CObject **)&pEntry) == NOERROR)
						rCount = pEntry->rTotalCount;

					printf("%.2f", rCount);
					}
				else
					printf(sValue.GetASCIIZPointer());
				}

			printf("\n");
			}

		printf("\n");
		}
	else
		printf("No entries match criteria.\n");
	}
void CPlayerGameStats::GenerateGameStats (CGameStats &Stats, CSpaceObject *pPlayerShip, bool bGameOver) const

//	GenerateGameStats
//
//	Generates a stats for everything we track

	{
	int j;

	CShip *pShip = (pPlayerShip ? pPlayerShip->AsShip() : NULL);
	if (pShip == NULL)
		return;

	CPlayerShipController *pPlayer = (CPlayerShipController *)pShip->GetController();
	if (pPlayer == NULL)
		return;

	CSovereign *pPlayerSovereign = g_pUniverse->FindSovereign(g_PlayerSovereignUNID);
	if (pPlayerSovereign == NULL)
		return;

	//	Base stats

	Stats.Insert(CONSTLIT("Genome"), strCapitalize(GetGenomeName(pPlayer->GetPlayerGenome())));
	Stats.Insert(CONSTLIT("Score"), strFormatInteger(CalcEndGameScore(), -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED));
	Stats.Insert(CONSTLIT("Ship class"), pShip->GetNounPhrase(0));

	CTimeSpan Time = GetPlayTime();
	if (!Time.IsBlank())
		Stats.Insert(CONSTLIT("Time played"), Time.Format(NULL_STR));

#ifdef REAL_TIME
	Time = GetGameTime();
	if (!Time.IsBlank())
		Stats.Insert(CONSTLIT("Time elapsed in game"), Time.Format(NULL_STR));
#endif

	//	Some combat stats

	CString sDestroyed = GetStat(ENEMY_SHIPS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Enemy ships destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(FRIENDLY_SHIPS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Friendly ships destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(ENEMY_STATIONS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Enemy stations destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(FRIENDLY_STATIONS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Friendly stations destroyed"), sDestroyed, CONSTLIT("combat"));

	//	Add stat for every station destroyed

	CStatCounterArray CounterArray;

	CMapIterator i;
	m_StationStats.Reset(i);
	while (m_StationStats.HasMore(i))
		{
		SStationTypeStats *pStats;
		DWORD dwUNID = m_StationStats.GetNext(i, &pStats);
		CStationType *pType = g_pUniverse->FindStationType(dwUNID);
		if (pType == NULL)
			continue;

		CString sName = pType->GetNounPhrase(0);
		CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pType->GetLevel(), sName);

		if (pType->GetSovereign()->IsEnemy(pPlayerSovereign))
			CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Enemy stations destroyed"), sSort);
		else
			CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Friendly stations destroyed"), sSort);
		}

	CounterArray.GenerateGameStats(Stats);
		
	//	Add stat for every ship class destroyed

	CounterArray.DeleteAll();
	m_ShipStats.Reset(i);
	while (m_ShipStats.HasMore(i))
		{
		SShipClassStats *pStats;
		DWORD dwUNID = m_ShipStats.GetNext(i, &pStats);
		CShipClass *pClass = g_pUniverse->FindShipClass(dwUNID);
		if (pClass == NULL)
			continue;

		CString sName = pClass->GetNounPhrase(0);
		CString sSort = strPatternSubst(CONSTLIT("%09d%s"), 100000000 - pClass->GetScore(), sName);

		if (pStats->iEnemyDestroyed > 0)
			CounterArray.Insert(sName, pStats->iEnemyDestroyed, CONSTLIT("Enemy ships destroyed"), sSort);

		if (pStats->iFriendDestroyed > 0)
			CounterArray.Insert(sName, pStats->iFriendDestroyed, CONSTLIT("Friendly ships destroyed"), sSort);
		}

	CounterArray.GenerateGameStats(Stats);

	//	Add stat for every weapon fired

	m_ItemStats.Reset(i);
	while (m_ItemStats.HasMore(i))
		{
		SItemTypeStats *pStats;
		DWORD dwUNID = m_ItemStats.GetNext(i, &pStats);
		CItemType *pItemType = g_pUniverse->FindItemType(dwUNID);
		if (pItemType == NULL)
			continue;

		CString sName = pItemType->GetNounPhrase(nounShort);
		CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pItemType->GetLevel(), sName);

		//	Installed items

		if (pStats->dwFirstInstalled != INVALID_TIME)
			Stats.Insert(sName, NULL_STR, CONSTLIT("Items installed"), sSort);

		if (pStats->iCountFired > 0)
			Stats.Insert(sName, 
					strFormatInteger(pStats->iCountFired, -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED), 
					CONSTLIT("Weapons fired"), 
					sSort);
		}

	//	Stats for player equipment (but only if the game is done)

	if (bGameOver)
		{
		TSortMap<CString, CItem> InstalledItems;

		//	First we generate a sorted list of installed items
		//	(We do this in case there are multiple of the same device/armor so that
		//	we can coalesce them together into a single line).

		CItemListManipulator ItemList(pShip->GetItemList());
		ItemList.ResetCursor();
		while (ItemList.MoveCursorForward())
			{
			const CItem &Item(ItemList.GetItemAtCursor());

			if (Item.IsInstalled())
				{
				CString sEnhancement = Item.GetEnhancedDesc(pShip);
				CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly | nounShort);
				CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));

				bool bInserted;
				CItem *pEntry = InstalledItems.SetAt(sLine, &bInserted);
				if (bInserted)
					{
					*pEntry = Item;
					pEntry->SetCount(1);
					}
				else
					pEntry->SetCount(pEntry->GetCount() + 1);
				}
			}

		//	Now add all the installed items to the stats

		for (j = 0; j < InstalledItems.GetCount(); j++)
			{
			//	Redo the line now that we know the proper count

			CString sEnhancement = InstalledItems[j].GetEnhancedDesc(pShip);
			CString sItemName = InstalledItems[j].GetNounPhrase(nounActual | nounCountOnly);
			CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));

			//	Compute the sort order

			int iOrder;
			switch (InstalledItems[j].GetType()->GetCategory())
				{
				case itemcatWeapon:
					iOrder = 0;
					break;

				case itemcatLauncher:
					iOrder = 1;
					break;

				case itemcatShields:
					iOrder = 2;
					break;

				case itemcatArmor:
					iOrder = 3;
					break;

				case itemcatReactor:
					iOrder = 4;
					break;

				case itemcatDrive:
					iOrder = 5;
					break;

				default:
					iOrder = 6;
					break;
				}

			CString sSort = strPatternSubst(CONSTLIT("%d%03d%s"), iOrder, 100 - InstalledItems[j].GetType()->GetLevel(), sLine);
			Stats.Insert(sLine, NULL_STR, CONSTLIT("Final equipment"), sSort);
			}

		//	Add the remaining items

		ItemList.ResetCursor();
		while (ItemList.MoveCursorForward())
			{
			const CItem &Item(ItemList.GetItemAtCursor());

			if (!Item.IsInstalled())
				{
				CString sEnhancement = Item.GetEnhancedDesc(pShip);
				CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly);
				CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));
				CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - Item.GetType()->GetLevel(), sLine);

				Stats.Insert(sLine, NULL_STR, CONSTLIT("Final items"), sSort);
				}
			}
		}
	}