sg
-
Автор темы
- #1
Итак, теперь у нас на повестке дня находится вычисление значений для разброса пуль, которые в теории можно использовать, чтобы сделать NoSpread, но есть нюанс и о нём чуть позже. Томить не буду, просто дам код для этого со всеми сигнатурками. Имеются некоторые хард офсеты, но вы можете завести под них сигнатуру, если имеете прямые руки. Код проверялся на локальном сервере, без каких-либо изменений в конварах.
Для того, чтобы компенсировать разброс вы можете сделать обратную калькуляцию к вычислениям из 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.
Использовать данные вычисления лучше всего, наверное, в хуке для FrameStageNotify, чтобы не ловить разницу для player_render_tick ( т.к. он обновляется каждый кадр, как ни странно ). А теперь о том самом нюансе, о котором я говорил в начале, так как GetRandomSeed синхронизирован вместе с сервером, вычисление разброса происходит только во время выстрела, то есть, если вы измените текущий угол взгляда, и потом выстрелите, значения изменятся и ваш NoSpread будет неверным.
P.s. в моем реверсе нет условий для некоторого типа оружий ( negev, revolver ), но вы всегда можете это сделать сами. Все значения вычисляются правильно ( проверял хукнув тот же FireBullet_CS2, где 13 и 14 аргументами идут как раз spreadX и spreadY соответственно.
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);
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);
P.s. в моем реверсе нет условий для некоторого типа оружий ( negev, revolver ), но вы всегда можете это сделать сами. Все значения вычисляются правильно ( проверял хукнув тот же FireBullet_CS2, где 13 и 14 аргументами идут как раз spreadX и spreadY соответственно.