like amiri in my mind
Пользователь
-
Автор темы
- #1
Хитчанс с этой темы - https://yougame.biz/threads/273111/#post-2774210
Credits: AkatsukiSun, me
пример использования в аиме:
is_valid_hitchance = g_hit_chance->can_hit(final_target.record , g_ctx.globals.weapon,aim_angle,final_target.data.hitbox);
коротко о нем: тестил недолго, но хитчанс оч понравился будет полюбе лучше других пабликов
Credits: AkatsukiSun, me
пример использования в аиме:
is_valid_hitchance = g_hit_chance->can_hit(final_target.record , g_ctx.globals.weapon,aim_angle,final_target.data.hitbox);
коротко о нем: тестил недолго, но хитчанс оч понравился будет полюбе лучше других пабликов
hitchance.cpp:
#include "../../utils/math.hpp"
#include "../../lagcompensation/animation_system.h"
#include "hitchance_system.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(Vector start, Vector delta, Vector min, Vector 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(Vector eye_pos, Vector end_pos, Vector min, Vector max, float radius) {
auto dist = math::segment_to_segment(eye_pos, end_pos, min, max);
return (dist < radius);
}
std::vector<hit_chance::hitbox_data_t> hit_chance::get_hitbox_data(adjust_data* log, int hitbox) {
std::vector<hitbox_data_t> hitbox_data;
auto target= static_cast<player_t*>(m_entitylist()->GetClientEntity(log->player->EntIndex()));
const auto model = target->GetClientRenderable()->GetModel();
if (!model)
return {};
auto hdr = m_modelinfo()->GetStudioModel(model);
if (!hdr)
return {};
auto set = hdr->pHitboxSet(log->player->m_nHitboxSet());
if (!set)
return {};
//we use 128 bones that not proper use aim matrix there
auto bone_matrix = log->matrixes_data.main;
Vector min, max;
if (hitbox == -1) {
for (int i = 0; i < set->numhitboxes; ++i) {
const auto box = set->pHitbox(i);
if (!box)
continue;
float radius = box->radius;
const auto is_capsule = radius != -1.f;
if (is_capsule) {
math::VectorTransform(box->bbmin, bone_matrix[box->bone], min);
math::VectorTransform(box->bbmax, bone_matrix[box->bone], max);
}
else {
math::VectorTransform(math::vector_rotate(box->bbmin, box->rotation), bone_matrix[box->bone], min);
math::VectorTransform(math::vector_rotate(box->bbmax, box->rotation), bone_matrix[box->bone], max);
radius = min.DistTo(max);
}
hitbox_data.emplace_back(hitbox_data_t{ min, max, radius, box, box->bone, box->rotation });
}
}
else {
const auto box = set->pHitbox(hitbox);
if (!box)
return {};
float radius = box->radius;
const auto is_capsule = radius != -1.f;
if (is_capsule) {
math::VectorTransform(box->bbmin, bone_matrix[box->bone], min);
math::VectorTransform(box->bbmax, bone_matrix[box->bone], max);
}
else {
math::VectorTransform(math::vector_rotate(box->bbmin, box->rotation), bone_matrix[box->bone], min);
math::VectorTransform(math::vector_rotate(box->bbmax, box->rotation), bone_matrix[box->bone], max);
radius = min.DistTo(max);
}
hitbox_data.emplace_back(hitbox_data_t{ min, max, radius, box, box->bone, box->rotation });
}
return hitbox_data;
}
Vector hit_chance::get_spread_direction(weapon_t* weapon, Vector angles, int seed) {
if (!weapon)
return Vector();
const int rnsd = (seed & 0xFF);
const auto* data = &hit_chance_records[rnsd];
if (!data)
return Vector();
float rand_a = data->random[0];
float rand_b = data->random[1];
if (weapon->m_iItemDefinitionIndex() == WEAPON_NEGEV) {
auto weapon_info = weapon ? g_ctx.globals.weapon->get_csweapon_info() : nullptr;
if (weapon_info && weapon_info->iRecoilSeed < 3) {
rand_a = 1.0f - std::pow(rand_a, static_cast<float>(3 - weapon_info->iRecoilSeed + 1));
rand_b = 1.0f - std::pow(rand_b, static_cast<float>(3 - weapon_info->iRecoilSeed + 1));
}
}
//must write from predition
const float rand_inaccuracy = rand_a * g_ctx.globals.inaccuracy;
const float rand_spread = rand_b * g_ctx.globals.spread;
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;
Vector 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 Vector start, const Vector end, Vector spread_dir, adjust_data* log, int hitbox)
{
const auto hitbox_data = get_hitbox_data(log, hitbox);
if (hitbox_data.empty())
return false;
auto intersected = false;
Vector delta;
Vector 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->matrixes_data.main[it.m_bone], start_scaled);
math::vector_i_rotate(spread_dir * 8192.f, log->matrixes_data.main[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(adjust_data* log, weapon_t* weapon, Vector angles, int hitbox) {
auto target = static_cast<player_t*>(m_entitylist()->GetClientEntity(log->player->EntIndex()));
if (!target || !weapon)
return false;
auto weapon_info = weapon ? g_ctx.globals.weapon->get_csweapon_info() : nullptr;
if (!weapon_info)
return false;
build_seed_table();
if ((weapon->m_iItemDefinitionIndex() == WEAPON_SSG08 || weapon->m_iItemDefinitionIndex() == WEAPON_REVOLVER) && !(g_ctx.local()->m_fFlags() & FL_ONGROUND)) {
if ((g_ctx.globals.inaccuracy < 0.009f)) {
return true;
}
}
const Vector eye_pos = g_ctx.local()->get_eye_pos();
Vector start_scaled = { };
const auto hitchance_cfg = g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitchance_amount;
const int hits_needed = (hitchance_cfg * 256) / 100;
int hits = 0;
for (int i = 0; i < 256; ++i) {
Vector spread_dir = get_spread_direction(weapon, angles, i);
Vector 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;
}
hitchance.h:
#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 Vector& min, const Vector& max, float radius, mstudiobbox_t* hitbox, int bone, const Vector& rotation) {
m_min = min;
m_max = max;
m_radius = radius;
m_hitbox = hitbox;
m_bone = bone;
m_rotation = rotation;
}
Vector m_min{ };
Vector m_max{ };
float m_radius{ };
mstudiobbox_t* m_hitbox{ };
int m_bone{ };
Vector m_rotation{ };
};
void build_seed_table();
Vector get_spread_direction(weapon_t* weapon, Vector angles, int seed);
bool can_intersect_hitbox(const Vector start, const Vector end, Vector spread_dir, adjust_data* log, int hitbox);
std::vector<hitbox_data_t> get_hitbox_data(adjust_data* log, int hitbox);
bool intersects_bb_hitbox(Vector start, Vector delta, Vector min, Vector max);
bool __vectorcall intersects_hitbox(Vector eye_pos, Vector end_pos, Vector min, Vector max, float radius);
bool can_hit(adjust_data* log, weapon_t* weapon, Vector angles, int hitbox);
private:
std::array<hit_chance_data_t, 256> hit_chance_records = {};
};
inline hit_chance* g_hit_chance = new hit_chance();
Последнее редактирование: