Hooks
static bool BeforeCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int(const CvCombatMemberEntry* pkDamageArray, int iDamageMembers, CvUnit* pkAttacker, CvPlot* pkTargetPlot, int iDamageLevel, uint& result);static void AfterCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int(const CvCombatMemberEntry* pkDamageArray, int iDamageMembers, CvUnit* pkAttacker, CvPlot* pkTargetPlot, int iDamageLevel, uint& result);static uint ReplaceCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int(uint (*original)(const CvCombatMemberEntry*, int, CvUnit*, CvPlot*, int), const CvCombatMemberEntry* pkDamageArray, int iDamageMembers, CvUnit* pkAttacker, CvPlot* pkTargetPlot, int iDamageLevel);CivRegisterBefore<CivHooks::CvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int>(host, &BeforeCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int);CivRegisterAfter<CivHooks::CvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int>(host, &AfterCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int);CivRegisterReplace<CivHooks::CvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int>(host, &ReplaceCvUnitCombat_ApplyNuclearExplosionDamage_with_const_CvCombatMemberEntry_int_CvUnit_CvPlot_int);
Code
2396uint CvUnitCombat::ApplyNuclearExplosionDamage(const CvCombatMemberEntry* pkDamageArray, int iDamageMembers, CvUnit* pkAttacker, CvPlot* pkTargetPlot, int iDamageLevel)2397{2398 uint uiOpposingDamageCount = 0;2399 PlayerTypes eAttackerOwner = pkAttacker?pkAttacker->getOwner():NO_PLAYER;24002401 // Do all the units first2402 for(int i = 0; i < iDamageMembers; ++i)2403 {2404 const CvCombatMemberEntry& kEntry = pkDamageArray[i];2405 if(kEntry.IsUnit())2406 {2407 CvUnit* pkUnit = GET_PLAYER(kEntry.GetPlayer()).getUnit(kEntry.GetUnitID());2408 if(pkUnit)2409 {2410 // Apply the damage2411 pkUnit->setCombatUnit(NULL);2412 pkUnit->ClearMissionQueue();2413 pkUnit->SetAutomateType(NO_AUTOMATE); // kick unit out of automation24142415 if((eAttackerOwner == NO_PLAYER || pkUnit->getOwner() != eAttackerOwner) && !pkUnit->isBarbarian())2416 uiOpposingDamageCount++; // Count the number of non-barbarian opposing units24172418 if(pkUnit->IsCombatUnit() || pkUnit->IsCanAttackRanged())2419 {2420#if defined(MOD_API_UNIT_STATS)2421 pkUnit->changeDamage(kEntry.GetDamage(), eAttackerOwner, pkAttacker ? pkAttacker->GetID() : -1);2422#else2423 pkUnit->changeDamage(kEntry.GetDamage(), eAttackerOwner);2424#endif2425 }2426 else if(kEntry.GetDamage() >= /*6*/ GC.getNUKE_NON_COMBAT_DEATH_THRESHOLD())2427 {2428 pkUnit->kill(false, eAttackerOwner);2429 }24302431 GET_PLAYER(kEntry.GetPlayer()).GetDiplomacyAI()->ChangeNumTimesNuked(pkAttacker->getOwner(), 1);2432 }2433 }2434 }24352436 // Then the terrain effects2437 int iBlastRadius = GC.getNUKE_BLAST_RADIUS();24382439 for(int iDX = -(iBlastRadius); iDX <= iBlastRadius; iDX++)2440 {2441 for(int iDY = -(iBlastRadius); iDY <= iBlastRadius; iDY++)2442 {2443 CvPlot* pLoopPlot = plotXYWithRangeCheck(pkTargetPlot->getX(), pkTargetPlot->getY(), iDX, iDY, iBlastRadius);24442445 if(pLoopPlot != NULL)2446 {2447 // if we remove roads, don't remove them on the city... XXX2448 CvCity* pLoopCity = pLoopPlot->getPlotCity();24492450 if(pLoopCity == NULL)2451 {2452 if(!(pLoopPlot->isWater()) && !(pLoopPlot->isImpassable()))2453 {2454 if(pLoopPlot->getFeatureType() != NO_FEATURE)2455 {2456 CvFeatureInfo* pkFeatureInfo = GC.getFeatureInfo(pLoopPlot->getFeatureType());2457 if(pkFeatureInfo && !pkFeatureInfo->isNukeImmune())2458 {2459 if(pLoopPlot == pkTargetPlot || GC.getGame().getJonRandNum(100, "Nuke Fallout") < GC.getNUKE_FALLOUT_PROB())2460 {2461 if(pLoopPlot->getImprovementType() != NO_IMPROVEMENT)2462 {2463 pLoopPlot->SetImprovementPillaged(true);2464 }2465 pLoopPlot->setFeatureType((FeatureTypes)(GC.getNUKE_FEATURE()));2466 }2467 }2468 }2469 else2470 {2471 if(pLoopPlot == pkTargetPlot || GC.getGame().getJonRandNum(100, "Nuke Fallout") < GC.getNUKE_FALLOUT_PROB())2472 {2473 if(pLoopPlot->getImprovementType() != NO_IMPROVEMENT)2474 {2475 pLoopPlot->SetImprovementPillaged(true);2476 }2477 pLoopPlot->setFeatureType((FeatureTypes)(GC.getNUKE_FEATURE()));2478 }2479 }2480#if defined(MOD_GLOBAL_NUKES_MELT_ICE)2481 } else if (MOD_GLOBAL_NUKES_MELT_ICE && pLoopPlot->getFeatureType() == FEATURE_ICE) {2482 if (pLoopPlot == pkTargetPlot || GC.getGame().getJonRandNum(100, "Nuke Fallout") < GC.getNUKE_FALLOUT_PROB()) {2483 pLoopPlot->setFeatureType(NO_FEATURE);2484 }2485#endif2486 }2487 }2488 }2489 }2490 }24912492 // Then the cities2493 for(int i = 0; i < iDamageMembers; ++i)2494 {2495 const CvCombatMemberEntry& kEntry = pkDamageArray[i];2496 if(kEntry.IsCity())2497 {2498 CvCity* pkCity = GET_PLAYER(kEntry.GetPlayer()).getCity(kEntry.GetCityID());2499 if(pkCity)2500 {2501 pkCity->setCombatUnit(NULL);25022503 if(eAttackerOwner == NO_PLAYER || pkCity->getOwner() != eAttackerOwner)2504 uiOpposingDamageCount++;25052506 if(kEntry.GetFinalDamage() >= pkCity->GetMaxHitPoints() && !pkCity->IsOriginalCapital())2507 {2508 auto_ptr<ICvCity1> pkDllCity(new CvDllCity(pkCity));2509 gDLL->GameplayCitySetDamage(pkDllCity.get(), 0, pkCity->getDamage()); // to stop the fires2510 gDLL->GameplayCityDestroyed(pkDllCity.get(), NO_PLAYER);25112512 PlayerTypes eOldOwner = pkCity->getOwner();2513 pkCity->kill();25142515 // slewis - check for killing a player2516 GET_PLAYER(pkAttacker->getOwner()).CheckForMurder(eOldOwner);2517 }2518 else2519 {2520 // Unlike the city hit points, the population damage is calculated when the pre-calculated damage is applied.2521 // This is simply to save space in the damage array, since the combat visualization does not need it.2522 // It can be moved into the pre-calculated damage array if needed.2523 int iBaseDamage, iRandDamage1, iRandDamage2;2524 // How much destruction is unleashed on nearby Cities?2525 if(iDamageLevel == 1)2526 {2527 iBaseDamage = /*30*/ GC.getNUKE_LEVEL1_POPULATION_DEATH_BASE();2528 iRandDamage1 = GC.getGame().getJonRandNum(/*20*/ GC.getNUKE_LEVEL1_POPULATION_DEATH_RAND_1(), "Population Nuked 1");2529 iRandDamage2 = GC.getGame().getJonRandNum(/*20*/ GC.getNUKE_LEVEL1_POPULATION_DEATH_RAND_2(), "Population Nuked 2");2530 }2531 else2532 {2533 iBaseDamage = /*60*/ GC.getNUKE_LEVEL2_POPULATION_DEATH_BASE();2534 iRandDamage1 = GC.getGame().getJonRandNum(/*10*/ GC.getNUKE_LEVEL2_POPULATION_DEATH_RAND_1(), "Population Nuked 1");2535 iRandDamage2 = GC.getGame().getJonRandNum(/*10*/ GC.getNUKE_LEVEL2_POPULATION_DEATH_RAND_2(), "Population Nuked 2");2536 }25372538 int iNukedPopulation = pkCity->getPopulation() * (iBaseDamage + iRandDamage1 + iRandDamage2) / 100;25392540 iNukedPopulation *= std::max(0, (pkCity->getNukeModifier() + 100));2541 iNukedPopulation /= 100;25422543 pkCity->changePopulation(-(std::min((pkCity->getPopulation() - 1), iNukedPopulation)));25442545 // Add damage to the city2546 pkCity->setDamage(kEntry.GetFinalDamage());25472548 GET_PLAYER(pkCity->getOwner()).GetDiplomacyAI()->ChangeNumTimesNuked(pkAttacker->getOwner(), 1);2549 }2550 }2551 }2552 }2553 return uiOpposingDamageCount;2554}