Hooks
static bool BeforeCvUnitCombat_GenerateNuclearExplosionDamage(CvPlot* pkTargetPlot, int iDamageLevel, CvUnit* pkAttacker, CvCombatMemberEntry* pkDamageArray, int* piDamageMembers, int iMaxDamageMembers);static void AfterCvUnitCombat_GenerateNuclearExplosionDamage(CvPlot* pkTargetPlot, int iDamageLevel, CvUnit* pkAttacker, CvCombatMemberEntry* pkDamageArray, int* piDamageMembers, int iMaxDamageMembers);static void ReplaceCvUnitCombat_GenerateNuclearExplosionDamage(void (*original)(CvPlot*, int, CvUnit*, CvCombatMemberEntry*, int*, int), CvPlot* pkTargetPlot, int iDamageLevel, CvUnit* pkAttacker, CvCombatMemberEntry* pkDamageArray, int* piDamageMembers, int iMaxDamageMembers);CivRegisterBefore<CivHooks::CvUnitCombat_GenerateNuclearExplosionDamage>(host, &BeforeCvUnitCombat_GenerateNuclearExplosionDamage);CivRegisterAfter<CivHooks::CvUnitCombat_GenerateNuclearExplosionDamage>(host, &AfterCvUnitCombat_GenerateNuclearExplosionDamage);CivRegisterReplace<CivHooks::CvUnitCombat_GenerateNuclearExplosionDamage>(host, &ReplaceCvUnitCombat_GenerateNuclearExplosionDamage);
Code
2557// Generate nuclear explosion damage for all the units and cities in the radius of the specified plot.2558// The attacker is optional, this is also called for a meltdown2559void CvUnitCombat::GenerateNuclearExplosionDamage(CvPlot* pkTargetPlot, int iDamageLevel, CvUnit* pkAttacker, CvCombatMemberEntry* pkDamageArray, int* piDamageMembers, int iMaxDamageMembers)2560{2561 int iBlastRadius = GC.getNUKE_BLAST_RADIUS();25622563#if defined(MOD_EVENTS_BATTLES)2564 CvCity* pDefenderCity = NULL;2565 CvUnit* pDefenderUnit = NULL;25662567 if (pkTargetPlot->isCity())2568 {2569 pDefenderCity = pkTargetPlot->getPlotCity();2570 }2571 else2572 {2573 pDefenderUnit = pkTargetPlot->getBestDefender(NO_PLAYER, pkAttacker->getOwner()).pointer();2574 }2575#endif25762577 *piDamageMembers = 0;25782579 for(int iDX = -(iBlastRadius); iDX <= iBlastRadius; iDX++)2580 {2581 for(int iDY = -(iBlastRadius); iDY <= iBlastRadius; iDY++)2582 {2583 CvPlot* pLoopPlot = plotXYWithRangeCheck(pkTargetPlot->getX(), pkTargetPlot->getY(), iDX, iDY, iBlastRadius);25842585 if(pLoopPlot != NULL)2586 {2587 CvCity* pLoopCity = pLoopPlot->getPlotCity();25882589 FFastSmallFixedList<IDInfo, 25, true, c_eCiv5GameplayDLL > oldUnits;2590 IDInfo* pUnitNode = pLoopPlot->headUnitNode();25912592 while(pUnitNode != NULL)2593 {2594 oldUnits.insertAtEnd(pUnitNode);2595 pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);2596 }25972598 pUnitNode = oldUnits.head();25992600 while(pUnitNode != NULL)2601 {2602 CvUnit* pLoopUnit = ::getUnit(*pUnitNode);2603 pUnitNode = oldUnits.next(pUnitNode);26042605 if(pLoopUnit != NULL)2606 {2607 if(pLoopUnit != pkAttacker)2608 {2609 if(!pLoopUnit->isNukeImmune() && !pLoopUnit->isDelayedDeath())2610 {2611 int iNukeDamage;2612 // How much destruction is unleashed on nearby Units?2613 if(iDamageLevel == 1 && pLoopPlot != pkTargetPlot) // Nuke level 1, but NOT the plot that got hit directly (units there are killed)2614 {2615 iNukeDamage = (/*3*/ GC.getNUKE_UNIT_DAMAGE_BASE() + /*4*/ GC.getGame().getJonRandNum(GC.getNUKE_UNIT_DAMAGE_RAND_1(), "Nuke Damage 1") + /*4*/ GC.getGame().getJonRandNum(GC.getNUKE_UNIT_DAMAGE_RAND_2(), "Nuke Damage 2"));2616 }2617 // Wipe everything out2618 else2619 {2620#if defined(MOD_UNITS_MAX_HP)2621 iNukeDamage = pLoopUnit->GetMaxHitPoints();2622#else2623 iNukeDamage = GC.getMAX_HIT_POINTS();2624#endif2625 }26262627 if(pLoopCity != NULL)2628 {2629 iNukeDamage *= std::max(0, (pLoopCity->getNukeModifier() + 100));2630 iNukeDamage /= 100;2631 }26322633 CvCombatMemberEntry* pkDamageEntry = AddCombatMember(pkDamageArray, piDamageMembers, iMaxDamageMembers, pLoopUnit);2634 if(pkDamageEntry)2635 {2636#if defined(MOD_EVENTS_BATTLES)2637 if (pLoopUnit != pDefenderUnit)2638 {2639 BATTLE_JOINED(pLoopUnit, BATTLE_UNIT_COUNT, false); // Bit of a fudge, as BATTLE_UNIT_COUNT happens to correspond to BATTLEUNIT_BYSTANDER2640 }2641#endif2642 pkDamageEntry->SetDamage(iNukeDamage);2643#if defined(MOD_UNITS_MAX_HP)2644 pkDamageEntry->SetFinalDamage(std::min(iNukeDamage + pLoopUnit->getDamage(), pLoopUnit->GetMaxHitPoints()));2645 pkDamageEntry->SetMaxHitPoints(pLoopUnit->GetMaxHitPoints());2646#else2647 pkDamageEntry->SetFinalDamage(std::min(iNukeDamage + pLoopUnit->getDamage(), GC.getMAX_HIT_POINTS()));2648 pkDamageEntry->SetMaxHitPoints(GC.getMAX_HIT_POINTS());2649#endif2650 if(pkAttacker)2651 pLoopUnit->setCombatUnit(pkAttacker);2652 }2653 else2654 {2655 CvAssertMsg(*piDamageMembers < iMaxDamageMembers, "Ran out of entries for the nuclear damage array");2656 }2657 }2658 }2659 }2660 }26612662 if(pLoopCity != NULL)2663 {2664 bool bKillCity = false;26652666 // Is the city wiped out? - no capitals!2667 if(!pLoopCity->IsOriginalCapital())2668 {2669 if(iDamageLevel > 2)2670 {2671 bKillCity = true;2672 }2673 else if(iDamageLevel > 1)2674 {2675 if(pLoopCity->getPopulation() < /*5*/ GC.getNUKE_LEVEL2_ELIM_POPULATION_THRESHOLD())2676 {2677 bKillCity = true;2678 }2679 }2680 }26812682 int iTotalDamage;2683 if(bKillCity)2684 {2685 iTotalDamage = pLoopCity->GetMaxHitPoints();2686 }2687 else2688 {2689 // Add damage to the city2690 iTotalDamage = (pLoopCity->GetMaxHitPoints() - pLoopCity->getDamage()) * /*50*/ GC.getNUKE_CITY_HIT_POINT_DAMAGE();2691 iTotalDamage /= 100;26922693 iTotalDamage += pLoopCity->getDamage();26942695 // Can't bring a city below 1 HP2696 iTotalDamage = min(iTotalDamage, pLoopCity->GetMaxHitPoints() - 1);2697 }26982699 CvCombatMemberEntry* pkDamageEntry = AddCombatMember(pkDamageArray, piDamageMembers, iMaxDamageMembers, pLoopCity);2700 if(pkDamageEntry)2701 {2702#if defined(MOD_EVENTS_BATTLES)2703 if (pLoopCity != pDefenderCity)2704 {2705 BATTLE_JOINED(pLoopCity, BATTLE_UNIT_COUNT, true); // Bit of a fudge, as BATTLE_UNIT_COUNT happens to correspond to BATTLEUNIT_BYSTANDER2706 }2707#endif2708 pkDamageEntry->SetDamage(iTotalDamage - pLoopCity->getDamage());2709 pkDamageEntry->SetFinalDamage(iTotalDamage);2710 pkDamageEntry->SetMaxHitPoints(pLoopCity->GetMaxHitPoints());27112712 if(pkAttacker)2713 pLoopCity->setCombatUnit(pkAttacker);2714 }2715 else2716 {2717 CvAssertMsg(*piDamageMembers < iMaxDamageMembers, "Ran out of entries for the nuclear damage array");2718 }2719 }2720 }2721 }2722 }2723}