void GenerateStats (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("STATS\n\n"); int iItemTypes = 0; for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pType = Universe.GetItemType(i); // Do not count virtual items if (pType->IsVirtual()) continue; iItemTypes++; } printf("Item types:\t\t%d\n", iItemTypes); printf("Ship classes:\t\t%d\n", Universe.GetShipClassCount()); printf("Station types:\t\t%d\n", Universe.GetStationTypeCount()); }
void GenerateRandomItemTables (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("RANDOM ITEM TABLES\n\n"); // Create a sorted list of item types CSymbolTable SortedList(FALSE, TRUE); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pType = Universe.GetItemType(i); SortedList.AddEntry(pType->GetSortName(), (CObject *)pType); } // Create the tables for (int iLevel = 1; iLevel <= MAX_ITEM_LEVEL; iLevel += 2) { for (TableTypes iTable = tableTypesFirst; iTable <= tableTypesCount; iTable = (enum TableTypes)((int)iTable + 1)) { int iCount = 0; ItemEntry Table[100]; // Fill the table with entries for each // item at this level for (i = 0; i < SortedList.GetCount(); i++) { CItemType *pType = (CItemType *)SortedList.GetValue(i); int iScore; if (iCount < 100 && ItemInTable(pType, iTable, iLevel, &iScore)) { Table[iCount].pType = pType; Table[iCount].iScore = iScore; iCount++; } } // Compute total score int iTotalScore = 0; for (i = 0; i < iCount; i++) iTotalScore += Table[i].iScore; // Compute chance for (i = 0; i < iCount; i++) { Table[i].iChance = (Table[i].iScore * 100) / iTotalScore; Table[i].iRemainder = (Table[i].iScore * 100) % iTotalScore; } // Compute remainder int iTotalChance = 0; for (i = 0; i < iCount; i++) iTotalChance += Table[i].iChance; while (iTotalChance < 100) { int iBestRemainder = 0; int iBestEntry = -1; for (i = 0; i < iCount; i++) if (Table[i].iRemainder > iBestRemainder) { iBestRemainder = Table[i].iRemainder; iBestEntry = i; } Table[iBestEntry].iChance++; Table[iBestEntry].iRemainder = 0; iTotalChance++; } // Title if (iCount > 0) { switch (iTable) { case tableArmorAndWeapons: printf("LEVEL %d: ARMOR AND WEAPONS\n\n", iLevel); break; case tableMiscItems: printf("LEVEL %d: MISCELLANEOUS ITEMS\n\n", iLevel); break; case tableUsefulItems: printf("LEVEL %d: USEFUL ITEMS\n\n", iLevel); break; } // Print table for (i = 0; i < iCount; i++) if (Table[i].iChance > 0) { //DWORD dwFlags; printf("%d\t%s\n", Table[i].iChance, //Table[i].pType->GetName(&dwFlags, true).GetASCIIZPointer()); Table[i].pType->GetSortName().GetASCIIZPointer()); } printf("\n"); } } } }
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 GenerateArmorTable (CUniverse &Universe, CXMLElement *pCmdLine) { int i; printf("ARMOR TABLE\n\n"); printf("Level\tArmor\tCost\tWeight\tHP\tLasr\tImpc\tPart\tBlst\tIon\tThrm\tPosi\tPlsm\tAnti\tNano\tGrav\tSing\tDacd\tDstl\tDlgt\tDfir\n"); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pItem = Universe.GetItemType(i); CArmorClass *pArmor = pItem->GetArmorClass(); if (pArmor == NULL) continue; CItem Item(pItem, 1); CString sName = pItem->GetName(NULL); int iHP = pArmor->GetMaxHP(CItemCtx(&Item)); printf("%d\t%s\t%d\t%d\t%d\t", pItem->GetLevel(), sName.GetASCIIZPointer(), Item.GetValue(true), Item.GetMassKg(), iHP); // For each damage type, compute the adjusted hit points of the armor int iDamage; for (iDamage = damageLaser; iDamage < damageCount; iDamage++) { printf("%d", pArmor->GetDamageAdj(CItemCtx(Item), (DamageTypes)iDamage)); if (iDamage != damageCount - 1) printf("\t"); } printf("\n"); } printf("ARMOR TABLE DAMAGE ADJUSTMENTS\n\n"); printf("Level\tArmor\tHP\tLasr\tImpc\tPart\tBlst\tIon\tThrm\tPosi\tPlsm\tAnti\tNano\tGrav\tSing\tDacd\tDstl\tDlgt\tDfir\n"); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pItem = Universe.GetItemType(i); CArmorClass *pArmor = pItem->GetArmorClass(); if (pArmor == NULL) continue; CString sName = pItem->GetName(NULL); CItem Item(pItem, 1); int iHP = pArmor->GetMaxHP(CItemCtx(&Item)); printf("%d\t%s\t%d\t", pItem->GetLevel(), sName.GetASCIIZPointer(), iHP); // For each damage type, compute the adjusted hit points of the armor int iDamage; for (iDamage = damageLaser; iDamage < damageCount; iDamage++) { int iAdj = pArmor->GetDamageAdj(CItemCtx(Item), (DamageTypes)iDamage); if (iAdj == 0) printf("----"); else printf("%d", iHP * 100 / iAdj); if (iDamage != damageCount - 1) printf("\t"); } printf("\n"); } }
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"); }