feat: free movement

This commit is contained in:
6arelyFuture 2025-02-05 16:15:09 +01:00
parent 87ce6fcf61
commit 9c796cd38b
Signed by: Future
GPG Key ID: F2000F181A4F7C85
7 changed files with 233 additions and 21 deletions

View File

@ -0,0 +1,76 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "command.hpp"
#include <utils/hook.hpp>
namespace free_move {
namespace {
void cg_noclip_f() {
if (!game::cgArray[game::LOCAL_CLIENT_0].nextSnap) {
return;
}
if (!(*dvars::sv_cheats)->current.enabled) {
game::Com_Printf(game::CON_CHANNEL_SYSTEM, "%s is cheat protected.\n",
"cg_noclip");
return;
}
if ((*dvars::cl_freemove)->current.integer == 1) {
if ((*dvars::cg_paused)->current.integer == 2) {
game::Dvar_SetInt(*dvars::cg_paused, 1);
}
}
game::Dvar_SetInt(*dvars::cl_freemove,
(*dvars::cl_freemove)->current.integer == 1 ? 0 : 1);
game::Com_Printf(
game::CON_CHANNEL_DONT_FILTER, "%s\n",
game::SEH_LocalizeTextMessage((*dvars::cl_freemove)->current.integer == 1
? "GAME_NOCLIPON"
: "GAME_NOCLIPOFF",
"noclip print", game::LOCMSG_SAFE));
}
void cg_ufo_f() {
if (!game::cgArray[game::LOCAL_CLIENT_0].nextSnap) {
return;
}
if (!(*dvars::sv_cheats)->current.enabled) {
game::Com_Printf(game::CON_CHANNEL_SYSTEM, "%s is cheat protected.\n",
"cg_ufo");
return;
}
if ((*dvars::cl_freemove)->current.integer == 2) {
if ((*dvars::cg_paused)->current.integer == 2) {
game::Dvar_SetInt(*dvars::cg_paused, 1);
}
}
game::Dvar_SetInt(*dvars::cl_freemove,
(*dvars::cl_freemove)->current.integer == 2 ? 0 : 2);
game::Com_Printf(
game::CON_CHANNEL_DONT_FILTER, "%s\n",
game::SEH_LocalizeTextMessage((*dvars::cl_freemove)->current.integer == 2
? "GAME_UFOON"
: "GAME_UFOOFF",
"ufo print", game::LOCMSG_SAFE));
}
} // namespace
class component final : public component_interface {
public:
void post_load() override {
command::add("cg_noclip", cg_noclip_f);
command::add("cg_ufo", cg_ufo_f);
}
};
} // namespace free_move
REGISTER_COMPONENT(free_move::component)

View File

@ -72,31 +72,34 @@ void __declspec(naked) string_table_get_column_value_for_row() {
static const char* fmt =
"Looking up row %i, column %i of table \'%s\' results in an empty string "
"(first column is %s, second column is %s for that row)\n";
static const DWORD Com_PrintError = 0x4C6980;
static const DWORD Com_PrintError_t = 0x4C6980;
using namespace game;
// EAX is safe to reuse because it's nuked by the game's code after this stub exits
__asm {
// game's code
mov eax, dword ptr [ecx + eax * 0x8]
push edx
push eax
mov eax, dword ptr [ecx + eax * 0x8];
push edx;
push eax;
mov eax, [esp + 0xC] // get table pointer
mov eax, [eax] // get table->name
push eax
mov eax, [esp + 0xC]; // get table pointer
mov eax, [eax]; // get table->name
push eax;
// game's code
push edi // column
push ebx // row
push edi; // column
push ebx; // row
push fmt
// game's format string
push fmt;
push 0xD // channel
call Com_PrintError
add esp, 0x1C
push CON_CHANNEL_UI; // channel
call Com_PrintError_t;
add esp, 0x1C;
push 0x4BC84E
ret
push 0x4BC84E;
ret;
}
}
// clang-format on

View File

@ -25,11 +25,21 @@ const game::dvar_t* bug_name = nullptr;
const game::dvar_t* g_log = nullptr;
// Game dvars
const game::dvar_t** cg_paused =
reinterpret_cast<const game::dvar_t**>(0x86D7C0);
const game::dvar_t** cl_freemove =
reinterpret_cast<const game::dvar_t**>(0x89776C);
const game::dvar_t** cl_freemoveScale =
reinterpret_cast<const game::dvar_t**>(0x897750);
const game::dvar_t** g_specialops =
reinterpret_cast<const game::dvar_t**>(0x1B2E1E8);
const game::dvar_t** sv_mapname =
reinterpret_cast<const game::dvar_t**>(0x1B2E1E4);
const game::dvar_t** sv_cheats =
reinterpret_cast<const game::dvar_t**>(0x1B2E1EC);
const game::dvar_t** version =
reinterpret_cast<const game::dvar_t**>(0x145D690);

View File

@ -25,9 +25,15 @@ extern const game::dvar_t* bug_name;
extern const game::dvar_t* g_log;
// Game dvars
extern const game::dvar_t** cg_paused;
extern const game::dvar_t** cl_freemove;
extern const game::dvar_t** cl_freemoveScale;
extern const game::dvar_t** g_specialops;
extern const game::dvar_t** sv_mapname;
extern const game::dvar_t** sv_cheats;
extern const game::dvar_t** version;

View File

@ -3,7 +3,7 @@
namespace game {
int FS_FOpenFileReadForThread(const char* filename, int* file,
FsThread thread) {
const static DWORD FS_FOpenFileReadForThread_t = 0x630380;
static const DWORD FS_FOpenFileReadForThread_t = 0x630380;
int result{};
__asm {
@ -23,7 +23,7 @@ int FS_FOpenFileReadForThread(const char* filename, int* file,
}
void IN_KeyDown(kbutton_t* b) {
const static DWORD IN_KeyDown_t = 0x57A350;
static const DWORD IN_KeyDown_t = 0x57A350;
__asm {
pushad;
@ -36,7 +36,7 @@ void IN_KeyDown(kbutton_t* b) {
}
void IN_KeyUp(kbutton_t* b) {
const static DWORD IN_KeyUp_t = 0x57A3F0;
static const DWORD IN_KeyUp_t = 0x57A3F0;
__asm {
pushad;
@ -94,7 +94,7 @@ HANDLE Sys_OpenFileReliable(const char* filename) {
}
int PC_Int_Parse(int handle, int* i) {
const static DWORD PC_Int_Parse_t = 0x62DF10;
static const DWORD PC_Int_Parse_t = 0x62DF10;
int result{};
__asm {
@ -112,7 +112,7 @@ int PC_Int_Parse(int handle, int* i) {
}
int PC_Float_Parse(int handle, float* f) {
const static DWORD PC_Float_Parse_t = 0x62DE40;
static const DWORD PC_Float_Parse_t = 0x62DE40;
int result{};
__asm {
@ -130,7 +130,7 @@ int PC_Float_Parse(int handle, float* f) {
}
void Menu_FreeItemMemory(itemDef_s* item) {
const static DWORD Menu_FreeItemMemory_t = 0x62B7E0;
static const DWORD Menu_FreeItemMemory_t = 0x62B7E0;
__asm {
pushad;

View File

@ -369,6 +369,11 @@ enum {
VAR_INTEGER = 0x6,
};
enum msgLocErrType_t {
LOCMSG_SAFE = 0x0,
LOCMSG_NOERR = 0x1,
};
enum {
CON_CHANNEL_DONT_FILTER = 0x0,
CON_CHANNEL_ERROR = 0x1,
@ -1745,6 +1750,109 @@ struct localization_t {
struct Sys_File {
HANDLE handle;
};
enum ShockViewTypes {
SHELLSHOCK_VIEWTYPE_BLURRED = 0x0,
SHELLSHOCK_VIEWTYPE_FLASHED = 0x1,
SHELLSHOCK_VIEWTYPE_NONE = 0x2,
};
struct shellshock_parms_t {
struct {
int blurredFadeTime;
int blurredEffectTime;
int flashWhiteFadeTime;
int flashShotFadeTime;
ShockViewTypes type;
} screenBlend;
struct {
int fadeTime;
float kickRate;
float kickRadius;
} view;
struct {
bool affect;
char loop[64];
char loopSilent[64];
char end[64];
char endAbort[64];
int fadeInTime;
int fadeOutTime;
float drylevel;
float wetlevel;
char roomtype[16];
float channelvolume[64];
int modEndDelay;
int loopFadeTime;
int loopEndDelay;
} sound;
struct {
bool affect;
int fadeTime;
float mouseSensitivity;
float maxPitchSpeed;
float maxYawSpeed;
} lookControl;
struct {
bool affect;
} movement;
};
struct cgs_t {
int viewX;
int viewY;
int viewWidth;
int viewHeight;
float viewAspect;
bool started;
shellshock_parms_t holdBreathParams;
};
static_assert(sizeof(cgs_t) == 0x280);
struct cpose_t {
unsigned char __pad0[0x64];
};
static_assert(sizeof(cpose_t) == 0x64);
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 snapshot_s {
int snapFlags;
int serverTime;
int numEntities;
unsigned __int16 entityNums[2048];
int numFxEntities;
unsigned __int16 fxEntityNums[768];
};
struct cg_s {
int clientNum;
int localClientNum;
CubemapShot cubemapShot;
int cubemapSize;
int serverCommandSequence;
int serverLatestCommandSequence;
int loaded;
snapshot_s* snap;
snapshot_s* nextSnap;
playerState_s* ps;
playerState_s* nextPs;
}; // Incomplete
static_assert(offsetof(cg_s, snap) == 0x1C);
static_assert(offsetof(cg_s, nextSnap) == 0x20);
static_assert(offsetof(cg_s, nextPs) == 0x28);
} // namespace game
#pragma warning(pop)

View File

@ -24,6 +24,9 @@ WEAK symbol<const char*(const char* fmt, ...)> va{0x4869F0};
// Con
WEAK symbol<bool(const char* cmd)> Con_IsDvarCommand{0x4B6610};
// SV
WEAK symbol<void(int clientNum, usercmd_s* cmd)> SV_ClientThink{0x4B43D0};
// ScrPlace
WEAK symbol<ScreenPlacement*(int localClientNum)> ScrPlace_GetActivePlacement{
0x4D2A60};
@ -289,11 +292,17 @@ WEAK symbol<void(const char* text, int maxChars, Font_s* font, float x, float y,
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{
0x508960};
WEAK symbol<const char*(const char* pszInputBuffer, const char* pszMessageType,
msgLocErrType_t errType)>
SEH_LocalizeTextMessage{0x4CD8D0};
// Variables
WEAK symbol<CmdArgs> cmd_args{0x144FED0};
WEAK symbol<CmdArgs> sv_cmd_args{0x145ABA0};
WEAK symbol<gentity_s> g_entities{0xEAAC38};
WEAK symbol<gclient_s> g_clients{0x10911E8};
WEAK symbol<cgs_t> cgsArray{0x762008};
WEAK symbol<cg_s> cgArray{0x7622A0};
WEAK symbol<scrVmPub_t> scrVmPub{0x190DDF0};
WEAK symbol<scrVarPub_t> scrVarPub{0x18E7508};