m_clrRender + OnColorChanged callback.how to change color of hero?
m_clrRender + OnColorChanged callback.how to change color of hero?
ent->SchemaMember<std::uint32_t>("client.dll/C_BaseModelEntity/m_clrRender") = clr;how to change color of hero?
m_clrRender + OnColorChanged callback.
thanksent->SchemaMember<std::uint32_t>("client.dll/C_BaseModelEntity/m_clrRender") = clr;
CNetworkMessages::GetInstance().FindNetworkCallback("OnColorChanged").Invoke(*ent);
I'm pretty sure he did it other way, but here's my option to do any color you want.how to change color of hero?
class CBaseEntity {
public:
void ChangeModelColor(int r, int g, int b, int a = 255) {
uintptr_t Base = ((uintptr_t)this + Netvars::Offsets.m_clrRender);
// m_clrRender is inside C_DOTA_BaseNPC_Hero
*(BYTE*)(Base + 0) = static_cast<BYTE>(r);
*(BYTE*)(Base + 1) = static_cast<BYTE>(g);
*(BYTE*)(Base + 2) = static_cast<BYTE>(b);
*(BYTE*)(Base + 3) = static_cast<BYTE>(a);
// Then you have to call callback function to let dota know you've just change model color
NVFunc.OnColorChanged(this);
}
}
// what the hell is OnColorChanged?
typedef void (*OnColorChangedFn)(CBaseEntity*);
IDA xref: "OnColorChanged"
.text:0000000180292EAF lea rax, aOncolorchanged ; "OnColorChanged"
.text:0000000180292EB6 mov [rbp+40h+var_C0], rax
.text:0000000180292EBA lea rax, OnColorChanged << Here it is
.text:0000000180292EC1 mov [rbp+40h+var_A8], rax
.text:0000000180292EC5 lea rax, aOnrenderattrib ; "OnRenderAttributesChanged"
Ну йобаны рот, пока я писал, уже стало поздноent->SchemaMember<std::uint32_t>("client.dll/C_BaseModelEntity/m_clrRender") = clr;
CNetworkMessages::GetInstance().FindNetworkCallback("OnColorChanged").Invoke(*ent);
А что, так можно было? А это как и где...CNetworkMessages::GetInstance().FindNetworkCallback("OnColorChanged").Invoke(*ent);
Это никак не связано с SendNetMessage.I'm pretty sure he did it other way, but here's my option to do any color you want.
Like, for illusions detection or smth.
C++:class CBaseEntity { public: void ChangeModelColor(int r, int g, int b, int a = 255) { uintptr_t Base = ((uintptr_t)this + Netvars::Offsets.m_clrRender); // m_clrRender is inside C_DOTA_BaseNPC_Hero *(BYTE*)(Base + 0) = static_cast<BYTE>(r); *(BYTE*)(Base + 1) = static_cast<BYTE>(g); *(BYTE*)(Base + 2) = static_cast<BYTE>(b); *(BYTE*)(Base + 3) = static_cast<BYTE>(a); // Then you have to call callback function to let dota know you've just change model color NVFunc.OnColorChanged(this); } } // what the hell is OnColorChanged? typedef void (*OnColorChangedFn)(CBaseEntity*);
Or just "40 ? 48 83 EC ? 48 8B ? 48 8B ? ? ? ? ? 48 8B ? 0F B6"C-like:IDA xref: "OnColorChanged" .text:0000000180292EAF lea rax, aOncolorchanged ; "OnColorChanged" .text:0000000180292EB6 mov [rbp+40h+var_C0], rax .text:0000000180292EBA lea rax, OnColorChanged << Here it is .text:0000000180292EC1 mov [rbp+40h+var_A8], rax .text:0000000180292EC5 lea rax, aOnrenderattrib ; "OnRenderAttributesChanged"
UPD:
Ну йобаны рот, пока я писал, уже стало поздно
UPD 2:
А что, так можно было?
UPD 3: Liberalist любые пинания по кодстайлу приветствуются.
class FieldChangeCallback_t
{
public:
char pad_0x0000[0x8]; //0x0000
char* m_name; //0x0008
char pad_0x0010[0x8]; //0x0010
std::uintptr_t m_pointer; //0x0018
char* m_class_name; //0x0020
char pad_0x0028[0x40]; //0x0028
}; //Size=0x0068
auto res = network_callbacks::manager->Call<__int64, CBaseEntity*>(HASH("OnColorChanged"), this);
template <typename Return, typename ...Args>
Return Call(hash_t name, Args&&... args)
{
if (const auto callback = Get(name); callback.has_value())
{
auto fn = reinterpret_cast<void* (*)(Args ...)>(&callback);
return reinterpret_cast<Return>(fn(args...));
}
throw std::runtime_error{fmt::format("{}: doesnt exists in network field callbacks!", name)};
}
У меня примерно то же самое, но немного по другому сделано.
Реализации могут быть разные, но в целом, мысль у нас одинаковая.
C++:auto res = network_callbacks::manager->Call<__int64, CBaseEntity*>(HASH("OnColorChanged"), this); template <typename Return, typename ...Args> Return Call(hash_t name, Args&&... args) { if (const auto callback = Get(name); callback.has_value()) { auto fn = reinterpret_cast<void* (*)(Args ...)>(&callback); return reinterpret_cast<Return>(fn(args...)); } throw std::runtime_error{fmt::format("{}: doesnt exists in network field callbacks!", name)}; }
Ответил в посте, обновись, про коллбеки.
Охереть. А ведь у меня база под это есть. Че я вообще туда не смотрел -- не пойму.Ответил в посте, обновись, про коллбеки.
ну во-первых хотелось бы пнуть свою хуйню с GetInstance(надо ее спрятать под колпак, сделать статик FindNetworkCallback чтобы он внутри уже вызывал GetInstance() и там бы чето ебашил)UPD 3: Liberalist любые пинания по кодстайлу приветствуются.
Color m_clrRender(offset 0x5a4)
+ MNetworkEnable
+ MNetworkChangeCallback "OnColorChanged"
class FrameSyncHook : public BaseVMTHook<FrameSyncHook, 11>// это не дота
{
public:
static return_type __fastcall Hook(void* rcx) noexcept
{
if (ejection_request_received.test())
{
auto result = CallOriginal(rcx);
ejection_flag.test_and_set();
ejection_flag.notify_all();
done_ejecting.wait(false);
return result;
}
else {
OnBeforeFrameSyncCallbacks::InvokeAllCallbacks();//опять таки авторег тут у меня в коде выше(авторегает мои коллбеки в массив в OnBeforeFrameSyncCallbacks)
return CallOriginal(rcx);
}
}
};
...
static VMTHook InstallHooks()
{
return { GetVMT(), FrameSyncHook {} };
}
...
class OpenChestAnywhereCallback : public OnBeforeFrameSyncCallback<OpenChestAnywhereCallback>
{
public:
static void Callback() noexcept
{ ... }
};
...
const auto& frame_hooks = FrameSync::InstallHooks();
Logger::log("Installed FrameSync hooks!");
class VMTXref : PatternParent<VMTXref,
"shit.exe",
"shit::shit::shit",
"12 34 56 78 90 12 ?? 34 56 ?? ?? 78"
>
{
public:
static inline VFTable xref{};
static void Initialize()
{
constexpr auto MOV_OFFSET = 0xC;
constexpr InstructionProperties mov{ 2, 6 };
xref = { GetAbsoluteAddress<mov, void*>
(GetLocation<std::uintptr_t>() + MOV_OFFSET) };
if (!xref.IsValid())
throw std::runtime_error{ "shit::shit::shit -> xref absolute address is nullptr!" };
}
};
...
static void ScanPatterns()//old shitcode
{
for (auto item : GetItems())
{
if (item == nullptr) continue;
item->Location =
FindPattern(GetExecutable(item->ExecutableName), item->Bytes, item->Name);
item->Initializer();
}
}
...
Patterns::ScanPatterns();
Ебанешься...ну во-первых хотелось бы пнуть свою хуйню с GetInstance(надо ее спрятать под колпак, сделать статик FindNetworkCallback чтобы он внутри уже вызывал GetInstance() и там бы чето ебашил)
CNetworkMessages::GetInstance().FindNetworkCallback("OnColorChanged").Invoke(*ent);
->
CNetworkMessages::FindNetworkCallback("OnColorChanged").Invoke(*ent);
можно еще дальше пойти
->
CNetworkMessages::InvokeNetworkCallback("OnColorChanged", *ent);//нахуя искать и вызывать если можно сразу вызвать внутри при нахождении?
потом можно еще дальше пойти добавить авторег и резолв на стадии инита(чтобы сразу еще на ините удостовериться что такой коллбек существует + для оптимизации чтобы один раз получить коллбек и всё)
->
CNetworkMessages::InvokeNetworkCallback<"OnColorChanged">(*ent);
а еще можно бы ent заменить с указателя на референс сразу после чека на нуллптр(ну новую переменную auto& ent_ref = *ent ввести например)
->
CNetworkMessages::InvokeNetworkCallback<"OnColorChanged">(ent_ref);
//и другие действия с ent_ref, чтобы не писать потом ent->, *ent и тд
в итоге у нас быстро работает(один раз коллбек нашли и всё. сам указатель на функцию доты всегда на одном и том же месте, так что нахуя нам каждый раз его переполучать или искать в мапе или еще какой-то хуйней заниматься), есть корректность и гарантия успеха(на ините сразу в ебало ошибка что такого коллбека нет(= мы либо неправильно его имя написали и пойдем фиксить либо например габен его из доты убрал и мы пойдем искать аналог. лучше сразу узнать при инжекте чем во время каточки например)).
ЕЩЕ можно еще еще еще дальше пойти и ебануть ваще InvokeNetworkCallback как метод у C_BaseEntity просто и тогда вызывать типа
ent_ref.InvokeNetworkCallback<"OnColorChanged">();//под колпаком хуйня с CNetworkMessages
и будет ваще прям идеально. меняешь на сущности нетвар и на этой же сущности сразу вызываешь коллбек.
можно ваще запариться очень жёска и сделать АВТОМАТОМ вызов коллбека путём доставания метапропов из шемы(ебать технологии нахуй 21 век)
достать сразу из описания в шеме m_clrRender коллбек OnColorChanged и просто вызыватьC++:Color m_clrRender(offset 0x5a4) + MNetworkEnable + MNetworkChangeCallback "OnColorChanged"
ent_ref.SetAndNotify<m_clrRender>(1234567);//= Set + m_clrRender.InvokeChangeCallback(). две строки в одной получается. и даже если габен коллбек у этой переменной переименует - ваще похуй будет ибо автоматом новый коллбек сразу на рантайме из шемы достанет и найдет(а если не найдет то инит зафейлится)
тогда чуть чуть авторег нужно будет переделать(надо будет вместе с оффсетом в хранилище нетваров еще и хранить коллбек если такой имеется(и тут же сразу на ините можно выдавать ошибку если коллбек не найден, а также и выдавать ошибку если нетвар не найден))
во-вторых я даун криво сделал можно было бы все синглтоны(типа CNetworkMessages и тд) тоже засунуть в авторег и резолвить на ините, тогда бы опять таки была гарантия успеха при получении синглтона в любом месте в коде(а провал бы обнаруживался бы сразу на стадии инита и дальше бы до других мест исполнение бы уже не доходило) (ну в общем мораль в том что имеет смысл везде стараться хуярить noexcept'ный код где можно и все ошибки(по типу не найденного оффсета коллбека хуека сиги интерфейса и прочего дерьма) все-таки чекать сразу в ините - меньше головной боли(не надо думать "а что если нетвар не найдет?") и больше корректности и конечно же на момент инита всегда можно адекватно отреагировать на любую ошибку просто перестав инититься. если же о критической ошибке(например сига не нашлась) мы узнаем например в каком-нибудь нашем хуке который хуй пойми когда и в каком треде вызывается - ну тут уже блядь сложнее будет гораздо отреагировать)
в общем авторег(авторегом я называю CRTP(= аутсурсинг логики на родителя + уникальность ребёнка засчёт уникальной темплейты) + static inline registrant(который изза CRTP будет уникальный для каждого ребёнка) + хранилище в которое регистрант регается. ну то есть вся суть авторега в том что чисто сама лишь декларация класса(class MyShit : public some_shit<123>{};) это уже сразу и регистрация каких-либо данных в хранилище) мастехв имбафича 2022 всем советую
вот пример авторега(представим что у меня есть какаято полиморф хуита(в данном случае у меня есть коллбек(= ивент хендлер) который реагирует на один из ивентов - клик, мув, пресс) и мне нужно все эти хуиты сохранить в одну пачку для централизованного диспатча(ну то есть мне дали ивент и я смотрю кому он нужен и даю тем кому он нужен) и при этом я не хочу писать руками RegisterCallback и прочую хуиту)
(на кленге и гсс нужно дополнительно как-нибудь упомянуть static inline переменные иначе компиляторы их оптимизируют нахуй, на мсвс такой хуйни нет поэтому там все норм и можно не париться)
Пожалуйста, авторизуйтесь для просмотра ссылки.пример применения авторега на практике для шемы есть тут
да и ваще CRTP сам по себе уже имба ебаная мастхев фича, у меня например вмт хуки на CRTP (это правда старый говно дизайн надо радикально реворкнуть)
ну и сиги тоже на автореге. да блядь ваще все что можно на автореге - фича слишком имбоваяC++:class FrameSyncHook : public BaseVMTHook<FrameSyncHook, 11>// это не дота { public: static return_type __fastcall Hook(void* rcx) noexcept { if (ejection_request_received.test()) { auto result = CallOriginal(rcx); ejection_flag.test_and_set(); ejection_flag.notify_all(); done_ejecting.wait(false); return result; } else { OnBeforeFrameSyncCallbacks::InvokeAllCallbacks();//опять таки авторег тут у меня в коде выше(авторегает мои коллбеки в массив в OnBeforeFrameSyncCallbacks) return CallOriginal(rcx); } } }; ... static VMTHook InstallHooks() { return { GetVMT(), FrameSyncHook {} }; } ... class OpenChestAnywhereCallback : public OnBeforeFrameSyncCallback<OpenChestAnywhereCallback> { public: static void Callback() noexcept { ... } }; ... const auto& frame_hooks = FrameSync::InstallHooks(); Logger::log("Installed FrameSync hooks!");
дальше.C++:class VMTXref : PatternParent<VMTXref, "shit.exe", "shit::shit::shit", "12 34 56 78 90 12 ?? 34 56 ?? ?? 78" > { public: static inline VFTable xref{}; static void Initialize() { constexpr auto MOV_OFFSET = 0xC; constexpr InstructionProperties mov{ 2, 6 }; xref = { GetAbsoluteAddress<mov, void*> (GetLocation<std::uintptr_t>() + MOV_OFFSET) }; if (!xref.IsValid()) throw std::runtime_error{ "shit::shit::shit -> xref absolute address is nullptr!" }; } }; ... static void ScanPatterns()//old shitcode { for (auto item : GetItems()) { if (item == nullptr) continue; item->Location = FindPattern(GetExecutable(item->ExecutableName), item->Bytes, item->Name); item->Initializer(); } } ... Patterns::ScanPatterns();
uintptr_t Base = ((uintptr_t)this + Netvars::Offsets.m_clrRender);
...
можно заменить на
Member<int>(Netvars::Offsets.m_clrRender) = r | (g << 8) | (b << 16) | (a << 24);
//Member<int> вернет int&
при этом аргументы r,g,b,a из int переделать сразу в BYTE(если они у тебя и так от 0 до 255 нахуя им тогда тип int)
ну и просто так к слову интересный факт альфа не будет работать по дефолту на героях потому что у них m_nRenderMode по дефолту kRenderNormal(не поддерживает прозрачность) и надо менять если альфа нужна
Пожалуйста, авторизуйтесь для просмотра ссылки.enum RenderMode_t(size: 1 bytes):
kRenderNormal = 0,
kRenderTransColor = 1,
kRenderTransTexture = 2,
kRenderGlow = 3,
kRenderTransAlpha = 4,
kRenderTransAdd = 5,
kRenderEnvironmental = 6,
kRenderTransAddFrameBlend = 7,
kRenderTransAlphaAdd = 8,
kRenderWorldGlow = 9,
kRenderNone = 10,
kRenderDevVisualizer = 11,
kRenderModeCount = 12,
class ParticleEffectIdentity
{
0x0 zero
0x8 zero
0x10 CNewParticleEffect* m_pParticleEffect
};
class CNewParticleEffect
{
0x0 vmt
0x08 thisptr
0x10 m_pPrev
0x18 m_pNext
0x20 m_pParticleCollection
};
ну хуй его знает кто за что отвечает конечноLiberalist как понять какие индексы в SetControlPoint и что за что отвечает? ну хочу я создать кружок вокруг героя радиус 1200 и перекрасить его в цвет красный.
CDOTA_ParticleManager, 7 индексКакие сейчас индексы у CreateParticle я наше две функции в CDotaManager_PArticle которые принимет параметры вточь точь которые говорились в треде.Одна по оффсету 0x50 от начала таблицы вторая по оффсету 0x38.Первая (та что по оффсету 0ч50)вызывается иногда со строкой которая содержит что то типа "hit_attach"?Так какая из них?УЖе 2 сутки найти не могу
партикль нужно не просто создать нужно еще и настроить(выставить контрол поинты(например коорды всякие цвета размеры и тд)) после этогоВот Эта функа я ее вызывал уже и ничего не происходило.Например я рассужадл так.Я зажимал альт (появлялся рендж таверов)срабатывал бряк и я смотрел параметры.Я воссоздавал точно такие же параметры и вызывал функцию с указателем на нее.Все работало хорошо,в том плане что не крашило.Но рендж таверов не рисовался.Индекс у функи тоже 7 ведь 0x7 *0x8 = 38;Что я делаю не так?Так же я заметил что эта единтсвенная функция которая вызывается при отображеннии партикля particles/mouse_actions/tower_oae(как то так).А внутри этой функции вызываются уже другие функции из вмт ParticleManager.Таким образом чтобы мне нарисовать партикль нужно вызвать только эту функу,с этими параметрами,все остальное она сделает внутри самой себя если потребуется(например SetParticleControlPoint и т.д)?
Спасибо партикли создаются успешно(в консоли выдается соотвествующие сообщение Creating collection: particles/ui_mouseactions/range_finder_tower_aoe.vpcf),теперь насколько я понял нужно установить контрл поинты.Но функции для утсановки контрол поинтов и дестрой партиклов находятся уже ж не в классе CDOTA_ParticleManaget а в классе NewParticleEffect?Так как я реверсил как дота создает партикли и увидел два образения к вмт CDOTA_ParticleManager (crateParticle 0x38 отнсоительно вмт и еще какая то функа которая видно ниче не делает).А после я видел только вызов методов ParticleNewEffeect?партикль нужно не просто создать нужно еще и настроить(выставить контрол поинты(например коорды всякие цвета размеры и тд)) после этого
ну и в доте есть консольные команды и конвары всякие(сам найдешь find консольная команда есть поищи всякую хуйню связанную с "particle" "dump" "log" и тд и тп) попробуй их поврубай и посмотри логает ли создание твоей партикли или нет. должно логать что партиклю создает если все правильно делаешь(а потом ты уже настраиваешь партиклю)
в NewParticleEffect есть CParticleCollection вот у нее виртуалка есть для контрол поинтов(в 2020 индекс 15 был щас скорее всего другой)Спасибо партикли создаются успешно(в консоли выдается соотвествующие сообщение Creating collection: particles/ui_mouseactions/range_finder_tower_aoe.vpcf),теперь насколько я понял нужно установить контрл поинты.Но функции для утсановки контрол поинтов и дестрой партиклов находятся уже ж не в классе CDOTA_ParticleManaget а в классе NewParticleEffect?Так как я реверсил как дота создает партикли и увидел два образения к вмт CDOTA_ParticleManager (crateParticle 0x38 отнсоительно вмт и еще какая то функа которая видно ниче не делает).А после я видел только вызов методов ParticleNewEffeect?
//old shitcode(2020) VVV
void SetControlPoint(u64 ControlPointIndex, Fvector& cp)
{
unsigned long Count = DPM->ParticlesCount();
auto List = DPM->Particles();
for (unsigned long i = 0; i < Count; i++)
{
if (List->items[i]->handle == handle)
{
List->items[i]->NPE->CParticleCollection->VirtualCall<15>(ControlPointIndex, cp);
return;
}
}
}
Проект предоставляет различный материал, относящийся к сфере киберспорта, программирования, ПО для игр, а также позволяет его участникам общаться на многие другие темы. Почта для жалоб: admin@yougame.biz