void CvUnit::collateralCombat(const CvPlot* pPlot, CvUnit* pSkipUnit)
{
CLLNode<IDInfo>* pUnitNode;
CvUnit* pLoopUnit;
CvUnit* pBestUnit;
CvWString szBuffer;
int iTheirStrength;
int iStrengthFactor;
int iCollateralDamage;
int iUnitDamage;
int iDamageCount;
int iPossibleTargets;
int iCount;
int iValue;
int iBestValue;
std::map<CvUnit*, int> mapUnitDamage;
std::map<CvUnit*, int>::iterator it;
int iCollateralStrength = (getDomainType() == DOMAIN_AIR ? airBaseCombatStr() : baseCombatStr()) * collateralDamage() / 100;
// BUG - Unofficial Patch - start
// Barrage promotions made working again on Tanks and other units with no base collateral ability
if (iCollateralStrength == 0 && getExtraCollateralDamage() == 0)
// BUG - Unofficial Patch - end
{
return;
}
iPossibleTargets = std::min((pPlot->getNumVisibleEnemyDefenders(this) - 1), collateralDamageMaxUnits());
pUnitNode = pPlot->headUnitNode();
while (pUnitNode != NULL)
{
pLoopUnit = ::getUnit(pUnitNode->m_data);
pUnitNode = pPlot->nextUnitNode(pUnitNode);
if (pLoopUnit != pSkipUnit)
{
if (isEnemy(pLoopUnit->getTeam(), pPlot))
{
if (!(pLoopUnit->isInvisible(getTeam(), false)))
{
if (pLoopUnit->canDefend())
{
iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Collateral Damage"));
iValue *= pLoopUnit->currHitPoints();
mapUnitDamage[pLoopUnit] = iValue;
}
}
}
}
}
CvCity* pCity = NULL;
if (getDomainType() == DOMAIN_AIR)
{
pCity = pPlot->getPlotCity();
}
iDamageCount = 0;
iCount = 0;
while (iCount < iPossibleTargets)
{
iBestValue = 0;
pBestUnit = NULL;
for (it = mapUnitDamage.begin(); it != mapUnitDamage.end(); it++)
{
if (it->second > iBestValue)
{
iBestValue = it->second;
pBestUnit = it->first;
}
}
if (pBestUnit != NULL)
{
mapUnitDamage.erase(pBestUnit);
if (NO_UNITCOMBAT == getUnitCombatType() || !pBestUnit->getUnitInfo().getUnitCombatCollateralImmune(getUnitCombatType()))
{
iTheirStrength = pBestUnit->baseCombatStr();
[B] if (iCollateralStrength == 0)
{
iCollateralStrength = baseCombatStr();
}
[/B]
iStrengthFactor = ((iCollateralStrength + iTheirStrength + 1) / 2);
iCollateralDamage = (GC.getDefineINT("COLLATERAL_COMBAT_DAMAGE") * (iCollateralStrength + iStrengthFactor)) / (iTheirStrength + iStrengthFactor);
iCollateralDamage *= 100 + getExtraCollateralDamage();
iCollateralDamage *= std::max(0, 100 - pBestUnit->getCollateralDamageProtection());
iCollateralDamage /= 100;
if (pCity != NULL)
{
iCollateralDamage *= 100 + pCity->getAirModifier();
iCollateralDamage /= 100;
}
iCollateralDamage /= 100;
iCollateralDamage = std::max(0, iCollateralDamage);
int iMaxDamage = std::min(collateralDamageLimit(), (collateralDamageLimit() * (iCollateralStrength + iStrengthFactor)) / (iTheirStrength + iStrengthFactor));
iUnitDamage = std::max(pBestUnit->getDamage(), std::min(pBestUnit->getDamage() + iCollateralDamage, iMaxDamage));
if (pBestUnit->getDamage() != iUnitDamage)
{
// BUG - Combat Events - start
int iDamageDone = iUnitDamage - pBestUnit->getDamage();
pBestUnit->setDamage(iUnitDamage, getOwnerINLINE());
CvEventReporter::getInstance().combatLogCollateral(this, pBestUnit, iDamageDone);
// BUG - Combat Events - end
iDamageCount++;
}
}
iCount++;
}
else
{
break;
}
}
if (iDamageCount > 0)
{
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_SUFFER_COL_DMG", iDamageCount);
gDLL->getInterfaceIFace()->addMessage(pSkipUnit->getOwnerINLINE(), (pSkipUnit->getDomainType() != DOMAIN_AIR), GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COLLATERAL", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pSkipUnit->getX_INLINE(), pSkipUnit->getY_INLINE(), true, true);
szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_INFLICT_COL_DMG", getNameKey(), iDamageCount);
gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COLLATERAL", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pSkipUnit->getX_INLINE(), pSkipUnit->getY_INLINE());
}
}