void CvUnitCombat::GenerateNuclearCombatInfo(CvUnit& kAttacker, CvPlot& plot, CvCombatInfo* pkCombatInfo)
{
int iExperience = 0;
pkCombatInfo->setUnit(BATTLE_UNIT_ATTACKER, &kAttacker);
pkCombatInfo->setUnit(BATTLE_UNIT_DEFENDER, NULL);
pkCombatInfo->setPlot(&plot);
// Any interception to be done?
CvUnit* pInterceptor = kAttacker.GetBestInterceptor(plot);
int iInterceptionDamage = 0;
if(pInterceptor != NULL)
{
pkCombatInfo->setUnit(BATTLE_UNIT_INTERCEPTOR, pInterceptor);
// Does the attacker evade?
if(GC.getGame().getJonRandNum(100, "Evasion Rand") >= kAttacker.evasionProbability())
{
// Is the interception successful?
if(GC.getGame().getJonRandNum(100, "Intercept Rand (Air)") < pInterceptor->currInterceptionProbability())
{
iInterceptionDamage = pInterceptor->GetInterceptionDamage(&kAttacker);
}
}
pkCombatInfo->setDamageInflicted(BATTLE_UNIT_INTERCEPTOR, iInterceptionDamage); // Damage inflicted this round
}
CvString strBuffer;
bool abTeamsAffected[MAX_TEAMS];
int iI;
for(iI = 0; iI < MAX_TEAMS; iI++)
{
abTeamsAffected[iI] = kAttacker.isNukeVictim(&plot, ((TeamTypes)iI));
}
...
pkCombatInfo->setFinalDamage(BATTLE_UNIT_ATTACKER, iInterceptionDamage); // Total damage to the unit
pkCombatInfo->setDamageInflicted(BATTLE_UNIT_ATTACKER, 0); // Damage inflicted this round
pkCombatInfo->setFinalDamage(BATTLE_UNIT_DEFENDER, 0); // Total damage to the unit
pkCombatInfo->setDamageInflicted(BATTLE_UNIT_DEFENDER, 0); // Damage inflicted this round
pkCombatInfo->setFearDamageInflicted(BATTLE_UNIT_ATTACKER, 0);
pkCombatInfo->setExperience(BATTLE_UNIT_ATTACKER, 0);
pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_ATTACKER, 0);
pkCombatInfo->setInBorders(BATTLE_UNIT_ATTACKER, plot.getOwner() != kAttacker.getOwner()); // Not really correct
pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_ATTACKER, !kAttacker.isBarbarian());
pkCombatInfo->setExperience(BATTLE_UNIT_DEFENDER, 0);
pkCombatInfo->setMaxExperienceAllowed(BATTLE_UNIT_DEFENDER, 0);
pkCombatInfo->setInBorders(BATTLE_UNIT_DEFENDER, plot.getOwner() == kAttacker.getOwner());
pkCombatInfo->setUpdateGlobal(BATTLE_UNIT_DEFENDER, false);
if (iInterceptionDamage > 0)
{
iExperience = /*2*/ GC.getEXPERIENCE_DEFENDING_AIR_SWEEP_GROUND();
pkCombatInfo->setExperience( BATTLE_UNIT_INTERCEPTOR, iExperience );
pkCombatInfo->setMaxExperienceAllowed( BATTLE_UNIT_INTERCEPTOR, MAX_INT );
pkCombatInfo->setInBorders( BATTLE_UNIT_INTERCEPTOR, plot.getOwner() == kAttacker.getOwner() );
pkCombatInfo->setUpdateGlobal( BATTLE_UNIT_INTERCEPTOR, false );
}
pkCombatInfo->setAttackIsBombingMission(true);
pkCombatInfo->setDefenderRetaliates(true);
pkCombatInfo->setAttackNuclearLevel(kAttacker.GetNukeDamageLevel() + 1);
if (!iInterceptionDamage)
{
// Set all of the units in the blast radius to defenders and calculate their damage
int iDamageMembers = 0;
GenerateNuclearExplosionDamage(&plot, kAttacker.GetNukeDamageLevel(), &kAttacker, pkCombatInfo->getDamageMembers(), &iDamageMembers, pkCombatInfo->getMaxDamageMemberCount());
pkCombatInfo->setDamageMemberCount(iDamageMembers);
}
GC.GetEngineUserInterface()->setDirty(UnitInfo_DIRTY_BIT, true);
}
...
void CvUnitCombat::ResolveNuclearCombat(const CvCombatInfo& kCombatInfo, uint uiParentEventID)
{
UNREFERENCED_PARAMETER(uiParentEventID);
bool bTargetDied = false;
int iAttackerDamageInflicted = kCombatInfo.getDamageInflicted(BATTLE_UNIT_ATTACKER);
int iDefenderDamageInflicted = kCombatInfo.getDamageInflicted(BATTLE_UNIT_DEFENDER);
CvUnit* pkAttacker = kCombatInfo.getUnit(BATTLE_UNIT_ATTACKER);
CvAssert_Debug(pkAttacker);
ICvUserInterface2* pkDLLInterface = GC.GetEngineUserInterface();
CvString strBuffer;
int iActivePlayerID = GC.getGame().getActivePlayer();
// Interception?
int iInterceptionDamage = kCombatInfo.getDamageInflicted(BATTLE_UNIT_INTERCEPTOR);
if (iInterceptionDamage > 0)
iDefenderDamageInflicted += iInterceptionDamage;
CvUnit* pInterceptor = kCombatInfo.getUnit(BATTLE_UNIT_INTERCEPTOR);
CvAssert_Debug(pInterceptor);
if (pInterceptor)
{
pInterceptor->setMadeInterception(true);
pInterceptor->setCombatUnit(NULL);
pInterceptor->changeExperience(
kCombatInfo.getExperience(BATTLE_UNIT_INTERCEPTOR),
kCombatInfo.getMaxExperienceAllowed(BATTLE_UNIT_INTERCEPTOR),
true,
kCombatInfo.getInBorders(BATTLE_UNIT_INTERCEPTOR),
kCombatInfo.getUpdateGlobal(BATTLE_UNIT_INTERCEPTOR));
if(!CvUnitMission::IsHeadMission(pInterceptor, CvTypes::getMISSION_WAIT_FOR())) // If the top mission was not a 'wait for', then clear it.
pInterceptor->ClearMissionQueue();
if (pkAttacker)
{
pkAttacker->changeDamage(iDefenderDamageInflicted, pInterceptor->getOwner());
// Attacker died
if(pkAttacker->IsDead())
{
auto_ptr<ICvUnit1> pAttacker = GC.WrapUnitPointer(pkAttacker);
gDLL->GameplayUnitDestroyedInCombat(pAttacker.get());
if(iActivePlayerID == pkAttacker->getOwner())
{
strBuffer = GetLocalizedText("TXT_KEY_MISC_YOU_UNIT_SHOT_DOWN", pkAttacker->getNameKey(), pInterceptor->getNameKey());
pkDLLInterface->AddMessage(uiParentEventID, pkAttacker->getOwner(), true, GC.getEVENT_MESSAGE_TIME(), strBuffer/*, GC.getEraInfo(GC.getGame().getCurrentEra())->getAudioUnitDefeatScript(), MESSAGE_TYPE_INFO, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pkTargetPlot->getX(), pkTargetPlot->getY()*/);
}
if(iActivePlayerID == pInterceptor->getOwner())
{
strBuffer = GetLocalizedText("TXT_KEY_MISC_ENEMY_AIR_UNIT_DESTROYED", pInterceptor->getNameKey(), pkAttacker->getVisualCivAdjective(pInterceptor->getTeam()), pkAttacker->getNameKey(), pInterceptor->getNameKey());
pkDLLInterface->AddMessage(uiParentEventID, pInterceptor->getOwner(), true, GC.getEVENT_MESSAGE_TIME(), strBuffer/*, GC.getEraInfo(GC.getGame().getCurrentEra())->getAudioUnitVictoryScript(), MESSAGE_TYPE_INFO, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pkTargetPlot->getX(), pkTargetPlot->getY()*/);
}
ApplyPostCombatTraitEffects(pkAttacker, pInterceptor);
}
// Clean up some stuff
pkAttacker->setCombatUnit(NULL);
pkAttacker->setAttackPlot(NULL, false);
pkAttacker->ClearMissionQueue(GetPostCombatDelay());
pkAttacker->SetAutomateType(NO_AUTOMATE); // kick unit out of automation
// Spend a move for this attack
pkAttacker->changeMoves(-GC.getMOVE_DENOMINATOR());
// Can't move or attack again
if (!pkAttacker->canMoveAfterAttacking())
{
pkAttacker->finishMoves();
}
}
// Report that combat is over in case we want to queue another attack
GET_PLAYER(pkAttacker->getOwner()).GetTacticalAI()->CombatResolved(pkAttacker, true);
}
else
{
CvPlot* pkTargetPlot = kCombatInfo.getPlot();
CvAssert_Debug(pkTargetPlot);
CvString strBuffer;
GC.getGame().changeNukesExploded(1);
...
CvUnitCombat::ATTACK_RESULT CvUnitCombat::AttackNuclear(CvUnit& kAttacker, int iX, int iY, ATTACK_OPTION /* eOption */)
{
...
// Set a combat unit/city. Not really needed for the combat since we are killing everyone, but it is currently the only way a unit is marked that it is 'in-combat'
if(pPlot->getPlotCity())
kAttacker.setCombatCity(pPlot->getPlotCity());
else
{
if(pPlot->getNumUnits())
kAttacker.setCombatUnit(pPlot->getUnitByIndex(0), true);
else
kAttacker.setAttackPlot(pPlot, false);
}
auto_ptr<ICvCombatInfo1> pDllCombatInfo(new CvDllCombatInfo(&kCombatInfo));
uiParentEventID = gDLL->GameplayUnitCombat(pDllCombatInfo.get());
CvUnit* pDefenderSupport = kCombatInfo.getUnit(BATTLE_UNIT_INTERCEPTOR);
if (pDefenderSupport)
pDefenderSupport->setCombatUnit(&kAttacker, false);
eResult = ATTACK_QUEUED;
}
else
{
eResult = ATTACK_COMPLETED;
// Set the plot, just so the unit is marked as 'in-combat'
kAttacker.setAttackPlot(pPlot, false);
}
ResolveCombat(kCombatInfo, uiParentEventID);
return eResult;
}