bool CArmorClass::GetReferenceDamageAdj (const CItem *pItem, CSpaceObject *pInstalled, int *retiHP, int *retArray) // GetReferenceDamageAdj // // Returns armor HP after adjustment for damage type { int i; CItemCtx ItemCtx(pItem, pInstalled); int iHP = GetMaxHP(ItemCtx); if (retiHP) *retiHP = iHP; for (i = 0; i < damageCount; i++) { DamageDesc Damage((DamageTypes)i, DiceRange(0, 0, 0)); int iAdj = GetDamageAdj(ItemCtx.GetMods(), Damage); if (retArray) retArray[i] = CalcHPDamageAdj(iHP, iAdj); } 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 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 CArmorClass::Update (CInstalledArmor *pArmor, CSpaceObject *pObj, int iTick, bool *retbModified) // Update // // Updates the armor. This should be called once every 10 ticks { bool bModified = false; // Compute total regeneration by adding mods to intrinsic if (pArmor->GetMods().IsRegenerating() || pArmor->GetMods().IsPhotoRegenerating() || !m_Regen.IsEmpty()) { CItemCtx ItemCtx(pObj, pArmor); int iHPNeeded = GetMaxHP(ItemCtx) - pArmor->GetHitPoints(); if (iHPNeeded > 0) { // Combine all regeneration CRegenDesc *pRegen; CRegenDesc RegenWithMod; if (pArmor->GetMods().IsRegenerating() || pArmor->GetMods().IsPhotoRegenerating()) { RegenWithMod.Init(4); RegenWithMod.Add(m_Regen); pRegen = &RegenWithMod; } else pRegen = &m_Regen; // Compute the HP that we regenerate this cycle int iHP = Min(iHPNeeded, pRegen->GetRegen(iTick, TICKS_PER_UPDATE)); // If this is photo-repair armor then adjust the cycle // based on how far away we are from the sun. if (iHP > 0) if (m_fPhotoRepair || pArmor->GetMods().IsPhotoRegenerating()) { int iIntensity = pObj->GetSystem()->CalculateLightIntensity(pObj->GetPos()); if (mathRandom(1, 100) > iIntensity) iHP = 0; } // Repair if (iHP > 0) { pArmor->IncHitPoints(iHP); bModified = true; } } } // See if we're decaying if (pArmor->GetHitPoints() > 0 && (pArmor->GetMods().IsDecaying() || !m_Decay.IsEmpty())) { // Combine decay with mod CRegenDesc *pDecay; CRegenDesc DecayWithMod; if (pArmor->GetMods().IsDecaying()) { DecayWithMod.Init(4); DecayWithMod.Add(m_Decay); pDecay = &DecayWithMod; } else pDecay = &m_Decay; // Compute the HP that we decay this cycle int iHP = Min(pArmor->GetHitPoints(), pDecay->GetRegen(iTick, TICKS_PER_UPDATE)); // Decrement if (iHP > 0) { pArmor->IncHitPoints(-iHP); bModified = true; } } // If this is solar armor then recharge the object if (pArmor->GetMods().IsPhotoRecharge() || m_fPhotoRecharge) { int iIntensity = pObj->GetSystem()->CalculateLightIntensity(pObj->GetPos()); // Intensity varies from 0 to 100 so this will recharge up to // 100 units of fuel every 10 ticks or 10 units per tick. At 1.5MW per fuel // unit, this means that a single armor plate can support up to 15MW when // right next to the sun. pObj->Refuel(iIntensity); } // If this armor interferes with shields, then lower shields now if (pArmor->GetMods().IsShieldInterfering() || m_fShieldInterference) pObj->DeactivateShields(); // Done *retbModified = bModified; }
void CSingleDevice::AddDevices (SDeviceGenerateCtx &Ctx) // AddDevices // // Add devices to list { int i; if (m_pItemType == NULL) return; int iCount = m_Count.Roll(); for (i = 0; i < iCount; i++) { // Initialize the desc SDeviceDesc Desc; Desc.Item = CItem(m_pItemType, 1); if (mathRandom(1, 100) <= m_iDamaged) Desc.Item.SetDamaged(); else m_Enhanced.EnhanceItem(Desc.Item); // Find the default settings for the device slot for this device SDeviceDesc SlotDesc; bool bUseSlotDesc = (Ctx.pRoot ? Ctx.pRoot->FindDefaultDesc(Desc.Item, &SlotDesc) : false); // Set the device position appropriately, either from the <Device> element, // from the slot descriptor at the root, or from defaults. if (!m_bDefaultPos) { Desc.iPosAngle = m_iPosAngle; Desc.iPosRadius = m_iPosRadius; Desc.iPosZ = m_iPosZ; Desc.b3DPosition = m_b3DPosition; } else if (bUseSlotDesc) { Desc.iPosAngle = SlotDesc.iPosAngle; Desc.iPosRadius = SlotDesc.iPosRadius; Desc.iPosZ = SlotDesc.iPosZ; Desc.b3DPosition = SlotDesc.b3DPosition; } // Set the device fire arc appropriately. if (!m_bDefaultFireArc) { Desc.bOmnidirectional = m_bOmnidirectional; Desc.iMinFireArc = m_iMinFireArc; Desc.iMaxFireArc = m_iMaxFireArc; } else if (bUseSlotDesc) { Desc.bOmnidirectional = SlotDesc.bOmnidirectional; Desc.iMinFireArc = SlotDesc.iMinFireArc; Desc.iMaxFireArc = SlotDesc.iMaxFireArc; } // Set linked fire if (!m_bDefaultLinkedFire) Desc.dwLinkedFireOptions = m_dwLinkedFireOptions; else if (bUseSlotDesc) Desc.dwLinkedFireOptions = SlotDesc.dwLinkedFireOptions; else Desc.dwLinkedFireOptions = 0; Desc.bSecondary = m_bSecondary; // Slot bonus if (!m_bDefaultSlotBonus) Desc.iSlotBonus = m_iSlotBonus; else if (bUseSlotDesc) Desc.iSlotBonus = SlotDesc.iSlotBonus; else Desc.iSlotBonus = 0; // Add extra items if (m_pExtraItems) { CItemListManipulator ItemList(Desc.ExtraItems); SItemAddCtx ItemCtx(ItemList); ItemCtx.iLevel = Ctx.iLevel; m_pExtraItems->AddItems(ItemCtx); } // Done Ctx.pResult->AddDeviceDesc(Desc); } }