├── tas ├── valve │ ├── model.h │ ├── entities │ │ ├── client_thinkable.h │ │ ├── base_handle.h │ │ ├── handle_entity.h │ │ ├── base_networkable.h │ │ ├── weapon.h │ │ ├── client_unknown.h │ │ ├── client_entity.h │ │ ├── player.cpp │ │ ├── client_networkable.h │ │ ├── base_entity.cpp │ │ ├── base_entity.h │ │ ├── client_renderable.h │ │ └── player.h │ ├── client_frame_stage.h │ ├── interface_reg.h │ ├── global_vars.h │ ├── client_class.h │ ├── color.h │ ├── app_system.h │ ├── bf_write.h │ ├── render_view.h │ ├── model_info.h │ ├── coord_size.h │ ├── input.h │ ├── entity_list.h │ ├── tracing │ │ ├── trace.h │ │ ├── engine_trace.h │ │ ├── trace_filter.h │ │ ├── trace_filter.cpp │ │ └── mask_defines.h │ ├── recv.h │ ├── usercmd.h │ ├── view_setup.h │ ├── bsp.h │ ├── prediction_copy.h │ ├── bsp.cpp │ ├── datamap.h │ ├── console.h │ ├── client_class_id.h │ ├── studio_header.h │ ├── cvar.h │ ├── base_client.h │ └── prediction.h ├── features │ ├── visual │ │ ├── esp.h │ │ └── esp.cpp │ ├── movement │ │ └── movement.h │ ├── tas │ │ ├── input.h │ │ └── segment.h │ ├── tas.h │ ├── compression_handler.h │ └── compression_handler.cpp ├── core │ ├── settings │ │ └── settings.h │ ├── debug │ │ ├── debug.h │ │ └── debug.cpp │ ├── menu │ │ └── menu.h │ ├── prediction │ │ ├── prediction.h │ │ └── prediction.cpp │ ├── netvars │ │ ├── netvars.h │ │ └── netvars.cpp │ ├── offsets │ │ ├── offsets.h │ │ └── offsets.cpp │ ├── input │ │ ├── input.h │ │ └── input.cpp │ ├── interfaces │ │ ├── interfaces.h │ │ └── interfaces.cpp │ └── player_manager │ │ ├── player_manager.h │ │ └── player_manager.cpp ├── library │ ├── hash.h │ ├── utils.h │ ├── utils.cpp │ ├── render.h │ ├── math.cpp │ ├── screen_position.h │ ├── safe_imgui_draw_cmds.h │ ├── math.h │ ├── safe_imgui_draw_cmds.cpp │ ├── render.cpp │ └── pe.h ├── main.cpp ├── hooks │ ├── hooks.h │ ├── hook.h │ └── hooks.cpp ├── cheat.h └── cheat.cpp ├── .gitignore ├── .gitattributes ├── README.md ├── .clang-format └── CMakeLists.txt /tas/valve/model.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tas/features/visual/esp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace esp { 4 | void run(); 5 | } 6 | -------------------------------------------------------------------------------- /tas/valve/entities/client_thinkable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class client_thinkable_t {}; 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !tas 3 | !.gitignore 4 | !.gitattributes 5 | !.clang-format 6 | !CMakeLists.txt 7 | -------------------------------------------------------------------------------- /tas/valve/entities/base_handle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class base_handle_t { 4 | protected: 5 | unsigned long m_index; 6 | }; 7 | -------------------------------------------------------------------------------- /tas/valve/entities/handle_entity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class handle_entity_t { 4 | public: 5 | virtual ~handle_entity_t() = 0; 6 | virtual void set_ref_handle() = 0; 7 | virtual void get_ref_handle() = 0; 8 | }; 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # CMake. 2 | /**/CMakeLists.txt linguist-generated 3 | 4 | # Default behaviour. 5 | * text=auto 6 | 7 | # LF for source code. 8 | /tas/** text eol=lf 9 | 10 | # Ensure languages for github. 11 | /tas/** linguist-language=C++ 12 | -------------------------------------------------------------------------------- /tas/valve/entities/base_networkable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class client_class_t; 6 | 7 | class base_networkable_t { 8 | virtual void* get_client_unknown() = 0; 9 | virtual void release() = 0; 10 | virtual client_class_t* client_class() = 0; 11 | }; 12 | -------------------------------------------------------------------------------- /tas/valve/client_frame_stage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum client_frame_stage_t { 4 | FRAME_UNDEFINED = -1, 5 | FRAME_START, 6 | FRAME_NET_UPDATE_START, 7 | FRAME_NET_UPDATE_POSTDATAUPDATE_START, 8 | FRAME_NET_UPDATE_POSTDATAUPDATE_END, 9 | FRAME_NET_UPDATE_END, 10 | FRAME_RENDER_START, 11 | FRAME_RENDER_END 12 | }; 13 | -------------------------------------------------------------------------------- /tas/valve/interface_reg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef void* (*instantiate_interface_fn)(); 4 | typedef void* (*create_interface_fn)(const char* name, int return_code); 5 | 6 | class interface_reg_t { 7 | public: 8 | instantiate_interface_fn create_fn; 9 | const char* name; 10 | interface_reg_t* next; 11 | }; 12 | -------------------------------------------------------------------------------- /tas/core/settings/settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace settings { 4 | namespace projectile_aim { 5 | inline bool enabled = false; 6 | } 7 | namespace movement { 8 | inline bool bunny_hop = false; 9 | inline bool auto_strafe = false; 10 | inline bool no_push = false; 11 | } // namespace movement 12 | } // namespace settings 13 | -------------------------------------------------------------------------------- /tas/library/hash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace hash { 6 | template constexpr inline uint32_t hash_crc(T* data, uint32_t value = 0) { 7 | return !(*data) ? value : hash_crc(&data[1], value * 31 + (uint32_t)data[0]); 8 | } 9 | } // namespace hash 10 | 11 | #define HASH(hash_value) std::integral_constant::value 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # css-tas 2 | ## Credits: 3 | [D3X](https://github.com/angelfor3v3r) - Thread safe renderer, menu help, some trigger parsing. 4 | 5 | [cursey](https://github.com/cursey) - KV parser. 6 | 7 | ## Dependencies 8 | glm, freetype, imgui, utfcpp, nlohmann json, PEGTL, safetyhook, zydis 9 | 10 | ## Demo video 11 | [![video](https://img.youtube.com/vi/f-E4Nb5HzrA/maxresdefault.jpg)](https://youtu.be/f-E4Nb5HzrA?si=oCMAdFP8fWNit7Ta) 12 | -------------------------------------------------------------------------------- /tas/valve/global_vars.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class global_vars_t { 4 | public: 5 | float real_time; 6 | int frame_count; 7 | float absolute_frame_time; 8 | float cur_time; 9 | float frame_time; 10 | int max_clients; 11 | int tick_count; 12 | float tick_interval; 13 | float interpolation_amount; 14 | int sim_ticks_this_frame; 15 | int unused0; 16 | int unused1; 17 | bool client; 18 | int unused2; 19 | int unused3; 20 | }; 21 | -------------------------------------------------------------------------------- /tas/valve/client_class.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "recv.h" 4 | 5 | typedef void* (*create_client_class_fn)(int ent_num, int serial_num); 6 | typedef void* (*create_event_fn)(); 7 | 8 | class client_class_t { 9 | public: 10 | create_client_class_fn create; 11 | create_event_fn create_event; 12 | const char* network_name; 13 | recv_table_t* recv_table; 14 | client_class_t* next; 15 | int class_id; 16 | }; 17 | -------------------------------------------------------------------------------- /tas/core/debug/debug.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum e_console_colors { 4 | console_color_white = 15, 5 | console_color_red = 12, 6 | console_color_green = 10, 7 | console_color_cyan = 11, 8 | console_color_beige = 14 9 | }; 10 | 11 | class debug_t { 12 | public: 13 | void open_console(); 14 | void close_console(); 15 | void set_console_color(e_console_colors color); 16 | void print(const char* text, e_console_colors color = e_console_colors::console_color_white); 17 | }; 18 | -------------------------------------------------------------------------------- /tas/library/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace utils { 8 | template T get_virtual_function(void* base, std::uint16_t index) noexcept { 9 | return (*static_cast(base))[index]; 10 | } 11 | 12 | // UTF-16 -> UTF-8. 13 | extern std::string str_utf16_to_8(std::wstring_view str) noexcept; 14 | 15 | // UTF-8 -> UTF-16. 16 | extern std::wstring str_utf8_to_16(std::string_view str) noexcept; 17 | } // namespace utils 18 | -------------------------------------------------------------------------------- /tas/core/menu/menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class form_t; 7 | 8 | namespace menu { 9 | inline bool open{}; 10 | inline bool allow_passthrough{}; 11 | inline auto nudge_step{0.25f}; 12 | inline std::vector> forms{}; 13 | void initialize(); 14 | void on_present(); 15 | } // namespace menu 16 | -------------------------------------------------------------------------------- /tas/valve/color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class color { 5 | public: 6 | int r, g, b, a; 7 | 8 | color(const int r, const int g, const int b, const int a = 255) : r(r), g(g), b(b), a(a) {} 9 | 10 | color operator-(const int val) const { 11 | color return_val = {255, 255, 255}; 12 | return_val.r = std::clamp(this->r - val, 0, 255); 13 | return_val.g = std::clamp(this->g - val, 0, 255); 14 | return_val.b = std::clamp(this->b - val, 0, 255); 15 | 16 | return return_val; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /tas/library/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | 5 | namespace utils { 6 | std::string str_utf16_to_8(std::wstring_view str) noexcept { 7 | std::string res{}; 8 | utf8::unchecked::utf16to8(str.begin(), str.end(), std::back_inserter(res)); 9 | 10 | return res; 11 | } 12 | 13 | std::wstring str_utf8_to_16(std::string_view str) noexcept { 14 | std::wstring res{}; 15 | utf8::unchecked::utf8to16(str.begin(), str.end(), std::back_inserter(res)); 16 | 17 | return res; 18 | } 19 | } // namespace utils -------------------------------------------------------------------------------- /tas/core/prediction/prediction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/prediction.h" 4 | 5 | class prediction_t { 6 | float old_current_time, old_frame_time; 7 | int tick_count; 8 | move_data_t move_data{}; 9 | float time; 10 | bool first_time_prediction = false; 11 | 12 | public: 13 | prediction_t() = default; 14 | void setup(); 15 | void set_time(float time) { this->time = time; } 16 | void set_first_time_prediction(bool first) { this->first_time_prediction = first; } 17 | 18 | bool start(); 19 | void finish(); 20 | }; 21 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | ColumnLimit: 96 4 | --- 5 | Language: Cpp 6 | AccessModifierOffset: -2 7 | SortIncludes: Never 8 | IndentCaseLabels: true 9 | NamespaceIndentation: All 10 | DerivePointerAlignment: false 11 | PointerAlignment: Left 12 | UseCRLF: false 13 | UseTab: Never 14 | AllowShortBlocksOnASingleLine: Empty 15 | AlignConsecutiveMacros: AcrossComments 16 | AlignConsecutiveAssignments: AcrossComments 17 | AlignConsecutiveDeclarations: AcrossComments 18 | BraceWrapping: 19 | AfterCaseLabel: true 20 | AfterUnion: true 21 | BeforeLambdaBody: true 22 | LineEnding: LF 23 | -------------------------------------------------------------------------------- /tas/valve/app_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/interface_reg.h" 4 | 5 | enum init_return_val_t { 6 | INIT_FAILED = 0, 7 | INIT_OK, 8 | INIT_LAST_VAL, 9 | }; 10 | 11 | class app_system_t { 12 | public: 13 | virtual bool connect(create_interface_fn factory) = 0; 14 | virtual void disconnect() = 0; 15 | virtual void* query_interface(const char* p_interface_name) = 0; 16 | virtual init_return_val_t init() = 0; 17 | virtual void shutdown() = 0; 18 | }; 19 | -------------------------------------------------------------------------------- /tas/library/render.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "safe_imgui_draw_cmds.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct render_vertex_t { 12 | float x, y, z; 13 | float rhw; 14 | uint32_t color; 15 | }; 16 | 17 | class render_t { 18 | public: 19 | glm::ivec2 screen_size{}; 20 | IDXGISwapChain* swap_chain{}; 21 | ImFont* tahoma_bold_13{}; 22 | safe_imgui_draw_cmds_t tas_draw_cmds{}; 23 | 24 | void initialize() noexcept; 25 | void detach() noexcept; 26 | void begin() noexcept; 27 | void finish() noexcept; 28 | }; 29 | -------------------------------------------------------------------------------- /tas/valve/entities/weapon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/utils.h" 4 | #include "valve/entities/base_entity.h" 5 | 6 | class weapon_t : public base_entity_t { 7 | public: 8 | netvar_value_func(int, item_id, offsets.base_weapon.item_definition_index); 9 | netvar_value_func(float, next_primary_attack, offsets.base_weapon.next_primary_attack); 10 | netvar_value_func(float, next_secondary_attack, offsets.base_weapon.next_secondary_attack); 11 | netvar_value_func(float, charge_begin_time, offsets.base_weapon.charge_begin_time); 12 | int weapon_id() { 13 | return utils::get_virtual_function(this, 381)(this); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /tas/core/netvars/netvars.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class recv_table_t; 5 | 6 | class netvars_t { 7 | public: 8 | netvars_t(); 9 | ~netvars_t(); 10 | 11 | using var_map_t = std::map; 12 | using table_map_t = std::map; 13 | 14 | table_map_t netvar_map = {}; 15 | 16 | void iterate_props(var_map_t* map, recv_table_t* table, uint32_t offset = 0); 17 | void store_data_map(uint32_t addr); 18 | void find_and_store_data_maps(); 19 | 20 | uintptr_t get_netvar_offset(uint32_t table_name, uint32_t var_name); 21 | inline uintptr_t get_netvar_offset(const char* table_name, const char* var_name); 22 | }; 23 | -------------------------------------------------------------------------------- /tas/valve/bf_write.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma pack(push, 1) 4 | 5 | class bf_write_t { 6 | public: 7 | bf_write_t() noexcept 8 | : m_pData{}, m_nDataBytes{}, m_nDataBits{-1}, m_iCurBit{}, m_bOverflow{}, 9 | m_bAssertOnOverflow{true}, m_pDebugName{} {} 10 | 11 | const auto& IsOverflowed() const noexcept { return m_bOverflow; } 12 | 13 | std::uint32_t* m_pData; 14 | std::int32_t m_nDataBytes; 15 | std::int32_t m_nDataBits; 16 | std::int32_t m_iCurBit; 17 | bool m_bOverflow; 18 | bool m_bAssertOnOverflow; 19 | 20 | private: 21 | std::uint8_t m_pad_00[2]; 22 | 23 | public: 24 | const char* m_pDebugName; 25 | }; 26 | 27 | #pragma pack(pop) -------------------------------------------------------------------------------- /tas/valve/entities/client_unknown.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/entities/handle_entity.h" 4 | 5 | class collideable_t; 6 | class client_renderable_t; 7 | class client_networkable_t; 8 | class client_entity_t; 9 | class client_thinkable_t; 10 | class base_entity_t; 11 | 12 | class client_unknown_t : public handle_entity_t { 13 | public: 14 | virtual collideable_t* collideable() = 0; 15 | virtual client_networkable_t* get_networkable() = 0; 16 | virtual client_renderable_t* get_client_renderable() = 0; 17 | virtual client_entity_t* get_client_entity() = 0; 18 | virtual base_entity_t* get_base_entity() = 0; 19 | virtual client_thinkable_t* get_client_thinkable() = 0; 20 | }; 21 | -------------------------------------------------------------------------------- /tas/main.cpp: -------------------------------------------------------------------------------- 1 | #include "cheat.h" 2 | #include "core/input/input.h" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | DWORD WINAPI initialize(void* arg) { 10 | if (cheat::initialize()) { 11 | while (!cheat::input.key_down(VK_DELETE)) { 12 | Sleep(250); 13 | } 14 | } 15 | 16 | printf("detach\n"); 17 | 18 | cheat::detach(); 19 | 20 | FreeLibraryAndExitThread(static_cast(arg), EXIT_SUCCESS); 21 | } 22 | 23 | BOOL WINAPI DllMain(HINSTANCE self, DWORD reason, LPVOID reserved) { 24 | if (reason == DLL_PROCESS_ATTACH) { 25 | if (auto handle = CreateThread(nullptr, 0, initialize, self, 0, nullptr)) { 26 | CloseHandle(handle); 27 | } 28 | } 29 | 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /tas/valve/entities/client_entity.h: -------------------------------------------------------------------------------- 1 | #include "library/math.h" 2 | 3 | #include "client_networkable.h" 4 | #include "client_unknown.h" 5 | #include "client_renderable.h" 6 | #include "client_thinkable.h" 7 | 8 | class client_entity_t : public client_unknown_t, 9 | public client_renderable_t, 10 | public client_networkable_t, 11 | public client_thinkable_t { 12 | public: 13 | virtual void release(void) = 0; 14 | virtual const vector3_t& get_abs_origin(void) const = 0; 15 | virtual const vector3_t& get_abs_angles(void) const = 0; 16 | virtual void* get_mouth(void) = 0; 17 | virtual bool get_sound_spatialization() = 0; 18 | }; 19 | -------------------------------------------------------------------------------- /tas/hooks/hooks.h: -------------------------------------------------------------------------------- 1 | #include "hook.h" 2 | #include "safetyhook.hpp" 3 | 4 | class usercmd_t; 5 | 6 | class hooks_t { 7 | private: 8 | struct minhook_original_functions { 9 | typedef bool(__stdcall* create_move_fn)(float, usercmd_t*); 10 | create_move_fn create_move; 11 | } minhook_original_functions; 12 | 13 | void setup_detour_hooks() noexcept; 14 | void setup_vtable_hooks() noexcept; 15 | 16 | public: 17 | hook_t client_mode; 18 | hook_t base_client; 19 | hook_t prediction; 20 | hook_t d3d9_device; 21 | hook_t engine_vgui; 22 | SafetyHookVmt input_hook{}; 23 | SafetyHookVm write_usercmd_delta_to_buffer_hook{}; 24 | SafetyHookVm get_usercmd_hook{}; 25 | 26 | void initialize() noexcept; 27 | void detach() noexcept; 28 | }; 29 | -------------------------------------------------------------------------------- /tas/features/movement/movement.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | class movement_t { 6 | public: 7 | static double max_accel_theta(float speed, double wishspeed, bool on_ground = false); 8 | static double max_deccel_theta(float speed, double wishspeed, bool on_ground = false); 9 | static double const_speed_theta(float speed, double wishspeed, bool on_ground = false); 10 | 11 | static double max_accel_into_yaw_theta(const double& speed, const double& vel_yaw, 12 | const double& yaw, const double& wish_speed, 13 | bool on_ground = false); 14 | 15 | void on_create_move(); 16 | void auto_strafe(); 17 | void bunny_hop(); 18 | void correct_movement(); 19 | vector3_t move_angles; 20 | }; 21 | -------------------------------------------------------------------------------- /tas/core/debug/debug.cpp: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | 3 | #include 4 | #include 5 | 6 | void debug_t::open_console() { 7 | AllocConsole(); 8 | 9 | FILE* f{}; 10 | freopen_s(&f, "CONIN$", "r", stdin); 11 | freopen_s(&f, "CONOUT$", "w", stdout); 12 | freopen_s(&f, "CONOUT$", "w", stderr); 13 | 14 | set_console_color(console_color_white); 15 | } 16 | 17 | void debug_t::close_console() { 18 | fclose(stdin); 19 | fclose(stdout); 20 | fclose(stderr); 21 | FreeConsole(); 22 | } 23 | 24 | void debug_t::set_console_color(e_console_colors color) { 25 | const auto console = GetStdHandle(STD_OUTPUT_HANDLE); 26 | SetConsoleTextAttribute(console, color); 27 | } 28 | 29 | void debug_t::print(const char* text, e_console_colors color) { 30 | set_console_color(color); 31 | printf_s("%s\n", text); 32 | } 33 | -------------------------------------------------------------------------------- /tas/valve/render_view.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | class model_t; // TODO: impliment 6 | class view_setup_t; 7 | 8 | class render_view_t { 9 | public: 10 | void get_matrices_for_view(view_setup_t& view, view_matrix_t* world_to_view, 11 | view_matrix_t* view_to_projection, 12 | view_matrix_t* world_to_projection, 13 | view_matrix_t* world_to_pixels) { 14 | return utils::get_virtual_function( 16 | this, 50)(view, world_to_view, view_to_projection, world_to_projection, 17 | world_to_pixels); 18 | } 19 | // virtual void draw_brush_model_ex(client_entity_t* base_entity, model_t* model, const 20 | // vector& origin, const q_angle& angles, draw_brush_model_mode_t mode) = 0; 21 | }; 22 | -------------------------------------------------------------------------------- /tas/features/tas/input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | enum movement_direction_t : int { left, right }; 6 | 7 | enum class yaw_type { set, relative, relative_accel, toward, pre_strafe }; 8 | 9 | struct input_data_t { 10 | float forward_move = 0; 11 | float side_move = 0; 12 | float up_move = 0; 13 | float yaw = 0; 14 | float pitch = 0; 15 | int buttons = 0; 16 | float accel_percentage = 0; 17 | yaw_type yaw_change_type = yaw_type::set; 18 | bool bhop = false; 19 | bool needs_packed = false; 20 | movement_direction_t direction{left}; 21 | float turn_rate = 0; 22 | float turn_accel_rate = 0; 23 | float turn_accel = 0; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /tas/valve/model_info.h: -------------------------------------------------------------------------------- 1 | #include "library/utils.h" 2 | 3 | class model_t; 4 | class studio_header_t; 5 | 6 | class model_info_t { 7 | public: 8 | model_t* GetModel(int index) { 9 | typedef model_t*(__thiscall * GetModelFn)(void*, int); 10 | return utils::get_virtual_function(this, 1)(this, index); 11 | } 12 | 13 | int GetModelIndex(const char* name) { 14 | typedef int(__thiscall * GetModelIndexFn)(void*, const char*); 15 | return utils::get_virtual_function(this, 2)(this, name); 16 | } 17 | 18 | const char* GetModelName(const model_t* model) { 19 | typedef const char*(__thiscall * GetModelNameFn)(void*, const model_t*); 20 | return utils::get_virtual_function(this, 3)(this, model); 21 | } 22 | 23 | studio_header_t* GetStudiomodel(const model_t* mod) { 24 | typedef studio_header_t*(__thiscall * GetStudiomodelFn)(void*, const model_t*); 25 | return utils::get_virtual_function(this, 28)(this, mod); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /tas/valve/coord_size.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // OVERALL Coordinate Size Limits used in COMMON.C MSG_*BitCoord() Routines (and someday the 4 | // HUD) 5 | #define COORD_INTEGER_BITS 14 6 | #define COORD_FRACTIONAL_BITS 5 7 | #define COORD_DENOMINATOR (1 << (COORD_FRACTIONAL_BITS)) 8 | #define COORD_RESOLUTION (1.0 / (COORD_DENOMINATOR)) 9 | 10 | // Special threshold for networking multiplayer origins 11 | #define COORD_FRACTIONAL_BITS_MP_LOWPRECISION 3 12 | #define COORD_DENOMINATOR_LOWPRECISION (1 << (COORD_FRACTIONAL_BITS_MP_LOWPRECISION)) 13 | #define COORD_RESOLUTION_LOWPRECISION (1.0 / (COORD_DENOMINATOR_LOWPRECISION)) 14 | 15 | #define NORMAL_FRACTIONAL_BITS11 16 | #define NORMAL_DENOMINATOR ((1 << (NORMAL_FRACTIONAL_BITS)) - 1) 17 | #define NORMAL_RESOLUTION (1.0 / (NORMAL_DENOMINATOR)) 18 | 19 | // this is limited by the network fractional bits used for coords 20 | // because net coords will be only be accurate to 5 bits fractional 21 | // Standard collision test epsilon 22 | // 1/32nd inch collision epsilon 23 | #define DIST_EPSILON (0.03125) 24 | -------------------------------------------------------------------------------- /tas/core/offsets/offsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct offsets_t { 7 | bool get_offsets(); 8 | 9 | struct { 10 | uint32_t origin, network_origin, team_id, health, life_state, owner, simulation_time, 11 | spawn_time, move_type, mins, maxs, ang_rotation, max_speed, hitbox_set, collision_prop; 12 | } base_entity; 13 | 14 | struct { 15 | uint32_t item_definition_index, clip1, clip2, next_primary_attack, next_secondary_attack, 16 | charge_begin_time; 17 | } base_weapon; 18 | 19 | struct { 20 | uint32_t view_offset, health, life_state, ground, velocity, eye_angles, taunt, flags, 21 | active_weapon, next_attack, max_speed, tick_base, class_id, shared, contraint_entity, 22 | base_velocity, fall_velocity, stamina, surface_friction; 23 | } base_player; 24 | 25 | struct { 26 | uint32_t save_data, restore_data, transfer_data, prediction_copy_init, write_usercmd, 27 | set_collision_bounds; 28 | } functions; 29 | 30 | std::vector datamaps = {}; 31 | } inline offsets; 32 | -------------------------------------------------------------------------------- /tas/valve/input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "usercmd.h" 4 | 5 | #include 6 | 7 | #pragma pack(push, 1) 8 | 9 | constexpr std::int32_t MULTIPLAYER_BACKUP = 90; 10 | 11 | class cinput_t { 12 | public: 13 | virtual ~cinput_t() = 0; 14 | virtual void pad_01() = 0; 15 | virtual void pad_02() = 0; 16 | virtual void pad_03() = 0; 17 | virtual void pad_04() = 0; 18 | virtual void pad_05() = 0; 19 | virtual void pad_06() = 0; 20 | virtual void pad_07() = 0; 21 | virtual usercmd_t* get_usercmd(std::int32_t sequence_number) = 0; 22 | 23 | private: 24 | uint8_t m_pad_00[192]; 25 | 26 | public: 27 | usercmd_t* cmds; 28 | // CVerifiedUserCmd* m_pVerifiedCommands; 29 | }; 30 | 31 | static_assert(offsetof(cinput_t, cmds) == 0xC4); 32 | 33 | #pragma pack(pop) -------------------------------------------------------------------------------- /tas/valve/entities/player.cpp: -------------------------------------------------------------------------------- 1 | #include "player.h" 2 | #include "cheat.h" 3 | #include "library/math.h" 4 | #include "valve/studio_header.h" 5 | 6 | int player_t::restore_data(const char* context, int slot, int type) { 7 | typedef int(__thiscall * restore_data_t)(void*, const char*, int, int); 8 | return utils::get_virtual_function(this, 116)(this, context, slot, type); 9 | } 10 | 11 | bool player_t::hitbox_position(vector3_t& out, int hitbox_number, matrix_3x4_t* matrix, 12 | vector3_t mins, vector3_t max) { 13 | const model_t* model = get_model(); 14 | 15 | if (!model) 16 | return false; 17 | 18 | const studio_header_t* header = cheat::interfaces.model_info->GetStudiomodel(model); 19 | 20 | if (!header) 21 | return false; 22 | 23 | const mstudiobbox_t* hitbox = header->GetHitbox(hitbox_number, hitbox_set()); 24 | 25 | if (!hitbox) 26 | return false; 27 | 28 | vector3_t center = (hitbox->bbmin * mins) + (hitbox->bbmax * max); 29 | 30 | out = math::vector_transform(matrix[hitbox->bone], center); 31 | 32 | return true; 33 | } 34 | -------------------------------------------------------------------------------- /tas/valve/entities/client_networkable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class client_class_t; 4 | class client_unknown_t; 5 | 6 | class client_networkable_t { 7 | public: 8 | virtual client_unknown_t* get_i_client_unknown() = 0; 9 | virtual void release() = 0; 10 | virtual client_class_t* get_client_class() = 0; 11 | virtual void notify_should_transmit() = 0; 12 | virtual void on_pre_data_changed() = 0; 13 | virtual void on_data_changed() = 0; 14 | virtual void pre_data_update() = 0; 15 | virtual void post_data_update() = 0; 16 | virtual bool is_dormant() = 0; 17 | virtual int entity_index() = 0; 18 | virtual void receive_message() = 0; 19 | virtual void* get_data_table_base_ptr() = 0; 20 | virtual void set_destroyed_on_recreate_entities() = 0; 21 | virtual void on_data_unchanged_in_pvs() = 0; 22 | }; 23 | -------------------------------------------------------------------------------- /tas/valve/entity_list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/entities/base_handle.h" 4 | 5 | class client_networkable; 6 | class client_entity; 7 | 8 | class entity_list_t { 9 | public: 10 | virtual client_networkable* get_client_networkable(int entity_number) = 0; 11 | virtual client_networkable* get_client_networkable_from_handle(base_handle_t) = 0; 12 | virtual client_networkable* get_client_unknown_from_handle(base_handle_t) = 0; 13 | 14 | private: 15 | virtual client_entity* get_client_entity(int entity_number) = 0; 16 | virtual client_entity* get_client_entity_from_handle(base_handle_t) = 0; 17 | 18 | public: 19 | virtual int entity_count(bool exclude_non_networkable) = 0; 20 | virtual int get_highest_entity_index(void) = 0; 21 | 22 | private: 23 | virtual void set_max_entities(int max_entities) = 0; 24 | virtual int get_max_entities() = 0; 25 | 26 | public: 27 | template T* get_entity(int entity_number) { 28 | return reinterpret_cast(get_client_entity(entity_number)); 29 | } 30 | template T* get_entity(base_handle_t handle) { 31 | return reinterpret_cast(get_client_entity_from_handle(handle)); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /tas/valve/tracing/trace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../library/math.h" 4 | 5 | #define DISPSURF_FLAG_SURFACE (1 << 0) 6 | #define DISPSURF_FLAG_WALKABLE (1 << 1) 7 | #define DISPSURF_FLAG_BUILDABLE (1 << 2) 8 | #define DISPSURF_FLAG_SURFPROP1 (1 << 3) 9 | #define DISPSURF_FLAG_SURFPROP2 (1 << 4) 10 | 11 | class base_entity_t; 12 | 13 | struct plane_t { 14 | vector3_t normal; 15 | float dist; 16 | std::byte type; 17 | std::byte sign_bits; 18 | std::byte pad[2]; 19 | }; 20 | 21 | struct surface_t { 22 | const char* name; 23 | short surface_props; 24 | unsigned short flags; 25 | }; 26 | 27 | struct trace_t { 28 | vector3_t start{}; 29 | vector3_t end{}; 30 | plane_t plane{}; 31 | float fraction = 0; 32 | int contents = 0; 33 | unsigned short disp_flags = 0; 34 | bool all_solid = 0; 35 | bool start_solid = 0; 36 | float fraction_left_solid = 0.f; 37 | surface_t surface{}; 38 | int hitgroup = 0; 39 | short physics_bone = 0; 40 | base_entity_t* entity = nullptr; 41 | int hitbox = 0; 42 | 43 | bool did_hit() const { return fraction < 1.f || all_solid || start_solid; } 44 | }; 45 | -------------------------------------------------------------------------------- /tas/library/math.cpp: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | #include "cheat.h" 3 | 4 | bool math::world_to_screen(const vector3_t& origin, vector3_t& screen_position) { 5 | view_matrix_t& matrix = cheat::view_matrix; 6 | 7 | const float w = matrix[3][0] * origin.x + matrix[3][1] * origin.y + matrix[3][2] * origin.z + 8 | matrix[3][3]; 9 | 10 | if (w <= 1e-6f) 11 | return false; 12 | 13 | auto half_screen_size = cheat::render.screen_size / 2; 14 | 15 | screen_position.x = static_cast(half_screen_size.x); 16 | screen_position.y = static_cast(half_screen_size.y); 17 | 18 | screen_position.x *= 1 + (matrix[0][0] * origin.x + matrix[0][1] * origin.y + 19 | matrix[0][2] * origin.z + matrix[0][3]) / 20 | w; 21 | screen_position.y *= 1 - (matrix[1][0] * origin.x + matrix[1][1] * origin.y + 22 | matrix[1][2] * origin.z + matrix[1][3]) / 23 | w; 24 | screen_position.z = 0.0f; 25 | 26 | return true; 27 | } 28 | 29 | float math::ticks_to_time(int ticks) { 30 | return (cheat::interfaces.global_vars->tick_interval * (float)(ticks)); 31 | } 32 | 33 | int math::time_to_ticks(float time) { 34 | return static_cast(0.5f + (float)(time) / cheat::interfaces.global_vars->tick_interval); 35 | } 36 | -------------------------------------------------------------------------------- /tas/core/input/input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | enum class InputState : uint8_t { Up, Down }; 12 | 13 | class input_t { 14 | public: 15 | input_t() = default; 16 | 17 | bool key_down(uint8_t vk) const noexcept; 18 | bool key_pressed(uint8_t vk) const noexcept; 19 | 20 | void on_menu_open() noexcept; 21 | void on_menu_close() noexcept; 22 | 23 | void initialize() noexcept; 24 | void detach() noexcept; 25 | void pre_check() noexcept; 26 | void post_check() noexcept; 27 | 28 | SafetyHookInline SetCursorPos_hook{}; 29 | SafetyHookInline GetCursorPos_hook{}; 30 | SafetyHookInline ShowCursor_hook{}; 31 | SafetyHookInline SetCursor_hook{}; 32 | SafetyHookInline GetCursor_hook{}; 33 | SafetyHookInline GetCursorInfo_hook{}; 34 | SafetyHookInline ClipCursor_hook{}; 35 | SafetyHookInline GetClipCursor_hook{}; 36 | 37 | POINT last_cursor_pos{}; 38 | std::int32_t show_cursor_count{}; 39 | HCURSOR last_cursor{}; 40 | RECT last_cursor_clip{}; 41 | WNDPROC orig_wndproc{}; 42 | 43 | std::array keys = {InputState::Up}; 44 | std::array last_keys = {InputState::Up}; 45 | 46 | std::recursive_mutex imgui_mutex{}; 47 | }; 48 | -------------------------------------------------------------------------------- /tas/core/interfaces/interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/entity_list.h" 4 | #include "valve/base_client.h" 5 | #include "valve/engine_client.h" 6 | #include "valve/global_vars.h" 7 | #include "valve/prediction.h" 8 | #include "valve/console.h" 9 | #include "valve/render_view.h" 10 | #include "valve/tracing/engine_trace.h" 11 | #include "valve/view_setup.h" 12 | #include "valve/model_info.h" 13 | #include "valve/input.h" 14 | #include "valve/bsp.h" 15 | 16 | #include 17 | 18 | class interfaces_t { 19 | public: 20 | base_client_t* base_client = nullptr; 21 | engine_client_t* engine_client = nullptr; 22 | void* client_mode = nullptr; 23 | cinput_t* input{}; 24 | ccsgamerules_t** game_rules{}; 25 | entity_list_t* entity_list = nullptr; 26 | prediction_manager_t* prediction = nullptr; 27 | game_movement_t* game_movement = nullptr; 28 | move_helper_t* move_helper = nullptr; 29 | global_vars_t* global_vars = nullptr; 30 | cvar_t* console = nullptr; 31 | IDirect3DDevice9* d3d9_device = nullptr; 32 | engine_trace_t* engine_trace = nullptr; 33 | render_view_t* render_view = nullptr; 34 | void* engine_vgui = nullptr; 35 | model_info_t* model_info = nullptr; 36 | collision_bsp_data_t* bsp_data{}; 37 | 38 | bool collect_interfaces(); 39 | }; 40 | -------------------------------------------------------------------------------- /tas/library/screen_position.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct area_t { 6 | float x = 0; 7 | float y = 0; 8 | float w = 0; 9 | float h = 0; 10 | }; 11 | 12 | struct screen_position_t { 13 | float x = 0; 14 | float y = 0; 15 | 16 | screen_position_t(float x, float y) : x(x), y(y) {} 17 | 18 | void set_x(float other) { x = other; } 19 | void set_y(float other) { y = other; } 20 | 21 | screen_position_t operator+(screen_position_t& other) { 22 | screen_position_t ret = *this; 23 | ret.x += other.x; 24 | ret.y += other.y; 25 | return ret; 26 | } 27 | screen_position_t operator+=(screen_position_t& other) { 28 | this->x += other.x; 29 | this->y += other.y; 30 | return *this; 31 | } 32 | screen_position_t operator+(float other) { 33 | screen_position_t ret = *this; 34 | ret.x += other; 35 | ret.y += other; 36 | return ret; 37 | } 38 | screen_position_t operator-(float other) { 39 | screen_position_t ret = *this; 40 | ret.x -= other; 41 | ret.y -= other; 42 | return ret; 43 | } 44 | bool operator>(screen_position_t other) { return other.x < x && other.y < y; } 45 | bool operator<(screen_position_t other) { return other.x > x && other.y > y; } 46 | bool within_area(float other_x, float other_y, float other2_x, float other2_y) { 47 | return x >= other_x && x <= other2_x && y >= other_y && y <= other2_y; 48 | } 49 | 50 | operator ImVec2() { return {x, y}; } 51 | }; 52 | -------------------------------------------------------------------------------- /tas/valve/recv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class recv_proxy_data; 4 | class recv_prop_t; 5 | class recv_decoder_t; 6 | class recv_table_t; 7 | 8 | typedef void (*recv_var_proxy_fn)(const recv_proxy_data* data, void* strct, void* out); 9 | typedef void (*array_length_proxy_fn)(void* strct, int object_id, int current_array_length); 10 | typedef void (*data_table_recv_var_proxy_fn)(const recv_prop_t* prop, void** out, void* data, 11 | int object_id); 12 | 13 | class recv_prop_t { 14 | public: 15 | const char* var_name; 16 | int recv_type; 17 | int flags; 18 | int string_buffer_size; 19 | bool inside_array; 20 | const void* m_extra_data; 21 | recv_prop_t* array_prop; 22 | array_length_proxy_fn array_length_proxy; 23 | recv_var_proxy_fn proxy; 24 | data_table_recv_var_proxy_fn data_table_proxy; 25 | recv_table_t* data_table; 26 | int offset; 27 | int element_stride; 28 | int num_of_elements; 29 | const char* parent_array_prop_name; 30 | }; 31 | 32 | class recv_table_t { 33 | public: 34 | recv_prop_t* props; 35 | int num_of_props; 36 | recv_decoder_t* decoder; 37 | const char* net_table_name; 38 | 39 | private: 40 | bool initialized; 41 | bool in_main_list; 42 | }; 43 | -------------------------------------------------------------------------------- /tas/valve/usercmd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | #define IN_ATTACK (1 << 0) 6 | #define IN_JUMP (1 << 1) 7 | #define IN_DUCK (1 << 2) 8 | #define IN_FORWARD (1 << 3) 9 | #define IN_BACK (1 << 4) 10 | #define IN_USE (1 << 5) 11 | #define IN_CANCEL (1 << 6) 12 | #define IN_LEFT (1 << 7) 13 | #define IN_RIGHT (1 << 8) 14 | #define IN_MOVELEFT (1 << 9) 15 | #define IN_MOVERIGHT (1 << 10) 16 | #define IN_ATTACK2 (1 << 11) 17 | #define IN_RUN (1 << 12) 18 | #define IN_RELOAD (1 << 13) 19 | #define IN_ALT1 (1 << 14) 20 | #define IN_ALT2 (1 << 15) 21 | #define IN_SCORE (1 << 16) 22 | #define IN_SPEED (1 << 17) 23 | #define IN_WALK (1 << 18) 24 | #define IN_ZOOM (1 << 19) 25 | #define IN_WEAPON1 (1 << 20) 26 | #define IN_WEAPON2 (1 << 21) 27 | #define IN_BULLRUSH (1 << 22) 28 | #define IN_GRENADE1 (1 << 23) 29 | #define IN_GRENADE2 (1 << 24) 30 | #define IN_ATTACK3 (1 << 25) 31 | 32 | #pragma pack(push, 1) 33 | 34 | class usercmd_t { 35 | public: 36 | virtual ~usercmd_t(){}; 37 | 38 | int command_number; 39 | int tick_count; 40 | vector3_t view_angles; 41 | float forward_move; 42 | float side_move; 43 | float up_move; 44 | int buttons; 45 | uint8_t impulse; 46 | 47 | private: 48 | uint8_t m_pad_00[3]; 49 | 50 | public: 51 | int weapon_select; 52 | int weapon_subtype; 53 | int random_seed; 54 | short mousedx; 55 | short mousedy; 56 | bool predicted; 57 | 58 | private: 59 | uint8_t m_pad_01[3]; 60 | }; 61 | 62 | #pragma pack(pop) 63 | -------------------------------------------------------------------------------- /tas/valve/entities/base_entity.cpp: -------------------------------------------------------------------------------- 1 | #include "base_entity.h" 2 | 3 | void collision_property_t::set_collision_bounds(const vector3_t& mins, 4 | const vector3_t& maxs) noexcept { 5 | using set_collision_bounds_fn = 6 | void(__thiscall*)(collision_property_t*, const vector3_t&, const vector3_t&); 7 | static auto fn = 8 | reinterpret_cast(offsets.functions.set_collision_bounds); 9 | 10 | fn(this, mins, maxs); 11 | } 12 | 13 | collision_property_t* base_entity_t::collision_prop() noexcept { return &collision(); } 14 | 15 | void base_entity_t::set_collision_bounds(const vector3_t& mins, 16 | const vector3_t& maxs) noexcept { 17 | auto col = collision_prop(); 18 | if (col == nullptr) { 19 | return; 20 | } 21 | 22 | col->set_collision_bounds(mins, maxs); 23 | } 24 | 25 | bool base_entity_t::get_bounding_box(area_t& out, vector3_t& origin) noexcept { 26 | vector3_t mins_screen = {}, maxs_screen = {}, origin_screen = {}; 27 | 28 | if (!math::world_to_screen(this->mins() + origin, mins_screen) || 29 | !math::world_to_screen(this->maxs() + origin, maxs_screen) || 30 | !math::world_to_screen(origin, origin_screen)) 31 | return false; 32 | 33 | out.h = abs(mins_screen.y - maxs_screen.y); 34 | out.y = std::min(maxs_screen.y, mins_screen.y); 35 | out.w = out.h / 2; 36 | out.x = origin_screen.x - (out.w / 2); 37 | return true; 38 | } 39 | 40 | bool base_entity_t::should_collide(int group, int mask) noexcept { 41 | return utils::get_virtual_function(this, 145)(this, group, 42 | mask); 43 | } -------------------------------------------------------------------------------- /tas/cheat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/input/input.h" 4 | #include "core/prediction/prediction.h" 5 | #include "core/interfaces/interfaces.h" 6 | #include "core/player_manager/player_manager.h" 7 | #include "core/debug/debug.h" 8 | #include "features/movement/movement.h" 9 | #include "features/tas.h" 10 | #include "features/compression_handler.h" 11 | #include "hooks/hooks.h" 12 | #include "library/math.h" 13 | #include "valve/client_frame_stage.h" 14 | #include "library/render.h" 15 | 16 | #include 17 | 18 | class usercmd_t; 19 | class player_t; 20 | class weapon_t; 21 | 22 | namespace cheat { 23 | inline debug_t debug; 24 | inline interfaces_t interfaces; 25 | inline hooks_t hooks; 26 | 27 | inline usercmd_t* cmd; 28 | inline player_t* local_player; 29 | inline weapon_t* local_weapon; 30 | 31 | inline render_t render; 32 | inline input_t input; 33 | 34 | inline HWND window; 35 | 36 | inline prediction_t prediction; 37 | inline movement_t movement; 38 | inline player_list_t player_list; 39 | inline tas_t tas; 40 | inline prediction_netvar_manager compression_manager; 41 | 42 | inline view_matrix_t view_matrix; 43 | 44 | inline std::shared_mutex render_mutex = {}; 45 | 46 | inline bool attached = false; 47 | 48 | inline vector3_t eye_position = vector3_t(0, 0, 0); 49 | 50 | inline std::filesystem::path dir{}; // Directory for saving stuff to. 51 | 52 | bool initialize(); 53 | void get_window_handle(); 54 | void get_view_matrix(); 55 | void detach(); 56 | void get_local_player(); 57 | bool on_create_move(usercmd_t* cmd); 58 | void on_present(); 59 | 60 | void pre_frame_stage_notify(client_frame_stage_t stage); 61 | void post_frame_stage_notify(client_frame_stage_t stage); 62 | } // namespace cheat 63 | -------------------------------------------------------------------------------- /tas/valve/view_setup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | enum stereo_eye_t { 6 | STEREO_EYE_MONO = 0, 7 | STEREO_EYE_LEFT = 1, 8 | STEREO_EYE_RIGHT = 2, 9 | STEREO_EYE_MAX = 3, 10 | }; 11 | 12 | class view_setup_t { 13 | public: 14 | int x = 0; 15 | int unscaled_x = 0; 16 | int y = 0; 17 | int unscaled_y = 0; 18 | int width = 0; 19 | int unscaled_width = 0; 20 | int height = 0; 21 | stereo_eye_t stereo_eye{}; 22 | int unscaled_height = 0; 23 | bool ortho = false; 24 | float ortho_left = 0; 25 | float ortho_top = 0; 26 | float ortho_right = 0; 27 | float ortho_bottom = 0; 28 | float fov = 0; 29 | float fov_viewmodel = 0; 30 | vector3_t origin{}; 31 | vector3_t angles{}; 32 | float near_ = 0; 33 | float far_ = 0; 34 | float near_view_model = 0; 35 | float far_view_model = 0; 36 | bool render_to_subrect_of_largerScreen = false; 37 | float aspect_ratio = 0; 38 | bool off_center = false; 39 | float off_center_top = 0; 40 | float off_center_bottom = 0; 41 | float off_center_left = 0; 42 | float off_center_right = 0; 43 | bool do_blooand_tone_mapping = false; 44 | bool cache_full_screen_state = false; 45 | bool view_to_projection_override = false; 46 | view_matrix_t view_to_projection{}; 47 | }; 48 | -------------------------------------------------------------------------------- /tas/valve/bsp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | constexpr std::size_t MAX_QPATH = 96; 14 | 15 | template class range_validated_array_t { 16 | public: 17 | const auto& operator[](std::int32_t i) const noexcept { return array[i]; } 18 | 19 | T* array; 20 | std::int32_t count; 21 | }; 22 | 23 | // TODO: Move this. 24 | namespace kv { 25 | struct KeyValues { 26 | std::string name{}; 27 | std::string value{}; 28 | std::unordered_map kvs{}; 29 | 30 | auto& operator[](const std::string& key) { return kvs[key]; } 31 | }; 32 | 33 | // Parse a KeyValue. 34 | std::expected, std::string> parse(std::string_view str); 35 | } // namespace kv 36 | 37 | #pragma pack(push, 1) 38 | 39 | class node_t { 40 | public: 41 | }; 42 | 43 | class phys_collide_t { 44 | public: 45 | }; 46 | 47 | class vcollide_t { 48 | public: 49 | std::uint16_t solid_count : 15; 50 | std::uint16_t is_packed : 1; 51 | std::uint16_t desc_size; 52 | phys_collide_t** solids; // VPhysicsSolids 53 | char* key_values; 54 | }; 55 | 56 | class model_t { 57 | public: 58 | vector3_t mins; 59 | vector3_t maxs; 60 | vector3_t origin; 61 | std::int32_t headnode; 62 | vcollide_t vcollisionData; 63 | }; 64 | 65 | static_assert(sizeof(model_t) == 52); 66 | 67 | class collision_bsp_data_t { 68 | public: 69 | node_t* map_rootnode; 70 | char map_name[MAX_QPATH]; 71 | std::uint8_t pad_00[80]; 72 | std::int32_t numcmodels; 73 | range_validated_array_t map_cmodels; 74 | }; 75 | 76 | static_assert(offsetof(collision_bsp_data_t, numcmodels) == 180); 77 | 78 | #pragma pack(pop) -------------------------------------------------------------------------------- /tas/valve/entities/base_entity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client_entity.h" 4 | #include "base_handle.h" 5 | 6 | #include "../../core/offsets/offsets.h" 7 | #include "library/screen_position.h" 8 | #include "library/utils.h" 9 | 10 | class player_t; 11 | class weapon_t; 12 | 13 | class collision_property_t { 14 | public: 15 | void set_collision_bounds(const vector3_t& mins, const vector3_t& maxs) noexcept; 16 | }; 17 | 18 | class base_entity_t : public client_entity_t { 19 | friend player_t; 20 | friend weapon_t; 21 | template inline T get_ptr_at_offset(uint32_t offset) noexcept { 22 | return reinterpret_cast(reinterpret_cast(this) + offset); 23 | } 24 | 25 | template inline T& get_value_at_offset(uint32_t offset) noexcept { 26 | return *get_ptr_at_offset(offset); 27 | } 28 | 29 | #define netvar_value_func(type, name, offset) \ 30 | type& name() noexcept { return get_value_at_offset(offset); } 31 | #define get_ptr_value_func(type, name, offset) \ 32 | type name() noexcept { return get_ptr_at_offset(offset); } 33 | 34 | public: 35 | netvar_value_func(vector3_t, origin, offsets.base_entity.origin); 36 | netvar_value_func(float, simulation_time, offsets.base_entity.simulation_time); 37 | netvar_value_func(vector3_t, velocity, offsets.base_player.velocity); 38 | netvar_value_func(vector3_t, mins, offsets.base_entity.mins); 39 | netvar_value_func(vector3_t, maxs, offsets.base_entity.maxs); 40 | netvar_value_func(int, collision_group, 896); 41 | netvar_value_func(int, team_number, offsets.base_entity.team_id); 42 | netvar_value_func(int, hitbox_set, offsets.base_entity.hitbox_set); 43 | netvar_value_func(collision_property_t, collision, offsets.base_entity.collision_prop); 44 | 45 | collision_property_t* collision_prop() noexcept; 46 | void set_collision_bounds(const vector3_t& mins, const vector3_t& maxs) noexcept; 47 | bool get_bounding_box(area_t& out, vector3_t& origin) noexcept; 48 | bool should_collide(int group, int mask) noexcept; 49 | }; 50 | -------------------------------------------------------------------------------- /tas/core/prediction/prediction.cpp: -------------------------------------------------------------------------------- 1 | #include "prediction.h" 2 | #include "cheat.h" 3 | #include "valve/entities/player.h" 4 | #include "valve/usercmd.h" 5 | 6 | void prediction_t::setup() {} 7 | 8 | bool prediction_t::start() { 9 | if (!cheat::local_player || !cheat::interfaces.move_helper) 10 | return false; 11 | 12 | cheat::interfaces.move_helper->set_host(cheat::local_player); 13 | memset(&move_data, 0, sizeof(move_data)); 14 | 15 | cheat::local_player->current_cmd() = cheat::cmd; 16 | 17 | old_frame_time = cheat::interfaces.global_vars->frame_time; 18 | old_current_time = cheat::interfaces.global_vars->cur_time; 19 | 20 | const bool old_is_first_prediction = cheat::interfaces.prediction->is_first_time_predicted(); 21 | const bool old_in_prediction = cheat::interfaces.prediction->in_prediction(); 22 | 23 | cheat::interfaces.global_vars->cur_time = time; 24 | cheat::interfaces.global_vars->frame_time = cheat::interfaces.global_vars->tick_interval; 25 | 26 | cheat::interfaces.prediction->is_in_prediction = true; 27 | cheat::interfaces.prediction->first_time_predicted = first_time_prediction; 28 | 29 | cheat::interfaces.prediction->set_local_view_angles(cheat::cmd->view_angles); 30 | 31 | cheat::interfaces.game_movement->start_track_prediction_errors(cheat::local_player); 32 | 33 | if (first_time_prediction) 34 | cheat::interfaces.prediction->setup_move(cheat::local_player, cheat::cmd, 35 | cheat::interfaces.move_helper, &move_data); 36 | cheat::interfaces.game_movement->proccess_movement(cheat::local_player, &move_data); 37 | 38 | cheat::interfaces.prediction->finish_move(cheat::local_player, cheat::cmd, &move_data); 39 | 40 | cheat::interfaces.game_movement->finish_tack_prediction_errors(cheat::local_player); 41 | 42 | cheat::interfaces.prediction->is_in_prediction = old_in_prediction; 43 | cheat::interfaces.prediction->first_time_predicted = old_is_first_prediction; 44 | 45 | cheat::interfaces.global_vars->cur_time = old_current_time; 46 | cheat::interfaces.global_vars->frame_time = old_frame_time; 47 | 48 | return true; 49 | } 50 | 51 | void prediction_t::finish() { 52 | if (!cheat::interfaces.move_helper) 53 | return; 54 | 55 | cheat::interfaces.move_helper->set_host(nullptr); 56 | } 57 | -------------------------------------------------------------------------------- /tas/valve/tracing/engine_trace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../../library/math.h" 5 | #include 6 | #include "mask_defines.h" 7 | #include "trace_filter.h" 8 | 9 | struct trace_t; 10 | 11 | struct ray_t { 12 | vector3_a_t start; // starting point, centered within the extents 13 | vector3_a_t delta; // direction + length of the ray 14 | vector3_a_t start_offset; // Add this to m_Start to get the actual ray start 15 | vector3_a_t extents; // Describes an axis aligned box extruded along a ray 16 | bool is_ray; // are the extents zero? 17 | bool is_swept; // is delta != 0? 18 | 19 | void initialize(const vector3_t& start, const vector3_t& end) { 20 | this->delta = end - start; 21 | 22 | this->is_swept = (glm::length(glm::vec2(this->delta)) != 0); 23 | 24 | this->extents = {0, 0, 0}; 25 | this->is_ray = true; 26 | 27 | this->start_offset = {0, 0, 0}; 28 | this->start = start; 29 | } 30 | 31 | void initialize(vector3_t const& start, vector3_t const& end, vector3_t const& mins, 32 | vector3_t const& maxs) { 33 | this->delta = end - start; 34 | 35 | this->is_swept = (glm::length(this->delta) != 0); 36 | 37 | this->extents = (maxs - mins); 38 | this->extents *= 0.5f; 39 | this->is_ray = (glm::length(glm::vec2(this->extents)) < 1e-6); 40 | 41 | // Offset m_Start to be in the center of the box... 42 | vector3_t offset = (mins + maxs) * 0.5f; 43 | 44 | this->start = (start + offset); 45 | this->start_offset = offset; 46 | this->start_offset *= -1.0f; 47 | } 48 | 49 | ray_t() {} 50 | 51 | ray_t(vector3_t vec_start, vector3_t vec_end) { initialize(vec_start, vec_end); } 52 | 53 | ray_t(vector3_t vec_start, vector3_t vec_end, vector3_t min, vector3_t max) { 54 | initialize(vec_start, vec_end, min, max); 55 | } 56 | }; 57 | 58 | class engine_trace_t { 59 | public: 60 | void trace_ray(const ray_t& ray, uint32_t mask, i_trace_filter_t* filter, trace_t* trace) { 61 | typedef void(__thiscall * TraceRayFn)(void*, const ray_t&, unsigned int, i_trace_filter_t*, 62 | trace_t*); 63 | return utils::get_virtual_function(this, 4)(this, ray, mask, filter, trace); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /tas/features/tas/segment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | #include "nlohmann/json.hpp" 6 | 7 | #include "input.h" 8 | 9 | 10 | struct frame_t { 11 | bool crouch = false; 12 | 13 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(frame_t, crouch) 14 | }; 15 | 16 | enum movement_type_t : int { 17 | strafe_towards, 18 | pre_strafe, 19 | manual, 20 | strafe_side, 21 | strafe_accel, 22 | none 23 | }; 24 | 25 | 26 | struct strafe_accel_data_t { 27 | float starting_turn_rate{5.f}; 28 | float accel_percentage{100.f}; 29 | float turn_accel_rate{}; 30 | }; 31 | 32 | struct strafe_side_data_t { 33 | float turn_rate{0.f}; 34 | 35 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(strafe_side_data_t, turn_rate) 36 | }; 37 | 38 | struct strafe_towards_data_t { 39 | float accel_percentage{100.f}; 40 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(strafe_towards_data_t, accel_percentage) 41 | }; 42 | 43 | struct manual_data_t { 44 | bool move_left{false}; 45 | bool move_right{false}; 46 | bool move_forward{false}; 47 | bool move_backward{false}; 48 | float pitch{}; 49 | 50 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(manual_data_t, move_left, move_right, move_forward, 51 | move_backward, pitch) 52 | }; 53 | 54 | struct segment_t { 55 | segment_t() = default; 56 | 57 | frame_t* get_frame(size_t frame) { return &frames[frame]; } 58 | std::vector* get_frames() { return &frames; } 59 | 60 | manual_data_t manual_data{}; 61 | strafe_towards_data_t strafe_towards_data{}; 62 | strafe_side_data_t strafe_side_data{}; 63 | strafe_accel_data_t strafe_accel_data{}; 64 | 65 | bool updated{true}; 66 | int start_tick{}; 67 | int end_tick{}; 68 | std::vector frames{{}}; 69 | movement_type_t move_type{none}; 70 | int selected_frame{}; 71 | uint32_t abs_selected_frame{}; 72 | 73 | bool bunnyhop{}; 74 | bool crouch_hop{}; 75 | movement_direction_t direction{left}; // this is reused for several different modes 76 | float yaw{}; // this is reused for several different modes 77 | 78 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(segment_t, manual_data, strafe_side_data, frames, move_type, 79 | bunnyhop, crouch_hop, direction, yaw) 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /tas/features/tas.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "valve/prediction.h" 4 | #include "library/math.h" 5 | 6 | #include "nlohmann/json.hpp" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "tas/input.h" 13 | #include "tas/segment.h" 14 | 15 | struct packed_map_t { 16 | uint8_t pad[1000]; 17 | 18 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(packed_map_t, pad); 19 | }; 20 | 21 | struct packed_map_holder { 22 | packed_map_holder() {} 23 | packed_map_t map{}; 24 | }; 25 | 26 | struct properties_t { 27 | bool ez_hop = true; 28 | bool updated = false; 29 | 30 | NLOHMANN_DEFINE_TYPE_INTRUSIVE(properties_t, ez_hop, updated) 31 | }; 32 | 33 | struct draw_data_t { 34 | int flags = 0; 35 | }; 36 | 37 | class tas_t { 38 | float cur_time{}; 39 | bool setup{}; 40 | bool needs_update{}; 41 | 42 | int update_from{}; 43 | 44 | std::vector input{}; 45 | std::vector move_data{}; 46 | std::vector draw_data{}; 47 | std::vector segments{}; 48 | std::vector used_segments{segments}; 49 | std::vector> packed_maps{}; 50 | 51 | properties_t properties{}; 52 | 53 | bool in_playback{}; 54 | size_t playback_tick{}; 55 | 56 | void setup_prediction(usercmd_t* cmd); 57 | void process_movement(move_data_t* move_data); 58 | void setup_move_data_input(move_data_t* move_data, input_data_t* input); 59 | void setup_command_input(usercmd_t* command, move_data_t* move_data); 60 | void handle_prediction(); 61 | void generate_input_for_segment(segment_t* segment, int& tick); 62 | void generate_input(); 63 | 64 | public: 65 | int selected_segment{}; 66 | bool start_playback{}; 67 | bool needs_setup{}; 68 | int max_segments_rendered{5}; 69 | std::shared_mutex mutex{}; 70 | bool set_playback_angles{}; 71 | auto& get_segments() { return segments; } 72 | auto& get_properties() { return properties; } 73 | auto& get_packed_maps() noexcept { return packed_maps; } 74 | void draw_frame(move_data_t*, draw_data_t*) noexcept; 75 | void draw_segment(segment_t*, bool selected) noexcept; 76 | void draw() noexcept; 77 | void playback(); 78 | void on_create_move(); 79 | }; 80 | -------------------------------------------------------------------------------- /tas/valve/tracing/trace_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class base_entity_t; 4 | 5 | enum class trace_type_t { 6 | TRACE_EVERYTHING = 0, 7 | TRACE_WORLD_ONLY, 8 | TRACE_ENTITIES_ONLY, 9 | TRACE_EVERYTHING_FILTER_PROPS 10 | }; 11 | 12 | class i_trace_filter_t { 13 | virtual bool should_hit_entity(base_entity_t* ent, int contents_mask) = 0; 14 | virtual trace_type_t get_type() const = 0; 15 | }; 16 | 17 | class trace_filter_t : public i_trace_filter_t { 18 | virtual bool should_hit_entity(base_entity_t* ent, int contents_mask) { 19 | return ent != skip_entity; 20 | } 21 | 22 | virtual trace_type_t get_type() const { return trace_type_t::TRACE_EVERYTHING; } 23 | 24 | public: 25 | trace_filter_t(base_entity_t* skip_entity_) : skip_entity(skip_entity_) {} 26 | 27 | base_entity_t* skip_entity; 28 | }; 29 | 30 | class trace_filter_simple_t : public i_trace_filter_t { 31 | typedef bool (*should_hit_t)(base_entity_t* handle_entity, int contents_mask); 32 | 33 | base_entity_t* pass_ent; 34 | int collision_group; 35 | should_hit_t should_hit_extra_func; 36 | 37 | public: 38 | trace_filter_simple_t(base_entity_t* pass_entity, int collision_group, 39 | should_hit_t should_hit_func = 0) { 40 | pass_ent = pass_entity; 41 | this->collision_group = collision_group; 42 | this->should_hit_extra_func = should_hit_func; 43 | } 44 | 45 | virtual trace_type_t get_type() const { return trace_type_t::TRACE_EVERYTHING; } 46 | 47 | virtual bool should_hit_entity(base_entity_t* handle_entity, int contents_mask); 48 | 49 | virtual void set_pass_entity(base_entity_t* handle_entity) { pass_ent = handle_entity; } 50 | 51 | virtual void set_collision_group(int collision_group) { 52 | this->collision_group = collision_group; 53 | } 54 | }; 55 | 56 | class trace_filter_ignore_players_t : public trace_filter_simple_t { 57 | public: 58 | trace_filter_ignore_players_t(base_entity_t* passentity, int collision_group) 59 | : trace_filter_simple_t(passentity, collision_group) {} 60 | 61 | virtual bool should_hit_entity(base_entity_t* server_entity, int contents_mask); 62 | }; 63 | 64 | class trace_filter_ignore_teammates_t : public trace_filter_simple_t { 65 | public: 66 | trace_filter_ignore_teammates_t(base_entity_t* passentity, int collision_group, 67 | int ignore_team) 68 | : trace_filter_simple_t(passentity, collision_group), ignore_team(ignore_team) {} 69 | 70 | virtual bool should_hit_entity(base_entity_t* server_entity, int contents_mask); 71 | 72 | int ignore_team; 73 | }; 74 | -------------------------------------------------------------------------------- /tas/features/compression_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Windows.h" 4 | #include "library/math.h" 5 | #include 6 | #include 7 | 8 | class datamap_t; 9 | class player_t; 10 | 11 | class managed_netvar { 12 | public: 13 | virtual ~managed_netvar() = default; 14 | 15 | virtual void pre_update(player_t* player, int idx) = 0; 16 | virtual void post_update(player_t* player, int idx) = 0; 17 | 18 | uintptr_t m_offset{}; 19 | }; 20 | 21 | class shared_netvar : public managed_netvar { 22 | public: 23 | shared_netvar(uintptr_t offset, float tolerance, const char* name) : m_tolerance(tolerance) { 24 | m_offset = offset; 25 | m_name = _strdup(name); 26 | } 27 | 28 | void pre_update(player_t* player, int idx) override; 29 | void post_update(player_t* player, int idx) override; 30 | 31 | float m_value[128]{}; 32 | float m_old_value[128]{}; 33 | float m_tolerance{}; 34 | char* m_name{}; 35 | }; 36 | 37 | class managed_vec : public managed_netvar { 38 | public: 39 | managed_vec(uintptr_t offset, float tolerance, const char* name, bool coord = false) 40 | : m_tolerance(tolerance), m_coord(coord) { 41 | m_offset = offset; 42 | m_proxied_offset = offset; 43 | m_name = _strdup(name); 44 | } 45 | 46 | managed_vec(uintptr_t offset, uintptr_t proxied_offset, float tolerance, const char* name, 47 | bool coord = false) 48 | : m_tolerance(tolerance), m_coord(coord) { 49 | m_offset = offset; 50 | m_proxied_offset = proxied_offset; 51 | m_name = _strdup(name); 52 | } 53 | 54 | void pre_update(player_t* player, int idx) override; 55 | void post_update(player_t* player, int idx) override; 56 | 57 | vector3_t m_value[128]{}; 58 | vector3_t m_old_value[128]{}; 59 | float m_tolerance{}; 60 | char* m_name{}; 61 | bool m_coord{}; 62 | uintptr_t m_proxied_offset{}; 63 | }; 64 | 65 | class prediction_netvar_manager { 66 | public: 67 | prediction_netvar_manager() = default; 68 | virtual ~prediction_netvar_manager(); 69 | void reset() { 70 | for (size_t i{}; i < 128; i++) 71 | has_saved[i] = false; 72 | } 73 | void pre_update(player_t*, int); 74 | void post_update(player_t*, int); 75 | void init(datamap_t* map); 76 | 77 | bool has_saved[128]{}; 78 | bool initalized{}; 79 | bool setup_vars{}; 80 | std::vector> vars{}; 81 | std::vector weapon_vars; 82 | bool called_once{}; 83 | }; 84 | -------------------------------------------------------------------------------- /tas/valve/prediction_copy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "datamap.h" 4 | #include "../core/offsets/offsets.h" 5 | 6 | enum { 7 | PC_EVERYTHING = 0, 8 | PC_NON_NETWORKED_ONLY, 9 | PC_NETWORKED_ONLY, 10 | }; 11 | 12 | #define PC_DATA_PACKED true 13 | #define PC_DATA_NORMAL false 14 | 15 | typedef void (*FN_FIELD_COMPARE)(const char* classname, const char* fieldname, 16 | const char* fieldtype, bool networked, bool noterrorchecked, 17 | bool differs, bool withintolerance, const char* value); 18 | 19 | class prediction_copy_t { 20 | 21 | typedef enum { 22 | DIFFERS = 0, 23 | IDENTICAL, 24 | WITHINTOLERANCE, 25 | } difftype_t; 26 | int type; 27 | void* dest; 28 | void const* src; 29 | int dest_offset_index; 30 | int src_offset_index; 31 | 32 | bool error_check; 33 | bool report_errors; 34 | bool describe_fields; 35 | void* current_field; 36 | char const* current_class_name; 37 | datamap_t* current_map; 38 | bool should_report; 39 | bool should_describe; 40 | int error_count; 41 | bool perform_copy; 42 | 43 | FN_FIELD_COMPARE field_compare_func; 44 | 45 | void* watch_field; 46 | char const* operation; 47 | char idk[100]; 48 | 49 | public: 50 | int transfer_data(const char* operation, int entindex, datamap_t* dmap) { 51 | typedef int(__thiscall * sub_1017D4D0)(void*, const char*, int, datamap_t*); 52 | return ((sub_1017D4D0)offsets.functions.transfer_data)(this, operation, entindex, dmap); 53 | } 54 | 55 | prediction_copy_t(int type, void* dest, bool dest_packed, void const* src, bool src_packed, 56 | bool counterrors = false, bool reporterrors = false, 57 | bool performcopy = true, bool describefields = false, 58 | FN_FIELD_COMPARE func = NULL) { 59 | 60 | this->type = type; 61 | this->dest = dest; 62 | this->src = src; 63 | this->dest_offset_index = dest_packed ? TD_OFFSET_PACKED : TD_OFFSET_NORMAL; 64 | this->src_offset_index = src_packed ? TD_OFFSET_PACKED : TD_OFFSET_NORMAL; 65 | this->error_check = counterrors; 66 | this->report_errors = reporterrors; 67 | this->perform_copy = performcopy; 68 | this->describe_fields = describefields; 69 | 70 | this->current_field = NULL; 71 | this->current_map = NULL; 72 | this->current_class_name = NULL; 73 | this->should_report = false; 74 | this->should_describe = false; 75 | this->error_count = 0; 76 | 77 | this->field_compare_func = func; 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /tas/core/netvars/netvars.cpp: -------------------------------------------------------------------------------- 1 | #include "netvars.h" 2 | #include "library/hash.h" 3 | #include "core/debug/debug.h" 4 | #include "valve/datamap.h" 5 | #include "core/offsets/offsets.h" 6 | #include "cheat.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | netvars_t::netvars_t() { 18 | client_class_t* client_class = cheat::interfaces.base_client->get_all_classes(); 19 | 20 | while (client_class) { 21 | recv_table_t* recv_table = client_class->recv_table; 22 | 23 | if (!recv_table) { 24 | client_class = client_class->next; 25 | continue; 26 | } 27 | 28 | const auto table_name = hash::hash_crc(recv_table->net_table_name); 29 | var_map_t var_map; 30 | iterate_props(&var_map, recv_table); 31 | netvar_map.insert({table_name, var_map}); 32 | 33 | client_class = client_class->next; 34 | } 35 | find_and_store_data_maps(); 36 | } 37 | 38 | void netvars_t::store_data_map(uint32_t addr) { 39 | datamap_t* map = nullptr; 40 | uint32_t base, var; 41 | typedescription_t* entry = nullptr; 42 | addr = *(uint32_t*)(addr + 2); 43 | map = (datamap_t*)(addr - 4); 44 | 45 | if (!map || !map->dataNumFields || map->dataNumFields > 200 || !map->dataDesc || 46 | !map->dataClassName) 47 | return; 48 | 49 | base = hash::hash_crc(map->dataClassName); 50 | 51 | for (size_t i = 0; i < map->dataNumFields; i++) { 52 | entry = &map->dataDesc[i]; 53 | if (!entry->fieldName) 54 | continue; 55 | 56 | var = hash::hash_crc(entry->fieldName); 57 | netvar_map[base][var] = entry->fieldOffset[0]; 58 | } 59 | } 60 | 61 | void netvars_t::find_and_store_data_maps() { 62 | if (offsets.datamaps.empty()) 63 | return; 64 | for (auto& addr : offsets.datamaps) { 65 | store_data_map(addr); 66 | } 67 | } 68 | 69 | netvars_t::~netvars_t() { netvar_map.clear(); } 70 | 71 | void netvars_t::iterate_props(var_map_t* map, recv_table_t* table, uint32_t offset) { 72 | if (!table) 73 | return; 74 | for (size_t i = 0; i < table->num_of_props; i++) { 75 | const auto& prop = table->props[i]; 76 | if (prop.data_table && prop.num_of_elements) 77 | iterate_props(map, prop.data_table, offset + prop.offset); 78 | 79 | map->insert({hash::hash_crc(prop.var_name), offset + prop.offset}); 80 | } 81 | } 82 | 83 | uintptr_t netvars_t::get_netvar_offset(uint32_t table_name, uint32_t var_name) { 84 | auto var_map = netvar_map.at(table_name); 85 | return var_map.at(var_name); 86 | } 87 | 88 | uintptr_t netvars_t::get_netvar_offset(const char* table_name, const char* var_name) { 89 | return get_netvar_offset(hash::hash_crc(table_name), hash::hash_crc(var_name)); 90 | } 91 | -------------------------------------------------------------------------------- /tas/core/player_manager/player_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | #include 6 | #include 7 | 8 | class player_t; 9 | 10 | class player_tick_manager_t; 11 | class player_manager_t; 12 | 13 | class player_tick_record_t { 14 | public: 15 | float simulation_time = 0; 16 | int flags = 0; 17 | int lag = 0; 18 | 19 | vector3_t origin; 20 | vector3_t abs_origin; 21 | vector3_t velocity; 22 | vector3_t eye_angles; 23 | vector3_t unstuck_origin; 24 | vector3_t ground_input_wish_dir; 25 | vector3_t air_input_wish_dir; 26 | 27 | std::array bones; 28 | bool bones_setup = false; 29 | 30 | player_tick_manager_t* manager; 31 | player_tick_record_t(player_tick_manager_t*); 32 | }; 33 | 34 | class player_tick_manager_t { 35 | public: 36 | player_tick_manager_t() {} 37 | 38 | void reset() { 39 | records.clear(); 40 | manager = nullptr; 41 | } 42 | 43 | player_manager_t* manager = nullptr; 44 | void update(player_manager_t*); 45 | std::deque records = {}; 46 | }; 47 | 48 | class player_manager_t { 49 | void check_targeting(); 50 | void get_unstuck_position(); 51 | 52 | public: 53 | bool is_target = false; 54 | 55 | uint32_t client_class_id = 0; // TODO: implement this caching 56 | player_t* player; 57 | player_tick_manager_t tick_manager{}; 58 | float simulation_time = 0; 59 | float spawn_time = 0; 60 | int lag = 0; 61 | 62 | bool prediction_successful = false; 63 | vector3_t predicted_origin = vector3_t(0, 0, 0); 64 | vector3_t predicted_velocity = vector3_t(0, 0, 0); 65 | bool needs_input_prediction = true; 66 | 67 | vector3_t origin; 68 | vector3_t abs_origin; 69 | vector3_t velocity; 70 | vector3_t eye_angles; 71 | vector3_t unstuck_origin; 72 | vector3_t ground_input_wish_dir; 73 | vector3_t air_input_wish_dir; 74 | 75 | void reset() { 76 | is_target = false; 77 | client_class_id = 0; 78 | player = nullptr; 79 | tick_manager.reset(); 80 | simulation_time = 0.f; 81 | spawn_time = 0.f; 82 | } 83 | 84 | void soft_reset() {} 85 | 86 | bool check_stuck(const vector3_t& origin); 87 | 88 | void post_network_update(); 89 | 90 | void update(player_t* player_) { 91 | if (player != player_) { 92 | reset(); 93 | player = player_; 94 | } 95 | } 96 | }; 97 | 98 | class player_list_t { 99 | public: 100 | std::array player_lists = {}; 101 | bool initialize(); 102 | void post_network_update(); 103 | }; 104 | -------------------------------------------------------------------------------- /tas/hooks/hook.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class hook_t { 8 | uintptr_t base; 9 | void** m_old_vmt; 10 | std::unique_ptr new_vmt; 11 | size_t size; 12 | bool rtti; 13 | 14 | __forceinline size_t count_methods() const { 15 | auto i{0u}; 16 | 17 | while (m_old_vmt[i] != nullptr) 18 | ++i; 19 | 20 | return i; 21 | } 22 | 23 | public: 24 | bool initialize(uintptr_t base, bool rtti = true) { 25 | // save base class. 26 | this->base = base; 27 | 28 | // get ptr to old VMT. 29 | m_old_vmt = *reinterpret_cast(base); 30 | if (!m_old_vmt) 31 | return false; 32 | 33 | // count number of methods in old VMT. 34 | size = count_methods(); 35 | if (!size) 36 | return false; 37 | 38 | // allocate new VMT. 39 | new_vmt = std::make_unique(rtti ? size + 1 : size); 40 | 41 | this->rtti = rtti; 42 | if (!new_vmt) 43 | return false; 44 | // get raw memory ptr. 45 | const auto vmt = reinterpret_cast(new_vmt.get()); 46 | 47 | if (rtti) { 48 | // copy VMT, starting from RTTI. 49 | std::memcpy(reinterpret_cast(vmt), m_old_vmt - 1, 50 | (size + 1) * sizeof(uintptr_t)); 51 | 52 | // VMTs are ( usually ) stored in the .data section we should be able to just overwrite 53 | // it, so let's do that here. also, since we've copied RTTI ptr then point the new table 54 | // at index 1 ( index 0 contains RTTI ptr ). 55 | *reinterpret_cast(base) = (vmt + sizeof(uintptr_t)); 56 | 57 | // we've sucesfully copied the RTTI ptr. 58 | } 59 | 60 | else { 61 | // copy vmt. 62 | std::memcpy(reinterpret_cast(vmt), m_old_vmt, size * sizeof(uintptr_t)); 63 | 64 | // since VMTs are ( usually ) stored in the .data section we should be able to just 65 | // overwrite it, so let's do that here. 66 | *reinterpret_cast(base) = vmt; 67 | } 68 | return true; 69 | } 70 | 71 | void undo_hooks() { 72 | new_vmt.reset(); 73 | 74 | if (base) 75 | *(uintptr_t*)base = (uintptr_t)m_old_vmt; 76 | 77 | base = uintptr_t{}; 78 | m_old_vmt = nullptr; 79 | size = 0; 80 | rtti = false; 81 | } 82 | 83 | void setup_hook(size_t function_index, uintptr_t func) { 84 | const auto vmt_index{rtti ? function_index + 1 : function_index}; 85 | 86 | // sanity check some stuff first. 87 | if (!m_old_vmt || !new_vmt || vmt_index > size) 88 | return; 89 | 90 | // redirect. 91 | new_vmt[vmt_index] = func; 92 | } 93 | 94 | template T get_virtual_function(size_t function_index) { 95 | return reinterpret_cast(m_old_vmt[function_index]); 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /tas/core/player_manager/player_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "player_manager.h" 2 | #include "valve/entities/player.h" 3 | #include "cheat.h" 4 | #include "library/math.h" 5 | #include "valve/client_class_id.h" 6 | #include "valve/coord_size.h" 7 | 8 | player_tick_record_t::player_tick_record_t(player_tick_manager_t* manager) { 9 | this->manager = manager; 10 | player_manager_t* player_manager = manager->manager; 11 | 12 | origin = player_manager->origin; 13 | abs_origin = player_manager->abs_origin; 14 | velocity = player_manager->velocity; 15 | eye_angles = player_manager->eye_angles; 16 | unstuck_origin = player_manager->unstuck_origin; 17 | ground_input_wish_dir = player_manager->ground_input_wish_dir; 18 | air_input_wish_dir = player_manager->air_input_wish_dir; 19 | 20 | simulation_time = player_manager->simulation_time; 21 | flags = player_manager->player->flags(); 22 | 23 | bones_setup = manager->manager->player->get_client_renderable()->setup_bones( 24 | bones.data(), 128, 0, simulation_time); 25 | } 26 | 27 | void player_tick_manager_t::update(player_manager_t* manager) { 28 | this->manager = manager; 29 | player_tick_record_t record = player_tick_record_t(this); 30 | records.push_front(record); 31 | while (records.size() > 256) 32 | records.pop_back(); 33 | } 34 | 35 | void player_manager_t::post_network_update() { 36 | check_targeting(); 37 | if (player->life_state() != life_state_t::life_alive) 38 | return; 39 | 40 | this->abs_origin = player->get_abs_origin(); 41 | 42 | if (player->simulation_time() <= simulation_time) 43 | return; 44 | 45 | float delta_sim_time = player->simulation_time() - simulation_time; 46 | 47 | predicted_origin = vector3_t(0, 0, 0); 48 | 49 | simulation_time = player->simulation_time(); 50 | 51 | vector3_t updated_origin = player->origin(); 52 | 53 | bool should_override = prediction_successful; 54 | if (prediction_successful) { 55 | vector3_t delta = (predicted_origin - updated_origin); 56 | if (abs(delta.x) > DIST_EPSILON) 57 | should_override = false; 58 | else if (abs(delta.y) > DIST_EPSILON) 59 | should_override = false; 60 | } 61 | 62 | needs_input_prediction = true; 63 | vector3_t last_origin = origin; 64 | if (should_override) { 65 | origin = {predicted_origin.x, predicted_origin.y, updated_origin.z}; 66 | needs_input_prediction = false; 67 | } else { 68 | 69 | origin = updated_origin; 70 | } 71 | 72 | velocity = (origin - last_origin) * (1.f / delta_sim_time); 73 | if (player->flags() & FL_ONGROUND) 74 | velocity.z = 0.f; 75 | 76 | eye_angles = player->eye_angles(); 77 | 78 | tick_manager.update(this); 79 | } 80 | 81 | void player_manager_t::check_targeting() { 82 | auto networkable = player->get_networkable(); 83 | is_target = !networkable->is_dormant() && 84 | player->team_number() != cheat::local_player->team_number() && 85 | player->life_state() == life_alive; 86 | } 87 | bool player_list_t::initialize() { return true; } 88 | void player_list_t::post_network_update() { 89 | for (size_t i = 1; i < cheat::interfaces.global_vars->max_clients; i++) { 90 | player_t* player = cheat::interfaces.entity_list->get_entity(i); 91 | player_lists[i - 1].update(player); 92 | if (player) 93 | player_lists[i - 1].post_network_update(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tas/library/safe_imgui_draw_cmds.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "math.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace ImGui { 14 | extern void outline_text(ImDrawList* draw_list, ImFont* font, float size, const ImVec2& pos, 15 | ImU32 fill_color, ImU32 outline_color, 16 | std::string_view str) noexcept; 17 | 18 | extern void outline_text(ImDrawList* draw_list, const ImVec2& pos, ImU32 fill_color, 19 | ImU32 outline_color, std::string_view str) noexcept; 20 | 21 | extern void outline_text(ImDrawList* draw_list, ImFont* font, const ImVec2& pos, 22 | ImU32 fill_color, ImU32 outline_color, 23 | std::string_view str) noexcept; 24 | 25 | vector2_t outlined_text_size(const char* text, const char* text_end = nullptr, 26 | bool hide_text_after_double_hash = false, 27 | float wrap_width = -1.0f) noexcept; 28 | } // namespace ImGui 29 | 30 | class safe_imgui_draw_cmds_t { 31 | public: 32 | safe_imgui_draw_cmds_t() noexcept = default; 33 | 34 | void line(const vector2_t& start, const vector2_t& end, ImU32 color, float thickness = 1.0f, 35 | bool antialiased = true) noexcept; 36 | 37 | void rect_filled(const vector2_t& pos, const vector2_t& size, ImU32 color, 38 | float rounding = 0.0f) noexcept; 39 | 40 | void rect(const vector2_t& pos, const vector2_t& size, ImU32 color, float rounding = 0.0f, 41 | float thickness = 1.0f) noexcept; 42 | 43 | void text(ImFont* font, const vector2_t& pos, ImU32 color, const std::string& str, 44 | bool center = false) noexcept; 45 | 46 | void text(const vector2_t& pos, ImU32 color, const std::string& str, 47 | bool center = false) noexcept; 48 | 49 | void text(ImFont* font, const vector2_t& pos, ImU32 fill_color, ImU32 outline_color, 50 | const std::string& str, bool center = false) noexcept; 51 | 52 | void text(const vector2_t& pos, ImU32 fill_color, ImU32 outline_color, const std::string& str, 53 | bool center = false) noexcept; 54 | 55 | // Clear all commands. 56 | void clear() noexcept; 57 | 58 | // Flush the temporary commands. 59 | void flush() noexcept; 60 | 61 | // Send commands to draw list. 62 | void draw(ImDrawList* draw_list) noexcept; 63 | 64 | private: 65 | struct line_t { 66 | ImVec2 start{}; 67 | ImVec2 end{}; 68 | ImU32 color{}; 69 | float thickness{}; 70 | bool antialiased{}; 71 | }; 72 | 73 | struct rect_filled_t { 74 | ImVec2 min{}; 75 | ImVec2 max{}; 76 | ImU32 color{}; 77 | float rounding{}; 78 | }; 79 | 80 | struct rect_t { 81 | ImVec2 min{}; 82 | ImVec2 max{}; 83 | ImU32 color{}; 84 | float rounding{}; 85 | float thickness{}; 86 | }; 87 | 88 | struct text_t { 89 | ImFont* font{}; 90 | ImVec2 pos{}; 91 | ImU32 fill_color{}; 92 | ImU32 outline_color{}; 93 | bool outlined{}; 94 | bool center{}; 95 | std::string str{}; 96 | }; 97 | 98 | std::mutex mtx{}; 99 | std::vector> cmds{}, safe_cmds{}; 100 | }; -------------------------------------------------------------------------------- /tas/core/interfaces/interfaces.cpp: -------------------------------------------------------------------------------- 1 | #include "interfaces.h" 2 | #include "cheat.h" 3 | #include "library/hash.h" 4 | #include "library/pe.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | bool interfaces_t::collect_interfaces() { 11 | pe::module_t server_browser; 12 | while (!pe::get_module("serverbrowser.dll", server_browser)) 13 | std::this_thread::sleep_for(std::chrono::milliseconds(300)); 14 | 15 | cheat::debug.print("init client.dll"); 16 | pe::module_t client_dll; 17 | if (!pe::get_module("client.dll", client_dll)) 18 | return false; 19 | 20 | cheat::debug.print("init engine.dll"); 21 | pe::module_t engine_dll; 22 | if (!pe::get_module("engine.dll", engine_dll)) 23 | return false; 24 | 25 | cheat::debug.print("init vstdlib.dll"); 26 | pe::module_t vstdlib_dll; 27 | if (!pe::get_module("vstdlib.dll", vstdlib_dll)) 28 | return false; 29 | 30 | cheat::debug.print("init shaderapidx9.dll"); 31 | pe::module_t shaderapidx9_dll; 32 | if (!pe::get_module("shaderapidx9.dll", shaderapidx9_dll)) 33 | return false; 34 | 35 | // GTFGCClientSystem() func 36 | // [actual address in first opcode] E8 ? ? ? ? 8B C8 E8 ? ? ? ? EB 17 37 | 38 | d3d9_device = **reinterpret_cast( 39 | shaderapidx9_dll.find_pattern_in_memory("A1 ? ? ? ? 50 8B 08 FF 51 0C") + 0x1); 40 | 41 | cheat::debug.print("init client017"); 42 | base_client = client_dll.get_interface(HASH("VClient017")); 43 | cheat::debug.print("init EntityList"); 44 | entity_list = client_dll.get_interface(HASH("VClientEntityList003")); 45 | cheat::debug.print("init clinet prediction"); 46 | prediction = client_dll.get_interface(HASH("VClientPrediction001")); 47 | cheat::debug.print("init gamemovement"); 48 | game_movement = client_dll.get_interface(HASH("GameMovement001")); 49 | cheat::debug.print("init cvar"); 50 | console = vstdlib_dll.get_interface(HASH("VEngineCvar004")); 51 | 52 | cheat::debug.print("init client mode"); 53 | client_mode = **reinterpret_cast((*(std::uintptr_t**)base_client)[10] + 5); 54 | 55 | cheat::debug.print("init input"); 56 | input = **reinterpret_cast( 57 | utils::get_virtual_function(base_client, 5) + 18); 58 | 59 | cheat::debug.print("init game rules"); 60 | game_rules = *reinterpret_cast( 61 | client_dll.find_pattern_in_memory("8B 0D ? ? ? ? 57 8B 01 74 16") + 2); 62 | 63 | cheat::debug.print("init engine client"); 64 | engine_client = engine_dll.get_interface(HASH("VEngineClient013")); 65 | cheat::debug.print("init render view"); 66 | render_view = engine_dll.get_interface(HASH("VEngineRenderView014")); 67 | cheat::debug.print("init vgui"); 68 | engine_vgui = engine_dll.get_interface(HASH("VEngineVGui001")); 69 | cheat::debug.print("init trace client"); 70 | engine_trace = engine_dll.get_interface(HASH("EngineTraceClient003")); 71 | cheat::debug.print("init global vars"); 72 | global_vars = *reinterpret_cast( 73 | engine_dll.find_pattern_in_memory("A1 ? ? ? ? 8B 11 68") + 0x8); 74 | cheat::debug.print("init model info client"); 75 | model_info = engine_dll.get_interface(HASH("VModelInfoClient006")); 76 | 77 | cheat::debug.print("init bsp data"); 78 | bsp_data = *reinterpret_cast( 79 | engine_dll.find_pattern_in_memory("68 ? ? ? ? 56 E8 ? ? ? ? E8") + 1); 80 | 81 | return true; 82 | } 83 | -------------------------------------------------------------------------------- /tas/valve/bsp.cpp: -------------------------------------------------------------------------------- 1 | #include "bsp.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | // All credits to: https://github.com/cursey/vdf-parser 8 | namespace kv { 9 | using namespace tao::pegtl; 10 | 11 | struct State { 12 | std::string item{}; 13 | std::string key{}; 14 | std::string value{}; 15 | std::stack objs{}; 16 | std::vector root{}; 17 | }; 18 | 19 | // Comments are "//" and read until the end of the line. 20 | struct Comment : disable, until> {}; 21 | 22 | // Whitespace characters. 23 | struct Whitespace : one<' ', '\r', '\n', '\t'> {}; 24 | 25 | // Separators (Skip white space and comments). 26 | struct Sep : sor {}; 27 | struct Seps : star {}; 28 | 29 | // Characters. 30 | struct EscapedChar : if_must, sor>> {}; 31 | struct UnescapedChar : not_one<'\r', '\n'> {}; 32 | struct Char : sor {}; 33 | 34 | // String. 35 | struct String : if_must, until, Char>> {}; 36 | 37 | // Key & Values. 38 | struct Key : String {}; 39 | struct Value : String {}; 40 | struct KeyValue : seq {}; 41 | 42 | // KeyValue stack. 43 | struct ObjectName : String {}; 44 | struct ObjectMembers : sor, Seps>, Seps> {}; 45 | struct Object : seq, Seps, one<'{'>, until, ObjectMembers>> {}; 46 | 47 | // Final grammar. 48 | struct Grammar : until> {}; 49 | 50 | template struct Action : nothing {}; 51 | 52 | template <> struct Action { 53 | template static void apply(const Input& in, State& s) { 54 | s.item += in.string_view(); 55 | } 56 | }; 57 | 58 | template <> struct Action { 59 | template static void apply(const Input& in, State& s) { 60 | s.key = std::move(s.item); 61 | } 62 | }; 63 | 64 | template <> struct Action { 65 | template static void apply(const Input& in, State& s) { 66 | s.value = std::move(s.item); 67 | } 68 | }; 69 | 70 | template <> struct Action { 71 | template static void apply(const Input& in, State& s) { 72 | KeyValues obj{.name = std::move(s.key), .value = std::move(s.value)}; 73 | 74 | if (s.objs.empty()) { 75 | // The object has no name (happens w/ root objects sometimes). Just add an empty parent 76 | // to add this kv to. 77 | s.objs.emplace(); 78 | } 79 | 80 | s.objs.top()[obj.name] = std::move(obj); 81 | } 82 | }; 83 | 84 | template <> struct Action { 85 | template static void apply(const Input& in, State& s) { 86 | s.objs.push({.name = std::move(s.item)}); 87 | } 88 | }; 89 | 90 | template <> struct Action { 91 | template static void apply(const Input& in, State& s) { 92 | auto obj = std::move(s.objs.top()); 93 | s.objs.pop(); 94 | 95 | if (s.objs.empty()) { 96 | s.root.emplace_back(std::move(obj)); 97 | } else { 98 | s.objs.top()[obj.name] = std::move(obj); 99 | } 100 | } 101 | }; 102 | 103 | std::expected, std::string> parse(std::string_view str) { 104 | memory_input in{str, ""}; 105 | State state{}; 106 | 107 | try { 108 | tao::pegtl::parse(in, state); 109 | return state.root; 110 | } catch (const std::exception& e) { 111 | return std::unexpected{e.what()}; 112 | } 113 | } 114 | } // namespace kv -------------------------------------------------------------------------------- /tas/features/visual/esp.cpp: -------------------------------------------------------------------------------- 1 | #include "esp.h" 2 | #include "cheat.h" 3 | #include "valve/entities/player.h" 4 | #include "valve/entities/base_entity.h" 5 | #include "library/math.h" 6 | #include "valve/client_class_id.h" 7 | 8 | #include 9 | 10 | bool get_player_box(player_t* player, area_t* box) { 11 | vector3_t bottom, top; 12 | 13 | const vector3_t origin = player->get_abs_origin(); 14 | vector3_t mins = player->mins(), maxs = player->maxs(); 15 | 16 | mins = {origin.x, origin.y, origin.z + mins.z - 0.8f}; 17 | maxs = {origin.x, origin.y, origin.z + maxs.z}; 18 | 19 | if (!math::world_to_screen(mins, bottom) || !math::world_to_screen(maxs, top)) 20 | return false; 21 | 22 | box->h = floorf(bottom.y - top.y); 23 | box->w = ceilf(box->h / 2.f); 24 | box->x = floorf(bottom.x - box->w / 2.f); 25 | box->y = ceilf(bottom.y - box->h); 26 | 27 | int screen_size_x = 0, screen_size_y = 0; // TODO: we should be caching these in renderer 28 | cheat::interfaces.engine_client->get_screen_size(screen_size_x, screen_size_y); 29 | 30 | if (box->h + box->y < 0) 31 | return false; 32 | 33 | if (box->x + box->w < 0) 34 | return false; 35 | 36 | if (box->y > screen_size_y) 37 | return false; 38 | 39 | if (box->x > screen_size_x) 40 | return false; 41 | 42 | return true; 43 | } 44 | 45 | void player_run(player_t* player) { 46 | auto networkable = player->get_networkable(); 47 | if (networkable->is_dormant() || player->life_state() != life_alive) 48 | return; 49 | 50 | area_t box; 51 | if (!player->get_bounding_box(box, player->origin())) 52 | return; 53 | 54 | int alpha = player->team_number() == cheat::local_player->team_number() ? 100 : 255; 55 | 56 | ImColor color = ImColor(255, 255, 255, alpha); 57 | 58 | switch (player->team_number()) { 59 | case TEAM_BLUE: 60 | color = ImColor(131, 198, 242, alpha); 61 | break; 62 | case TEAM_RED: 63 | color = ImColor(227, 68, 71, alpha); 64 | break; 65 | default: 66 | break; 67 | } 68 | 69 | // cheat::render.draw_list->AddRect(ImVec2{box.x - 1, box.y - 1}, 70 | // ImVec2{box.x + (box.w + 1), box.y + (box.h + 1)}, 71 | // IM_COL32(0, 0, 0, 200)); 72 | // cheat::render.draw_list->AddRect(ImVec2{box.x, box.y}, ImVec2{box.x + box.w, box.y + 73 | // box.h}, 74 | // color); 75 | // cheat::render.draw_list->AddRect(ImVec2{box.x + 1, box.y + 1}, 76 | // ImVec2{box.x + (box.w - 1), box.y + (box.h - 1)}, 77 | // IM_COL32(0, 0, 0, 200)); 78 | 79 | player_info_t info; 80 | if (!cheat::interfaces.engine_client->get_player_info( 81 | player->get_networkable()->entity_index(), &info)) 82 | return; 83 | 84 | // ImGui::PushFont(cheat::render.candara_14); 85 | auto text_size = ImGui::CalcTextSize(info.m_name); 86 | // cheat::render.draw_text_outlined( 87 | // ImVec2{box.x + (box.w * 0.5f) - (text_size.x * 0.5f), box.y - (5.f + text_size.y)}, 88 | // IM_COL32(255, 255, 255, 255), IM_COL32(0, 0, 0, 255), info.m_name); 89 | // ImGui::PopFont(); 90 | } 91 | 92 | void esp::run() { 93 | for (int i = 1; i < cheat::interfaces.entity_list->get_highest_entity_index(); ++i) { 94 | base_entity_t* ent = cheat::interfaces.entity_list->get_entity(i); 95 | 96 | if (!ent) 97 | continue; 98 | 99 | auto client_class = ent->get_networkable()->get_client_class(); 100 | if (client_class->class_id == client_class_id::CCSPlayer) { 101 | player_run(reinterpret_cast(ent)); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /tas/valve/datamap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum { 4 | TD_OFFSET_NORMAL = 0, 5 | TD_OFFSET_PACKED = 1, 6 | 7 | // Must be last 8 | TD_OFFSET_COUNT, 9 | }; 10 | 11 | struct datamap_t; 12 | 13 | typedef enum _fieldtypes { 14 | FIELD_VOID = 0, // No type or value 15 | FIELD_FLOAT, // Any floating point value 16 | FIELD_STRING, // A string ID (return from ALLOC_STRING) 17 | FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse 18 | FIELD_QUATERNION, // A quaternion 19 | FIELD_INTEGER, // Any integer or enum 20 | FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression 21 | FIELD_SHORT, // 2 byte integer 22 | FIELD_CHARACTER, // a byte 23 | FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color) 24 | FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded 25 | // class/structure based on an additional typedescription 26 | FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse 27 | // functions 28 | 29 | FIELD_CLASSPTR, // CBaseEntity * 30 | FIELD_EHANDLE, // Entity handle 31 | FIELD_EDICT, // edict_t * 32 | 33 | FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions 34 | // automagically) 35 | FIELD_TIME, // a floating point time (these are fixed up automatically too!) 36 | FIELD_TICK, // an integer tick count( fixed up similarly to time) 37 | FIELD_MODELNAME, // Engine string that is a model name (needs precache) 38 | FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) 39 | 40 | FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar) 41 | FIELD_FUNCTION, // A class function pointer (Think, Use, etc) 42 | 43 | FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace) 44 | 45 | // NOTE: Use float arrays for local transformations that don't need to be fixed up. 46 | FIELD_VMATRIX_WORLDSPACE, // A VMatrix that maps some local space to world space (translation 47 | // is fixed up on level transitions) 48 | FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space 49 | // (translation is fixed up on level transitions) 50 | 51 | FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 ) 52 | FIELD_MODELINDEX, // a model index 53 | FIELD_MATERIALINDEX, // a material index (using the material precache string table) 54 | 55 | FIELD_VECTOR2D, // 2 floats 56 | 57 | FIELD_TYPECOUNT, // MUST BE LAST 58 | } fieldtype_t; 59 | 60 | typedef void (*inputfunc_t)(); 61 | 62 | struct typedescription_t { 63 | fieldtype_t fieldType; 64 | const char* fieldName; 65 | int fieldOffset[TD_OFFSET_COUNT]; // 0 == normal, 1 == packed offset 66 | unsigned short fieldSize; 67 | short flags; 68 | // the name of the variable in the map/fgd data, or the name of the action 69 | const char* externalName; 70 | // pointer to the function set for save/restoring of custom data types 71 | void* pSaveRestoreOps; 72 | // for associating function with string names 73 | inputfunc_t inputFunc; 74 | // For embedding additional datatables inside this one 75 | datamap_t* td; 76 | 77 | // Stores the actual member variable size in bytes 78 | int fieldSizeInBytes; 79 | 80 | // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred 81 | struct typedescription_t* override_field; 82 | 83 | // Used to track exclusion of baseclass fields 84 | int override_count; 85 | 86 | // Tolerance for field errors for float fields 87 | float fieldTolerance; 88 | }; 89 | 90 | struct datamap_t { 91 | typedescription_t* dataDesc; 92 | int dataNumFields; 93 | char const* dataClassName; 94 | datamap_t* baseMap; 95 | 96 | bool chains_validated; 97 | // Have the "packed" offsets been computed 98 | bool packed_offsets_computed; 99 | char pad[2]; 100 | int packed_size; 101 | }; 102 | -------------------------------------------------------------------------------- /tas/valve/console.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cvar.h" 4 | #include "app_system.h" 5 | 6 | class console_display_func_t { 7 | public: 8 | virtual void color_print(const color& clr, const char* p_message) = 0; 9 | virtual void print(const char* message) = 0; 10 | virtual void d_print(const char* message) = 0; 11 | }; 12 | 13 | class cvar_query_t : public app_system_t { 14 | public: 15 | virtual bool are_con_vars_linkable(const convar_t* child, const convar_t* parent) = 0; 16 | }; 17 | 18 | class cvar_t : public app_system_t { 19 | public: 20 | virtual cvar_dll_identifier_t allocate_dll_identifier() = 0; 21 | virtual void register_con_command(con_command_base_t* command_base) = 0; 22 | virtual void unregister_con_command(con_command_base_t* command_base) = 0; 23 | virtual void unregister_con_commands(cvar_dll_identifier_t id) = 0; 24 | virtual const char* get_command_line_value(const char* variable_name) = 0; 25 | virtual con_command_base_t* find_command_base(const char* name) = 0; 26 | virtual const con_command_base_t* find_command_base(const char* name) const = 0; 27 | virtual convar_t* find_var(const char* var_name) = 0; 28 | virtual const convar_t* find_var(const char* var_name) const = 0; 29 | virtual con_command_t* find_command(const char* name) = 0; 30 | virtual const con_command_t* find_command(const char* name) const = 0; 31 | virtual con_command_base_t* get_commands(void) = 0; 32 | virtual const con_command_base_t* get_commands(void) const = 0; 33 | virtual void install_global_change_callback(change_callback_t callback) = 0; 34 | virtual void remove_global_change_callback(change_callback_t callback) = 0; 35 | virtual void call_global_change_callbacks(convar_t* var, const char* old_string, 36 | float fold_value) = 0; 37 | virtual void install_console_display_func(console_display_func_t* display_func) = 0; 38 | virtual void remove_console_display_func(console_display_func_t* display_func) = 0; 39 | virtual void console_color_printf(const color& clr, const char* format, ...) const = 0; 40 | virtual void console_printf(const char* format, ...) const = 0; 41 | virtual void console_d_printf(const char* format, ...) const = 0; 42 | virtual void revert_flagged_convars(int flag) = 0; 43 | virtual void install_cvar_query(cvar_query_t* p_query) = 0; 44 | virtual bool is_material_thread_set_allowed() const = 0; 45 | virtual void queue_material_thread_set_value(convar_t* cvar, const char* value) = 0; 46 | virtual void queue_material_thread_set_value(convar_t* cvar, int value) = 0; 47 | virtual void queue_material_thread_set_value(convar_t* cvar, float value) = 0; 48 | virtual bool has_queued_material_thread_convar_sets() const = 0; 49 | virtual int process_queued_material_thread_con_var_sets() = 0; 50 | 51 | protected: 52 | class cvar_iterator_internal_t; 53 | 54 | public: 55 | class iterator { 56 | public: 57 | inline iterator(cvar_t* icvar); 58 | inline ~iterator(void); 59 | inline void set_first(void); 60 | inline void next(void); 61 | inline bool is_valid(void); 62 | inline con_command_base_t* get(void); 63 | 64 | private: 65 | cvar_iterator_internal_t* m_iter; 66 | }; 67 | 68 | protected: 69 | class cvar_iterator_internal_t { 70 | public: 71 | virtual ~cvar_iterator_internal_t() {} 72 | virtual void set_first(void) = 0; 73 | virtual void next(void) = 0; 74 | virtual bool is_valid(void) = 0; 75 | virtual con_command_base_t* get(void) = 0; 76 | }; 77 | virtual cvar_iterator_internal_t* factory_internal_iterator(void) = 0; 78 | friend class iterator; 79 | }; 80 | -------------------------------------------------------------------------------- /tas/library/math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using vector2_t = glm::vec2; 13 | using vector3_t = glm::vec3; 14 | using vector3_a_t = glm::aligned_vec3; 15 | using matrix_3x4_a_t = glm::aligned_mat3x4; 16 | using matrix_3x4_t = glm::mat3x4; 17 | using view_matrix_t = glm::mat<4, 4, float, glm::defaultp>; 18 | 19 | namespace math { 20 | constexpr double PI = 3.14159265358979323846; 21 | constexpr double PI_2 = 1.57079632679489661923; 22 | constexpr float radian_to_degrees(const double x) { return x * (180.f / PI); } 23 | 24 | constexpr float degrees_to_radian(const float x) { return x * (PI / 180.f); } 25 | 26 | inline float remap_val_clamped(float val, float A, float B, float C, float D) { 27 | if (A == B) 28 | return val >= B ? D : C; 29 | float cVal = (val - A) / (B - A); 30 | cVal = std::clamp(cVal, 0.0f, 1.0f); 31 | 32 | return C + (D - C) * cVal; 33 | } 34 | 35 | inline double normalize_rad(double a) { 36 | a = fmod(a, std::numbers::pi_v * 2); 37 | 38 | if (a >= std::numbers::pi_v) { 39 | a -= 2 * std::numbers::pi_v; 40 | } else if (a < -std::numbers::pi_v) { 41 | a += 2 * std::numbers::pi_v; 42 | } 43 | 44 | return a; 45 | } 46 | 47 | inline vector3_t vector_transform(matrix_3x4_t& matrix, vector3_t offset) { 48 | return vector3_t{glm::dot(offset, vector3_t(matrix[0])) + matrix[0][3], 49 | glm::dot(offset, vector3_t(matrix[1])) + matrix[1][3], 50 | glm::dot(offset, vector3_t(matrix[2])) + matrix[2][3]}; 51 | } 52 | 53 | float ticks_to_time(int ticks); 54 | int time_to_ticks(float time); 55 | 56 | static void sin_cos(float r, float* s, float* c) { 57 | *s = sin(r); 58 | *c = cos(r); 59 | } 60 | 61 | inline float normalize_angle(float angle) { return std::remainder(angle, 360.0f); } 62 | 63 | inline void angle_vector(const vector3_t& from, vector3_t& forward) { 64 | const auto sy = sin(degrees_to_radian(from.y)); 65 | const auto sp = sin(degrees_to_radian(from.x)); 66 | const auto cy = cos(degrees_to_radian(from.y)); 67 | const auto cp = cos(degrees_to_radian(from.x)); 68 | 69 | forward.x = cp * cy; 70 | forward.y = cp * sy; 71 | forward.z = -sp; 72 | } 73 | 74 | inline void angle_vectors(const vector3_t& from, vector3_t* forward, vector3_t* right, 75 | vector3_t* up) { 76 | float sp, sy, sr, cp, cy, cr; 77 | 78 | sin_cos(degrees_to_radian(from.x), &sp, &cp); 79 | sin_cos(degrees_to_radian(from.y), &sy, &cy); 80 | sin_cos(degrees_to_radian(from.z), &sr, &cr); 81 | 82 | if (forward) { 83 | forward->x = cp * cy; 84 | forward->y = cp * sy; 85 | forward->z = -sp; 86 | } 87 | 88 | if (right) { 89 | right->x = -1 * sr * sp * cy + -1 * cr * -sy; 90 | right->y = -1 * sr * sp * sy + -1 * cr * cy; 91 | right->z = -1 * sr * cp; 92 | } 93 | 94 | if (up) { 95 | up->x = cr * sp * cy + -sr * -sy; 96 | up->y = cr * sp * sy + -sr * cy; 97 | up->z = cr * cp; 98 | } 99 | } 100 | 101 | inline float length_2d(vector3_t vector) { 102 | return std::sqrtf(std::pow(vector.x, 2) + std::pow(vector.y, 2)); 103 | } 104 | 105 | constexpr void vector_angle(const vector3_t& from, vector3_t to, vector3_t& result) { 106 | to -= from; 107 | if (to.y == 0.0f && to.x == 0.0f) { 108 | result.x = (to.z > 0.0f) ? 270.0f : 90.0f; 109 | result.y = 0.0f; 110 | } else { 111 | result.x = radian_to_degrees(atan2(-to.z, length_2d(to))); 112 | result.y = radian_to_degrees(atan2(to.y, to.x)); 113 | } 114 | 115 | result.z = 0.0f; 116 | } 117 | 118 | inline float normalize_in_place(vector3_t& vec) { 119 | const float hyp = glm::length(vec); 120 | if (hyp > 0.f) 121 | vec *= (1.f / hyp); 122 | else 123 | vec = vector3_t(0, 0, 0); 124 | return hyp; 125 | } 126 | 127 | inline float delta_to_angle(vector3_t direction, vector3_t to_ang) { 128 | direction *= 1.f / glm::length(direction); 129 | vector3_t forward; 130 | angle_vector(to_ang, forward); 131 | 132 | return radian_to_degrees(acos(glm::dot(forward, direction))); 133 | } 134 | 135 | bool world_to_screen(const vector3_t& origin, vector3_t& screen_position); 136 | 137 | } // namespace math 138 | -------------------------------------------------------------------------------- /tas/valve/client_class_id.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum client_class_id : int { 4 | CTeamTrainWatcher = 0, 5 | CPropVehicleChoreoGeneric = 0, 6 | CWeaponCubemap = 0, 7 | CAI_BaseNPC = 0, 8 | CAK47, 9 | CBaseAnimating, 10 | CBaseAnimatingOverlay, 11 | CBaseCombatCharacter, 12 | CBaseCombatWeapon, 13 | CBaseCSGrenade, 14 | CBaseCSGrenadeProjectile, 15 | CBaseDoor, 16 | CBaseEntity, 17 | CBaseFlex, 18 | CBaseGrenade, 19 | CBaseParticleEntity, 20 | CBasePlayer, 21 | CBaseProjectile, 22 | CBasePropDoor, 23 | CBaseTeamObjectiveResource, 24 | CBaseTempEntity, 25 | CBaseViewModel, 26 | CBeam, 27 | CBoneFollower, 28 | CBreakableProp, 29 | CBreakableSurface, 30 | CC4, 31 | CColorCorrection, 32 | CColorCorrectionVolume, 33 | CCSGameRulesProxy, 34 | CCSPlayer, 35 | CCSPlayerResource, 36 | CCSRagdoll, 37 | CCSTeam, 38 | CDEagle, 39 | CDynamicLight, 40 | CDynamicProp, 41 | CEmbers, 42 | CEntityDissolve, 43 | CEntityFlame, 44 | CEntityParticleTrail, 45 | CEnvDetailController, 46 | CEnvParticleScript, 47 | CEnvProjectedTexture, 48 | CEnvQuadraticBeam, 49 | CEnvScreenEffect, 50 | CEnvScreenOverlay, 51 | CEnvTonemapController, 52 | CEnvWind, 53 | CFireSmoke, 54 | CFireTrail, 55 | CFish, 56 | CFlashbang, 57 | CFogController, 58 | CFootstepControl, 59 | CFunc_Dust, 60 | CFunc_LOD, 61 | CFuncAreaPortalWindow, 62 | CFuncConveyor, 63 | CFuncLadder, 64 | CFuncMonitor, 65 | CFuncOccluder, 66 | CFuncReflectiveGlass, 67 | CFuncRotating, 68 | CFuncSmokeVolume, 69 | CFuncTrackTrain, 70 | CGameRulesProxy, 71 | CHandleTest, 72 | CHEGrenade, 73 | CHostage, 74 | CInfoLadderDismount, 75 | CInfoLightingRelative, 76 | CInfoOverlayAccessor, 77 | CKnife, 78 | CLightGlow, 79 | CMaterialModifyControl, 80 | CParticleFire, 81 | CParticlePerformanceMonitor, 82 | CParticleSystem, 83 | CPhysBox, 84 | CPhysBoxMultiplayer, 85 | CPhysicsProp, 86 | CPhysicsPropMultiplayer, 87 | CPhysMagnet, 88 | CPlantedC4, 89 | CPlasma, 90 | CPlayerResource, 91 | CPointCamera, 92 | CPointCommentaryNode, 93 | CPoseController, 94 | CPrecipitation, 95 | CPredictedViewModel, 96 | CPropJeep, 97 | CPropVehicleDriveable, 98 | CRagdollManager, 99 | CRagdollProp, 100 | CRagdollPropAttached, 101 | CRopeKeyframe, 102 | CSceneEntity, 103 | CShadowControl, 104 | CSlideshowDisplay, 105 | CSmokeGrenade, 106 | CSmokeStack, 107 | CSpotlightEnd, 108 | CSprite, 109 | CSpriteOriented, 110 | CSpriteTrail, 111 | CSteamJet, 112 | CSun, 113 | CTeam, 114 | CTeamplayRoundBasedRulesProxy, 115 | CTEArmorRicochet, 116 | CTEBaseBeam, 117 | CTEBeamEntPoint, 118 | CTEBeamEnts, 119 | CTEBeamFollow, 120 | CTEBeamLaser, 121 | CTEBeamPoints, 122 | CTEBeamRing, 123 | CTEBeamRingPoint, 124 | CTEBeamSpline, 125 | CTEBloodSprite, 126 | CTEBloodStream, 127 | CTEBreakModel, 128 | CTEBSPDecal, 129 | CTEBubbles, 130 | CTEBubbleTrail, 131 | CTEClientProjectile, 132 | CTEDecal, 133 | CTEDust, 134 | CTEDynamicLight, 135 | CTEEffectDispatch, 136 | CTEEnergySplash, 137 | CTEExplosion, 138 | CTEFireBullets, 139 | CTEFizz, 140 | CTEFootprintDecal, 141 | CTEGaussExplosion, 142 | CTEGlowSprite, 143 | CTEImpact, 144 | CTEKillPlayerAttachments, 145 | CTELargeFunnel, 146 | CTEMetalSparks, 147 | CTEMuzzleFlash, 148 | CTEParticleSystem, 149 | CTEPhysicsProp, 150 | CTEPlantBomb, 151 | CTEPlayerAnimEvent, 152 | CTEPlayerDecal, 153 | CTEProjectedDecal, 154 | CTERadioIcon, 155 | CTEShatterSurface, 156 | CTEShowLine, 157 | CTesla, 158 | CTESmoke, 159 | CTESparks, 160 | CTESprite, 161 | CTESpriteSpray, 162 | CTest_ProxyToggle_Networkable, 163 | CTestTraceline, 164 | CTEWorldDecal, 165 | CVGuiScreen, 166 | CVoteController, 167 | CWaterBullet, 168 | CWaterLODControl, 169 | CWeaponAug, 170 | CWeaponAWP, 171 | CWeaponCSBase, 172 | CWeaponCSBaseGun, 173 | CWeaponCycler, 174 | CWeaponElite, 175 | CWeaponFamas, 176 | CWeaponFiveSeven, 177 | CWeaponG3SG1, 178 | CWeaponGalil, 179 | CWeaponGlock, 180 | CWeaponM249, 181 | CWeaponM3, 182 | CWeaponM4A1, 183 | CWeaponMAC10, 184 | CWeaponMP5Navy, 185 | CWeaponP228, 186 | CWeaponP90, 187 | CWeaponScout, 188 | CWeaponSG550, 189 | CWeaponSG552, 190 | CWeaponTMP, 191 | CWeaponUMP45, 192 | CWeaponUSP, 193 | CWeaponXM1014, 194 | CWorld, 195 | DustTrail, 196 | MovieExplosion, 197 | NextBotCombatCharacter, 198 | ParticleSmokeGrenade, 199 | RocketTrail, 200 | SmokeTrail, 201 | SporeExplosion, 202 | SporeTrail, 203 | }; 204 | -------------------------------------------------------------------------------- /tas/features/compression_handler.cpp: -------------------------------------------------------------------------------- 1 | #include "compression_handler.h" 2 | 3 | #include "core/offsets/offsets.h" 4 | #include "glm/gtc/noise.inl" 5 | #include "valve/entities/player.h" 6 | 7 | auto get_new(float old_val, float new_val, float tolerance) noexcept { 8 | return glm::abs(new_val - old_val) <= tolerance ? old_val : new_val; 9 | } 10 | 11 | glm::vec3 get_new(const vector3_t& old_val, const vector3_t& new_val, 12 | float tolerance) noexcept { 13 | return {get_new(old_val.x, new_val.x, tolerance), get_new(old_val.y, new_val.y, tolerance), 14 | get_new(old_val.z, new_val.z, tolerance)}; 15 | } 16 | 17 | void shared_netvar::post_update(player_t* player, int idx) { 18 | m_value[idx] = *reinterpret_cast(reinterpret_cast(player) + m_offset); 19 | *reinterpret_cast(reinterpret_cast(player) + m_offset) = 20 | get_new(m_old_value[idx], m_value[idx], m_tolerance); 21 | } 22 | 23 | void shared_netvar::pre_update(player_t* player, int idx) { 24 | m_old_value[idx] = 25 | *reinterpret_cast(reinterpret_cast(player) + m_offset); 26 | } 27 | 28 | void managed_vec::pre_update(player_t* player, int idx) { 29 | m_old_value[idx] = *reinterpret_cast(reinterpret_cast(player) + 30 | m_proxied_offset); 31 | } 32 | 33 | void managed_vec::post_update(player_t* player, int idx) { 34 | m_value[idx] = 35 | *reinterpret_cast(reinterpret_cast(player) + m_offset); 36 | *reinterpret_cast(reinterpret_cast(player) + m_offset) = 37 | get_new(m_old_value[idx], m_value[idx], m_tolerance); 38 | } 39 | 40 | void prediction_netvar_manager::pre_update(player_t* player, int idx) { 41 | has_saved[idx] = true; 42 | 43 | for (auto&& var : vars) { 44 | var->pre_update(player, idx); 45 | } 46 | } 47 | 48 | void prediction_netvar_manager::post_update(player_t* player, int idx) { 49 | if (!has_saved[idx]) { 50 | return; 51 | } 52 | 53 | for (auto&& var : vars) { 54 | var->post_update(player, idx); 55 | } 56 | } 57 | 58 | constinit float EQUAL_EPSILON = 1e-3; 59 | 60 | bool CloseEnough(float a, float b, float epsilon = EQUAL_EPSILON) { 61 | return glm::abs(a - b) <= epsilon; 62 | } 63 | 64 | float AssignRangeMultiplier(int nBits, double range) { 65 | unsigned long iHighValue; 66 | if (nBits == 32) { 67 | iHighValue = 0xFFFFFFFE; 68 | } else { 69 | iHighValue = (1 << (unsigned long)nBits) - 1; 70 | } 71 | 72 | auto fHighLowMul = static_cast(iHighValue / range); 73 | if (CloseEnough(static_cast(range), 0)) { 74 | fHighLowMul = static_cast(iHighValue); 75 | } 76 | 77 | // If the precision is messing us up, then adjust it so it won't. 78 | if ((unsigned long)(fHighLowMul * range) > iHighValue || 79 | fHighLowMul * range > (double)iHighValue) { 80 | // Squeeze it down smaller and smaller until it's going to produce an 81 | // integer in the valid range when given the highest value. 82 | float multipliers[] = {0.9999f, 0.99f, 0.9f, 0.8f, 0.7f}; 83 | int i; 84 | for (i = 0; i < ARRAYSIZE(multipliers); i++) { 85 | fHighLowMul = (float)(iHighValue / range) * multipliers[i]; 86 | if ((unsigned long)(fHighLowMul * range) > iHighValue || 87 | fHighLowMul * range > (double)iHighValue) { 88 | } else { 89 | break; 90 | } 91 | } 92 | 93 | if (i == ARRAYSIZE(multipliers)) { 94 | // Doh! We seem to be unable to represent this range. 95 | return 0; 96 | } 97 | } 98 | 99 | return fHighLowMul; 100 | } 101 | 102 | void prediction_netvar_manager::init(datamap_t* map) { 103 | if (std::exchange(initalized, true)) { 104 | return; 105 | } 106 | 107 | float val = 1.0f / AssignRangeMultiplier(17, 4096.0f - -4096.0f); 108 | vars.push_back(std::make_unique(offsets.base_player.fall_velocity, val, 109 | "m_flFallVelocity")); 110 | val = 1.0f / AssignRangeMultiplier(14, 1400.0f); 111 | vars.push_back(std::make_unique(offsets.base_player.stamina, val, "stamina")); 112 | 113 | val = 1.0f / AssignRangeMultiplier(20, 2000.0f); 114 | printf("%d\n", offsets.base_player.base_velocity); 115 | printf("%f\n", val); 116 | vars.push_back(std::make_unique(offsets.base_player.base_velocity, val, 117 | "m_vecBaseVelocity")); 118 | } 119 | 120 | prediction_netvar_manager::~prediction_netvar_manager() { 121 | for (auto&& i : vars) { 122 | i.reset(); 123 | } 124 | 125 | vars.clear(); 126 | } 127 | -------------------------------------------------------------------------------- /tas/core/offsets/offsets.cpp: -------------------------------------------------------------------------------- 1 | #include "offsets.h" 2 | #include "cheat.h" 3 | #include "core/netvars/netvars.h" 4 | #include "library/hash.h" 5 | #include "library/pe.h" 6 | 7 | #include 8 | 9 | bool offsets_t::get_offsets() { 10 | cheat::debug.print("base weapon offsets initialized", console_color_red); 11 | 12 | pe::module_t client_dll; 13 | if (!pe::get_module("client.dll", client_dll)) 14 | return false; 15 | functions.set_collision_bounds = 16 | client_dll.find_pattern_in_memory("55 8B EC 83 EC 2C 53 8B 5D 0C 56 57 8B 7D 08"); 17 | functions.save_data = client_dll.find_pattern_in_memory("55 8B EC 83 EC 7C 53 57"); 18 | functions.restore_data = client_dll.find_pattern_in_memory("55 8B EC 83 EC 7C 53 56 57"); 19 | functions.transfer_data = client_dll.find_pattern_in_memory("55 8B EC FF 05 ?? ?? ?? ?? 53"); 20 | functions.prediction_copy_init = 21 | client_dll.find_pattern_in_memory("55 8B EC 8B 45 08 89 01 8B 45 0C 89 41 04 8B 45 14"); 22 | functions.write_usercmd = client_dll.find_pattern_in_memory("55 8B EC 8B 45 10 83 EC 08"); 23 | cheat::debug.print("client module offsets initialized", console_color_red); 24 | datamaps = client_dll.find_all_pattern_in_memory( 25 | "C7 05 ? ? ? ? ? ? ? ? C7 05 ? ? ? ? ? ? ? ? C3 CC"); 26 | netvars_t netvars; 27 | cheat::debug.print("initalizing netvars"); 28 | 29 | base_entity.origin = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_vecOrigin")); 30 | // base_entity.network_origin = 31 | // netvars.get_netvar_offset(HASH("DT_BaseEntity"), 32 | // HASH("m_vecNetworkOrigin")); 33 | base_entity.mins = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_vecMins")); 34 | base_entity.maxs = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_vecMaxs")); 35 | 36 | base_entity.move_type = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("movetype")); 37 | base_entity.simulation_time = 38 | netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_flSimulationTime")); 39 | base_entity.owner = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_hOwnerEntity")); 40 | base_entity.team_id = netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_iTeamNum")); 41 | base_entity.ang_rotation = 42 | netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_angRotation")); 43 | base_entity.hitbox_set = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_nHitboxSet")); 44 | base_entity.collision_prop = 45 | netvars.get_netvar_offset(HASH("DT_BaseEntity"), HASH("m_Collision")); 46 | 47 | cheat::debug.print("base entity offsets initialized", console_color_red); 48 | 49 | base_player.view_offset = 50 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_vecViewOffset[0]")); 51 | base_player.flags = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_fFlags")); 52 | base_player.tick_base = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_nTickBase")); 53 | base_player.life_state = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_lifeState")); 54 | base_player.health = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_iHealth")); 55 | base_player.velocity = 56 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_vecVelocity[0]")); 57 | base_player.max_speed = 58 | netvars.get_netvar_offset(HASH("DT_BasePlayer"), HASH("m_flMaxspeed")); 59 | base_player.eye_angles = 60 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_angEyeAngles[0]")); 61 | base_player.active_weapon = 62 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_hActiveWeapon")); 63 | base_player.contraint_entity = 64 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_hConstraintEntity")); 65 | base_player.next_attack = 66 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_flNextAttack")); 67 | base_player.stamina = netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_flStamina")); 68 | base_player.fall_velocity = 69 | netvars.get_netvar_offset(HASH("DT_CSPlayer"), HASH("m_flFallVelocity")); 70 | base_player.base_velocity = 71 | netvars.get_netvar_offset(HASH("C_BasePlayer"), HASH("m_vecBaseVelocity")); 72 | base_player.surface_friction = 73 | netvars.get_netvar_offset(HASH("C_BasePlayer"), HASH("m_surfaceFriction")); 74 | 75 | cheat::debug.print("base player offsets initialized", console_color_red); 76 | 77 | base_weapon.next_primary_attack = 78 | netvars.get_netvar_offset(HASH("DT_BaseCombatWeapon"), HASH("m_flNextPrimaryAttack")); 79 | base_weapon.next_secondary_attack = 80 | netvars.get_netvar_offset(HASH("DT_BaseCombatWeapon"), HASH("m_flNextSecondaryAttack")); 81 | base_weapon.clip1 = netvars.get_netvar_offset(HASH("DT_BaseCombatWeapon"), HASH("m_iClip1")); 82 | base_weapon.clip2 = netvars.get_netvar_offset(HASH("DT_BaseCombatWeapon"), HASH("m_iClip2")); 83 | 84 | return true; 85 | } 86 | -------------------------------------------------------------------------------- /tas/cheat.cpp: -------------------------------------------------------------------------------- 1 | #include "cheat.h" 2 | 3 | #include "core/menu/menu.h" 4 | #include "core/settings/settings.h" 5 | #include "library/math.h" 6 | #include "library/pe.h" 7 | #include "library/utils.h" 8 | #include "core/offsets/offsets.h" 9 | #include "valve/client_frame_stage.h" 10 | #include "valve/entities/base_entity.h" 11 | #include "valve/entities/player.h" 12 | #include "valve/usercmd.h" 13 | #include "core/prediction/prediction.h" 14 | #include "features/visual/esp.h" 15 | 16 | #include 17 | 18 | void cheat::get_window_handle() { 19 | D3DDEVICE_CREATION_PARAMETERS creation_params; 20 | 21 | interfaces.d3d9_device->GetCreationParameters(&creation_params); 22 | 23 | window = creation_params.hFocusWindow; 24 | } 25 | 26 | void cheat::get_view_matrix() { 27 | view_setup_t setup; 28 | if (!interfaces.base_client->get_player_view(setup)) 29 | return; 30 | 31 | view_matrix_t matrix1, matrix2, matrix3; 32 | interfaces.render_view->get_matrices_for_view(setup, &matrix1, &matrix2, &view_matrix, 33 | &matrix3); 34 | } 35 | 36 | bool cheat::initialize() { 37 | debug.open_console(); 38 | 39 | debug.print("init misc"); 40 | 41 | PWSTR localappdata_path{}; 42 | if (SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &localappdata_path) != 43 | S_OK) { 44 | return false; 45 | } 46 | 47 | dir = utils::str_utf16_to_8(localappdata_path); 48 | 49 | CoTaskMemFree(localappdata_path); 50 | 51 | dir /= "css_tas"; 52 | 53 | // Create the cheat dirs if they don't exist. 54 | std::error_code ec{}; 55 | 56 | if (std::filesystem::create_directories(dir, ec); ec) { 57 | return false; 58 | } 59 | 60 | if (std::filesystem::create_directories(dir / "configs", ec); ec) { 61 | return false; 62 | } 63 | 64 | debug.print("init interfaces"); 65 | if (!interfaces.collect_interfaces()) 66 | return false; 67 | 68 | debug.print("init window handle"); 69 | get_window_handle(); 70 | 71 | debug.print("init render"); 72 | render.initialize(); 73 | 74 | debug.print("init input"); 75 | input.initialize(); 76 | 77 | debug.print("init offsets"); 78 | offsets.get_offsets(); 79 | 80 | // debug.print("init player list"); 81 | // player_list.initialize(); 82 | 83 | // debug.print("init move sim"); 84 | // movement_simulation.initialize(); 85 | 86 | // debug.print("init proj aimbot"); 87 | // projectile_aimbot.initialize(); 88 | 89 | debug.print("init menu"); 90 | menu::initialize(); 91 | 92 | debug.print("init hooks"); 93 | hooks.initialize(); 94 | 95 | debug.print("flush modules"); 96 | pe::flush_module_cache(); 97 | 98 | attached = true; 99 | 100 | return true; 101 | } 102 | 103 | void cheat::detach() { 104 | attached = false; 105 | hooks.detach(); 106 | debug.close_console(); 107 | render.detach(); 108 | input.detach(); 109 | } 110 | 111 | void cheat::get_local_player() { 112 | local_player = interfaces.entity_list->get_entity( 113 | interfaces.engine_client->get_local_player()); 114 | if (local_player) { 115 | // eye_position = local_player->eye_position(); 116 | local_weapon = 117 | interfaces.entity_list->get_entity(local_player->active_weapon_handle()); 118 | } 119 | } 120 | 121 | bool cheat::on_create_move(usercmd_t* current_cmd) { 122 | if (!current_cmd || !attached) 123 | return false; 124 | 125 | cmd = current_cmd; 126 | 127 | get_local_player(); 128 | 129 | if (!local_player || local_player->life_state() != life_alive) 130 | return false; 131 | 132 | // movement.on_create_move(); 133 | 134 | local_player->save_data("pre_pred", 10, 0); 135 | prediction.setup(); 136 | 137 | tas.on_create_move(); 138 | 139 | prediction.finish(); 140 | 141 | local_player->restore_data("post_pred", 10, 0); 142 | 143 | // movement.correct_movement(); 144 | 145 | // cmd->view_angles.y = math::normalize_angle(cmd->view_angles.y); 146 | // cmd->view_angles.x = std::clamp(cmd->view_angles.x, -89.9f, 89.9f); 147 | // cmd->view_angles.z = std::clamp(cmd->view_angles.z, -45.f, 45.f); 148 | 149 | return false; 150 | } 151 | 152 | void cheat::on_present() { 153 | // std::scoped_lock _{imgui_mutex}; 154 | 155 | if (!attached) 156 | return; 157 | 158 | get_local_player(); 159 | 160 | input.pre_check(); 161 | 162 | render.begin(); 163 | if (local_player) { 164 | // esp::run(); 165 | } 166 | 167 | menu::on_present(); 168 | input.post_check(); 169 | 170 | render.finish(); 171 | } 172 | 173 | void cheat::pre_frame_stage_notify(client_frame_stage_t stage) {} 174 | 175 | void cheat::post_frame_stage_notify(client_frame_stage_t stage) { 176 | return; 177 | if (stage == FRAME_NET_UPDATE_POSTDATAUPDATE_END) { 178 | player_list.post_network_update(); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /tas/valve/entities/client_renderable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | #include "valve/entities/client_unknown.h" 5 | 6 | typedef unsigned short client_shadow_handle_t; 7 | typedef unsigned short client_render_handle_t; 8 | typedef unsigned short model_instance_handle_t; 9 | 10 | enum shadow_type_t { 11 | SHADOWS_NONE = 0, 12 | SHADOWS_SIMPLE, 13 | SHADOWS_RENDER_TO_TEXTURE, 14 | SHADOWS_RENDER_TO_TEXTURE_DYNAMIC, 15 | SHADOWS_RENDER_TO_DEPTH_TEXTURE, 16 | }; 17 | 18 | class model_t; 19 | 20 | class client_renderable_t { 21 | public: 22 | virtual client_unknown_t* get_i_client_unknown() = 0; 23 | virtual vector3_t const& get_render_origin(void) = 0; 24 | virtual vector3_t const& get_render_angles(void) = 0; 25 | virtual bool should_draw(void) = 0; 26 | virtual bool is_transparent(void) = 0; 27 | virtual bool uses_power_of_two_frame_buffer_texture() = 0; 28 | virtual bool uses_full_frame_buffer_texture() = 0; 29 | virtual client_shadow_handle_t get_shadow_handle() const = 0; 30 | virtual client_render_handle_t& render_handle() = 0; 31 | virtual const model_t* get_model() const = 0; 32 | virtual int draw_model(int flags) = 0; 33 | virtual int get_body() = 0; 34 | virtual void compute_fx_blend() = 0; 35 | virtual int get_fx_blend(void) = 0; 36 | virtual void get_color_modulation(float* color) = 0; 37 | virtual bool lod_test() = 0; 38 | virtual bool setup_bones(matrix_3x4_t* bone_to_world_out, int max_bones, int bone_mask, 39 | float current_time) = 0; 40 | virtual void setup_weights(const matrix_3x4_a_t* bone_to_world, int flex_weight_count, 41 | float* flex_weights, float* flex_delayed_weights) = 0; 42 | virtual void do_animation_events(void) = 0; 43 | virtual void* get_pvs_notify_interface() = 0; 44 | virtual void get_render_bounds(vector3_t& mins, vector3_t& maxs) = 0; 45 | virtual void get_render_bounds_worldspace(vector3_t& mins, vector3_t& maxs) = 0; 46 | virtual void get_shadow_render_bounds(vector3_t& mins, vector3_t& maxs, 47 | shadow_type_t shadow_type) = 0; 48 | virtual bool should_receive_projected_textures(int flags) = 0; 49 | virtual bool get_shadow_cast_distance(float* dist, shadow_type_t shadow_type) const = 0; 50 | virtual bool get_shadow_cast_direction(vector3_t* direction, 51 | shadow_type_t shadow_type) const = 0; 52 | virtual bool is_shadow_dirty() = 0; 53 | virtual void mark_shadow_dirty(bool dirty) = 0; 54 | virtual client_renderable_t* get_shadow_parent() = 0; 55 | virtual client_renderable_t* first_shadow_child() = 0; 56 | virtual client_renderable_t* next_shadow_peer() = 0; 57 | virtual shadow_type_t shadow_cast_type() = 0; 58 | virtual void create_model_instance() = 0; 59 | virtual model_instance_handle_t get_model_instance() = 0; 60 | virtual const matrix_3x4_a_t& renderable_to_world_transform() = 0; 61 | virtual int lookup_attachment(const char* attachment_name) = 0; 62 | virtual bool get_attachment(int number, vector3_t& origin, vector3_t& angles) = 0; 63 | virtual bool get_attachment(int number, matrix_3x4_a_t& matrix) = 0; 64 | virtual float* get_render_clip_plane(void) = 0; 65 | virtual int get_skin() = 0; 66 | virtual bool is_two_pass(void) = 0; 67 | virtual void on_threaded_draw_setup() = 0; 68 | virtual bool uses_flex_delayed_weights() = 0; 69 | virtual void record_tool_message() = 0; 70 | virtual bool ignores_z_buffer(void) const = 0; 71 | }; 72 | -------------------------------------------------------------------------------- /tas/valve/entities/player.h: -------------------------------------------------------------------------------- 1 | #include "base_entity.h" 2 | #include "library/math.h" 3 | #include "valve/entities/base_handle.h" 4 | #include 5 | #include "../datamap.h" 6 | 7 | class usercmd_t; 8 | 9 | #define FL_ONGROUND (1 << 0) 10 | #define FL_DUCKING (1 << 1) 11 | #define FL_WATERJUMP (1 << 2) 12 | #define FL_ONTRAIN (1 << 3) 13 | #define FL_INRAIN (1 << 4) 14 | #define FL_FROZEN (1 << 5) 15 | #define FL_ATCONTROLS (1 << 6) 16 | #define FL_CLIENT (1 << 7) 17 | #define FL_FAKECLIENT (1 << 8) 18 | #define FL_INWATER (1 << 9) 19 | 20 | enum team_id : int { TEAM_NONE, TEAM_SPEC, TEAM_RED, TEAM_BLUE }; 21 | 22 | enum collision_group_t : int { 23 | COLLISION_GROUP_NONE = 0, 24 | COLLISION_GROUP_DEBRIS, // Collides with nothing but world and static stuff 25 | COLLISION_GROUP_DEBRIS_TRIGGER, // Same as debris, but hits triggers 26 | COLLISION_GROUP_INTERACTIVE_DEBRIS, // Collides with everything except other interactive 27 | // debris or debris 28 | COLLISION_GROUP_INTERACTIVE, // Collides with everything except interactive debris or debris 29 | COLLISION_GROUP_PLAYER, 30 | COLLISION_GROUP_BREAKABLE_GLASS, 31 | COLLISION_GROUP_VEHICLE, 32 | COLLISION_GROUP_PLAYER_MOVEMENT, // For HL2, same as Collision_Group_Player, for 33 | // TF2, this filters out other players and CBaseObjects 34 | COLLISION_GROUP_NPC, // Generic NPC group 35 | COLLISION_GROUP_IN_VEHICLE, // for any entity inside a vehicle 36 | COLLISION_GROUP_WEAPON, // for any weapons that need collision detection 37 | COLLISION_GROUP_VEHICLE_CLIP, // vehicle clip brush to restrict vehicle movement 38 | COLLISION_GROUP_PROJECTILE, // Projectiles! 39 | COLLISION_GROUP_DOOR_BLOCKER, // Blocks entities not permitted to get near moving doors 40 | COLLISION_GROUP_PASSABLE_DOOR, // Doors that the player shouldn't collide with 41 | COLLISION_GROUP_DISSOLVING, // Things that are dissolving are in this group 42 | COLLISION_GROUP_PUSHAWAY, // Nonsolid on client and server, pushaway in player code 43 | 44 | COLLISION_GROUP_NPC_ACTOR, // Used so NPCs in scripts ignore the player. 45 | COLLISION_GROUP_NPC_SCRIPTED, // USed for NPCs in scripts that should not collide with each 46 | // other 47 | 48 | LAST_SHARED_COLLISION_GROUP 49 | }; 50 | 51 | enum tf_collision_group_t { 52 | TF_COLLISIONGROUP_GRENADES = LAST_SHARED_COLLISION_GROUP, 53 | TFCOLLISION_GROUP_OBJECT, 54 | TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT, 55 | TFCOLLISION_GROUP_COMBATOBJECT, 56 | TFCOLLISION_GROUP_ROCKETS, // Solid to players, but not player movement. ensures touch calls 57 | // are originating from rocket 58 | TFCOLLISION_GROUP_RESPAWNROOMS, 59 | TFCOLLISION_GROUP_TANK, 60 | TFCOLLISION_GROUP_ROCKET_BUT_NOT_WITH_OTHER_ROCKETS, 61 | 62 | // 63 | // ADD NEW ITEMS HERE TO AVOID BREAKING DEMOS 64 | // 65 | }; 66 | enum life_state_t : char { 67 | life_alive, 68 | life_dying, 69 | life_dead, 70 | life_respawnable, 71 | life_discardbody 72 | }; 73 | 74 | class player_t : public base_entity_t { 75 | public: 76 | netvar_value_func(uint32_t, flags, offsets.base_player.flags); 77 | netvar_value_func(uint32_t, tick_base, offsets.base_player.tick_base); 78 | netvar_value_func(life_state_t, life_state, offsets.base_player.life_state); 79 | netvar_value_func(int, health, offsets.base_player.health); 80 | netvar_value_func(float, max_speed, offsets.base_player.max_speed); 81 | netvar_value_func(vector3_t, eye_angles, offsets.base_player.eye_angles); 82 | netvar_value_func(vector3_t, view_offset, offsets.base_player.view_offset); 83 | netvar_value_func(base_handle_t, active_weapon_handle, offsets.base_player.active_weapon); 84 | netvar_value_func(usercmd_t*, current_cmd, 0x101C); 85 | netvar_value_func(float, next_attack_time, offsets.base_player.next_attack); 86 | netvar_value_func(float, stamina, offsets.base_player.stamina); 87 | netvar_value_func(float, fall_velocity, offsets.base_player.fall_velocity); 88 | netvar_value_func(float, surface_friction, offsets.base_player.surface_friction); 89 | netvar_value_func(vector3_t, base_velocity, offsets.base_player.base_velocity); 90 | 91 | int restore_data(const char* context, int slot, int type); 92 | 93 | typedef int(__thiscall* save_data_t)(void*, const char*, int, int); 94 | 95 | int save_data(const char* context, int slot, int type) { 96 | return ((save_data_t)offsets.functions.save_data)(this, context, slot, type); 97 | } 98 | 99 | bool hitbox_position(vector3_t& out, int hitbox, matrix_3x4_t* matrix, 100 | vector3_t mins = vector3_t{0, 0, 0}, 101 | vector3_t maxs = vector3_t{0, 0, 0}); 102 | 103 | vector3_t eye_position() { return origin() + view_offset(); } 104 | datamap_t* get_data_map() { 105 | typedef datamap_t* (*datamap_func)(); 106 | return utils::get_virtual_function(this, 15)(); 107 | } 108 | 109 | // netvar_value_func(vector3_t, origin, offsets.base_entity.origin); 110 | // netvar_value_func(vector3_t, origin, offsets.base_entity.origin); 111 | // netvar_value_func(vector3_t, origin, offsets.base_entity.origin); 112 | }; 113 | -------------------------------------------------------------------------------- /tas/valve/tracing/trace_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "trace_filter.h" 2 | #include "cheat.h" 3 | #include "valve/entities/player.h" 4 | 5 | bool StandardFilterRules(void* pHandleEntity, int fContentsMask) { 6 | base_entity_t* ent = (base_entity_t*)(pHandleEntity); 7 | 8 | // Static prop case... 9 | if (!ent) 10 | return true; 11 | // const auto collide = ent->get_collideable(); 12 | // if (!collide) 13 | // return true; 14 | 15 | // solid_type_t solid = collide->get_solid(); 16 | // const model_t* pModel = collide->get_collision_model(); 17 | 18 | // if ((modelinfo->GetModelType(pModel) != mod_brush) || (solid != SOLID_BSP && solid != 19 | // SOLID_VPHYSICS)) 20 | //{ 21 | // if ((fContentsMask & CONTENTS_MONSTER) == 0) 22 | // return false; 23 | // } 24 | 25 | // This code is used to cull out tests against see-thru entities 26 | // if (!(fContentsMask & CONTENTS_WINDOW) && collide->IsTransparent()) 27 | // return false; 28 | 29 | // FIXME: this is to skip BSP models that are entities that can be 30 | // potentially moved/deleted, similar to a monster but doors don't seem to 31 | // be flagged as monsters 32 | // FIXME: the FL_WORLDBRUSH looked promising, but it needs to be set on 33 | // everything that's actually a worldbrush and it currently isn't 34 | // if (!(fContentsMask & CONTENTS_MOVEABLE) && (collid() == MOVETYPE_PUSH))// !(touch->flags & 35 | // FL_WORLDBRUSH) ) 36 | // return false; 37 | // 38 | return true; 39 | } 40 | 41 | bool PassServerEntityFilter(const void* pTouch, const void* pPass) { 42 | if (!pPass) 43 | return true; 44 | 45 | if (pTouch == pPass) 46 | return false; 47 | 48 | const auto* pEntTouch = (base_entity_t*)(pTouch); 49 | const auto* pEntPass = (base_entity_t*)(pPass); 50 | if (!pEntTouch || !pEntPass) 51 | return true; 52 | 53 | // don't clip against own missiles 54 | // if (pEntTouch->GetOwnerEntity() == pEntPass) 55 | // return false; 56 | // 57 | //// don't clip against owner 58 | // if (pEntPass->GetOwnerEntity() == pEntTouch) 59 | // return false; 60 | 61 | return true; 62 | } 63 | 64 | //----------------------------------------------------------------------------- 65 | // The trace filter! 66 | //----------------------------------------------------------------------------- 67 | typedef bool(_cdecl* PassServer)(void* pTouch, void* pPass); 68 | typedef bool(_cdecl* StandardFilter)(void* a1, int a2); 69 | PassServer oPassServerEntityFilter = 0; 70 | typedef bool(__stdcall* ShouldCollide)(int a1, int a2); 71 | ShouldCollide oShouldCollide = 0; 72 | StandardFilter oStandardFilterRules = 0; 73 | bool trace_filter_simple_t::should_hit_entity(base_entity_t* pHandleEntity, int contentsMask) { 74 | // if (!oPassServerEntityFilter) 75 | // oPassServerEntityFilter = (PassServer)offsets.functions.pass_server_entity_filter; 76 | // if (!oShouldCollide) 77 | // oShouldCollide = (ShouldCollide)offsets.functions.should_collide; 78 | // if (!oStandardFilterRules) 79 | // oStandardFilterRules = (StandardFilter)offsets.functions.standard_filter_rules; 80 | 81 | if (!oStandardFilterRules(pHandleEntity, contentsMask)) 82 | return false; 83 | 84 | if (pass_ent) { 85 | if (!oPassServerEntityFilter(pHandleEntity, pass_ent)) { 86 | return false; 87 | } 88 | } 89 | 90 | // "55 8B EC 56 8B 75 ? 85 F6 75 ? B0 ?"; // bool __cdecl PassServerEntityFilter(int pTouch, 91 | // int pPass) "55 8B EC 8B 4D ? 56 8B 01 FF 50 ? 8B F0 85 F6 75 ? B0 ? 5E 5D C3"; // bool 92 | // __cdecl StandardFilterRules(int a1, int 93 | // // a2) 94 | // Don't test if the game code tells us we should ignore this collision... 95 | base_entity_t* pEntity = (base_entity_t*)(pHandleEntity); 96 | if (!pEntity) 97 | return false; 98 | if (!pEntity->should_collide(collision_group, contentsMask)) 99 | return false; 100 | if (pEntity && !oShouldCollide(collision_group, pEntity->collision_group())) 101 | return false; 102 | if (should_hit_extra_func && (!(should_hit_extra_func(pHandleEntity, contentsMask)))) 103 | return false; 104 | 105 | return true; 106 | } 107 | 108 | bool trace_filter_ignore_players_t::should_hit_entity(base_entity_t* server_entity, 109 | int contentsMask) { 110 | auto networkable = server_entity->get_networkable(); 111 | if (networkable->entity_index() != 0 && 112 | networkable->entity_index() < cheat::interfaces.engine_client->get_max_clients()) 113 | return false; 114 | 115 | return trace_filter_simple_t::should_hit_entity(server_entity, contentsMask); 116 | } 117 | 118 | bool trace_filter_ignore_teammates_t::should_hit_entity(base_entity_t* server_entity, 119 | int contentsMask) { 120 | auto networkable = server_entity->get_networkable(); 121 | if (networkable->entity_index() != 0 && 122 | networkable->entity_index() < cheat::interfaces.engine_client->get_max_clients()) { 123 | if (server_entity->team_number() == ignore_team) { 124 | return false; 125 | } 126 | } 127 | 128 | return trace_filter_simple_t::should_hit_entity(server_entity, contentsMask); 129 | } 130 | -------------------------------------------------------------------------------- /tas/valve/studio_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | struct mstudiobbox_t { 6 | int bone; 7 | int group; // intersection group 8 | vector3_t bbmin; // bounding box 9 | vector3_t bbmax; 10 | int szhitboxnameindex; // offset to the name of the hitbox. 11 | int unused[8]; 12 | 13 | const char* pszHitboxName() { 14 | if (szhitboxnameindex == 0) 15 | return ""; 16 | 17 | return ((const char*)this) + szhitboxnameindex; 18 | } 19 | 20 | mstudiobbox_t() {} 21 | 22 | private: 23 | // No copy constructors allowed 24 | mstudiobbox_t(const mstudiobbox_t& vOther); 25 | }; 26 | 27 | struct mstudiohitboxset_t { 28 | int sznameindex; 29 | inline char* const pszName(void) const { return ((char*)this) + sznameindex; } 30 | int numhitboxes; 31 | int hitboxindex; 32 | inline mstudiobbox_t* pHitbox(int i) const { 33 | return (mstudiobbox_t*)(((std::byte*)this) + hitboxindex) + i; 34 | }; 35 | }; 36 | 37 | struct mstudiobone_t { 38 | int sznameindex; 39 | inline char* const pszName(void) const { return ((char*)this) + sznameindex; } 40 | int parent; // parent bone 41 | int bonecontroller[6]; // bone controller index, -1 == none 42 | 43 | // default values 44 | vector3_t pos; 45 | float quat[4]; 46 | vector3_t rot; 47 | // compression scale 48 | vector3_t posscale; 49 | vector3_t rotscale; 50 | 51 | float poseToBone[3][4]; 52 | float qAlignment[4]; 53 | int flags; 54 | int proctype; 55 | int procindex; // procedural rule 56 | mutable int physicsbone; // index into physically simulated bone 57 | inline void* pProcedure() const { 58 | if (procindex == 0) 59 | return NULL; 60 | else 61 | return (void*)(((std::byte*)this) + procindex); 62 | }; 63 | int surfacepropidx; // index into string tablefor property name 64 | inline char* const pszSurfaceProp(void) const { return ((char*)this) + surfacepropidx; } 65 | int contents; // See BSPFlags.h for the contents flags 66 | 67 | int unused[8]; // remove as appropriate 68 | 69 | mstudiobone_t() {} 70 | 71 | private: 72 | // No copy constructors allowed 73 | mstudiobone_t(const mstudiobone_t& vOther); 74 | }; 75 | 76 | struct studio_header_t { 77 | int id; 78 | int version; 79 | 80 | int checksum; 81 | 82 | char name[64]; 83 | int length; 84 | 85 | vector3_t eyeposition; 86 | 87 | vector3_t illumposition; 88 | 89 | vector3_t hull_min; 90 | vector3_t hull_max; 91 | 92 | vector3_t view_bbmin; 93 | vector3_t view_bbmax; 94 | 95 | int flags; 96 | 97 | int numbones; 98 | int boneindex; 99 | 100 | inline mstudiobone_t* GetBone(int i) const { 101 | return (mstudiobone_t*)(((std::byte*)this) + boneindex) + i; 102 | }; 103 | // inline mstudiobone_t *pBone(int i) const { Assert(i >= 0 && i < numbones); return 104 | //(mstudiobone_t *)(((byte 105 | //*)this) + boneindex) + i; }; 106 | 107 | int numbonecontrollers; 108 | int bonecontrollerindex; 109 | 110 | int numhitboxsets; 111 | int hitboxsetindex; 112 | 113 | mstudiohitboxset_t* GetHitboxSet(int i) const { 114 | return (mstudiohitboxset_t*)(((std::byte*)this) + hitboxsetindex) + i; 115 | } 116 | 117 | inline mstudiobbox_t* GetHitbox(int i, int set) const { 118 | mstudiohitboxset_t const* s = GetHitboxSet(set); 119 | 120 | if (!s) 121 | return NULL; 122 | 123 | return s->pHitbox(i); 124 | } 125 | 126 | inline int GetHitboxCount(int set) const { 127 | mstudiohitboxset_t const* s = GetHitboxSet(set); 128 | 129 | if (!s) 130 | return 0; 131 | 132 | return s->numhitboxes; 133 | } 134 | 135 | int numlocalanim; 136 | int localanimindex; 137 | 138 | int numlocalseq; 139 | int localseqindex; 140 | 141 | mutable int activitylistversion; 142 | mutable int eventsindexed; 143 | 144 | int numtextures; 145 | int textureindex; 146 | 147 | int numcdtextures; 148 | int cdtextureindex; 149 | 150 | int numskinref; 151 | int numskinfamilies; 152 | int skinindex; 153 | 154 | int numbodyparts; 155 | int bodypartindex; 156 | 157 | int numlocalattachments; 158 | int localattachmentindex; 159 | 160 | int numlocalnodes; 161 | int localnodeindex; 162 | int localnodenameindex; 163 | 164 | int numflexdesc; 165 | int flexdescindex; 166 | 167 | int numflexcontrollers; 168 | int flexcontrollerindex; 169 | 170 | int numflexrules; 171 | int flexruleindex; 172 | 173 | int numikchains; 174 | int ikchainindex; 175 | 176 | int nummouths; 177 | int mouthindex; 178 | 179 | int numlocalposeparameters; 180 | int localposeparamindex; 181 | 182 | int surfacepropindex; 183 | 184 | int keyvalueindex; 185 | int keyvaluesize; 186 | 187 | int numlocalikautoplaylocks; 188 | int localikautoplaylockindex; 189 | 190 | float mass; 191 | int contents; 192 | 193 | int numincludemodels; 194 | int includemodelindex; 195 | 196 | mutable void* virtualModel; 197 | 198 | int szanimblocknameindex; 199 | int numanimblocks; 200 | int animblockindex; 201 | 202 | mutable void* animblockModel; 203 | 204 | int bonetablebynameindex; 205 | 206 | void* pVertexBase; 207 | void* pIndexBase; 208 | 209 | std::byte constdirectionallightdot; 210 | 211 | std::byte rootLOD; 212 | 213 | std::byte numAllowedRootLODs; 214 | 215 | std::byte unused[1]; 216 | 217 | int unused4; 218 | 219 | int numflexcontrollerui; 220 | int flexcontrolleruiindex; 221 | float flVertAnimFixedPointScale; 222 | int unused3[1]; 223 | int studiohdr2index; 224 | int unused2[1]; 225 | }; 226 | -------------------------------------------------------------------------------- /tas/valve/cvar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "color.h" 4 | 5 | // forward decl. 6 | class con_command_base_t; 7 | typedef int cvar_dll_identifier_t; 8 | class command_t; 9 | class i_convar_t; 10 | 11 | typedef void (*change_callback_t)(i_convar_t* var, const char* old_value, float f_old_value); 12 | typedef void (*command_callback_void_t)(void); 13 | typedef void (*command_callback_t)(const command_t& command); 14 | typedef int (*command_completion_callback_t)(const char* partial, char commands[64][64]); 15 | 16 | class con_command_base_accessor_t { 17 | public: 18 | virtual bool register_con_command_base(con_command_base_t* var) = 0; 19 | }; 20 | 21 | class i_convar { 22 | public: 23 | virtual void set_value(const char* p_value) = 0; 24 | virtual void set_value(float value) = 0; 25 | virtual void set_value(int value) = 0; 26 | virtual void set_value(color value) = 0; 27 | virtual const char* get_name(void) const = 0; 28 | virtual const char* get_base_name(void) const = 0; 29 | virtual bool is_flag_set(int n_flag) const = 0; 30 | virtual int get_split_screen_player_slot() const = 0; 31 | }; 32 | 33 | class con_command_base_t { 34 | public: 35 | virtual ~con_command_base_t(void); 36 | virtual bool is_command(void) const; 37 | virtual bool is_flag_set(int flag) const; 38 | virtual void add_flags(int flags); 39 | virtual void remove_flags(int flags); 40 | virtual int get_flags() const; 41 | virtual const char* get_name(void) const; 42 | virtual const char* get_help_text(void) const; 43 | virtual bool is_registered(void) const; 44 | virtual cvar_dll_identifier_t get_dll_identifier() const; 45 | virtual void create(const char* name, const char* help_string = 0, int flags = 0); 46 | virtual void init(); 47 | 48 | con_command_base_t* next; 49 | bool registered; 50 | const char* name; 51 | const char* help_string; 52 | int flags; 53 | }; 54 | 55 | class command_t { 56 | public: 57 | command_t(); 58 | command_t(int n_arg_c, const char** pp_arg_v); 59 | 60 | private: 61 | enum { 62 | command_max_argc = 64, 63 | command_max_length = 512, 64 | }; 65 | 66 | int m_argc; 67 | int m_argv0_size; 68 | char m_arg_s_buffer[command_max_length]; 69 | char m_argv_buffer[command_max_length]; 70 | const char* m_argv[command_max_argc]; 71 | }; 72 | 73 | class command_callback_manager_t { 74 | public: 75 | virtual void command_callback(const command_t& command) = 0; 76 | }; 77 | 78 | class command_completion_callback_manager_t { 79 | public: 80 | virtual int command_completion_callback(); // const char* partial, c_utl_vector& 81 | // commands) = 0; 82 | }; 83 | 84 | class con_command_t : public con_command_base_t { 85 | public: 86 | virtual ~con_command_t(void); 87 | virtual bool is_command(void) const; 88 | virtual int 89 | auto_complete_suggest() = 0; // const char* partial, c_utl_vector& commands); 90 | virtual bool can_auto_complete(void); 91 | virtual void dispatch(const command_t& command); 92 | 93 | union { 94 | command_callback_void_t m_fn_command_callback_v1; 95 | command_callback_t m_fn_command_callback; 96 | command_callback_manager_t* m_p_command_callback; 97 | }; 98 | union { 99 | command_completion_callback_t m_fn_completion_callback; 100 | command_completion_callback_manager_t* m_p_command_completion_callback; 101 | }; 102 | 103 | bool m_has_completion_callback; 104 | bool m_using_new_command_callback; 105 | bool m_using_command_callback_interface; 106 | }; 107 | 108 | class convar_t : public con_command_base_t, public i_convar { 109 | public: 110 | typedef con_command_base_t base_class; 111 | virtual ~convar_t(void); 112 | virtual bool is_flag_set(int flag) const; 113 | virtual const char* get_help_text(void) const; 114 | virtual bool is_registered(void) const; 115 | virtual const char* get_name(void) const; 116 | virtual const char* get_base_name(void) const; 117 | virtual int get_split_screen_player_slot() const; 118 | virtual void add_flags(int flags); 119 | virtual int get_flags() const; 120 | virtual bool is_command(void) const; 121 | virtual void set_value(const char* value); 122 | virtual void set_value(float value); 123 | virtual void set_value(int value); 124 | virtual void set_value(color value); 125 | 126 | struct cv_value_t { 127 | char* string_value; 128 | int string_length; 129 | float float_value; 130 | int int_value; 131 | }; 132 | 133 | virtual void internal_set_value(const char* value); 134 | virtual void internal_set_float_value(float f_new_value); 135 | virtual void internal_set_int_value(int n_value); 136 | virtual void internal_set_color_value(color value); 137 | virtual bool clamp_value(float& value); 138 | virtual void change_string_value(const char* temp_val, float fl_old_value); 139 | virtual void create(const char* name, const char* default_value, int flags = 0, 140 | const char* help_string = 0, bool min = false, float f_min = 0.0, 141 | bool b_max = false, float f_max = false, change_callback_t callback = 0); 142 | virtual void init(); 143 | 144 | convar_t* parent; 145 | const char* default_value; 146 | cv_value_t value; 147 | bool has_min; 148 | float min_val; 149 | bool has_max; 150 | float max_val; 151 | // c_utl_vector m_change_callbacks; 152 | }; 153 | -------------------------------------------------------------------------------- /tas/library/safe_imgui_draw_cmds.cpp: -------------------------------------------------------------------------------- 1 | #include "safe_imgui_draw_cmds.h" 2 | 3 | namespace ImGui { 4 | // This is unfortunate... 5 | void outline_text(ImDrawList* draw_list, ImFont* font, float size, const ImVec2& pos, 6 | ImU32 fill_color, ImU32 outline_color, std::string_view str) noexcept { 7 | draw_list->AddText(font, size, {pos.x - 1, pos.y}, outline_color, str.data()); 8 | draw_list->AddText(font, size, {pos.x - 1, pos.y - 1}, outline_color, str.data()); 9 | draw_list->AddText(font, size, {pos.x, pos.y - 1}, outline_color, str.data()); 10 | draw_list->AddText(font, size, {pos.x + 1, pos.y - 1}, outline_color, str.data()); 11 | draw_list->AddText(font, size, {pos.x + 1, pos.y}, outline_color, str.data()); 12 | draw_list->AddText(font, size, {pos.x + 1, pos.y + 1}, outline_color, str.data()); 13 | draw_list->AddText(font, size, {pos.x, pos.y + 1}, outline_color, str.data()); 14 | draw_list->AddText(font, size, {pos.x - 1, pos.y + 1}, outline_color, str.data()); 15 | draw_list->AddText(font, size, {pos.x, pos.y}, fill_color, str.data()); 16 | } 17 | 18 | void outline_text(ImDrawList* draw_list, const ImVec2& pos, ImU32 fill, ImU32 outline, 19 | std::string_view str) noexcept { 20 | outline_text(draw_list, nullptr, 0.f, pos, fill, outline, str); 21 | } 22 | 23 | void outline_text(ImDrawList* draw_list, ImFont* font, const ImVec2& pos, ImU32 fill, 24 | ImU32 outline, std::string_view str) noexcept { 25 | outline_text(draw_list, font, 0.f, pos, fill, outline, str); 26 | } 27 | 28 | vector2_t outlined_text_size(const char* text, const char* text_end, 29 | bool hide_text_after_double_hash, float wrap_width) noexcept { 30 | auto size = CalcTextSize(text, text_end, hide_text_after_double_hash, wrap_width); 31 | 32 | auto res = vector2_t(size.x, size.y); 33 | res += 2; 34 | 35 | return res; 36 | } 37 | } // namespace ImGui 38 | 39 | void safe_imgui_draw_cmds_t::line(const vector2_t& start, const vector2_t& end, ImU32 color, 40 | float thickness, bool antialiased) noexcept { 41 | cmds.emplace_back(line_t{{start.x, start.y}, {end.x, end.y}, color, thickness, antialiased}); 42 | } 43 | 44 | void safe_imgui_draw_cmds_t::rect_filled(const glm::vec2& pos, const vector2_t& size, 45 | ImU32 color, float rounding) noexcept { 46 | auto max = pos + size; 47 | cmds.emplace_back(rect_filled_t{{pos.x, pos.y}, {max.x, max.y}, color, rounding}); 48 | } 49 | 50 | void safe_imgui_draw_cmds_t::rect(const vector2_t& pos, const vector2_t& size, ImU32 color, 51 | float rounding, float thickness) noexcept { 52 | auto max = pos + size; 53 | cmds.emplace_back(rect_t{{pos.x, pos.y}, {max.x, max.y}, color, rounding, thickness}); 54 | } 55 | 56 | void safe_imgui_draw_cmds_t::text(ImFont* font, const vector2_t& pos, ImU32 color, 57 | const std::string& str, bool center) noexcept { 58 | cmds.emplace_back(text_t{font, {pos.x, pos.y}, color, 0, false, center, str}); 59 | } 60 | 61 | void safe_imgui_draw_cmds_t::text(const vector2_t& pos, ImU32 color, const std::string& str, 62 | bool center) noexcept { 63 | text(nullptr, pos, color, str, center); 64 | } 65 | 66 | void safe_imgui_draw_cmds_t::text(ImFont* font, const vector2_t& pos, ImU32 fill_color, 67 | ImU32 outline_color, const std::string& str, 68 | bool center) noexcept { 69 | cmds.emplace_back(text_t{font, {pos.x, pos.y}, fill_color, outline_color, true, center, str}); 70 | } 71 | 72 | void safe_imgui_draw_cmds_t::text(const vector2_t& pos, ImU32 fill_color, ImU32 outline_color, 73 | const std::string& str, bool center) noexcept { 74 | text(nullptr, pos, fill_color, outline_color, str, center); 75 | } 76 | 77 | void safe_imgui_draw_cmds_t::flush() noexcept { 78 | { 79 | std::scoped_lock _{mtx}; 80 | std::swap(safe_cmds, cmds); 81 | } 82 | 83 | cmds.clear(); 84 | } 85 | 86 | void safe_imgui_draw_cmds_t::clear() noexcept { 87 | { 88 | std::scoped_lock _{mtx}; 89 | safe_cmds.clear(); 90 | } 91 | 92 | cmds.clear(); 93 | } 94 | 95 | void safe_imgui_draw_cmds_t::draw(ImDrawList* draw_list) noexcept { 96 | std::scoped_lock _{mtx}; 97 | 98 | for (auto&& cmd : safe_cmds) { 99 | if (auto* line = std::get_if(&cmd)) { 100 | if ((line->color & IM_COL32_A_MASK) == 0) { 101 | break; 102 | } 103 | 104 | auto old_flags = draw_list->Flags; 105 | 106 | if (line->antialiased) { 107 | draw_list->Flags |= 108 | ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedLinesUseTex; 109 | } else { 110 | draw_list->Flags &= 111 | ~(ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedLinesUseTex); 112 | } 113 | 114 | draw_list->PathLineTo(line->start); 115 | draw_list->PathLineTo(line->end); 116 | draw_list->PathStroke(line->color, ImDrawFlags_None, line->thickness); 117 | 118 | draw_list->Flags = old_flags; 119 | } else if (auto* rect_filled = std::get_if(&cmd)) { 120 | // TODO: Support more args (anti alias, rounding sides, etc). 121 | draw_list->AddRectFilled(rect_filled->min, rect_filled->max, rect_filled->color, 122 | rect_filled->rounding, ImDrawFlags_None); 123 | } else if (auto* rect = std::get_if(&cmd)) { 124 | // TODO: Support more args (anti alias, rounding sides, etc). 125 | draw_list->AddRect(rect->min, rect->max, rect->color, rect->rounding, ImDrawFlags_None, 126 | rect->thickness); 127 | } else if (auto* text = std::get_if(&cmd)) { 128 | if (text->center) { 129 | text->pos.x -= glm::round(ImGui::outlined_text_size(text->str.c_str()).x / 2.f); 130 | } 131 | 132 | if (text->outlined) { 133 | ImGui::outline_text(draw_list, text->font, 0.0f, text->pos, text->fill_color, 134 | text->outline_color, text->str); 135 | } else { 136 | draw_list->AddText(text->font, 0.0f, text->pos, text->fill_color, text->str.c_str()); 137 | } 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | project(tas LANGUAGES CXX) 4 | 5 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 6 | 7 | # Static linking. 8 | set(MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 9 | 10 | # CPM. 11 | set(CPM_DOWNLOAD_VERSION 0.38.7) 12 | set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5") 13 | 14 | if (CPM_SOURCE_CACHE) 15 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 16 | elseif (DEFINED ENV{CPM_SOURCE_CACHE}) 17 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 18 | else () 19 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 20 | endif () 21 | 22 | get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) 23 | 24 | if (NOT EXISTS ${CPM_DL_LOCATION}) 25 | message(STATUS "Downloading CPM.cmake to: ${CPM_DOWNLOAD_LOCATION}") 26 | 27 | file(DOWNLOAD 28 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 29 | ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} 30 | ) 31 | endif () 32 | 33 | include(${CPM_DOWNLOAD_LOCATION}) 34 | 35 | # External libraries. 36 | CPMAddPackage("gh:g-truc/glm#adf31f555e73e2bd6fda373bb5d8740f9c6c17c0") 37 | CPMAddPackage("gh:freetype/freetype#VER-2-13-2") 38 | CPMAddPackage("gh:ocornut/imgui@1.90.3") 39 | CPMAddPackage("gh:nemtrif/utfcpp@4.0.5") 40 | CPMAddPackage("gh:nlohmann/json@3.11.3") 41 | CPMAddPackage("gh:taocpp/PEGTL#3.2.7") 42 | CPMAddPackage("gh:cursey/safetyhook#91fbc796862d80bc99294393e707db4c925dfeb1") 43 | CPMAddPackage( 44 | NAME zydis 45 | GITHUB_REPOSITORY zyantific/zydis 46 | VERSION 4.0.0 47 | OPTIONS 48 | "ZYDIS_BUILD_EXAMPLES OFF" 49 | "ZYDIS_BUILD_TOOLS OFF" 50 | "ZYDIS_BUILD_DOXYGEN OFF") 51 | 52 | # TAS DLL. 53 | add_library(tas SHARED 54 | # Main 55 | tas/main.cpp 56 | tas/cheat.cpp 57 | 58 | # Core 59 | tas/core/debug/debug.cpp 60 | tas/core/input/input.cpp 61 | tas/core/interfaces/interfaces.cpp 62 | tas/core/menu/menu.cpp 63 | tas/core/netvars/netvars.cpp 64 | tas/core/offsets/offsets.cpp 65 | tas/core/player_manager/player_manager.cpp 66 | tas/core/prediction/prediction.cpp 67 | 68 | # Features 69 | tas/features/movement/movement.cpp 70 | tas/features/visual/esp.cpp 71 | tas/features/tas.cpp 72 | tas/features/compression_handler.cpp 73 | 74 | # Hooks 75 | tas/hooks/hooks.cpp 76 | 77 | # Library 78 | tas/library/math.cpp 79 | tas/library/render.cpp 80 | tas/library/utils.cpp 81 | tas/library/safe_imgui_draw_cmds.cpp 82 | 83 | # SDK 84 | tas/valve/entities/base_entity.cpp 85 | tas/valve/entities/player.cpp 86 | tas/valve/bsp.cpp 87 | tas/valve/tracing/trace_filter.cpp 88 | ) 89 | 90 | if (imgui_ADDED) 91 | target_sources(tas PRIVATE 92 | ${imgui_SOURCE_DIR}/imgui.cpp 93 | ${imgui_SOURCE_DIR}/imgui_draw.cpp 94 | ${imgui_SOURCE_DIR}/imgui_tables.cpp 95 | ${imgui_SOURCE_DIR}/imgui_widgets.cpp 96 | ${imgui_SOURCE_DIR}/misc/freetype/imgui_freetype.cpp 97 | # ${imgui_SOURCE_DIR}/backends/imgui_impl_win32.cpp 98 | tas/imgui_impl_win32.cpp 99 | ${imgui_SOURCE_DIR}/backends/imgui_impl_dx9.cpp 100 | ) 101 | 102 | target_include_directories(tas PUBLIC 103 | $ 104 | $) 105 | 106 | target_compile_definitions(tas PUBLIC 107 | "IMGUI_USER_CONFIG=\"${CMAKE_SOURCE_DIR}/tas/imconfig.hpp\"" 108 | IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 109 | ) 110 | endif () 111 | 112 | target_include_directories(tas PUBLIC tas) 113 | target_compile_features(tas PUBLIC cxx_std_23) 114 | 115 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 116 | target_compile_definitions(tas PRIVATE 117 | NDEBUG 118 | NOMINMAX 119 | _HAS_EXCEPTIONS=0 120 | _ITERATOR_DEBUG_LEVEL=0 121 | WINVER=0x0A00 122 | _WIN32_WINNT=0x0A00 123 | GLM_FORCE_SWIZZLE 124 | GLM_FORCE_ALIGNED_GENTYPES 125 | GLM_ENABLE_EXPERIMENTAL 126 | JSON_NOEXCEPTION 127 | ) 128 | 129 | target_compile_options(tas PRIVATE 130 | /O2 131 | /fp:precise 132 | /Ob2 133 | /GR- 134 | /GS- 135 | /EHsc 136 | /guard:cf- 137 | /clang:-mfpmath=sse 138 | /clang:-march=haswell # Haswell minimum. 139 | /clang:-mtune=generic 140 | /clang:-fno-ident 141 | /clang:-fno-unwind-tables 142 | /clang:-fno-asynchronous-unwind-tables 143 | /clang:-g0 144 | ) 145 | elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") 146 | target_compile_definitions(tas PRIVATE 147 | NDEBUG 148 | NOMINMAX 149 | _HAS_EXCEPTIONS=0 150 | _ITERATOR_DEBUG_LEVEL=0 151 | WINVER=0x0A00 152 | _WIN32_WINNT=0x0A00 153 | GLM_FORCE_SWIZZLE 154 | GLM_FORCE_ALIGNED_GENTYPES 155 | GLM_ENABLE_EXPERIMENTAL 156 | JSON_NOEXCEPTION 157 | ) 158 | 159 | target_compile_options(tas PRIVATE 160 | /O2 161 | /fp:precise 162 | /Ob2 163 | /GR- 164 | /GS- 165 | /EHsc 166 | /guard:cf- 167 | /clang:-mfpmath=sse 168 | /clang:-march=haswell # Haswell minimum. 169 | /clang:-mtune=generic 170 | /clang:-fno-ident 171 | /clang:-fno-unwind-tables 172 | /clang:-fno-asynchronous-unwind-tables 173 | /clang:-g0 174 | ) 175 | elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") 176 | target_compile_definitions(tas PRIVATE 177 | NOMINMAX 178 | GLM_FORCE_SWIZZLE 179 | GLM_FORCE_ALIGNED_GENTYPES 180 | GLM_ENABLE_EXPERIMENTAL 181 | ) 182 | 183 | target_compile_options(tas PRIVATE 184 | /Od 185 | /fp:precise 186 | /Ob2 187 | /GR- 188 | /GS- 189 | /EHsc 190 | /guard:cf- 191 | /clang:-mfpmath=sse 192 | /clang:-march=haswell # Haswell minimum. 193 | /clang:-mtune=generic 194 | /clang:-fno-ident 195 | /clang:-fno-unwind-tables 196 | /clang:-fno-asynchronous-unwind-tables 197 | /clang:-g 198 | ) 199 | endif () 200 | 201 | target_link_libraries(tas PRIVATE glm::glm nlohmann_json::nlohmann_json taocpp::pegtl safetyhook::safetyhook utf8cpp freetype d3d9) 202 | -------------------------------------------------------------------------------- /tas/library/render.cpp: -------------------------------------------------------------------------------- 1 | #include "render.h" 2 | #include "cheat.h" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | DWORD g_prev_srgb{}; 14 | 15 | std::string get_system_font_path(std::string_view font_name) noexcept { 16 | char windows_directory[MAX_PATH]{}; 17 | 18 | if (!GetWindowsDirectoryA(windows_directory, MAX_PATH)) { 19 | return {}; 20 | } 21 | 22 | HKEY key{}; 23 | 24 | if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts)", 25 | 0, KEY_READ, &key)) { 26 | return {}; 27 | } 28 | 29 | DWORD index{}; 30 | 31 | for (;;) { 32 | DWORD value_name_size = MAX_PATH; 33 | DWORD value_data_size = MAX_PATH; 34 | DWORD value_type{}; 35 | char value_name[MAX_PATH]{}; 36 | char value_data[MAX_PATH]{}; 37 | 38 | auto error = RegEnumValueA(key, index++, value_name, &value_name_size, nullptr, &value_type, 39 | reinterpret_cast(value_data), &value_data_size); 40 | 41 | if (error == ERROR_NO_MORE_ITEMS) { 42 | break; 43 | } 44 | 45 | if (error != ERROR_SUCCESS || value_type != REG_SZ) { 46 | continue; 47 | } 48 | 49 | auto name = 50 | std::string_view{value_name, static_cast(value_name_size)}; 51 | 52 | if (name.compare(0, font_name.size(), font_name) != 0) { 53 | continue; 54 | } 55 | 56 | RegCloseKey(key); 57 | 58 | return std::string(windows_directory) + R"(\fonts\)" + 59 | std::string(value_data, value_data_size); 60 | } 61 | 62 | RegCloseKey(key); 63 | 64 | return {}; 65 | } 66 | 67 | constexpr auto rgba_to_vec4(int32_t r, int32_t g, int32_t b, int32_t a = 255) noexcept { 68 | return ImColor(r, g, b, a).Value; 69 | } 70 | 71 | void render_t::initialize() noexcept { 72 | if (!ImGui::CreateContext()) { 73 | return; 74 | } 75 | 76 | auto& io = ImGui::GetIO(); 77 | io.IniFilename = nullptr; // TODO: Save this to hack dir too. 78 | io.ConfigFlags |= 79 | ImGuiConfigFlags_NoMouseCursorChange; // No mouse changes since we handle it ourselves. 80 | 81 | auto calibri = get_system_font_path("Calibri (TrueType)"); 82 | if (calibri.empty()) { 83 | return; 84 | } 85 | 86 | auto tahoma = get_system_font_path("Tahoma Bold (TrueType)"); 87 | if (tahoma.empty()) { 88 | return; 89 | } 90 | 91 | ImFontConfig font_config{}; 92 | 93 | // Add menu font. 94 | io.Fonts->AddFontFromFileTTF(calibri.c_str(), 14); 95 | 96 | // Add overlay font. 97 | font_config.FontBuilderFlags |= 98 | ImGuiFreeTypeBuilderFlags_Monochrome | ImGuiFreeTypeBuilderFlags_MonoHinting; 99 | 100 | tahoma_bold_13 = io.Fonts->AddFontFromFileTTF(tahoma.c_str(), 13, &font_config); 101 | 102 | // Colors. 103 | { 104 | ImGui::StyleColorsDark(); 105 | 106 | auto& style = ImGui::GetStyle(); 107 | auto& colors = style.Colors; 108 | 109 | colors[ImGuiCol_TitleBgActive] = rgba_to_vec4(235, 94, 40, 200); 110 | colors[ImGuiCol_TitleBg] = rgba_to_vec4(204, 197, 185); 111 | colors[ImGuiCol_Text] = rgba_to_vec4(255, 252, 242); 112 | colors[ImGuiCol_WindowBg] = rgba_to_vec4(37, 36, 34); 113 | colors[ImGuiCol_ChildBg] = rgba_to_vec4(204, 197, 185); 114 | colors[ImGuiCol_FrameBg] = rgba_to_vec4(64, 61, 57); 115 | colors[ImGuiCol_FrameBgHovered] = rgba_to_vec4(235, 94, 40, 100); 116 | colors[ImGuiCol_FrameBgActive] = rgba_to_vec4(235, 94, 40, 200); 117 | colors[ImGuiCol_SliderGrab] = rgba_to_vec4(204, 197, 185); 118 | colors[ImGuiCol_SliderGrabActive] = rgba_to_vec4(235, 94, 40); 119 | // colors[ImGuiCol_FrameBgHovered] = rgba_to_vec4(45, 45, 45); 120 | // colors[ImGuiCol_FrameBgActive] = rgba_to_vec4(35, 35, 35); 121 | colors[ImGuiCol_Button] = rgba_to_vec4(64, 61, 57); 122 | colors[ImGuiCol_ButtonHovered] = rgba_to_vec4(235, 94, 40, 100); 123 | colors[ImGuiCol_ButtonActive] = rgba_to_vec4(235, 94, 40, 200); 124 | colors[ImGuiCol_CheckMark] = rgba_to_vec4(235, 94, 40); 125 | colors[ImGuiCol_Header] = rgba_to_vec4(80, 65, 90); 126 | colors[ImGuiCol_HeaderHovered] = rgba_to_vec4(235, 94, 40, 100); 127 | colors[ImGuiCol_HeaderActive] = rgba_to_vec4(235, 94, 40, 100); 128 | colors[ImGuiCol_Tab] = 129 | ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); 130 | colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; 131 | colors[ImGuiCol_TabActive] = 132 | ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); 133 | colors[ImGuiCol_TabUnfocused] = 134 | ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); 135 | colors[ImGuiCol_TabUnfocusedActive] = 136 | ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); 137 | } 138 | // ImGui::StyleColorsDark(); 139 | 140 | if (!ImGui_ImplWin32_Init(cheat::window)) 141 | return; 142 | 143 | ImGui_ImplDX9_Init(cheat::interfaces.d3d9_device); 144 | } 145 | 146 | void render_t::detach() noexcept { 147 | ImGui_ImplDX9_Shutdown(); 148 | ImGui_ImplWin32_Shutdown(); 149 | ImGui::DestroyContext(); 150 | } 151 | 152 | void render_t::begin() noexcept { 153 | cheat::interfaces.d3d9_device->GetRenderState(D3DRS_SRGBWRITEENABLE, &g_prev_srgb); 154 | 155 | cheat::interfaces.d3d9_device->SetRenderState( 156 | D3DRS_SRGBWRITEENABLE, FALSE); // this will disable linear to gamma correction 157 | 158 | ImGui_ImplDX9_NewFrame(); 159 | ImGui_ImplWin32_NewFrame(); 160 | 161 | // Save off the screen size each frame. NOTE: This is grabbed from WinAPI's `GetClientRect`. 162 | auto& display_size = ImGui::GetIO().DisplaySize; 163 | screen_size = {display_size.x, display_size.y}; 164 | 165 | { // NOTE: https://github.com/ocornut/imgui/issues/6895#issuecomment-1747239385 166 | std::scoped_lock _{cheat::input.imgui_mutex}; 167 | ImGui::NewFrame(); 168 | } 169 | 170 | // Render thread-safe draw commands. 171 | tas_draw_cmds.draw(ImGui::GetBackgroundDrawList()); 172 | } 173 | 174 | void render_t::finish() noexcept { 175 | ImGui::Render(); 176 | ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); 177 | 178 | cheat::interfaces.d3d9_device->SetRenderState(D3DRS_SRGBWRITEENABLE, g_prev_srgb); 179 | } 180 | -------------------------------------------------------------------------------- /tas/hooks/hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "cheat.h" 2 | #include "library/pe.h" 3 | #include "core/offsets/offsets.h" 4 | #include "core/settings/settings.h" 5 | #include "valve/base_client.h" 6 | #include "valve/entities/player.h" 7 | #include "valve/prediction_copy.h" 8 | #include "valve/input.h" 9 | #include "valve/bf_write.h" 10 | 11 | extern long ImGui_ImplWin32_WndProcHandler(HWND, unsigned, unsigned, long); 12 | 13 | void __thiscall create_move(base_client_t* thisptr, std::int32_t sequence, float sample, 14 | std::int32_t active) noexcept { 15 | cheat::hooks.base_client.get_virtual_function(21)(thisptr, sequence, 16 | sample, active); 17 | 18 | cheat::on_create_move(cheat::interfaces.input->get_usercmd(sequence)); 19 | } 20 | 21 | void __thiscall paint(void* thisptr, std::int32_t mode) noexcept { 22 | cheat::get_view_matrix(); 23 | 24 | cheat::hooks.engine_vgui.get_virtual_function(13)(thisptr, mode); 25 | } 26 | 27 | void __thiscall frame_stage_notify(base_client_t* thisptr, 28 | client_frame_stage_t stage) noexcept { 29 | cheat::pre_frame_stage_notify(stage); 30 | 31 | cheat::hooks.base_client.get_virtual_function(35)(thisptr, 32 | stage); 33 | 34 | cheat::post_frame_stage_notify(stage); 35 | } 36 | 37 | void __thiscall run_command(prediction_manager_t* thisptr, player_t* player, usercmd_t* cmd, 38 | move_helper_t* move_helper) { 39 | cheat::hooks.prediction.get_virtual_function(17)(thisptr, player, cmd, 40 | move_helper); 41 | cheat::interfaces.move_helper = move_helper; 42 | 43 | if (cheat::local_player != nullptr) { 44 | cheat::compression_manager.init(cheat::local_player->get_data_map()); 45 | cheat::compression_manager.pre_update(cheat::local_player, cmd->command_number % 90); 46 | } 47 | } 48 | 49 | HRESULT __stdcall present(IDirect3DDevice9* device, RECT* source_rect, RECT* dest_rect, 50 | HWND dest_window_override, RGNDATA* dirty_region) noexcept { 51 | cheat::on_present(); 52 | 53 | return cheat::hooks.d3d9_device.get_virtual_function(17)( 54 | device, source_rect, dest_rect, dest_window_override, dirty_region); 55 | } 56 | 57 | HRESULT __stdcall reset(IDirect3DDevice9* device, 58 | D3DPRESENT_PARAMETERS* present_parameters) noexcept { 59 | cheat::render.detach(); 60 | 61 | auto result = cheat::hooks.d3d9_device.get_virtual_function(16)( 62 | device, present_parameters); 63 | 64 | cheat::get_window_handle(); 65 | cheat::render.initialize(); // this is really bad.. 66 | 67 | return result; 68 | } 69 | 70 | void __thiscall override_view(void* thisptr, view_setup_t* view) noexcept { 71 | cheat::hooks.client_mode.get_virtual_function(16)(thisptr, view); 72 | } 73 | 74 | void __thiscall pre_entity_packet_received(prediction_manager_t* thisptr, 75 | std::int32_t commands_acknowledged, 76 | std::int32_t current_world_update_packet) noexcept { 77 | cheat::get_local_player(); 78 | 79 | if (cheat::local_player && commands_acknowledged > 0) { 80 | cheat::local_player->restore_data("PreEntityPacketReceived", commands_acknowledged - 1, 81 | PC_EVERYTHING); 82 | } 83 | 84 | cheat::hooks.prediction.get_virtual_function(4)( 85 | thisptr, commands_acknowledged, current_world_update_packet); 86 | } 87 | 88 | void __thiscall post_network_data_received(prediction_manager_t* thisptr, 89 | std::int32_t commands_acknowledged) noexcept { 90 | cheat::get_local_player(); 91 | 92 | if (cheat::local_player && commands_acknowledged > 0) { 93 | cheat::compression_manager.init(cheat::local_player->get_data_map()); 94 | cheat::compression_manager.post_update( 95 | cheat::local_player, 96 | (cheat::interfaces.prediction->server_commands_acknowledged + commands_acknowledged) % 97 | 90); 98 | // cheat::local_player->save_data("post_network_data_received", -1, PC_EVERYTHING); 99 | } 100 | 101 | cheat::hooks.prediction.get_virtual_function(6)( 102 | thisptr, commands_acknowledged); 103 | } 104 | 105 | void hooks_t::setup_detour_hooks() noexcept {} 106 | 107 | class hooked_cinput_t : public cinput_t { 108 | public: 109 | bool hooked_write_usercmd_delta_to_buffer(bf_write_t* buf, std::int32_t from, std::int32_t to, 110 | bool isnewcommand) noexcept { 111 | // NOTE: Recreating this function to get rid of `CUserCmd` checksums entirely. 112 | usercmd_t nullcmd{}, *f{&nullcmd}, *t{&nullcmd}; 113 | 114 | if (from != -1) { 115 | if (auto from_cmd = get_usercmd(from)) { 116 | f = from_cmd; 117 | } 118 | } 119 | 120 | if (auto to_cmd = get_usercmd(to)) { 121 | t = to_cmd; 122 | } 123 | 124 | static auto write_usercmd = 125 | reinterpret_cast( 126 | offsets.functions.write_usercmd); 127 | 128 | write_usercmd(buf, t, f); 129 | 130 | return !buf->IsOverflowed(); 131 | } 132 | 133 | usercmd_t* hooked_get_usercmd(std::int32_t sequence_number) noexcept { 134 | // NOTE: Recreating this function to bypass the check inside it, so we can forcefully set 135 | // command numbers. 136 | return &cmds[sequence_number % MULTIPLAYER_BACKUP]; 137 | } 138 | }; 139 | 140 | void hooks_t::setup_vtable_hooks() noexcept { 141 | input_hook = safetyhook::create_vmt(cheat::interfaces.input); 142 | 143 | get_usercmd_hook = safetyhook::create_vm(input_hook, 8, &hooked_cinput_t::hooked_get_usercmd); 144 | 145 | write_usercmd_delta_to_buffer_hook = safetyhook::create_vm( 146 | input_hook, 5, &hooked_cinput_t::hooked_write_usercmd_delta_to_buffer); 147 | 148 | client_mode.initialize(reinterpret_cast(cheat::interfaces.client_mode)); 149 | 150 | // client_mode.setup_hook(21, reinterpret_cast(create_move)); 151 | 152 | client_mode.setup_hook(16, reinterpret_cast(override_view)); 153 | 154 | base_client.initialize(reinterpret_cast(cheat::interfaces.base_client)); 155 | 156 | base_client.setup_hook(35, reinterpret_cast(frame_stage_notify)); 157 | base_client.setup_hook(21, reinterpret_cast(create_move)); 158 | 159 | d3d9_device.initialize(reinterpret_cast(cheat::interfaces.d3d9_device)); 160 | 161 | d3d9_device.setup_hook(17, reinterpret_cast(present)); 162 | 163 | d3d9_device.setup_hook(16, reinterpret_cast(reset)); 164 | 165 | engine_vgui.initialize(reinterpret_cast(cheat::interfaces.engine_vgui)); 166 | 167 | engine_vgui.setup_hook(13, reinterpret_cast(paint)); 168 | 169 | prediction.initialize(reinterpret_cast(cheat::interfaces.prediction)); 170 | 171 | prediction.setup_hook(17, reinterpret_cast(run_command)); 172 | prediction.setup_hook(6, reinterpret_cast(post_network_data_received)); 173 | prediction.setup_hook(4, reinterpret_cast(pre_entity_packet_received)); 174 | } 175 | 176 | void hooks_t::initialize() noexcept { 177 | setup_vtable_hooks(); 178 | setup_detour_hooks(); 179 | } 180 | 181 | void hooks_t::detach() noexcept { 182 | client_mode.undo_hooks(); 183 | base_client.undo_hooks(); 184 | d3d9_device.undo_hooks(); 185 | engine_vgui.undo_hooks(); 186 | prediction.undo_hooks(); 187 | input_hook = {}; 188 | } 189 | -------------------------------------------------------------------------------- /tas/library/pe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/hash.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace pe { 14 | struct module_t { 15 | std::map interface_cache = {}; 16 | uint8_t* base_ = nullptr; 17 | 18 | module_t(uintptr_t ptr) { 19 | base_ = reinterpret_cast(ptr); 20 | populate_interfaces(); 21 | } 22 | 23 | module_t() {} 24 | 25 | ~module_t() { flush_interfaces(); } 26 | 27 | uint8_t* base() { return base_; } 28 | 29 | IMAGE_DOS_HEADER* dos_header() { return reinterpret_cast(base()); } 30 | 31 | IMAGE_NT_HEADERS* nt_headers() { 32 | return reinterpret_cast(base() + dos_header()->e_lfanew); 33 | } 34 | 35 | inline uint8_t* get_export(uint64_t hash) { 36 | auto export_dir = 37 | nt_headers()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 38 | auto exports = 39 | reinterpret_cast((base() + export_dir.VirtualAddress)); 40 | if (!export_dir.VirtualAddress) { 41 | return nullptr; 42 | } 43 | 44 | auto functions = reinterpret_cast((base() + exports->AddressOfFunctions)); 45 | auto names = reinterpret_cast(base() + exports->AddressOfNames); 46 | auto ordinals = reinterpret_cast(base() + exports->AddressOfNameOrdinals); 47 | for (size_t i = 0; i < exports->NumberOfNames; i++) { 48 | if (hash::hash_crc(reinterpret_cast(base() + names[i])) != hash) { 49 | continue; 50 | } 51 | 52 | return base() + functions[ordinals[i]]; 53 | } 54 | 55 | return nullptr; 56 | } 57 | 58 | inline uint8_t* get_export(std::string_view name) { 59 | return get_export(hash::hash_crc(name.data(), name.size())); 60 | } 61 | 62 | inline bool populate_interfaces() { 63 | uint32_t interface_registry = 64 | find_pattern_in_memory("8B 35 ?? ?? ?? ?? 57 85 F6 74 38") + 0x2; 65 | if (!interface_registry) 66 | return false; 67 | interface_reg_t* interface_list = 68 | **reinterpret_cast(interface_registry); 69 | 70 | if (!interface_list) 71 | return false; 72 | 73 | for (interface_reg_t* current_interface = interface_list; current_interface; 74 | current_interface = current_interface->next) { 75 | if (!current_interface || !current_interface->create_fn) 76 | continue; 77 | 78 | printf("%s\n", current_interface->name); 79 | interface_cache.insert({hash::hash_crc(current_interface->name), 80 | reinterpret_cast(current_interface->create_fn())}); 81 | } 82 | 83 | return true; 84 | } 85 | 86 | template inline T get_interface(uint32_t hash) { 87 | if (interface_cache.count(hash)) 88 | return reinterpret_cast(interface_cache.at(hash)); 89 | printf("%u, missing\n", hash); 90 | return nullptr; 91 | } 92 | 93 | inline void flush_interfaces() { interface_cache.clear(); } 94 | 95 | inline std::vector find_all_pattern_in_memory(const char* pattern) { 96 | static std::vector patterns = {}; 97 | patterns.clear(); 98 | 99 | static auto pattern_to_byte = [](const char* pattern) { 100 | auto bytes = std::vector{}; 101 | const auto start = const_cast(pattern); 102 | const auto end = const_cast(pattern) + std::strlen(pattern); 103 | 104 | for (auto current = start; current < end; ++current) { 105 | if (*current == '?') { 106 | ++current; 107 | 108 | if (*current == '?') 109 | ++current; 110 | 111 | bytes.push_back(-1); 112 | } else { 113 | bytes.push_back(std::strtoul(current, ¤t, 16)); 114 | } 115 | } 116 | return bytes; 117 | }; 118 | 119 | const auto dos_header = reinterpret_cast(base()); 120 | const auto nt_headers = reinterpret_cast( 121 | reinterpret_cast(base()) + dos_header->e_lfanew); 122 | 123 | const auto size_of_image = nt_headers->OptionalHeader.SizeOfImage; 124 | const auto pattern_bytes = pattern_to_byte(pattern); 125 | const auto scan_bytes = reinterpret_cast(base()); 126 | 127 | const auto s = pattern_bytes.size(); 128 | const auto d = pattern_bytes.data(); 129 | 130 | for (auto i = 0ul; i < size_of_image - s; ++i) { 131 | auto found = true; 132 | 133 | for (auto j = 0ul; j < s; ++j) { 134 | if (scan_bytes[i + j] != d[j] && d[j] != -1) { 135 | found = false; 136 | break; 137 | } 138 | } 139 | 140 | if (found) 141 | patterns.push_back((uintptr_t)(&scan_bytes[i])); 142 | } 143 | 144 | return patterns; 145 | } 146 | 147 | inline uint32_t find_pattern_in_memory(const char* pattern) { 148 | static auto pattern_to_byte = [](const char* pattern) { 149 | auto bytes = std::vector{}; 150 | const auto start = const_cast(pattern); 151 | const auto end = const_cast(pattern) + std::strlen(pattern); 152 | 153 | for (auto current = start; current < end; ++current) { 154 | if (*current == '?') { 155 | ++current; 156 | 157 | if (*current == '?') 158 | ++current; 159 | 160 | bytes.push_back(-1); 161 | } else { 162 | bytes.push_back(std::strtoul(current, ¤t, 16)); 163 | } 164 | } 165 | return bytes; 166 | }; 167 | 168 | const auto dos_header = reinterpret_cast(base()); 169 | const auto nt_headers = reinterpret_cast( 170 | reinterpret_cast(base()) + dos_header->e_lfanew); 171 | 172 | const auto size_of_image = nt_headers->OptionalHeader.SizeOfImage; 173 | const auto pattern_bytes = pattern_to_byte(pattern); 174 | const auto scan_bytes = reinterpret_cast(base()); 175 | 176 | const auto s = pattern_bytes.size(); 177 | const auto d = pattern_bytes.data(); 178 | 179 | for (auto i = 0ul; i < size_of_image - s; ++i) { 180 | auto found = true; 181 | 182 | for (auto j = 0ul; j < s; ++j) { 183 | if (scan_bytes[i + j] != d[j] && d[j] != -1) { 184 | found = false; 185 | break; 186 | } 187 | } 188 | 189 | if (found) 190 | return (uintptr_t)(&scan_bytes[i]); 191 | } 192 | 193 | return 0; 194 | } 195 | }; 196 | 197 | struct ldr_entry_t { 198 | LIST_ENTRY InLoadOrderLinks; 199 | LIST_ENTRY InMemoryOrderLinks; 200 | LIST_ENTRY InInitializationOrderLinks; 201 | uintptr_t DllBase; 202 | uintptr_t EntryPoint; 203 | uint32_t SizeOfImage; 204 | UNICODE_STRING FullDllName; 205 | UNICODE_STRING BaseDllName; 206 | }; 207 | 208 | inline std::map module_cache = {}; 209 | 210 | inline void flush_module_cache() { module_cache.clear(); } 211 | 212 | inline bool get_module(std::string module_name, module_t& module) { 213 | uint32_t name_hash = hash::hash_crc(module_name.c_str()); 214 | if (module_cache.count(name_hash) != 0) { 215 | module = module_cache.at(name_hash); 216 | return true; 217 | } 218 | auto peb = ((_TEB*)__readfsdword(0x18))->ProcessEnvironmentBlock; 219 | auto list = &peb->Ldr->InMemoryOrderModuleList; 220 | auto wstr = std::wstring(module_name.begin(), module_name.end()); 221 | 222 | for (auto iter = list->Flink; iter != list; iter = iter->Flink) { 223 | auto entry = CONTAINING_RECORD(iter, ldr_entry_t, InMemoryOrderLinks); 224 | 225 | if (entry->BaseDllName.Buffer && wstr.compare(entry->BaseDllName.Buffer) == 0) { 226 | module_cache.insert({name_hash, module_t(entry->DllBase)}); 227 | module = module_cache.at(name_hash); 228 | return true; 229 | } 230 | } 231 | 232 | return false; 233 | } 234 | } // namespace pe 235 | -------------------------------------------------------------------------------- /tas/valve/base_client.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client_class.h" 4 | #include "interface_reg.h" 5 | #include 6 | 7 | #include "client_frame_stage.h" 8 | #include "../library/math.h" 9 | #include "view_setup.h" 10 | 11 | #include "../library/utils.h" 12 | 13 | // not going down the rabbit hole of adding this. 14 | // todo: maybe add later? 15 | class c_engine_sprite; 16 | class c_save_restore_data; 17 | struct x_user_context; 18 | struct x_user_property; 19 | class global_vars; 20 | 21 | // todo: remove when i add convars 22 | class i_convar; 23 | 24 | // nowhere else to put this that makes sense. 25 | // todo: figure that out. 26 | struct screen_fade_t { 27 | unsigned short m_duration; 28 | unsigned short m_hold_time; 29 | short m_fade_flags; 30 | std::byte m_r, m_g, m_b, m_a; 31 | }; 32 | 33 | class base_client_t { 34 | public: 35 | virtual int init(create_interface_fn app_system_factory, create_interface_fn physics_factory, 36 | global_vars* globals) = 0; 37 | virtual void post_init() = 0; 38 | virtual void shutdown(void) = 0; 39 | virtual bool replay_init(create_interface_fn replay_factory) = 0; 40 | virtual bool replay_post_init() = 0; 41 | virtual void level_init_pre_entity(char const* map_name) = 0; 42 | virtual void level_init_post_entity() = 0; 43 | virtual void level_shutdown(void) = 0; 44 | virtual client_class_t* get_all_classes(void) = 0; 45 | virtual int hud_vid_init(void) = 0; 46 | virtual void hud_process_input(bool active) = 0; 47 | virtual void hud_update(bool active) = 0; 48 | virtual void hud_reset(void) = 0; 49 | virtual void hud_text(const char* message) = 0; 50 | virtual void in_activate_mouse(void) = 0; 51 | virtual void in_deactive_mouse(void) = 0; 52 | virtual void in_accumulate(void) = 0; 53 | virtual void in_clear_states(void) = 0; 54 | virtual bool in_is_key_down(const char* name, bool& is_down) = 0; 55 | virtual void in_on_mouse_wheeld(int delta) = 0; 56 | virtual int in_key_event() = 0; // int event_code, button_code_t key_num, const char* 57 | // current_binding) = 0; 58 | virtual void create_move(int sequence_number, float input_sample_frametime, bool active) = 0; 59 | virtual void extra_mouse_sample(float frame_time, bool active) = 0; 60 | virtual bool write_user_cmd_delta_to_buffer() = 0; // bf_write* buf, int from, int to, bool 61 | // is_new_command) = 0; 62 | virtual void encode_user_cmd_to_buffer() = 0; // bf_write& buf, int slot) = 0; 63 | virtual void decode_user_cmd_from_buffer() = 0; // bf_read& buf, int slot) = 0; 64 | virtual void view_render() = 0; // vrect_t* rect) = 0; 65 | virtual void view_fade(screen_fade_t* sf) = 0; 66 | virtual void set_crosshair_angle(const vector3_t& angle) = 0; 67 | virtual void init_sprite(c_engine_sprite* sprite, const char* load_name) = 0; 68 | virtual void shutdown_sprite(c_engine_sprite* sprite) = 0; 69 | virtual int get_sprite_size(void) const = 0; 70 | virtual void voice_status(int ent_index, int talking) = 0; 71 | virtual void install_string_table_callback(char const* table_name) = 0; 72 | virtual void frame_stage_notify(client_frame_stage_t stage) = 0; 73 | virtual bool dispatch_user_message() = 0; // int msg_type, bf_read& msg_data) = 0; 74 | virtual c_save_restore_data* save_init(int size) = 0; 75 | virtual void save_write_fields() = 0; // c_save_restore_data*, const char*, void*, 76 | // data_map_t*, type_description_t*, int) = 0; 77 | virtual void save_read_fields() = 0; // c_save_restore_data*, const char*, void*, data_map_t*, 78 | // type_description_t*, int) = 0; 79 | virtual void pre_save(c_save_restore_data*) = 0; 80 | virtual void save(c_save_restore_data*) = 0; 81 | virtual void write_save_headers(c_save_restore_data*) = 0; 82 | virtual void read_restore_save_headers(c_save_restore_data*) = 0; 83 | virtual void restore(c_save_restore_data*, bool) = 0; 84 | virtual void dispatch_on_restore() = 0; 85 | virtual void* get_standard_recv_proxies() = 0; 86 | // virtual c_standard_recv_proxies* get_standard_recv_proxies() = 0; 87 | virtual void write_save_game_screenshot(const char* filename) = 0; 88 | virtual void emit_sentence_close_caption(char const* tokenstream) = 0; 89 | virtual void emit_close_caption(char const* caption_name, float duration) = 0; 90 | virtual bool can_record_demo(char* error_msg, int length) const = 0; 91 | virtual void on_demo_record_start(char const* demo_base_name) = 0; 92 | virtual void on_demo_record_stop() = 0; 93 | virtual void on_demo_playback_start(char const* demo_base_name) = 0; 94 | virtual void on_demo_playback_stop() = 0; 95 | virtual bool should_draw_dropdown_console() = 0; 96 | virtual int get_screen_width() = 0; 97 | virtual int get_screen_height() = 0; 98 | virtual void write_save_game_screenshot_of_size(const char* file_name, int width, int height, 99 | bool create_power_of_2_padded = false, 100 | bool write_vtf = false) = 0; 101 | virtual bool get_player_view2(view_setup_t& player_view) = 0; 102 | bool get_player_view(view_setup_t& playerView) { 103 | typedef bool(__thiscall * func)(void*, view_setup_t&); 104 | return utils::get_virtual_function(this, 59)(this, playerView); 105 | } 106 | virtual void setup_game_properties() = 0; // c_utl_vector& contexts, 107 | // c_utl_vector& properties) = 0; 108 | virtual int get_presence_id(const char* id_name) = 0; 109 | virtual const char* get_property_id_string(const int id) = 0; 110 | virtual void get_property_display_string(int id, int value, char* output, int bytes) = 0; 111 | virtual void start_stats_reporting() = 0; // HANDLE handle, bool arbitrated) = 0; 112 | virtual void invalidate_mdl_cache() = 0; 113 | virtual void in_set_sample_time(float frame_time) = 0; 114 | virtual void reload_files_in_list() = 0; // i_file_list* files_to_reload) = 0; 115 | virtual bool handle_ui_toggle() = 0; 116 | virtual bool should_allow_console() = 0; 117 | virtual void* get_renamed_recv_table_infos() = 0; 118 | // virtual c_renamed_recv_table_info* get_renamed_recv_table_infos() = 0; 119 | // virtual c_mouth_info* get_client_ui_mouth_info() = 0; 120 | virtual void* get_client_ui_mouth_info() = 0; 121 | virtual void file_received(const char* file_name, unsigned int transfer_id) = 0; 122 | virtual const char* translate_effect_for_vision_filter(const char* pch_effect_type, 123 | const char* pch_effect_name) = 0; 124 | virtual void client_adjust_start_sound_params(struct start_sound_params_t& params) = 0; 125 | virtual bool disconnect_attempt(void) = 0; 126 | virtual bool is_connected_user_info_change_allowed(i_convar* cvar) = 0; 127 | }; 128 | -------------------------------------------------------------------------------- /tas/valve/tracing/mask_defines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // contents flags are seperate bits 4 | // a given brush can contribute multiple content bits 5 | // multiple brushes can be in a single leaf 6 | 7 | // these definitions also need to be in q_shared.h! 8 | 9 | // lower bits are stronger, and will eat weaker brushes completely 10 | #define CONTENTS_EMPTY 0 // No contents 11 | 12 | #define CONTENTS_SOLID 0x1 // an eye is never valid in a solid 13 | #define CONTENTS_WINDOW 0x2 // translucent, but not watery (glass) 14 | #define CONTENTS_AUX 0x4 15 | #define CONTENTS_GRATE \ 16 | 0x8 // alpha-tested "grate" textures. Bullets/sight pass through, but solids don't 17 | #define CONTENTS_SLIME 0x10 18 | #define CONTENTS_WATER 0x20 19 | #define CONTENTS_BLOCKLOS 0x40 // block AI line of sight 20 | #define CONTENTS_OPAQUE 0x80 // things that cannot be seen through (may be non-solid though) 21 | #define LAST_VISIBLE_CONTENTS 0x80 22 | 23 | #define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS - 1)) 24 | 25 | #define CONTENTS_TESTFOGVOLUME 0x100 26 | #define CONTENTS_UNUSED 0x200 27 | 28 | // unused 29 | // NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS 30 | // if not visible, then grab from the bottom. 31 | #define CONTENTS_UNUSED6 0x400 32 | 33 | #define CONTENTS_TEAM1 0x800 // per team contents used to differentiate collisions 34 | #define CONTENTS_TEAM2 0x1000 // between players and objects on different teams 35 | 36 | // ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW 37 | #define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000 38 | 39 | // hits entities which are MOVETYPE_PUSH (doors, plats, etc.) 40 | #define CONTENTS_MOVEABLE 0x4000 41 | 42 | // remaining contents are non-visible, and don't eat brushes 43 | #define CONTENTS_AREAPORTAL 0x8000 44 | 45 | #define CONTENTS_PLAYERCLIP 0x10000 46 | #define CONTENTS_MONSTERCLIP 0x20000 47 | 48 | // currents can be added to any other contents, and may be mixed 49 | #define CONTENTS_CURRENT_0 0x40000 50 | #define CONTENTS_CURRENT_90 0x80000 51 | #define CONTENTS_CURRENT_180 0x100000 52 | #define CONTENTS_CURRENT_270 0x200000 53 | #define CONTENTS_CURRENT_UP 0x400000 54 | #define CONTENTS_CURRENT_DOWN 0x800000 55 | 56 | #define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity 57 | 58 | #define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game 59 | #define CONTENTS_DEBRIS 0x4000000 60 | #define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs 61 | #define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans 62 | #define CONTENTS_LADDER 0x20000000 63 | #define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace 64 | 65 | // NOTE: These are stored in a short in the engine now. Don't use more than 16 bits 66 | #define SURF_LIGHT 0x0001 // value will hold the light strength 67 | #define SURF_SKY2D \ 68 | 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox 69 | #define SURF_SKY 0x0004 // don't draw, but add to skybox 70 | #define SURF_WARP 0x0008 // turbulent water warp 71 | #define SURF_TRANS 0x0010 72 | #define SURF_NOPORTAL 0x0020 // the surface can not have a portal placed on it 73 | #define SURF_TRIGGER \ 74 | 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which 75 | // breaks occluders 76 | #define SURF_NODRAW 0x0080 // don't bother referencing the texture 77 | 78 | #define SURF_HINT 0x0100 // make a primary bsp splitter 79 | 80 | #define SURF_SKIP 0x0200 // completely ignore, allowing non-closed brushes 81 | #define SURF_NOLIGHT 0x0400 // Don't calculate light 82 | #define SURF_BUMPLIGHT 0x0800 // calculate three lightmaps for the surface for bumpmapping 83 | #define SURF_NOSHADOWS 0x1000 // Don't receive shadows 84 | #define SURF_NODECALS 0x2000 // Don't receive decals 85 | #define SURF_NOCHOP 0x4000 // Don't subdivide patches on this surface 86 | #define SURF_HITBOX 0x8000 // surface is part of a hitbox 87 | 88 | // ----------------------------------------------------- 89 | // spatial content masks - used for spatial queries (traceline,etc.) 90 | // ----------------------------------------------------- 91 | #define MASK_ALL (0xFFFFFFFF) 92 | // everything that is normally solid 93 | #define MASK_SOLID \ 94 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTER | CONTENTS_GRATE) 95 | // everything that blocks player movement 96 | #define MASK_PLAYERSOLID \ 97 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | \ 98 | CONTENTS_MONSTER | CONTENTS_GRATE) 99 | // blocks npc movement 100 | #define MASK_NPCSOLID \ 101 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTERCLIP | CONTENTS_WINDOW | \ 102 | CONTENTS_MONSTER | CONTENTS_GRATE) 103 | // water physics in these contents 104 | #define MASK_WATER (CONTENTS_WATER | CONTENTS_MOVEABLE | CONTENTS_SLIME) 105 | // everything that blocks lighting 106 | #define MASK_OPAQUE (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_OPAQUE) 107 | // everything that blocks lighting, but with monsters added. 108 | #define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE | CONTENTS_MONSTER) 109 | // everything that blocks line of sight for AI 110 | #define MASK_BLOCKLOS (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_BLOCKLOS) 111 | // everything that blocks line of sight for AI plus NPCs 112 | #define MASK_BLOCKLOS_AND_NPCS (MASK_BLOCKLOS | CONTENTS_MONSTER) 113 | // everything that blocks line of sight for players 114 | #define MASK_VISIBLE (MASK_OPAQUE | CONTENTS_IGNORE_NODRAW_OPAQUE) 115 | // everything that blocks line of sight for players, but with monsters added. 116 | #define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS | CONTENTS_IGNORE_NODRAW_OPAQUE) 117 | // bullets see these as solid 118 | #define MASK_SHOT \ 119 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTER | CONTENTS_WINDOW | CONTENTS_DEBRIS | \ 120 | CONTENTS_HITBOX) 121 | // non-raycasted weapons see this as solid (includes grates) 122 | #define MASK_SHOT_HULL \ 123 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_MONSTER | CONTENTS_WINDOW | CONTENTS_DEBRIS | \ 124 | CONTENTS_GRATE) 125 | // hits solids (not grates) and passes through everything else 126 | #define MASK_SHOT_PORTAL \ 127 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTER) 128 | // everything normally solid, except monsters (world+brush only) 129 | #define MASK_SOLID_BRUSHONLY \ 130 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_GRATE) 131 | // everything normally solid for player movement, except monsters (world+brush only) 132 | #define MASK_PLAYERSOLID_BRUSHONLY \ 133 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_PLAYERCLIP | CONTENTS_GRATE) 134 | // everything normally solid for npc movement, except monsters (world+brush only) 135 | #define MASK_NPCSOLID_BRUSHONLY \ 136 | (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP | CONTENTS_GRATE) 137 | // just the world, used for route rebuilding 138 | #define MASK_NPCWORLDSTATIC \ 139 | (CONTENTS_SOLID | CONTENTS_WINDOW | CONTENTS_MONSTERCLIP | CONTENTS_GRATE) 140 | // These are things that can split areaportals 141 | #define MASK_SPLITAREAPORTAL (CONTENTS_WATER | CONTENTS_SLIME) 142 | 143 | // UNDONE: This is untested, any moving water 144 | #define MASK_CURRENT \ 145 | (CONTENTS_CURRENT_0 | CONTENTS_CURRENT_90 | CONTENTS_CURRENT_180 | CONTENTS_CURRENT_270 | \ 146 | CONTENTS_CURRENT_UP | CONTENTS_CURRENT_DOWN) 147 | 148 | // everything that blocks corpse movement 149 | // UNDONE: Not used yet / may be deleted 150 | #define MASK_DEADSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_WINDOW | CONTENTS_GRATE) 151 | -------------------------------------------------------------------------------- /tas/core/input/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include "cheat.h" 3 | #include "core/menu/menu.h" 4 | 5 | #include 6 | #include 7 | 8 | extern long ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM); 9 | 10 | BOOL WINAPI hooked_SetCursorPos(std::int32_t x, std::int32_t y) noexcept { 11 | if (!menu::open) { 12 | return cheat::input.SetCursorPos_hook.stdcall(x, y); 13 | } 14 | 15 | cheat::input.last_cursor_pos = {x, y}; 16 | 17 | return TRUE; 18 | } 19 | 20 | BOOL WINAPI hooked_GetCursorPos(LPPOINT point) noexcept { 21 | if (!menu::open) { 22 | return cheat::input.GetCursorPos_hook.stdcall(point); 23 | } 24 | 25 | if (point != nullptr) { 26 | *point = cheat::input.last_cursor_pos; 27 | } 28 | 29 | return TRUE; 30 | } 31 | 32 | std::int32_t WINAPI hooked_ShowCursor(BOOL show) noexcept { 33 | if (!menu::open) { 34 | return cheat::input.ShowCursor_hook.stdcall(show); 35 | } 36 | 37 | // Keep track of cursor show count while the menu is open. 38 | if (show == TRUE) { 39 | ++cheat::input.show_cursor_count; 40 | } else { 41 | --cheat::input.show_cursor_count; 42 | } 43 | 44 | return cheat::input.show_cursor_count; 45 | } 46 | 47 | HCURSOR WINAPI hooked_SetCursor(HCURSOR cursor) noexcept { 48 | if (!menu::open) { 49 | cheat::input.last_cursor = cursor; 50 | return cheat::input.SetCursor_hook.stdcall(cursor); 51 | } 52 | 53 | auto prev = cheat::input.last_cursor; 54 | 55 | cheat::input.last_cursor = cursor; 56 | 57 | return prev; 58 | } 59 | 60 | HCURSOR WINAPI hooked_GetCursor() noexcept { 61 | if (!menu::open) { 62 | return cheat::input.GetCursor_hook.stdcall(); 63 | } 64 | 65 | return cheat::input.last_cursor; 66 | } 67 | 68 | BOOL WINAPI hooked_GetCursorInfo(PCURSORINFO pci) noexcept { 69 | if (!menu::open || pci == nullptr) { 70 | return cheat::input.GetCursorInfo_hook.stdcall(pci); 71 | } 72 | 73 | // Feed saved data into cursor info. 74 | pci->ptScreenPos = cheat::input.last_cursor_pos; 75 | 76 | if (pci->flags != CURSOR_SUPPRESSED && cheat::input.show_cursor_count >= 0) { 77 | pci->flags = CURSOR_SHOWING; 78 | } 79 | 80 | pci->hCursor = cheat::input.last_cursor; 81 | 82 | return cheat::input.GetCursorInfo_hook.stdcall(pci); 83 | } 84 | 85 | BOOL WINAPI hooked_ClipCursor(const RECT* rect) noexcept { 86 | cheat::input.last_cursor_clip = *rect; 87 | 88 | if (menu::open) { 89 | rect = nullptr; 90 | } 91 | 92 | return cheat::input.ClipCursor_hook.stdcall(rect); 93 | } 94 | 95 | BOOL WINAPI hooked_GetClipCursor(LPRECT rect) noexcept { 96 | if (!menu::open || rect == nullptr) { 97 | return cheat::input.GetClipCursor_hook.stdcall(rect); 98 | } 99 | 100 | *rect = cheat::input.last_cursor_clip; 101 | 102 | return TRUE; 103 | } 104 | 105 | LRESULT WINAPI wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) noexcept { 106 | auto stop_input = false; 107 | 108 | if (!cheat::attached) { 109 | return CallWindowProcW(cheat::input.orig_wndproc, hwnd, msg, wp, lp); 110 | } 111 | 112 | // NOTE: Calling `DefWindowProc` on these cause application hang (menu bar). IDK, Needs 113 | // testing. 114 | auto call_def = true; 115 | 116 | switch (msg) { 117 | case WM_SYSKEYDOWN: 118 | case WM_SYSKEYUP: 119 | case WM_SYSCHAR: { 120 | call_def = false; 121 | break; 122 | } 123 | 124 | default: { 125 | break; 126 | } 127 | } 128 | 129 | switch (msg) { 130 | case WM_KEYDOWN: 131 | case WM_KEYUP: { 132 | auto is_key_down = msg == WM_KEYDOWN; 133 | 134 | uint8_t vk{}; 135 | 136 | vk = wp; 137 | 138 | cheat::input.keys[vk] = is_key_down ? InputState::Down : InputState::Up; 139 | 140 | break; 141 | } 142 | 143 | default: { 144 | break; 145 | } 146 | } 147 | 148 | // Pass input to Dear ImGui. 149 | // NOTE: https://github.com/ocornut/imgui/issues/6895#issuecomment-1747239385 150 | { 151 | std::scoped_lock _{cheat::input.imgui_mutex}; 152 | ImGui_ImplWin32_WndProcHandler(hwnd, msg, wp, lp); 153 | } 154 | 155 | if (menu::open) { 156 | // Stop input if hovering menu. 157 | if (menu::allow_passthrough) { 158 | // TODO: Whitelist messages if needed (sizing, etc). 159 | 160 | auto& io = ImGui::GetIO(); 161 | 162 | if (io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput) { 163 | stop_input = true; 164 | } 165 | } else { 166 | stop_input = true; 167 | } 168 | } 169 | 170 | if (stop_input) { 171 | return call_def ? DefWindowProcW(hwnd, msg, wp, lp) : 0; 172 | } 173 | 174 | return CallWindowProcW(cheat::input.orig_wndproc, hwnd, msg, wp, lp); 175 | } 176 | 177 | void input_t::pre_check() noexcept {} 178 | 179 | void input_t::post_check() noexcept { last_keys = keys; } 180 | 181 | bool input_t::key_down(uint8_t vk) const noexcept { return keys[vk] == InputState::Down; } 182 | 183 | bool input_t::key_pressed(uint8_t vk) const noexcept { 184 | return keys[vk] == InputState::Down && last_keys[vk] == InputState::Up; 185 | } 186 | 187 | void input_t::on_menu_open() noexcept { 188 | // Can we see the cursor? 189 | CURSORINFO ci{.cbSize = sizeof(CURSORINFO)}; 190 | GetCursorInfo(&ci); 191 | 192 | // Hide the cursor. 193 | if (ci.flags == CURSOR_SHOWING) { 194 | if ((show_cursor_count = ShowCursor_hook.stdcall(FALSE) + 1) >= 0) { 195 | while (ShowCursor_hook.stdcall(FALSE) >= 0) {} 196 | } 197 | } 198 | 199 | // Save off cursor info. 200 | GetCursorPos_hook.stdcall(&last_cursor_pos); 201 | 202 | last_cursor = GetCursor_hook.stdcall(); 203 | 204 | // Force a mouse event. 205 | PostMessageW(cheat::window, WM_SETCURSOR, (WPARAM)cheat::window, 206 | MAKELPARAM(HTCLIENT, WM_MOUSEMOVE)); 207 | } 208 | 209 | void input_t::on_menu_close() noexcept { 210 | // Restore original show amount. 211 | auto show_count = ShowCursor_hook.stdcall(TRUE); 212 | auto show_count_restore = show_count < show_cursor_count; 213 | 214 | if (show_count > show_cursor_count) { 215 | std::int32_t cur_show_count; 216 | 217 | while ((cur_show_count = ShowCursor_hook.stdcall(FALSE)) > show_cursor_count) 218 | show_count_restore = cur_show_count < show_cursor_count; 219 | } 220 | 221 | if (show_count_restore) { 222 | while (ShowCursor_hook.stdcall(TRUE) < show_cursor_count) {} 223 | } 224 | 225 | // Restore original cursor info. 226 | SetCursorPos_hook.stdcall(last_cursor_pos.x, last_cursor_pos.y); 227 | SetCursor_hook.stdcall(last_cursor); 228 | 229 | // Force a mouse event. 230 | PostMessageW(cheat::window, WM_SETCURSOR, (WPARAM)cheat::window, 231 | MAKELPARAM(HTCLIENT, WM_MOUSEMOVE)); 232 | } 233 | 234 | void input_t::initialize() noexcept { 235 | SetCursorPos_hook = safetyhook::create_inline(reinterpret_cast(SetCursorPos), 236 | reinterpret_cast(hooked_SetCursorPos)); 237 | 238 | GetCursorPos_hook = safetyhook::create_inline(reinterpret_cast(GetCursorPos), 239 | reinterpret_cast(hooked_GetCursorPos)); 240 | 241 | ShowCursor_hook = safetyhook::create_inline(reinterpret_cast(ShowCursor), 242 | reinterpret_cast(hooked_ShowCursor)); 243 | 244 | SetCursor_hook = safetyhook::create_inline(reinterpret_cast(SetCursor), 245 | reinterpret_cast(hooked_SetCursor)); 246 | 247 | GetCursor_hook = safetyhook::create_inline(reinterpret_cast(GetCursor), 248 | reinterpret_cast(hooked_GetCursor)); 249 | 250 | GetCursorInfo_hook = safetyhook::create_inline(reinterpret_cast(GetCursorInfo), 251 | reinterpret_cast(hooked_GetCursorInfo)); 252 | 253 | ClipCursor_hook = safetyhook::create_inline(reinterpret_cast(ClipCursor), 254 | reinterpret_cast(hooked_ClipCursor)); 255 | 256 | GetClipCursor_hook = safetyhook::create_inline(reinterpret_cast(GetClipCursor), 257 | reinterpret_cast(hooked_GetClipCursor)); 258 | 259 | orig_wndproc = reinterpret_cast( 260 | SetWindowLongPtrW(cheat::window, GWLP_WNDPROC, reinterpret_cast(wndproc))); 261 | } 262 | 263 | void input_t::detach() noexcept { 264 | SetWindowLongPtrW(cheat::window, GWLP_WNDPROC, reinterpret_cast(orig_wndproc)); 265 | 266 | GetClipCursor_hook = {}; 267 | ClipCursor_hook = {}; 268 | GetCursorInfo_hook = {}; 269 | GetCursor_hook = {}; 270 | SetCursor_hook = {}; 271 | ShowCursor_hook = {}; 272 | GetCursorPos_hook = {}; 273 | SetCursorPos_hook = {}; 274 | } 275 | -------------------------------------------------------------------------------- /tas/valve/prediction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "library/math.h" 4 | 5 | #pragma pack(push, 1) 6 | class view_vectors_t { 7 | public: 8 | vector3_t view; 9 | 10 | vector3_t hull_min; 11 | vector3_t hull_max; 12 | 13 | vector3_t duck_hull_min; 14 | vector3_t duck_hull_max; 15 | vector3_t duck_view; 16 | 17 | vector3_t obs_hull_min; 18 | vector3_t obs_hull_max; 19 | 20 | vector3_t dead_view_height; 21 | }; 22 | #pragma pack(pop) 23 | 24 | class ccsgamerules_t { 25 | public: 26 | virtual void pad_00() = 0; 27 | virtual void pad_01() = 0; 28 | virtual void pad_02() = 0; 29 | virtual void pad_03() = 0; 30 | virtual void pad_04() = 0; 31 | virtual void pad_05() = 0; 32 | virtual void pad_06() = 0; 33 | virtual void pad_07() = 0; 34 | virtual void pad_08() = 0; 35 | virtual void pad_09() = 0; 36 | virtual void pad_10() = 0; 37 | virtual void pad_11() = 0; 38 | virtual void pad_12() = 0; 39 | virtual void pad_13() = 0; 40 | virtual void pad_14() = 0; 41 | virtual void pad_15() = 0; 42 | virtual void pad_16() = 0; 43 | virtual void pad_17() = 0; 44 | virtual void pad_18() = 0; 45 | virtual void pad_19() = 0; 46 | virtual void pad_20() = 0; 47 | virtual void pad_21() = 0; 48 | virtual void pad_22() = 0; 49 | virtual void pad_23() = 0; 50 | virtual void pad_24() = 0; 51 | virtual void pad_25() = 0; 52 | virtual void pad_26() = 0; 53 | virtual void pad_27() = 0; 54 | virtual void pad_28() = 0; 55 | virtual void pad_29() = 0; 56 | virtual void pad_30() = 0; 57 | virtual view_vectors_t* get_view_vectors() noexcept = 0; 58 | }; 59 | 60 | class i_prediction_t { 61 | public: 62 | virtual ~i_prediction_t(){}; 63 | virtual void init() = 0; 64 | virtual void shutdown() = 0; 65 | virtual void update(int start_frame, bool valid_frame, int incoming_acknowledged, 66 | int outgoing_command) = 0; 67 | 68 | virtual void pre_entity_packet_received(int commands_acknowledged, 69 | int current_world_update_packet) = 0; 70 | virtual void post_entity_packet_received() = 0; 71 | virtual void post_network_data_received(int commands_acknowledged) = 0; 72 | virtual void on_received_uncompressed_packet() = 0; 73 | virtual void get_view_origin(vector3_t& org) = 0; 74 | virtual void set_view_origin(vector3_t& org) = 0; 75 | virtual void get_view_angles(vector3_t& ang) = 0; 76 | virtual void set_view_angles(vector3_t& ang) = 0; 77 | virtual void get_local_view_angles(vector3_t& ang) = 0; 78 | virtual void set_local_view_angles(vector3_t& ang) = 0; 79 | }; 80 | 81 | class player_t; 82 | class usercmd_t; 83 | class move_helper_t; 84 | 85 | class move_data_t { 86 | 87 | public: 88 | // bool is_first_run_of_functions : 1; 89 | // bool is_game_code_moved_player : 1; 90 | 91 | // void* player_handle; // edict index on server, client entity handle on client 92 | 93 | // int impulse_command; // Impulse command issued. 94 | // vector3_t view_angles; // Command view angles (local space) 95 | // vector3_t abs_view_angles; // Command view angles (world space) 96 | // int buttons; // Attack buttons. 97 | // int old_buttons; // From host_client->oldbuttons; 98 | // float forward_move; 99 | // float old_forward_move; 100 | // float side_move; 101 | // float up_move; 102 | 103 | // float max_speed; 104 | // float client_max_speed; 105 | 106 | // // Variables from the player edict (sv_player) or entvars on the client. 107 | // // These are copied in here before calling and copied out after calling. 108 | // vector3_t velocity; 109 | // vector3_t angles; 110 | // vector3_t old_angles; 111 | 112 | // // Output only 113 | // float out_step_height; // how much you climbed this move 114 | // vector3_t out_wish_vel; // This is where you tried 115 | // vector3_t out_jump_vel; // This is your jump velocity 116 | 117 | // // Movement constraints 118 | // vector3_t constraint_center; 119 | // float constraint_radius; 120 | // float constraint_width; 121 | // // float constraint_speed_factor; 122 | 123 | // // private: 124 | // vector3_t abs_origin; // edict::origin 125 | char pad_0[0xc]; 126 | vector3_t view_angles; // 0xc 127 | char pad_18[0xc]; 128 | int buttons; // 0x24 129 | char pad_28[0x4]; 130 | float forward_move; // 0x2c 131 | float side_move; // 0x30 132 | float up_move; // 0x34 133 | char pad_38[0x8]; 134 | vector3_t velocity; // 0x40 135 | vector3_t angles; // 0x4c 136 | vector3_t old_angles; // 0x58 137 | char pad_64[0x34]; 138 | vector3_t abs_origin; // 0x98 139 | }; 140 | 141 | class move_helper_t { 142 | public: 143 | virtual void set_host(player_t*) = 0; 144 | }; 145 | 146 | class prediction_manager_t : i_prediction_t { 147 | public: 148 | virtual ~prediction_manager_t(); 149 | virtual void init(); 150 | virtual void shutdown(); 151 | virtual void update(int, bool, int, int); 152 | 153 | virtual void on_received_uncompressed_packet() = 0; 154 | virtual void pre_entity_packet_received(int, int) = 0; 155 | virtual void post_entity_packet_received() = 0; 156 | virtual void post_network_data_received(int) = 0; 157 | virtual bool in_prediction() = 0; 158 | virtual bool is_first_time_predicted() = 0; 159 | virtual int get_incoming_packet_number() = 0; 160 | virtual void get_view_origin(vector3_t&) = 0; 161 | virtual void set_view_origin(vector3_t&) = 0; 162 | virtual void get_view_angles(vector3_t&) = 0; 163 | virtual void set_view_angles(vector3_t&) = 0; 164 | virtual void get_local_view_angles(vector3_t&) = 0; 165 | virtual void set_local_view_angles(vector3_t&) = 0; 166 | virtual void run_command(player_t*, usercmd_t*, move_helper_t*) = 0; 167 | virtual void setup_move(player_t*, usercmd_t*, move_helper_t*, move_data_t*) = 0; 168 | virtual void finish_move(player_t*, usercmd_t*, move_data_t*) = 0; 169 | virtual void set_ideal_pitch(player_t*, const vector3_t&, const vector3_t&, 170 | const vector3_t&) = 0; 171 | virtual void _update(bool, bool, int, int) = 0; 172 | 173 | uint32_t last_ground; 174 | bool is_in_prediction; 175 | bool first_time_predicted; 176 | bool old_cl_predict_value; 177 | bool engine_paused; 178 | int previous_start_frame; 179 | int commands_predicted; 180 | int server_commands_acknowledged; 181 | int previous_ack_had_errors; 182 | int incoming_packet_number; 183 | float ideal_pitch; 184 | }; 185 | 186 | class game_movement_t { 187 | public: 188 | virtual ~game_movement_t(void) {} 189 | 190 | // Process the current movement command 191 | virtual void proccess_movement(player_t* pPlayer, move_data_t* pMove) = 0; 192 | virtual void start_track_prediction_errors(player_t* pPlayer) = 0; 193 | virtual void finish_tack_prediction_errors(player_t* pPlayer) = 0; 194 | virtual void diff_print(char const* fmt, ...) = 0; 195 | 196 | // Allows other parts of the engine to find out the normal and ducked player bbox sizes 197 | virtual vector3_t get_player_mins(bool ducked) const = 0; 198 | virtual vector3_t get_player_maxs(bool ducked) const = 0; 199 | virtual vector3_t get_player_view_offset(bool ducked) const = 0; 200 | }; 201 | --------------------------------------------------------------------------------