You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
456 lines
11 KiB
C++
456 lines
11 KiB
C++
#include "prediction.h"
|
|
|
|
extern Memory apex_mem;
|
|
|
|
extern bool firing_range;
|
|
float smooth = 12.0f;
|
|
bool aim_no_recoil = true;
|
|
int bone = 2;
|
|
|
|
// https://github.com/Gerosity/zap-client/blob/master/Core/Player.hpp#L161
|
|
bool Entity::Observing(uint64_t localptr)
|
|
{
|
|
uint64_t SpectatorList;
|
|
apex_mem.Read<uint64_t>(apex_mem.get_proc_baseaddr() + OFFSET_OBSERVER_LIST, SpectatorList);
|
|
|
|
int PlayerData;
|
|
apex_mem.Read<int>(ptr + 0x38, PlayerData);
|
|
|
|
int SpecIndex;
|
|
apex_mem.Read<int>(SpectatorList + PlayerData * 8 + 0x964, SpecIndex);
|
|
|
|
uint64_t SpectatorAddr;
|
|
apex_mem.Read<uint64_t>(apex_mem.get_proc_baseaddr() + OFFSET_ENTITYLIST + ((SpecIndex & 0xFFFF) << 5), SpectatorAddr);
|
|
|
|
if (SpectatorAddr == localptr)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//https://github.com/CasualX/apexbot/blob/master/src/state.cpp#L104
|
|
void get_class_name(uint64_t entity_ptr, char* out_str)
|
|
{
|
|
uint64_t client_networkable_vtable;
|
|
apex_mem.Read<uint64_t>(entity_ptr + 8 * 3, client_networkable_vtable);
|
|
|
|
uint64_t get_client_class;
|
|
apex_mem.Read<uint64_t>(client_networkable_vtable + 8 * 3, get_client_class);
|
|
|
|
uint32_t disp;
|
|
apex_mem.Read<uint32_t>(get_client_class + 3, disp);
|
|
const uint64_t client_class_ptr = get_client_class + disp + 7;
|
|
|
|
ClientClass client_class;
|
|
apex_mem.Read<ClientClass>(client_class_ptr, client_class);
|
|
|
|
apex_mem.ReadArray<char>(client_class.pNetworkName, out_str, 32);
|
|
}
|
|
|
|
void charge_rifle_hack(uint64_t entity_ptr)
|
|
{
|
|
extern uint64_t g_Base;
|
|
extern bool shooting;
|
|
WeaponXEntity curweap = WeaponXEntity();
|
|
curweap.update(entity_ptr);
|
|
float BulletSpeed = curweap.get_projectile_speed();
|
|
int ammo = curweap.get_ammo();
|
|
|
|
if (ammo != 0 && BulletSpeed == 1 && shooting)
|
|
{
|
|
apex_mem.Write<float>(g_Base + OFFSET_TIMESCALE + 0x68, std::numeric_limits<float>::min());
|
|
}
|
|
else
|
|
{
|
|
apex_mem.Write<float>(g_Base + OFFSET_TIMESCALE + 0x68, 1.f);
|
|
}
|
|
}
|
|
|
|
int Entity::getTeamId()
|
|
{
|
|
return *(int*)(buffer + OFFSET_TEAM);
|
|
}
|
|
|
|
int Entity::getHealth()
|
|
{
|
|
return *(int*)(buffer + OFFSET_HEALTH);
|
|
}
|
|
|
|
int Entity::getShield()
|
|
{
|
|
return *(int*)(buffer + OFFSET_SHIELD);
|
|
}
|
|
|
|
Vector Entity::getAbsVelocity()
|
|
{
|
|
return *(Vector*)(buffer + OFFSET_ABS_VELOCITY);
|
|
}
|
|
|
|
Vector Entity::getPosition()
|
|
{
|
|
return *(Vector*)(buffer + OFFSET_ORIGIN);
|
|
}
|
|
|
|
bool Entity::isPlayer()
|
|
{
|
|
return *(uint64_t*)(buffer + OFFSET_NAME) == 125780153691248;
|
|
}
|
|
|
|
bool Entity::isDummy()
|
|
{
|
|
char class_name[33] = {};
|
|
get_class_name(ptr, class_name);
|
|
|
|
return strncmp(class_name, "CAI_BaseNPC", 11) == 0;
|
|
}
|
|
|
|
bool Entity::isKnocked()
|
|
{
|
|
return *(int*)(buffer + OFFSET_BLEED_OUT_STATE) > 0;
|
|
}
|
|
|
|
bool Entity::isAlive()
|
|
{
|
|
return *(int*)(buffer + OFFSET_LIFE_STATE) == 0;
|
|
}
|
|
|
|
float Entity::lastVisTime()
|
|
{
|
|
return *(float*)(buffer + OFFSET_VISIBLE_TIME);
|
|
}
|
|
|
|
Vector Entity::getBonePosition(int id)
|
|
{
|
|
Vector position = getPosition();
|
|
uintptr_t boneArray = *(uintptr_t*)(buffer + OFFSET_BONES);
|
|
Vector bone = Vector();
|
|
uint32_t boneloc = (id * 0x30);
|
|
Bone bo = {};
|
|
apex_mem.Read<Bone>(boneArray + boneloc, bo);
|
|
bone.x = bo.x + position.x;
|
|
bone.y = bo.y + position.y;
|
|
bone.z = bo.z + position.z;
|
|
return bone;
|
|
}
|
|
|
|
//https://www.unknowncheats.me/forum/apex-legends/496984-getting-hitbox-positions-cstudiohdr-externally.html
|
|
//https://www.unknowncheats.me/forum/3499185-post1334.html
|
|
//https://www.unknowncheats.me/forum/3562047-post11000.html
|
|
Vector Entity::getBonePositionByHitbox(int id)
|
|
{
|
|
Vector origin = getPosition();
|
|
|
|
//BoneByHitBox
|
|
uint64_t Model = *(uint64_t*)(buffer + OFFSET_STUDIOHDR);
|
|
|
|
//get studio hdr
|
|
uint64_t StudioHdr;
|
|
apex_mem.Read<uint64_t>(Model + 0x8, StudioHdr);
|
|
|
|
//get hitbox array
|
|
uint16_t HitboxCache;
|
|
apex_mem.Read<uint16_t>(StudioHdr + 0x34, HitboxCache);
|
|
uint64_t HitBoxsArray = StudioHdr + ((uint16_t)(HitboxCache & 0xFFFE) << (4 * (HitboxCache & 1)));
|
|
|
|
uint16_t IndexCache;
|
|
apex_mem.Read<uint16_t>(HitBoxsArray + 0x4, IndexCache);
|
|
int HitboxIndex = ((uint16_t)(IndexCache & 0xFFFE) << (4 * (IndexCache & 1)));
|
|
|
|
uint16_t Bone;
|
|
apex_mem.Read<uint16_t>(HitBoxsArray + HitboxIndex + (id * 0x20), Bone);
|
|
|
|
if(Bone < 0 || Bone > 255)
|
|
return Vector();
|
|
|
|
//hitpos
|
|
uint64_t BoneArray = *(uint64_t*)(buffer + OFFSET_BONES);
|
|
|
|
matrix3x4_t Matrix = {};
|
|
apex_mem.Read<matrix3x4_t>(BoneArray + Bone * sizeof(matrix3x4_t), Matrix);
|
|
|
|
return Vector(Matrix.m_flMatVal[0][3] + origin.x, Matrix.m_flMatVal[1][3] + origin.y, Matrix.m_flMatVal[2][3] + origin.z);
|
|
}
|
|
|
|
QAngle Entity::GetSwayAngles()
|
|
{
|
|
return *(QAngle*)(buffer + OFFSET_BREATH_ANGLES);
|
|
}
|
|
|
|
QAngle Entity::GetViewAngles()
|
|
{
|
|
return *(QAngle*)(buffer + OFFSET_VIEWANGLES);
|
|
}
|
|
|
|
Vector Entity::GetViewAnglesV()
|
|
{
|
|
return *(Vector*)(buffer + OFFSET_VIEWANGLES);
|
|
}
|
|
|
|
float Entity::GetYaw()
|
|
{
|
|
float yaw = 0;
|
|
apex_mem.Read<float>(ptr + OFFSET_YAW, yaw);
|
|
|
|
if (yaw < 0)
|
|
yaw += 360;
|
|
yaw += 90;
|
|
if (yaw > 360)
|
|
yaw -= 360;
|
|
|
|
return yaw;
|
|
}
|
|
|
|
bool Entity::isGlowing()
|
|
{
|
|
return *(int*)(buffer + OFFSET_GLOW_ENABLE) == 7;
|
|
}
|
|
|
|
bool Entity::isZooming()
|
|
{
|
|
return *(int*)(buffer + OFFSET_ZOOMING) == 1;
|
|
}
|
|
|
|
void Entity::enableGlow()
|
|
{
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_T1, 16256);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_T2, 1193322764);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_ENABLE, 7);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_THROUGH_WALLS, 2);
|
|
}
|
|
|
|
void Entity::disableGlow()
|
|
{
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_T1, 0);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_T2, 0);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_ENABLE, 2);
|
|
apex_mem.Write<int>(ptr + OFFSET_GLOW_THROUGH_WALLS, 5);
|
|
}
|
|
|
|
void Entity::SetViewAngles(SVector angles)
|
|
{
|
|
apex_mem.Write<SVector>(ptr + OFFSET_VIEWANGLES, angles);
|
|
}
|
|
|
|
void Entity::SetViewAngles(QAngle& angles)
|
|
{
|
|
SetViewAngles(SVector(angles));
|
|
}
|
|
|
|
Vector Entity::GetCamPos()
|
|
{
|
|
return *(Vector*)(buffer + OFFSET_CAMERAPOS);
|
|
}
|
|
|
|
QAngle Entity::GetRecoil()
|
|
{
|
|
return *(QAngle*)(buffer + OFFSET_AIMPUNCH);
|
|
}
|
|
|
|
void Entity::get_name(uint64_t g_Base, uint64_t index, char* name)
|
|
{
|
|
index *= 0x10;
|
|
uint64_t name_ptr = 0;
|
|
apex_mem.Read<uint64_t>(g_Base + OFFSET_NAME_LIST + index, name_ptr);
|
|
apex_mem.ReadArray<char>(name_ptr, name, 32);
|
|
}
|
|
|
|
bool Item::isItem()
|
|
{
|
|
char class_name[33] = {};
|
|
get_class_name(ptr, class_name);
|
|
|
|
return strncmp(class_name, "CPropSurvival", 13) == 0;
|
|
}
|
|
|
|
bool Item::isGlowing()
|
|
{
|
|
return *(int*)(buffer + OFFSET_ITEM_GLOW) == 1363184265;
|
|
}
|
|
|
|
void Item::enableGlow()
|
|
{
|
|
apex_mem.Write<int>(ptr + OFFSET_ITEM_GLOW, 1363184265);
|
|
}
|
|
|
|
void Item::disableGlow()
|
|
{
|
|
apex_mem.Write<int>(ptr + OFFSET_ITEM_GLOW, 1411417991);
|
|
}
|
|
|
|
Vector Item::getPosition()
|
|
{
|
|
return *(Vector*)(buffer + OFFSET_ORIGIN);
|
|
}
|
|
|
|
float CalculateFov(Entity& from, Entity& target)
|
|
{
|
|
QAngle ViewAngles = from.GetViewAngles();
|
|
Vector LocalCamera = from.GetCamPos();
|
|
Vector EntityPosition = target.getPosition();
|
|
QAngle Angle = Math::CalcAngle(LocalCamera, EntityPosition);
|
|
return Math::GetFov(ViewAngles, Angle);
|
|
}
|
|
|
|
QAngle CalculateBestBoneAim(Entity& from, uintptr_t t, float max_fov)
|
|
{
|
|
Entity target = getEntity(t);
|
|
if(firing_range)
|
|
{
|
|
if (!target.isAlive())
|
|
{
|
|
return QAngle(0, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!target.isAlive() || target.isKnocked())
|
|
{
|
|
return QAngle(0, 0, 0);
|
|
}
|
|
}
|
|
|
|
Vector LocalCamera = from.GetCamPos();
|
|
Vector TargetBonePosition = target.getBonePositionByHitbox(bone);
|
|
QAngle CalculatedAngles = QAngle(0, 0, 0);
|
|
|
|
WeaponXEntity curweap = WeaponXEntity();
|
|
curweap.update(from.ptr);
|
|
float BulletSpeed = curweap.get_projectile_speed();
|
|
float BulletGrav = curweap.get_projectile_gravity();
|
|
float zoom_fov = curweap.get_zoom_fov();
|
|
|
|
if (zoom_fov != 0.0f && zoom_fov != 1.0f)
|
|
{
|
|
max_fov *= zoom_fov/90.0f;
|
|
}
|
|
|
|
/*
|
|
//simple aim prediction
|
|
if (BulletSpeed > 1.f)
|
|
{
|
|
Vector LocalBonePosition = from.getBonePosition(bone);
|
|
float VerticalTime = TargetBonePosition.DistTo(LocalBonePosition) / BulletSpeed;
|
|
TargetBonePosition.z += (BulletGrav * 0.5f) * (VerticalTime * VerticalTime);
|
|
|
|
float HorizontalTime = TargetBonePosition.DistTo(LocalBonePosition) / BulletSpeed;
|
|
TargetBonePosition += (target.getAbsVelocity() * HorizontalTime);
|
|
}
|
|
*/
|
|
|
|
//more accurate prediction
|
|
if (BulletSpeed > 1.f)
|
|
{
|
|
PredictCtx Ctx;
|
|
Ctx.StartPos = LocalCamera;
|
|
Ctx.TargetPos = TargetBonePosition;
|
|
Ctx.BulletSpeed = BulletSpeed - (BulletSpeed*0.08);
|
|
Ctx.BulletGravity = BulletGrav + (BulletGrav*0.05);
|
|
Ctx.TargetVel = target.getAbsVelocity();
|
|
|
|
if (BulletPredict(Ctx))
|
|
CalculatedAngles = QAngle{Ctx.AimAngles.x, Ctx.AimAngles.y, 0.f};
|
|
}
|
|
|
|
if (CalculatedAngles == QAngle(0, 0, 0))
|
|
CalculatedAngles = Math::CalcAngle(LocalCamera, TargetBonePosition);
|
|
QAngle ViewAngles = from.GetViewAngles();
|
|
QAngle SwayAngles = from.GetSwayAngles();
|
|
//remove sway and recoil
|
|
if(aim_no_recoil)
|
|
CalculatedAngles-=SwayAngles-ViewAngles;
|
|
Math::NormalizeAngles(CalculatedAngles);
|
|
QAngle Delta = CalculatedAngles - ViewAngles;
|
|
double fov = Math::GetFov(SwayAngles, CalculatedAngles);
|
|
if (fov > max_fov)
|
|
{
|
|
return QAngle(0, 0, 0);
|
|
}
|
|
|
|
Math::NormalizeAngles(Delta);
|
|
|
|
QAngle SmoothedAngles = ViewAngles + Delta/smooth;
|
|
return SmoothedAngles;
|
|
}
|
|
|
|
Entity getEntity(uintptr_t ptr)
|
|
{
|
|
Entity entity = Entity();
|
|
entity.ptr = ptr;
|
|
apex_mem.ReadArray<uint8_t>(ptr, entity.buffer, sizeof(entity.buffer));
|
|
return entity;
|
|
}
|
|
|
|
Item getItem(uintptr_t ptr)
|
|
{
|
|
Item entity = Item();
|
|
entity.ptr = ptr;
|
|
apex_mem.ReadArray<uint8_t>(ptr, entity.buffer, sizeof(entity.buffer));
|
|
return entity;
|
|
}
|
|
|
|
bool WorldToScreen(Vector from, float* m_vMatrix, int targetWidth, int targetHeight, Vector& to)
|
|
{
|
|
float w = m_vMatrix[12] * from.x + m_vMatrix[13] * from.y + m_vMatrix[14] * from.z + m_vMatrix[15];
|
|
|
|
if (w < 0.01f) return false;
|
|
|
|
to.x = m_vMatrix[0] * from.x + m_vMatrix[1] * from.y + m_vMatrix[2] * from.z + m_vMatrix[3];
|
|
to.y = m_vMatrix[4] * from.x + m_vMatrix[5] * from.y + m_vMatrix[6] * from.z + m_vMatrix[7];
|
|
|
|
float invw = 1.0f / w;
|
|
to.x *= invw;
|
|
to.y *= invw;
|
|
|
|
float x = targetWidth / 2;
|
|
float y = targetHeight / 2;
|
|
|
|
x += 0.5 * to.x * targetWidth + 0.5;
|
|
y -= 0.5 * to.y * targetHeight + 0.5;
|
|
|
|
to.x = x;
|
|
to.y = y;
|
|
to.z = 0;
|
|
return true;
|
|
}
|
|
|
|
void WeaponXEntity::update(uint64_t LocalPlayer)
|
|
{
|
|
extern uint64_t g_Base;
|
|
uint64_t entitylist = g_Base + OFFSET_ENTITYLIST;
|
|
uint64_t wephandle = 0;
|
|
apex_mem.Read<uint64_t>(LocalPlayer + OFFSET_WEAPON, wephandle);
|
|
|
|
wephandle &= 0xffff;
|
|
|
|
uint64_t wep_entity = 0;
|
|
apex_mem.Read<uint64_t>(entitylist + (wephandle << 5), wep_entity);
|
|
|
|
projectile_speed = 0;
|
|
apex_mem.Read<float>(wep_entity + OFFSET_BULLET_SPEED, projectile_speed);
|
|
projectile_scale = 0;
|
|
apex_mem.Read<float>(wep_entity + OFFSET_BULLET_SCALE, projectile_scale);
|
|
zoom_fov = 0;
|
|
apex_mem.Read<float>(wep_entity + OFFSET_ZOOM_FOV, zoom_fov);
|
|
ammo = 0;
|
|
apex_mem.Read<int>(wep_entity + OFFSET_AMMO, ammo);
|
|
}
|
|
|
|
float WeaponXEntity::get_projectile_speed()
|
|
{
|
|
return projectile_speed;
|
|
}
|
|
|
|
float WeaponXEntity::get_projectile_gravity()
|
|
{
|
|
return 750.0f * projectile_scale;
|
|
}
|
|
|
|
float WeaponXEntity::get_zoom_fov()
|
|
{
|
|
return zoom_fov;
|
|
}
|
|
|
|
int WeaponXEntity::get_ammo()
|
|
{
|
|
return ammo;
|
|
}
|