Code:
DWORD _BG_GetWeaponDef = 0x00529FF0;
DWORD _BG_GetSpreadForWeapon = 0x0047DE70;
DWORD _CG_GetPlayerViewOrigin = 0x004E7470;
DWORD _GetSpreadEndVec = 0x007FC040;
DWORD clients = 0x00E67C80; // clientActive_t struct
int* currentCmdNum = 0x00EABEE8;
int GetCurrentWeapon()
{
return *(short*)((int)cgArray + 263836 + 324); // "Player is holding" string
}
int BG_GetWeaponDef(int weapon)
{
DWORD result = 0;
__asm
{
push weapon
_BG_GetWeaponDef
mov result,eax
add esp,04h
}
return result;
}
void BG_GetSpreadForWeapon(int playerStatePtr, int weaponDefPtr, float* minSpreadOut, float* maxSpreadOut)
{
// WARNING: Use _fxsave and _fxrstor if your XMM
// registers screw up
__asm
{
push maxSpreadOut
push minSpreadOut
push weaponDefPtr
push playerStatePtr
call _BG_GetSpreadForWeapon
add esp,10h
}
}
int CG_GetPlayerViewOrigin(int localClientNum, int playerStatePtr, pvec3_t vecOut)
{
DWORD result = 0;
__asm
{
push vecOut
push playerStatePtr
push localClientNum
call _CG_GetPlayerViewOrigin
mov result,eax
add esp,0Ch
}
return result;
}
void GetSpreadEndVec(pvec3_t viewOrigin, pvec3_t spreadEndVecOut, float spread, int commandTime, pvec3_t spreadDirectionOut, pvec3_t forward, pvec3_t right, pvec3_t up, float range)
{
__asm
{
push range
push up
push right
push forward
push spreadDirectionOut
push commandTime
movss xmm0,spread
mov esi,spreadEndVecOut
mov edi,viewOrigin
call _GetSpreadEndVec
add esp,18h
}
}
usercmd_s* CL_GetUserCmd(int cmdNum)
{
return (usercmd_s*)((int)clients + 272488 + sizeof(usercmd_s) * (cmdNum & 0x7F));
}
int CL_GetCurrentCmdNumber()
{
return *currentCmdNum;
}
void NoSpread()
{
// get playerState_s struct
int playerStatePtr = (int)cgArray + 263836;
// get weaponDef struct and our starting spread float value
float spread;
int weaponDefPtr = BG_GetWeaponDef(GetCurrentWeapon());
spread = *(float*)((int)cgArray + 457488) / 255.0f;
// get final spread float value
float minSpread, maxSpread;
BG_GetSpreadForWeapon(playerStatePtr, weaponDefPtr, &minSpread, &maxSpread);
if (*(float*)(playerStatePtr + 360) == 1.0f) // if (fWeaponPosFrac == 1.0f) get minSpread from weaponDef
spread = *(float*)(weaponDefPtr + 1736) + ((maxSpread - *(float*)(weaponDefPtr + 1736)) * spread);
else
spread = minSpread + ((maxSpread - minSpread) * spread);
// get our view origin
vec3_t viewOrigin;
if (!CG_GetPlayerViewOrigin(0, playerStatePtr, viewOrigin))
return;
// get our view axis
vec3_t viewAngles;
vec3_t viewAxis[3];
if (*(int*)((int)cgArray + 263832)) // renderingThirdPerson
{
AngleVectors((float*)((int)cgArray + 390792 + sizeof(clientInfo_t) * cgArray->clientNum), viewAxis[0], viewAxis[1], viewAxis[2]);
}
else
{
viewAngles[0] = *(float*)((int)cgArray + 389012);
viewAngles[1] = *(float*)((int)cgArray + 389016);
viewAngles[2] = 0;
AngleVectors(viewAngles, viewAxis[0], viewAxis[1], viewAxis[2]);
}
// get the range
float range;
if (*(int*)(weaponDefPtr + 32) == 3) // if (weapClass == WEAPCLASS_SPREAD)
range = *(float*)(weaponDefPtr + 1964); // range = fMinDamageRange; (probably for shotguns)
else
range = 8192.0f; // from bulletrange dvar
// NOTE: you can't do 100% no spread with shotguns, because you can only fix 1 bullet at a time
// get the end vector in the game world of the spread and the direction vector too
// we use the direction vector directly instead of the end vector
vec3_t spreadEndVec;
vec3_t spreadDirection;
GetSpreadEndVec(viewOrigin, spreadEndVec, spread, *(int*)playerStatePtr, spreadDirection, viewAxis[0], viewAxis[1], viewAxis[2], range);
// convert the spread direction to angles
vectoangles(spreadDirection, viewAngles);
// fix our angles
usercmd_s* oldcmd = CL_GetUserCmd(CL_GetCurrentCmdNumber() - 1);
// get the angle delta and write it to the user cmd
// do -= because we want to get the inverse of the spread
oldcmd->angles[0] -= ANGLE2SHORT(-(*(float*)((int)cgArray + 389012) - viewAngles[0]));
oldcmd->angles[1] -= ANGLE2SHORT(-(*(float*)((int)cgArray + 389016) - viewAngles[1]));
oldcmd->serverTime += 1;
}
Author says that you're doing something wrong if your no spread isn't as accurate as this: