Bazaar developer reference

CvUnit::canMoveInto(const CvPlot &, byte) const

Defined in
CvUnit.cpp, line 3068
Class
CvUnit
Hook name
CivHooks::CvUnit_canMoveInto
Lua events
GameEvents.CanMoveInto

Hooks

static bool BeforeCvUnit_canMoveInto(const CvUnit* self, const CvPlot& plot, byte bMoveFlags, bool& result);static void AfterCvUnit_canMoveInto(const CvUnit* self, const CvPlot& plot, byte bMoveFlags, bool& result);static bool ReplaceCvUnit_canMoveInto(bool (*original)(const CvUnit*, const CvPlot&, byte), const CvUnit* self, const CvPlot& plot, byte bMoveFlags);CivRegisterBefore<CivHooks::CvUnit_canMoveInto>(host, &BeforeCvUnit_canMoveInto);CivRegisterAfter<CivHooks::CvUnit_canMoveInto>(host, &AfterCvUnit_canMoveInto);CivRegisterReplace<CivHooks::CvUnit_canMoveInto>(host, &ReplaceCvUnit_canMoveInto);

Code

3068bool CvUnit::canMoveInto(const CvPlot& plot, byte bMoveFlags) const3069{3070	VALIDATE_OBJECT3071	TeamTypes ePlotTeam;30723073	if(atPlot(plot))3074	{3075		return false;3076	}30773078	// Cannot move around in unrevealed land freely3079	if(!(bMoveFlags & MOVEFLAG_PRETEND_UNEMBARKED) && isNoRevealMap() && willRevealByMove(plot))3080	{3081		return false;3082	}30833084	// Barbarians have special restrictions early in the game3085	if(isBarbarian() && (GC.getGame().getGameTurn() < GC.getGame().GetBarbarianReleaseTurn()) && (plot.isOwned()))3086	{3087		return false;3088	}30893090	// Added in Civ 5: Destination plots can't allow stacked Units of the same type3091#if defined(MOD_GLOBAL_BREAK_CIVILIAN_RESTRICTIONS)3092	if((bMoveFlags & MOVEFLAG_DESTINATION) && (!MOD_GLOBAL_BREAK_CIVILIAN_RESTRICTIONS || !IsCivilianUnit()))3093#else3094	if(bMoveFlags & MOVEFLAG_DESTINATION)3095#endif3096	{3097		// Don't let another player's unit inside someone's city3098		if(!(bMoveFlags & MOVEFLAG_ATTACK) && !(bMoveFlags & MOVEFLAG_DECLARE_WAR))3099		{3100			if(plot.isCity() && plot.getPlotCity()->getOwner() != getOwner())3101				return false;3102		}31033104		// Check to see if any units are present at this full-turn move plot (borrowed from CvGameCoreUtils::pathDestValid())3105#if defined(MOD_GLOBAL_STACKING_RULES)3106		if(!(bMoveFlags & MOVEFLAG_IGNORE_STACKING) && plot.getUnitLimit() > 0)3107#else3108		if(!(bMoveFlags & MOVEFLAG_IGNORE_STACKING) && GC.getPLOT_UNIT_LIMIT() > 0)3109#endif3110		{3111			// pSelectionGroup has no Team but the HeadUnit does... ???3112#if defined(MOD_GLOBAL_STACKING_RULES)3113			if(plot.isVisible(getTeam()) && plot.getNumFriendlyUnitsOfType(this) >= plot.getUnitLimit())3114#else3115			if(plot.isVisible(getTeam()) && plot.getNumFriendlyUnitsOfType(this) >= GC.getPLOT_UNIT_LIMIT())3116#endif3117			{3118				return FALSE;3119			}3120		}3121	}31223123	if(isNoCapture())3124	{3125		if(!(bMoveFlags & MOVEFLAG_ATTACK))3126		{3127			if(plot.isEnemyCity(*this))3128			{3129				return false;3130			}3131		}3132	}31333134	if(bMoveFlags & MOVEFLAG_ATTACK)3135	{3136		if(isOutOfAttacks())3137		{3138#if defined(MOD_GLOBAL_CAPTURE_AFTER_ATTACKING)3139			// If there are only enemy civilians in the plot, then we don't need remaining attacks to capture them3140			// eg a worker in a barbarian camp where we just killed the defender3141			if (plot.getBestDefender(NO_PLAYER) != ((UnitHandle) NULL))3142			{3143				return false;3144			}3145#else3146			return false;3147#endif3148		}31493150		// Does unit only attack cities?3151		if(IsCityAttackOnly() && !plot.isEnemyCity(*this) && plot.getBestDefender(NO_PLAYER))3152		{3153			return false;3154		}3155	}31563157	// Can't enter an enemy city until it's "defeated"3158	if(plot.isEnemyCity(*this))3159	{3160		if(plot.getPlotCity()->getDamage() < plot.getPlotCity()->GetMaxHitPoints() && !(bMoveFlags & MOVEFLAG_ATTACK))3161		{3162			return false;3163		}3164		if(bMoveFlags & MOVEFLAG_ATTACK)3165		{3166			if(getDomainType() == DOMAIN_AIR)3167				return false;3168			if(isHasPromotion((PromotionTypes)GC.getPROMOTION_ONLY_DEFENSIVE()))3169				return false;	// Can't advance into an enemy city3170		}3171	}31723173	if(getDomainType() == DOMAIN_AIR)3174	{3175		if(bMoveFlags & MOVEFLAG_ATTACK)3176		{3177			if(!canRangeStrikeAt(plot.getX(), plot.getY()))3178			{3179				return false;3180			}3181		}3182	}3183	else3184	{3185		if(bMoveFlags & MOVEFLAG_ATTACK)3186		{3187			if(!IsCanAttack())  // trying to give an attack order to a unit that can't fight. That doesn't work!3188			{3189				return false;3190			}31913192			if(getDomainType() == DOMAIN_LAND && plot.isWater() && !canMoveAllTerrain() && !plot.IsAllowsWalkWater())3193			{3194				return false;3195			}31963197			if(!isHuman() || (plot.isVisible(getTeam())))3198			{3199				// This stuff to the next if statement is to get units to advance into a tile with an enemy if that enemy is dying...3200				bool bCanAdvanceOnDeadUnit = false;32013202				const IDInfo* pUnitNode = plot.headUnitNode();3203				const CvUnit* pLoopUnit;32043205				bool bPlotContainsCombat = false;3206				while(pUnitNode != NULL)3207				{3208					pLoopUnit = ::getUnit(*pUnitNode);3209					CvAssertMsg(pLoopUnit, "pUnitNode data should lead to a unit");32103211					pUnitNode = plot.nextUnitNode(pUnitNode);32123213					// NULL check is always a good thing to do.3214					if(pLoopUnit)3215					{3216						if(GET_TEAM(getTeam()).isAtWar(GET_PLAYER(pLoopUnit->getOwner()).getTeam()))3217						{3218							if(!pLoopUnit->IsDead() && pLoopUnit->isInCombat())3219							{3220								if(pLoopUnit->getCombatUnit() != this)3221									bPlotContainsCombat = true;3222							}32233224							if(pLoopUnit->IsDead() || !pLoopUnit->IsCombatUnit())3225							{3226								bCanAdvanceOnDeadUnit = true;3227							}3228							else3229							{3230								bCanAdvanceOnDeadUnit = false;3231								break;3232							}3233						}3234					}3235				}32363237				if(bPlotContainsCombat)3238				{3239					return false;		// Can't enter a plot that contains combat that doesn't involve us.3240				}32413242				if(!bCanAdvanceOnDeadUnit)3243				{3244					if(plot.isVisibleEnemyUnit(this) != (bMoveFlags & MOVEFLAG_ATTACK))3245					{3246						// Prevent an attack from failing if a city is empty but still an "enemy" capable of being attacked (this wouldn't happen before in Civ 4)3247						if(!(bMoveFlags & MOVEFLAG_ATTACK) || !plot.isEnemyCity(*this))3248						{3249							if(!(bMoveFlags & MOVEFLAG_DECLARE_WAR) || (plot.isVisibleOtherUnit(getOwner()) != (bMoveFlags & MOVEFLAG_ATTACK) && !((bMoveFlags & MOVEFLAG_ATTACK) && plot.getPlotCity() && !isNoCapture())))3250							{3251								return false;3252							}3253						}3254					}3255				}3256			}32573258			if(plot.isVisible(getTeam()))3259			{3260				const UnitHandle pDefender = plot.getBestDefender(NO_PLAYER, getOwner(), this, true);3261				if(pDefender)3262				{3263					if(pDefender->getDamage() >= GetCombatLimit())3264					{3265						return false;3266					}32673268					// EFB: Check below is not made when capturing civilians3269					else if(pDefender->GetBaseCombatStrength() > 0)	// Note: this value will be 0 for embarked Units3270					{3271						// EFB: Added so units can't come out of cities to attack (but so that units in city's pathing doesn't fail all the time)3272						if(!(bMoveFlags & MOVEFLAG_NOT_ATTACKING_THIS_TURN) && !IsCanAttackWithMoveNow())3273						{3274							return false;3275						}3276					}3277				}3278			}3279		}3280		else //if !(bMoveFlags & MOVEFLAG_ATTACK)3281		{3282			bool bEmbarkedAndAdjacent = false;3283			bool bEnemyUnitPresent = false;32843285			// Without this code, Embarked Units can move on top of enemies because they have no visibility3286			if(isEmbarked() || (bMoveFlags & MOVEFLAG_PRETEND_EMBARKED))3287			{3288				if(plotDistance(getX(), getY(), plot.getX(), plot.getY()) == 1)3289				{3290					bEmbarkedAndAdjacent = true;3291				}3292			}32933294			bool bPlotContainsCombat = false;3295			if(plot.getNumUnits())3296			{3297				for(int iUnitLoop = 0; iUnitLoop < plot.getNumUnits(); iUnitLoop++)3298				{3299					CvUnit* loopUnit = plot.getUnitByIndex(iUnitLoop);33003301					if(loopUnit && GET_TEAM(getTeam()).isAtWar(plot.getUnitByIndex(iUnitLoop)->getTeam()))3302					{3303						bEnemyUnitPresent = true;3304						if(!loopUnit->IsDead() && loopUnit->isInCombat())3305						{3306							if(loopUnit->getCombatUnit() != this)3307								bPlotContainsCombat = true;3308						}3309						break;3310					}3311				}3312			}33133314			if(bPlotContainsCombat)3315			{3316				return false;		// Can't enter a plot that contains combat that doesn't involve us.3317			}33183319			if(!isHuman() || plot.isVisible(getTeam()) || bEmbarkedAndAdjacent)3320			{3321				if(plot.isEnemyCity(*this))3322				{3323					return false;3324				}33253326				if(plot.isVisibleEnemyUnit(this) || (bEmbarkedAndAdjacent && bEnemyUnitPresent))3327				{3328					return false;3329				}3330			}3331		}33323333		ePlotTeam = ((isHuman()) ? plot.getRevealedTeam(getTeam()) : plot.getTeam());33343335		if(!canEnterTerritory(ePlotTeam, false /*bIgnoreRightOfPassage*/, plot.isCity(), bMoveFlags & MOVEFLAG_DECLARE_WAR))3336		{3337			CvAssert(ePlotTeam != NO_TEAM);33383339#if defined(MOD_EVENTS_WAR_AND_PEACE)3340			if(!(GET_TEAM(getTeam()).canDeclareWar(ePlotTeam, getOwner())))3341#else3342			if(!(GET_TEAM(getTeam()).canDeclareWar(ePlotTeam)))3343#endif3344			{3345				return false;3346			}33473348			if(isHuman())3349			{3350				if(!(bMoveFlags & MOVEFLAG_DECLARE_WAR))3351				{3352					return false;3353				}3354			}3355			else3356			{3357				return false;3358			}3359		}3360	}33613362#if defined(MOD_EVENTS_CAN_MOVE_INTO)3363	if (MOD_EVENTS_CAN_MOVE_INTO && m_pUnitInfo->IsSendCanMoveIntoEvent()) {3364		if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_CanMoveInto, getOwner(), GetID(), plot.getX(), plot.getY(), ((bMoveFlags & MOVEFLAG_ATTACK) != 0), ((bMoveFlags & MOVEFLAG_DECLARE_WAR) != 0)) == GAMEEVENTRETURN_FALSE) {3365			return false;3366		}3367	}3368#endif33693370	// Make sure we can enter the terrain.  Somewhat expensive call, so we do this last.3371	if(!canEnterTerrain(plot, bMoveFlags))3372	{3373		return false;3374	}33753376	return true;3377}

Calls

Called by