Fix crithack issues with Minigun and flamethrower

This commit is contained in:
BenCat07 2022-07-14 00:46:54 +02:00
parent 7f39894446
commit 4e09888306
6 changed files with 85 additions and 4 deletions

View File

@ -22,8 +22,6 @@ set(CMAKE_BUILD_TYPE_VALUES "Debug;Release" CACHE INTERNAL "List of supported bu
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_BUILD_TYPE_VALUES}) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_BUILD_TYPE_VALUES})
project(cathook VERSION 0.0.1) project(cathook VERSION 0.0.1)
set(CMAKE_CXX_STANDARD 23)
add_library(cathook SHARED "") add_library(cathook SHARED "")
set(GameSpecific 1 CACHE BOOL "Build for specific target game (As opposed to universal, but slower, lib)") set(GameSpecific 1 CACHE BOOL "Build for specific target game (As opposed to universal, but slower, lib)")
@ -161,13 +159,18 @@ endif()
configure_file(include/config.h.in ${CMAKE_SOURCE_DIR}/include/config.h @ONLY) configure_file(include/config.h.in ${CMAKE_SOURCE_DIR}/include/config.h @ONLY)
configure_file(include/version.h.in ${CMAKE_SOURCE_DIR}/include/version.h @ONLY) configure_file(include/version.h.in ${CMAKE_SOURCE_DIR}/include/version.h @ONLY)
set(CMAKE_CXX_FLAGS "-m32 -march=native -fexceptions -fno-gnu-unique -DNDEBUG") set(CMAKE_CXX_FLAGS "-m32 -march=native -fexceptions -DNDEBUG")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gnu-unique")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "-march=native -rdynamic -ggdb -Og") set(CMAKE_CXX_FLAGS_DEBUG "-march=native -rdynamic -ggdb -Og")
if (Internal_Symbolized) if (Internal_Symbolized)
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -ggdb -fvisibility=hidden -fvisibility-inlines-hidden") set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -ggdb -fvisibility=hidden -fvisibility-inlines-hidden")
else() else()
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -s -fvisibility=hidden -fvisibility-inlines-hidden") set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -s -fvisibility=hidden -fvisibility-inlines-hidden")
endif() endif()
set(CMAKE_CXX_FLAGS "-std=gnu++2b ${CMAKE_CXX_FLAGS}")
target_compile_definitions(cathook PRIVATE target_compile_definitions(cathook PRIVATE
_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX11_ABI=0

View File

@ -232,4 +232,8 @@ struct offsets
{ {
return PlatformOffset(27, undefined, undefined); return PlatformOffset(27, undefined, undefined);
} }
static constexpr uint32_t CalcIsAttackCriticalHelper_brokenweps()
{
return PlatformOffset(464, undefined, 464);
}
}; };

View File

@ -8,6 +8,7 @@ extern settings::Boolean enabled;
extern settings::Boolean melee; extern settings::Boolean melee;
extern std::map<int, std::vector<int>> crit_cmds; extern std::map<int, std::vector<int>> crit_cmds;
extern size_t current_index; extern size_t current_index;
extern bool calling_crithelper;
extern bool isEnabled(); extern bool isEnabled();
extern bool force_crit_this_tick; extern bool force_crit_this_tick;
void fixBucket(IClientEntity *weapon, CUserCmd *cmd); void fixBucket(IClientEntity *weapon, CUserCmd *cmd);

View File

@ -96,6 +96,8 @@ DECLARE_HOOKED_METHOD(EmitSound3, void, void *, IRecipientFilter &, int, int, in
DECLARE_HOOKED_METHOD(RunCommand, void, IPrediction *, IClientEntity *, CUserCmd *, IMoveHelper *); DECLARE_HOOKED_METHOD(RunCommand, void, IPrediction *, IClientEntity *, CUserCmd *, IMoveHelper *);
// g_IToolFramework // g_IToolFramework
DECLARE_HOOKED_METHOD(Think, void, IToolFrameworkInternal *, bool); DECLARE_HOOKED_METHOD(Think, void, IToolFrameworkInternal *, bool);
// CTFMinigun and CTFFlameThrower
DECLARE_HOOKED_METHOD(CalcIsAttackCriticalHelper_brokenweps, bool, IClientEntity *);
} // namespace hooked_methods } // namespace hooked_methods
// TODO // TODO

View File

@ -39,6 +39,7 @@ static bool is_out_of_sync = false;
// Optimization // Optimization
static int shots_to_fill_bucket = 0; static int shots_to_fill_bucket = 0;
bool calling_crithelper = false;
static float getBucketCap() static float getBucketCap()
{ {
static ConVar *tf_weapon_criticals_bucket_cap = g_ICvar->FindVar("tf_weapon_criticals_bucket_cap"); static ConVar *tf_weapon_criticals_bucket_cap = g_ICvar->FindVar("tf_weapon_criticals_bucket_cap");
@ -220,7 +221,9 @@ static int nextCritTick(int loops = 4096)
*g_PredictionRandomSeed = MD5_PseudoRandom(cmd_number) & 0x7FFFFFFF; *g_PredictionRandomSeed = MD5_PseudoRandom(cmd_number) & 0x7FFFFFFF;
// Save weapon state to not break anything // Save weapon state to not break anything
weapon_info info(wep); weapon_info info(wep);
bool is_crit = re::C_TFWeaponBase::CalcIsAttackCritical(wep); calling_crithelper = true;
bool is_crit = re::C_TFWeaponBase::CalcIsAttackCritical(wep);
calling_crithelper = false;
// Restore state // Restore state
info.restore_data(wep); info.restore_data(wep);
// Is a crit // Is a crit

View File

@ -1,5 +1,6 @@
#include "HookedMethods.hpp" #include "HookedMethods.hpp"
#include "WeaponData.hpp"
namespace hooked_methods namespace hooked_methods
{ {
@ -17,4 +18,71 @@ DEFINE_HOOKED_METHOD(RunCommand, void, IPrediction *prediction, IClientEntity *e
else else
return original::RunCommand(prediction, entity, usercmd, move); return original::RunCommand(prediction, entity, usercmd, move);
} }
static std::map<int, int> previous_ammo;
// Also fix heavy M2 causing bucket to fill faster, same for pyro
DEFINE_HOOKED_METHOD(CalcIsAttackCriticalHelper_brokenweps, bool, IClientEntity *ent)
{
if (CE_GOOD(LOCAL_E) && CE_GOOD(LOCAL_W) && ent && re::C_TFWeaponBase::GetOwnerViaInterface(ent) == LOCAL_E->InternalEntity() && !criticals::calling_crithelper)
{
auto current_ammo = CE_INT(LOCAL_E, netvar.m_iAmmo + 4);
if (previous_ammo[ent->entindex()] == current_ammo)
{
weapon_info info(ent);
auto ret = original::CalcIsAttackCriticalHelper_brokenweps(ent);
info.restore_data(ent);
return ret;
}
previous_ammo[ent->entindex()] = current_ammo;
}
if (LOCAL_W->m_iClassID() == CL_CLASS(CTFMinigun))
{
int weapon_mode = NET_INT(ent, 0xb08);
NET_INT(ent, 0xb08) = 0;
auto ret = original::CalcIsAttackCriticalHelper_brokenweps(ent);
NET_INT(ent, 0xb08) = weapon_mode;
return ret;
}
else
return original::CalcIsAttackCriticalHelper_brokenweps(ent);
}
static hooks::VMTHook minigun_hook{};
static Timer minigun_check_timer{};
static InitRoutine minigun_check(
[]()
{
EC::Register(
EC::CreateMove,
[]()
{
if (CE_BAD(LOCAL_E) || HasCondition<TFCond_HalloweenGhostMode>(LOCAL_E) || !LOCAL_E->m_bAlivePlayer() || !minigun_check_timer.test_and_set(1000))
return;
// Grab the handle and store it into the var
int *hWeapons = &CE_INT(LOCAL_E, netvar.hMyWeapons);
if (!hWeapons)
return;
// Go through the handle array and search for the item
for (int i = 0; hWeapons[i]; i++)
{
if (IDX_BAD(HandleToIDX(hWeapons[i])))
continue;
// Get the weapon
CachedEntity *weapon = ENTITY(HandleToIDX(hWeapons[i]));
// if weapon is what we are looking for, hook and move on
if (CE_VALID(weapon) && (weapon->m_iClassID() == CL_CLASS(CTFMinigun) || weapon->m_iClassID() == CL_CLASS(CTFFlameThrower)) && !minigun_hook.IsHooked(weapon->InternalEntity()))
{
logging::Info("Found and hooked Minigun/Flamethrower!");
minigun_hook.Set(weapon->InternalEntity());
minigun_hook.HookMethod(HOOK_ARGS(CalcIsAttackCriticalHelper_brokenweps));
minigun_hook.Apply();
break;
}
}
},
"cm_runcommand");
});
} // namespace hooked_methods } // namespace hooked_methods