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}