- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 703
- Реакции
- 21
Здарова, реверсеры. Раз уж разработчики большинства P2C софтов уже вовсю торгуют этой фичей, пора выкатить базу в паблик. В этом треде разберем, как реализовать постоянный Advanced UAV на тактической карте без единой записи в память игры. Метод максимально безопасный для External-проектов и DMA-платформ.
1. Инициализация данных из cg_t
Для начала вытаскиваем информацию из структуры cg_t (она же client_info). Нам понадобятся три вектора: compassMapUpperLeft, compassMapWorldSize и compassNorth. Парсим их один раз в начале катки.
Актуальные оффсеты (на момент релиза):
2. Работа со структурой CgCompassSystem
Доступ к системе компаса получаем через указатель ms_compassSystemArray.
Оффсеты массива:
3. Математика: Перевод WorldPos в координаты карты
Теперь самое интересное — ребилдим игровую функцию WorldPosToCompass. Это позволит нам корректно отрисовывать противников даже при зуме или перемещении тактической карты.
4. Отрисовка
Проблема внешних читов в том, что тяжело выцепить LUIElement напрямую. Проще всего захардкодить позицию тактической карты под 1080p и скейлить её под разрешение юзера. Центр карты в BO6 обычно статичен.
Финальный штрих через ImGui:
Метод Read-Only, так что Ricochet за запись в память не прилетит. Основная сложность — следить за обновлением оффсетов ms_compassSystemArray, так как игра часто обновляется. Код выше легко адаптируется под полноценный радар (minimap), если немного пореверсить типы компаса в перечислении CompassType.
Интересно посмотреть, как вы реализуете фильтрацию по высоте, чтобы не захламлять карту в многоуровневых зонах.
1. Инициализация данных из cg_t
Для начала вытаскиваем информацию из структуры cg_t (она же client_info). Нам понадобятся три вектора: compassMapUpperLeft, compassMapWorldSize и compassNorth. Парсим их один раз в начале катки.
- LUI_LuaCall_Game_GetMapSizeData (тут лежат mapWidth, mapHeight, mapLeft, mapTop):
Код:33 D2 41 B8 ? ? ? ? 48 8B CF E8 ? ? ? ? C5 FA 10 8B - CG_CompassFullToWorld (здесь ищем compassNorth):
Код:C5 FA 10 81 ? ? ? ? C5 FA 59 1A C5 FA 10 89 ? ? ? ? C5 F2 59 62
Актуальные оффсеты (на момент релиза):
Код:
Steam:
compassMapUpperLeft = 0x1D7E20;
compassMapWorldSize = 0x1711BC;
compassNorth = 0x48EC0;
Bnet:
compassMapUpperLeft = 0x15B9A4;
compassMapWorldSize = 0x189D40;
compassNorth = 0x175628;
Xbox:
compassMapUpperLeft = 0x1D35B0;
compassMapWorldSize = 0xCD030;
compassNorth = 0x1B6EFC;
2. Работа со структурой CgCompassSystem
Доступ к системе компаса получаем через указатель ms_compassSystemArray.
Код:
struct CgCompassSystem {
uint64_t __vftable = 0;
char pad[0x1];
bool m_compassMirrorLeftRight; // 0x9
bool m_isUsingTabletMode; // 0xA
bool m_PreventZoom; // 0xB
float m_compassPlayerYaw; // 0xC
vec2_t m_compassPlayerForward; // 0x10
CompassType m_currentCompassType; // 0x18
char pad2[0x8];
CompassDisplay m_currentDisplayType; // 0x24
char pad3[0x5AC];
vec2_t m_tacmapMapCenter; // 0x5D4
char pad4[0x4B1C];
float m_currentZoomLevel; // 0x50F8
};
Оффсеты массива:
- Steam: 0xC782B88
- Bnet: 0xCC30870
- Xbox: 0xC728AD8
- Сигнатура: 48 8D 05 ?? ?? ?? ?? 48 8B 0C C8 E8 ?? ?? ?? ?? 33 C0 48 8B 4C 24
3. Математика: Перевод WorldPos в координаты карты
Теперь самое интересное — ребилдим игровую функцию WorldPosToCompass. Это позволит нам корректно отрисовывать противников даже при зуме или перемещении тактической карты.
Код:
bool WorldPosToCompass(const vec3_t& worldPos, vec2_t* out, const rectDef_s* mapRect) {
vec2_t pos = {
worldPos.x - LocalClientGlobals->compassMapUpperLeft.x,
worldPos.y - LocalClientGlobals->compassMapUpperLeft.y
};
float zoom = 1.f / this->m_currentZoomLevel;
vec2_t compassWorldPos = {
(((pos.x * north.y - pos.y * north.x) / worldSize.x) - m_tacmapMapCenter.x) * zoom * mapRect->w,
((-(pos.x * north.x + pos.y * north.x) / worldSize.y) - m_tacmapMapCenter.y) * zoom * mapRect->h
};
*out = { (0.5f * mapRect->w) + mapRect->x + compassWorldPos.x, (0.5f * mapRect->h) + mapRect->y + compassWorldPos.y };
return true;
}
4. Отрисовка
Проблема внешних читов в том, что тяжело выцепить LUIElement напрямую. Проще всего захардкодить позицию тактической карты под 1080p и скейлить её под разрешение юзера. Центр карты в BO6 обычно статичен.
Финальный штрих через ImGui:
Код:
vec2_t compassPos;
if (WorldPosToCompass(entity->origin, &compassPos, &mapRect)) {
ImGui::GetBackgroundDrawList()->AddCircleFilled(ImVec2(compassPos.x, compassPos.y), 7.f, ImColor(255, 255, 255, 255), 10);
}
Метод Read-Only, так что Ricochet за запись в память не прилетит. Основная сложность — следить за обновлением оффсетов ms_compassSystemArray, так как игра часто обновляется. Код выше легко адаптируется под полноценный радар (minimap), если немного пореверсить типы компаса в перечислении CompassType.
Интересно посмотреть, как вы реализуете фильтрацию по высоте, чтобы не захламлять карту в многоуровневых зонах.