#pragma once
namespace resolver {
bool use_freestand_angle[65];
float freestand_angle[65];
Vector abs_origin_backup;
float pitch_hit[65];
void animation_fix(CBasePlayer* local, CBasePlayer* player) {
static float old_sim_time[MAX_PLAYERS];
static float stored_sim_time[MAX_PLAYERS];
static float shot_time[MAX_PLAYERS];
static float side_time[MAX_PLAYERS][3];
static int last_desync_side[MAX_PLAYERS];
static bool delaying[MAX_PLAYERS];
static AnimationLayer stored_layers[MAX_PLAYERS][15];
static CAnimState* stored_anim_state[MAX_PLAYERS];
static Vector old_eye_angles[MAX_PLAYERS];
static float old_goal_feet_yaw[MAX_PLAYERS];
float* pos_params = (float*)((uintptr_t)player + 0x2774);
bool shot = false;
static bool jittering[MAX_PLAYERS];
auto* anim_state = player->get_anim_state();
if (!anim_state || !player->get_anim_overlays() || !pos_params) return;
auto remap_val = [](float val, float A, float B, float C, float D) -> float {
if (A == B) return val >= B ? D : C;
return C + (D - C) * (val - A) / (B - A);
};
if (stored_sim_time[player->GetIndex()] != player->get_simulation_time()) {
jittering[player->GetIndex()] = false;
player->get_client_animations() = true;
player->UpdateClientSideAnimation();
memcpy(stored_layers[player->GetIndex()], player->get_anim_overlays(), sizeof(AnimationLayer) * 15);
old_goal_feet_yaw[player->GetIndex()] = anim_state->m_flGoalFeetYaw;
auto weapon = player->get_weapon();
if (weapon && !weapon->get_item_def_index().is_knife() && !weapon->get_item_def_index().is_grenade()) {
if (shot_time[player->GetIndex()] != weapon->get_last_shot_time()) {
shot = true;
shot_time[player->GetIndex()] = weapon->get_last_shot_time();
} else shot = false;
} else {
shot = false;
shot_time[player->GetIndex()] = 0.f;
}
float ang_to_local = Math::NormalizeYaw(Math::CalculateAngle(local->GetOrigin(), player->GetOrigin()).y);
float back = Math::NormalizeYaw(ang_to_local);
float desync_fix = 0;
float resim = Math::NormalizeYaw((0.24f / (player->get_simulation_time() - old_sim_time[player->GetIndex()]))*(old_eye_angles[player->GetIndex()].y - player->get_eye_angles().y));
if (resim > 58.f) resim = 58.f;
if (resim < -58.f) resim = -58.f;
if (player->get_velocity().Length2D() > 0.5f && !shot) {
float delta = Math::NormalizeYaw(Math::NormalizeYaw(Math::CalculateAngle(Vector(0, 0, 0), player->get_velocity()).y) - Math::NormalizeYaw(Math::NormalizeYaw(anim_state->m_flGoalFeetYaw + remap_val(pos_params[11], 0, 1, -60, 60)) + resim));
int current_side = 0;
if (delta < 0) {
current_side = 1;
side_time[player->GetIndex()][1] = g_globals->curtime;
} else if (delta > 0) {
current_side = 2;
side_time[player->GetIndex()][2] = g_globals->curtime;
}
if (last_desync_side[player->GetIndex()] == 1) {
resim += (58.f - resim);
desync_fix += (58.f - resim);
}
if (last_desync_side[player->GetIndex()] == 2) {
resim += (-58.f - resim);
desync_fix += (-58.f - resim);
}
if (last_desync_side[player->GetIndex()] != current_side) {
delaying[player->GetIndex()] = true;
if (0.5f < (g_globals->curtime - side_time[player->GetIndex()][last_desync_side[player->GetIndex()]])) {
last_desync_side[player->GetIndex()] = current_side;
delaying[player->GetIndex()] = false;
}
}
if (!delaying[player->GetIndex()]) last_desync_side[player->GetIndex()] = current_side;
} else if (!shot) {
float brute = use_freestand_angle[player->GetIndex()] ? Math::NormalizeYaw(back + freestand_angle[player->GetIndex()]) : player->get_lower_body_yaw();
float delta = Math::NormalizeYaw(Math::NormalizeYaw(brute - Math::NormalizeYaw(Math::NormalizeYaw(anim_state->m_flGoalFeetYaw + remap_val(pos_params[11], 0, 1, -60, 60))) + resim));
if (delta > 58.f) delta = 58.f;
if (delta < -58.f) delta = -58.f;
resim += delta;
desync_fix += delta;
if (resim > 58.f) resim = 58.f;
if (resim < -58.f) resim = -58.f;
}
float equalized = Math::NormalizeYaw(Math::NormalizeYaw(anim_state->m_flGoalFeetYaw + remap_val(pos_params[11], 0, 1, -60, 60)) + resim);
float jitter_delta = fabs(Math::NormalizeYaw(old_eye_angles[player->GetIndex()].y - player->get_eye_angles().y));
if (jitter_delta >= 70.f && !shot) jittering[player->GetIndex()] = true;
if (player->get_flags() & FL_ONGROUND) {
if (jittering[player->GetIndex()]) anim_state->m_flGoalFeetYaw = Math::NormalizeYaw(player->get_eye_angles().y + desync_fix);
else anim_state->m_flGoalFeetYaw = equalized;
player->get_lower_body_yaw() = anim_state->m_flGoalFeetYaw;
}
stored_anim_state[player->GetIndex()] = anim_state;
old_eye_angles[player->GetIndex()] = player->get_eye_angles();
old_sim_time[player->GetIndex()] = stored_sim_time[player->GetIndex()];
stored_sim_time[player->GetIndex()] = player->get_simulation_time();
}
player->get_client_animations() = false;
if (player->get_flags() & FL_ONGROUND) player->get_lower_body_yaw() = anim_state->m_flGoalFeetYaw;
anim_state = stored_anim_state[player->GetIndex()];
memcpy(player->get_anim_overlays(), stored_layers[player->GetIndex()], sizeof(AnimationLayer) * 15);
if ((player->get_flags() & FL_ONGROUND) && jittering[player->GetIndex()]) player->SetAbsAngles(Vector(0, player->get_eye_angles().y, 0));
else player->SetAbsAngles(Vector(0, old_goal_feet_yaw[player->GetIndex()], 0));
*reinterpret_cast<int*>(uintptr_t(player) + 0xA30) = g_globals->framecount;
*reinterpret_cast<int*>(uintptr_t(player) + 0xA28) = 0;
}
void handle_hits(CBasePlayer* player) {
auto net_channel = g_engine->get_net_channel_info();
if (!net_channel) return;
static float pred_time[65];
static bool init[65];
if (G::shot[player->GetIndex()]) {
if (init[player->GetIndex()]) {
pitch_hit[player->GetIndex()] = player->get_eye_angles().x;
pred_time[player->GetIndex()] = g_globals->curtime + net_channel->GetAvgLatency(FLOW_INCOMING) + net_channel->GetAvgLatency(FLOW_OUTGOING) + TICKS_TO_TIME(1) + TICKS_TO_TIME(g_engine->get_net_channel()->m_nChokedPackets);
init[player->GetIndex()] = false;
}
if (g_globals->curtime > pred_time[player->GetIndex()] && !G::hit[player->GetIndex()]) {
G::missed_shots[player->GetIndex()] += 1;
G::shot[player->GetIndex()] = false;
} else if (g_globals->curtime <= pred_time[player->GetIndex()] && G::hit[player->GetIndex()]) G::shot[player->GetIndex()] = false;
} else init[player->GetIndex()] = true;
G::hit[player->GetIndex()] = false;
}
void run_resolver(CBasePlayer* local) {
if (!options::rage::resolver) return;
if (local->get_health() < 1) return;
auto weapon = local->get_weapon();
if (!weapon || weapon->get_item_def_index().is_knife() || weapon->get_item_def_index().is_grenade()) return;
for (auto i = 1; i < g_engine->get_max_clients(); ++i) {
auto player = GET_PLAYER(i);
if (!player->is_valid(options::rage::death_match)) {
use_freestand_angle[i] = false;
continue;
}
if (abs(player->get_velocity().Length2D()) > 29.f)
use_freestand_angle[player->GetIndex()] = false;
if (abs(player->get_velocity().Length2D()) <= 29.f && !use_freestand_angle[player->GetIndex()]) {
bool autowalled = false, hit_side_1 = false, hit_side_2 = false;
float ang_to_local = Math::CalculateAngle(local->GetOrigin(), player->GetOrigin()).y;
Vector view_point = local->GetOrigin() + Vector(0, 0, 90);
Vector side_1 = { (45 * sin(Math::Deg2Rad(ang_to_local))), (45 * cos(Math::Deg2Rad(ang_to_local))), 0 };
Vector side_2 = { (45 * sin(Math::Deg2Rad(ang_to_local + 180))) ,(45 * cos(Math::Deg2Rad(ang_to_local + 180))), 0 };
Vector side_3 = { (50 * sin(Math::Deg2Rad(ang_to_local))),(50 * cos(Math::Deg2Rad(ang_to_local))), 0 };
Vector side_4 = { (50 * sin(Math::Deg2Rad(ang_to_local + 180))) ,(50 * cos(Math::Deg2Rad(ang_to_local + 180))), 0 };
Vector origin = player->GetOrigin();
Vector origin_left_right[] = { Vector(side_1.x, side_1.y, 0), Vector(side_2.x, side_2.y, 0) };
Vector origin_left_right_local[] = { Vector(side_3.x, side_3.y, 0), Vector(side_4.x, side_4.y, 0) };
for (auto side = 0; side < 2; side++) {
Vector origin_autowall = { origin.x + origin_left_right[side].x, origin.y - origin_left_right[side].y , origin.z + 90 };
Vector origin_autowall_2 = { view_point.x + origin_left_right_local[side].x, view_point.y - origin_left_right_local[side].y , view_point.z };
if (auto_wall::can_hit_floating_point(origin_autowall, view_point)) {
if (side == 0) {
hit_side_1 = true;
freestand_angle[player->GetIndex()] = 90;
}
else if (side == 1) {
hit_side_2 = true;
freestand_angle[player->GetIndex()] = -90;
}
autowalled = true;
}
else {
for (auto side_2 = 0; side_2 < 2; side_2++) {
Vector origin_autowall_3 = { origin.x + origin_left_right[side_2].x, origin.y - origin_left_right[side_2].y , origin.z + 90 };
if (auto_wall::can_hit_floating_point(origin_autowall_3, origin_autowall_2)) {
if (side_2 == 0) {
hit_side_1 = true;
freestand_angle[player->GetIndex()] = 90;
} else if (side_2 == 1) {
hit_side_2 = true;
freestand_angle[player->GetIndex()] = -90;
}
autowalled = true;
}
}
}
}
if (autowalled) {
if (hit_side_1 && hit_side_2) use_freestand_angle[player->GetIndex()] = false;
else use_freestand_angle[player->GetIndex()] = true;
}
}
}
}
void fsn_resolver(CBasePlayer* local, ClientFrameStage_t stage) {
if (!options::rage::resolver) return;
if (!local || !g_engine->is_in_game()) return;
for (auto i = 1; i < g_engine->get_max_clients(); ++i) {
auto player = GET_PLAYER(i);
if (!player->is_valid(options::rage::death_match)) continue;
if (stage == FRAME_RENDER_START) {
handle_hits(player);
animation_fix(local, player);
}
if (stage == FRAME_NET_UPDATE_END) {
auto var_map = reinterpret_cast<uintptr_t>(player) + 36;
auto var_map_size = *reinterpret_cast<int*>(var_map + 20);
for (auto index = 0; index < var_map_size; index++) *reinterpret_cast<uintptr_t*>(*reinterpret_cast<uintptr_t*>(var_map) + index * 12) = 0;
}
}
}
}