Hooks
static bool BeforeCvTacticalAI_LaunchAttack(CvTacticalAI* self, void* pAttacker, CvTacticalTarget* pTarget, bool bFirstAttack, bool bRanged, bool bCityAttack);static void AfterCvTacticalAI_LaunchAttack(CvTacticalAI* self, void* pAttacker, CvTacticalTarget* pTarget, bool bFirstAttack, bool bRanged, bool bCityAttack);static void ReplaceCvTacticalAI_LaunchAttack(void (*original)(CvTacticalAI*, void*, CvTacticalTarget*, bool, bool, bool), CvTacticalAI* self, void* pAttacker, CvTacticalTarget* pTarget, bool bFirstAttack, bool bRanged, bool bCityAttack);CivRegisterBefore<CivHooks::CvTacticalAI_LaunchAttack>(host, &BeforeCvTacticalAI_LaunchAttack);CivRegisterAfter<CivHooks::CvTacticalAI_LaunchAttack>(host, &AfterCvTacticalAI_LaunchAttack);CivRegisterReplace<CivHooks::CvTacticalAI_LaunchAttack>(host, &ReplaceCvTacticalAI_LaunchAttack);
Code
589/// Pushes the mission to launch an attack and logs this activity590void CvTacticalAI::LaunchAttack(void* pAttacker, CvTacticalTarget* pTarget, bool bFirstAttack, bool bRanged, bool bCityAttack)591{592 CvCity* pCity = NULL;593 UnitHandle pUnit;594595 if(bCityAttack)596 {597 pCity = (CvCity*)pAttacker;598 }599 else600 {601 pUnit = UnitHandle((CvUnit*)pAttacker);602 }603604 if(GC.getLogging() && GC.getAILogging())605 {606 CvString strMsg;607 CvString strTemp;608 int iX, iY;609610 if(bCityAttack)611 {612 strTemp = pCity->getName();613 iX = pCity->getX();614 iY = pCity->getY();615 }616 else617 {618 strTemp = pUnit->getUnitInfo().GetDescription();619 iX = pUnit->getX();620 iY = pUnit->getY();621 }622623 if(bRanged)624 {625 if(bFirstAttack)626 {627 strMsg.Format("Made initial ranged attack with %s, at X: %d, Y: %d, vs. target at X: %d, Y: %d", strTemp.GetCString(), iX, iY, pTarget->GetTargetX(), pTarget->GetTargetY());628 }629 else630 {631 strMsg.Format("Made follow-on ranged attack with %s, at X: %d, Y: %d, vs. target at X: %d, Y: %d", strTemp.GetCString(), iX, iY, pTarget->GetTargetX(), pTarget->GetTargetY());632 }633 }634 else635 {636 if(bFirstAttack)637 {638 strMsg.Format("Made initial attack with %s, at X: %d, Y: %d, vs. target at X: %d, Y: %d", strTemp.GetCString(), iX, iY, pTarget->GetTargetX(), pTarget->GetTargetY());639 }640 else641 {642 strMsg.Format("Made follow-on attack with %s, at X: %d, Y: %d, vs. target at X: %d, Y: %d", strTemp.GetCString(), iX, iY, pTarget->GetTargetX(), pTarget->GetTargetY());643 }644 }645646 LogTacticalMessage(strMsg);647 }648649 // Attack AFTER logging since our attacker could die650 if(bCityAttack)651 {652 pCity->doTask(TASK_RANGED_ATTACK, pTarget->GetTargetX(), pTarget->GetTargetY(), 0);653 }654 else655 {656 CvAssertMsg(pUnit->getMoves() > 0, "Tactical AI is going to push a mission on the queue to attack, but the unit is out of moves.");657 CvAssertMsg(!pUnit->isOutOfAttacks(), "Tactical AI is going to push a mission on the queue to attack, but the unit is out of attacks.");658659 bool bSendAttack = pUnit->getMoves() > 0 && !pUnit->isOutOfAttacks();660 if(bSendAttack)661 {662 if(bRanged && pUnit->getDomainType() != DOMAIN_AIR) // Air attack is ranged, but it goes through the 'move to' mission.663 {664 pUnit->PushMission(CvTypes::getMISSION_RANGE_ATTACK(), pTarget->GetTargetX(), pTarget->GetTargetY());665 }666 //else if (pUnit->canNuke(NULL)) // NUKE tactical attack (ouch)667 //{668 // pUnit->PushMission(CvTypes::getMISSION_NUKE(), pTarget->GetTargetX(), pTarget->GetTargetY());669 //}670 else671 {672 pUnit->PushMission(CvTypes::getMISSION_MOVE_TO(), pTarget->GetTargetX(), pTarget->GetTargetY());673 }674 }675676 // Make sure we did make an attack, if not we should take out this unit from the queue677 if(!bSendAttack || (!pUnit->isOutOfAttacks() && !pUnit->isFighting()))678 {679 pUnit->SetTurnProcessed(false);680 CombatResolved(pAttacker, false, bCityAttack);681 }682 }683}