* @brief Calculates the world position for creature movement along its path. * * This function walks the path from creature's current box to the target box, * finding the best position to move toward. It handles box boundary clipping * to ensure the creature moves along valid paths through connected boxes. * * CLIPPING SYSTEM: * - Uses directional flags (CLIP_LEFT/RIGHT/TOP/BOTTOM) to track
| 3022 | * @return TARGET_TYPE indicating the quality of target found. |
| 3023 | */ |
| 3024 | TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) |
| 3025 | { |
| 3026 | // Set creature's current box for A* heuristic. |
| 3027 | LOT->SourceBox = item->BoxNumber; |
| 3028 | |
| 3029 | // Expand the pathfinding search if needed. |
| 3030 | UpdateLOT(LOT, g_GameFlow->GetSettings()->Pathfinding.SearchDepth); |
| 3031 | |
| 3032 | // Start with creature's current position as default target. |
| 3033 | *target = item->Pose.Position; |
| 3034 | |
| 3035 | int boxNumber = item->BoxNumber; |
| 3036 | if (boxNumber == NO_VALUE) |
| 3037 | return TARGET_TYPE::NO_TARGET; |
| 3038 | |
| 3039 | auto* box = &g_Level.PathfindingBoxes[boxNumber]; |
| 3040 | |
| 3041 | // Convert box boundaries to world coordinates. |
| 3042 | // Note: box coordinates are in blocks, multiply by BLOCK(1) for world units. |
| 3043 | int boxLeft = ((int)box->left * BLOCK(1)); |
| 3044 | int boxRight = ((int)box->right * BLOCK(1)) - 1; |
| 3045 | int boxTop = ((int)box->top * BLOCK(1)); |
| 3046 | int boxBottom = ((int)box->bottom * BLOCK(1)) - 1; |
| 3047 | |
| 3048 | // Track the valid corridor as we traverse boxes. |
| 3049 | int left = boxLeft; |
| 3050 | int right = boxRight; |
| 3051 | int top = boxTop; |
| 3052 | int bottom = boxBottom; |
| 3053 | int direction = CLIP_ALL; // Can move in all directions initially. |
| 3054 | |
| 3055 | // Safety limit to prevent infinite loops from corrupted exitBox chains. |
| 3056 | int maxIterations = (int)g_Level.PathfindingBoxes.size(); |
| 3057 | int iterations = 0; |
| 3058 | |
| 3059 | // MAIN LOOP: Walk along the path from current box to target box. |
| 3060 | do |
| 3061 | { |
| 3062 | if (++iterations > maxIterations) |
| 3063 | break; |
| 3064 | |
| 3065 | box = &g_Level.PathfindingBoxes[boxNumber]; |
| 3066 | |
| 3067 | // Clamp target Y to box height. |
| 3068 | // Flying creatures stay above the floor. |
| 3069 | if (LOT->Fly != NO_FLYING) |
| 3070 | { |
| 3071 | if (target->y > box->height - BLOCK(1)) |
| 3072 | target->y = box->height - BLOCK(1); |
| 3073 | } |
| 3074 | else if (target->y > box->height) |
| 3075 | { |
| 3076 | target->y = box->height; |
| 3077 | } |
| 3078 | |
| 3079 | // Get current box boundaries. |
| 3080 | boxLeft = ((int)box->left * BLOCK(1)); |
| 3081 | boxRight = ((int)box->right * BLOCK(1)) - 1; |
no test coverage detected