Вопрос Идеи с m_Inventory и m_hAbilities

Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
вроде де бы

6 шмотко главный инветарь 9 шмоток стеш слот для тп + слот для нейтралки
получается 17 ( ну 32 взял чтобы точно попало) я один хуй там везде проверку влепил на валидность чтобы не крашнуло

про 0x7FFF уже запомнил наизусть не вижу смысла отводить отдельный вар для него

про итемс чутка не понял все и так работает и про uint64_t я просто взял хендл итема и сравнил с хендлами в моем ентити листе

ну и про функу мне удобнее передавать в нее ссылку на вектор чем создавать новый вектор )

работает и не крашит ну впринцепе и похуй а CHandle тоже впадлу делать у меня такой гавно код стайл как ты понял потому что впервый я узнал что такое плюсы 20 февраля и я далеко в них не гений а до этого только джс и питон где вприцепе типизации не было
смысл отдельный вар делать в том, чтобы не ошибиться(0x7ff напишешь одну f недопишешь и пизда тебе условно) + для ясности(это не математика здесь не надо называть переменные a b c x y и кучу какихто непонятных констант
Пожалуйста, авторизуйтесь для просмотра ссылки.
). ты везде пишешь 0x7fff. но еще лучше вариант - просто завернуть все это в класс тогда вместо & 0x7fff ты будешь писать GetIndex() просто. но вопрос - если ты сравниваешь равенство схендлов - нахуя тебе индекс( & 0x7fff )? сравнивай целиком весь хендл(сериал и индекс). и CHandle это не uint64_t, это uint32_t(точнее это класс конечно, но на низком уровне это просто юинт32)
то что у тебя без итемс работает - просто совпадение. так звезды сошлись. ты например считываешь с переменной m_SharedCooldownList(и с 8 байт до нее. а это вмт). тебе просто повезло что там нет каких-то данных которые бы тебе помешали. ты считываешь кучу лишнего мусора который тебе нахуй не нужен. зачем? поэтому и крашит потому что хуйню какую-то делаешь.
еще раз,
m_Inventory это не итемы. это инвентарь. m_Inventory.m_hItems вот это уже итемы.
C_DOTA_UnitInventory m_Inventory(offset 0xf58)
+ MNetworkEnable
...
-----members of class C_DOTA_UnitInventory-----
CUtlVector< sSharedCooldownInfo > m_SharedCooldownList(offset 0x8)
CHandle< C_BaseEntity >[19] m_hItems(offset 0x20) //19 шмоток
+ MNetworkEnable
bool[19] m_bItemQueried(offset 0x6c)
int32 m_iParity(offset 0x80)
+ MNetworkEnable
+ MNetworkChangeCallback "OnInventoryParityChanged"
CHandle< C_BaseEntity > m_hInventoryParent(offset 0x84)
+ MNetworkEnable
bool m_bIsActive(offset 0x88)
bool m_bStashEnabled(offset 0x89)
+ MNetworkEnable
CHandle< C_BaseEntity > m_hTransientCastItem(offset 0x8c)
+ MNetworkEnable
bool m_bSendChangedMsg(offset 0xa8)

ну и по секрету скажу
(ent + 0x10)
знаешь что у ентити лежит на 0x10?
class C_BaseEntity(size: 0x580 bytes) extends CEntityInstance
-----members of class CEntityInstance-----
CUtlSymbolLarge m_iszPrivateVScripts(offset 0x8)
+ MNetworkDisable
CEntityIdentity* m_pEntity(offset 0x10)
+ MNetworkEnable
+ MNetworkPriority 56
у ентити на 0x10 лежит айдентити а не хендл)) а у тебя хендл
следовательно
твоя ent это НИХУЯ НЕ СУЩНОСТЬ.
это CEntityIdentity. АЙДЕНТИТИ. это У НЕЕ лежит на 0x10 хендл.
так что иди переименовывай пока не запутался нахуй(ent -> identity).
ну и конечно самый главный вопрос - нахуя ты итерируешь каждую сущность и чекаешь у нее равенство схендла когда ты можешь то же самое сделать быстрее в 100 раз взяв сущность из массива по индексу?(aka GetEntityByIndex) индекс в схендле это не просто какаято циферка, это индекс в массиве.
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
26 Янв 2022
Сообщения
70
Реакции[?]
7
Поинты[?]
0
смысл отдельный вар делать в том, чтобы не ошибиться(0x7ff напишешь одну f недопишешь и пизда тебе условно) + для ясности(это не математика здесь не надо называть переменные a b c x y и кучу какихто непонятных констант
Пожалуйста, авторизуйтесь для просмотра ссылки.
). ты везде пишешь 0x7fff. но еще лучше вариант - просто завернуть все это в класс тогда вместо & 0x7fff ты будешь писать GetIndex() просто. но вопрос - если ты сравниваешь равенство схендлов - нахуя тебе индекс( & 0x7fff )? сравнивай целиком весь хендл(сериал и индекс). и CHandle это не uint64_t, это uint32_t(точнее это класс конечно, но на низком уровне это просто юинт32)
то что у тебя без итемс работает - просто совпадение. так звезды сошлись. ты например считываешь с переменной m_SharedCooldownList(и с 8 байт до нее. а это вмт). тебе просто повезло что там нет каких-то данных которые бы тебе помешали. ты считываешь кучу лишнего мусора который тебе нахуй не нужен. зачем? поэтому и крашит потому что хуйню какую-то делаешь.
еще раз,
m_Inventory это не итемы. это инвентарь. m_Inventory.m_hItems вот это уже итемы.
C_DOTA_UnitInventory m_Inventory(offset 0xf58)
+ MNetworkEnable
...
-----members of class C_DOTA_UnitInventory-----
CUtlVector< sSharedCooldownInfo > m_SharedCooldownList(offset 0x8)
CHandle< C_BaseEntity >[19] m_hItems(offset 0x20) //19 шмоток
+ MNetworkEnable
bool[19] m_bItemQueried(offset 0x6c)
int32 m_iParity(offset 0x80)
+ MNetworkEnable
+ MNetworkChangeCallback "OnInventoryParityChanged"
CHandle< C_BaseEntity > m_hInventoryParent(offset 0x84)
+ MNetworkEnable
bool m_bIsActive(offset 0x88)
bool m_bStashEnabled(offset 0x89)
+ MNetworkEnable
CHandle< C_BaseEntity > m_hTransientCastItem(offset 0x8c)
+ MNetworkEnable
bool m_bSendChangedMsg(offset 0xa8)

ну и по секрету скажу
(ent + 0x10)
знаешь что у ентити лежит на 0x10?
class C_BaseEntity(size: 0x580 bytes) extends CEntityInstance
-----members of class CEntityInstance-----
CUtlSymbolLarge m_iszPrivateVScripts(offset 0x8)
+ MNetworkDisable
CEntityIdentity* m_pEntity(offset 0x10)
+ MNetworkEnable
+ MNetworkPriority 56
у ентити на 0x10 лежит айдентити а не хендл)) а у тебя хендл
следовательно
твоя ent это НИХУЯ НЕ СУЩНОСТЬ.
это CEntityIdentity. АЙДЕНТИТИ. это У НЕЕ лежит на 0x10 хендл.
так что иди переименовывай пока не запутался нахуй(ent -> identity).
ну и конечно самый главный вопрос - нахуя ты итерируешь каждую сущность и чекаешь у нее равенство схендла когда ты можешь то же самое сделать быстрее в 100 раз взяв сущность из массива по индексу?(aka GetEntityByIndex) индекс в схендле это не просто какаято циферка, это индекс в массиве.
я ужк запутался ну похуй работает и так сойдет а про ентити бай индекс я уже сделал только потом дошло
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
663
Реакции[?]
104
Поинты[?]
67K
не забудь про чеки
C++:
    for( auto offset = 0x0020; offset < 0x0064; offset += 0x0004 )
    {
        const auto item_list = entity->m_Inventory( );
        const auto item_idx = memory.Read< std::uint32_t >( inventory_list + offset ) & 0x7FFF;
        const auto item_ent = global::g_entity_system->GetBaseEntity( item_idx );
        const auto item_name = item_ent->GetClassName( );
        // ...
    }
как можно с абилками сделать?

C++:
    std::set<int> GetAbilities()
    {
        std::set<int> ability_list;

        for (int offset = 32; offset < 100; offset += 4)
        {
            const auto ability = *reinterpret_cast<CHandle*>(this + global::offsets::m_hAbilities + offset);
            if(ability.IsValid())
            ability_list.insert(ability.GetIndex().Get());
        }
        return ability_list;
    }


                std::cout << ent->GetEntityName() << std::endl << std::endl << std::endl;

                for (const int abil_index : ent->GetAbilities()) {
                    CBaseEntity* abilqa = reinterpret_cast<CBaseEntity*>(g_pGameEntitySystem->GetBaseEntity(abil_index));
               
                    std::cout << "   abilqa: " << abilqa->GetEntityName() << std::endl;
                }

                std::cout << std::endl;
вот так сделал - выводит только скрытые абилки или что это...


1660459845606.png
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
как можно с абилками сделать?

C++:
    std::set<int> GetAbilities()
    {
        std::set<int> ability_list;

        for (int offset = 32; offset < 100; offset += 4)
        {
            const auto ability = *reinterpret_cast<CHandle*>(this + global::offsets::m_hAbilities + offset);
            if(ability.IsValid())
            ability_list.insert(ability.GetIndex().Get());
        }
        return ability_list;
    }


                std::cout << ent->GetEntityName() << std::endl << std::endl << std::endl;

                for (const int abil_index : ent->GetAbilities()) {
                    CBaseEntity* abilqa = reinterpret_cast<CBaseEntity*>(g_pGameEntitySystem->GetBaseEntity(abil_index));
             
                    std::cout << "   abilqa: " << abilqa->GetEntityName() << std::endl;
                }

                std::cout << std::endl;
вот так сделал - выводит только скрытые абилки или что это...


Посмотреть вложение 216845
почаще копипасть код который не понимаешь и точно нихуя работать не будет)
что за 32? что за 100? ПОЧЕМУ ТЫ ДАЖЕ НЕ УДОСУЖИЛСЯ ПОДУМАТЬ ЧТО ЭТО ЗА ЦИФРЫ И ОТКУДА ОНИ ВЗЯЛИСЬ
32(0x20) взялось отсюда:
C++:
CHandle< C_BaseEntity >[19] m_hItems(offset 0x20)
        + MNetworkEnable
100 это [ДОЛЖНО БЫЛО БЫТЬ] 32 + 19*sizeof(CHandle< C_BaseEntity >)(это 4) (то есть оффсет верхней граница массива = оффсет нижней границы + количество элементов на размер элемента)
но по факту получается 108. 100 это ошибка. ты получается взял и скопипастил себе ошибку. зачем ты так делаешь?
попробуй САМ сделать и всё получится
абилки это(11.08.2022)
C++:
CHandle< C_BaseEntity >[32] m_hAbilities(offset 0xc98)
        + MNetworkEnable
        + MNetworkPriority 32
 
🤡
Пользователь
Статус
Оффлайн
Регистрация
28 Апр 2014
Сообщения
127
Реакции[?]
163
Поинты[?]
21K
На, держи пасту братка.

entity:
CDOTABaseAbility *CBaseEntity::GetAbility(const std::int32_t index)
{
    if (index > sdk::kMaxSpells || !GetAbilities()[index].IsValid()) return nullptr;

    const auto ability = sdk::g_gameentitysystem->GetBaseEntity<CDOTABaseAbility>(
            GetAbilities()[index].GetEntryIndex()
            );
    if (!ability) return nullptr;

    return ability;
}

CDOTABaseAbility *CBaseEntity::GetAbilityByName(const std::string_view &name)
{
    for (auto index = 0; index < sdk::kMaxSpells; index++)
    {
        if (!GetAbilities()[index].IsValid()) continue;

        const auto ability = sdk::g_gameentitysystem->GetBaseEntity<CDOTAItem>(GetAbilities()[index].GetEntryIndex());
        if (!ability || !ability->IsValidAbility()) continue;

        if (ability->ClassName() == name) return ability;
    }

    return nullptr;
}
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
На, держи пасту братка.

entity:
CDOTABaseAbility *CBaseEntity::GetAbility(const std::int32_t index)
{
    if (index > sdk::kMaxSpells || !GetAbilities()[index].IsValid()) return nullptr;

    const auto ability = sdk::g_gameentitysystem->GetBaseEntity<CDOTABaseAbility>(
            GetAbilities()[index].GetEntryIndex()
            );
    if (!ability) return nullptr;

    return ability;
}

CDOTABaseAbility *CBaseEntity::GetAbilityByName(const std::string_view &name)
{
    for (auto index = 0; index < sdk::kMaxSpells; index++)
    {
        if (!GetAbilities()[index].IsValid()) continue;

        const auto ability = sdk::g_gameentitysystem->GetBaseEntity<CDOTAItem>(GetAbilities()[index].GetEntryIndex());
        if (!ability || !ability->IsValidAbility()) continue;

        if (ability->ClassName() == name) return ability;
    }

    return nullptr;
}
не давай ему пасту ему уже дали пасту смотри чем закончилось(тем что он не понимает что делает)
и у тебя кстати чек неправильный.
у тебя итерация
index < sdk::kMaxSpells
а обратный чек должен быть !(index < sdk::kMaxSpells), то есть index >= sdk::kMaxSpells (а у тебя index > sdk::kMaxSpells)
иначе у тебя получается что ласт индекс(32) валидный(= OOB) хотя по факту последний валидный это ласт-1(31)(0->31)
ну и if(!ability) return nullptr это то же самое что и просто return ability. если ability это нуллптр то оно и так вернет нуллптр))
вот собственно очередная причина не пастить. ни у меня(очевидно что я тоже временами баганный код кидаю) ни у кого-то еще.
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
663
Реакции[?]
104
Поинты[?]
67K
что за 32? что за 100? ПОЧЕМУ ТЫ ДАЖЕ НЕ УДОСУЖИЛСЯ ПОДУМАТЬ ЧТО ЭТО ЗА ЦИФРЫ И ОТКУДА ОНИ ВЗЯЛИСЬ
32(0x20) взялось отсюда:
32, я думал это размер массива, да и человек написал что нужно entity + m_hitems + offset, а не entity + offset, т.е. 0x20(m_hitems)
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
32, я думал это размер массива, да и человек написал что нужно entity + m_hitems + offset, а не entity + offset, т.е. 0x20(m_hitems)
так если ты думал что 32 это размер массива(коим он не является. 32 это оффсет m_hItems), значит ты нихуя не понимаешь. если ты нихуя не понимаешь - почему вместо того чтобы разобраться ты копипастишь? копипаста разрешена только когда ты понимаешь всё что видишь но тебе лень самому писать и ты берешь чужое с целью дальнейшей модификации под свои нужды и стиль. копипаста в любых других целях ни к чему хорошему не приводит
по факту для итемов там нужен entity + m_Inventory + m_hItems + (size*index)
а для абилок entity + m_hAbilities + (size*index)
так что 32(= m_hItems) прибавлять не надо. и естественно верхняя граница будет другая(не +100) изза того что m_hAbilities имеет другой размер.
иди сам сделай а не пасть и все будет хорошо
 
🤡
Пользователь
Статус
Оффлайн
Регистрация
28 Апр 2014
Сообщения
127
Реакции[?]
163
Поинты[?]
21K
не давай ему пасту ему уже дали пасту смотри чем закончилось(тем что он не понимает что делает)
и у тебя кстати чек неправильный.
у тебя итерация
index < sdk::kMaxSpells
а обратный чек должен быть !(index < sdk::kMaxSpells), то есть index >= sdk::kMaxSpells (а у тебя index > sdk::kMaxSpells)
иначе у тебя получается что ласт индекс(32) валидный(= OOB) хотя по факту последний валидный это ласт-1(31)(0->31)
ну и if(!ability) return nullptr это то же самое что и просто return ability. если ability это нуллптр то оно и так вернет нуллптр))
вот собственно очередная причина не пастить. ни у меня(очевидно что я тоже временами баганный код кидаю) ни у кого-то еще.
Да я как ты наверно заметил, не часто кидаю пасту, но иногда мне лень описывать, как ты или еще чот и мне проще spoonfeed'нуть.

А вот про проверку, спасибо, не заметил при разработке и жил с ней и даж не знал проблем.
Кидать обратно нуллптр это такой у меня стиль кодинга, мне так лучше читать код. Я шиз в этом плане, это можно забить.
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
663
Реакции[?]
104
Поинты[?]
67K
а для абилок entity + m_hAbilities + (size*index)
так что 32(= m_hItems) прибавлять не надо. и естественно верхняя граница будет другая(не +100) изза того что m_hAbilities имеет другой размер.
иди сам сделай а не пасть и все будет хорошо
да так и вправду заработало чет тупанул
если надо кому-то будет:

C++:
for (int index = 0; index < 32; index++)
    {
        const auto ability = *reinterpret_cast<CHandle*>(this + global::offsets::m_hAbilities + (4 * index));
        if(ability.IsValid())
        ability_list.insert(ability.GetIndex().Get());
    }
только оно в какой-то странной последовательностивыводит ну ладно
1660482147759.png
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
да так и вправду заработало чет тупанул
если надо кому-то будет:

C++:
for (int index = 0; index < 32; index++)
    {
        const auto ability = *reinterpret_cast<CHandle*>(this + global::offsets::m_hAbilities + (4 * index));
        if(ability.IsValid())
        ability_list.insert(ability.GetIndex().Get());
    }
только оно в какой-то странной последовательностивыводит ну ладно
Посмотреть вложение 216902
почаще std::set юзай, который сортирует содержимое))
опять таки делаешь вещи о которых ты ничего не понимаешь. почитай для начала про сет прежде чем его юзать.
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
663
Реакции[?]
104
Поинты[?]
67K
почаще std::set юзай, который сортирует содержимое))
опять таки делаешь вещи о которых ты ничего не понимаешь. почитай для начала про сет прежде чем его юзать.
название просто понравилось это, а что лучше для этого, std::vector? или что нибудь еще?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
название просто понравилось это, а что лучше для этого, std::vector? или что нибудь еще?
вопрос зачастую не в том что "лучше", а в том что тебе надо. у каждого контейнера свои алгоритмы и свои назначения.
мапа - дерево ключ-значение с сортировкой
анордеред_мапа - хештейбла
вектор - кучка последовательных данных
сет - как мапа, токо там онли ключи без значений и сет хранит только уникальные ключи без дубликатов
лист - дабл линкед лист
deque - двухсторонняя очередь
и тд и тп много всякого говна в этом мире есть
что хочешь то и выбирай
самый лучший выбор в данной ситуации - ничего не выбирать. У ГАБЕНА УЖЕ ХРАНИТСЯ КУЧКА CHANDLE В m_hAbilities. ты в любой момент можешь оттуда взять любой схендл. зачем тебе самому что-то где-то хранить? там автоматом m_hAbilities меняется когда абилки меняются(например рубик первый скилл(поднять героя) нажал теперь у него первый скилл это уже совсем другая абилка - отпустить героя). нужна абилка - бери с m_hAbilities
 
Пользователь
Статус
Оффлайн
Регистрация
26 Окт 2017
Сообщения
519
Реакции[?]
95
Поинты[?]
2K
вопрос зачастую не в том что "лучше", а в том что тебе надо. у каждого контейнера свои алгоритмы и свои назначения.
мапа - дерево ключ-значение с сортировкой
анордеред_мапа - хештейбла
вектор - кучка последовательных данных
сет - как мапа, токо там онли ключи без значений и сет хранит только уникальные ключи без дубликатов
лист - дабл линкед лист
deque - двухсторонняя очередь
и тд и тп много всякого говна в этом мире есть
что хочешь то и выбирай
самый лучший выбор в данной ситуации - ничего не выбирать. У ГАБЕНА УЖЕ ХРАНИТСЯ КУЧКА CHANDLE В m_hAbilities. ты в любой момент можешь оттуда взять любой схендл. зачем тебе самому что-то где-то хранить? там автоматом m_hAbilities меняется когда абилки меняются(например рубик первый скилл(поднять героя) нажал теперь у него первый скилл это уже совсем другая абилка - отпустить героя). нужна абилка - бери с m_hAbilities
ну на счёт не надо хранить где то ты преувеличил. варианты использования дефолтные не катят для быстрой реализации функционала скриптов
каждый раз проходить через функу которая тебе что то вернёт не найс даже если это твоя которая просто через for проходит.
с таким же успехом можно обёртки выковырять из доты и использовать абсолютно всё что хочешь. и к числу 32 для перебора что был выше
толком до конца не понял что там было не вчитывался, но в предметах это актуально если верить всё тем же обёрткам доты. ранее я там это видел и в индексах после 15 можно наткнуться на аганимы съеденные и шмот типа нейтралки и тп
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
ну на счёт не надо хранить где то ты преувеличил. варианты использования дефолтные не катят для быстрой реализации функционала скриптов
каждый раз проходить через функу которая тебе что то вернёт не найс даже если это твоя которая просто через for проходит.
с таким же успехом можно обёртки выковырять из доты и использовать абсолютно всё что хочешь. и к числу 32 для перебора что был выше
толком до конца не понял что там было не вчитывался, но в предметах это актуально если верить всё тем же обёрткам доты. ранее я там это видел и в индексах после 15 можно наткнуться на аганимы съеденные и шмот типа нейтралки и тп
я в посте который ты процитировал написал "вопрос ... в том что тебе надо" и написал "в данной ситуации". под "данной ситуацией" я имел ввиду конкретно его ситуацию(он просто индексы сущностей абилок(даже не сами сущности) хранил в сете - смысла в этом 0). я ничего не преувеличивал. читать с массива и засовывать в сет(именно индексы)(= аллоцировать память, балансировать дерево, чекать дубликаты и тд) то что уже и так лежит в массиве - глупо.
к числу 32 был вопрос не как к размеру массива а как к оффсету который он прибавлял и терял первые 32/4 = 8 абилок и потом спрашивал ээ а где мои 8 первых абилок
 
Сверху Снизу