Add bullet changes from iw4x
This commit is contained in:
parent
949d6ad9d5
commit
f4f5960dcf
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -34,3 +34,6 @@
|
|||||||
path = deps/zstd
|
path = deps/zstd
|
||||||
url = https://github.com/facebook/zstd.git
|
url = https://github.com/facebook/zstd.git
|
||||||
branch = dev
|
branch = dev
|
||||||
|
[submodule "deps/minhook"]
|
||||||
|
path = deps/minhook
|
||||||
|
url = https://github.com/TsudaKageyu/minhook.git
|
||||||
|
1
deps/minhook
vendored
Submodule
1
deps/minhook
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4a455528f61b5a375b1f9d44e7d296d47f18bb18
|
31
deps/premake/minhook.lua
vendored
Normal file
31
deps/premake/minhook.lua
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
minhook = {
|
||||||
|
source = path.join(dependencies.basePath, "minhook"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function minhook.import()
|
||||||
|
links { "minhook" }
|
||||||
|
minhook.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function minhook.includes()
|
||||||
|
includedirs {
|
||||||
|
path.join(minhook.source, "include")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function minhook.project()
|
||||||
|
project "minhook"
|
||||||
|
language "C"
|
||||||
|
|
||||||
|
minhook.includes()
|
||||||
|
|
||||||
|
files {
|
||||||
|
path.join(minhook.source, "src/**.h"),
|
||||||
|
path.join(minhook.source, "src/**.c"),
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, minhook)
|
@ -17,8 +17,6 @@ namespace game
|
|||||||
|
|
||||||
Dvar_RegisterInt_t Dvar_RegisterInt;
|
Dvar_RegisterInt_t Dvar_RegisterInt;
|
||||||
|
|
||||||
Dvar_RegisterFloat_t Dvar_RegisterFloat;
|
|
||||||
|
|
||||||
Dvar_SetIntByName_t Dvar_SetIntByName;
|
Dvar_SetIntByName_t Dvar_SetIntByName;
|
||||||
|
|
||||||
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||||
@ -246,11 +244,64 @@ namespace game
|
|||||||
{
|
{
|
||||||
return dvar_find_malleable_var(dvarName);
|
return dvar_find_malleable_var(dvarName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return reinterpret_cast<dvar_t*(*)(const char*)>
|
return reinterpret_cast<dvar_t*(*)(const char*)>
|
||||||
(SELECT_VALUE(0x539550, 0x5BDCC0, 0x0))(dvarName);
|
(SELECT_VALUE(0x539550, 0x5BDCC0, 0x0))(dvarName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr auto Dvar_RegisterVariant_Addr = 0x531F70;
|
||||||
|
__declspec(naked) const dvar_t* Dvar_RegisterVariant(const char* dvarName, unsigned char type,
|
||||||
|
unsigned __int16 flags, DvarValue value, DvarLimits domain, const char* description)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push eax
|
||||||
|
pushad
|
||||||
|
|
||||||
|
mov edi, [esp + 0x24 + 0x28] // description
|
||||||
|
mov eax, [esp + 0x24 + 0x4] // dvarName
|
||||||
|
|
||||||
|
push [esp + 0x24 + 0x24] // domain
|
||||||
|
push [esp + 0x24 + 0x24] // domain
|
||||||
|
|
||||||
|
push [esp + 0x24 + 0x24] // value
|
||||||
|
push [esp + 0x24 + 0x24] // value
|
||||||
|
push [esp + 0x24 + 0x24] // value
|
||||||
|
push [esp + 0x24 + 0x24] // value
|
||||||
|
|
||||||
|
push [esp + 0x24 + 0x24] // flags
|
||||||
|
push [esp + 0x24 + 0x24] // type
|
||||||
|
|
||||||
|
call Dvar_RegisterVariant_Addr
|
||||||
|
add esp, 0x20
|
||||||
|
|
||||||
|
mov [esp + 0x20], eax // result
|
||||||
|
popad
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dvar_t* Dvar_RegisterFloat(const char* dvarName, float value,
|
||||||
|
float min, float max, unsigned __int16 flags, const char* description)
|
||||||
|
{
|
||||||
|
if (!is_dedi())
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const dvar_t*(*)(const char*, float, float, float, unsigned __int16, const char*)>
|
||||||
|
(SELECT_VALUE(0x4F9CC0, 0x5BEA80, 0x0))(dvarName, value, min, max, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
DvarLimits domain;
|
||||||
|
DvarValue dvar_value;
|
||||||
|
|
||||||
|
domain.value.min = min;
|
||||||
|
domain.value.max = max;
|
||||||
|
|
||||||
|
dvar_value.value = value;
|
||||||
|
|
||||||
|
return Dvar_RegisterVariant(dvarName, dvar_type::DVAR_TYPE_FLOAT,
|
||||||
|
flags, dvar_value, domain, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* Scr_AllocVector(const float* v)
|
const float* Scr_AllocVector(const float* v)
|
||||||
@ -632,8 +683,6 @@ namespace game
|
|||||||
|
|
||||||
native::Dvar_RegisterInt = native::Dvar_RegisterInt_t(SELECT_VALUE(0x48CD40, 0x5BEA40, 0x0));
|
native::Dvar_RegisterInt = native::Dvar_RegisterInt_t(SELECT_VALUE(0x48CD40, 0x5BEA40, 0x0));
|
||||||
|
|
||||||
native::Dvar_RegisterFloat = native::Dvar_RegisterFloat_t(SELECT_VALUE(0x4F9CC0, 0x5BEA80, 0x0));
|
|
||||||
|
|
||||||
native::Dvar_SetIntByName = native::Dvar_SetIntByName_t(SELECT_VALUE(0x5396B0, 0x5BF560, 0x0));
|
native::Dvar_SetIntByName = native::Dvar_SetIntByName_t(SELECT_VALUE(0x5396B0, 0x5BF560, 0x0));
|
||||||
|
|
||||||
native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(
|
native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(
|
||||||
|
@ -31,10 +31,6 @@ namespace game
|
|||||||
int min, int max, unsigned __int16 flags, const char* description);
|
int min, int max, unsigned __int16 flags, const char* description);
|
||||||
extern Dvar_RegisterInt_t Dvar_RegisterInt;
|
extern Dvar_RegisterInt_t Dvar_RegisterInt;
|
||||||
|
|
||||||
typedef const dvar_t* (*Dvar_RegisterFloat_t)(const char* dvarName, float value,
|
|
||||||
float min, float max, unsigned __int16 flags, const char* description);
|
|
||||||
extern Dvar_RegisterFloat_t Dvar_RegisterFloat;
|
|
||||||
|
|
||||||
typedef void (*Dvar_SetIntByName_t)(const char* dvarName, int value);
|
typedef void (*Dvar_SetIntByName_t)(const char* dvarName, int value);
|
||||||
extern Dvar_SetIntByName_t Dvar_SetIntByName;
|
extern Dvar_SetIntByName_t Dvar_SetIntByName;
|
||||||
|
|
||||||
@ -104,8 +100,8 @@ namespace game
|
|||||||
typedef void (*PM_WeaponUseAmmo_t)(playerState_s* ps, const Weapon weapon, bool isAlternate, int amount, PlayerHandIndex hand);
|
typedef void (*PM_WeaponUseAmmo_t)(playerState_s* ps, const Weapon weapon, bool isAlternate, int amount, PlayerHandIndex hand);
|
||||||
extern PM_WeaponUseAmmo_t PM_WeaponUseAmmo;
|
extern PM_WeaponUseAmmo_t PM_WeaponUseAmmo;
|
||||||
|
|
||||||
typedef void (*CM_TransformedCapsuleTrace_t)(game::native::trace_t* results, const float* start, const float* end,
|
typedef void (*CM_TransformedCapsuleTrace_t)(trace_t* results, const float* start, const float* end,
|
||||||
const game::native::Bounds* bounds, const game::native::Bounds* capsule, int contents,
|
const Bounds* bounds, const Bounds* capsule, int contents,
|
||||||
const float* origin, const float* angles);
|
const float* origin, const float* angles);
|
||||||
extern CM_TransformedCapsuleTrace_t CM_TransformedCapsuleTrace;
|
extern CM_TransformedCapsuleTrace_t CM_TransformedCapsuleTrace;
|
||||||
|
|
||||||
@ -197,6 +193,8 @@ namespace game
|
|||||||
void* MT_Alloc(int numBytes, int type);
|
void* MT_Alloc(int numBytes, int type);
|
||||||
|
|
||||||
dvar_t* Dvar_FindVar(const char* dvarName);
|
dvar_t* Dvar_FindVar(const char* dvarName);
|
||||||
|
const dvar_t* Dvar_RegisterVariant(const char* dvarName, unsigned char type, unsigned __int16 flags, DvarValue value, DvarLimits domain, const char* description);
|
||||||
|
const dvar_t* Dvar_RegisterFloat(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description);
|
||||||
|
|
||||||
const float* Scr_AllocVector(const float* v);
|
const float* Scr_AllocVector(const float* v);
|
||||||
void Scr_ClearOutParams();
|
void Scr_ClearOutParams();
|
||||||
|
@ -547,13 +547,14 @@ namespace game
|
|||||||
|
|
||||||
enum dvar_flags : std::uint16_t
|
enum dvar_flags : std::uint16_t
|
||||||
{
|
{
|
||||||
DVAR_ARCHIVE = 0x1,
|
DVAR_ARCHIVE = 1 << 0,
|
||||||
DVAR_CHEAT = 0x4,
|
DVAR_CHEAT = 1 << 2,
|
||||||
DVAR_CODINFO = 0x8,
|
DVAR_CODINFO = 1 << 3,
|
||||||
DVAR_SCRIPTINFO = 0x10,
|
DVAR_SCRIPTINFO = 1 << 4,
|
||||||
DVAR_SERVERINFO = 0x400,
|
DVAR_SERVERINFO = 1 << 10,
|
||||||
DVAR_WRITEPROTECTED = 0x800,
|
DVAR_WRITEPROTECTED = 1 << 11,
|
||||||
DVAR_READONLY = 0x2000,
|
DVAR_READONLY = 1 << 13,
|
||||||
|
DVAR_AUTOEXEC = 1 << 15,
|
||||||
}; // Incomplete
|
}; // Incomplete
|
||||||
|
|
||||||
enum dvar_type : std::int8_t
|
enum dvar_type : std::int8_t
|
||||||
@ -581,6 +582,8 @@ namespace game
|
|||||||
char color[4];
|
char color[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(DvarValue) == 0x10);
|
||||||
|
|
||||||
struct enum_limit
|
struct enum_limit
|
||||||
{
|
{
|
||||||
int stringCount;
|
int stringCount;
|
||||||
|
56
src/module/bullet.cpp
Normal file
56
src/module/bullet.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include <loader/module_loader.hpp>
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
#include "bullet.hpp"
|
||||||
|
|
||||||
|
const game::native::dvar_t* bullet::bg_bulletRange;
|
||||||
|
const game::native::dvar_t* bullet::bg_surfacePenetration;
|
||||||
|
|
||||||
|
DWORD bullet::bullet_fire_addr;
|
||||||
|
|
||||||
|
utils::hook::detour bullet::bg_get_surface_penetration_depth_hook;
|
||||||
|
|
||||||
|
__declspec(naked) void bullet::bullet_fire_stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push eax
|
||||||
|
mov eax, bg_bulletRange
|
||||||
|
fld dword ptr [eax + 0xC] //dvar_t.current
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
jmp bullet_fire_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float bullet::bg_get_surface_penetration_depth_stub(const game::native::Weapon weapon, bool is_alternate, int surface_type)
|
||||||
|
{
|
||||||
|
const auto value = bg_surfacePenetration->current.value;
|
||||||
|
if (value > 0.0f)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bg_get_surface_penetration_depth_hook.invoke<float>(weapon, is_alternate, surface_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bullet::post_load()
|
||||||
|
{
|
||||||
|
bg_bulletRange = game::native::Dvar_RegisterFloat("bg_bulletRange", 8192.0f, 0.0f,
|
||||||
|
std::numeric_limits<float>::max(), game::native::DVAR_CODINFO,
|
||||||
|
"Max range used when calculating the bullet end position");
|
||||||
|
|
||||||
|
bg_surfacePenetration = game::native::Dvar_RegisterFloat("bg_surfacePenetration", 0.0f,
|
||||||
|
0.0f, std::numeric_limits<float>::max(), game::native::DVAR_CODINFO,
|
||||||
|
"Set to a value greater than 0 to override the surface penetration depth");
|
||||||
|
|
||||||
|
bullet_fire_addr = SELECT_VALUE(0x5B6442, 0x4F6C5C, 0x46CFFA);
|
||||||
|
utils::hook(SELECT_VALUE(0x5B643C, 0x4F6C56, 0x46CFF4), &bullet_fire_stub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
bg_get_surface_penetration_depth_hook.create(SELECT_VALUE(0x43BDE0, 0x42F4D0, 0x421610), &bg_get_surface_penetration_depth_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_MODULE(bullet)
|
17
src/module/bullet.hpp
Normal file
17
src/module/bullet.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class bullet final : public module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_load() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const game::native::dvar_t* bg_bulletRange;
|
||||||
|
static const game::native::dvar_t* bg_surfacePenetration;
|
||||||
|
|
||||||
|
static DWORD bullet_fire_addr;
|
||||||
|
static void bullet_fire_stub();
|
||||||
|
|
||||||
|
static utils::hook::detour bg_get_surface_penetration_depth_hook;
|
||||||
|
static float bg_get_surface_penetration_depth_stub(const game::native::Weapon weapon, bool isAlternate, int surfaceType);
|
||||||
|
};
|
@ -1,8 +1,30 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "hook.hpp"
|
#include "hook.hpp"
|
||||||
|
|
||||||
|
#include <MinHook.h>
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
[[maybe_unused]] class _
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
_()
|
||||||
|
{
|
||||||
|
if (MH_Initialize() != MH_OK)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to initialize MinHook");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~_()
|
||||||
|
{
|
||||||
|
MH_Uninitialize();
|
||||||
|
}
|
||||||
|
} __;
|
||||||
|
}
|
||||||
|
|
||||||
void hook::signature::process()
|
void hook::signature::process()
|
||||||
{
|
{
|
||||||
if (this->signatures_.empty()) return;
|
if (this->signatures_.empty()) return;
|
||||||
@ -42,6 +64,64 @@ namespace utils
|
|||||||
signatures_.push_back(container);
|
signatures_.push_back(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook::detour::detour(const size_t place, void* target) : detour(reinterpret_cast<void*>(place), target)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
hook::detour::detour(void* place, void* target)
|
||||||
|
{
|
||||||
|
this->create(place, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
hook::detour::~detour()
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook::detour::enable() const
|
||||||
|
{
|
||||||
|
MH_EnableHook(this->place_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook::detour::disable() const
|
||||||
|
{
|
||||||
|
MH_DisableHook(this->place_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook::detour::create(void* place, void* target)
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
this->place_ = place;
|
||||||
|
|
||||||
|
if (MH_CreateHook(this->place_, target, &this->original_) != MH_OK)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Unable to create hook");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook::detour::create(const size_t place, void* target)
|
||||||
|
{
|
||||||
|
this->create(reinterpret_cast<void*>(place), target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hook::detour::clear()
|
||||||
|
{
|
||||||
|
if (this->place_)
|
||||||
|
{
|
||||||
|
MH_RemoveHook(this->place_);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->place_ = nullptr;
|
||||||
|
this->original_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* hook::detour::get_original() const
|
||||||
|
{
|
||||||
|
return this->original_;
|
||||||
|
}
|
||||||
|
|
||||||
hook::~hook()
|
hook::~hook()
|
||||||
{
|
{
|
||||||
if (this->initialized_)
|
if (this->initialized_)
|
||||||
|
@ -40,6 +40,64 @@ namespace utils
|
|||||||
std::vector<container> signatures_;
|
std::vector<container> signatures_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class detour
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
detour() = default;
|
||||||
|
detour(void* place, void* target);
|
||||||
|
detour(size_t place, void* target);
|
||||||
|
~detour();
|
||||||
|
|
||||||
|
detour(detour&& other) noexcept
|
||||||
|
{
|
||||||
|
this->operator=(std::move(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
detour& operator=(detour&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
this->~detour();
|
||||||
|
|
||||||
|
this->place_ = other.place_;
|
||||||
|
this->original_ = other.original_;
|
||||||
|
|
||||||
|
other.place_ = nullptr;
|
||||||
|
other.original_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
detour(const detour&) = delete;
|
||||||
|
detour& operator=(const detour&) = delete;
|
||||||
|
|
||||||
|
void enable() const;
|
||||||
|
void disable() const;
|
||||||
|
|
||||||
|
void create(void* place, void* target);
|
||||||
|
void create(size_t place, void* target);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* get() const
|
||||||
|
{
|
||||||
|
return static_cast<T*>(this->get_original());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = void, typename... Args>
|
||||||
|
T invoke(Args ... args)
|
||||||
|
{
|
||||||
|
return static_cast<T(*)(Args ...)>(this->get_original())(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] void* get_original() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* place_{};
|
||||||
|
void* original_{};
|
||||||
|
};
|
||||||
|
|
||||||
hook() : initialized_(false), installed_(false), place_(nullptr), stub_(nullptr), original_(nullptr),
|
hook() : initialized_(false), installed_(false), place_(nullptr), stub_(nullptr), original_(nullptr),
|
||||||
use_jump_(false), protection_(0)
|
use_jump_(false), protection_(0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user