Hooks
static bool BeforeCvHomelandAI_MoveCivilianToSafety(CvHomelandAI* self, CvUnit* pUnit, bool bIgnoreUnits, bool bSecondary, bool& result);static void AfterCvHomelandAI_MoveCivilianToSafety(CvHomelandAI* self, CvUnit* pUnit, bool bIgnoreUnits, bool bSecondary, bool& result);static bool ReplaceCvHomelandAI_MoveCivilianToSafety(bool (*original)(CvHomelandAI*, CvUnit*, bool, bool), CvHomelandAI* self, CvUnit* pUnit, bool bIgnoreUnits, bool bSecondary);CivRegisterBefore<CivHooks::CvHomelandAI_MoveCivilianToSafety>(host, &BeforeCvHomelandAI_MoveCivilianToSafety);CivRegisterAfter<CivHooks::CvHomelandAI_MoveCivilianToSafety>(host, &AfterCvHomelandAI_MoveCivilianToSafety);CivRegisterReplace<CivHooks::CvHomelandAI_MoveCivilianToSafety>(host, &ReplaceCvHomelandAI_MoveCivilianToSafety);
Code
4944/// Fleeing to safety for civilian units4945#if defined(MOD_AI_SECONDARY_WORKERS)4946bool CvHomelandAI::MoveCivilianToSafety(CvUnit* pUnit, bool bIgnoreUnits, bool bSecondary)4947#else4948bool CvHomelandAI::MoveCivilianToSafety(CvUnit* pUnit, bool bIgnoreUnits)4949#endif4950{4951 int iSearchRange = pUnit->SearchRange(1);49524953 // Collecting all the possibilities first.4954 WeightedPlotVector aBestPlotList;4955 aBestPlotList.reserve( ((iSearchRange * 2) + 1) * 2 );49564957 for(int iDX = -(iSearchRange); iDX <= iSearchRange; iDX++)4958 {4959 for(int iDY = -(iSearchRange); iDY <= iSearchRange; iDY++)4960 {4961 CvPlot* pLoopPlot = plotXYWithRangeCheck(pUnit->getX(), pUnit->getY(), iDX, iDY, iSearchRange);4962 if(!pLoopPlot)4963 {4964 continue;4965 }49664967#if defined(MOD_AI_SECONDARY_WORKERS)4968 if(!pUnit->PlotValid(pLoopPlot, CvUnit::MOVEFLAG_PRETEND_CORRECT_EMBARK_STATE))4969#else4970 if(!pUnit->PlotValid(pLoopPlot))4971#endif4972 {4973 continue;4974 }49754976 if(pLoopPlot->isVisibleEnemyUnit(pUnit))4977 {4978 continue;4979 }49804981 int iValue = 0;4982 if(pLoopPlot->getOwner() != NO_PLAYER && GET_PLAYER(pLoopPlot->getOwner()).getTeam() == m_pPlayer->getTeam())4983 {4984 // if this is within our territory, provide a minor benefit4985 iValue += 1;4986 }49874988#if defined(MOD_AI_SECONDARY_WORKERS)4989 if (bSecondary && pUnit->getDomainType() == DOMAIN_LAND && pLoopPlot->isWater()) {4990 // being embarked is NOT safe!4991 iValue -= 100;4992 }4993#endif49944995 CvCity* pCity = pLoopPlot->getPlotCity();4996 if(pCity && pCity->getTeam() == pUnit->getTeam())4997 {4998 iValue += pCity->getStrengthValue() * (GC.getMAX_CITY_DEFENSE_DAMAGE() - pCity->getDamage());4999 }5000 else if(!bIgnoreUnits)5001 {5002 IDInfo* pUnitNode = pLoopPlot->headUnitNode();5003 while(pUnitNode != NULL)5004 {5005 CvUnit* pLoopUnit = ::getUnit(*pUnitNode);5006 pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);50075008 if(pLoopUnit && pLoopUnit->getOwner() == pUnit->getOwner())5009 {5010 if(pLoopUnit->IsCanDefend())5011 {5012 if(pLoopUnit != pUnit)5013 {5014 if(pLoopUnit->isWaiting() || !(pLoopUnit->canMove()))5015 {5016 iValue += pLoopUnit->GetMaxDefenseStrength(pLoopPlot, NULL) * pLoopUnit->GetCurrHitPoints();5017 }5018 }5019 }5020 }5021 }5022 }50235024 iValue -= m_pPlayer->GetPlotDanger(*pLoopPlot);50255026 aBestPlotList.push_back(pLoopPlot, iValue);5027 }5028 }50295030 // Now loop through the sorted score list and go to the best one we can reach in one turn.5031 CvPlot* pBestPlot = NULL;5032 uint uiListSize;5033 if ((uiListSize = aBestPlotList.size()) > 0)5034 {5035 aBestPlotList.SortItems(); // highest score will be first.5036 for (uint i = 0; i < uiListSize; ++i ) 5037 {5038 CvPlot* pPlot = aBestPlotList.GetElement(i);50395040 int iPathTurns;5041 if(!pUnit->GeneratePath(pPlot, MOVE_UNITS_IGNORE_DANGER, true, &iPathTurns))5042 {5043 continue;5044 }50455046 // if we can't get there this turn, forget it5047 if(iPathTurns > 1)5048 {5049 continue;5050 }50515052 pBestPlot = pPlot;5053 break;5054 }5055 }50565057 if(pBestPlot != NULL)5058 {5059 if(pUnit->atPlot(*pBestPlot))5060 {5061 if (pUnit->canHold(pBestPlot))5062 {5063 if(GC.getLogging() && GC.getAILogging())5064 {5065 CvString strLogString;5066 CvString strTemp;5067 strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();5068 strLogString.Format("%s (%d) tried to move to safety but is at the best spot, X: %d, Y: %d", strTemp.GetCString(), pUnit->GetID(), pBestPlot->getX(), pBestPlot->getY());5069 LogHomelandMessage(strLogString);5070 }50715072 pUnit->PushMission(CvTypes::getMISSION_SKIP());5073 return true;5074 }5075 else5076 {5077 if(GC.getLogging() && GC.getAILogging())5078 {5079 CvString strLogString;5080 CvString strTemp;5081 strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();5082 strLogString.Format("%s (%d) tried to move to safety but cannot hold in current location, X: %d, Y: %d", strTemp.GetCString(), pUnit->GetID(), pBestPlot->getX(), pBestPlot->getY());5083 LogHomelandMessage(strLogString);5084 }5085 pUnit->SetAutomateType(NO_AUTOMATE);5086 }5087 }5088 else5089 {5090 if(GC.getLogging() && GC.getAILogging())5091 {5092 CvString strLogString;5093 CvString strTemp;5094 strTemp = GC.getUnitInfo(pUnit->getUnitType())->GetDescription();5095 strLogString.Format("%s (%d) moving to safety, X: %d, Y: %d", strTemp.GetCString(), pUnit->GetID(), pBestPlot->getX(), pBestPlot->getY());5096 LogHomelandMessage(strLogString);5097 }50985099 pUnit->PushMission(CvTypes::getMISSION_MOVE_TO(), pBestPlot->getX(), pBestPlot->getY(), MOVE_UNITS_IGNORE_DANGER);5100 return true;5101 }5102 }5103 else5104 {5105 if(GC.getLogging() && GC.getAILogging())5106 {5107 CvString strLogString;5108 CvString strTemp;5109 strTemp = pUnit->getUnitInfo().GetDescription();5110 strLogString.Format("%s (%d) tried to move to a safe point but couldn't find a good place to go", strTemp.GetCString(), pUnit->GetID());5111 LogHomelandMessage(strLogString);5112 }5113 }511451155116 return false;5117}