Гайд Продолжение серии. шема(оффсеты)+локал игрок

Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
дамп обновил(в теме ссылку на дамп тоже обновил)
Feb 22 2023 дамп(версия игры от Feb 21 2023)
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Can you provide the dump for this update? thanks.
No, sorry, not anytime soon - I'm using a metered connection right now and the update is too huge to download :)
Consider making your own dumper though - it's fairly trivial. For me the most difficult part was nicely formatting and indenting the data as text.
Read the original post, read all the other posts in the thread, and if you still don't know/understand something - just ask here specifically what part you don't understand. I/others will gladly share insights/hints/chunks of code etc.
If you just need offsets for specific fields - extract them from CSchemaSystem at runtime.
This dumper consists of several parts:
convars/concommands - moslty stuff from https://yougame.biz/threads/267157/
gamesystems - almost the same as source1 engine, except IIRC source1 had a table of gamesystems, source2 uses a linked list
C++:
    //xref "IGameSystem::InitAllSystems"
    //target function is IGameSystem::InitAllSystems(IGameSystem *__hidden this)
    class FirstGameSystemPtr_Client : PatternParent<FirstGameSystemPtr_Client,
        "client.dll",
        "FirstGameSystemPtr",
        "40 53 55 56 57 41 55 48 81 ec ?? ?? ?? ?? 48 8b 1d"
    >
...
            constexpr auto GAMESYSTEMS_insn_mov_offset = 0xE;
            //xref in IGameSystem::InitAllSystems, a mov+test right at the start
            //target function is IGameSystem::InitAllSystems(IGameSystem *__hidden this)
            //target variable is CBaseGameSystemFactory::sm_pFirst
you get the first gamesystemfactory from pattern(pattern points at the beginning of a function and there's a mov referencing sm_pFirst followed by a test) and keep factory->next until it's nullptr
factories are either static or reallocating
C++:
class IGameSystemFactory : public VClass
{
public:
    IGameSystemFactory* Next{};
    const char* FactoryName{};
private:
    struct ReallocatingFactoryData
    {
        IGameSystem* System_Ptr;
        //...
    };
    union SystemData
    {
        IGameSystem* Static_Ptr;
        ReallocatingFactoryData* Reallocating_Ptr;
    };
    SystemData Ptr{};

    bool IsReallocating() const
    {
        return CallVFunc<8, bool>();
    }

public:
    IGameSystem* GetSystem() const
    {
        if (IsReallocating())
        {
            if (const auto* realloc_data_ptr = Ptr.Reallocating_Ptr; realloc_data_ptr)
                return realloc_data_ptr->System_Ptr;
            else
                return nullptr;
        }
        return Ptr.Static_Ptr;
    }
};
interfaces - you iterate every module in dota2.exe, check for export "CreateInterface", get the export address,
check if first 3 bytes are 0x4c 0x8b 0x0d(it's a mov instruction)
if so, you extract the address from the instruction and you get the first InterfaceReg - it's a linked list so you keep reg-> m_pNext until it's nullptr
network field change callbacks - CNetworkMessages has a CUtlStringMap of callbacks at 0x4c0
schema - stuff from this thread(large part of it is https://yougame.biz/threads/139802/page-4#post-2582741), also you can consult
Пожалуйста, авторизуйтесь для просмотра ссылки.
(from https://yougame.biz/threads/263327/)
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
663
Реакции[?]
104
Поинты[?]
67K
А где взять обновлённый енам ClassID для клиенткласса чтобы строчки не сравнивать?
В шеме не нашел его чот
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
🤡
Пользователь
Статус
Оффлайн
Регистрация
28 Апр 2014
Сообщения
127
Реакции[?]
163
Поинты[?]
21K
У ентити вроде на 33 индексе есть GetClientClass, берешь и сканишь весь ентити листи и делаешь себе дамп классидов.
Как делали это все время до доты, в ксс, в ксго. Чекаешь на повторы и т.п. И собираешь себе классид лист. Можешь при дампе сразу енам формировать.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
А где взять обновлённый енам ClassID для клиенткласса чтобы строчки не сравнивать?
В шеме не нашел его чот
в айдентити вторым членом(сразу после ентити) лежит ClassTemplate*(моё название) в ней на 0x108 ClassMetaDef*(моё название) там на 0x28 класс айди
в CNetworkGameClient есть список ServerClassNode'ов в которых лежат конст чар* и ClassMetaDef*
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
324
Реакции[?]
24
Поинты[?]
12K
Немножко обновилось

C++:
class CSchemaType
{
public:
    void* N00000506; //0x0000
    char* DataType; //0x0008
}; //Size: 0x0010

class MemberDesc
{
public:
    const char* name; //0x0000
    CSchemaType* SchemaType; //0x0008
    uint32_t Offset; //0x0010
    uint32_t N0000052C; //0x0014
    void* N000004D6; //0x0018
}; //Size: 0x0080

class ClassDesc
{
public:
    void* unk; //0x0000
    const char* name; //0x0008
    const char* module; //0x0010
    int32_t N00000357; //0x0018
    uint16_t Size; //0x001C
    uint16_t unko;
    int32_t N00000358; //0x0020
    int32_t N00000513; //0x0024
    void* MembersDesc; //0x0028

    void IterateMembers()
    {
         ... // кому надо тот сам напишет, размер MemberDesc 0x20
    }

    int GetOffset(const char* Name)
    {
         ...  // кому надо тот сам напишет, размер MemberDesc 0x20
    }
}; //Size: 0x04D8

class CSchemaSystemTypeScope
{
public:
    virtual void func0() = 0;

    virtual void func1() = 0;

    virtual void* func2(uintptr_t* returnPtr,const char* ClassName) = 0; // если поставить в returnPtr nullptr(void* nullptr) то будет краш

    ClassDesc* FindDeclaredClass(const char* ClassName)
    {
        uintptr_t value;

        auto returntype = func2(&value, ClassName);
        
        return (ClassDesc*)value;
    }
};

class SchemaSystem
{
public:
    virtual void func0() = 0;
    virtual void func1() = 0;
    virtual void func2() = 0;
    virtual void func3() = 0;
    virtual void func4() = 0;
    virtual void func5() = 0;
    virtual void func6() = 0;
    virtual void func7() = 0;
    virtual void func8() = 0;
    virtual void func9() = 0;
    virtual void func10() = 0;
    virtual void* GetGlobalScope() = 0;
    virtual CSchemaSystemTypeScope* FindOrCreateTypeScopeForModule(const char*, void*) = 0;
    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(const char*,void* = nullptr) = 0; //
};
 
🤡
Пользователь
Статус
Оффлайн
Регистрация
28 Апр 2014
Сообщения
127
Реакции[?]
163
Поинты[?]
21K
Немножко обновилось

C++:
class CSchemaType
{
public:
    void* N00000506; //0x0000
    char* DataType; //0x0008
}; //Size: 0x0010

class MemberDesc
{
public:
    const char* name; //0x0000
    CSchemaType* SchemaType; //0x0008
    uint32_t Offset; //0x0010
    uint32_t N0000052C; //0x0014
    void* N000004D6; //0x0018
}; //Size: 0x0080

class ClassDesc
{
public:
    void* unk; //0x0000
    const char* name; //0x0008
    const char* module; //0x0010
    int32_t N00000357; //0x0018
    uint16_t Size; //0x001C
    uint16_t unko;
    int32_t N00000358; //0x0020
    int32_t N00000513; //0x0024
    void* MembersDesc; //0x0028

    void IterateMembers()
    {
         ... // кому надо тот сам напишет, размер MemberDesc 0x20
    }

    int GetOffset(const char* Name)
    {
         ...  // кому надо тот сам напишет, размер MemberDesc 0x20
    }
}; //Size: 0x04D8

class CSchemaSystemTypeScope
{
public:
    virtual void func0() = 0;

    virtual void func1() = 0;

    virtual void* func2(uintptr_t* returnPtr,const char* ClassName) = 0; // если поставить в returnPtr nullptr(void* nullptr) то будет краш

    ClassDesc* FindDeclaredClass(const char* ClassName)
    {
        uintptr_t value;

        auto returntype = func2(&value, ClassName);
      
        return (ClassDesc*)value;
    }
};

class SchemaSystem
{
public:
    virtual void func0() = 0;
    virtual void func1() = 0;
    virtual void func2() = 0;
    virtual void func3() = 0;
    virtual void func4() = 0;
    virtual void func5() = 0;
    virtual void func6() = 0;
    virtual void func7() = 0;
    virtual void func8() = 0;
    virtual void func9() = 0;
    virtual void func10() = 0;
    virtual void* GetGlobalScope() = 0;
    virtual CSchemaSystemTypeScope* FindOrCreateTypeScopeForModule(const char*, void*) = 0;
    virtual CSchemaSystemTypeScope* FindTypeScopeForModule(const char*,void* = nullptr) = 0; //
};
Поглядывай сюда (
Пожалуйста, авторизуйтесь для просмотра ссылки.
), стараюсь следить за схемой и обновлять по возможности.
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
13 Июн 2017
Сообщения
71
Реакции[?]
5
Поинты[?]
0
Чет я не пойму, как использовать оффсеты из дампа. Самое интересное, что со своими указателями у меня все прекрасно. Вот к примеру я открыл вот
Пожалуйста, авторизуйтесь для просмотра ссылки.
, нашел там int32_t m_iHealth; // 0x334. То есть нужное мне значение лежит в "client.dll" + 0x334? Если так, то почему у меня не сходится? Допустим у персонажа 626 хп, но найденное значение будет равно 74372608.

Вот если что то как я это делаю.

C++:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

int main() {
    const wchar_t* process_name = L"dota2.exe";
    const wchar_t* module_name = L"client.dll";

    DWORD pid = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32W process_entry;
        process_entry.dwSize = sizeof(process_entry);

        if (Process32FirstW(snapshot, &process_entry)) {
            do {
                if (wcscmp(process_entry.szExeFile, process_name) == 0) {
                    pid = process_entry.th32ProcessID;
                    break;
                }
            } while (Process32NextW(snapshot, &process_entry));
        }

        CloseHandle(snapshot);
    }

    if (pid != 0) {
        HANDLE module_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
        if (module_snapshot != INVALID_HANDLE_VALUE) {
            MODULEENTRY32W module_entry;
            module_entry.dwSize = sizeof(module_entry);

            if (Module32FirstW(module_snapshot, &module_entry)) {
                do {
                    if (wcscmp(module_entry.szModule, module_name) == 0) {
                        DWORD_PTR base_address = (DWORD_PTR)module_entry.modBaseAddr;

                        DWORD_PTR address_to_read = base_address + 0x334;
                        DWORD value;
                        if (ReadProcessMemory(OpenProcess(PROCESS_VM_READ, FALSE, pid), (LPCVOID)address_to_read, &value, sizeof(value), nullptr)) {
                            std::cout << "Value at address " << std::hex << address_to_read << " is: " << std::dec << value << std::endl;
                        }
                        else {
                            std::cerr << "Error: ReadProcessMemory failed." << std::endl;
                        }

                        break;
                    }
                } while (Module32NextW(module_snapshot, &module_entry));
            }

            CloseHandle(module_snapshot);
        }
        else {
            std::cerr << "Error: CreateToolhelp32Snapshot failed for modules." << std::endl;
        }
    }
    else {
        std::cerr << "Error: Process " << process_name << " not found." << std::endl;
    }

    return 0;
}
Вывод: Value at address 7fffcfe70334 is: 74372608

К примеру в чит энжине "client.dll"+0x334 то же самое показывает.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Чет я не пойму, как использовать оффсеты из дампа. Самое интересное, что со своими указателями у меня все прекрасно. Вот к примеру я открыл вот
Пожалуйста, авторизуйтесь для просмотра ссылки.
, нашел там int32_t m_iHealth; // 0x334. То есть нужное мне значение лежит в "client.dll" + 0x334? Если так, то почему у меня не сходится? Допустим у персонажа 626 хп, но найденное значение будет равно 74372608.


C++:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

int main() {
    const wchar_t* process_name = L"dota2.exe";
    const wchar_t* module_name = L"client.dll";

    DWORD pid = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32W process_entry;
        process_entry.dwSize = sizeof(process_entry);

        if (Process32FirstW(snapshot, &process_entry)) {
            do {
                if (wcscmp(process_entry.szExeFile, process_name) == 0) {
                    pid = process_entry.th32ProcessID;
                    break;
                }
            } while (Process32NextW(snapshot, &process_entry));
        }

        CloseHandle(snapshot);
    }

    if (pid != 0) {
        HANDLE module_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
        if (module_snapshot != INVALID_HANDLE_VALUE) {
            MODULEENTRY32W module_entry;
            module_entry.dwSize = sizeof(module_entry);

            if (Module32FirstW(module_snapshot, &module_entry)) {
                do {
                    if (wcscmp(module_entry.szModule, module_name) == 0) {
                        DWORD_PTR base_address = (DWORD_PTR)module_entry.modBaseAddr;

                        DWORD_PTR address_to_read = base_address + 0x334;
                        DWORD value;
                        if (ReadProcessMemory(OpenProcess(PROCESS_VM_READ, FALSE, pid), (LPCVOID)address_to_read, &value, sizeof(value), nullptr)) {
                            std::cout << "Value at address " << std::hex << address_to_read << " is: " << std::dec << value << std::endl;
                        }
                        else {
                            std::cerr << "Error: ReadProcessMemory failed." << std::endl;
                        }

                        break;
                    }
                } while (Module32NextW(module_snapshot, &module_entry));
            }

            CloseHandle(module_snapshot);
        }
        else {
            std::cerr << "Error: CreateToolhelp32Snapshot failed for modules." << std::endl;
        }
    }
    else {
        std::cerr << "Error: Process " << process_name << " not found." << std::endl;
    }

    return 0;
}
ты путаешь оффсет от начала структуры и RVA(Relative Virtual Address)
оффсет(из дампа) ты прибавляешь к адресу где лежит структура указанного типа(в случае m_iHealth это структура типа C_BaseEntity(или любые ее дети(которые наследуют без множественного наследования. ну это 99% детей)))
к дллкам ты прибавляешь RVA'шки а не оффсеты
ты сначала своего героя находишь а потом уже к нему 0x334 прибавляешь
m_iHealth есть у всех сущностей, и у всех на 0x334 от адреса сущности.
Чет я не пойму, как использовать оффсеты из дампа. Самое интересное, что со своими указателями у меня все прекрасно. Вот к примеру я открыл вот
Пожалуйста, авторизуйтесь для просмотра ссылки.
, нашел там int32_t m_iHealth; // 0x334. То есть нужное мне значение лежит в "client.dll" + 0x334? Если так, то почему у меня не сходится? Допустим у персонажа 626 хп, но найденное значение будет равно 74372608.

Вот если что то как я это делаю.

C++:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

int main() {
    const wchar_t* process_name = L"dota2.exe";
    const wchar_t* module_name = L"client.dll";

    DWORD pid = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32W process_entry;
        process_entry.dwSize = sizeof(process_entry);

        if (Process32FirstW(snapshot, &process_entry)) {
            do {
                if (wcscmp(process_entry.szExeFile, process_name) == 0) {
                    pid = process_entry.th32ProcessID;
                    break;
                }
            } while (Process32NextW(snapshot, &process_entry));
        }

        CloseHandle(snapshot);
    }

    if (pid != 0) {
        HANDLE module_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
        if (module_snapshot != INVALID_HANDLE_VALUE) {
            MODULEENTRY32W module_entry;
            module_entry.dwSize = sizeof(module_entry);

            if (Module32FirstW(module_snapshot, &module_entry)) {
                do {
                    if (wcscmp(module_entry.szModule, module_name) == 0) {
                        DWORD_PTR base_address = (DWORD_PTR)module_entry.modBaseAddr;

                        DWORD_PTR address_to_read = base_address + 0x334;
                        DWORD value;
                        if (ReadProcessMemory(OpenProcess(PROCESS_VM_READ, FALSE, pid), (LPCVOID)address_to_read, &value, sizeof(value), nullptr)) {
                            std::cout << "Value at address " << std::hex << address_to_read << " is: " << std::dec << value << std::endl;
                        }
                        else {
                            std::cerr << "Error: ReadProcessMemory failed." << std::endl;
                        }

                        break;
                    }
                } while (Module32NextW(module_snapshot, &module_entry));
            }

            CloseHandle(module_snapshot);
        }
        else {
            std::cerr << "Error: CreateToolhelp32Snapshot failed for modules." << std::endl;
        }
    }
    else {
        std::cerr << "Error: Process " << process_name << " not found." << std::endl;
    }

    return 0;
}
Вывод: Value at address 7fffcfe70334 is: 74372608

К примеру в чит энжине "client.dll"+0x334 то же самое показывает.
чекни темы в соседнем разделе там есть куски кода демонстративного характера, возможно они что-то прояснят
типа
 
Начинающий
Статус
Оффлайн
Регистрация
13 Июн 2017
Сообщения
71
Реакции[?]
5
Поинты[?]
0
ты путаешь оффсет от начала структуры и RVA(Relative Virtual Address)
оффсет(из дампа) ты прибавляешь к адресу где лежит структура указанного типа(в случае m_iHealth это структура типа C_BaseEntity(или любые ее дети(которые наследуют без множественного наследования. ну это 99% детей)))
к дллкам ты прибавляешь RVA'шки а не оффсеты
ты сначала своего героя находишь а потом уже к нему 0x334 прибавляешь
m_iHealth есть у всех сущностей, и у всех на 0x334 от адреса сущности.

чекни темы в соседнем разделе там есть куски кода демонстративного характера, возможно они что-то прояснят
типа
Короче мне надо сначала найти своего героя (пусть будет называться localplayer). Как я понимаю это можно сделать от его хп. Далее base = client.dll+localplayer, потом base + 0x334 и я получу хп своего персонажа, верно? И еще вопрос, лежит ли адрес localplayer в дампе, чтобы мне его не искать?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Короче мне надо сначала найти своего героя (пусть будет называться localplayer). Как я понимаю это можно сделать от его хп. Далее base = client.dll+localplayer, потом base + 0x334 и я получу хп своего персонажа, верно? И еще вопрос, лежит ли адрес localplayer в дампе, чтобы мне его не искать?
не совсем; в доте игрок и герой это разные вещи. игрок это тот кто контроллит юнитов(их может быть несколько - те же призванные/прирученные крипы и прочая хуйня. это все ИГРОК их контроллит. у игрока(C_DOTAPlayerController) есть айди сущности подконтрольного героя(m_hAssignedHero нетвар))
сущность по айди можно получить через энтитисистему. там 64 списка по 512 айдентитей(айдентити это вспомогательная структура там есть имя сущности ее айди и так далее, а еще там есть указатель на саму сущность(а в сущности указатель на айдентити)). индекс это индексСписка * 64 + индексВСписке. раскладывается соответственно индексВСписке = индекс mod 512(остаток от деления на 512), индексСписка = индекс div 512(целочисленное деление(выбрасывая дробную часть))
ну а когда получишь героя то можешь прибавить 0x334 и считать оттуда int и будет тебе твое хп.
нет локалплеера нет в дампе ты можешь получить через движок(даст айди игрока. к нему надо +1 прибавить получишь айди сущности) и энтитисистему(я тебе там две ссылки в прошлом ответе кинул чекни их)
ну и еще забыл сказать m_hAssignedHero это не совсем айди, это CHandle. это 17 битов серийник и 15 битов айди. достаешь 15 нижних битов(умножаешь побитово на 0x7FFF, что есть 2 в 15 степени; id = m_hAssignedHero & 0x7FFF)
 
Начинающий
Статус
Оффлайн
Регистрация
13 Июн 2017
Сообщения
71
Реакции[?]
5
Поинты[?]
0
не совсем; в доте игрок и герой это разные вещи. игрок это тот кто контроллит юнитов(их может быть несколько - те же призванные/прирученные крипы и прочая хуйня. это все ИГРОК их контроллит. у игрока(C_DOTAPlayerController) есть айди сущности подконтрольного героя(m_hAssignedHero нетвар))
сущность по айди можно получить через энтитисистему. там 64 списка по 512 айдентитей(айдентити это вспомогательная структура там есть имя сущности ее айди и так далее, а еще там есть указатель на саму сущность(а в сущности указатель на айдентити)). индекс это индексСписка * 64 + индексВСписке. раскладывается соответственно индексВСписке = индекс mod 512(остаток от деления на 512), индексСписка = индекс div 512(целочисленное деление(выбрасывая дробную часть))
ну а когда получишь героя то можешь прибавить 0x334 и считать оттуда int и будет тебе твое хп.
нет локалплеера нет в дампе ты можешь получить через движок(даст айди игрока. к нему надо +1 прибавить получишь айди сущности) и энтитисистему(я тебе там две ссылки в прошлом ответе кинул чекни их)
ну и еще забыл сказать m_hAssignedHero это не совсем айди, это CHandle. это 17 битов серийник и 15 битов айди. достаешь 15 нижних битов(умножаешь побитово на 0x7FFF, что есть 2 в 15 степени; id = m_hAssignedHero & 0x7FFF)
как много информации :NotLikeThis:

ладно, спасибо, буду продолжать разбираться..
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Начинающий
Статус
Оффлайн
Регистрация
13 Июн 2017
Сообщения
71
Реакции[?]
5
Поинты[?]
0
ну ссылки чекни почитай там код. если че спрашивай отвечу
Окей, я разобрался как найти указатель до нужного мне значения через Pointer Scanner в CE. Разобрался, как найти EntityList. Разобрался, как взаимодействовать с значениями, оффсетами и т.д. Даже получилось написать автоармлет, который вполне себе работает.

Теперь очередной вопрос. Допустим у меня есть EntityList ("client.dll"+0485B960+0). Я хочу получить хп и название каждого персонажа на карте, так же хочу разделить их на тиммейтов и врагов. Ну и конечно же определить, какой персонаж принадлежит игроку (сейчас я узнаю это с помощью конкретного указателя, полученного от Pointer Scanner). Как мне это сделать, если допустим персонажу Lycan принадлежит каждый раз разный указатель? Допустим в первый раз это ("client.dll"+0485B960+0)+388, во второй раз это ("client.dll"+0485B960+0)+338.

Возможно я что-то упустил выше, но все же.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Окей, я разобрался как найти указатель до нужного мне значения через Pointer Scanner в CE. Разобрался, как найти EntityList. Разобрался, как взаимодействовать с значениями, оффсетами и т.д. Даже получилось написать автоармлет, который вполне себе работает.

Теперь очередной вопрос. Допустим у меня есть EntityList ("client.dll"+0485B960+0). Я хочу получить хп и название каждого персонажа на карте, так же хочу разделить их на тиммейтов и врагов. Ну и конечно же определить, какой персонаж принадлежит игроку (сейчас я узнаю это с помощью конкретного указателя, полученного от Pointer Scanner). Как мне это сделать, если допустим персонажу Lycan принадлежит каждый раз разный указатель? Допустим в первый раз это ("client.dll"+0485B960+0)+388, во второй раз это ("client.dll"+0485B960+0)+338.

Возможно я что-то упустил выше, но все же.
1) хп - C_BaseEntity::m_iHealth
2) имя персонажа - можно из айдентити брать(CEntityInstance::m_pEntity, CEntityIdentity::m_name), можно C_DOTA_BaseNPC::m_iszUnitName
3) это не ентитилист, это список объектов типа C_NextBotCombatCharacter(или ниже по иерархии, например C_DOTA_BaseNPC и тд - они все являются валидными инстанциями C_NextBotCombatCharacter)
4) у локал плеера(или локал героя) есть DOTATeam_t C_BaseEntity::m_iTeamNum. если у кого-либо тима равна той что у локал игрока/героя = это союзник. нет = враг
5) у контроллера есть хендл героя C_DOTAPlayerController::m_hAssignedHero, а у героя C_BaseEntity::m_hOwnerEntity будет равен хендлу контроллера
6) локальный герой либо через CEngineClient/CNetworkGameClient, либо у контроллера есть CBasePlayerController::m_bIsLocalPlayerController
7) список контроллеров есть либо в C_DOTA_PlayerResource(плеер айдишники), либо в энтитисистеме сам отфильтруешь(как хочешь - по ртти по имени по метахуйне всякой), либо в метахуйне(то что ты назвал "энтитилистом" это список объектов C_NextBotCombatCharacter, существует также список объектов и C_DOTAPlayerController)
тебе прежде всего локальный контроллер(игрок) нужен
 
Начинающий
Статус
Оффлайн
Регистрация
13 Июн 2017
Сообщения
71
Реакции[?]
5
Поинты[?]
0
1) хп - C_BaseEntity::m_iHealth
2) имя персонажа - можно из айдентити брать(CEntityInstance::m_pEntity, CEntityIdentity::m_name), можно C_DOTA_BaseNPC::m_iszUnitName
3) это не ентитилист, это список объектов типа C_NextBotCombatCharacter(или ниже по иерархии, например C_DOTA_BaseNPC и тд - они все являются валидными инстанциями C_NextBotCombatCharacter)
4) у локал плеера(или локал героя) есть DOTATeam_t C_BaseEntity::m_iTeamNum. если у кого-либо тима равна той что у локал игрока/героя = это союзник. нет = враг
5) у контроллера есть хендл героя C_DOTAPlayerController::m_hAssignedHero, а у героя C_BaseEntity::m_hOwnerEntity будет равен хендлу контроллера
6) локальный герой либо через CEngineClient/CNetworkGameClient, либо у контроллера есть CBasePlayerController::m_bIsLocalPlayerController
7) список контроллеров есть либо в C_DOTA_PlayerResource(плеер айдишники), либо в энтитисистеме сам отфильтруешь(как хочешь - по ртти по имени по метахуйне всякой), либо в метахуйне(то что ты назвал "энтитилистом" это список объектов C_NextBotCombatCharacter, существует также список объектов и C_DOTAPlayerController)
тебе прежде всего локальный контроллер(игрок) нужен
пошла возня, спасибо
 
Сверху Снизу