CArmorClass *CItemCtx::GetArmorClass(void) // GetArmorClass // // Returns the armor class { // Get it from the installed device if (m_pArmor) return m_pArmor->GetClass(); // Otherwise, get it from the item if (m_pItem) { CItemType *pType = m_pItem->GetType(); if (pType) return pType->GetArmorClass(); } // Couldn't get it return NULL; }
ALERROR CShieldClass::OnDesignLoadComplete (SDesignLoadCtx &Ctx) // OnDesignLoadComplete // // Bind design { ALERROR error; // Compute shield damage adjustments if (error = m_DamageAdj.Bind(Ctx, g_pUniverse->GetShieldDamageAdj(m_iDamageAdjLevel))) return error; // Load events CItemType *pType = GetItemType(); pType->InitCachedEvents(evtCount, CACHED_EVENTS, m_CachedEvents); // Hit effect if (error = m_pHitEffect.Bind(Ctx)) return error; // If the hit effect is NULL, then use default if (m_pHitEffect == NULL) m_pHitEffect.Set(g_pUniverse->FindEffectType(g_ShieldEffectUNID)); return NOERROR; }
bool CDeviceClass::FindAmmoDataField (CItemType *pItem, const CString &sField, CString *retsValue) // FindAmmoDataField // // Finds the device that fires this item and returns the given field { int i; for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); CDeviceClass *pWeapon; if (pType->IsDevice() && (pWeapon = pType->GetDeviceClass())) { int iVariant = pWeapon->GetAmmoVariant(pItem); if (iVariant != -1) return pWeapon->FindDataField(iVariant, sField, retsValue); } } return false; }
void CRandomItems::AddItems (SItemAddCtx &Ctx) // AddItems // // Add items { int i, j; int iRoll = mathRandom(1, 1000); bool bAllAtOnce = (m_iDamaged == 0 && m_Enhanced.GetChance() == 0); for (i = 0; i < m_iCount; i++) { iRoll -= m_Table[i].iProbability; if (iRoll <= 0) { CItemType *pType = m_Table[i].pType; int iCount = pType->GetNumberAppearing().Roll(); // If we don't have a chance of enhancement or damage, just optimize the // result by adding a group of items. if (bAllAtOnce) Ctx.ItemList.AddItem(CItem(m_Table[i].pType, iCount)); // If this is armor, then treat them as a block else if (pType->GetCategory() == itemcatArmor) { CItem Item(m_Table[i].pType, iCount); if (mathRandom(1, 100) <= m_iDamaged) Item.SetDamaged(); else m_Enhanced.EnhanceItem(Item); Ctx.ItemList.AddItem(Item); } // Otherwise, enhance/damage each item individually else { for (j = 0; j < iCount; j++) { CItem Item(m_Table[i].pType, 1); if (mathRandom(1, 100) <= m_iDamaged) Item.SetDamaged(); else m_Enhanced.EnhanceItem(Item); Ctx.ItemList.AddItem(Item); } } break; } } }
bool CWeaponFireDesc::FindEventHandler (const CString &sEvent, SEventHandlerDesc *retEvent) const // FindEventHandler // // Returns an event handler (if found) { // Look for an event handler at the weapon fire level ICCItem *pCode; if (m_Events.FindEvent(sEvent, &pCode)) { if (retEvent) { retEvent->pExtension = m_pExtension; retEvent->pCode = pCode; } return true; } // Then look for an event handler at the item level CItemType *pDevice; CItemType *pAmmo = GetWeaponType(&pDevice); if (pAmmo && pAmmo->FindEventHandler(sEvent, retEvent)) return true; if (pDevice && pAmmo != pDevice && pDevice->FindEventHandler(sEvent, retEvent)) return true; // Otherwise, we have no event return false; }
bool CDeviceClass::FindWeaponFor (CItemType *pItem, CDeviceClass **retpWeapon, int *retiVariant, CWeaponFireDesc **retpDesc) // FindWeaponFor // // Returns weapon data for the given item (which may be a weapon or a missile). { int i; CDeviceClass *pDevice; int iVariant; // Get the device and variant if (pItem->IsMissile()) { iVariant = -1; for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); if (pDevice = pType->GetDeviceClass()) { iVariant = pDevice->GetAmmoVariant(pItem); if (iVariant != -1) break; } } if (iVariant == -1) return false; } else { pDevice = pItem->GetDeviceClass(); if (pDevice == NULL) return false; iVariant = 0; } CWeaponClass *pWeapon = pDevice->AsWeaponClass(); if (pWeapon == NULL) return false; CWeaponFireDesc *pDesc = pWeapon->GetVariant(iVariant); // Done if (retpWeapon) *retpWeapon = pDevice; if (retiVariant) *retiVariant = iVariant; if (retpDesc) *retpDesc = pDesc; return true; }
void OutputTable (SItemTableCtx &Ctx, const SItemTypeList &ItemList) { int i, j; if (ItemList.GetCount() == 0) return; // Output each row for (i = 0; i < ItemList.GetCount(); i++) { CItemType *pType = ItemList[i]; for (j = 0; j < Ctx.Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Ctx.Cols[j]; // Get the field value CString sValue; CItem Item(pType, 1); CItemCtx ItemCtx(Item); CCodeChainCtx CCCtx; ICCItem *pResult = Item.GetProperty(&CCCtx, ItemCtx, sField); if (pResult->IsNil()) sValue = NULL_STR; else sValue = pResult->Print(&g_pUniverse->GetCC(), PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY); pResult->Discard(&g_pUniverse->GetCC()); // Format the value 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)) { SDesignTypeInfo *pInfo = Ctx.TotalCount.GetAt(pType->GetUNID()); double rCount = (pInfo ? pInfo->rPerGameMeanCount : 0.0); printf("%.2f", rCount); } else printf(sValue.GetASCIIZPointer()); } printf("\n"); } }
void OutputByAttribute (SItemTableCtx &Ctx, const SItemTypeList &ItemList) { int i, j; // Make a categorized list by attribute SByAttributeTypeList ByAttributeTable; for (i = 0; i < ItemList.GetCount(); i++) { const CString &sKey = ItemList.GetKey(i); CItemType *pType = ItemList[i]; // Loop over all attributes TArray<CString> Attribs; ParseAttributes(pType->GetAttributes(), &Attribs); for (j = 0; j < Attribs.GetCount(); j++) { bool bNew; SAttributeEntry *pEntry = ByAttributeTable.SetAt(Attribs[j], &bNew); if (bNew) pEntry->sAttribute = Attribs[j]; pEntry->ItemTable.Insert(sKey, pType); } // If no attribute if (Attribs.GetCount() == 0) { bool bNew; SAttributeEntry *pEntry = ByAttributeTable.SetAt(CONSTLIT("(none)"), &bNew); if (bNew) pEntry->sAttribute = CONSTLIT("(none)"); pEntry->ItemTable.Insert(sKey, pType); } } // Now loop over all attributes for (i = 0; i < ByAttributeTable.GetCount(); i++) { const SAttributeEntry &Entry = ByAttributeTable[i]; printf("%s\n\n", Entry.sAttribute.GetASCIIZPointer()); OutputHeader(Ctx); OutputTable(Ctx, Entry.ItemTable); printf("\n"); } }
IContentItem* CRootItem::addContentItem(string text, int posInParent) throw (ExMalformedPatch) { string path = stripFirstSection(text); CItemType itemType = getItemType(text); if(itemType.getType() == CItemType::E_INVAL ) { throw ExMalformedPatch("invalid item type", -1); } CCategoryItem* parent = getCategoryPtr(path); if(parent == 0) { parent = mkPath(path); } //beginInsertItems(posInParent, 1, parent ); IContentItem* newItem = IContentItem::itemFactory( itemType, this, text, parent, posInParent); //endInsertItems(); return newItem; }
CurrencyValue CRandomItems::GetAverageValue (int iLevel) // GetAverageValue // // Returns the average value. { int i; // If this is a dynamic table we need to compute all levels if (m_bDynamicLevelFrequency) { Metric rTotal = 0.0; InitTable(GenerateLevelFrequency(m_sLevelFrequency, iLevel)); m_iDynamicLevel = iLevel; for (i = 0; i < m_iCount; i++) { CItemType *pType = m_Table[i].pType; CurrencyValue ItemValue = CEconomyType::ExchangeToCredits(pType->GetCurrencyType(), pType->GetValue(CItemCtx(), true)); rTotal += (pType->GetNumberAppearing().GetAveValueFloat() * (Metric)ItemValue * (Metric)m_Table[i].iProbability / 1000.0); } return (CurrencyValue)(rTotal + 0.5); } // Otherwise the table is already initialized. else { // Average value is proportional to chances. Metric rTotal = 0.0; for (i = 0; i < m_iCount; i++) { CItemType *pType = m_Table[i].pType; CurrencyValue ItemValue = CEconomyType::ExchangeToCredits(pType->GetCurrencyType(), pType->GetValue(CItemCtx(), true)); rTotal += (pType->GetNumberAppearing().GetAveValueFloat() * (Metric)ItemValue * (Metric)m_Table[i].iProbability / 1000.0); } return (CurrencyValue)(rTotal + 0.5); } }
void CRootItem::setContentPtr(const CItemType& type, IContentItem* ptr, const uint32_t hash) { pair<map<uint32_t, IContentItem*>::iterator, bool> ret; map<uint32_t, IContentItem*>* content_map = m_content_maps[type.getType()]; ret = content_map->insert(pair<uint32_t, IContentItem*>(hash, ptr)); if (ret.second==false) { std::cerr << "setContentPtr: element '" << ret.first->first << "' already existed"; std::cerr << " with a value of " << ret.first->second << std::endl; } }
ALERROR CArmorClass::OnBindDesign (SDesignLoadCtx &Ctx) // OnBindDesign // // Called on Bind { ALERROR error; // Compute armor damage adjustments if (error = m_DamageAdj.Bind(Ctx, g_pUniverse->GetArmorDamageAdj(m_iDamageAdjLevel))) return error; // Cache some events CItemType *pType = GetItemType(); pType->InitCachedEvents(evtCount, CACHED_EVENTS, m_CachedEvents); return NOERROR; }
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 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); } }
bool CWeaponBenchmarkCtx::InitArmorTable (void) // InitArmorTable // // Initializes the armor table, which lists armor by level. { int i; // If we've already initialized the table, then nothing to do. if (m_ArmorTable.GetCount() != 0) return true; // Create table for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); // Skip non-armor if (!pType->IsArmor() || pType->IsVirtual()) continue; // Add to our list, indexed by level. TArray<CItemType *> *pTable = m_ArmorTable.SetAt(pType->GetLevel()); pTable->Insert(pType); } // Done return true; }
CWeaponFireDesc *CWeaponFireDesc::FindWeaponFireDescFromFullUNID (const CString &sUNID) // FindWeaponFireDesc // // Finds the descriptor by name { char *pPos = sUNID.GetPointer(); // Get the UNID of the type DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos); if (dwUNID == 0) return NULL; // Get the type CDesignType *pType = g_pUniverse->FindDesignType(dwUNID); if (pType == NULL) return NULL; // If this is an item, then it must be a weapon if (pType->GetType() == designItemType) { CItemType *pItemType = CItemType::AsType(pType); ASSERT(pItemType); CDeviceClass *pDevice = pItemType->GetDeviceClass(); if (pDevice == NULL) return NULL; CWeaponClass *pClass = pDevice->AsWeaponClass(); if (pClass == NULL) return NULL; // Get the ordinal ASSERT(*pPos == '/'); pPos++; int iOrdinal = strParseInt(pPos, 0, &pPos); // Get the weapon fire desc of the ordinal CWeaponFireDesc *pDesc = pClass->GetVariant(iOrdinal); if (pDesc == NULL) return NULL; // Continue parsing return pDesc->FindWeaponFireDesc(CString(pPos)); } // If this is an effect, then get it from that else if (pType->GetType() == designEffectType) { CEffectCreator *pEffectType = CEffectCreator::AsType(pType); ASSERT(pEffectType); // Expect /d ASSERT(*pPos == '/'); pPos++; ASSERT(*pPos == 'd'); pPos++; CWeaponFireDesc *pDesc = pEffectType->GetDamageDesc(); if (pDesc == NULL) return NULL; // Continue parsing return pDesc->FindWeaponFireDesc(CString(pPos)); } // Otherwise, we don't know else return NULL; }
void CRandomItems::InitTable (void) // InitTable // // Initializes the m_Table array. // // We assume that m_Criteria, m_sLevelFrequency, m_iLevel, and m_iLevelCurve are properly initialized. { int i; // Start by allocating an array large enough to hold // all item types in the universe ItemEntryStruct *pTable = new ItemEntryStruct [g_pUniverse->GetItemTypeCount()]; int iTableSize = 0; // Figure out if we should use level curves or level frequency bool bUseLevelFrequency = !m_sLevelFrequency.IsBlank(); // Iterate over every item type and add it to the table if // it matches the given criteria for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); CItem Item(pType, 1); // Skip if the item doesn't match the categories if (!Item.MatchesCriteria(m_Criteria)) continue; // Skip if this item is not found randomly if (pType->GetFrequency() == ftNotRandom) continue; // Adjust score based on level, either the level curve // or the level frequency string. int iScore; if (bUseLevelFrequency) { iScore = 1000 * GetFrequencyByLevel(m_sLevelFrequency, pType->GetLevel()) / ftCommon; } else { // Skip if the item is not within the level curve if ((pType->GetLevel() < m_iLevel - m_iLevelCurve) || (pType->GetLevel() > m_iLevel + m_iLevelCurve)) continue; // If we get this far then the item perfectly matches // and we need to add it to our table. First, however, we need // to calculate a score. // // The score is number that represents how common the item // is in the table. Later we normalize the score to be a probability int iLevelDelta = pType->GetLevel() - m_iLevel; switch (iLevelDelta) { case 0: iScore = 1000; break; case 1: case -1: iScore = 500; break; case 2: case -2: iScore = 200; break; default: iScore = 50; } } // Adjust score based on item frequency iScore = iScore * pType->GetFrequency() * 10 / (ftCommon * 10); // If we have a score of 0 then we skip this item if (iScore == 0) continue; // Add the item to the table pTable[iTableSize].pType = pType; pTable[iTableSize].iChance = iScore; iTableSize++; } // We must have items if (iTableSize == 0) { m_iCount = 0; m_Table = NULL; return; } // Add up the total score of all items int iTotalScore = 0; for (i = 0; i < iTableSize; i++) iTotalScore += pTable[i].iChance; // Compute the chance int iTotalChance = 0; for (i = 0; i < iTableSize; i++) { int iScore = pTable[i].iChance; pTable[i].iChance = (iScore * 1000) / iTotalScore; pTable[i].iRemainder = (iScore * 1000) % iTotalScore; iTotalChance += pTable[i].iChance; } // Distribute the remaining chance points while (iTotalChance < 1000) { // Look for the entry with the biggest remainder int iBestRemainder = 0; int iBestEntry = -1; for (i = 0; i < iTableSize; i++) if (pTable[i].iRemainder > iBestRemainder) { iBestRemainder = pTable[i].iRemainder; iBestEntry = i; } pTable[iBestEntry].iChance++; pTable[iBestEntry].iRemainder = 0; iTotalChance++; } // Count the number of entries that we've got m_iCount = 0; for (i = 0; i < iTableSize; i++) if (pTable[i].iChance > 0) m_iCount++; // Now loop over the entire table and add it to the // random entry generator m_Table = new SEntry [m_iCount]; int j = 0; for (i = 0; i < iTableSize; i++) if (pTable[i].iChance > 0) { m_Table[j].pType = pTable[i].pType; m_Table[j].iProbability = pTable[i].iChance; j++; } // Done delete [] pTable; }
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"); } } }
void OutputTable (SItemTableCtx &Ctx, const SItemTypeList &ItemList) { int i, j; if (ItemList.GetCount() == 0) return; // Output each row for (i = 0; i < ItemList.GetCount(); i++) { CItemType *pType = ItemList[i]; CItem Item(pType, 1); CItemCtx ItemCtx(Item); for (j = 0; j < Ctx.Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Ctx.Cols[j]; // Handle some special fields if (strEquals(sField, FIELD_BENCHMARK)) { CWeaponBenchmarkCtx::SStats Stats; if (!Ctx.WeaponBenchmarks.GetStats(pType, Stats)) { printf("\t\t\t\t"); } else { CString sBestArmor; if (Stats.pBestArmor) { CItem BestArmor(Stats.pBestArmor, 1); sBestArmor = BestArmor.GetNounPhrase(nounShort); } CString sWorstArmor; if (Stats.pWorstArmor) { CItem WorstArmor(Stats.pWorstArmor, 1); sWorstArmor = WorstArmor.GetNounPhrase(nounShort); } printf("%d\t%s\t%d\t%s\t%d", Stats.iAverageTime, (LPSTR)sBestArmor, Stats.iBestTime, (LPSTR)sWorstArmor, Stats.iWorstTime); } } else if (strEquals(sField, FIELD_BALANCE_STATS)) { CDeviceClass *pDevice = pType->GetDeviceClass(); CWeaponClass *pWeapon = NULL; if (pDevice) pWeapon = pDevice->AsWeaponClass(); else if (pType->IsMissile() && ItemCtx.ResolveVariant()) { pDevice = ItemCtx.GetVariantDevice(); pWeapon = pDevice->AsWeaponClass(); } if (pWeapon) { CWeaponClass::SBalance Balance; pWeapon->CalcBalance(ItemCtx, Balance); printf("%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f", Balance.rBalance, Balance.rBalance - Balance.rCost, Balance.rDamage, Balance.rDamageType, Balance.rAmmo, Balance.rOmni, Balance.rTracking, Balance.rRange, Balance.rSpeed, Balance.rWMD, Balance.rRadiation, Balance.rMining, Balance.rShatter, Balance.rDeviceDisrupt, Balance.rDeviceDamage, Balance.rDisintegration, Balance.rShieldPenetrate, Balance.rArmor, Balance.rShield, Balance.rProjectileHP, Balance.rPower, Balance.rCost, Balance.rSlots, Balance.rExternal, Balance.rLinkedFire, Balance.rRecoil ); } else printf("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"); } // Get the field value else { CString sValue; CCodeChainCtx CCCtx; ICCItem *pResult = Item.GetProperty(&CCCtx, ItemCtx, sField); if (pResult->IsNil()) sValue = NULL_STR; else sValue = pResult->Print(&g_pUniverse->GetCC(), PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY); pResult->Discard(&g_pUniverse->GetCC()); // Format the value if (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)) { SDesignTypeInfo *pInfo = Ctx.TotalCount.GetAt(pType->GetUNID()); double rCount = (pInfo ? pInfo->rPerGameMeanCount : 0.0); printf("%.2f", rCount); } else printf(sValue.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 CRootItem::delContentPtr(const CItemType& type, const uint32_t hash) { map<uint32_t, IContentItem*>* content_map = m_content_maps[type.getType()]; content_map->erase(hash); }
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"); } }
bool CSpaceObject::GetRefuelItemAndPrice (CSpaceObject *pObjToRefuel, CItemType **retpItemType, int *retiPrice) // GetRefuelItemAndPrice // // Returns the appropriate item to use for refueling (based on the trading // directives). { int i; if (IsAbandoned()) return false; // See if we have an override CTradingDesc *pTradeOverride = GetTradeDescOverride(); if (pTradeOverride && pTradeOverride->GetRefuelItemAndPrice(this, pObjToRefuel, 0, retpItemType, retiPrice)) return true; // Otherwise, ask our design type CDesignType *pType = GetType(); if (pType == NULL) return false; CTradingDesc *pTrade = pType->GetTradingDesc(); if (pTrade && pTrade->GetRefuelItemAndPrice(this, pObjToRefuel, 0, retpItemType, retiPrice)) return true; // For compatibility, any ship prior to version 23 has a default. // [For API Version 23 and above, ships must have a <Trade> descriptor.] if (pType->GetAPIVersion() < 23 && pType->GetType() == designShipClass) { // Get the ship CShip *pShipToRefuel = pObjToRefuel->AsShip(); if (pShipToRefuel == NULL) return false; // Find the highest-level item that can be used by the ship int iBestLevel = 0; int iBestPrice = 0; CItemType *pBestItem = NULL; for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++) { CItemType *pType = g_pUniverse->GetItemType(i); CItem Item(pType, 1); if (pShipToRefuel->IsFuelCompatible(Item)) { if (pBestItem == NULL || pType->GetLevel() > iBestPrice) { // Compute the price, because if we don't sell it, then we // skip it. // // NOTE: Unlike selling, we allow 0 prices because some // stations give fuel for free. int iPrice = CTradingDesc::CalcPriceForService(serviceRefuel, this, Item, 1, 0); if (iPrice >= 0) { pBestItem = pType; iBestLevel = pType->GetLevel(); iBestPrice = iPrice; } } } } if (pBestItem == NULL) return false; // Done if (retpItemType) *retpItemType = pBestItem; if (retiPrice) *retiPrice = iBestPrice; return true; } // Otherwise, we do not refuel return false; }
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 CGItemListArea::PaintItem (CG16bitImage &Dest, const CItem &Item, const RECT &rcRect, bool bSelected) // PaintItem // // Paints the item { // Item context CItemCtx Ctx(&Item, m_pListData->GetSource()); CItemType *pItemType = Item.GetType(); // Paint the image DrawItemTypeIcon(Dest, rcRect.left, rcRect.top, pItemType); RECT rcDrawRect = rcRect; rcDrawRect.left += ICON_WIDTH + ITEM_TEXT_MARGIN_X; rcDrawRect.right -= ITEM_TEXT_MARGIN_X; rcDrawRect.top += ITEM_TEXT_MARGIN_Y; // Paint the attribute blocks RECT rcAttrib; rcAttrib = rcDrawRect; rcAttrib.bottom = rcAttrib.top + m_pFonts->MediumHeavyBold.GetHeight(); if (Item.IsDamaged()) PaintItemModifier(Dest, CONSTLIT("Damaged"), RGB_ILLEGAL_BACKGROUND, &rcAttrib); else if (Item.IsDisrupted()) PaintItemModifier(Dest, CONSTLIT("Ionized"), RGB_ILLEGAL_BACKGROUND, &rcAttrib); if (pItemType->IsKnown() && pItemType->HasAttribute(CONSTLIT("Military"))) PaintItemModifier(Dest, CONSTLIT("Military"), RGB_MILITARY_BACKGROUND, &rcAttrib); if (pItemType->IsKnown() && pItemType->HasAttribute(CONSTLIT("Illegal"))) PaintItemModifier(Dest, CONSTLIT("Illegal"), RGB_ILLEGAL_BACKGROUND, &rcAttrib); CString sEnhanced = Item.GetEnhancedDesc(m_pListData->GetSource()); if (!sEnhanced.IsBlank()) { bool bDisadvantage = (*(sEnhanced.GetASCIIZPointer()) == '-'); PaintItemModifier(Dest, sEnhanced, (bDisadvantage ? RGB_ILLEGAL_BACKGROUND : RGB_MILITARY_BACKGROUND), &rcAttrib); } // Paint the item name int cyHeight; RECT rcTitle = rcDrawRect; rcTitle.right = rcAttrib.right; m_pFonts->LargeBold.DrawText(Dest, rcTitle, m_pFonts->wItemTitle, Item.GetNounPhrase(nounCount | nounNoModifiers), 0, CG16bitFont::SmartQuotes | CG16bitFont::TruncateLine, &cyHeight); rcDrawRect.top += cyHeight; // Stats CString sStat; int iLevel = pItemType->GetApparentLevel(); CString sReference = pItemType->GetReference(Ctx); DamageTypes iDamageType; CString sDamageRef; int iDamageAdj[damageCount]; int iHP; if (Item.GetReferenceDamageType(m_pListData->GetSource(), -1, 0, &iDamageType, &sDamageRef)) { // Paint the initial text sStat = strPatternSubst("Level %s —", strLevel(iLevel)); int cxWidth = m_pFonts->Medium.MeasureText(sStat, &cyHeight); m_pFonts->Medium.DrawText(Dest, rcDrawRect, m_pFonts->wItemRef, sStat, 0, 0, &cyHeight); // Paint the damage type reference m_pUIRes->DrawReferenceDamageType(Dest, rcDrawRect.left + cxWidth + DAMAGE_ADJ_SPACING_X, rcDrawRect.top, iDamageType, sDamageRef); rcDrawRect.top += cyHeight; // Paint additional reference in the line below if (!sReference.IsBlank()) { m_pFonts->Medium.DrawText(Dest, rcDrawRect, m_pFonts->wItemRef, sReference, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } } else if (Item.GetReferenceDamageAdj(m_pListData->GetSource(), 0, &iHP, iDamageAdj)) { // Paint the initial text sStat = strPatternSubst("Level %s — hp: %d ", strLevel(iLevel), iHP); int cxWidth = m_pFonts->Medium.MeasureText(sStat, &cyHeight); m_pFonts->Medium.DrawText(Dest, rcDrawRect, m_pFonts->wItemRef, sStat, 0, 0, &cyHeight); // Paint the damage type array m_pUIRes->DrawReferenceDamageAdj(Dest, rcDrawRect.left + cxWidth + DAMAGE_ADJ_SPACING_X, rcDrawRect.top, iLevel, iHP, iDamageAdj); rcDrawRect.top += cyHeight; // Paint additional reference in the line below if (!sReference.IsBlank()) { m_pFonts->Medium.DrawText(Dest, rcDrawRect, m_pFonts->wItemRef, sReference, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } } else { if (sReference.IsBlank()) sStat = strPatternSubst("Level %s", strLevel(iLevel)); else sStat = strPatternSubst("Level %s — %s", strLevel(iLevel), sReference); m_pFonts->Medium.DrawText(Dest, rcDrawRect, m_pFonts->wItemRef, sStat, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } // Description CString sDesc = Item.GetDesc(); m_pFonts->Medium.DrawText(Dest, rcDrawRect, (bSelected ? m_pFonts->wItemDescSelected : m_pFonts->wItemDesc), sDesc, 0, CG16bitFont::SmartQuotes, &cyHeight); rcDrawRect.top += cyHeight; }
int CUIHelper::CalcItemEntryHeight (CSpaceObject *pSource, const CItem &Item, const RECT &rcRect, DWORD dwOptions) const // CalcItemEntryHeight // // Computes the height necessary to paint the item entry. { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &LargeBold = VI.GetFont(fontLargeBold); const CG16bitFont &Medium = VI.GetFont(fontMedium); bool bNoIcon = ((dwOptions & OPTION_NO_ICON) == OPTION_NO_ICON); bool bTitle = ((dwOptions & OPTION_TITLE) == OPTION_TITLE); // Get the item CItemCtx Ctx(&Item, pSource); CItemType *pType = Item.GetType(); if (pType == NULL) return ITEM_DEFAULT_HEIGHT; // Compute the rect where the reference text will paint RECT rcDrawRect = rcRect; rcDrawRect.left += ITEM_TEXT_MARGIN_X; rcDrawRect.right -= ITEM_TEXT_MARGIN_X; if (!bNoIcon) rcDrawRect.left += ICON_WIDTH; int iLevel = pType->GetApparentLevel(); // Compute the height of the row int cyHeight = 0; // Account for margin cyHeight += ITEM_TEXT_MARGIN_Y; // Item title cyHeight += LargeBold.GetHeight(); if (bTitle) cyHeight += ITEM_TITLE_EXTRA_MARGIN; // Attributes TArray<SDisplayAttribute> Attribs; if (Item.GetDisplayAttributes(Ctx, &Attribs)) { int cyAttribs; FormatDisplayAttributes(Attribs, rcDrawRect, &cyAttribs); cyHeight += cyAttribs + ATTRIB_SPACING_Y; } // Reference CString sReference = pType->GetReference(Ctx); // If this is a weapon, then add room for the weapon damage if (Item.GetReferenceDamageType(pSource, -1, 0, NULL, NULL)) cyHeight += Medium.GetHeight(); // If this is armor or a shield, then add room for damage resistance else if (Item.GetReferenceDamageAdj(pSource, 0, NULL, NULL)) cyHeight += Medium.GetHeight(); // Measure the reference text int iLines; if (!sReference.IsBlank()) { iLines = Medium.BreakText(sReference, RectWidth(rcDrawRect), NULL, 0); cyHeight += iLines * Medium.GetHeight(); } // Measure the description CString sDesc = Item.GetDesc(); iLines = Medium.BreakText(sDesc, RectWidth(rcDrawRect), NULL, 0); cyHeight += iLines * Medium.GetHeight(); // Margin cyHeight += ITEM_TEXT_MARGIN_BOTTOM; // Done cyHeight = Max(ITEM_DEFAULT_HEIGHT, cyHeight); return cyHeight; }
int CGItemListArea::CalcRowHeight (int iRow) // CalcRowHeight // // Returns the height of the given row { // Set the position int iOldPos = m_pListData->GetCursor(); m_pListData->SetCursor(iRow); // Compute the rect where we're painting (we only care about width) RECT rcRect = GetRect(); // Compute row height based on type of list int cyHeight; switch (m_iType) { case listItem: { // Get the item if (!m_pListData->IsCursorValid()) { cyHeight = DEFAULT_ROW_HEIGHT; break; } const CItem &Item = m_pListData->GetItemAtCursor(); CItemCtx Ctx(&Item, m_pListData->GetSource()); CItemType *pType = Item.GetType(); if (pType == NULL) { cyHeight = DEFAULT_ROW_HEIGHT; break; } int iLevel = pType->GetApparentLevel(); // Compute the height of the row cyHeight = 0; // Account for margin cyHeight += ITEM_TEXT_MARGIN_Y; // Item title cyHeight += m_pFonts->LargeBold.GetHeight(); // Reference CString sReference = pType->GetReference(Ctx); // If this is a weapon, then add room for the weapon damage if (Item.GetReferenceDamageType(m_pListData->GetSource(), -1, 0, NULL, NULL)) cyHeight += m_pFonts->Medium.GetHeight(); // If this is armor or a shield, then add room for damage resistance else if (Item.GetReferenceDamageAdj(m_pListData->GetSource(), 0, NULL, NULL)) cyHeight += m_pFonts->Medium.GetHeight(); // Otherwise, we add the level to the reference else { if (sReference.IsBlank()) sReference = strPatternSubst("Level %s", strLevel(iLevel)); else sReference = strPatternSubst("Level %s — %s", strLevel(iLevel), sReference); } // Compute the rect where the reference text will paint RECT rcDrawRect = rcRect; rcDrawRect.left += ICON_WIDTH + ITEM_TEXT_MARGIN_X; rcDrawRect.right -= ITEM_TEXT_MARGIN_X; // Measure the reference text int iLines = m_pFonts->Medium.BreakText(sReference, RectWidth(rcDrawRect), NULL, 0); cyHeight += iLines * m_pFonts->Medium.GetHeight(); // Measure the description CString sDesc = Item.GetDesc(); iLines = m_pFonts->Medium.BreakText(sDesc, RectWidth(rcDrawRect), NULL, 0); cyHeight += iLines * m_pFonts->Medium.GetHeight(); // Margin cyHeight += ITEM_TEXT_MARGIN_BOTTOM; // Done cyHeight = Max(DEFAULT_ROW_HEIGHT, cyHeight); break; } case listCustom: cyHeight = m_cyRow; break; default: cyHeight = DEFAULT_ROW_HEIGHT; break; } // Done m_pListData->SetCursor(iOldPos); return cyHeight; }
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(); }
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 CUIHelper::PaintItemEntry (CG16bitImage &Dest, CSpaceObject *pSource, const CItem &Item, const RECT &rcRect, DWORD dwOptions) const // PaintItemEntry // // Paints an item entry suitable for an item list. { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &LargeBold = VI.GetFont(fontLargeBold); const CG16bitFont &Medium = VI.GetFont(fontMedium); WORD wColorTitle = VI.GetColor(colorTextHighlight); WORD wColorRef = VI.GetColor(colorTextHighlight); WORD wColorDescSel = CG16bitImage::RGBValue(200,200,200); WORD wColorDesc = CG16bitImage::RGBValue(128,128,128); bool bSelected = ((dwOptions & OPTION_SELECTED) == OPTION_SELECTED); bool bNoIcon = ((dwOptions & OPTION_NO_ICON) == OPTION_NO_ICON); bool bTitle = ((dwOptions & OPTION_TITLE) == OPTION_TITLE); // Item context CItemCtx Ctx(&Item, pSource); CItemType *pItemType = Item.GetType(); // Calc the rect where we will draw RECT rcDrawRect = rcRect; rcDrawRect.left += ITEM_TEXT_MARGIN_X; rcDrawRect.right -= ITEM_TEXT_MARGIN_X; rcDrawRect.top += ITEM_TEXT_MARGIN_Y; // Paint the image if (!bNoIcon) { DrawItemTypeIcon(Dest, rcRect.left, rcRect.top, pItemType); rcDrawRect.left += ICON_WIDTH; } // Paint the item name DWORD dwNounPhraseFlags = nounNoModifiers; if (bTitle) dwNounPhraseFlags |= nounTitleCapitalize | nounShort; else dwNounPhraseFlags |= nounCount; int cyHeight; RECT rcTitle = rcDrawRect; LargeBold.DrawText(Dest, rcTitle, wColorTitle, Item.GetNounPhrase(dwNounPhraseFlags), 0, CG16bitFont::SmartQuotes | CG16bitFont::TruncateLine, &cyHeight); rcDrawRect.top += cyHeight; if (bTitle) rcDrawRect.top += ITEM_TITLE_EXTRA_MARGIN; // Paint the display attributes TArray<SDisplayAttribute> Attribs; if (Item.GetDisplayAttributes(Ctx, &Attribs)) { FormatDisplayAttributes(Attribs, rcDrawRect, &cyHeight); PaintDisplayAttributes(Dest, Attribs); rcDrawRect.top += cyHeight + ATTRIB_SPACING_Y; } // Stats CString sStat; int iLevel = pItemType->GetApparentLevel(); CString sReference = pItemType->GetReference(Ctx); DamageTypes iDamageType; CString sDamageRef; int iDamageAdj[damageCount]; int iHP; if (Item.GetReferenceDamageType(pSource, -1, 0, &iDamageType, &sDamageRef)) { // Paint the damage type reference PaintReferenceDamageType(Dest, rcDrawRect.left + DAMAGE_ADJ_SPACING_X, rcDrawRect.top, iDamageType, sDamageRef); rcDrawRect.top += Medium.GetHeight(); // Paint additional reference in the line below if (!sReference.IsBlank()) { Medium.DrawText(Dest, rcDrawRect, wColorRef, sReference, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } } else if (Item.GetReferenceDamageAdj(pSource, 0, &iHP, iDamageAdj)) { // Paint the initial text sStat = strPatternSubst("hp: %d ", iHP); int cxWidth = Medium.MeasureText(sStat, &cyHeight); Medium.DrawText(Dest, rcDrawRect, wColorRef, sStat, 0, 0, &cyHeight); // Paint the damage type array PaintReferenceDamageAdj(Dest, rcDrawRect.left + cxWidth + DAMAGE_ADJ_SPACING_X, rcDrawRect.top, iLevel, iHP, iDamageAdj); rcDrawRect.top += cyHeight; // Paint additional reference in the line below if (!sReference.IsBlank()) { Medium.DrawText(Dest, rcDrawRect, wColorRef, sReference, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } } else { Medium.DrawText(Dest, rcDrawRect, wColorRef, sReference, 0, 0, &cyHeight); rcDrawRect.top += cyHeight; } // Description CString sDesc = Item.GetDesc(); Medium.DrawText(Dest, rcDrawRect, (bSelected ? wColorDescSel : wColorDesc), sDesc, 0, CG16bitFont::SmartQuotes, &cyHeight); rcDrawRect.top += cyHeight; }