• Ищем качественного (не новичок) разработчиков Xenforo для этого форума! В идеале, чтобы ты был фулл стек программистом. Если у тебя есть что показать, то свяжись с нами по контактным данным: https://t.me/DREDD

Вопрос Проверка класса сущности

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
364
Реакции
24
Как эффективно проверять приналежность объекта к своему классу?
Ну вот я делаю итерацию например стандартным методом :
C++:
Expand Collapse Copy
for(const C_BaseEntity* ent = EntitySystem->GetBaseEntity(i++); i <GetHighestEntityIndex(); ent = EntitySystem->GetBaseEntity(i))
{
...
}
Я лично делаю через проверку и сравнение строки entity->instance->0x8->0x0->0x0 с 'C_DOTA_BaseNPC_Hero'

Есть ли другие варианты ещё? Заметил что вроде как есть поле C_DOTA_BaseNPC::m_iUnitType.
 
вот это то что ты написал entity->instance->0x8->0x0->0x0
это (мои названия. хз как по факту называется) у айдентити лежит на 0x8 ClassTemplate*, там есть всякое говно включая шема биндинг класса, можешь там покопаться. там инфа вроде есть о бейз классе
C++:
Expand Collapse Copy
class ClassInfo
{
    const char* name_1{};
    const char* name_2{};
    const char* name_3{};
    ClassTemplate* cls_template{};
    ClassInfo* base_class{};
    CSchemaClassBinding* binding{};
};

class ClassTemplate//na (identity + 8) lezhit ukazatel na eto
{
    void* some_base_shit_unk{};
    void* unk_1{};
    void* unk_2{};
    void* unk_3{};
    void* unk_4{};
    ClassInfo* class_info{};//tut binding est'
    //at 0x108 is ClassMetaDef* metadef;
};

class ClassMetaDef
{
    const char* server_name{};
    const char* client_name{};
    ClassTemplate* class_template{};
    const char* scoped_name{};
    void* unk{};
    std::uint32_t id{};
public:
    std::string_view GetClientName() const noexcept
    {
        if (!client_name)
            return {};
        return client_name;
    }
    const auto& GetClassTemplate() const
    {
        if (!class_template)
            throw std::runtime_error{std::format(R"(ClassMetaDef::class_template is nullptr for "{}"!)", GetClientName())};
        return *class_template;
    }
};
можешь по именам в шема биндингах сравнивать
C++:
Expand Collapse Copy
bool helper_check_hierarchy_for_name(const CSchemaClassBinding& binding, std::string_view name) noexcept
{
    for (const auto& parent_node : binding.GetParents())
    {
        if (const auto* parent = parent_node.GetParent(); parent)
        {
            if (parent->GetName() == name || helper_check_hierarchy_for_name(*parent, name))
                return true;
        }
    }
    return false;
}
... entity vvv ...
    bool IsInstanceOfClass(std::string_view cls) const
    {
        const auto& binding = GetBinding();
        if (binding.GetName() == cls)
            return true;
        else
            return helper_check_hierarchy_for_name(binding, cls);
        return false;
    }
а по факту если хочешь можешь заранее часто встречающиеся биндинги из шемы брать определенных классов(крип хуип и так далее) и сразу напрямую сравнивать указатели в классинфо.
либо можешь тем же самым путём пойти и темплейты а не биндинги сравнивать. метадефы лежат в таблице в CNetworkGameClient, в метадефе есть указатель на темплейту
 
  • Мне нравится
Реакции: og
вот это то что ты написал entity->instance->0x8->0x0->0x0
это (мои названия. хз как по факту называется) у айдентити лежит на 0x8 ClassTemplate*, там есть всякое говно включая шема биндинг класса, можешь там покопаться. там инфа вроде есть о бейз классе
C++:
Expand Collapse Copy
class ClassInfo
{
    const char* name_1{};
    const char* name_2{};
    const char* name_3{};
    ClassTemplate* cls_template{};
    ClassInfo* base_class{};
    CSchemaClassBinding* binding{};
};

class ClassTemplate//na (identity + 8) lezhit ukazatel na eto
{
    void* some_base_shit_unk{};
    void* unk_1{};
    void* unk_2{};
    void* unk_3{};
    void* unk_4{};
    ClassInfo* class_info{};//tut binding est'
    //at 0x108 is ClassMetaDef* metadef;
};

class ClassMetaDef
{
    const char* server_name{};
    const char* client_name{};
    ClassTemplate* class_template{};
    const char* scoped_name{};
    void* unk{};
    std::uint32_t id{};
public:
    std::string_view GetClientName() const noexcept
    {
        if (!client_name)
            return {};
        return client_name;
    }
    const auto& GetClassTemplate() const
    {
        if (!class_template)
            throw std::runtime_error{std::format(R"(ClassMetaDef::class_template is nullptr for "{}"!)", GetClientName())};
        return *class_template;
    }
};
можешь по именам в шема биндингах сравнивать
C++:
Expand Collapse Copy
bool helper_check_hierarchy_for_name(const CSchemaClassBinding& binding, std::string_view name) noexcept
{
    for (const auto& parent_node : binding.GetParents())
    {
        if (const auto* parent = parent_node.GetParent(); parent)
        {
            if (parent->GetName() == name || helper_check_hierarchy_for_name(*parent, name))
                return true;
        }
    }
    return false;
}
... entity vvv ...
    bool IsInstanceOfClass(std::string_view cls) const
    {
        const auto& binding = GetBinding();
        if (binding.GetName() == cls)
            return true;
        else
            return helper_check_hierarchy_for_name(binding, cls);
        return false;
    }
а по факту если хочешь можешь заранее часто встречающиеся биндинги из шемы брать определенных классов(крип хуип и так далее) и сразу напрямую сравнивать указатели в классинфо.
либо можешь тем же самым путём пойти и темплейты а не биндинги сравнивать. метадефы лежат в таблице в CNetworkGameClient, в метадефе есть указатель на темплейту
Там мне бы хотелось чтото легкое, просто чтобы узнать является ли данная сущность героем или крипом. Я смотрел в джаваскриптовые, и там какая-то непонятная херня вызывается.

Ну да, я по твоему старому гайду делал так собственно.
C++:
Expand Collapse Copy
bool C_BaseEntity::IsHero()
{
    return !strcmp(this->instance->ClassData->Data->BaseClass, "C_DOTA_BaseNPC_Hero");
}
По твоему это лучший способ проверки?
 
вот это то что ты написал entity->instance->0x8->0x0->0x0
это (мои названия. хз как по факту называется) у айдентити лежит на 0x8 ClassTemplate*, там есть всякое говно включая шема биндинг класса, можешь там покопаться. там инфа вроде есть о бейз классе
Код:
Expand Collapse Copy
class ClassInfo
{
    const char* name_1{};
    const char* name_2{};
    const char* name_3{};
    ClassTemplate* cls_template{};
    ClassInfo* base_class{};
    CSchemaClassBinding* binding{};
};

class ClassTemplate//na (identity + 8) lezhit ukazatel na eto
{
    void* some_base_shit_unk{};
    void* unk_1{};
    void* unk_2{};
    void* unk_3{};
    void* unk_4{};
    ClassInfo* class_info{};//tut binding est'
    //at 0x108 is ClassMetaDef* metadef;
};

class ClassMetaDef
{
    const char* server_name{};
    const char* client_name{};
    ClassTemplate* class_template{};
    const char* scoped_name{};
    void* unk{};
    std::uint32_t id{};
public:
    std::string_view GetClientName() const noexcept
    {
        if (!client_name)
            return {};
        return client_name;
    }
    const auto& GetClassTemplate() const
    {
        if (!class_template)
            throw std::runtime_error{std::format(R"(ClassMetaDef::class_template is nullptr for "{}"!)", GetClientName())};
        return *class_template;
    }
};
можешь по именам в шема биндингах сравнивать
C++:
Expand Collapse Copy
bool helper_check_hierarchy_for_name(const CSchemaClassBinding& binding, std::string_view name) noexcept
{
    for (const auto& parent_node : binding.GetParents())
    {
        if (const auto* parent = parent_node.GetParent(); parent)
        {
            if (parent->GetName() == name || helper_check_hierarchy_for_name(*parent, name))
                return true;
        }
    }
    return false;
}
... entity vvv ...
    bool IsInstanceOfClass(std::string_view cls) const
    {
        const auto& binding = GetBinding();
        if (binding.GetName() == cls)
            return true;
        else
            return helper_check_hierarchy_for_name(binding, cls);
        return false;
    }
а по факту если хочешь можешь заранее часто встречающиеся биндинги из шемы брать определенных классов(крип хуип и так далее) и сразу напрямую сравнивать указатели в классинфо.
либо можешь тем же самым путём пойти и темплейты а не биндинги сравнивать. метадефы лежат в таблице в CNetworkGameClient, в метадефе есть указатель на темплейту
0x8 - CEntityClass

C++:
Expand Collapse Copy
class CEntityClassInfo
{
public:
    const char          *m_pszClassname;        // 0x0000
    const char          *m_pszCPPClassname;     // 0x0008
    const char          *m_pszDescription;      // 0x0010
    CEntityClass        *m_pClass;              // 0x0014
    CEntityClassInfo    *m_pBaseClassInfo;      // 0x0018
    CSchemaClassBinding *m_pSchemaClassBinding; // 0x0028
    PAD(16)                                     // 0x0030
};                                              // Size: 0x0040
static_assert(sizeof(CEntityClassInfo) == 0x40);

class CEntityClass
{

    CPanoramaGameScriptScope* m_pPanoramaGameScriptScope;
    // Тут пады сами соберете.
    CEntityClassInfo   *m_pClassInfo;                                    // 0x0028
    CEntityClassInfo   *m_pBaseClassInfo;                                // 0x0030
};

В общем, структура очень полезная и там если расковырять фулл структуру, не нужно будет сравнять по имени или сверять хеши что ты заранее сделаешь на компил-тайме название биндингов. Помимо всего остального там очень много другого полезного, что может очень сильно бустать, но это уже другая история.

Там мне бы хотелось чтото легкое, просто чтобы узнать является ли данная сущность героем или крипом. Я смотрел в джаваскриптовые, и там какая-то непонятная херня вызывается.

Ну да, я по твоему старому гайду делал так собственно.
C++:
Expand Collapse Copy
bool C_BaseEntity::IsHero()
{
    return !strcmp(this->instance->ClassData->Data->BaseClass, "C_DOTA_BaseNPC_Hero");
}
По твоему это лучший способ проверки?

Тогда уж так, если лень реверсить и думать. Выбери лучший хешер, что умеет в норм скорость и сиди сверяй.
(Или ебани сверку по TypeName vftable :), так же по компайл тайму хешеру, в общем способов куча, главное желание.)

C++:
Expand Collapse Copy
bool IsHero() {
    return HASH(GetSchemaBindingClass()->GetName()) == COMPILETIME_HASH("C_DOTA_BaseNPC_Hero"))
}
 
Последнее редактирование:
Назад
Сверху Снизу