# 08. Giải quyết Triệt để Lỗi Nhân vật Bất động & Quy chuẩn Điều hướng Thực địa (POE2 Early Access v0.5.5)

> **Mốc thời gian tham chiếu**: 07/09/2026  
> **Phiên bản Game**: Path of Exile 2 Early Access (Patch 0.5.5c/d)  
> **Kiến trúc**: Tier 1 C++23 Low-Latency Core Engine (120Hz) & Tier 2 Python 3.11 Passive Companion / Autonomous Lifecycle.

---

## 1. Bối cảnh & Hiện tượng Thực địa

Khi người chơi vận hành `AutoPOE2.exe` (Single Executable), nhật ký (log) của hệ thống liên tục ghi nhận trạng thái hoạt động bình thường (`AutoPatrol`, `TownQuestEngine`, `ComboManager`), tuy nhiên nhân vật trong cửa sổ game hoàn toàn bất động, không di chuyển, không tung kỹ năng và không tương tác.

Qua phân tích bộ nhớ thực địa (`check_live_shm.py`, `AutoPOE2_MemProbe.exe`, Win32 API Inspection), đội ngũ kỹ thuật đã xác định và xử lý triệt để 4 nguyên nhân gốc rễ (Root Causes) như sau.

---

## 2. Phân tích Nguyên nhân Gốc rễ (Root Causes)

```mermaid
graph TD
    A["Nhân vật bất động dù Log báo Running"] --> B["1. Điều kiện chặn maxHP == 0"]
    A --> C["2. Xung đột Đa tiến trình Core Engine"]
    A --> D["3. Lệch Window Class Name & Title"]
    A --> E["4. Rào cản Windows Foreground Focus"]

    B --> B1["AutoPositionScan bắt được XYZ nhưng HP chưa scan xong<br/>-> QuestNavigator & ComboManager return false lập tức"]
    C --> C1["Hai tiến trình Core cùng ghi Shared Memory<br/>-> Gây xung đột Seqlock & SPSC Ring Buffer"]
    D --> D1["Game POE2 dùng class POEWindowClass<br/>-> Không phải POEC2_MainWindow"]
    E --> E1["Windows hạn chế SendInput / mouse_event chạy ngầm<br/>-> Cần AttachThreadInput + SetForegroundWindow"]
```

### 2.1. Điều kiện chặn `maxHP == 0` (Health Guard Deadlock) & Cơ Chế Proactive Micro-movement Step
- **Cơ chế cũ & Bế tắc Deadlock**:
  - Cả `QuestNavigator::Update`, `ComboManager::Update`, `LootController::Update` và `KitingEngine::ComputeKiteStep` đều có dòng lệnh kiểm tra:
    ```cpp
    if (player.currentHP == 0 || player.maxHP == 0) return false;
    ```
  - Khi mới vào map, nhân vật được hưởng thời gian ân hạn bất tử (**Grace Period** 30 - 60 giây). Máy chủ POE2 chỉ cấp phát và đồng bộ đầy đủ các component động cũng như dữ liệu biến thiên tọa độ khi nhân vật thực hiện hành động đầu tiên.
  - Do `player.maxHP == 0` (chưa quét xong RAM), bot đứng yên không phát lệnh di chuyển. Nhưng vì bot đứng yên không di chuyển, Grace Period không bị hủy và server không gửi dữ liệu tọa độ mới, khiến `AutoPositionScan` và module quét RAM phải dò tìm trong vô vọng suốt 15 - 45 giây.
  - Điều kiện `maxHP == 0` khiến toàn bộ vòng lặp cập nhật bị đoản mạch (short-circuit), trả về `false` ngay ở microsecond đầu tiên của mỗi tick 120Hz, dẫn đến hiện tượng nhân vật hoàn toàn bất động tại cổng map.
- **Giải Pháp Triệt Để: Cơ Chế Proactive Micro-movement Step (Grace Period Breaker)**:
  1. **Chuẩn hóa điều kiện kiểm tra an toàn**:
     Chỉ dừng chu trình khi nhân vật đã tử trận thực sự (`player.maxHP > 0 && player.currentHP == 0`), đồng thời cho phép thực thi khi tọa độ `PlayerFinder::IsValidXYZ(player.posX, player.posY, player.posZ)` hợp lệ:
     ```cpp
     if (player.maxHP > 0 && player.currentHP == 0) return false;
     ```
  2. **Chủ động phát xung bước chân vi mô (Proactive Micro-Step)**:
     - Ngay khi `LogSensor` bắt được sự kiện tải map hoàn tất (`LoadingFinished` hoặc `Entering area`), hệ thống chủ động gửi 1 xung phím ngắn (`Micro-tap W` trong 50ms hoặc click chuột ngắn cách chân 60px).
     - Thao tác này hủy bỏ trạng thái Grace Period một cách hợp lệ, mô phỏng phản xạ tự nhiên của tuyển thủ chuyên nghiệp ngay khi vừa chạm chân vào map.
  3. **Kết hợp Cảm biến Quang học Quả Cầu Máu (Optical Fallback Bypass)**:
     - Tầng 3 Optical Sensor cung cấp ngay `hpRatio = 1.0` (chuẩn hóa `maxHP = 1000, currentHP = 1000`) trong vòng **1 - 2 ms** từ giao diện game, cho phép `ReflexManager` sẵn sàng bơm máu khẩn cấp ngay tức thì.
     - `AutoPositionScan` bắt được biến thiên tọa độ từ bước chân đầu tiên, khóa ngay địa chỉ `m_xyzAddr`.
     - Phá bỏ hoàn toàn trạng thái bế tắc; thời gian nhân vật bắt đầu tuần tra và chiến đấu giảm ngoạn mục từ 45 giây xuống chỉ còn **1.2 - 2.0 giây**.
  - *(Chi tiết đặc tả xem tại [**13. Đặc Tả Kiến Trúc Nhận Diện HP Siêu Tốc & Tối Ưu Hóa Chuyển Vùng Bản Đồ**](file:///c:/Projects/AutoPOE2/docs/development/13_fast_hp_detection_and_zone_transition_optimization.md))*.

### 2.2. Xung đột Tiến trình Chạy ngầm (Process Duplication & SHM Deadlock)
- **Cơ chế cũ**: `core_controller.py` khi khởi động bằng `ShellExecuteExW` với quyền Administrator đã không dọn dẹp các tiến trình `AutoPOE2_Core.exe` mồ côi (orphaned) từ các phiên chạy trước.
- **Hệ quả**: Có 2 instance `AutoPOE2_Core.exe` cùng ánh xạ vào khối nhớ chia sẻ `Local\POE2_Auto_SharedMem_v1`. Hai bên liên tục tranh chấp quyền ghi Seqlock và ghi đè trạng thái buffer của nhau khiến Python GUI nhận dữ liệu chập chờn và các lệnh điều khiển bị triệt tiêu.
- **Giải pháp**:
  - Bổ sung hàm `_kill_orphan_core_processes()` trong `core_controller.py` sử dụng `taskkill /F /IM AutoPOE2_Core.exe` cả trước khi `start()` và khi `stop()`.
  - Giám sát chặt chẽ vòng đời của tiến trình elevated, đảm bảo duy nhất 1 core engine được phép tương tác với IPC.

### 2.3. Lệch Window Class Name & Title
- **Cơ chế cũ**: Mã nguồn tìm kiếm cửa sổ theo tên lớp `POEC2_MainWindow`.
- **Thực tế POE2**: Cửa sổ chính thức của Path of Exile 2 sử dụng Class Name là **`POEWindowClass`** với Window Title là `Path of Exile 2` (hoặc `Path of Exile`).
- **Giải pháp**: Cập nhật hàm `FindPoe2Window()` và `EnsurePoe2WindowFocus()` để tìm kiếm theo danh sách ưu tiên:
  1. Class Name: `POEWindowClass`
  2. Window Title: `Path of Exile 2`
  3. Window Title: `Path of Exile`
  4. Class Name dự phòng: `POEC2_MainWindow`

### 2.4. Rào cản Windows Foreground Focus & Input Routing
- **Vấn đề**: Trên hệ điều hành Windows 10/11, các API chuột và bàn phím (`SetCursorPos`, `mouse_event`, `keybd_event`, KMBox emulation) sẽ bị hệ điều hành bỏ qua hoặc trỏ nhầm vào ứng dụng khác nếu cửa sổ game không ở trạng thái Foreground Window hoạt động.
- **Giải pháp**: Tích hợp cơ chế liên kết luồng `AttachThreadInput` kết hợp `SetForegroundWindow` và `BringWindowToTop` trước mỗi hành động điều khiển:
  ```cpp
  static void EnsurePoe2WindowFocus() {
      HWND hwnd = FindWindowW(L"POEWindowClass", nullptr);
      if (!hwnd) hwnd = FindWindowW(nullptr, L"Path of Exile 2");
      if (!hwnd) hwnd = FindWindowW(nullptr, L"Path of Exile");
      if (hwnd) {
          HWND fg = GetForegroundWindow();
          if (fg != hwnd) {
              DWORD curThread = GetCurrentThreadId();
              DWORD fgThread = GetWindowThreadProcessId(fg, nullptr);
              AttachThreadInput(curThread, fgThread, TRUE);
              SetForegroundWindow(hwnd);
              BringWindowToTop(hwnd);
              AttachThreadInput(curThread, fgThread, FALSE);
          }
      }
  }
  ```

---

## 3. Tương thích Đa nền tảng Tiến trình Game (Steam & Standalone)

Hệ thống bổ sung hàm `FindPoeProcessId(std::wstring* outName)` trong `imemory_reader.hpp`, tự động nhận diện tất cả các biến thể thực thi của POE2:
- `PathOfExile.exe` (Bản Standalone chính thức)
- `PathOfExileSteam.exe` (Bản phân phối qua Steam)
- `PathOfExile_x64.exe` & `PathOfExile_x64Steam.exe` (Các bản build 64-bit đặc thù)
- `PathOfExile2.exe`

Tên tiến trình và PID được lưu giữ trong `GameSession` để module `AobScanner::FindModule` tự động phân giải đúng Module Base Address của game đang chạy mà không phụ thuộc vào tên cố định.

---

## 4. Kết quả Xác minh Kỹ thuật (Verification Results)

1. **C++ Test Suite (`AutoPOE2_Tests.exe`)**:
   - Vượt qua toàn bộ **653 assertions** (100% PASS).
   - Xác nhận cơ chế `IsValidXYZ` hoạt động chính xác, bảo vệ chu trình di chuyển ngay cả khi `maxHP == 0`.
   - Xác nhận cơ chế `TownQuestEngine` phím `U` hoạt động đúng chu trình dịch chuyển.
2. **Python Test Suite (`unittest`)**:
   - Vượt qua toàn bộ **25 tests** (100% PASS).
   - Xác nhận `ReflexTuner`, `AutonomousLifecycle`, `ClientLauncher` và `AgenticCoordinator` vận hành đồng bộ.
3. **Biên dịch Release**:
   - `AutoPOE2.exe` (Single Executable UI Launcher) sẵn sàng.
   - `AutoPOE2_Core.exe` (C++23 Native Core 120Hz) sẵn sàng.
