Hooks
static bool BeforeCvTacticalAI_ExecuteHedgehogDefense(CvTacticalAI* self, CvTacticalTarget& kTarget, CvTacticalDominanceZone* pZone);static void AfterCvTacticalAI_ExecuteHedgehogDefense(CvTacticalAI* self, CvTacticalTarget& kTarget, CvTacticalDominanceZone* pZone);static void ReplaceCvTacticalAI_ExecuteHedgehogDefense(void (*original)(CvTacticalAI*, CvTacticalTarget&, CvTacticalDominanceZone*), CvTacticalAI* self, CvTacticalTarget& kTarget, CvTacticalDominanceZone* pZone);CivRegisterBefore<CivHooks::CvTacticalAI_ExecuteHedgehogDefense>(host, &BeforeCvTacticalAI_ExecuteHedgehogDefense);CivRegisterAfter<CivHooks::CvTacticalAI_ExecuteHedgehogDefense>(host, &AfterCvTacticalAI_ExecuteHedgehogDefense);CivRegisterReplace<CivHooks::CvTacticalAI_ExecuteHedgehogDefense>(host, &ReplaceCvTacticalAI_ExecuteHedgehogDefense);
Code
8561/// Deploy defensive forces around a friendly city8562void CvTacticalAI::ExecuteHedgehogDefense(CvTacticalTarget& kTarget, CvTacticalDominanceZone* pZone)8563{8564 CvOperationUnit unit;8565 int iDistance;8566 CvPlot* pTargetPlot;8567 int iRangedUnits = 0;8568 int iMeleeUnits = 0;8569 list<int>::iterator it;8570 int iTacticalRadius = GC.getGame().GetTacticalAnalysisMap()->GetTacticalRange();85718572 pTargetPlot = GC.getMap().plot(kTarget.GetTargetX(), kTarget.GetTargetY());8573 m_OperationUnits.clear();8574 m_GeneralsToMove.clear();85758576 for(it = m_CurrentTurnUnits.begin(); it != m_CurrentTurnUnits.end(); it++)8577 {8578 UnitHandle pUnit = m_pPlayer->getUnit(*it);8579 if(pUnit)8580 {8581 // Proper domain of unit?8582 if(pZone->IsWater() && pUnit->getDomainType() == DOMAIN_SEA || !pZone->IsWater() && pUnit->getDomainType() == DOMAIN_LAND)8583 {8584 // Find units really close to target or somewhat close that just came out of an operation8585 iDistance = plotDistance(pUnit->getX(), pUnit->getY(), kTarget.GetTargetX(), kTarget.GetTargetY());8586 if(iDistance <= iTacticalRadius)8587 {8588 unit.SetUnitID(pUnit->GetID());85898590 if (pUnit->IsGreatGeneral())8591 {8592 if(pUnit->getMoves() > 0)8593 {8594 CvOperationUnit operationUnit;8595 operationUnit.SetUnitID(pUnit->GetID());8596 operationUnit.SetPosition((MultiunitPositionTypes)m_CachedInfoTypes[eMUPOSITION_CIVILIAN_SUPPORT]);8597 m_GeneralsToMove.push_back(operationUnit);8598 }8599 }8600 else if (pUnit->IsCanAttackRanged())8601 {8602 unit.SetPosition((MultiunitPositionTypes)m_CachedInfoTypes[eMUPOSITION_BOMBARD]);8603 iRangedUnits++;8604 m_OperationUnits.push_back(unit);8605 }8606 else8607 {8608 unit.SetPosition((MultiunitPositionTypes)m_CachedInfoTypes[eMUPOSITION_FRONT_LINE]);8609 iMeleeUnits++;8610 m_OperationUnits.push_back(unit);8611 }8612 }8613 }8614 }8615 }86168617 // If have any units to move...8618 if(m_OperationUnits.size() > 0)8619 {8620 ScoreHedgehogPlots(pTargetPlot);86218622 // Compute the moves to get the best deployment8623 std::stable_sort(m_TempTargets.begin(), m_TempTargets.end());8624 m_PotentialBlocks.clear();86258626 int iRangedUnitsToPlace = iRangedUnits;8627 int iMeleeUnitsToPlace = iMeleeUnits;86288629 // First loop for ranged unit spots8630 bool bDone = false;8631 for(unsigned int iI = 0; iI < m_TempTargets.size() && !bDone; iI++)8632 {8633 AITacticalTargetType eTargetType = m_TempTargets[iI].GetTargetType();8634 if (eTargetType == AI_TACTICAL_TARGET_HIGH_PRIORITY_UNIT)8635 {8636 CvPlot* pLoopPlot = GC.getMap().plot(m_TempTargets[iI].GetTargetX(), m_TempTargets[iI].GetTargetY());8637 if(FindClosestOperationUnit(pLoopPlot, true /*bSafeForRanged*/, true /*bMustBeRangedUnit*/))8638 {8639 for(unsigned int jJ = 0; jJ < m_CurrentMoveUnits.size(); jJ++)8640 {8641 CvBlockingUnit block;8642 block.SetUnitID(m_CurrentMoveUnits[jJ].GetID());8643 block.SetPlot(pLoopPlot);8644 block.SetNumChoices((int)m_CurrentMoveUnits.size());8645 block.SetDistanceToTarget(m_CurrentMoveUnits[jJ].GetMovesToTarget());8646 m_PotentialBlocks.push_back(block);8647 }86488649 iRangedUnitsToPlace--;8650 if(iRangedUnitsToPlace == 0)8651 {8652 bDone = true;8653 }8654 }8655 }8656 }8657 AssignDeployingUnits(iRangedUnits - iRangedUnitsToPlace);8658 PerformChosenMoves();86598660 // Second loop for everyone else (including remaining ranged units)8661 m_PotentialBlocks.clear();8662 iMeleeUnits += iRangedUnitsToPlace;8663 iMeleeUnitsToPlace += iRangedUnitsToPlace;8664 bDone = false;8665 for(unsigned int iI = 0; iI < m_TempTargets.size() && !bDone; iI++)8666 {8667 AITacticalTargetType eTargetType = m_TempTargets[iI].GetTargetType();8668 if (eTargetType != AI_TACTICAL_TARGET_HIGH_PRIORITY_UNIT)8669 {8670 CvPlot* pLoopPlot = GC.getMap().plot(m_TempTargets[iI].GetTargetX(), m_TempTargets[iI].GetTargetY());8671 if(FindClosestOperationUnit(pLoopPlot, true /*bSafeForRanged*/, false /*bMustBeRangedUnit*/))8672 {8673 for(unsigned int jJ = 0; jJ < m_CurrentMoveUnits.size(); jJ++)8674 {8675 CvBlockingUnit block;8676 block.SetUnitID(m_CurrentMoveUnits[jJ].GetID());8677 block.SetPlot(pLoopPlot);8678 block.SetNumChoices((int)m_CurrentMoveUnits.size());8679 block.SetDistanceToTarget(m_CurrentMoveUnits[jJ].GetMovesToTarget());8680 m_PotentialBlocks.push_back(block);8681 }86828683 iMeleeUnitsToPlace--;8684 if(iMeleeUnitsToPlace == 0)8685 {8686 bDone = true;8687 }8688 }8689 }8690 }8691 AssignDeployingUnits(iMeleeUnits - iMeleeUnitsToPlace);8692 PerformChosenMoves();8693 }86948695 if(m_GeneralsToMove.size() > 0)8696 {8697 MoveGreatGeneral();8698 }8699}