Hooks
static bool BeforeCvTacticalAI_ExecuteNavalFormationMoves(CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pTurnTarget);static void AfterCvTacticalAI_ExecuteNavalFormationMoves(CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pTurnTarget);static void ReplaceCvTacticalAI_ExecuteNavalFormationMoves(void (*original)(CvTacticalAI*, CvArmyAI*, CvPlot*), CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pTurnTarget);CivRegisterBefore<CivHooks::CvTacticalAI_ExecuteNavalFormationMoves>(host, &BeforeCvTacticalAI_ExecuteNavalFormationMoves);CivRegisterAfter<CivHooks::CvTacticalAI_ExecuteNavalFormationMoves>(host, &AfterCvTacticalAI_ExecuteNavalFormationMoves);CivRegisterReplace<CivHooks::CvTacticalAI_ExecuteNavalFormationMoves>(host, &ReplaceCvTacticalAI_ExecuteNavalFormationMoves);
Code
5635/// Complete moves for all units requested through calls to MoveWithFormation()5636void CvTacticalAI::ExecuteNavalFormationMoves(CvArmyAI* pArmy, CvPlot* pTurnTarget)5637{5638 UnitHandle pUnit;5639 int iMostUnits;5640 int iLeastUnits;5641 CvPlot* pLoopPlot;5642 bool bMoreEscorted = true;5643 FStaticVector<CvOperationUnit, SAFE_ESTIMATE_NUM_MULTIUNITFORMATION_ENTRIES, true, c_eCiv5GameplayDLL, 0>::iterator it;56445645 if(m_OperationUnits.size() == 0)5646 {5647 return;5648 }56495650 int iNavalUnits = 0;5651 int iEscortedUnits = 0;5652 for(it = m_OperationUnits.begin(); it != m_OperationUnits.end(); it++)5653 {5654 CvUnit *pOpUnit = m_pPlayer->getUnit(it->GetUnitID());5655 if (pOpUnit)5656 {5657 if (pOpUnit->getDomainType() == DOMAIN_LAND)5658 {5659 iEscortedUnits++;5660 }5661 else5662 {5663 if (pOpUnit->IsGreatAdmiral())5664 {5665 iEscortedUnits++;5666 }5667 else5668 {5669 iNavalUnits++;5670 }5671 }5672 }5673 }56745675 iMostUnits = max(iNavalUnits, iEscortedUnits);5676 iLeastUnits = min(iNavalUnits, iEscortedUnits);5677 if(iNavalUnits > iEscortedUnits)5678 {5679 bMoreEscorted = false;5680 }56815682 // Range around turn target based on number of units we need to place5683 int iRange = OperationalAIHelpers::GetGatherRangeForXUnits(iMostUnits);56845685 // See if we have enough places to put everyone5686 if(!ScoreDeploymentPlots(pTurnTarget, pArmy, iMostUnits, 0, iRange) &&5687 !ScoreDeploymentPlots(pTurnTarget, pArmy, iMostUnits, 0, 3))5688 {5689 if(GC.getLogging() && GC.getAILogging())5690 {5691 CvString strLogString;5692 strLogString.Format("Operation aborting. Army ID: %d. Not enough spaces to deploy near turn target", pArmy->GetID());5693 LogTacticalMessage(strLogString);5694 }5695 m_pPlayer->getAIOperation(pArmy->GetOperationID())->SetToAbort(AI_ABORT_NO_ROOM_DEPLOY);5696 }56975698 // Compute moves for whomever has more units first5699 else5700 {5701 std::stable_sort(m_TempTargets.begin(), m_TempTargets.end());5702 m_PotentialBlocks.clear();5703 bool bDone = false;5704 int iMostUnitsToPlace = iMostUnits;57055706 for(unsigned int iI = 0; iI < m_TempTargets.size() && !bDone; iI++)5707 {5708 pLoopPlot = GC.getMap().plot(m_TempTargets[iI].GetTargetX(), m_TempTargets[iI].GetTargetY());5709 if(FindClosestNavalOperationUnit(pLoopPlot, bMoreEscorted))5710 {5711 for(unsigned int jJ = 0; jJ < m_CurrentMoveUnits.size(); jJ++)5712 {5713 CvBlockingUnit block;5714 block.SetUnitID(m_CurrentMoveUnits[jJ].GetID());5715 block.SetPlot(pLoopPlot);5716 block.SetNumChoices((int)m_CurrentMoveUnits.size());5717 block.SetDistanceToTarget(m_CurrentMoveUnits[jJ].GetMovesToTarget());5718 m_PotentialBlocks.push_back(block);5719 }5720 iMostUnitsToPlace--;5721 if(iMostUnitsToPlace == 0)5722 {5723 bDone = true;5724 }5725 }5726 }57275728 // Now ready to make the assignments5729 AssignDeployingUnits(iMostUnits - iMostUnitsToPlace);5730 PerformChosenMoves(2);57315732 // Log if someone in army didn't get a move assigned (how do we address this in the future?)5733 if(m_ChosenBlocks.size() < (unsigned int)iMostUnits)5734 {5735 if(GC.getLogging() && GC.getAILogging())5736 {5737 CvString strMsg;5738 strMsg.Format("No naval deployment move for %d units in first pass", iMostUnits - m_ChosenBlocks.size());5739 LogTacticalMessage(strMsg);5740 }5741 }5742 5743 if(iLeastUnits > 0)5744 {5745 // Now repeat for the other type of units, using the same target plots5746 m_TempTargets.clear();5747 CvTacticalTarget temp;57485749 for(unsigned int iI = 0; iI < m_ChosenBlocks.size(); iI++)5750 {5751 temp.SetTargetX(m_ChosenBlocks[iI].GetPlot()->getX());5752 temp.SetTargetY(m_ChosenBlocks[iI].GetPlot()->getY());5753 m_TempTargets.push_back(temp);5754 }57555756 m_PotentialBlocks.clear();5757 bDone = false;5758 int iLeastUnitsToPlace = iLeastUnits;57595760 for(unsigned int iI = 0; iI < m_TempTargets.size() && !bDone; iI++)5761 {5762 pLoopPlot = GC.getMap().plot(m_TempTargets[iI].GetTargetX(), m_TempTargets[iI].GetTargetY());5763 if(FindClosestNavalOperationUnit(pLoopPlot, !bMoreEscorted))5764 {5765 for(unsigned int jJ = 0; jJ < m_CurrentMoveUnits.size(); jJ++)5766 {5767 CvBlockingUnit block;5768 block.SetUnitID(m_CurrentMoveUnits[jJ].GetID());5769 block.SetPlot(pLoopPlot);5770 block.SetNumChoices((int)m_CurrentMoveUnits.size());5771 block.SetDistanceToTarget(m_CurrentMoveUnits[jJ].GetMovesToTarget());5772 m_PotentialBlocks.push_back(block);5773 }5774 iLeastUnitsToPlace--;5775 if(iLeastUnitsToPlace == 0)5776 {5777 bDone = true;5778 }5779 }5780 }57815782 // Now ready to make the assignments5783 AssignDeployingUnits(iLeastUnits - iLeastUnitsToPlace);5784 PerformChosenMoves(2);57855786 if(m_ChosenBlocks.size() < (unsigned int)iLeastUnits)5787 {5788 if(GC.getLogging() && GC.getAILogging())5789 {5790 CvString strMsg;5791 strMsg.Format("No naval deployment move for %d units in second pass", iLeastUnits - m_ChosenBlocks.size());5792 LogTacticalMessage(strMsg);5793 }5794 }5795 }5796 }5797}