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
|
||||
url = https://github.com/facebook/zstd.git
|
||||
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_RegisterFloat_t Dvar_RegisterFloat;
|
||||
|
||||
Dvar_SetIntByName_t Dvar_SetIntByName;
|
||||
|
||||
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||
@ -246,13 +244,66 @@ namespace game
|
||||
{
|
||||
return dvar_find_malleable_var(dvarName);
|
||||
}
|
||||
else
|
||||
|
||||
return reinterpret_cast<dvar_t*(*)(const char*)>
|
||||
(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
|
||||
{
|
||||
return reinterpret_cast<dvar_t*(*)(const char*)>
|
||||
(SELECT_VALUE(0x539550, 0x5BDCC0, 0x0))(dvarName);
|
||||
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 auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
|
||||
@ -632,8 +683,6 @@ namespace game
|
||||
|
||||
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_SetFromStringByName = native::Dvar_SetFromStringByName_t(
|
||||
|
@ -31,10 +31,6 @@ namespace game
|
||||
int min, int max, unsigned __int16 flags, const char* description);
|
||||
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);
|
||||
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);
|
||||
extern PM_WeaponUseAmmo_t PM_WeaponUseAmmo;
|
||||
|
||||
typedef void (*CM_TransformedCapsuleTrace_t)(game::native::trace_t* results, const float* start, const float* end,
|
||||
const game::native::Bounds* bounds, const game::native::Bounds* capsule, int contents,
|
||||
typedef void (*CM_TransformedCapsuleTrace_t)(trace_t* results, const float* start, const float* end,
|
||||
const Bounds* bounds, const Bounds* capsule, int contents,
|
||||
const float* origin, const float* angles);
|
||||
extern CM_TransformedCapsuleTrace_t CM_TransformedCapsuleTrace;
|
||||
|
||||
@ -197,6 +193,8 @@ namespace game
|
||||
void* MT_Alloc(int numBytes, int type);
|
||||
|
||||
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);
|
||||
void Scr_ClearOutParams();
|
||||
|
@ -547,13 +547,14 @@ namespace game
|
||||
|
||||
enum dvar_flags : std::uint16_t
|
||||
{
|
||||
DVAR_ARCHIVE = 0x1,
|
||||
DVAR_CHEAT = 0x4,
|
||||
DVAR_CODINFO = 0x8,
|
||||
DVAR_SCRIPTINFO = 0x10,
|
||||
DVAR_SERVERINFO = 0x400,
|
||||
DVAR_WRITEPROTECTED = 0x800,
|
||||
DVAR_READONLY = 0x2000,
|
||||
DVAR_ARCHIVE = 1 << 0,
|
||||
DVAR_CHEAT = 1 << 2,
|
||||
DVAR_CODINFO = 1 << 3,
|
||||
DVAR_SCRIPTINFO = 1 << 4,
|
||||
DVAR_SERVERINFO = 1 << 10,
|
||||
DVAR_WRITEPROTECTED = 1 << 11,
|
||||
DVAR_READONLY = 1 << 13,
|
||||
DVAR_AUTOEXEC = 1 << 15,
|
||||
}; // Incomplete
|
||||
|
||||
enum dvar_type : std::int8_t
|
||||
@ -581,6 +582,8 @@ namespace game
|
||||
char color[4];
|
||||
};
|
||||
|
||||
static_assert(sizeof(DvarValue) == 0x10);
|
||||
|
||||
struct enum_limit
|
||||
{
|
||||
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 "hook.hpp"
|
||||
|
||||
#include <MinHook.h>
|
||||
|
||||
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()
|
||||
{
|
||||
if (this->signatures_.empty()) return;
|
||||
@ -42,6 +64,64 @@ namespace utils
|
||||
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()
|
||||
{
|
||||
if (this->initialized_)
|
||||
|
@ -40,6 +40,64 @@ namespace utils
|
||||
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),
|
||||
use_jump_(false), protection_(0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user