Fetch the live offsets when your program starts, so you never rebuild after an update.
A plain GET request returns every offset as JSON, grouped by category. No key needed.
This uses WinHTTP, which ships with Windows. Link winhttp.lib.
#include <windows.h>
#include <winhttp.h>
#include <string>
#pragma comment(lib, "winhttp.lib")
std::string HttpGet(const wchar_t* host, const wchar_t* path)
{
std::string body;
HINTERNET session = WinHttpOpen(L"FNOffsets/1.0",
WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, nullptr, nullptr, 0);
HINTERNET conn = session
? WinHttpConnect(session, host, INTERNET_DEFAULT_HTTPS_PORT, 0) : nullptr;
HINTERNET req = conn
? WinHttpOpenRequest(conn, L"GET", path, nullptr, nullptr, nullptr,
WINHTTP_FLAG_SECURE) : nullptr;
if (req && WinHttpSendRequest(req, nullptr, 0, nullptr, 0, 0, 0)
&& WinHttpReceiveResponse(req, nullptr))
{
DWORD avail = 0;
while (WinHttpQueryDataAvailable(req, &avail) && avail)
{
std::string chunk(avail, '\0');
DWORD read = 0;
WinHttpReadData(req, chunk.data(), avail, &read);
body.append(chunk, 0, read);
}
}
if (req) WinHttpCloseHandle(req);
if (conn) WinHttpCloseHandle(conn);
if (session) WinHttpCloseHandle(session);
return body;
}Uses nlohmann/json (single header). Values arrive as hex strings like "0x1B096DE8" and are converted to numbers.
#include <nlohmann/json.hpp>
#include <cstdint>
#include <stdexcept>
using json = nlohmann::json;
namespace Offsets
{
inline json g_data;
inline bool Load()
{
std::string raw = HttpGet(L"fnoffsets.site", L"/api/offsets");
if (raw.empty()) return false;
g_data = json::parse(raw, nullptr, false);
return !g_data.is_discarded();
}
// Get("Core", "TeamIndex") -> 0xF69
inline uintptr_t Get(const char* category, const char* name)
{
const std::string s = g_data.at(category).at(name).get<std::string>();
return static_cast<uintptr_t>(std::stoull(s, nullptr, 16));
}
}Call Load() once at startup, then read any offset by category and name.
int main()
{
if (!Offsets::Load())
return 1; // could not reach the API
uintptr_t base = (uintptr_t)GetModuleHandleW(nullptr);
// Module-relative offsets: add to the base address
uintptr_t gworld = base + Offsets::Get("World", "Gworld");
uintptr_t gnames = base + Offsets::Get("World", "GNames");
// Struct member offsets: add to an object pointer
uintptr_t teamIdx = Offsets::Get("Core", "TeamIndex");
uintptr_t ammo = Offsets::Get("Weapon", "AmmoCount");
uintptr_t fovMin = Offsets::Get("Fov", "FOVMinimum");
}Get() in a try/catch: a missing name throws, which tells you an offset was renamed.Changes go live for every user as soon as you save.