do not pull - broken
This commit is contained in:
parent
825865ca0c
commit
381ff27659
44
README.md
44
README.md
@ -1,11 +1,14 @@
|
||||
# Cathook Multihack
|
||||
# Cathook Training Software
|
||||

|
||||
|
||||
cathook is a multihack for Team Fortress 2 for Linux. cathook includes some joke features like
|
||||
## Discord Server
|
||||
[Official Discord Server](https://discord.gg/kvNVNSX)
|
||||
|
||||
cathook is a training software designed for Team Fortress 2 for Linux. cathook includes some joke features like
|
||||
|
||||
* Always/Never spycrab
|
||||
* Ignore Hoovy
|
||||
* 100% Casual/Comp coin flip hack
|
||||
* 100% Casual/Comp coin flip
|
||||
* Encrypted chat
|
||||
* Emoji ESP
|
||||
* Fidget Spinner crosshair
|
||||
@ -13,29 +16,50 @@ cathook is a multihack for Team Fortress 2 for Linux. cathook includes some joke
|
||||
and a lot of useful features, including
|
||||
|
||||
* Anti Backstab with option to say "No" voice command when spy tries to backstab you
|
||||
* Heal Arrows hack (overheal an enemy for 1200 health with single huntsman arrow, you can also do it with buildings!)
|
||||
* Heal Arrows exploit (overheal an enemy for 1200 health with single huntsman arrow, you can also do it with buildings!)
|
||||
* Extremely customizable spam (you can make spam lines that'll include name of random dead enemy pyro or sniper)
|
||||
* Follow Bots
|
||||
* Working crit hack
|
||||
|
||||
[FULL LIST OF FEATURES HERE](https://github.com/nullifiedcat/cathook/wiki/List-of-features)
|
||||
|
||||
# Discord Server
|
||||
[Official Discord Server](https://discord.gg/kvNVNSX)
|
||||
|
||||
# INSTALLATION
|
||||
|
||||
Ubuntu dependencies installation:
|
||||
You **have** to use gcc6, not 7 or 5!
|
||||
|
||||
You also have to have g++-6-multilib package.
|
||||
|
||||
Ubuntu gcc6 installation: (check if you have gcc-6 installed already by typing `gcc-6 -v`
|
||||
```bash
|
||||
sudo apt update && sudo apt install build-essential software-properties-common -y && sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y && sudo apt update && sudo apt install gcc-snapshot -y && sudo apt update && sudo apt install git libc6-dev gcc-6 g++-6 libc6-dev:i386 g++-6-multilib gdb libsdl2-dev libglew-dev libfreetype6-dev libfreetype6-dev:i386 -y
|
||||
sudo apt update && sudo apt install build-essential software-properties-common -y && sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y && sudo apt update && sudo apt install gcc-snapshot g++-6-multilib gcc-6 g++-6 -y
|
||||
```
|
||||
|
||||
Ubuntu other dependencies installation:
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt install git libssl-dev:i386 libc6-dev:i386 gdb libsdl2-dev libglew-dev:i386 libfreetype6-dev:i386 -y
|
||||
```
|
||||
|
||||
|
||||
Arch dependencies installation::
|
||||
Arch gcc6 & dependencies installation:
|
||||
```bash
|
||||
sudo pacman -Syu && sudo pacman -S gdb gdb-common glew1.10 lib32-glew1.10 rsync --noconfirm && yes | sudo pacman -U https://archive.archlinux.org/packages/g/gcc-multilib/gcc-multilib-6.3.1-2-x86_64.pkg.tar.xz https://archive.archlinux.org/packages/g/gcc-libs-multilib/gcc-libs-multilib-6.3.1-2-x86_64.pkg.tar.xz https://archive.archlinux.org/packages/l/lib32-gcc-libs/lib32-gcc-libs-6.3.1-2-x86_64.pkg.tar.xz
|
||||
```
|
||||
|
||||
If you don't use Ubuntu or Arch (or if Arch script gets outdated), here's the list of what cathook requires:
|
||||
|
||||
* `gcc-6`
|
||||
* `g++-6`
|
||||
* `gcc-6-multilib`
|
||||
* `g++-6-multilib`
|
||||
* `gdb` (for the injection script, you can use different injector if you want)
|
||||
* `libssl-dev:i386`
|
||||
* `libc6-dev:i386`
|
||||
* `libsdl2-dev`
|
||||
* `libglew-dev:i386`
|
||||
* `libfreetype6-dev:i386`
|
||||
* `rsync` (only for copying shaders/fonts to tf2 data directory, `update-data` script)
|
||||
|
||||
|
||||
Cathook installation script:
|
||||
```bash
|
||||
|
BIN
banner.png
BIN
banner.png
Binary file not shown.
Before Width: | Height: | Size: 219 KiB After Width: | Height: | Size: 222 KiB |
2
makefile
2
makefile
@ -52,7 +52,7 @@ ifndef CLANG
|
||||
LDFLAGS+=-flto
|
||||
endif
|
||||
endif
|
||||
LDLIBS=-l:libSDL2-2.0.so.0 -static -l:libc.so.6 -static -l:libstdc++.so.6 -l:libtier0.so -l:libvstdlib.so -static -l:libGLEW.so -l:libfreetype.so
|
||||
LDLIBS=-lssl -l:libSDL2-2.0.so.0 -static -l:libc.so.6 -static -l:libstdc++.so.6 -l:libtier0.so -l:libvstdlib.so -static -l:libGLEW.so -l:libfreetype.so
|
||||
SRC_DIR = src
|
||||
RES_DIR = res
|
||||
OUT_NAME = libcathook.so
|
||||
|
181
src/backpacktf.cpp
Normal file
181
src/backpacktf.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* backpacktf.cpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include "backpacktf.hpp"
|
||||
#include "json.hpp"
|
||||
#include "https_request.hpp"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "cvwrapper.h"
|
||||
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
|
||||
namespace backpacktf {
|
||||
|
||||
std::unordered_map<unsigned, backpack_data_s> cache {};
|
||||
std::queue<backpack_data_s*> pending_queue {};
|
||||
std::mutex queue_mutex {};
|
||||
std::mutex cache_mutex {};
|
||||
|
||||
std::string api_key_s = "";
|
||||
bool valid_api_key = false;
|
||||
|
||||
CatVar enable_bptf(CV_SWITCH, "bptf_enable", "0", "Enable backpack.tf", "Enable backpack.tf integration\nYou have to set your API key in cat_bptf_key");
|
||||
CatCommand api_key("bptf_key", "Set API Key", [](const CCommand& args) {
|
||||
api_key_s = args.ArgS();
|
||||
logging::Info("API key changed!");
|
||||
valid_api_key = false;
|
||||
if (api_key_s.length() != 24) {
|
||||
logging::Info("API key must be exactly 24 characters long");
|
||||
valid_api_key = false;
|
||||
} else {
|
||||
valid_api_key = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
void store_data(unsigned id, unsigned value, bool no_value, bool outdated_value);
|
||||
|
||||
void processing_thread() {
|
||||
logging::Info("[bp.tf] Starting the thread");
|
||||
while (true) {
|
||||
if (enabled()) {
|
||||
try {
|
||||
std::vector<backpack_data_s*> batch {};
|
||||
int count = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queue_mutex);
|
||||
while (not pending_queue.empty() && ++count < 100) {
|
||||
batch.push_back(pending_queue.front());
|
||||
pending_queue.pop();
|
||||
}
|
||||
}
|
||||
logging::Info("[bp.tf] Requesting data for %d users", count);
|
||||
if (count) {
|
||||
std::string id_list = "";
|
||||
logging::Info("Constructing list");
|
||||
for (const auto& x : batch) {
|
||||
x->pending = false;
|
||||
logging::Info("Adding %u to the list", x->id);
|
||||
id_list += format("[U:1:", x->id, "],");
|
||||
}
|
||||
logging::Info("List constructed");
|
||||
// Remove trailing ','
|
||||
id_list = id_list.substr(0, id_list.length() - 1);
|
||||
std::string query = format("steamids=", id_list, "&key=", api_key_s);
|
||||
logging::Info("Query constructed");
|
||||
try {
|
||||
auto sock = https::RAII_HTTPS_Socket("backpack.tf");
|
||||
logging::Info("Socket created");
|
||||
sock.ssl_connect();
|
||||
logging::Info("Socket connected (%d)", sock.sock_);
|
||||
std::string response = sock.get("/api/users/info/v1?" + query);
|
||||
logging::Info("Request sent");
|
||||
if (response.find("HTTP/1.1 200 OK\r\n") != 0) {
|
||||
size_t status = response.find("\r\n");
|
||||
throw std::runtime_error("Response isn't 200 OK! It's " + response.substr(0, status));
|
||||
}
|
||||
|
||||
std::string body = response.substr(response.find("\r\n\r\n") + 4);
|
||||
|
||||
logging::Info("[bp.tf] Response: %s", body.c_str());
|
||||
|
||||
try {
|
||||
nlohmann::json data(body);
|
||||
nlohmann::json users = data["users"];
|
||||
std::lock_guard<std::mutex> lock(cache_mutex);
|
||||
for (auto it = users.begin(); it != users.end(); ++it) {
|
||||
try {
|
||||
unsigned userid = strtoul(it.key().substr(5).c_str(), nullptr, 10);
|
||||
const auto& v = it.value();
|
||||
if (not v.is_object()) {
|
||||
logging::Info("Data for %u (%s) is not an object!", userid, it.key());
|
||||
continue;
|
||||
}
|
||||
logging::Info("Parsing data for user %u (%s)", userid, v["name"]);
|
||||
const auto& inv = v["inventory"]["440"];
|
||||
if (inv.find("value") == inv.end()) {
|
||||
logging::Info("Private backpack");
|
||||
store_data(userid, 0, true, false);
|
||||
} else {
|
||||
float value = float(inv["value"]);
|
||||
unsigned updated = unsigned(inv["updated"]);
|
||||
store_data(userid, value * REFINED_METAL_PRICE, false, (unsigned(time(0)) - updated > OUTDATED_AGE));
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
logging::Info("Error while parsing user %s", it.key().c_str());
|
||||
}
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
logging::Info("[bp.tf] Exception while parsing response: %s", e.what());
|
||||
}
|
||||
|
||||
} catch (std::exception& e) {
|
||||
logging::Info("[bp.tf] HTTPS exception: %s", e.what());
|
||||
}
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
logging::Info("[bp.tf] Thread exception: %s", e.what());
|
||||
}
|
||||
}
|
||||
sleep(REQUEST_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
void request_data(unsigned id) {
|
||||
if (cache[id].pending) return;
|
||||
cache[id].pending = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queue_mutex);
|
||||
pending_queue.push(&cache[id]);
|
||||
}
|
||||
}
|
||||
|
||||
bool enabled() {
|
||||
return enable_bptf && valid_api_key;
|
||||
}
|
||||
|
||||
backpack_data_s& access_data(unsigned id) {
|
||||
try {
|
||||
return cache.at(id);
|
||||
} catch (std::out_of_range& oor) {
|
||||
cache.emplace(id, backpack_data_s {});
|
||||
cache.at(id).id = id;
|
||||
return cache.at(id);
|
||||
}
|
||||
}
|
||||
|
||||
void store_data(unsigned id, unsigned value, bool none, bool outdated) {
|
||||
auto& d = access_data(id);
|
||||
d.last_request = unsigned(time(0));
|
||||
d.bad = false;
|
||||
d.value = value;
|
||||
d.no_value = none;
|
||||
d.outdated_value = outdated;
|
||||
d.pending = false;
|
||||
}
|
||||
|
||||
const backpack_data_s& get_data(unsigned id) {
|
||||
auto& d = access_data(id);
|
||||
if (d.bad || ((unsigned)time(0) - MAX_CACHE_AGE > cache[id].last_request)) {
|
||||
request_data(id);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
std::thread& GetBackpackTFThread() {
|
||||
static std::thread thread(processing_thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
void init() {
|
||||
GetBackpackTFThread();
|
||||
}
|
||||
|
||||
}
|
35
src/backpacktf.hpp
Normal file
35
src/backpacktf.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* backpacktf.hpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class CatVar;
|
||||
|
||||
namespace backpacktf {
|
||||
|
||||
constexpr float REFINED_METAL_PRICE = 0.075f; // $
|
||||
constexpr unsigned REQUEST_INTERVAL = 10; // Make a backpack.tf request every 30 seconds
|
||||
constexpr unsigned MAX_CACHE_AGE = 60 * 30;
|
||||
constexpr unsigned OUTDATED_AGE = 60 * 60 * 24 * 3; // After how many seconds backpack is marked "outdated" (possibly private)
|
||||
|
||||
extern CatVar enable_bptf;
|
||||
|
||||
struct backpack_data_s {
|
||||
bool pending { false };
|
||||
bool bad { true };
|
||||
bool no_value { false }; // No recorded value
|
||||
bool outdated_value { false }; // Outdated value. Private inventory?
|
||||
unsigned last_request { 0 };
|
||||
unsigned value { 0 };
|
||||
unsigned id { 0 };
|
||||
};
|
||||
|
||||
const backpack_data_s& get_data(unsigned id);
|
||||
void init();
|
||||
bool enabled();
|
||||
|
||||
}
|
@ -83,6 +83,7 @@ extern "C" {
|
||||
#include "hooks/hookedmethods.h"
|
||||
#include "classinfo/classinfo.hpp"
|
||||
#include "crits.h"
|
||||
#include "backpacktf.hpp"
|
||||
|
||||
#if ENABLE_GUI
|
||||
#include "gui/GUI.h"
|
||||
|
@ -83,7 +83,31 @@ void RenderPlayer(int eid) {
|
||||
if (bgcolor.a) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (backpacktf::enabled()) {
|
||||
ImGui::SameLine();
|
||||
if (!info.friendsID) {
|
||||
ImGui::Text("[BOT]");
|
||||
}
|
||||
const auto& d = backpacktf::get_data(info.friendsID);
|
||||
if (d.bad && not d.pending) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::Text("Error");
|
||||
} else if (d.pending) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
|
||||
ImGui::Text("Fetching");
|
||||
} else if (d.no_value) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
ImGui::Text("No value");
|
||||
} else if (d.outdated_value) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
|
||||
ImGui::Text("$%u", d.value);
|
||||
} else {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.8f, 0.0f, 1.0f));
|
||||
ImGui::Text("$%u", d.value);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::SameLine(610);
|
||||
ImGui::PushItemWidth(200.0f);
|
||||
if (ImGui::ColorEdit3("", data.color)) {
|
||||
if (!data.color.r && !data.color.b && !data.color.g) {
|
||||
@ -104,7 +128,7 @@ void RenderPlayerlist() {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 1));
|
||||
std::vector<int> teammates {};
|
||||
for (int i = 1; i < 32; i++) {
|
||||
if (g_pPlayerResource->GetTeam(i) == LOCAL_E->m_iTeam) {
|
||||
if (!g_Settings.bInvalid && (g_pPlayerResource->GetTeam(i) == LOCAL_E->m_iTeam)) {
|
||||
teammates.push_back(i);
|
||||
continue;
|
||||
}
|
||||
|
@ -272,8 +272,10 @@ void hack::Initialize() {
|
||||
hacks::shared::anticheat::Init();
|
||||
hacks::tf2::healarrow::Init();
|
||||
InitSpinner();
|
||||
hacks::shared::spam::Init();
|
||||
logging::Info("Initialized Fidget Spinner");
|
||||
hacks::shared::spam::Init();
|
||||
backpacktf::init();
|
||||
logging::Info("Initialized Backpack.TF integration");
|
||||
|
||||
}
|
||||
|
||||
|
127
src/https_request.cpp
Normal file
127
src/https_request.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* https_request.cpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include "https_request.hpp"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace https {
|
||||
|
||||
SSL_CTX *ssl_context;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
RAII_HTTPS_Socket::RAII_HTTPS_Socket(const std::string& host) : hostname_(host) {
|
||||
if (!initialized) {
|
||||
logging::Info("Initializing SSL");
|
||||
initialize();
|
||||
}
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock_ < 0) {
|
||||
throw std::runtime_error("Socket creation error");
|
||||
}
|
||||
host_ = gethostbyname(hostname_.c_str());
|
||||
if (not host_) {
|
||||
throw std::runtime_error("Could not resolve hostname: " + host);
|
||||
}
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(443);
|
||||
memcpy(&addr_.sin_addr.s_addr, host_->h_addr, host_->h_length);
|
||||
if (connect(sock_, (sockaddr *)&addr_, sizeof(addr_)) < 0) {
|
||||
close(sock_);
|
||||
sock_ = -1;
|
||||
throw std::runtime_error("Couldn't connect to host");
|
||||
}
|
||||
ssl_connect();
|
||||
}
|
||||
|
||||
RAII_HTTPS_Socket::~RAII_HTTPS_Socket() {
|
||||
logging::Info("Cleaning up HTTPS socket");
|
||||
ssl_die();
|
||||
if (sock_ >= 0)
|
||||
close(sock_);
|
||||
}
|
||||
|
||||
bool RAII_HTTPS_Socket::ssl_connect() {
|
||||
connection_ = SSL_new(ssl_context);
|
||||
SSL_set_fd(connection_, sock_);
|
||||
if (SSL_connect(connection_) != 1) {
|
||||
printf("SSL connection error\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RAII_HTTPS_Socket::ssl_die() {
|
||||
if (connection_) {
|
||||
SSL_free(connection_);
|
||||
connection_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string RAII_HTTPS_Socket::get(const std::string& path) {
|
||||
constexpr size_t rq_size = 1024 * 8;
|
||||
constexpr size_t rs_size = 1024 * 1024;
|
||||
|
||||
std::unique_ptr<char>
|
||||
buffer_rq(new char[rq_size]),
|
||||
buffer_rs(new char[rs_size]);
|
||||
|
||||
memset(buffer_rq.get(), 0, rq_size);
|
||||
int rq_length = snprintf(buffer_rq.get(), rq_size, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", path.c_str(), hostname_.c_str());
|
||||
int sent = 0;
|
||||
int chunk = 0;
|
||||
logging::Info("Writing %d bytes to socket %d", rq_length, sock_);
|
||||
do {
|
||||
chunk = SSL_write(connection_, buffer_rq.get() + sent, rq_length - sent);
|
||||
logging::Info("Written %d bytes", chunk);
|
||||
if (chunk < 0) {
|
||||
throw std::runtime_error("Error writing to Secure Socket: " + std::to_string(ERR_get_error()));
|
||||
} else if (chunk == 0) {
|
||||
break;
|
||||
}
|
||||
sent += chunk;
|
||||
} while (sent < rq_length);
|
||||
|
||||
memset(buffer_rs.get(), 0, rs_size);
|
||||
int total = rs_size - 1;
|
||||
int received = 0;
|
||||
do {
|
||||
chunk = SSL_read(connection_, buffer_rs.get() + received, total - received);
|
||||
if (chunk < 0)
|
||||
throw std::runtime_error("Error reading from socket");
|
||||
if (chunk == 0)
|
||||
break;
|
||||
received += chunk;
|
||||
} while (received < total);
|
||||
|
||||
if (received == total)
|
||||
throw std::runtime_error("Response too large");
|
||||
|
||||
return std::string(buffer_rs.get());
|
||||
}
|
||||
|
||||
|
||||
void initialize() {
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
ssl_context = SSL_CTX_new(SSLv23_client_method());
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
}
|
44
src/https_request.hpp
Normal file
44
src/https_request.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* https_request.hpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "beforecheaders.h"
|
||||
#include <string>
|
||||
#include "aftercheaders.h"
|
||||
|
||||
|
||||
namespace https {
|
||||
|
||||
extern SSL_CTX *ssl_context;
|
||||
|
||||
class RAII_HTTPS_Socket {
|
||||
public:
|
||||
RAII_HTTPS_Socket(const std::string& host);
|
||||
~RAII_HTTPS_Socket();
|
||||
|
||||
bool ssl_connect();
|
||||
void ssl_die();
|
||||
|
||||
std::string get(const std::string& path);
|
||||
|
||||
const std::string hostname_;
|
||||
|
||||
hostent *host_ { nullptr };
|
||||
sockaddr_in addr_ {};
|
||||
int sock_ { -1 };
|
||||
SSL *connection_ { nullptr };
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
||||
}
|
||||
|
||||
|
@ -222,10 +222,17 @@ Vector ProjectilePrediction_Engine(CachedEntity* ent, int hb, float speed, float
|
||||
return result;
|
||||
}
|
||||
|
||||
CatVar debug_pp_extrapolate(CV_SWITCH, "debug_pp_extrapolate", "0", "Extrapolate entity position when predicting projectiles");
|
||||
CatVar debug_pp_rockettimeping(CV_SWITCH, "debug_pp_rocket_time_ping", "0", "Compensate for ping in pp");
|
||||
|
||||
Vector ProjectilePrediction(CachedEntity* ent, int hb, float speed, float gravitymod, float entgmod) {
|
||||
if (!ent) return Vector();
|
||||
Vector result;
|
||||
GetHitbox(ent, hb, result);
|
||||
if (not debug_pp_extrapolate) {
|
||||
GetHitbox(ent, hb, result);
|
||||
} else {
|
||||
result = SimpleLatencyPrediction(ent, hb);
|
||||
}
|
||||
if (speed == 0.0f) return Vector();
|
||||
float dtg = DistanceToGround(ent);
|
||||
Vector vel;
|
||||
@ -250,6 +257,7 @@ Vector ProjectilePrediction(CachedEntity* ent, int hb, float speed, float gravit
|
||||
if (curpos.z < result.z - dtg) curpos.z = result.z - dtg;
|
||||
}
|
||||
float rockettime = g_pLocalPlayer->v_Eye.DistTo(curpos) / speed;
|
||||
if (debug_pp_rockettimeping) rockettime += g_IEngine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING);
|
||||
if (fabs(rockettime - currenttime) < mindelta) {
|
||||
besttime = currenttime;
|
||||
bestpos = curpos;
|
||||
|
Reference in New Issue
Block a user