add cg_thirdperson

This commit is contained in:
quaK 2024-07-10 03:17:09 +03:00
parent 72e89f0014
commit 02bc694695
5 changed files with 209 additions and 11 deletions

View File

@ -0,0 +1,108 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "scheduler.hpp"
#include <utils/hook.hpp>
namespace thirdperson
{
namespace
{
void* cg_offset_third_person_view_stub()
{
return utils::hook::assemble([](utils::hook::assembler& a)
{
a.push(rax);
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&dvars::cg_thirdPersonAngle)));
a.movss(xmm11, dword_ptr(rax, 0x10));
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&dvars::cg_thirdPersonRange)));
a.movss(xmm10, dword_ptr(rax, 0x10));
a.pop(rax);
// original code
a.mulss(xmm7, xmm0);
a.mulss(xmm6, xmm0);
a.addss(xmm7, qword_ptr(rdi));
a.jmp(0x140274596);
});
}
void* cg_offset_chase_cam_view_stub()
{
return utils::hook::assemble([](utils::hook::assembler& a)
{
a.push(rax);
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&dvars::cg_thirdPersonAngle)));
a.movss(xmm8, dword_ptr(rax, 0x10));
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&dvars::cg_thirdPersonRange)));
a.movss(xmm7, dword_ptr(rax, 0x10));
a.pop(rax);
// original code
a.mulss(xmm2, xmm2);
a.mulss(xmm3, xmm3);
a.addss(xmm2, xmm3);
a.jmp(0x140272069);
});
}
utils::hook::detour cg_should_render_third_person_hook;
int cg_should_render_third_person_stub(int localClientNum, game::cg_s* cgameGlob)
{
auto result = cg_should_render_third_person_hook.invoke<int>(localClientNum, cgameGlob);
if (!result && cgameGlob->predictedPlayerState.pm_type != 3)
{
result = static_cast<int>(dvars::cg_thirdPerson->current.enabled);
if (result)
{
cgameGlob->m_deathCameraFailsafeLock = false; // disable this, acts up for some reason
}
}
return result;
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
if (game::environment::is_dedi())
{
return;
}
scheduler::once([]()
{
dvars::cg_thirdPerson = game::Dvar_RegisterBool("cg_thirdPerson", false, game::DVAR_FLAG_CHEAT, "Use third person view");
dvars::cg_thirdPersonAngle = game::Dvar_RegisterFloat("cg_thirdPersonAngle", 356.0f, -180.0f, 360.0f, game::DVAR_FLAG_CHEAT,
"The angle of the camera from the player in third person view");
dvars::cg_thirdPersonRange = game::Dvar_RegisterFloat("cg_thirdPersonRange", 120.0f, 0.0f, 1024, game::DVAR_FLAG_CHEAT,
"The range of the camera from the player in third person view");
}, scheduler::main);
utils::hook::jump(0x14027205D, cg_offset_chase_cam_view_stub(), true);
utils::hook::jump(0x14027458A, cg_offset_third_person_view_stub(), true);
cg_should_render_third_person_hook.create(0x140275B50, cg_should_render_third_person_stub);
}
};
}
REGISTER_COMPONENT(thirdperson::component)

View File

@ -164,9 +164,9 @@ namespace weapon
void PM_Weapon_CheckForInspect(game::pmove_t* pm, game::pml_t* pml)
{
if ((pm->ps->weapFlags[1] & WEAP_FLAG2_INSPECT) != 0)
if ((pm->ps->weapFlags.m_flags[1] & WEAP_FLAG2_INSPECT) != 0)
{
pm->ps->weapFlags[1] = ~pm->ps->weapFlags[1] & WEAP_FLAG2_INSPECT;
pm->ps->weapFlags.m_flags[1] = ~pm->ps->weapFlags.m_flags[1] & WEAP_FLAG2_INSPECT;
}
else
{
@ -290,7 +290,7 @@ namespace weapon
return scripting::script_value{};
}
ent->client->ps.weapFlags[1] |= WEAP_FLAG2_INSPECT; // lets hope the game doesn't use this flag already...
ent->client->ps.weapFlags.m_flags[1] |= WEAP_FLAG2_INSPECT; // lets hope the game doesn't use this flag already...
return scripting::script_value{};
});

View File

@ -28,6 +28,10 @@ namespace dvars
game::dvar_t* cg_gun_y = nullptr;
game::dvar_t* cg_gun_z = nullptr;
game::dvar_t* cg_thirdPerson = nullptr;
game::dvar_t* cg_thirdPersonRange = nullptr;
game::dvar_t* cg_thirdPersonAngle = nullptr;
game::dvar_t* cg_unlockall_items = nullptr;
game::dvar_t* cg_unlockall_loot = nullptr;

View File

@ -25,6 +25,10 @@ namespace dvars
extern game::dvar_t* cg_gun_y;
extern game::dvar_t* cg_gun_z;
extern game::dvar_t* cg_thirdPerson;
extern game::dvar_t* cg_thirdPersonRange;
extern game::dvar_t* cg_thirdPersonAngle;
extern game::dvar_t* cg_unlockall_items;
extern game::dvar_t* cg_unlockall_loot;

View File

@ -687,17 +687,67 @@ namespace game
assert_offsetof(PlayerActiveWeaponState, weaponDelay, 8);
assert_offsetof(PlayerActiveWeaponState, weaponState, 16);
typedef int GameModeFlagValues[2];
enum pmtype_t : std::int32_t
{
PM_NORMAL = 0x0,
PM_NORMAL_LINKED = 0x1,
PM_NOCLIP = 0x2,
PM_UFO = 0x3,
PM_MPVIEWER = 0x4,
PM_SPECTATOR = 0x5,
PM_INTERMISSION = 0x6,
PM_DEAD = 0x7,
PM_DEAD_LINKED = 0x8,
};
enum PMoveFlagsCommon : std::uint64_t;
enum PMoveFlagsSP : std::uint64_t;
enum PMoveFlagsMP : std::uint64_t;
enum POtherFlagsCommon : std::uint64_t;
enum POtherFlagsSP : std::uint64_t;
enum POtherFlagsMP : std::uint64_t;
enum PLinkFlagsCommon : std::uint32_t;
enum PLinkFlagsSP : std::uint32_t;
enum PLinkFlagsMP : std::uint32_t;
enum EntityStateFlagsCommon : std::uint32_t;
enum EntityStateFlagsSP : std::uint32_t;
enum EntityStateFlagsMP : std::uint32_t;
enum PWeaponFlagsCommon : std::uint64_t;
enum PWeaponFlagsSP : std::uint64_t;
enum PWeaponFlagsMP : std::uint64_t;
template<typename CommonE, typename spE, typename mpE, int bitSize>
struct GameModeFlagContainer
{
static_assert(bitSize % sizeof(unsigned int) * CHAR_BIT == 0, "bitSize must be divisible by sizeof(unsigned int) * CHAR_BIT");
unsigned int m_flags[bitSize >> (sizeof(unsigned int) + 1)];
};
struct playerState_s
{
int commandTime;
int pm_type;
char __pad0[1612];
int pm_time;
GameModeFlagContainer<PMoveFlagsCommon, PMoveFlagsSP, PMoveFlagsMP, 64> pm_flags;
GameModeFlagContainer<POtherFlagsCommon, POtherFlagsSP, POtherFlagsMP, 64> otherFlags;
GameModeFlagContainer<PLinkFlagsCommon, PLinkFlagsSP, PLinkFlagsMP, 32> linkFlags;
char __pad0[312];
GameModeFlagContainer<EntityStateFlagsCommon, EntityStateFlagsSP, EntityStateFlagsMP, 32> eFlags;
char __pad1[1272];
PlayerActiveWeaponState weapState[2];
char __pad1[464];
GameModeFlagValues weapFlags;
};
char __pad2[464];
GameModeFlagContainer<PWeaponFlagsCommon, PWeaponFlagsSP, PWeaponFlagsMP, 64> weapFlags;
float fWeaponPosFrac;
char __pad3[0x4000];
}; // unk size
assert_offsetof(playerState_s, pm_flags, 12);
assert_offsetof(playerState_s, otherFlags, 20);
assert_offsetof(playerState_s, linkFlags, 28);
assert_offsetof(playerState_s, eFlags, 344);
assert_offsetof(playerState_s, weapState, 1620);
assert_offsetof(playerState_s, weapFlags, 2188);
@ -723,7 +773,7 @@ namespace game
struct gclient_s
{
playerState_s ps;
char __pad0[17180];
char __pad0[19376 - sizeof(playerState_s)];
char name[32]; // 19376
char __pad1[1516];
int flags; // 20924
@ -787,12 +837,44 @@ namespace game
}
using namespace entity;
enum CubemapShot
{
CUBEMAPSHOT_NONE = 0x0,
CUBEMAPSHOT_RIGHT = 0x1,
CUBEMAPSHOT_LEFT = 0x2,
CUBEMAPSHOT_BACK = 0x3,
CUBEMAPSHOT_FRONT = 0x4,
CUBEMAPSHOT_UP = 0x5,
CUBEMAPSHOT_DOWN = 0x6,
CUBEMAPSHOT_COUNT = 0x7,
};
struct cg_s
{
char __pad0[324368];
playerState_s predictedPlayerState;
char __pad0[19160 - sizeof(playerState_s)];
CubemapShot cubemapShot;
int cubemapSize;
char __pad1[305200];
float viewModelAxis[4][3];
};
char __pad2[168476];
int renderScreen;
int latestSnapshotNum;
int latestSnapshotTime;
int mapRestart;
int spectatingThirdPerson;
int renderingThirdPerson;
char __pad3[60792];
bool m_deathCameraFailsafeLock;
char __pad4[3];
char __pad5[486328];
}; static_assert(sizeof(cg_s) == 1040040);
static_assert(offsetof(cg_s, cubemapShot) == 19160);
static_assert(offsetof(cg_s, cubemapSize) == 19164);
static_assert(offsetof(cg_s, viewModelAxis) == 324368);
static_assert(offsetof(cg_s, renderScreen) == 492892);
static_assert(offsetof(cg_s, renderingThirdPerson) == 492912);
static_assert(offsetof(cg_s, m_deathCameraFailsafeLock) == 553708);
namespace scripting
{