Bazaar developer reference

CanSeeDisplacementPlot_Strict(int, int, int, int, int)

Defined in
CvTargeting.cpp, line 102
Hook name
CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Strict

Hooks

static bool BeforeCvTargeting_cpp_CanSeeDisplacementPlot_Strict(int startX, int startY, int dx, int dy, int fromLevel, bool& result);static void AfterCvTargeting_cpp_CanSeeDisplacementPlot_Strict(int startX, int startY, int dx, int dy, int fromLevel, bool& result);static bool ReplaceCvTargeting_cpp_CanSeeDisplacementPlot_Strict(bool (*original)(int, int, int, int, int), int startX, int startY, int dx, int dy, int fromLevel);CivRegisterBefore<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Strict>(host, &BeforeCvTargeting_cpp_CanSeeDisplacementPlot_Strict);CivRegisterAfter<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Strict>(host, &AfterCvTargeting_cpp_CanSeeDisplacementPlot_Strict);CivRegisterReplace<CivHooks::CvTargeting_cpp_CanSeeDisplacementPlot_Strict>(host, &ReplaceCvTargeting_cpp_CanSeeDisplacementPlot_Strict);

Code

97//	Test if the team can see from the supplied hex to a displacement in HEXSPACE98//	from the start hex.99//	This is the strict version that prevents you from seeing through partially blocked hexes100//	after a certain distance threshold is reached.  Even when below the distance threshold101//	more than one blockage will cause the LOS to fail.102static bool CanSeeDisplacementPlot_Strict(int startX, int startY, int dx, int dy, int fromLevel)103{104	int originalDX = dx;105	int originalDY = dy;106107	CvMap& kMap = GC.getMap();108109	// Use Bresenham's line algorithm, with a slight modification, to step through the cells.110	// The modification is that if we are stepping in the upper-right or lower-left quadrant,111	// and we need to take a step on the 'short' axis, we will check the plot with just the112	// adjustment to the X axis, before we do the normal check for the step on the X and Y113	// axis.  This is needed because in those quadrants a change on both the X and Y axis 114	// is not contiguous.115116	// Because the hex grid is low-resolution, checks are also made to allow the ray to continue 117	// around a blockage if that blockage obscures only part of the next hex cell along the ray.118	// This is done by 'looking back' at the alternate path the ray could have taken as it is 119	// traversing the hex grid.120121	// Make DX and DY positive and adjust the step constant for the opposite axis.122	int stepY;123	if (dy < 0) 124	{ 125		dy = -dy;  126		stepY = -1; 127	} 128	else 129		stepY = 1; 130131	int stepX;132	if (dx < 0) 133	{ 134		dx = -dx;  135		stepX = -1; 136	} 137	else 138		stepX = 1;139140	dy <<= 1;141	dx <<= 1;142143	int currentDX = 0;144	int currentDY = 0;145146	// If in an odd quadrant, stepping down on the short axis requires two checks to be contiguous147	bool oddQuadrant = stepX != stepY;148	// Is the line going to go such that it travels through the centers of the hexes?149	// If so, we don't have to worry about testing to see if we can look around blocked hexes.150	bool straightThrough = dx == 0 || dy == 0;151152	// Start from the next cell after the source plot153	int lastDX = currentDX;154	int lastDY = currentDY;155	int lookbackDirection = -1;156	int stepCount = 0;157	int iBlockedCount = 0;158159	// If dx is greater than dy, scan along the x axis, adjusting the Y as needed160	if (dx > dy) 161	{162		int shortAxisStepFactor = (dx >> 1); 163		while (currentDX != originalDX) 164		{165			shortAxisStepFactor += dy;166167			if (shortAxisStepFactor >= dx) 168			{169				shortAxisStepFactor -= dx;170171				if (oddQuadrant)172				{173					currentDX += stepX;174					currentDY += stepY;175				}176				else177				{178					currentDX += stepX;179180					// Look back to see if we were possibly blocked by the alternate route to this hex.  We will ignore the check if inside the rings that allow the user to look around obstacles.181					if (!straightThrough && lookbackDirection != -1)182					{183						CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[lookbackDirection], startY + currentDY + ms_LookBackY[lookbackDirection]);184						TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);185						if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())186						{187							++iBlockedCount;188							if (stepCount > STRICT_LOOSE_CUTOFF || iBlockedCount >= 2)189								return false;190						}191					}192193					// Don't test the destination, we only want to test the plots between the start and the destination194					if (currentDX == originalDX && currentDY == originalDY)195						break;	196197					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);198					TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);199					if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())200						return false;201202					lookbackDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];203204					++stepCount;205					lastDX = currentDX; lastDY = currentDY;206207					currentDY += stepY;208				}209			}210			else211				currentDX += stepX;212213			// Look back to see if we were possibly blocked by the alternate route to this hex.214			if (!straightThrough && lookbackDirection != -1)215			{216				CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[lookbackDirection], startY + currentDY + ms_LookBackY[lookbackDirection]);217				TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);218				if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())219				{220					if (stepCount > STRICT_LOOSE_CUTOFF || ++iBlockedCount >= 2)221						return false;222				}223			}224225			// Don't test the destination, we only want to test the plots between the start and the destination226			if (currentDX == originalDX && currentDY == originalDY)227				break;	228229			CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);230			TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);231			if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())232				return false;233234			lookbackDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];235236			++stepCount;237			lastDX = currentDX; lastDY = currentDY;238		}239	} 240	else 241	{242		// Y axis runs are longer, scan along them and adjust the X as needed.243		// The short axis step is primed slightly differently if the step ratio is 2:1244		// so that the initial step goes in a more favorable direction245		int shortAxisStepFactor = (dy!=dx && dx != 0 && (dy>>1) == dx)?((dy >> 1) - dx):(dy >> 1);246		//int fraction = (dy >> 1);247		while (currentDY != originalDY) 248		{249			shortAxisStepFactor += dx;250251			if (shortAxisStepFactor >= dy) 252			{253				shortAxisStepFactor -= dy;254255				if (oddQuadrant)256				{257					// A change in the X and Y axis will yield a contiguous line258					currentDX += stepX;259					currentDY += stepY;260				}261				else262				{263					// Adjust just the X axis, then check so that the line is contiguous.264					currentDX += stepX;265266					// Look back to see if we were possibly blocked by the alternate route to this hex.267					if (!straightThrough && lookbackDirection != -1)268					{269						CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[lookbackDirection], startY + currentDY + ms_LookBackY[lookbackDirection]);270						TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);271						if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())272						{273							if (stepCount > STRICT_LOOSE_CUTOFF || ++iBlockedCount >= 2)274								return false;275						}276					}277278					// Don't test the destination, we only want to test the plots between the start and the destination279					if (currentDX == originalDX && currentDY == originalDY)280						break;	281282					CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);283					TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);284					if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())285						return false;286287					lookbackDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];288289					++stepCount;290					lastDX = currentDX; lastDY = currentDY;291292					currentDY += stepY;293				}294			}295			else296				currentDY += stepY;297298			// Look back to see if we were possibly blocked by the alternate route to this hex.299			if (!straightThrough && lookbackDirection != -1)300			{301				CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX + ms_LookBackX[lookbackDirection], startY + currentDY + ms_LookBackY[lookbackDirection]);302				TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);303				if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())304				{305					if (stepCount > STRICT_LOOSE_CUTOFF || ++iBlockedCount >= 2)306						return false;307				}308			}309310			// Don't test the destination, we only want to test the plots between the start and the destination311			if (currentDX == originalDX && currentDY == originalDY)312				break;	313314			CvPlot* passThroughPlot = PlotFromHex(kMap, startX + currentDX, startY + currentDY);315			TRACK_LAST_TARGET_PATH_ENTRY(passThroughPlot);316			if(!passThroughPlot || fromLevel < passThroughPlot->seeThroughLevel())317				return false;318319			lookbackDirection = ms_HexDirection[(currentDX - lastDX) + 1][(currentDY - lastDY) + 1];320321			++stepCount;322			lastDX = currentDX; lastDY = currentDY;323		}324	}325326	return true;327}

Calls

Called by