Гайд [CS2] Вычисление значений Spread'а

Участник
Статус
Оффлайн
Регистрация
15 Янв 2021
Сообщения
491
Реакции[?]
277
Поинты[?]
67K
Итак, теперь у нас на повестке дня находится вычисление значений для разброса пуль, которые в теории можно использовать, чтобы сделать NoSpread, но есть нюанс и о нём чуть позже. Томить не буду, просто дам код для этого со всеми сигнатурками. Имеются некоторые хард офсеты, но вы можете завести под них сигнатуру, если имеете прямые руки. Код проверялся на локальном сервере, без каких-либо изменений в конварах.

C++:
int64_t pContext;
float unk_val = 0;
int iMode = 1;
// client.dll "48 89 5C 24 08 57 48 83 EC 30 0F 29 74 24 20 45 8B"
BacktrackLocalPlayer((__int64)pLocalWeapon, (__int64)&pContext, unk_val, iMode);

// client.dll "48 81 EC F8 00 00 00 F3 0F 10 09"
// viewangles <- angles when you are shooting
auto random_seed = GetRandomSeed(&viewangles, render_tick);

// init random system with this seed
g_pWinApi->m_RandomSeed(random_seed + 1);   

// Exports from tier0.dll
float flRadiusCurveDensity = g_pWinApi->m_RandomFloat(0, 1.f);
float fTheta3 = g_pWinApi->m_RandomFloat(0.0f, 2.0f * M_PI);
float flSpreadCurveDensity = flRadiusCurveDensity;

// Convar
auto weapon_accuracy_shotgun_spread_patterns = (int64_t)(client_dll + 0x186C930);
// Unknown shit
auto unk_addr3 = (int64_t)(client_dll + 0x1676AF8);

int* pItem = (int*)((int64_t)pLocalWeapon + 0x1090);

using GetWeaponVData_t = __int64(__fastcall*)(__int64);
// client.dll "48 81 EC 38 01 00 00 48 85 C9 75 0A 33 C0 48 81 C4 38 01 00 00 C3 48 89"
auto pWeaponData = GetWeaponData(pItem);
auto nWeaponBullets = *(DWORD*)(pWeaponData + 268);

// client.dll "E8 ?? ?? ?? ?? 48 85 C0 75 E9"
auto v91 = GetConvarValue(weapon_accuracy_shotgun_spread_patterns, -1);
float theta_1;
auto flRecoilIndex = *(float*)((int64_t)pLocalWeapon + 5828);
float my_flSpreadCurveDensity = 0;

if (*v91)
{
    auto v92 = 0 + nWeaponBullets * (int)flRecoilIndex;
    auto v93 = *(int*)(uintptr_t(pItem) + 0x1BA);

    // client.dll "66 89 54 24 10 55 48"
    RandomizeSomeShit((__int64)unk_addr3, v93, iMode, v92, &theta_1, &my_flSpreadCurveDensity);
}

// Just a get spread/inaccuracy values. Too lazy to do it like a vfuncs
float flSpread, flInaccuracy;
auto flSpread1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 2856))((int64_t)pLocalWeapon);
auto flInaccr1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 3216))((int64_t)pLocalWeapon);
flSpread = *(float*)&flSpread1;
flInaccuracy = *(float*)&flInaccr1;

double fRadius1 = my_flSpreadCurveDensity * flSpread;
double fRadius0 = flRadiusCurveDensity * flInaccuracy;

auto flCosinusTheta1_1 = cosf(theta_1);
auto flCosinusTheta3 = cosf(fTheta3);

auto flSinusTheta1_1 = sinf(theta_1);
auto flSinusTheta3 = sinf(fTheta3);

double y_res_value = (double)(flSinusTheta3 * fRadius0) + (double)(flSinusTheta1_1 * fRadius1);
double x_res_value = (double)(flCosinusTheta3 * fRadius0) + (double)(flCosinusTheta1_1 * fRadius1);
Для того, чтобы компенсировать разброс вы можете сделать обратную калькуляцию к вычислениям из FireBullet для CS2 ( clien.dll "48 89 5C 24 18 48 89 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 90" ). Это я уже подчеркнул с одной старой темы на UC.

C++:
CVector3 vecDirShooting{}, vecRight{}, vecUp{}, vecAntiDir{}, vecAntiSpread{};

g_pMath->AngleVectors(res_vec, vecDirShooting, vecRight, vecUp);
g_pMath->AngleVectors(res_vec, vecDirShooting);

// Making antidirection for spread calcs ref from pseudo:
// vecDir.x = (vecDirShooting.x - (vecRight.x * flSpreadX)) + (vecUp.x * flSpreadY);
vecAntiDir = vecDirShooting + (vecRight * pr_x) - (vecUp * pr_y);
vecAntiDir.NormalizeInPlace();
g_pMath->VectorAngles(vecAntiDir, vecAntiSpread);
Использовать данные вычисления лучше всего, наверное, в хуке для FrameStageNotify, чтобы не ловить разницу для player_render_tick ( т.к. он обновляется каждый кадр, как ни странно ). А теперь о том самом нюансе, о котором я говорил в начале, так как GetRandomSeed синхронизирован вместе с сервером, вычисление разброса происходит только во время выстрела, то есть, если вы измените текущий угол взгляда, и потом выстрелите, значения изменятся и ваш NoSpread будет неверным.

P.s. в моем реверсе нет условий для некоторого типа оружий ( negev, revolver ), но вы всегда можете это сделать сами. Все значения вычисляются правильно ( проверял хукнув тот же FireBullet_CS2, где 13 и 14 аргументами идут как раз spreadX и spreadY соответственно.
 
Keine panik!
Эксперт
Статус
Оффлайн
Регистрация
29 Апр 2020
Сообщения
812
Реакции[?]
417
Поинты[?]
49K
Участник
Статус
Оффлайн
Регистрация
15 Янв 2021
Сообщения
491
Реакции[?]
277
Поинты[?]
67K
На эту смесь псевдокода и говна физически больно смотреть...
Если не считать СИ-шных кастов, за которые готов убивать OXXXYMlRON и парочки непонятных функций, то всё ок :/ Рыться в псевдо коде от вальве, всегда физически больно. И это всё я ещё привёл к более менее читабельному виду.
 
              ru p2cs > all                      
Разработчик
Статус
Оффлайн
Регистрация
19 Авг 2016
Сообщения
1,574
Реакции[?]
1,955
Поинты[?]
125K
g_pWinApi->m_RandomSeed(random_seed + 1);

g_pWinApi->m_RandomFloat(0, 1.f);
g_pWinApi->m_RandomFloat(0.0f, 2.0f * M_PI);
давно в винапи появились экспорты из тиер0? не вижу проблем в смешивании с псевдо, но вот такой смешной нейминг это сильно да
 
Разработчик
Статус
Оффлайн
Регистрация
1 Сен 2018
Сообщения
1,606
Реакции[?]
870
Поинты[?]
111K
Итак, теперь у нас на повестке дня находится вычисление значений для разброса пуль, которые в теории можно использовать, чтобы сделать NoSpread, но есть нюанс и о нём чуть позже. Томить не буду, просто дам код для этого со всеми сигнатурками. Имеются некоторые хард офсеты, но вы можете завести под них сигнатуру, если имеете прямые руки. Код проверялся на локальном сервере, без каких-либо изменений в конварах.

C++:
int64_t pContext;
float unk_val = 0;
int iMode = 1;
// client.dll "48 89 5C 24 08 57 48 83 EC 30 0F 29 74 24 20 45 8B"
BacktrackLocalPlayer((__int64)pLocalWeapon, (__int64)&pContext, unk_val, iMode);

// client.dll "48 81 EC F8 00 00 00 F3 0F 10 09"
// viewangles <- angles when you are shooting
auto random_seed = GetRandomSeed(&viewangles, render_tick);

// init random system with this seed
g_pWinApi->m_RandomSeed(random_seed + 1); 

// Exports from tier0.dll
float flRadiusCurveDensity = g_pWinApi->m_RandomFloat(0, 1.f);
float fTheta3 = g_pWinApi->m_RandomFloat(0.0f, 2.0f * M_PI);
float flSpreadCurveDensity = flRadiusCurveDensity;

// Convar
auto weapon_accuracy_shotgun_spread_patterns = (int64_t)(client_dll + 0x186C930);
// Unknown shit
auto unk_addr3 = (int64_t)(client_dll + 0x1676AF8);

int* pItem = (int*)((int64_t)pLocalWeapon + 0x1090);

using GetWeaponVData_t = __int64(__fastcall*)(__int64);
// client.dll "48 81 EC 38 01 00 00 48 85 C9 75 0A 33 C0 48 81 C4 38 01 00 00 C3 48 89"
auto pWeaponData = GetWeaponData(pItem);
auto nWeaponBullets = *(DWORD*)(pWeaponData + 268);

// client.dll "E8 ?? ?? ?? ?? 48 85 C0 75 E9"
auto v91 = GetConvarValue(weapon_accuracy_shotgun_spread_patterns, -1);
float theta_1;
auto flRecoilIndex = *(float*)((int64_t)pLocalWeapon + 5828);
float my_flSpreadCurveDensity = 0;

if (*v91)
{
    auto v92 = 0 + nWeaponBullets * (int)flRecoilIndex;
    auto v93 = *(int*)(uintptr_t(pItem) + 0x1BA);

    // client.dll "66 89 54 24 10 55 48"
    RandomizeSomeShit((__int64)unk_addr3, v93, iMode, v92, &theta_1, &my_flSpreadCurveDensity);
}

// Just a get spread/inaccuracy values. Too lazy to do it like a vfuncs
float flSpread, flInaccuracy;
auto flSpread1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 2856))((int64_t)pLocalWeapon);
auto flInaccr1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 3216))((int64_t)pLocalWeapon);
flSpread = *(float*)&flSpread1;
flInaccuracy = *(float*)&flInaccr1;

double fRadius1 = my_flSpreadCurveDensity * flSpread;
double fRadius0 = flRadiusCurveDensity * flInaccuracy;

auto flCosinusTheta1_1 = cosf(theta_1);
auto flCosinusTheta3 = cosf(fTheta3);

auto flSinusTheta1_1 = sinf(theta_1);
auto flSinusTheta3 = sinf(fTheta3);

double y_res_value = (double)(flSinusTheta3 * fRadius0) + (double)(flSinusTheta1_1 * fRadius1);
double x_res_value = (double)(flCosinusTheta3 * fRadius0) + (double)(flCosinusTheta1_1 * fRadius1);
Для того, чтобы компенсировать разброс вы можете сделать обратную калькуляцию к вычислениям из FireBullet для CS2 ( clien.dll "48 89 5C 24 18 48 89 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 90" ). Это я уже подчеркнул с одной старой темы на UC.

C++:
CVector3 vecDirShooting{}, vecRight{}, vecUp{}, vecAntiDir{}, vecAntiSpread{};

g_pMath->AngleVectors(res_vec, vecDirShooting, vecRight, vecUp);
g_pMath->AngleVectors(res_vec, vecDirShooting);

// Making antidirection for spread calcs ref from pseudo:
// vecDir.x = (vecDirShooting.x - (vecRight.x * flSpreadX)) + (vecUp.x * flSpreadY);
vecAntiDir = vecDirShooting + (vecRight * pr_x) - (vecUp * pr_y);
vecAntiDir.NormalizeInPlace();
g_pMath->VectorAngles(vecAntiDir, vecAntiSpread);
Использовать данные вычисления лучше всего, наверное, в хуке для FrameStageNotify, чтобы не ловить разницу для player_render_tick ( т.к. он обновляется каждый кадр, как ни странно ). А теперь о том самом нюансе, о котором я говорил в начале, так как GetRandomSeed синхронизирован вместе с сервером, вычисление разброса происходит только во время выстрела, то есть, если вы измените текущий угол взгляда, и потом выстрелите, значения изменятся и ваш NoSpread будет неверным.

P.s. в моем реверсе нет условий для некоторого типа оружий ( negev, revolver ), но вы всегда можете это сделать сами. Все значения вычисляются правильно ( проверял хукнув тот же FireBullet_CS2, где 13 и 14 аргументами идут как раз spreadX и spreadY соответственно.
А в чём прикол темы?
-Давайте заребилдим расчёт сприда, и обратим его
-Бля мужики оказывается получается сприд хэша, и его нельзя обратить так просто, ну короче додумайте сами!!

Но в любом случае, если убрать 90% лишнего мусора отсюда, то получится правильная крупичка знаний, которую и так дал соуфив своим постом
 
Участник
Статус
Оффлайн
Регистрация
15 Янв 2021
Сообщения
491
Реакции[?]
277
Поинты[?]
67K
давно в винапи появились экспорты из тиер0? не вижу проблем в смешивании с псевдо, но вот такой смешной нейминг это сильно да
Ну нейминг ебейший, тут я согласен, а делать ещё один свой крутой класс под экспорты чисто кс посчитал совсем нецелесообразным.
А в чём прикол темы?
-Давайте заребилдим расчёт сприда, и обратим его
-Бля мужики оказывается получается сприд хэша, и его нельзя обратить так просто, ну короче додумайте сами!!

Но в любом случае, если убрать 90% лишнего мусора отсюда, то получится правильная крупичка знаний, которую и так дал соуфив своим постом
Ну я и сам не допёр как делать дальше, потому решил просто выложить здесь, а-ля кто-нибудь додумается или дополнит, что делать дальше.
 
              ru p2cs > all                      
Разработчик
Статус
Оффлайн
Регистрация
19 Авг 2016
Сообщения
1,574
Реакции[?]
1,955
Поинты[?]
125K
А в чём прикол темы?
-Давайте заребилдим расчёт сприда, и обратим его
-Бля мужики оказывается получается сприд хэша, и его нельзя обратить так просто, ну короче додумайте сами!!

Но в любом случае, если убрать 90% лишнего мусора отсюда, то получится правильная крупичка знаний, которую и так дал соуфив своим постом
тема ради темы, зато всякие шизопастеры теперь в ТСе будут видеть пророка и гения, он же в отличии от этих проклятых капиталистов, делится знаниями (пусть и отчасти бесполезными) но зато делится!!!
Ну нейминг ебейший, тут я согласен, а делать ещё один свой крутой класс под экспорты чисто кс посчитал совсем нецелесообразным.
ну сделал бы в математике эти функции, тк это прямое отношение к ней имеет (лично у мя так)
 
Участник
Статус
Оффлайн
Регистрация
15 Янв 2021
Сообщения
491
Реакции[?]
277
Поинты[?]
67K
тема ради темы, зато всякие шизопастеры теперь в ТСе будут видеть пророка и гения
Ну я и сам не допёр как делать дальше, потому решил просто выложить здесь, а-ля кто-нибудь додумается или дополнит, что делать дальше.
Просто, если я думаю не совсем в правильно направлении, ты можешь подсказать, куда своими глазками мне смотреть, может что-то и получится, но дело твоё.

P. s. может звучать как оправдание, но если верить тому же NoSpread'у с ксго ( не застал, точно не знаю ), то вычисление слегка изменились и не подходят, ну и вдруг этот пост кому-то пригодится.
 
              ru p2cs > all                      
Разработчик
Статус
Оффлайн
Регистрация
19 Авг 2016
Сообщения
1,574
Реакции[?]
1,955
Поинты[?]
125K
Просто, если я думаю не совсем в правильно направлении, ты можешь подсказать, куда своими глазками мне смотреть, может что-то и получится, но дело твоё.
это не была к тебе претензия на самом деле, а к шизопастерам которые за каждый подобный пост готовы потом тебя на руках носить. но собсна - вернемся к теме диалога.

я не стану тебе (или кому либо другому) что-то подсказывать потому что в итоге всё это сольётся в паблик, и всякие убогие пастеры вроде нексуса сразу-же пойдут добавлять себе этот функционал. мне это нахуй не нужно, я вообще желаю чтобы подобные проекты сгинули в небытиё куда им и дорога.

если бы был смысл делиться этими знаниями, и не получать в замен слитую на юг/юц пасту - этим бы делились, но увы имеем что имеем.
 
Участник
Статус
Оффлайн
Регистрация
19 Апр 2020
Сообщения
1,165
Реакции[?]
313
Поинты[?]
151K
данный человек делает самые полезные темы на югейме
 
ЧВК EB_LAN
Забаненный
Статус
Оффлайн
Регистрация
12 Сен 2021
Сообщения
425
Реакции[?]
121
Поинты[?]
162K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
давно в винапи появились экспорты из тиер0? не вижу проблем в смешивании с псевдо, но вот такой смешной нейминг это сильно да
неее, ты не понимаешь, у чувака не псевдо, он просто ребилднул винапи и добавил имплементации всех экспортов дллок игры, при этом оставив #include <windows.h>
 
Начинающий
Статус
Оффлайн
Регистрация
14 Июн 2023
Сообщения
155
Реакции[?]
6
Поинты[?]
6K
Итак, теперь у нас на повестке дня находится вычисление значений для разброса пуль, которые в теории можно использовать, чтобы сделать NoSpread, но есть нюанс и о нём чуть позже. Томить не буду, просто дам код для этого со всеми сигнатурками. Имеются некоторые хард офсеты, но вы можете завести под них сигнатуру, если имеете прямые руки. Код проверялся на локальном сервере, без каких-либо изменений в конварах.

C++:
int64_t pContext;
float unk_val = 0;
int iMode = 1;
// client.dll "48 89 5C 24 08 57 48 83 EC 30 0F 29 74 24 20 45 8B"
BacktrackLocalPlayer((__int64)pLocalWeapon, (__int64)&pContext, unk_val, iMode);

// client.dll "48 81 EC F8 00 00 00 F3 0F 10 09"
// viewangles <- angles when you are shooting
auto random_seed = GetRandomSeed(&viewangles, render_tick);

// init random system with this seed
g_pWinApi->m_RandomSeed(random_seed + 1);  

// Exports from tier0.dll
float flRadiusCurveDensity = g_pWinApi->m_RandomFloat(0, 1.f);
float fTheta3 = g_pWinApi->m_RandomFloat(0.0f, 2.0f * M_PI);
float flSpreadCurveDensity = flRadiusCurveDensity;

// Convar
auto weapon_accuracy_shotgun_spread_patterns = (int64_t)(client_dll + 0x186C930);
// Unknown shit
auto unk_addr3 = (int64_t)(client_dll + 0x1676AF8);

int* pItem = (int*)((int64_t)pLocalWeapon + 0x1090);

using GetWeaponVData_t = __int64(__fastcall*)(__int64);
// client.dll "48 81 EC 38 01 00 00 48 85 C9 75 0A 33 C0 48 81 C4 38 01 00 00 C3 48 89"
auto pWeaponData = GetWeaponData(pItem);
auto nWeaponBullets = *(DWORD*)(pWeaponData + 268);

// client.dll "E8 ?? ?? ?? ?? 48 85 C0 75 E9"
auto v91 = GetConvarValue(weapon_accuracy_shotgun_spread_patterns, -1);
float theta_1;
auto flRecoilIndex = *(float*)((int64_t)pLocalWeapon + 5828);
float my_flSpreadCurveDensity = 0;

if (*v91)
{
    auto v92 = 0 + nWeaponBullets * (int)flRecoilIndex;
    auto v93 = *(int*)(uintptr_t(pItem) + 0x1BA);

    // client.dll "66 89 54 24 10 55 48"
    RandomizeSomeShit((__int64)unk_addr3, v93, iMode, v92, &theta_1, &my_flSpreadCurveDensity);
}

// Just a get spread/inaccuracy values. Too lazy to do it like a vfuncs
float flSpread, flInaccuracy;
auto flSpread1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 2856))((int64_t)pLocalWeapon);
auto flInaccr1 = (*(double(__fastcall**)(__int64))((*(int64_t*)pLocalWeapon) + 3216))((int64_t)pLocalWeapon);
flSpread = *(float*)&flSpread1;
flInaccuracy = *(float*)&flInaccr1;

double fRadius1 = my_flSpreadCurveDensity * flSpread;
double fRadius0 = flRadiusCurveDensity * flInaccuracy;

auto flCosinusTheta1_1 = cosf(theta_1);
auto flCosinusTheta3 = cosf(fTheta3);

auto flSinusTheta1_1 = sinf(theta_1);
auto flSinusTheta3 = sinf(fTheta3);

double y_res_value = (double)(flSinusTheta3 * fRadius0) + (double)(flSinusTheta1_1 * fRadius1);
double x_res_value = (double)(flCosinusTheta3 * fRadius0) + (double)(flCosinusTheta1_1 * fRadius1);
Для того, чтобы компенсировать разброс вы можете сделать обратную калькуляцию к вычислениям из FireBullet для CS2 ( clien.dll "48 89 5C 24 18 48 89 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 90" ). Это я уже подчеркнул с одной старой темы на UC.

C++:
CVector3 vecDirShooting{}, vecRight{}, vecUp{}, vecAntiDir{}, vecAntiSpread{};

g_pMath->AngleVectors(res_vec, vecDirShooting, vecRight, vecUp);
g_pMath->AngleVectors(res_vec, vecDirShooting);

// Making antidirection for spread calcs ref from pseudo:
// vecDir.x = (vecDirShooting.x - (vecRight.x * flSpreadX)) + (vecUp.x * flSpreadY);
vecAntiDir = vecDirShooting + (vecRight * pr_x) - (vecUp * pr_y);
vecAntiDir.NormalizeInPlace();
g_pMath->VectorAngles(vecAntiDir, vecAntiSpread);
Использовать данные вычисления лучше всего, наверное, в хуке для FrameStageNotify, чтобы не ловить разницу для player_render_tick ( т.к. он обновляется каждый кадр, как ни странно ). А теперь о том самом нюансе, о котором я говорил в начале, так как GetRandomSeed синхронизирован вместе с сервером, вычисление разброса происходит только во время выстрела, то есть, если вы измените текущий угол взгляда, и потом выстрелите, значения изменятся и ваш NoSpread будет неверным.

P.s. в моем реверсе нет условий для некоторого типа оружий ( negev, revolver ), но вы всегда можете это сделать сами. Все значения вычисляются правильно ( проверял хукнув тот же FireBullet_CS2, где 13 и 14 аргументами идут как раз spreadX и spreadY соответственно.
спасибо
 
Сверху Снизу