-
Автор темы
- #1
C++:
void CEnginePrediction::Start(CUserCmd* cmd, IBasePlayer* local) {
if (!local)
return;
// runcommand is only called on frames, when ur framerate dips, ur cmds wont be predicted (in time), so lots of things like desync etc fuck up
// by simply forcing prediction on our cmds in CM, we circumvent all problems caused by this flawed setup where prediction is based on framerate
interfaces.prediction->Update(csgo->client_state->iDeltaTick, true, csgo->client_state->nLastCommandAck,csgo->client_state->nLastOutgoingCommand + csgo->client_state->iChokedCommands);
// random_seed isn't generated in ClientMode::CreateMove yet, we must generate it ourselves
if (!prediction_random_seed)
prediction_random_seed = *reinterpret_cast <int**> (csgo->Utils.FindPatternIDA(GetModuleHandleA(g_Modules[fnv::hash(hs::client_dll::s().c_str())].c_str()),hs::randomseed::s().c_str()) + 0x1);
// backup globals.
old_vars.curtime = interfaces.global_vars->curtime;
old_vars.frametime = interfaces.global_vars->frametime;
old_vars.tickcount = interfaces.global_vars->tickcount;
// backup prediction states
old_vars.m_in_prediction = interfaces.prediction->bInPrediction;
old_vars.m_first_time_predicted = interfaces.prediction->bIsFirstTimePredicted;
// set corrected values
interfaces.global_vars->curtime = TICKS_TO_TIME(GetTickbase(cmd, local));
interfaces.global_vars->frametime = interfaces.prediction->bEnginePaused ? 0.f : interfaces.global_vars->interval_per_tick;
interfaces.global_vars->tickcount = TIME_TO_TICKS(interfaces.global_vars->curtime);
interfaces.prediction->bInPrediction = true;
interfaces.prediction->bIsFirstTimePredicted = false;
*reinterpret_cast<CUserCmd**>(reinterpret_cast<uintptr_t>(local) + 0x3288) = cmd;
if (!prediction_player)
prediction_player = *reinterpret_cast <int**> (csgo->Utils.FindPatternIDA(GetModuleHandleA(g_Modules[fnv::hash(hs::client_dll::s().c_str())].c_str()),hs::player_sig::s().c_str()) + 0x2);
auto buttons_forced = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(local) + 0x3334);
auto buttons_disabled = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(local) + 0x3330);
cmd->buttons |= buttons_forced;
cmd->buttons &= ~buttons_disabled;
//weapon predict
if (cmd->weaponselect) {
auto weapon = reinterpret_cast<IBaseCombatWeapon*>(interfaces.ent_list->GetClientEntity(cmd->weaponselect));
if (weapon) {
auto weapon_data = weapon->GetCSWpnData();
weapon_data ? local->SelectItem(weapon_data->m_szWeaponName, cmd->weaponsubtype) : 0;
}
}
if (cmd->impulse)
*local->GetImpulse() = cmd->impulse;
auto buttons = cmd->buttons;
auto buttons_changed = buttons ^ *local->GetButtons();
// sync m_afButtonLast
local->GetButtonLast() = *local->GetButtons();
// syn m_nButtons
*local->GetButtons() = buttons;
// sync m_afButtonPressed
local->GetButtonPressed() = buttons_changed & buttons;
// sync m_afButtonReleased
local->GetButtonReleased() = buttons_changed & ~buttons;
// check if the player is standing on a moving entity and adjusts velocity and basevelocity appropriately
interfaces.prediction->CheckMovingGround(local, interfaces.global_vars->frametime);
// copy angles from command to player
local->SetLocalViewAngles(cmd->viewangles);
if (local->PhysicsRunThink(0)) //0 THINK_FIRE_ALL_FUNCTIONS
local->PreThink();
// run think
if (local->GetNextThinkTick() > 0 && *local->GetNextThinkTick() <= GetTickbase(cmd, local))
{
*local->GetNextThinkTick() = -1;
local->UnkFunc();
local->Think();
}
// set target player ( host ).
interfaces.move_helper->SetHost(local);
interfaces.game_movement->StartTrackPredictionErrors(local);
// setup move
memset(&data, 0, sizeof(data));
interfaces.prediction->SetupMove(local, cmd, interfaces.move_helper, &data);
interfaces.game_movement->ProcessMovement(local, &data);
// finish move
interfaces.prediction->FinishMove(local, cmd, &data);
interfaces.move_helper->ProcessImpacts();
// run post think
post_think(local);
// restore prediction states
interfaces.prediction->bInPrediction = old_vars.m_in_prediction;
interfaces.prediction->bIsFirstTimePredicted = old_vars.m_first_time_predicted;
}
void CEnginePrediction::Finish(IBasePlayer* local) {
if (!local)
return;
interfaces.game_movement->FinishTrackPredictionErrors(local);
// reset host player
interfaces.move_helper->SetHost(nullptr);
interfaces.game_movement->Reset();
*prediction_random_seed = -1;
*prediction_player = 0;
//restore globals
interfaces.global_vars->curtime = old_vars.curtime;
interfaces.global_vars->frametime = old_vars.frametime;
interfaces.global_vars->tickcount = old_vars.tickcount;//why wernt u restroing tick count before -_-
!interfaces.prediction->bEnginePaused&& interfaces.global_vars->frametime ? local->GetTickBasePtr()++ : 0;
}
//fixing tickbase this way is -_-
//we fix tickbase in our prediction so we can just use fixed curtime and the fix curtime help with other shit
int CEnginePrediction::GetTickbase(CUserCmd* pCmd, IBasePlayer* pLocal)
{
static int iTick = 0;
static CUserCmd* pLastCmd = nullptr;
if (pCmd != nullptr)
{
// if command was not predicted - increment tickbase
if (pLastCmd == nullptr || pLastCmd->hasbeenpredicted)
iTick = pLocal->GetTickBase();
else
iTick++;
pLastCmd = pCmd;
}
return iTick;
}
C++:
#pragma once
#include "hooks.h"
class CEnginePrediction : public Singleton<CEnginePrediction>
{
public:
void Start(CUserCmd* cmd, IBasePlayer* local);
void Finish(IBasePlayer* local);
int GetTickbase(CUserCmd* pCmd, IBasePlayer* pLocal);
backup backup_data;
private:
CMoveData data;
CUserCmd* last_cmd{};
int32_t tick_base{};
struct {
float curtime, frametime;
int tickcount, tickbase;
bool m_in_prediction, m_first_time_predicted;
}old_vars;
int* prediction_random_seed = nullptr;
int* prediction_player = nullptr;
};
Последнее редактирование: