Гайд Сущности в доте для чайников

Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Чет нифига не получается, два дня потратил в пустую, уже жопа горит.
1: Не могу понять, где тут конкретно вызов NextEnt. Там, где оно было, его уже нет.
Что из этого -- оно? 26 строчка? 31? Или 38? Третий день не сплю, уже вообще не соображаю нифига.
2: g_pGameEntitySystem -- это qword_1835D2468, который на 26 строчке? Чет ida не показывает на него оффсет, придется ручками считать, right? Или просто в другом месте его взять? Там вроде дофига хрефов на него.
Потому что я не уверен, в чем именно проблема -- в NextEnt, или в GameEntitySystem.

1624433349088.png
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
Чет нифига не получается, два дня потратил в пустую, уже жопа горит.
1: Не могу понять, где тут конкретно вызов NextEnt. Там, где оно было, его уже нет.
Что из этого -- оно? 26 строчка? 31? Или 38? Третий день не сплю, уже вообще не соображаю нифига.
2: g_pGameEntitySystem -- это qword_1835D2468, который на 26 строчке? Чет ida не показывает на него оффсет, придется ручками считать, right? Или просто в другом месте его взять? Там вроде дофига хрефов на него.
Потому что я не уверен, в чем именно проблема -- в NextEnt, или в GameEntitySystem.

Посмотреть вложение 156289
советую https://yougame.biz/threads/139583/page-2#post-1745098 будет быстрее.
а так ида лучше закрой нафиг и открой дебагер с реклассом. динамик анализ как правило будет более плодородный. но конечно статик анализ тоже мощь. просто от ситуации зависит. когда ты какой-то класс ищешь лучше динамик юзать и RTTI чекать. а потом уже если ниче не нашел можно статик попробовать.
x64dbg->ctrl+g->client.base->пкм->search for->current module->string references->"Format: ent_find <substring>\n"->
ищешь все qword птрчки(ну кроме строк) и чекаешь их в реклассе. и сразу все находишь.
Снимок.PNG
Снимок2.PNG
и сразу по RTTI видно что это за хрень там хранится по указателю.(RTTI правда не у всех классов есть но да ладно. у всяких больших важных есть)
(не знаю почему в x64dbg нет функции на просмотр RTTI :( )
вальвы немножко переделали и теперь чтобы получить первую сущность нужно [entSys + 0x210]. это указатель на сущность. дальше у нее как обычно итерируешь через 0x58 m_pNextEnt. но все равно советую лучше итерацию с ссылки которую я скинул( не копипасти там какаято тупая дичь xD перепиши на свой стиль я там половину хуйни написал но суть правильная - делаешь себе функцию GetEntByIndex и вызываешь ее в цикле от 0 до HighestEntity(оффсет 0x2080) - а потом эту функцию распаковываешь в самой итерации чтобы например лист не получать по 100 раз. а всякую хуйню то что я написал там про локальные переменные стек и тд не читай там они энивей инлайнятся не делай так как я даун(ну щас я уже не делаю так это давно было) ). в главном меню кстати HighestEntity = -1 почемуто но зато в матче все норм.
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
советую https://yougame.biz/threads/139583/page-2#post-1745098 будет быстрее.
а так ида лучше закрой нафиг и открой дебагер с реклассом. динамик анализ как правило будет более плодородный. но конечно статик анализ тоже мощь. просто от ситуации зависит. когда ты какой-то класс ищешь лучше динамик юзать и RTTI чекать. а потом уже если ниче не нашел можно статик попробовать.
x64dbg->ctrl+g->client.base->пкм->search for->current module->string references->"Format: ent_find <substring>\n"->
ищешь все qword птрчки(ну кроме строк) и чекаешь их в реклассе. и сразу все находишь.
Посмотреть вложение 156313
Посмотреть вложение 156314
и сразу по RTTI видно что это за хрень там хранится по указателю.(RTTI правда не у всех классов есть но да ладно. у всяких больших важных есть)
(не знаю почему в x64dbg нет функции на просмотр RTTI :( )
вальвы немножко переделали и теперь чтобы получить первую сущность нужно [entSys + 0x210]. это указатель на сущность. дальше у нее как обычно итерируешь через 0x58 m_pNextEnt. но все равно советую лучше итерацию с ссылки которую я скинул( не копипасти там какаято тупая дичь xD перепиши на свой стиль я там половину хуйни написал но суть правильная - делаешь себе функцию GetEntByIndex и вызываешь ее в цикле от 0 до HighestEntity(оффсет 0x2080) - а потом эту функцию распаковываешь в самой итерации чтобы например лист не получать по 100 раз. а всякую хуйню то что я написал там про локальные переменные стек и тд не читай там они энивей инлайнятся не делай так как я даун(ну щас я уже не делаю так это давно было) ). в главном меню кстати HighestEntity = -1 почемуто но зато в матче все норм.

Спасибо, лучший <З
А я сижу, не могу понять, то ли я идиот, то ли вальвы опять всё перелопатили, то ли у меня код херовый (хотя я на плюсах лет 10 уже пишу) XD
Но в реверсе я, конечно, как слепой котенок. Потому и пытаюсь вкатиться -- в доту-то я сто лет как не играю.
БТВ рекласс обычно стороной обходил, а недавно потыкал, засовывая в него энтили-лист, и охерел от того, насколько полезная штука.
Каротщи, спасибо, буду разбираться.
 
Начинающий
Статус
Оффлайн
Регистрация
1 Июн 2021
Сообщения
3
Реакции[?]
1
Поинты[?]
0
советую https://yougame.biz/threads/139583/page-2#post-1745098 будет быстрее.
а так ида лучше закрой нафиг и открой дебагер с реклассом. динамик анализ как правило будет более плодородный. но конечно статик анализ тоже мощь. просто от ситуации зависит. когда ты какой-то класс ищешь лучше динамик юзать и RTTI чекать. а потом уже если ниче не нашел можно статик попробовать.
x64dbg->ctrl+g->client.base->пкм->search for->current module->string references->"Format: ent_find <substring>\n"->
ищешь все qword птрчки(ну кроме строк) и чекаешь их в реклассе. и сразу все находишь.
Посмотреть вложение 156313
Посмотреть вложение 156314
и сразу по RTTI видно что это за хрень там хранится по указателю.(RTTI правда не у всех классов есть но да ладно. у всяких больших важных есть)
(не знаю почему в x64dbg нет функции на просмотр RTTI :( )
вальвы немножко переделали и теперь чтобы получить первую сущность нужно [entSys + 0x210]. это указатель на сущность. дальше у нее как обычно итерируешь через 0x58 m_pNextEnt. но все равно советую лучше итерацию с ссылки которую я скинул( не копипасти там какаято тупая дичь xD перепиши на свой стиль я там половину хуйни написал но суть правильная - делаешь себе функцию GetEntByIndex и вызываешь ее в цикле от 0 до HighestEntity(оффсет 0x2080) - а потом эту функцию распаковываешь в самой итерации чтобы например лист не получать по 100 раз. а всякую хуйню то что я написал там про локальные переменные стек и тд не читай там они энивей инлайнятся не делай так как я даун(ну щас я уже не делаю так это давно было) ). в главном меню кстати HighestEntity = -1 почемуто но зато в матче все норм.
Давно там от 0x210 ? После последнего обновления на несколько гигов ? Просто у меня все брейкпоинты слетят в дебагере, если обновлюсь, не могу посмотреть пока что.

Просто мб ты ошибся, там на 0x210 и раньше какие то ентити лежали, но не с самого начала списка. по 0x10 лежат энтити которые на сервер передаются, их мало. А по 0x110 те, что локальные. Там можно деревья найти. Их кол-во для удобной итерации пока что не нашел. По идее можно и без количества если по next итерировать. Но showEnts функция игровая итерирует через количество и не по next, а просто как по массиву и индекс чекает. Если неправильный то скип. Потому могут быть подвдодные камни.

По поводу плагина для RTTI в ближайшие дни доделаю
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
Давно там от 0x210 ? После последнего обновления на несколько гигов ? Просто у меня все брейкпоинты слетят в дебагере, если обновлюсь, не могу посмотреть пока что.

Просто мб ты ошибся, там на 0x210 и раньше какие то ентити лежали, но не с самого начала списка. по 0x10 лежат энтити которые на сервер передаются, их мало. А по 0x110 те, что локальные. Там можно деревья найти. Их кол-во для удобной итерации пока что не нашел. По идее можно и без количества если по next итерировать. Но showEnts функция игровая итерирует через количество и не по next, а просто как по массиву и индекс чекает. Если неправильный то скип. Потому могут быть подвдодные камни.

По поводу плагина для RTTI в ближайшие дни доделаю
хз я не слежу за обновлениями особо, но да, вроде относительно давно. на 0x210 лежит первая сущность для некста. вальвы переделали. это скрин cl_ent_find, который через некст итерирует. и у этой сущности на 0x210 нету m_pPrev что еще раз подтверждает что она первая.
(о кстати внатуре на 0x110(то есть начиная с 33 листа) лежит всякая чушь типа деревьев. я даже не замечал:D я видел что через next больше ентитей а через массив меньше, но не выяснял почему. это лишь еще одна причина не итерировать через некст. меньше ентитей итерируешь, больше фпс. а деревья можно отдельно при надобности с 33 листа начинать итерировать. правда сначала нужно найти количество деревьев и тд xD если тебе не лень можешь чит енджином поискать циферки которые уменьшаются когда ты прописываешь cl_ent_remove ent_dota_tree например. либо можешь почекать в дилибах какую-нибудь итерацию деревьев)
1624714206236.png
 
Начинающий
Статус
Оффлайн
Регистрация
1 Июн 2021
Сообщения
3
Реакции[?]
1
Поинты[?]
0
хз я не слежу за обновлениями особо, но да, вроде относительно давно. на 0x210 лежит первая сущность для некста. вальвы переделали. это скрин cl_ent_find, который через некст итерирует. и у этой сущности на 0x210 нету m_pPrev что еще раз подтверждает что она первая.
(о кстати внатуре на 0x110(то есть начиная с 33 листа) лежит всякая чушь типа деревьев. я даже не замечал:D я видел что через next больше ентитей а через массив меньше, но не выяснял почему. это лишь еще одна причина не итерировать через некст. меньше ентитей итерируешь, больше фпс. а деревья можно отдельно при надобности с 33 листа начинать итерировать. правда сначала нужно найти количество деревьев и тд xD если тебе не лень можешь чит енджином поискать циферки которые уменьшаются когда ты прописываешь cl_ent_remove ent_dota_tree например. либо можешь почекать в дилибах какую-нибудь итерацию деревьев)
Посмотреть вложение 157166
хм, странная вещь. У меня дота недельной давности, по адресу 0x10 лежит worldent у него id = 0. (0x8000 & 0x7fff = 0)
НО у него есть prev_ent, А по адресу 0x210 лежит энтити без prev. У него только next. Но id = 0x250. ( loword(0x728250) & 0x7fff = 0x250)
Плюс я наспавнил много энтитей то что они все по 0x10 не поместились, 0x18 используется (Ну я думаю ты знаешь что там не просто 0x10 а массив из указателей на мини энтити массивы.
Пожалуйста, авторизуйтесь для просмотра ссылки.
).
А вот дальше 0x210 всегда кладется мусор какой то. Потому я думаю все таки 0x10 начало энтити листа основного( того что по сети передается).

Немного другую функцию юзаю для энтитей вот такой хреф Ent %3d: %s class %s name %s, можно вызывать по адресу без агрументов,
она прям сама выводит в консоль все энтити. Она по офссету 0x10 берет и через массив выводит.

А по поводу фпс, зачем их итерировать каждый цикл ? По моему их в начале при итерации можно по типам разбить и закешировать их адреса, а дальше хук на добавление entity и в нужную категорию кидать. Так побыстрее будет
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
хм, странная вещь. У меня дота недельной давности, по адресу 0x10 лежит worldent у него id = 0. (0x8000 & 0x7fff = 0)
НО у него есть prev_ent, А по адресу 0x210 лежит энтити без prev. У него только next. Но id = 0x250. ( loword(0x728250) & 0x7fff = 0x250)
Плюс я наспавнил много энтитей то что они все по 0x10 не поместились, 0x18 используется (Ну я думаю ты знаешь что там не просто 0x10 а массив из указателей на мини энтити массивы.
Пожалуйста, авторизуйтесь для просмотра ссылки.
).
А вот дальше 0x210 всегда кладется мусор какой то. Потому я думаю все таки 0x10 начало энтити листа основного( того что по сети передается).

Немного другую функцию юзаю для энтитей вот такой хреф Ent %3d: %s class %s name %s, можно вызывать по адресу без агрументов,
она прям сама выводит в консоль все энтити. Она по офссету 0x10 берет и через массив выводит.

А по поводу фпс, зачем их итерировать каждый цикл ? По моему их в начале при итерации можно по типам разбить и закешировать их адреса, а дальше хук на добавление entity и в нужную категорию кидать. Так побыстрее будет
да, OnAdd/OnRemoveEntity. но иногда все равно надо итерировать - например абилки героя. рубен поднимает героя и у него первая абилка уже меняется на другую(опустить героя). не удаляется не добавляется а просто меняется в таблице его абилок(m_hAbilities). поэтому каждый тик нужно пробегать по таблице его абилок и чекать изменились ли они.(коллбека на изменение абилки в слоте я вроде не видел мб он есть я особо не парился с поиском. тогда все было бы гораздо проще) ну естественно рубена можно не из ентитилиста а из своего листа кешированного взять(ну лист с героями отдельно сделать). но как правило ты не будешь начинать с такого. сначала же научиться надо. сначала некст осознаешь как работает, потом массив, потом уже коллбеки а дальше сам разберешься что наиболее фпс-эффективно. поэтому просто привожу стату, что массив быстрее некста. а что наиболее быстрое пусть люди сами решают и тестят.
на 0x10 лежит EntityList* lists[64], 64 листа по 512 сущностей. с 33 листа начинаются дерьмосущности типа деревьев. до этого с 0 листа идут нормальные сущности герои крипы и тд. на 0x210 первая для next сущность. на 0x2080 макс индекс сущности для 0-32 листов. worldent всегда имеет индекс 0 и она служит для того чтобы [мои догадки] к ней партикли можно было прикреплять(ибо партикли нужно к сущности прикреплять. поэтому и мир существует, чтобы к нему партикли крепить и они как бы были независимы, поэтому и число выбрано 0 что типо ни к чему не прикрепляешь. а по факту к миру крепишь)
 
Начинающий
Статус
Оффлайн
Регистрация
1 Июн 2021
Сообщения
3
Реакции[?]
1
Поинты[?]
0
да, OnAdd/OnRemoveEntity. но иногда все равно надо итерировать - например абилки героя. рубен поднимает героя и у него первая абилка уже меняется на другую(опустить героя). не удаляется не добавляется а просто меняется в таблице его абилок(m_hAbilities). поэтому каждый тик нужно пробегать по таблице его абилок и чекать изменились ли они.(коллбека на изменение абилки в слоте я вроде не видел мб он есть я особо не парился с поиском. тогда все было бы гораздо проще) ну естественно рубена можно не из ентитилиста а из своего листа кешированного взять(ну лист с героями отдельно сделать). но как правило ты не будешь начинать с такого. сначала же научиться надо. сначала некст осознаешь как работает, потом массив, потом уже коллбеки а дальше сам разберешься что наиболее фпс-эффективно. поэтому просто привожу стату, что массив быстрее некста. а что наиболее быстрое пусть люди сами решают и тестят.
на 0x10 лежит EntityList* lists[64], 64 листа по 512 сущностей. с 33 листа начинаются дерьмосущности типа деревьев. до этого с 0 листа идут нормальные сущности герои крипы и тд. на 0x210 первая для next сущность. на 0x2080 макс индекс сущности для 0-32 листов. worldent всегда имеет индекс 0 и она служит для того чтобы [мои догадки] к ней партикли можно было прикреплять(ибо партикли нужно к сущности прикреплять. поэтому и мир существует, чтобы к нему партикли крепить и они как бы были независимы, поэтому и число выбрано 0 что типо ни к чему не прикрепляешь. а по факту к миру крепишь)
Ну да, по массиву быстрее еще и потому что там кэш предикшн работает. По поводу рубика, я бы это через протобафы сделал. Там пакет скорее всего приходит с инфой этой.
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Тут спрошу, пожалуй. Я щас уже кукухой поеду от непонимания, как такое вообще в принципе возможно.

Хукнул OnAddEntity и OnRemoveEntity. В целом они работают, но есть очень странная хрень.
У OnRemoveEntity GetTeam() возвращает номер команды, как и должна. У OnAddEntity -- всегда 0.
GetTeam() -- это просто return *(DOTATeam_t*)(((uintptr_t)this) + 0x3af);
Я, естественно, указатель на нужный адрес выводил, открывал в CheatEngine -- там 2.
А внутри функции всегда 0. Я уже вообще не понимаю, что происходит, функции же абсолютно одинаковые.
При этом EntityIdentity->IsHero() и прочее работает, т.е. дело не в EntityIdentity\BaseEntity .
Ну и я их адрес открывал в реклассе, всё так, как и должно быть.

Код:
CEntityInstance* OnAddEntity(CGameEntitySystem* exc, CEntityInstance* ptr, unsigned int index) {
    int EntityIndex = index & 0x7FFF;
    CBaseEntity* BaseEntity = sdk.EntitySystem->GetBaseEntity(EntityIndex);
    CEntityIdentity* EntityIdentity = (CEntityIdentity*)BaseEntity->GetEntityIdent();

    cout << "OnAdd: " << BaseEntity->GetTeam() << endl;

    return vmt.EntitySystem->GetOriginalMethod(OnAddEntity)(exc, ptr, index);
}


CEntityInstance* OnRemoveEntity(CGameEntitySystem* exc, CEntityInstance* ptr, unsigned int index) {
    int EntityIndex = index & 0x7FFF;
    CBaseEntity* BaseEntity = sdk.EntitySystem->GetBaseEntity(EntityIndex);
    CEntityIdentity* EntityIdentity = (CEntityIdentity*)BaseEntity->GetEntityIdent();

    cout << "OnRemove: " << BaseEntity->GetTeam() << endl;

    return vmt.EntitySystem->GetOriginalMethod(OnRemoveEntity)(exc, ptr, index);
}
 
Начинающий
Статус
Оффлайн
Регистрация
21 Июн 2021
Сообщения
13
Реакции[?]
3
Поинты[?]
0
Посмотри описание
Пожалуйста, авторизуйтесь для просмотра ссылки.
у minority. Цитирую:
Когда Entity только создался, у него не заполнена информация о Unit Name и многие другие поля. Чтобы избежать этого необходимо ставить таймаут внутри коллбека, см. пример использования.
Скорей всего проблема в этом.
Хукнул OnAddEntity и OnRemoveEntity
А какие, у них сейчас, там индексы под Windows? OnAddEntity - 14 и OnRemoveEntity - 15?
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Посмотри описание
Пожалуйста, авторизуйтесь для просмотра ссылки.
у minority. Цитирую:
Скорей всего проблема в этом.

А какие, у них сейчас, там индексы под Windows? OnAddEntity - 14 и OnRemoveEntity - 15?
А, лол, даже не подумал бы туда посмотреть. Теперь буду почаще, спасибо.
Индексы -- да, 14 и 15. Сто лет уже не меняются по ходу.

UPD: Ага, работает. Но нафига я это делал, лол, достаточно Heroes.push_back.
Поспать нужно было, ваще тупил.
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
там инфы нет. ты в OnAdd/Remove только добавляешь/удаляешь из своего списка сущностей(Heroes.emplace_back()), а потом просто в каком-нибудь OnUpdate уже бегаешь по своему списку. OnAdd/Remove это лишь коллбеки которые служат для оповещения тех кому это надо, это не место для какой-нибудь жёсткой логики. логику лучше в одном месте всегда делать и сидеть чисто все за раз выполнять. то есть каждый кадр, или каждый тик или еще как-нибудь но точно не по мере каких-нибудь коллбеков или ивентов.(просто потому, что когда ты все в одном месте выполняешь, у тебя все получается синхронно, а когда все в разных, то получается асинхронно, то есть в разные времена, и тебе придется синхронизировать чтобы как-то что-то контроллировать. синхронно = просто. асинхронно = можно но сложно.)
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Та у меня уже проект разросся так, что я в файлах путаюсь XD
Но, да, я OnAdd просто добавляю в список. Пока залепу через std::set сделал, а там посмотрим.
Про OnUpdate не знал, кстати. Звучит хайпово, пойду смотреть.

А, заодно сразу спрошу. У меня единственного, что ли, GetLocalPlayer() крашит при любом вызове? Вроде оно до сих пор на 22 индексе.
И туда же. Локальный игрок всегда №2 в энтити-листе, после World? В игре не хочу тестить, но в лобби работает залепа по типу
EntitySystem->GetBaseEntity(2);
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
Та у меня уже проект разросся так, что я в файлах путаюсь XD
Но, да, я OnAdd просто добавляю в список. Пока залепу через std::set сделал, а там посмотрим.
Про OnUpdate не знал, кстати. Звучит хайпово, пойду смотреть.

А, заодно сразу спрошу. У меня единственного, что ли, GetLocalPlayer() крашит при любом вызове? Вроде оно до сих пор на 22 индексе.
И туда же. Локальный игрок всегда №2 в энтити-листе, после World? В игре не хочу тестить, но в лобби работает залепа по типу
EntitySystem->GetBaseEntity(2);
во-первых world = id 0, поэтому player = id 1 а не 2, а во-вторых GetLocalPlayer вызывается не без аргументов.
int CEngineClient::GetLocalPlayerIndex() {
int ret = 0;
VirtualCall<22>(&ret, 0);//&ret это int* первый аргумент(указатель на переменную куда айди сунет), 0 это слот сплитскрина(сплитскрин это как в портал 2, можно сразу у двух игроков экран видеть, с другом там играть и тд). возвращает войд
return ret;
}
OnUpdate я имел ввиду каждый тик. потести там с фреймстейджнотифай https://yougame.biz/threads/145854/#post-1632059
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
А, понял, недоглядел, спасибо еще раз. Насчет того, что player -- 1, ну не знаю, у меня почему-то работает, я же из своего кода строчку копипастнул. Да и щас сравнил с GetLocalPlayerIndex, тот же результат.
Надо глянуть, что там в 1 и почему я 2 использовать стал, не помню уже.
А FrameStageNotify у меня хукнут, само собой.
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
А, понял, недоглядел, спасибо еще раз. Насчет того, что player -- 1, ну не знаю, у меня почему-то работает, я же из своего кода строчку копипастнул. Да и щас сравнил с GetLocalPlayerIndex, тот же результат.
Надо глянуть, что там в 1 и почему я 2 использовать стал, не помню уже.
А FrameStageNotify у меня хукнут, само собой.
впринципе 1 2 3 или 4 ничего не решает. да, там player, но нельзя сказать что 1 - локальный, а 2 - чужой. это я так просто для общего развития сказал что он не 2 а 1, потому что он идет после worldspawn/worldent которая 0. а если там еще и другие игроки есть то твой игрок может еще и после них идти и быть 2 3 или еще что-нибудь(worldent 0 player_other 1 player_local 2 player_other 3). а в демо или лобби без ботов он всегда 1 будет потому что ты один на сервере. локальный не по циферке индекса определяется, а по тому, что тебе функция движка вернула. но как правило после worldspawn/worldent идут игроки. а кто именно твой это уже по функции движка смотри конечно. нельзя всегда предполагать что локальный игрок на №1 или №2 в ентити листе(тогда функция движка не нужна бы была :D). да, там игроки, но не факт что локальные(один из них локальный но ты не знаешь какой пока функцию движка не вызовешь). а №0 это во всех сурс играх впринципе worldspawn/worldent.
 
smoking on that #pragma pack
Пользователь
Статус
Оффлайн
Регистрация
10 Янв 2018
Сообщения
324
Реакции[?]
96
Поинты[?]
1K
~ да, там игроки, но не факт что локальные(один из них локальный но ты не знаешь какой пока функцию движка не вызовешь).~
альтернативно, есть нетвар "m_bIsLocalPlayer", который имеет значение true, когда игрок является локальным.
таким образом, получив локального игрока через этот нетвар, можно получить и его героя.
сам пользуюсь этим, ибо делаю экстернал.. может пригодится кому.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
760
Реакции[?]
328
Поинты[?]
60K
А где NextEnt сейчас найти? CGameEntSystem нашёл, а вот NextEnt - нет
на оффсете от ентитисистемы лежит FirstEnt. у нее просто ->m_pNext берешь.
C++:
//class CGameEntitySystem VVV
    static inline constexpr auto first_identity_offset = 0x210;
    CEntityIdentity* GetFirstIdentity() const noexcept
    {
        return Member<CEntityIdentity*>(first_identity_offset);
    }

    class EntitySystemView
    {
        class iterator {
        public:
            using iterator_concept = std::forward_iterator_tag;
            using iterator_category = std::input_iterator_tag;
            using difference_type = std::ptrdiff_t;
            using value_type = C_BaseEntity;
            using pointer = value_type*;
            using reference = value_type&;

            CEntityIdentity* ptr{ nullptr };

            auto& operator++() noexcept
            {
                ptr = ptr->GetNext();
                return *this;
            };
            auto operator++(int) noexcept
            {
                iterator copy{ *this };
                operator++();
                return copy;
            };

            auto& operator*() const
            {
                auto entity = ptr->entity;
                if (!entity)
                    throw std::runtime_error{ "EntitySystemView -> identity had nullptr entity!" }; // альтернативно просто скипаешь сущность(сам напишешь логику)
                return *entity;
            }
            auto operator->() const
            {
                return &operator*();
            }
        };
        class sentinel {};

        friend bool operator==(const iterator& it,
            const sentinel&) noexcept
        {
            return it.ptr == nullptr;
        }

    private:
        CEntityIdentity* FirstPtr{ nullptr };
    public:
        explicit EntitySystemView(CEntityIdentity* ptr) noexcept : FirstPtr{ ptr } {}

        iterator begin() const noexcept
        {
            return iterator{ FirstPtr };
        }
        sentinel end() const noexcept
        {
            return {};
        }
    };

    auto GetEntitiesView() const noexcept
    {
        return EntitySystemView{ GetFirstIdentity() };
    }
C++:
for (const auto& entity : entitysystem.GetEntitiesView())
{
    if (entity.SchemaMember<std::uint8_t>("client.dll/C_BaseEntity/m_iTeamNum") == local_team)
    {
        if (entity.IsInstanceOfClass("C_DOTA_BaseNPC"))
        {

            ...
        }
    }
}
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
644
Реакции[?]
102
Поинты[?]
65K
на оффсете от ентитисистемы лежит FirstEnt. у нее просто ->m_pNext берешь.
C++:
//class CGameEntitySystem VVV
    static inline constexpr auto first_identity_offset = 0x210;
    CEntityIdentity* GetFirstIdentity() const noexcept
    {
        return Member<CEntityIdentity*>(first_identity_offset);
    }

    class EntitySystemView
    {
        class iterator {
        public:
            using iterator_concept = std::forward_iterator_tag;
            using iterator_category = std::input_iterator_tag;
            using difference_type = std::ptrdiff_t;
            using value_type = C_BaseEntity;
            using pointer = value_type*;
            using reference = value_type&;

            CEntityIdentity* ptr{ nullptr };

            auto& operator++() noexcept
            {
                ptr = ptr->GetNext();
                return *this;
            };
            auto operator++(int) noexcept
            {
                iterator copy{ *this };
                operator++();
                return copy;
            };

            auto& operator*() const
            {
                auto entity = ptr->entity;
                if (!entity)
                    throw std::runtime_error{ "EntitySystemView -> identity had nullptr entity!" }; // альтернативно просто скипаешь сущность(сам напишешь логику)
                return *entity;
            }
            auto operator->() const
            {
                return &operator*();
            }
        };
        class sentinel {};

        friend bool operator==(const iterator& it,
            const sentinel&) noexcept
        {
            return it.ptr == nullptr;
        }

    private:
        CEntityIdentity* FirstPtr{ nullptr };
    public:
        explicit EntitySystemView(CEntityIdentity* ptr) noexcept : FirstPtr{ ptr } {}

        iterator begin() const noexcept
        {
            return iterator{ FirstPtr };
        }
        sentinel end() const noexcept
        {
            return {};
        }
    };

    auto GetEntitiesView() const noexcept
    {
        return EntitySystemView{ GetFirstIdentity() };
    }
C++:
for (const auto& entity : entitysystem.GetEntitiesView())
{
    if (entity.SchemaMember<std::uint8_t>("client.dll/C_BaseEntity/m_iTeamNum") == local_team)
    {
        if (entity.IsInstanceOfClass("C_DOTA_BaseNPC"))
        {

            ...
        }
    }
}
Спасибо, а где взять CEntityIdentity, Member? И что за C_BaseEntity, просто класс или шо?
1655708345620.png
 
Сверху Снизу