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}