void CvUnit::collateralCombat(const CvPlot* pPlot, CvUnit* pSkipUnit)
{
CLLNode<IDInfo>* pUnitNode;
CvUnit* pLoopUnit;
CvUnit* pBestUnit;
CvWString szBuffer;
int iCollateralStrength;
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;
iCollateralStrength = ((((getDomainType() == DOMAIN_AIR) ? airBaseCombatStr() : baseCombatStr()) * collateralDamage()) / 100);
if (iCollateralStrength == 0)
{
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)))
{
/*** World Piece Begin ***/
if (pLoopUnit->canDefend() || (getDomainType() == DOMAIN_AIR && pLoopUnit->getDomainType() == DOMAIN_SEA && !(pPlot->isWater())))
{ // Exception for naval units in cities when attacked by air units
iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Collateral Damage"));
iValue *= pLoopUnit->currHitPoints();
mapUnitDamage[pLoopUnit] = iValue;
}
/*** World Piece End ***/
}
}
}
}
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();
iStrengthFactor = ((iCollateralStrength + iTheirStrength + 1) / 2);
iCollateralDamage = (GC.getDefineINT("COLLATERAL_COMBAT_DAMAGE") * (iCollateralStrength + iStrengthFactor)) / (iTheirStrength + iStrengthFactor);
iCollateralDamage -= (iCollateralDamage * pBestUnit->getCollateralDamageProtection()) / 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)
{
pBestUnit->setDamage(iUnitDamage, getOwnerINLINE());
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());
}
}