Bazaar developer reference

CanSeeDisplacementPlot_Loose(int, int, int, int, int)

Defined in
CvTargeting.cpp, line 333
Hook name
CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Loose

Hooks

static bool BeforeCvTargeting_cpp_CanSeeDisplacementPlot_Loose(int startX, int startY, int dx, int dy, int fromLevel, bool& result);static void AfterCvTargeting_cpp_CanSeeDisplacementPlot_Loose(int startX, int startY, int dx, int dy, int fromLevel, bool& result);static bool ReplaceCvTargeting_cpp_CanSeeDisplacementPlot_Loose(bool (*original)(int, int, int, int, int), int startX, int startY, int dx, int dy, int fromLevel);CivRegisterBefore<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Loose>(host, &BeforeCvTargeting_cpp_CanSeeDisplacementPlot_Loose);CivRegisterAfter<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Loose>(host, &AfterCvTargeting_cpp_CanSeeDisplacementPlot_Loose);CivRegisterReplace<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Loose>(host, &ReplaceCvTargeting_cpp_CanSeeDisplacementPlot_Loose);

Code

330//	Test if the team can see from the supplied hex to a displacement in HEXSPACE331//	from the start hex.332//	This is the 'loose' version that lets you see around partially blocked hexes333static bool CanSeeDisplacementPlot_Loose(int startX, int startY, int dx, int dy, int fromLevel)334{335	int originalDX = dx;336	int originalDY = dy;337338	CvMap& kMap = GC.getMap();339340	// Use Bresenham's line algorithm, with a slight modification, to step through the cells.341	// The modification is that if we are stepping in the upper-right or lower-left quadrant,342	// and we need to take a step on the 'short' axis, we will check the plot with just the343	// adjustment to the X axis, before we do the normal check for the step on the X and Y344	// axis.  This is needed because in those quadrants a change on both the X and Y axis 345	// is not contiguous.346347	// Because the hex grid is low-resolution, checks are also made to allow the ray to continue 348	// around a blockage if that blockage obscures only part of the next hex cell along the ray.349	// This is done by 'looking back' at the alternate path the ray could have taken as it is 350	// traversing the hex grid.351352	// Make DX and DY positive and adjust the step constant for the opposite axis.353	int stepY;354	if (dy < 0) 355	{ 356		dy = -dy;  357		stepY = -1; 358	} 359	else 360		stepY = 1; 361362	int stepX;363	if (dx < 0) 364	{ 365		dx = -dx;  366		stepX = -1; 367	} 368	else 369		stepX = 1;370371	dy <<= 1;372	dx <<= 1;373374	int currentDX = 0;375	int currentDY = 0;376377	bool bBlocked = false;378	// If in an odd quadrant, stepping down on the short axis requires two checks to be contiguous379	bool oddQuadrant = stepX != stepY;380	// Is the line going to go such that it travels through the centers of the hexes?381	// If so, we don't have to worry about testing to see if we can look around blocked hexes.382	bool straightThrough = dx == 0 || dy == 0;383384	// Start from the next cell after the source plot385	int lastDX = currentDX;386	int lastDY = currentDY;387	int blockedDirection = 0;388389	// If dx is greater than dy, scan along the x axis, adjusting the Y as needed390	if (dx > dy) 391	{392		int shortAxisStepFactor = (dx >> 1); 393		while (currentDX != originalDX) 394		{395			shortAxisStepFactor += dy;396397			if (shortAxisStepFactor >= dx) 398			{399				shortAxisStepFactor -= dx;400401				if (oddQuadrant)402				{403					currentDX += stepX;404					currentDY += stepY;405				}406				else407				{408					currentDX += stepX;409410					// If we were blocked by the previous hex, see if we are able to look around the adjacent one if we split between them411					if (bBlocked)412					{413						if (!straightThrough)414						{415							CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[blockedDirection], startY + currentDY + ms_LookBackY[blockedDirection]);416							if(passThroughPlot)417							{418								TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);419								bBlocked = (fromLevel < passThroughPlot->seeThroughLevel());420							}421422							if (bBlocked)423								return false;424						}425						else426							return false;427					}428429					// Don't test the destination, we only want to test the plots between the start and the destination430					if (currentDX == originalDX && currentDY == originalDY)431						break;	432433					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);434					TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);435					if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())436					{437						bBlocked = true;438						blockedDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];439					}440441					lastDX = currentDX; lastDY = currentDY;442443					currentDY += stepY;444				}445			}446			else447				currentDX += stepX;448449			// If we were blocked by the previous hex, see if we are able to look around the adjacent one if we split between them450			if (bBlocked)451			{452				if (!straightThrough)	// If going along a single axis, we are looking directly down the middle of a hex so there is nothing to look around.453				{454					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[blockedDirection], startY + currentDY + ms_LookBackY[blockedDirection]);455					if(passThroughPlot)456					{457						TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);458						bBlocked = (fromLevel < passThroughPlot->seeThroughLevel());459					}460461					if (bBlocked)462						return false;463				}464				else465					return false;466			}467468			// Don't test the destination, we only want to test the plots between the start and the destination469			if (currentDX == originalDX && currentDY == originalDY)470				break;	471472			CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);473			TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);474			if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())475			{476				bBlocked = true;477				blockedDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];478			}479480			lastDX = currentDX; lastDY = currentDY;481		}482	} 483	else 484	{485		// Y axis runs are longer, scan along them and adjust the X as needed.486		// The short axis step is primed slightly differently if the step ratio is 2:1487		// so that the initial step goes in a more favorable direction488		int shortAxisStepFactor = (dy!=dx && dx != 0 && (dy>>1) == dx)?((dy >> 1) - dx):(dy >> 1);489		//int fraction = (dy >> 1);490		while (currentDY != originalDY) 491		{492			shortAxisStepFactor += dx;493494			if (shortAxisStepFactor >= dy) 495			{496				shortAxisStepFactor -= dy;497498				if (oddQuadrant)499				{500					// A change in the X and Y axis will yield a contiguous line501					currentDX += stepX;502					currentDY += stepY;503				}504				else505				{506					// Adjust just the X axis, then check so that the line is contiguous.507					currentDX += stepX;508509					// If we were blocked by the previous hex, see if we are able to look around the adjacent one if we split between them510					if (bBlocked)511					{512						if (!straightThrough)	// If going along a single axis, we are looking directly down the middle of a hex so there is nothing to look around.513						{514							CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[blockedDirection], startY + currentDY + ms_LookBackY[blockedDirection]);515							if(passThroughPlot)516							{517								TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);518								bBlocked = (fromLevel < passThroughPlot->seeThroughLevel());519							}520521							if (bBlocked)522								return false;523						}524						else525							return false;526					}527528					// Don't test the destination, we only want to test the plots between the start and the destination529					if (currentDX == originalDX && currentDY == originalDY)530						break;	531532					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);533					TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);534					if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())535					{536						bBlocked = true;537						blockedDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];538					}539540					lastDX = currentDX; lastDY = currentDY;541542					currentDY += stepY;543				}544			}545			else546				currentDY += stepY;547548			// If we were blocked by the previous hex, see if we are able to look around the adjacent one if we split between them549			if (bBlocked)550			{551				if (!straightThrough)	// If going along a single axis, we are looking directly down the middle of a hex so there is nothing to look around.552				{553					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[blockedDirection], startY + currentDY + ms_LookBackY[blockedDirection]);554					if(passThroughPlot)555					{556						TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);557						bBlocked = (fromLevel < passThroughPlot->seeThroughLevel());558					}559560					if (bBlocked)561						return false;562				}563				else564					return false;565			}566567			// Don't test the destination, we only want to test the plots between the start and the destination568			if (currentDX == originalDX && currentDY == originalDY)569				break;	570571			CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);572			TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);573			if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())574			{575				bBlocked = true;576				blockedDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];577			}578579			lastDX = currentDX; lastDY = currentDY;580		}581	}582583	return true;584}

Calls

Called by