Bazaar developer reference

CvUnit::UnitPathTo(int, int, int, int, bool)

Defined in
CvUnit.cpp, line 23020
Class
CvUnit
Hook name
CivHooks::CvUnit_UnitPathTo

Hand-placed hooks inside

A replacement for this function that does not call original stops these hooks from running.

Hooks

static bool BeforeCvUnit_UnitPathTo(CvUnit* self, int iX, int iY, int iFlags, int iPrevETA, bool bBuildingRoute, int& result);static void AfterCvUnit_UnitPathTo(CvUnit* self, int iX, int iY, int iFlags, int iPrevETA, bool bBuildingRoute, int& result);static int ReplaceCvUnit_UnitPathTo(int (*original)(CvUnit*, int, int, int, int, bool), CvUnit* self, int iX, int iY, int iFlags, int iPrevETA, bool bBuildingRoute);CivRegisterBefore<CivHooks::CvUnit_UnitPathTo>(host, &BeforeCvUnit_UnitPathTo);CivRegisterAfter<CivHooks::CvUnit_UnitPathTo>(host, &AfterCvUnit_UnitPathTo);CivRegisterReplace<CivHooks::CvUnit_UnitPathTo>(host, &ReplaceCvUnit_UnitPathTo);

Code

23017// Returns the number of turns it will take to reach the target.  23018// If no move was made it will return 0. 23019// If it can reach the target in one turn or less than one turn (i.e. not use up all its movement points) it will return 123020int CvUnit::UnitPathTo(int iX, int iY, int iFlags, int iPrevETA, bool bBuildingRoute)23021{23022	VALIDATE_OBJECT23023	CvPlot* pDestPlot;23024	CvPlot* pPathPlot = NULL;2302523026	LOG_UNIT_MOVES_MESSAGE_OSTR( std::string("UnitPathTo() : player ") << GET_PLAYER(getOwner()).getName() << std::string(" ") << getName() << std::string(" id=") << GetID() << std::string(" moving to ") << iX << std::string(", ") << iY);2302723028	if(at(iX, iY))23029	{23030		LOG_UNIT_MOVES_MESSAGE("Already at location");23031		return 0;23032	}2303323034	CvAssert(!IsBusy());23035	CvAssert(getOwner() != NO_PLAYER);2303623037	CvMap& kMap = GC.getMap();23038	pDestPlot = kMap.plot(iX, iY);23039	CvAssertMsg(pDestPlot != NULL, "DestPlot is not assigned a valid value");23040	if(!pDestPlot)23041	{23042		LOG_UNIT_MOVES_MESSAGE("Destination is not a valid plot location");23043		return 0;23044	}2304523046	CvAssertMsg(canMove(), "canAllMove is expected to be true");2304723048	if(getDomainType() == DOMAIN_AIR)23049	{23050		if(!canMoveInto(*pDestPlot))23051		{23052#if defined(CIV_HOST_API)23053			CivHandUnitOrdersCancelled(this, CIV_ORDERS_CANNOT_LAND);hand-placed hook: UnitOrdersCancelled23054#endif23055			return 0;23056		}2305723058		pPathPlot = pDestPlot;23059		m_kLastPath.clear();		// Not used by air units, keep it clear.23060	}23061	else23062	{23063		if(bBuildingRoute)23064		{23065			if(!GC.GetBuildRouteFinder().GeneratePath(getX(), getY(), iX, iY, getOwner()))23066			{23067				LOG_UNIT_MOVES_MESSAGE("Unable to generate path with BuildRouteFinder");23068#if defined(CIV_HOST_API)23069				CivHandUnitOrdersCancelled(this, CIV_ORDERS_NO_ROUTE_TO_BUILD);hand-placed hook: UnitOrdersCancelled23070#endif23071				return 0;23072			}2307323074			CvAStarNode* pNode = GC.GetBuildRouteFinder().GetLastNode();23075			if(pNode)23076			{23077				// walk the nodes until the next node23078				while(pNode->m_pParent && pNode->m_pParent->m_pParent)23079				{23080					pNode = pNode->m_pParent;23081				}2308223083				pPathPlot = GC.getMap().plotCheckInvalid(pNode->m_iX, pNode->m_iY);23084			}2308523086			if(!pPathPlot || !canMoveInto(*pPathPlot, iFlags | MOVEFLAG_DESTINATION))23087			{23088#if defined(CIV_HOST_API)23089				CivHandUnitOrdersCancelled(this, CIV_ORDERS_ROUTE_BLOCKED);hand-placed hook: UnitOrdersCancelled23090#endif23091				// add route interrupted23092				CvNotifications* pNotifications = GET_PLAYER(getOwner()).GetNotifications();23093				if(pNotifications)23094				{23095					CvString strBuffer = GetLocalizedText("TXT_KEY_NOTIFICATION_ROUTE_TO_CANCELLED");23096					CvString strSummary = GetLocalizedText("TXT_KEY_NOTIFICATION_SUMMARY_ROUTE_TO_CANCELLED");23097					pNotifications->Add(NOTIFICATION_GENERIC, strBuffer, strSummary, getX(), getY(), -1);23098				}2309923100#ifdef LOG_UNIT_MOVES23101				if(!pPathPlot)23102					LOG_UNIT_MOVES_MESSAGE("pPathPlot is NULL");23103				else23104					LOG_UNIT_MOVES_MESSAGE_OSTR(std::string("Cannot move into pPathPlot ") << pPathPlot->getX() << std::string(" ") << pPathPlot->getY());23105#endif23106				return 0;23107			}23108		}23109		else23110		{23111			bool bPathGenerated = UpdatePathCache(pDestPlot, iFlags);2311223113			if (!bPathGenerated)23114			{23115				LOG_UNIT_MOVES_MESSAGE("Unable to Generate path");23116#if defined(CIV_HOST_API)23117				CivHandUnitOrdersCancelled(this, CIV_ORDERS_NO_PATH);hand-placed hook: UnitOrdersCancelled23118#endif23119				return 0;23120			}2312123122			pPathPlot = GetPathFirstPlot();23123		}23124	}2312523126	bool bRejectMove = false;2312723128	// slewis'd23129	if(m_kLastPath.size() != 0)23130	{23131		const CvPathNode& kNode = m_kLastPath.front();23132		// If we were provided with a previous ETA, check against the new one and if it is two turns greater, cancel the move.23133		// We probably revealed something that is causing the unit to take longer to reach the target.23134		if(iPrevETA >= 0 && kNode.m_iData2 > iPrevETA + 2)23135		{23136			LOG_UNIT_MOVES_MESSAGE_OSTR(std::string("Rejecting move iPrevETA=") << iPrevETA << std::string(", m_iData2=") << kNode.m_iData2);23137#if defined(CIV_HOST_API)23138			CivHandUnitOrdersCancelled(this, CIV_ORDERS_PATH_LONGER);hand-placed hook: UnitOrdersCancelled23139#endif23140			bRejectMove = true;23141		}2314223143		if(kNode.m_iData2 == 1 && !canMoveInto(*pDestPlot, MOVEFLAG_PRETEND_CORRECT_EMBARK_STATE))  // if we should end our turn there this turn, but can't move into that tile23144		{23145			// this is a bit tricky23146			// we want to see if this move would be a capture move23147			// Since we can't move into the tile, there may be an enemy unit there23148			// We can't move into tiles with enemy combat units, so getBestDefender should return null on the tile23149			// If there is no defender but we can attack move into the tile, then we know that it is a civilian unit and we should be able to move into it23150			const UnitHandle pDefender = pDestPlot->getBestDefender(NO_PLAYER, getOwner(), this, true);23151			if(!pDefender && !pDestPlot->isEnemyCity(*this) && canMoveInto(*pDestPlot, MOVEFLAG_ATTACK | MOVEFLAG_PRETEND_CORRECT_EMBARK_STATE))23152			{23153				// Turn on ability to move into enemy units in this case so we can capture civilians23154				iFlags |= MOVE_UNITS_THROUGH_ENEMY;23155			}2315623157			const MissionData* pkMissionData = GetHeadMissionData();23158			CvAssertMsg(pkMissionData, "Unit mission is null. Need to rethink this code!");23159			if(pkMissionData != NULL && pkMissionData->iPushTurn != GC.getGame().getGameTurn())23160			{23161				LOG_UNIT_MOVES_MESSAGE_OSTR(std::string("Rejecting move pkMissionData->iPushTurn=") << pkMissionData->iPushTurn << std::string(", GC.getGame().getGameTurn()=") << GC.getGame().getGameTurn());23162#if defined(CIV_HOST_API)23163				CivHandUnitOrdersCancelled(this, CIV_ORDERS_DESTINATION_BLOCKED);hand-placed hook: UnitOrdersCancelled23164#endif23165				bRejectMove = true;23166			}23167		}2316823169		if(bRejectMove)23170		{23171			m_kLastPath.clear();23172			// slewis - perform its queued moves?23173			PublishQueuedVisualizationMoves();23174			return 0;23175		}23176	}23177	// end slewis'd2317823179	bool bEndMove = (pPathPlot == pDestPlot);23180	bool bMoved = UnitMove(pPathPlot, iFlags & MOVE_UNITS_THROUGH_ENEMY, NULL, bEndMove);2318123182	int iETA = 1;23183	uint uiCachedPathSize = m_kLastPath.size();23184	if (uiCachedPathSize)23185	{23186		iETA = m_kLastPath[ 0 ].m_iData2;23187		// Only do the shift if we actually moved23188		if (bMoved)23189		{23190			if(uiCachedPathSize > 1)23191			{23192				// Go back to front, adjusting the turns if needed23193				if (m_kLastPath[ uiCachedPathSize - 1 ].m_iData2 != m_kLastPath[ uiCachedPathSize - 2 ].m_iData2)23194				{23195					// We have exhausted a turns worth of nodes.  Adjust all the others.23196					// KWG: It is unlikely that we will use this path again, because the unit is out of moves anyhow.  Should we just clear the path and save time?23197					for (uint uiIndex = uiCachedPathSize - 1; uiIndex--; )23198					{23199						CvPathNode* pNode = &m_kLastPath[uiIndex];23200						if (pNode->m_iData2 > 0)23201							pNode->m_iData2 -= 1;23202					}23203				}2320423205				m_kLastPath.pop_back();23206			}23207			else23208				m_kLastPath.clear();23209		}23210		else23211			m_kLastPath.clear();	// Failed to move, recalculate.23212	}2321323214	return iETA;23215}

Calls

Called by