Keep Ev0lving, Stay Fatal
-
Автор темы
- #1
В общем, я действительно старался поработать над этим.
Этот хитшанс до сих пор не аккуратен до конца.
hit_chance.cpp:
hit_chance.h:
База хитшанса была взята из fatality, millionware и moneybot.
Дополнена немного из rifk, enrage и pandora-legacy.
Что скажите о нём?
Этот хитшанс до сих пор не аккуратен до конца.
hit_chance.cpp:
C++:
#include "../features.hpp"
#include "../animations/lagcomp.h"
void hit_chance::build_seed_table() {
constexpr float pi_2 = 2.0f * (float)M_PI;
for (size_t i = 0; i < 256; ++i) {
math::random_seed(i);
const float rand_a = math::random_float(0.0f, 1.0f);
const float rand_pi_a = math::random_float(0.0f, pi_2);
const float rand_b = math::random_float(0.0f, 1.0f);
const float rand_pi_b = math::random_float(0.0f, pi_2);
hit_chance_records[i] = {
{ rand_a, rand_b },
{ std::cos(rand_pi_a), std::sin(rand_pi_a) },
{ std::cos(rand_pi_b), std::sin(rand_pi_b) }
};
}
}
bool hit_chance::intersects_bb_hitbox(vec3_t start, vec3_t delta, vec3_t min, vec3_t max) {
float d1, d2, f;
auto start_solid = true;
auto t1 = -1.0, t2 = 1.0;
const float _start[3] = { start.x, start.y, start.z };
const float _delta[3] = { delta.x, delta.y, delta.z };
const float mins[3] = { min.x, min.y, min.z };
const float maxs[3] = { max.x, max.y, max.z };
for (auto i = 0; i < 6; ++i) {
if (i >= 3) {
const auto j = (i - 3);
d1 = _start[j] - maxs[j];
d2 = d1 + _delta[j];
}
else {
d1 = -_start[i] + mins[i];
d2 = d1 - _delta[i];
}
if (d1 > 0 && d2 > 0) {
start_solid = false;
return false;
}
if (d1 <= 0 && d2 <= 0)
continue;
if (d1 > 0)
start_solid = false;
if (d1 > d2) {
f = d1;
if (f < 0)
f = 0;
f /= d1 - d2;
if (f > t1)
t1 = f;
}
else {
f = d1 / (d1 - d2);
if (f < t2)
t2 = f;
}
}
return start_solid || (t1 < t2&& t1 >= 0.0f);
}
bool __vectorcall hit_chance::intersects_hitbox(vec3_t eye_pos, vec3_t end_pos, vec3_t min, vec3_t max, float radius) {
auto dist = math::dist_segment_to_segment(eye_pos, end_pos, min, max);
return (dist < radius);
}
std::vector<hit_chance::hitbox_data_t> hit_chance::get_hitbox_data(C_LagRecord& log, int hitbox) {
std::vector<hitbox_data_t> hitbox_data;
BaseEntity* target = interfaces::entity_list->get < BaseEntity >(log.m_nEntIndex);
const auto model = target->GetClientRenderable()->GetModel();
if (!model)
return {};
const auto hdr = interfaces::model_info->get_studio_model(model);
if (!hdr)
return {};
const auto set = hdr->hitbox_set(target->HitboxSet());
if (!set)
return {};
std::array<matrix_t, 256> bone_matrix = log.m_Matricies[log.m_RotationMode];
vec3_t min, max;
if (hitbox == -1) {
for (int i = 0; i < set->hitbox_count; ++i) {
const auto box = set->hitbox(i);
if (!box)
continue;
float radius = box->radius;
const auto is_capsule = radius != -1.f;
if (is_capsule) {
math::transform_vector(box->mins, bone_matrix[box->bone], min);
math::transform_vector(box->maxs, bone_matrix[box->bone], max);
}
else {
math::transform_vector(math::vector_rotate(box->mins, box->rotation), bone_matrix[box->bone], min);
math::transform_vector(math::vector_rotate(box->maxs, box->rotation), bone_matrix[box->bone], max);
radius = min.distance_to(max);
}
hitbox_data.emplace_back(hitbox_data_t{ min, max, radius, box, box->bone, box->rotation });
}
}
else {
const auto box = set->hitbox(hitbox);
if (!box)
return {};
float radius = box->radius;
const auto is_capsule = radius != -1.f;
if (is_capsule) {
math::transform_vector(box->mins, bone_matrix[box->bone], min);
math::transform_vector(box->maxs, bone_matrix[box->bone], max);
}
else {
math::transform_vector(math::vector_rotate(box->mins, box->rotation), bone_matrix[box->bone], min);
math::transform_vector(math::vector_rotate(box->maxs, box->rotation), bone_matrix[box->bone], max);
radius = min.distance_to(max);
}
hitbox_data.emplace_back(hitbox_data_t{ min, max, radius, box, box->bone, box->rotation });
}
return hitbox_data;
}
vec3_t hit_chance::get_spread_direction(BaseWeapon* weapon, vec3_t angles, int seed) {
if (!weapon)
return vec3_t();
const int rnsd = (seed & 0xFF);
const auto* data = &hit_chance_records[rnsd];
if (!data)
return vec3_t();
float rand_a = data->random[0];
float rand_b = data->random[1];
if (weapon->ItemDefinitionIndex() == WEAPON_NEGEV) {
auto weapon_info = weapon ? interfaces::weapon_system->get_weapon_data(weapon->ItemDefinitionIndex()) : nullptr;
if (weapon_info && weapon_info->weapon_recoil_seed < 3) {
rand_a = 1.0f - std::pow(rand_a, static_cast<float>(3 - weapon_info->weapon_recoil_seed + 1));
rand_b = 1.0f - std::pow(rand_b, static_cast<float>(3 - weapon_info->weapon_recoil_seed + 1));
}
}
const float rand_inaccuracy = rand_a * prediction.flInaccuracy;
const float rand_spread = rand_b * prediction.flSpread;
const float spread_x = data->inaccuracy[0] * rand_inaccuracy + data->spread[0] * rand_spread;
const float spread_y = data->inaccuracy[1] * rand_inaccuracy + data->spread[1] * rand_spread;
vec3_t forward, right, up;
math::angle_vectors(angles, &forward, &right, &up);
return forward + right * spread_x + up * spread_y;
}
bool hit_chance::can_intersect_hitbox(const vec3_t start, const vec3_t end, vec3_t spread_dir, C_LagRecord& log, int hitbox)
{
const auto hitbox_data = get_hitbox_data(log, hitbox);
if (hitbox_data.empty())
return false;
auto intersected = false;
vec3_t delta;
vec3_t start_scaled;
for (const auto& it : hitbox_data) {
const auto is_capsule = it.m_radius != -1.f;
if (!is_capsule) {
math::vector_i_transform(start, log.m_Matricies[log.m_RotationMode][it.m_bone], start_scaled);
math::vector_i_rotate(spread_dir * 8192.f, log.m_Matricies[log.m_RotationMode][it.m_bone], delta);
if (intersects_bb_hitbox(start_scaled, delta, it.m_min, it.m_max)) {
intersected = true;
break; //note - AkatsukiSun: cannot hit more than one hitbox.
}
}
else if (intersects_hitbox(start, end, it.m_min, it.m_max, it.m_radius)) {
intersected = true;
break;//note - AkatsukiSun: cannot hit more than one hitbox.
}
else {
intersected = false;
break;
}
}
return intersected;
}
bool hit_chance::can_hit(C_LagRecord& log, BaseWeapon* weapon, vec3_t angles, int hitbox) {
BaseEntity* target = interfaces::entity_list->get < BaseEntity >(log.m_nEntIndex);
if (!target || !weapon)
return false;
auto weapon_info = weapon ? interfaces::weapon_system->get_weapon_data(weapon->ItemDefinitionIndex()) : nullptr;
if (!weapon_info)
return false;
build_seed_table();
if ((weapon->ItemDefinitionIndex() == WEAPON_SSG08 || weapon->ItemDefinitionIndex() == WEAPON_REVOLVER) && !(g::pLocalPlayer->Flags() & FL_ONGROUND)) {
if ((prediction.flInaccuracy < 0.009f)) {
return true;
}
}
const vec3_t eye_pos = g::pLocalPlayer->GetEyePosition(true);
vec3_t start_scaled = { };
const auto hitchance_cfg = weapon->ItemDefinitionIndex() == WEAPON_TASER ? config.zeus_hc : g_aimbot->rage_settings.hitchance_amount;
const int hits_needed = (hitchance_cfg * 256) / 100;
int hits = 0;
for (int i = 0; i < 256; ++i) {
vec3_t spread_dir = get_spread_direction(weapon, angles, i);
vec3_t end_pos = eye_pos + (spread_dir * 8192.f);
if(can_intersect_hitbox(eye_pos, end_pos, spread_dir, log, hitbox))
hits++;
if (hits >= hits_needed)
return true;
}
return false;
}
C++:
#pragma once
class hit_chance {
public:
struct hit_chance_data_t {
float random[2];
float inaccuracy[2];
float spread[2];
};
struct hitbox_data_t {
hitbox_data_t(const vec3_t& min, const vec3_t& max, float radius, studio_box_t* hitbox, int bone, const vec3_t& rotation) {
m_min = min;
m_max = max;
m_radius = radius;
m_hitbox = hitbox;
m_bone = bone;
m_rotation = rotation;
}
vec3_t m_min{ };
vec3_t m_max{ };
float m_radius{ };
studio_box_t* m_hitbox{ };
int m_bone{ };
vec3_t m_rotation{ };
};
void build_seed_table();
vec3_t get_spread_direction(BaseWeapon* weapon, vec3_t angles, int seed);
bool can_intersect_hitbox(const vec3_t start, const vec3_t end, vec3_t spread_dir, C_LagRecord& log, int hitbox);
std::vector<hitbox_data_t> get_hitbox_data(C_LagRecord& log, int hitbox);
bool intersects_bb_hitbox(vec3_t start, vec3_t delta, vec3_t min, vec3_t max);
bool __vectorcall intersects_hitbox(vec3_t eye_pos, vec3_t end_pos, vec3_t min, vec3_t max, float radius);
bool can_hit(C_LagRecord& log, BaseWeapon* weapon, vec3_t angles, int hitbox);
private:
std::array<hit_chance_data_t, 256> hit_chance_records = {};
};
inline hit_chance* g_hit_chance = new hit_chance();
Дополнена немного из rifk, enrage и pandora-legacy.
Что скажите о нём?