From 7d54105fecef3ecdd43d95c7bd45253bfac95921 Mon Sep 17 00:00:00 2001 From: F1ssi0N Date: Sun, 18 Mar 2018 19:24:49 +0000 Subject: [PATCH] Fix all issues related to running doghook on linux (#21) * add more linux signatures * Update premake script to generate correct symbols on respective platforms * Add debugger gdb for linux builds * Change from -ggdb to -gdwarf * change from -gdward to -g3 * Update linux signatures * Fix issues with virtual function calling * Fix a bunch of crashes. * Update prediction vfunc indexes * Update more indexes * No more crashes! * Fix usercmd padding * Fix more index issues * Change attach scripts to reflect what they do * Fix windows compilation issues - remove hardcoded path from attach-basic * Update attach script --- attach-basic.sh | 61 +++++++++++++++++++++++ attach-interactive.sh | 105 ++++++++++++++++++++++++++++++++++++++++ attach.sh | 8 ++- premake5.lua | 8 ++- src/doghook.cc | 60 +++++++++++++++++++---- src/doghook.hh | 1 + src/hooks/createmove.cc | 21 ++++++-- src/main.cc | 8 ++- src/modules/aimbot.cc | 9 +++- src/precompiled.hh | 1 + src/sdk/convar.cc | 22 +++++++-- src/sdk/entity.cc | 8 +-- src/sdk/hooks.hh | 12 ++++- src/sdk/interface.hh | 2 +- src/sdk/player.cc | 12 ++--- src/sdk/player.hh | 2 +- src/sdk/sdk.hh | 20 +++++--- src/sdk/vfunc.hh | 4 ++ src/utils/math.hh | 6 ++- 19 files changed, 322 insertions(+), 48 deletions(-) create mode 100755 attach-basic.sh create mode 100755 attach-interactive.sh create mode 100644 src/doghook.hh diff --git a/attach-basic.sh b/attach-basic.sh new file mode 100755 index 0000000..152f7d3 --- /dev/null +++ b/attach-basic.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# cwd into where this script is located +line=$(pidof hl2_linux) +arr=($line) +inst=$1 +if [ $# == 0 ]; then + inst=0 +fi + +if [ ${#arr[@]} == 0 ]; then + echo TF2 isn\'t running! + exit +fi + +if [ $inst -gt ${#arr[@]} ] || [ $inst == ${#arr[@]} ]; then + echo wrong index! + exit +fi + +proc=${arr[$inst]} + +echo Running instances: "${arr[@]}" +echo Attaching to "$proc" + +#sudo ./detach $inst bin/libcathook.so + +#if grep -q "$(realpath bin/libcathook.so)" /proc/"$proc"/maps; then +# echo already loaded +# exit +#fi + +# pBypass for crash dumps being sent +# You may also want to consider using -nobreakpad in your launch options. +sudo rm -rf /tmp/dumps # Remove if it exists +sudo mkdir /tmp/dumps # Make it as root +sudo chmod 000 /tmp/dumps # No permissions + +#FILENAME="/tmp/.gl$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)" + +#cp "bin/Debug/libdoghook.so" "$FILENAME" +FILENAME=$(readlink -f "${0%/*}/bin/Debug/libdoghook.so") + +echo loading "$FILENAME" to "$proc" + +sudo killall -19 steam +sudo killall -19 steamwebhelper + +sudo gdb -n -q -batch \ + -ex "attach $proc" \ + -ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \ + -ex "call \$dlopen(\"$FILENAME\", 1)" \ + -ex "call dlerror()" \ + -ex 'print (char *) $2' \ + -ex "detach" \ + -ex "quit" + +#rm $FILENAME + +sudo killall -18 steamwebhelper +sudo killall -18 steam diff --git a/attach-interactive.sh b/attach-interactive.sh new file mode 100755 index 0000000..8eea2cf --- /dev/null +++ b/attach-interactive.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash + +pid=$(pidof hl2_linux) # Default to TF2 + +if [[ -n "$1" ]]; then + if [ "$1" -eq "$1" ] 2>/dev/null; then + # First argument is a int (PID) + pid=$1 + else + # First argument is a string (Process ID) + pid=$(pidof $1) + fi +fi + +if [ -z "$pid" ]; then + echo -e "\e[91mCould not find target process.\e[39m" + exit -1 +fi + +# Get the full path of the .so that we'll be faking +victim_lib=$(cat /proc/${pid}/maps | grep ".so" | shuf -n 1) + +echo $victim_lib + +victim_lib=${victim_lib##* } + +# Some magic that I copied straight from StackOverflow +victim_lib_array=(${victim_lib//./ }) + +number_to_spoof=${victim_lib_array[-1]} +library_path=$(IFS=. ; echo "${victim_lib_array[*]}") + +if [ "$number_to_spoof" == "so" ]; then + # If the shared library doesn't have multiple versions, let's just append .0 at the end. + number_to_spoof="$number_to_spoof.0" +else + # else we'll increase the found version by one + number_to_spoof=$(($number_to_spoof + 1)) +fi + +victim_lib_array[-1]="$number_to_spoof" +library_path=$(IFS=. ; echo "${victim_lib_array[*]}") + +if [ -e "$library_path" ]; then + echo -e "\e[91mA error occurred. Please retry.\e[39m" + exit -1 +else + sudo cp "bin/Debug/libdoghook.so" "$library_path" + + # Get the file name of the resulting library + result_lib_name=$(basename ${library_path}) + result_lib="${result_lib_name%.*}" + + # and patch the soname + sudo patchelf --set-soname "$library_path" "$result_lib" +fi + +echo "Attaching as $result_lib ($library_path) to PID $pid" + +# Allows only root to use ptrace. This is temporary until the user reboots the machine. +ptrace_input=$(sudo echo "2" | sudo tee /proc/sys/kernel/yama/ptrace_scope) + +# Prevent crash dumps from being sent to kisak +sudo rm -rf /tmp/dumps +sudo mkdir /tmp/dumps +sudo chmod 000 /tmp/dumps + +# Pause Steam +sudo killall -19 steam +sudo killall -19 steamwebhelper + +# Uses dlmopen instead of normal dlopen - Credit to LWSS +sudo gdb -n \ + -ex "set logging on" \ + -ex "set logging file /dev/null" \ + -ex "attach $pid" \ + -ex "set \$linkMapID = (long int)0" \ + -ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \ + -ex "set \$dlmopen = (void*(*)(long int, char*, int)) dlmopen" \ + -ex "set \$dlinfo = (int (*)(void*, int, void*)) dlinfo" \ + -ex "set \$malloc = (void*(*)(long long)) malloc" \ + -ex "set \$target = \$dlopen(\"$library_path\", 2)" \ + -ex "p \$target" \ + -ex "p \$linkMapID" \ + -ex "call \$dlmopen(0, \"$library_path\", 1)" \ + -ex "set \$error = call dlerror()" \ + -ex "x/s \$error" + +# Resume Steam +sleep 1 +sudo killall -18 steamwebhelper +sudo killall -18 steam + +sudo rm -rf "$library_path" + +if grep -q "$library_path" /proc/${pid}/maps; then + echo "Successfully attached to PID $pid." +else + echo -e "\e[91mA error occurred. See gdb.txt\e[39m" + exit -1 +fi + +if [ -f "$(pwd)/gdb.txt" ]; then + sudo rm -rf gdb.txt +fi diff --git a/attach.sh b/attach.sh index 7b56f53..b3f3079 100755 --- a/attach.sh +++ b/attach.sh @@ -70,7 +70,7 @@ sudo killall -19 steam sudo killall -19 steamwebhelper # Uses dlmopen instead of normal dlopen - Credit to LWSS -sudo gdb -n \ +sudo gdb -n -batch \ -ex "set logging on" \ -ex "set logging file /dev/null" \ -ex "attach $pid" \ @@ -85,7 +85,11 @@ sudo gdb -n \ -ex "call \$dlmopen(0, \"$library_path\", 1)" \ -ex "set \$error = call dlerror()" \ -ex "x/s \$error" \ - -ex "catch syscall exit exit_group" + -ex "catch syscall exit exit_group" \ + -ex "continue" \ + -ex "backtrace" \ + -ex "detach" \ + -ex "quit" # Resume Steam sleep 1 diff --git a/premake5.lua b/premake5.lua index 42570e4..009fefe 100644 --- a/premake5.lua +++ b/premake5.lua @@ -25,7 +25,13 @@ workspace "doghook" filter "configurations:Debug" defines { "DEBUG", "_DEBUG" } optimize "Off" - symbols "Full" + + filter "system:windows" + symbols "Full" + filter "system:linux" + symbols "On" + buildoptions "-g3" + filter "" runtime "Debug" filter "configurations:Release" diff --git a/src/doghook.cc b/src/doghook.cc index 988a3f2..bc4382d 100644 --- a/src/doghook.cc +++ b/src/doghook.cc @@ -1,5 +1,7 @@ #include "precompiled.hh" +#include "doghook.hh" + #include "sdk/gamesystem.hh" #include "sdk/log.hh" @@ -14,6 +16,8 @@ #include "hooks/createmove.hh" +#include "sdk/signature.hh" + // Singleton for doing init / deinit of doghook // and dealing with hooks from gamesystem @@ -39,14 +43,33 @@ public: IFace().set_from_interface("client", "VClient"); IFace().set_from_interface("engine", "VEngineClient"); IFace().set_from_interface("client", "VClientEntityList"); - IFace().set_from_pointer(**reinterpret_cast( - vfunc::get_func(IFace().get(), 15, 0) + 0x2)); + + if constexpr (doghook_platform::windows()) + IFace().set_from_pointer(**reinterpret_cast( + vfunc::get_func(IFace().get(), 15, 0) + 0x2)); + else if constexpr (doghook_platform::linux()) + IFace().set_from_pointer(**reinterpret_cast( + vfunc::get_func(IFace().get(), 15, 0) + 0x1)); + IFace().set_from_interface("vstdlib", "VEngineCvar"); - // TODO linux signatures - IFace().set_from_pointer( - *signature::find_pattern( - "client", "B9 ? ? ? ? A3 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? E8 ? ? ? ? 83 C4 04 C7 05", 1)); + if constexpr (doghook_platform::windows()) + IFace().set_from_pointer( + *signature::find_pattern( + "client", "B9 ? ? ? ? A3 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? E8 ? ? ? ? 83 C4 04 C7 05", 1)); + else if constexpr (doghook_platform::linux()) { + // ClientMode is a magic static. So getting a sig for it is difficult (conflicts with all other magic statics) + // So we are going to do some multistage shit in order to retrieve it + auto outer_function = signature::find_pattern("client", "55 89 E5 83 EC 18 E8 ? ? ? ? A3 ? ? ? ? E8", 6); + assert(outer_function); + + auto inner_function = static_cast(signature::resolve_callgate(outer_function)); + assert(outer_function); + + IFace().set_from_pointer(*reinterpret_cast(inner_function + 10)); + assert(IFace().get()); + } + IFace().set_from_interface("engine", "VModelInfoClient"); IFace().set_from_interface("engine", "EngineTraceClient"); IFace().set_from_interface("engine", "VDebugOverlay"); @@ -59,17 +82,32 @@ public: // TODO: this globals_real_address is windows only! if constexpr (doghook_platform::windows()) { auto globals_real_address = (u32)*signature::find_pattern("engine", "A1 ? ? ? ? 8B 11 68", 8); + IFace().set_from_pointer((sdk::Globals *)globals_real_address); + } else if constexpr (doghook_platform::linux()) { + auto globals_real_address = (u32) * *signature::find_pattern("client", "8B 15 ? ? ? ? F3 0F 10 88 D0 08 00 00", 2); + IFace().set_from_pointer((sdk::Globals *)globals_real_address); } IFace().set_from_interface("client", "GameMovement"); IFace().set_from_interface("client", "VClientPrediction"); - IFace().set_from_pointer( - *signature::find_pattern( - "client", "8B 0D ? ? ? ? 8B 01 FF 50 28 56", 2)); + + if constexpr (doghook_platform::windows()) + IFace().set_from_pointer( + *signature::find_pattern( + "client", "8B 0D ? ? ? ? 8B 01 FF 50 28 56", 2)); + else if constexpr (doghook_platform::linux()) + IFace().set_from_pointer(nullptr); + + inited = true; } void process_attach() { + // Wait for init... + while (!inited) { + std::this_thread::yield(); + } + Log::msg("process_attach()"); // make sure that the netvars are initialised @@ -130,4 +168,8 @@ auto __stdcall doghook_process_attach([[maybe_unused]] void *hmodule) -> u32 { return 0; } +#elif doghook_platform_linux() +void doghook_process_attach() { + doghook.process_attach(); +} #endif diff --git a/src/doghook.hh b/src/doghook.hh new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/doghook.hh @@ -0,0 +1 @@ +#pragma once diff --git a/src/hooks/createmove.cc b/src/hooks/createmove.cc index d394ab9..5a817da 100644 --- a/src/hooks/createmove.cc +++ b/src/hooks/createmove.cc @@ -8,6 +8,8 @@ #include "modules/aimbot.hh" +#include "utils/math.hh" + using namespace sdk; namespace create_move { @@ -28,18 +30,28 @@ static inline auto local_player_prediction(Player *local, UserCmd *cmd) { IFace()->tickcount = local->tick_base(); // Set the current usercmd and run prediction - local->set(cmd); + if constexpr (doghook_platform::windows()) + local->set(cmd); + else if constexpr (doghook_platform::linux()) + local->set(cmd); IFace()->setup_move(local, cmd, IFace().get(), move_data_buffer); IFace()->process_movement(local, move_data_buffer); IFace()->finish_move(local, cmd, move_data_buffer); - local->set(0); + if constexpr (doghook_platform::windows()) + local->set(0); + else if constexpr (doghook_platform::linux()) + local->set(0); // Cleanup from prediction IFace()->curtime = old_cur_time; IFace()->frametime = old_frame_time; IFace()->tickcount = old_tick_count; + + // TODO: if you do this then make sure to change the fov time calculation + // in aimbot::try_autoshoot!! + //local->tick_base() += 1; } hooks::HookFunction *create_move_hook = nullptr; @@ -51,14 +63,13 @@ bool hooked_create_move(void *instance, float sample_framerate, UserCmd *user_cm #endif { auto local_player = Player::local(); - if (local_player == nullptr) return true; + assert(local_player); // TODO: call original // Currently possible but the method is slow // Fixme in HookFunction! // Do create_move_pre_predict() - aimbot::create_move_pre_predict(user_cmd); local_player_prediction(local_player, user_cmd); @@ -74,7 +85,7 @@ void level_init() { Log::msg("=> Hooking up!"); assert(create_move_hook == nullptr); - create_move_hook = new hooks::HookFunction(IFace().get(), 21, reinterpret_cast(&hooked_create_move)); + create_move_hook = new hooks::HookFunction(IFace().get(), 21, 22, 22, reinterpret_cast(&hooked_create_move)); } void level_shutdown() { diff --git a/src/main.cc b/src/main.cc index c45b651..41f6bc5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,7 @@ #include "precompiled.hh" +#include + #if doghook_platform_windows() extern u32 __stdcall doghook_process_attach(void *a); @@ -18,7 +20,11 @@ __declspec(dllexport) BOOL APIENTRY DllMain(HMODULE hModule, #else // TODO: send process attach over to gamesystem -void __attribute__((constructor)) startup() {} +extern void doghook_process_attach(); + +void __attribute__((constructor)) startup() { + std::thread{&doghook_process_attach}.detach(); +} void __attribute__((destructor)) shutdown() {} #endif diff --git a/src/modules/aimbot.cc b/src/modules/aimbot.cc index cd02360..099aa44 100644 --- a/src/modules/aimbot.cc +++ b/src/modules/aimbot.cc @@ -241,7 +241,7 @@ auto find_targets() { if (e->dormant()) continue; if (valid_target(e)) { - auto pos = math::Vector::invalid(); + auto pos = math::Vector::invalid(); if (visible_target(e, pos)) { finished_target(Target{e, pos}); } @@ -301,7 +301,7 @@ static Convar doghook_aimbot_aim_if_not_attack = Convar{" static Convar doghook_aimbot_disallow_attack_if_no_target = Convar{"doghook_aimbot_disallow_attack_if_no_target", false, nullptr}; void create_move(sdk::UserCmd *cmd) { - if (local_weapon == nullptr) return; + if (local_weapon == nullptr || !can_find_targets) return; find_targets(); @@ -341,6 +341,11 @@ void create_move_pre_predict(sdk::UserCmd *cmd) { local_player = Player::local(); assert(local_player); + if (local_player->alive() == false) { + can_find_targets = false; + return; + } + local_weapon = local_player->active_weapon()->to_weapon(); local_team = local_player->team(); diff --git a/src/precompiled.hh b/src/precompiled.hh index ef70187..21dddf9 100644 --- a/src/precompiled.hh +++ b/src/precompiled.hh @@ -10,5 +10,6 @@ #include #include +#include #include #include diff --git a/src/sdk/convar.cc b/src/sdk/convar.cc index b343ec9..83a3d3f 100644 --- a/src/sdk/convar.cc +++ b/src/sdk/convar.cc @@ -9,6 +9,9 @@ // implementation of a source convar namespace sdk { +// Helper to prevent crashes if Cvar isnt initied properly yet +bool can_init_convars_at_construction_time = false; + class IConVar; using ChangeCallbackFn = void (*)(IConVar *, const char *, float); @@ -33,7 +36,9 @@ public: virtual const char *get_name() const { return name; } virtual const char *get_help_text() const { return help_string; } - virtual bool is_registered() const { return registered; } + virtual bool is_registered() const { + return registered; + } virtual int get_dll_identifier() const { if (dll_identifier == -1) dll_identifier = IFace()->allocate_dll_identifier(); @@ -55,7 +60,7 @@ public: // We might not have Cvar here (global variables) - if (auto cvar = IFace()) { + if (auto cvar = IFace() && can_init_convars_at_construction_time) { IFace()->register_command(this); } } @@ -158,12 +163,19 @@ public: static auto to_iconvar(ConCommandBase *b) { return reinterpret_cast(reinterpret_cast(b) + 24); } auto to_iconvar() -> IConVar * { return ConCommandBase::to_iconvar(this); } +#if doghook_platform_windows() #define DEFINE_THUNK(type, name, real_name) \ static void __fastcall name(IConVar *ecx, void *edx, type v) { \ auto *real = ConCommandBase::from_iconvar(ecx); \ real->real_name(v); \ } - +#elif doghook_platform_linux() +#define DEFINE_THUNK(type, name, real_name) \ + static void name(IConVar *ecx, type v) { \ + auto *real = ConCommandBase::from_iconvar(ecx); \ + real->real_name(v); \ + } +#endif DEFINE_THUNK(const char *, set_value_string_thunk, set_value); DEFINE_THUNK(float, set_value_float_thunk, set_value); DEFINE_THUNK(int, set_value_int_thunk, set_value); @@ -233,7 +245,7 @@ public: // Convar is an mi class and therefore needs this // TODO: is this windows only - what is the linux equivilent?? - void *convar_vtable; + void *convar_vtable; // Should be at 0x24 // Convar members ConCommandBase *parent; @@ -317,6 +329,8 @@ ConvarBase::~ConvarBase() { void ConvarBase::init_all() { assert(IFace()); + sdk::can_init_convars_at_construction_time = true; + // We have to do this goofy loop here as register_command() will // change the `next` pointer to the next in its chain // which will cause all kinds of problems for us diff --git a/src/sdk/entity.cc b/src/sdk/entity.cc index d089890..63950d6 100644 --- a/src/sdk/entity.cc +++ b/src/sdk/entity.cc @@ -11,7 +11,7 @@ using namespace sdk; auto Entity::to_handle() -> EntityHandle & { - return_virtual_func(to_handle, 2, 0, 0, 0); + return_virtual_func(to_handle, 2, 3, 3, 0); } auto Entity::is_valid() -> bool { @@ -37,13 +37,13 @@ auto Entity::to_weapon() -> class Weapon * { } auto Entity::client_class() -> struct ClientClass * { - return_virtual_func(client_class, 2, 0, 0, 8); + return_virtual_func(client_class, 2, 17, 17, 8); } auto Entity::dormant() -> bool { - return_virtual_func(dormant, 8, 0, 0, 8); + return_virtual_func(dormant, 8, 75, 75, 8); } auto Entity::index() -> u32 { - return_virtual_func(index, 9, 0, 0, 8); + return_virtual_func(index, 9, 79, 79, 8); } diff --git a/src/sdk/hooks.hh b/src/sdk/hooks.hh index 3334ea0..b2d390b 100644 --- a/src/sdk/hooks.hh +++ b/src/sdk/hooks.hh @@ -7,6 +7,8 @@ #include #include +// TODO: in all of these cases shouldnt offset be in terms of bytes instead of dwords??? + namespace hooks { template class HookInstance { @@ -42,7 +44,6 @@ class HookInstance { public: HookInstance(T *instance) : instance(instance) { - assert(instance); original_table = get_table(); @@ -127,7 +128,7 @@ class HookFunction { u32 index; public: - HookFunction(T *instance, u32 index, void *f) { + HookFunction(T *instance, u32 index_windows, u32 index_linux, u32 index_osx, void *f) { assert(instance); HookInstance *val = nullptr; @@ -138,6 +139,13 @@ public: } } + // TODO: osx + u32 index; + if constexpr (doghook_platform::windows()) + index = index_windows; + else if constexpr (doghook_platform::linux()) + index = index_linux; + if (val == nullptr) { // we havent hooked this instance yet, so do that now create_hook_instance(instance)->hook_function(index, f); diff --git a/src/sdk/interface.hh b/src/sdk/interface.hh index a112524..9de09bc 100644 --- a/src/sdk/interface.hh +++ b/src/sdk/interface.hh @@ -39,7 +39,7 @@ public: }; template -T *Interface::value; +T *Interface::value = nullptr; template using IFace = Interface; diff --git a/src/sdk/player.cc b/src/sdk/player.cc index 0feac29..aa07b95 100644 --- a/src/sdk/player.cc +++ b/src/sdk/player.cc @@ -25,7 +25,7 @@ auto Player::alive() -> bool { } auto Player::origin() -> math::Vector & { - return_virtual_func(origin, 9, 0, 0, 0); + return_virtual_func(origin, 9, 11, 11, 0); } auto Player::set_origin(const math::Vector &v) -> void { @@ -39,7 +39,7 @@ auto Player::set_origin(const math::Vector &v) -> void { } auto Player::angles() -> math::Vector & { - return_virtual_func(angles, 10, 0, 0, 0); + return_virtual_func(angles, 10, 12, 12, 0); } auto Player::set_angles(const math::Vector &v) -> void { @@ -63,7 +63,7 @@ auto Player::cond() -> u32 & { } auto Player::render_bounds() -> std::pair { - auto func = vfunc::Func(this, 20, 0, 0, 4); + auto func = vfunc::Func(this, 20, 60, 60, 4); std::pair ret; @@ -98,7 +98,7 @@ auto Player::tf_class() -> int { } static auto tick_base = Netvar("DT_BasePlayer", "localdata", "m_nTickBase"); -auto Player::tick_base() -> int { +auto Player::tick_base() -> int & { return ::tick_base.get(this); } @@ -189,11 +189,11 @@ auto Player::view_position() -> math::Vector { } auto Player::bone_transforms(math::Matrix3x4 *hitboxes_out, u32 max_bones, u32 bone_mask, float current_time) -> bool { - return_virtual_func(bone_transforms, 16, 0, 0, 4, hitboxes_out, max_bones, bone_mask, current_time); + return_virtual_func(bone_transforms, 16, 96, 96, 4, hitboxes_out, max_bones, bone_mask, current_time); } auto Player::model_handle() -> const ModelHandle * { - return_virtual_func(model_handle, 9, 0, 0, 4); + return_virtual_func(model_handle, 9, 55, 55, 4); } auto Player::studio_model() -> const StudioModel * { diff --git a/src/sdk/player.hh b/src/sdk/player.hh index 6c40612..3fd9fc8 100644 --- a/src/sdk/player.hh +++ b/src/sdk/player.hh @@ -52,7 +52,7 @@ public: auto tf_class() -> int; - auto tick_base() -> int; + auto tick_base() -> int &; auto sim_time() -> float &; auto anim_time() -> float &; auto cycle() -> float &; diff --git a/src/sdk/sdk.hh b/src/sdk/sdk.hh index 6fe726b..f70e56c 100644 --- a/src/sdk/sdk.hh +++ b/src/sdk/sdk.hh @@ -154,15 +154,19 @@ public: EntList() = delete; auto entity(u32 index) -> Entity * { - return_virtual_func(entity, 3, 0, 0, 0, index); + return_virtual_func(entity, 3, 3, 3, 0, index); } auto from_handle(EntityHandle h) -> Entity * { - return_virtual_func(from_handle, 4, 4, 4, 0, h); + + if constexpr (doghook_platform::windows()) { + return_virtual_func(from_handle, 4, 4, 4, 0, h); + } else if constexpr (doghook_platform::linux()) + return entity(h.serial_index & 0xFFF); } auto max_entity_index() -> u32 { - return_virtual_func(max_entity_index, 6, 0, 0, 0); + return_virtual_func(max_entity_index, 6, 6, 6, 0); } class EntityRange { @@ -365,11 +369,11 @@ public: ModelInfo() = delete; auto model_name(const ModelHandle *m) -> const char * { - return_virtual_func(model_name, 3, 0, 0, 0, m); + return_virtual_func(model_name, 3, 4, 4, 0, m); } auto studio_model(const ModelHandle *m) -> const StudioModel * { - return_virtual_func(studio_model, 28, 0, 0, 0, m); + return_virtual_func(studio_model, 28, 29, 29, 0, m); } }; @@ -416,17 +420,17 @@ class MoveHelper; class Prediction { public: auto setup_move(Player *player, UserCmd *ucmd, MoveHelper *helper, void *move) -> void { - return_virtual_func(setup_move, 18, 18, 18, 0, player, ucmd, helper, move); + return_virtual_func(setup_move, 18, 19, 19, 0, player, ucmd, helper, move); } void finish_move(Player *player, UserCmd *ucmd, void *move) { - return_virtual_func(finish_move, 19, 19, 19, 0, player, ucmd, move); + return_virtual_func(finish_move, 19, 20, 20, 0, player, ucmd, move); } }; class GameMovement { public: void process_movement(Player *player, void *move) { - return_virtual_func(process_movement, 1, 1, 1, 0, player, move); + return_virtual_func(process_movement, 1, 2, 2, 0, player, move); } }; diff --git a/src/sdk/vfunc.hh b/src/sdk/vfunc.hh index f08da1a..3251545 100644 --- a/src/sdk/vfunc.hh +++ b/src/sdk/vfunc.hh @@ -35,7 +35,11 @@ class Func; template class Func { +#if doghook_platform_windows() using function_type = Ret(__thiscall *)(ObjectType *, Args...); +#elif doghook_platform_linux() + using function_type = Ret (*)(ObjectType *, Args...); +#endif function_type f; // On windows this will take into account the offset diff --git a/src/utils/math.hh b/src/utils/math.hh index fdfe2ee..46b221b 100644 --- a/src/utils/math.hh +++ b/src/utils/math.hh @@ -140,12 +140,12 @@ public: else pitch = 90; } else { - yaw = (atan2(y, x) * 180 / PI); + yaw = (to_degrees(atan2(y, x))); if (yaw < 0) yaw += 360; tmp = sqrt(x * x + y * y); - pitch = (atan2(-z, tmp) * 180 / PI); + pitch = (to_degrees(atan2(-z, tmp))); if (pitch < 0) pitch += 360; } @@ -350,3 +350,5 @@ inline void matrix_angles(const Matrix3x4 &matrix, Vector &angles, Vector &posit } } // namespace math + +#define Vector_split_components(v) (v).x, (v).y, (v).z