Hooks
static bool BeforeCvUnitCombat_AttackRanged(CvUnit& kAttacker, int iX, int iY, CvUnitCombat::ATTACK_OPTION arg3, CvUnitCombat::ATTACK_RESULT& result);static void AfterCvUnitCombat_AttackRanged(CvUnit& kAttacker, int iX, int iY, CvUnitCombat::ATTACK_OPTION arg3, CvUnitCombat::ATTACK_RESULT& result);static CvUnitCombat::ATTACK_RESULT ReplaceCvUnitCombat_AttackRanged(CvUnitCombat::ATTACK_RESULT (*original)(CvUnit&, int, int, CvUnitCombat::ATTACK_OPTION), CvUnit& kAttacker, int iX, int iY, CvUnitCombat::ATTACK_OPTION arg3);// CivHooks.h gives this hook point no types, so nothing checks these hooks' parameters.host->RegisterHook(host->pluginIndex, CivHooks::CvUnitCombat_AttackRanged::ID, CIV_HOOK_BEFORE, (void*)&BeforeCvUnitCombat_AttackRanged);host->RegisterHook(host->pluginIndex, CivHooks::CvUnitCombat_AttackRanged::ID, CIV_HOOK_AFTER, (void*)&AfterCvUnitCombat_AttackRanged);host->RegisterHook(host->pluginIndex, CivHooks::CvUnitCombat_AttackRanged::ID, CIV_HOOK_REPLACE, (void*)&ReplaceCvUnitCombat_AttackRanged);
Code
3232CvUnitCombat::ATTACK_RESULT CvUnitCombat::AttackRanged(CvUnit& kAttacker, int iX, int iY, CvUnitCombat::ATTACK_OPTION /* eOption */)3233{3234 //VALIDATE_OBJECT3235 CvPlot* pPlot = GC.getMap().plot(iX, iY);3236 ATTACK_RESULT eResult = ATTACK_ABORTED;32373238 CvAssertMsg(kAttacker.getDomainType() != DOMAIN_AIR, "Air units should not use AttackRanged, they should just MoveTo the target");32393240 if(NULL == pPlot)3241 {3242 return eResult;3243 }32443245 if (!kAttacker.isRangedSupportFire())3246 {3247 if(!kAttacker.canRangeStrikeAt(iX, iY))3248 {3249 return eResult;3250 }32513252 if(GC.getRANGED_ATTACKS_USE_MOVES() == 0)3253 {3254 kAttacker.setMadeAttack(true);3255 }3256 kAttacker.changeMoves(-GC.getMOVE_DENOMINATOR());3257 }32583259 // Unit that attacks loses his Fort bonus3260 kAttacker.setFortifyTurns(0);32613262 // New test feature - attacking/range striking uses up all moves for most Units3263 if(!kAttacker.canMoveAfterAttacking() && !kAttacker.isRangedSupportFire())3264 {3265 kAttacker.finishMoves();3266 GC.GetEngineUserInterface()->changeCycleSelectionCounter(1);3267 }32683269 kAttacker.SetAutomateType(NO_AUTOMATE);32703271 bool bDoImmediate = CvPreGame::quickCombat();3272 // Range-striking a Unit3273 if(!pPlot->isCity())3274 {3275 CvUnit* pDefender = kAttacker.airStrikeTarget(*pPlot, true);32763277#if defined(MOD_EVENTS_UNIT_RANGEATTACK)3278 if (!pDefender) {3279 if (MOD_EVENTS_UNIT_RANGEATTACK) {3280 int iValue = 0;3281 if (GAMEEVENTINVOKE_VALUE(iValue, GAMEEVENT_UnitRangeAttackAt, kAttacker.getOwner(), kAttacker.GetID(), iX, iY) == GAMEEVENTRETURN_VALUE) {3282 if (iValue) {3283 return CvUnitCombat::ATTACK_COMPLETED;3284 }32853286 return CvUnitCombat::ATTACK_ABORTED;3287 }3288 }3289 }3290#endif32913292 CvAssert(pDefender != NULL);3293 if(!pDefender) return ATTACK_ABORTED;32943295 pDefender->SetAutomateType(NO_AUTOMATE);3296#if defined(MOD_BUGFIX_UNITS_AWAKE_IN_DANGER)3297 if (MOD_BUGFIX_UNITS_AWAKE_IN_DANGER) {3298 pDefender->SetActivityType(ACTIVITY_AWAKE, false); 3299 }3300#endif33013302 CvCombatInfo kCombatInfo;3303 CvUnitCombat::GenerateRangedCombatInfo(kAttacker, pDefender, *pPlot, &kCombatInfo);3304 CvAssertMsg(!kAttacker.isDelayedDeath() && !pDefender->isDelayedDeath(), "Trying to battle and one of the units is already dead!");33053306 uint uiParentEventID = 0;3307 if(!bDoImmediate)3308 {3309 // Center camera here!3310 bool isTargetVisibleToActivePlayer = pPlot->isActiveVisible(false);3311 if(isTargetVisibleToActivePlayer)3312 {3313 auto_ptr<ICvPlot1> pDllPlot = GC.WrapPlotPointer(pPlot);3314 GC.GetEngineUserInterface()->lookAt(pDllPlot.get(), CAMERALOOKAT_NORMAL);3315 }3316 kCombatInfo.setVisualizeCombat(isTargetVisibleToActivePlayer);33173318 auto_ptr<ICvCombatInfo1> pDllCombatInfo(new CvDllCombatInfo(&kCombatInfo));3319 uiParentEventID = gDLL->GameplayUnitCombat(pDllCombatInfo.get());33203321 // Set the combat units so that other missions do not continue until combat is over.3322 kAttacker.setCombatUnit(pDefender, true);3323 pDefender->setCombatUnit(&kAttacker, false);3324 eResult = ATTACK_QUEUED;3325 }3326 else3327 eResult = ATTACK_COMPLETED;33283329 ResolveCombat(kCombatInfo, uiParentEventID);3330 }3331 // Range-striking a City3332 else3333 {3334 if (kAttacker.isRangedSupportFire())3335 {3336 return eResult;3337 }33383339 CvCombatInfo kCombatInfo;3340 GenerateRangedCombatInfo(kAttacker, NULL, *pPlot, &kCombatInfo);3341 CvAssertMsg(!kAttacker.isDelayedDeath(), "Trying to battle and the attacker is already dead!");33423343 uint uiParentEventID = 0;3344 if(!bDoImmediate)3345 {3346 // Center camera here!3347 bool isTargetVisibleToActivePlayer = pPlot->isActiveVisible(false);3348 if(isTargetVisibleToActivePlayer)3349 {3350 auto_ptr<ICvPlot1> pDllPlot = GC.WrapPlotPointer(pPlot);3351 GC.GetEngineUserInterface()->lookAt(pDllPlot.get(), CAMERALOOKAT_NORMAL);3352 }33533354 kCombatInfo.setVisualizeCombat(isTargetVisibleToActivePlayer);33553356 auto_ptr<ICvCombatInfo1> pDllCombatInfo(new CvDllCombatInfo(&kCombatInfo));3357 uiParentEventID = gDLL->GameplayCityCombat(pDllCombatInfo.get());33583359 CvCity* pkDefender = pPlot->getPlotCity();3360 kAttacker.setCombatCity(pkDefender);3361 if(pkDefender)3362 pkDefender->setCombatUnit(&kAttacker);3363 eResult = ATTACK_QUEUED;3364 }3365 else3366 eResult = ATTACK_COMPLETED;33673368 ResolveCombat(kCombatInfo, uiParentEventID);3369 }33703371 return eResult;3372}