commit
2ea94b1ba9
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -51,5 +51,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: ${{matrix.configuration}} binaries
|
name: ${{matrix.configuration}} binaries
|
||||||
path: |
|
path: |
|
||||||
build/bin/x32/${{matrix.configuration}}/open-iw5.exe
|
build/bin/Win32/${{matrix.configuration}}/open-iw5.exe
|
||||||
build/bin/x32/${{matrix.configuration}}/open-iw5.pdb
|
build/bin/Win32/${{matrix.configuration}}/open-iw5.pdb
|
||||||
|
@ -13,6 +13,10 @@ namespace game
|
|||||||
|
|
||||||
DB_LoadXAssets_t DB_LoadXAssets;
|
DB_LoadXAssets_t DB_LoadXAssets;
|
||||||
|
|
||||||
|
Dvar_RegisterBool_t Dvar_RegisterBool;
|
||||||
|
|
||||||
|
Dvar_SetIntByName_t Dvar_SetIntByName;
|
||||||
|
|
||||||
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||||
|
|
||||||
G_RunFrame_t G_RunFrame;
|
G_RunFrame_t G_RunFrame;
|
||||||
@ -53,6 +57,10 @@ namespace game
|
|||||||
|
|
||||||
XUIDToString_t XUIDToString;
|
XUIDToString_t XUIDToString;
|
||||||
|
|
||||||
|
SEH_LocalizeTextMessage_t SEH_LocalizeTextMessage;
|
||||||
|
|
||||||
|
PM_WeaponUseAmmo_t PM_WeaponUseAmmo;
|
||||||
|
|
||||||
decltype(longjmp)* _longjmp;
|
decltype(longjmp)* _longjmp;
|
||||||
|
|
||||||
CmdArgs* sv_cmd_args;
|
CmdArgs* sv_cmd_args;
|
||||||
@ -88,6 +96,11 @@ namespace game
|
|||||||
client_t* svs_clients;
|
client_t* svs_clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace sp
|
||||||
|
{
|
||||||
|
sp::gentity_s* g_entities;
|
||||||
|
}
|
||||||
|
|
||||||
void AddRefToValue(VariableValue* value)
|
void AddRefToValue(VariableValue* value)
|
||||||
{
|
{
|
||||||
if (value->type == SCRIPT_OBJECT)
|
if (value->type == SCRIPT_OBJECT)
|
||||||
@ -539,6 +552,19 @@ namespace game
|
|||||||
(0x50D840)(player, origin, angles);
|
(0x50D840)(player, origin, angles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SP takes one extra argument, all possible values are undocumented
|
||||||
|
void CG_GameMessage(LocalClientNum_t localClientNum, const char* msg, int flags)
|
||||||
|
{
|
||||||
|
if (is_mp())
|
||||||
|
{
|
||||||
|
reinterpret_cast<void(*)(LocalClientNum_t, const char*)>(0x456DC0)(localClientNum, msg);
|
||||||
|
}
|
||||||
|
else if (is_sp())
|
||||||
|
{
|
||||||
|
reinterpret_cast<void(*)(LocalClientNum_t, const char*, int)>(0x4228A0)(localClientNum, msg, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launcher::mode mode = launcher::mode::none;
|
launcher::mode mode = launcher::mode::none;
|
||||||
@ -580,6 +606,10 @@ namespace game
|
|||||||
|
|
||||||
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
|
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
|
||||||
|
|
||||||
|
native::Dvar_RegisterBool = native::Dvar_RegisterBool_t(SELECT_VALUE(0x4914D0, 0x5BE9F0, 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(
|
||||||
SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
|
SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
|
||||||
|
|
||||||
@ -595,7 +625,7 @@ namespace game
|
|||||||
|
|
||||||
native::Scr_AddEntityNum = native::Scr_AddEntityNum_t(SELECT_VALUE(0x0, 0x56ABC0, 0x4EA2F0));
|
native::Scr_AddEntityNum = native::Scr_AddEntityNum_t(SELECT_VALUE(0x0, 0x56ABC0, 0x4EA2F0));
|
||||||
|
|
||||||
native::Scr_Notify = native::Scr_Notify_t(SELECT_VALUE(0x0, 0x52B190, 0x0));
|
native::Scr_Notify = native::Scr_Notify_t(SELECT_VALUE(0x4895B0, 0x52B190, 0x0));
|
||||||
|
|
||||||
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
||||||
|
|
||||||
@ -617,15 +647,20 @@ namespace game
|
|||||||
|
|
||||||
native::SV_Cmd_EndTokenizedString = native::SV_Cmd_EndTokenizedString_t(SELECT_VALUE(0x0, 0x545D70, 0x0));
|
native::SV_Cmd_EndTokenizedString = native::SV_Cmd_EndTokenizedString_t(SELECT_VALUE(0x0, 0x545D70, 0x0));
|
||||||
|
|
||||||
native::SV_GameSendServerCommand = native::SV_GameSendServerCommand_t(SELECT_VALUE(0x0, 0x573220, 0x0));
|
native::SV_GameSendServerCommand = native::SV_GameSendServerCommand_t(SELECT_VALUE(0x402130, 0x573220, 0x0));
|
||||||
|
|
||||||
native::SV_SendServerCommand = native::SV_SendServerCommand_t(SELECT_VALUE(0x0, 0x575DE0, 0x4FD5A0));
|
native::SV_SendServerCommand = native::SV_SendServerCommand_t(SELECT_VALUE(0x4F6990, 0x575DE0, 0x4FD5A0));
|
||||||
|
|
||||||
native::XUIDToString = native::XUIDToString_t(SELECT_VALUE(0x4FAA30, 0x55CC20, 0x0));
|
native::XUIDToString = native::XUIDToString_t(SELECT_VALUE(0x4FAA30, 0x55CC20, 0x0));
|
||||||
|
|
||||||
|
native::SEH_LocalizeTextMessage = native::SEH_LocalizeTextMessage_t(
|
||||||
|
SELECT_VALUE(0x41EA20, 0x57E240, 0x0));
|
||||||
|
|
||||||
|
native::PM_WeaponUseAmmo = native::PM_WeaponUseAmmo_t(SELECT_VALUE(0x463F80, 0x42E930, 0x0));
|
||||||
|
|
||||||
native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558));
|
native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558));
|
||||||
|
|
||||||
native::sv_cmd_args = reinterpret_cast<native::CmdArgs*>(SELECT_VALUE(0x0, 0x1CAA998, 0x1B5E7D8));
|
native::sv_cmd_args = reinterpret_cast<native::CmdArgs*>(SELECT_VALUE(0x1757218, 0x1CAA998, 0x1B5E7D8));
|
||||||
native::cmd_args = reinterpret_cast<native::CmdArgs*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
native::cmd_args = reinterpret_cast<native::CmdArgs*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
||||||
|
|
||||||
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
|
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
|
||||||
@ -653,5 +688,6 @@ namespace game
|
|||||||
native::dedi::svs_clients = reinterpret_cast<native::dedi::client_t*>(0x4A12E90);
|
native::dedi::svs_clients = reinterpret_cast<native::dedi::client_t*>(0x4A12E90);
|
||||||
|
|
||||||
native::g_entities = reinterpret_cast<native::gentity_s*>(SELECT_VALUE(0, 0x1A66E28, 0x191B900));
|
native::g_entities = reinterpret_cast<native::gentity_s*>(SELECT_VALUE(0, 0x1A66E28, 0x191B900));
|
||||||
|
native::sp::g_entities = reinterpret_cast<native::sp::gentity_s*>(0x1197AD8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,13 @@ namespace game
|
|||||||
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
||||||
extern DB_LoadXAssets_t DB_LoadXAssets;
|
extern DB_LoadXAssets_t DB_LoadXAssets;
|
||||||
|
|
||||||
|
typedef const dvar_t* (*Dvar_RegisterBool_t)(const char* dvarName, bool value,
|
||||||
|
unsigned __int16 flags, const char* description);
|
||||||
|
extern Dvar_RegisterBool_t Dvar_RegisterBool;
|
||||||
|
|
||||||
|
typedef void (*Dvar_SetIntByName_t)(const char* dvarName, int value);
|
||||||
|
extern Dvar_SetIntByName_t Dvar_SetIntByName;
|
||||||
|
|
||||||
typedef void (*Dvar_SetFromStringByName_t)(const char* dvarName, const char* string);
|
typedef void (*Dvar_SetFromStringByName_t)(const char* dvarName, const char* string);
|
||||||
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||||
|
|
||||||
@ -83,6 +90,12 @@ namespace game
|
|||||||
typedef void (*XUIDToString_t)(const unsigned __int64* xuid, char* str);
|
typedef void (*XUIDToString_t)(const unsigned __int64* xuid, char* str);
|
||||||
extern XUIDToString_t XUIDToString;
|
extern XUIDToString_t XUIDToString;
|
||||||
|
|
||||||
|
typedef char* (*SEH_LocalizeTextMessage_t)(const char* pszInputBuffer, const char* pszMessageType, msgLocErrType_t errType);
|
||||||
|
extern SEH_LocalizeTextMessage_t SEH_LocalizeTextMessage;
|
||||||
|
|
||||||
|
typedef void (*PM_WeaponUseAmmo_t)(playerState_s* ps, const Weapon weapon, bool isAlternate, int amount, PlayerHandIndex hand);
|
||||||
|
extern PM_WeaponUseAmmo_t PM_WeaponUseAmmo;
|
||||||
|
|
||||||
extern decltype(longjmp)* _longjmp;
|
extern decltype(longjmp)* _longjmp;
|
||||||
|
|
||||||
constexpr auto CMD_MAX_NESTING = 8;
|
constexpr auto CMD_MAX_NESTING = 8;
|
||||||
@ -119,6 +132,11 @@ namespace game
|
|||||||
extern client_t* svs_clients;
|
extern client_t* svs_clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace sp
|
||||||
|
{
|
||||||
|
extern sp::gentity_s* g_entities;
|
||||||
|
}
|
||||||
|
|
||||||
void AddRefToValue(VariableValue* value);
|
void AddRefToValue(VariableValue* value);
|
||||||
|
|
||||||
void Conbuf_AppendText(const char* message);
|
void Conbuf_AppendText(const char* message);
|
||||||
@ -156,6 +174,8 @@ namespace game
|
|||||||
void Cbuf_AddText(LocalClientNum_t localClientNum, const char* text);
|
void Cbuf_AddText(LocalClientNum_t localClientNum, const char* text);
|
||||||
|
|
||||||
void TeleportPlayer(gentity_s* player, float* origin, float* angles);
|
void TeleportPlayer(gentity_s* player, float* origin, float* angles);
|
||||||
|
|
||||||
|
void CG_GameMessage(LocalClientNum_t localClientNum, const char* msg, int flags = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_mp();
|
bool is_mp();
|
||||||
|
@ -391,6 +391,12 @@ namespace game
|
|||||||
LOCAL_CLIENT_INVALID = -1,
|
LOCAL_CLIENT_INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum msgLocErrType_t
|
||||||
|
{
|
||||||
|
LOCMSG_SAFE,
|
||||||
|
LOCMSG_NOERR,
|
||||||
|
};
|
||||||
|
|
||||||
struct cmd_function_t
|
struct cmd_function_t
|
||||||
{
|
{
|
||||||
cmd_function_t* next;
|
cmd_function_t* next;
|
||||||
@ -527,6 +533,31 @@ namespace game
|
|||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
}; // Incomplete
|
||||||
|
|
||||||
|
enum dvar_type : std::int8_t
|
||||||
|
{
|
||||||
|
DVAR_TYPE_BOOL = 0x0,
|
||||||
|
DVAR_TYPE_FLOAT = 0x1,
|
||||||
|
DVAR_TYPE_FLOAT_2 = 0x2,
|
||||||
|
DVAR_TYPE_FLOAT_3 = 0x3,
|
||||||
|
DVAR_TYPE_FLOAT_4 = 0x4,
|
||||||
|
DVAR_TYPE_INT = 0x5,
|
||||||
|
DVAR_TYPE_ENUM = 0x6,
|
||||||
|
DVAR_TYPE_STRING = 0x7,
|
||||||
|
DVAR_TYPE_COLOR = 0x8,
|
||||||
|
DVAR_TYPE_FLOAT_3_COLOR = 0x9,
|
||||||
|
};
|
||||||
|
|
||||||
union DvarValue
|
union DvarValue
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
@ -578,6 +609,12 @@ namespace game
|
|||||||
dvar_t* hashNext;
|
dvar_t* hashNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Bounds
|
||||||
|
{
|
||||||
|
float midPoint[3];
|
||||||
|
float halfSize[3];
|
||||||
|
};
|
||||||
|
|
||||||
struct usercmd_s
|
struct usercmd_s
|
||||||
{
|
{
|
||||||
int serverTime;
|
int serverTime;
|
||||||
@ -598,6 +635,33 @@ namespace game
|
|||||||
|
|
||||||
static_assert(sizeof(usercmd_s) == 0x2C);
|
static_assert(sizeof(usercmd_s) == 0x2C);
|
||||||
|
|
||||||
|
enum PlayerHandIndex
|
||||||
|
{
|
||||||
|
WEAPON_HAND_RIGHT = 0,
|
||||||
|
WEAPON_HAND_LEFT = 1,
|
||||||
|
NUM_WEAPON_HANDS = 2,
|
||||||
|
WEAPON_HAND_DEFAULT = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Weapon_s
|
||||||
|
{
|
||||||
|
unsigned int padding : 8;
|
||||||
|
unsigned int scopeVariation : 3;
|
||||||
|
unsigned int weaponOthers : 4;
|
||||||
|
unsigned int weaponUnderBarrels : 2;
|
||||||
|
unsigned int weaponScopes : 3;
|
||||||
|
unsigned int weaponIdx : 8;
|
||||||
|
unsigned int weaponVariation : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
union Weapon
|
||||||
|
{
|
||||||
|
Weapon_s _s_0;
|
||||||
|
unsigned int data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(Weapon) == 4);
|
||||||
|
|
||||||
struct playerState_s
|
struct playerState_s
|
||||||
{
|
{
|
||||||
unsigned char __pad0[0x4EC];
|
unsigned char __pad0[0x4EC];
|
||||||
@ -638,6 +702,26 @@ namespace game
|
|||||||
FL_MOVER_SLIDE = 0x8000000
|
FL_MOVER_SLIDE = 0x8000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum entityType
|
||||||
|
{
|
||||||
|
ET_GENERAL,
|
||||||
|
ET_PLAYER,
|
||||||
|
ET_ITEM,
|
||||||
|
ET_MISSILE,
|
||||||
|
ET_INVISIBLE,
|
||||||
|
ET_SCRIPTMOVER,
|
||||||
|
ET_SOUND_BLEND,
|
||||||
|
ET_PRIMARY_LIGHT,
|
||||||
|
ET_TURRET,
|
||||||
|
ET_VEHICLE,
|
||||||
|
ET_VEHICLE_COLLMAP,
|
||||||
|
ET_VEHICLE_CORPSE,
|
||||||
|
ET_VEHICLE_SPAWNER,
|
||||||
|
ET_ACTOR,
|
||||||
|
ET_ACTOR_SPAWNER,
|
||||||
|
ET_ACTOR_CORPSE,
|
||||||
|
};
|
||||||
|
|
||||||
struct entityState_s
|
struct entityState_s
|
||||||
{
|
{
|
||||||
int number;
|
int number;
|
||||||
@ -792,5 +876,61 @@ namespace game
|
|||||||
|
|
||||||
static_assert(sizeof(dedi::client_t) == 0x78690);
|
static_assert(sizeof(dedi::client_t) == 0x78690);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace sp
|
||||||
|
{
|
||||||
|
struct gclient_s
|
||||||
|
{
|
||||||
|
unsigned char __pad0[0xAE04];
|
||||||
|
int flags;
|
||||||
|
}; // Warning, incorrect size
|
||||||
|
|
||||||
|
struct entityState_s
|
||||||
|
{
|
||||||
|
int eType;
|
||||||
|
unsigned char __pad0[0x80];
|
||||||
|
int number;
|
||||||
|
unsigned char __pad1[0x28];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(entityState_s) == 0xB0);
|
||||||
|
|
||||||
|
struct entityShared_t
|
||||||
|
{
|
||||||
|
unsigned __int8 isLinked;
|
||||||
|
unsigned __int8 modelType;
|
||||||
|
unsigned __int8 svFlags;
|
||||||
|
unsigned __int8 eventType;
|
||||||
|
unsigned __int8 isInUse;
|
||||||
|
Bounds box;
|
||||||
|
int contents;
|
||||||
|
Bounds absBox;
|
||||||
|
float currentOrigin[3];
|
||||||
|
float currentAngles[3];
|
||||||
|
EntHandle ownerNum;
|
||||||
|
int eventTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(entityShared_t) == 0x5C);
|
||||||
|
|
||||||
|
struct gentity_s
|
||||||
|
{
|
||||||
|
entityState_s s;
|
||||||
|
entityShared_t r;
|
||||||
|
sp::gclient_s* client; // 0x10C
|
||||||
|
unsigned char __pad0[0x2C];
|
||||||
|
int flags;
|
||||||
|
int clipmask;
|
||||||
|
int processedFrame;
|
||||||
|
EntHandle parent;
|
||||||
|
int nextthink;
|
||||||
|
int health;
|
||||||
|
int maxHealth;
|
||||||
|
int damage;
|
||||||
|
unsigned char __pad1[0x114];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(gentity_s) == 0x270);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/module_loader.hpp"
|
#include "loader/module_loader.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
|
||||||
#include "game/structs.hpp"
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
@ -26,7 +24,7 @@ private:
|
|||||||
game::native::SV_SendServerCommand(&game::native::dedi::svs_clients[client_num],
|
game::native::SV_SendServerCommand(&game::native::dedi::svs_clients[client_num],
|
||||||
type, string);
|
type, string);
|
||||||
}
|
}
|
||||||
else if (game::is_mp())
|
else
|
||||||
{
|
{
|
||||||
game::native::SV_GameSendServerCommand(client_num, type, string);
|
game::native::SV_GameSendServerCommand(client_num, type, string);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
utils::memory::allocator command::allocator_;
|
utils::memory::allocator command::allocator_;
|
||||||
std::unordered_map<std::string, std::function<void(const command::params&)>> command::handlers;
|
std::unordered_map<std::string, std::function<void(const command::params&)>> command::handlers;
|
||||||
std::unordered_map<std::string, std::function<void(game::native::gentity_s*, command::params_sv&)>> command::handlers_sv;
|
std::unordered_map<std::string, std::function<void(game::native::gentity_s*, command::params_sv&)>> command::handlers_sv;
|
||||||
|
std::unordered_map<std::string, std::function<void(game::native::sp::gentity_s*, command::params_sv&)>> command::handlers_sp_sv;
|
||||||
|
|
||||||
command::params::params()
|
command::params::params()
|
||||||
: nesting_(game::native::cmd_args->nesting)
|
: nesting_(game::native::cmd_args->nesting)
|
||||||
@ -112,12 +113,22 @@ void command::add_sv(const char* name, std::function<void(game::native::gentity_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command::add_sp_sv(const char* name, std::function<void(game::native::sp::gentity_s*, const params_sv&)> callback)
|
||||||
|
{
|
||||||
|
const auto command = utils::string::to_lower(name);
|
||||||
|
|
||||||
|
if (handlers_sp_sv.find(command) == handlers_sp_sv.end())
|
||||||
|
{
|
||||||
|
handlers_sp_sv[command] = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void command::main_handler()
|
void command::main_handler()
|
||||||
{
|
{
|
||||||
params params;
|
params params;
|
||||||
|
|
||||||
const auto command = utils::string::to_lower(params[0]);
|
const auto command = utils::string::to_lower(params[0]);
|
||||||
const auto got = handlers.find(command);
|
const auto got = command::handlers.find(command);
|
||||||
|
|
||||||
if (got != handlers.end())
|
if (got != handlers.end())
|
||||||
{
|
{
|
||||||
@ -137,7 +148,7 @@ void command::client_command_stub(int client_num)
|
|||||||
params_sv params;
|
params_sv params;
|
||||||
|
|
||||||
const auto command = utils::string::to_lower(params[0]);
|
const auto command = utils::string::to_lower(params[0]);
|
||||||
const auto got = handlers_sv.find(command);
|
const auto got = command::handlers_sv.find(command);
|
||||||
|
|
||||||
if (got != handlers_sv.end())
|
if (got != handlers_sv.end())
|
||||||
{
|
{
|
||||||
@ -148,6 +159,45 @@ void command::client_command_stub(int client_num)
|
|||||||
game::native::ClientCommand(client_num);
|
game::native::ClientCommand(client_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command::client_command_sp(int client_num, const char* s)
|
||||||
|
{
|
||||||
|
auto* entity = &game::native::sp::g_entities[client_num];
|
||||||
|
|
||||||
|
assert(entity->client != nullptr); // On sp it should only be an assertion
|
||||||
|
|
||||||
|
params_sv params;
|
||||||
|
|
||||||
|
const auto command = utils::string::to_lower(params[0]);
|
||||||
|
const auto got = command::handlers_sp_sv.find(command);
|
||||||
|
|
||||||
|
if (got != handlers_sp_sv.end())
|
||||||
|
{
|
||||||
|
got->second(entity, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void command::client_command_sp_stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
pushad
|
||||||
|
|
||||||
|
push [esp + 0x20 + 0x8]
|
||||||
|
push [esp + 0x20 + 0x8]
|
||||||
|
call command::client_command_sp
|
||||||
|
add esp, 0x8
|
||||||
|
|
||||||
|
popad
|
||||||
|
|
||||||
|
// Code our hook skipped
|
||||||
|
mov eax, [esp + 0x8]
|
||||||
|
sub esp, 0x400
|
||||||
|
|
||||||
|
push 0x44BB5A // ClientCommand
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__declspec(naked) void command::client_command_dedi_stub()
|
__declspec(naked) void command::client_command_dedi_stub()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
@ -163,6 +213,85 @@ __declspec(naked) void command::client_command_dedi_stub()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Between ufo/noclip functions and their mp counterpart is that I reversed the 'CG' type
|
||||||
|
void command::add_sp_commands()
|
||||||
|
{
|
||||||
|
add("noclip", []()
|
||||||
|
{
|
||||||
|
const auto* ent = &game::native::sp::g_entities[0];
|
||||||
|
|
||||||
|
if (ent->health < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(ent->s.eType == game::native::ET_PLAYER);
|
||||||
|
|
||||||
|
ent->client->flags ^= 1;
|
||||||
|
|
||||||
|
const auto* msg = (ent->client->flags & 1) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF";
|
||||||
|
printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "noclip print", game::native::LOCMSG_SAFE));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("ufo", []()
|
||||||
|
{
|
||||||
|
const auto* ent = &game::native::sp::g_entities[0];
|
||||||
|
|
||||||
|
if (ent->health < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(ent->s.eType == game::native::ET_PLAYER);
|
||||||
|
|
||||||
|
ent->client->flags ^= 2;
|
||||||
|
|
||||||
|
const auto* msg = (ent->client->flags & 2) ? "GAME_UFOON" : "GAME_UFOOFF";
|
||||||
|
printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "ufo print", game::native::LOCMSG_SAFE));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("god", []()
|
||||||
|
{
|
||||||
|
auto* ent = &game::native::sp::g_entities[0];
|
||||||
|
|
||||||
|
if (ent->health < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(ent->s.eType == game::native::ET_PLAYER);
|
||||||
|
|
||||||
|
ent->flags ^= game::native::FL_GODMODE;
|
||||||
|
|
||||||
|
const auto* msg = (ent->flags & game::native::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF";
|
||||||
|
printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "god print", game::native::LOCMSG_SAFE));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("demigod", []()
|
||||||
|
{
|
||||||
|
auto* ent = &game::native::sp::g_entities[0];
|
||||||
|
|
||||||
|
if (ent->health < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(ent->s.eType == game::native::ET_PLAYER);
|
||||||
|
|
||||||
|
ent->flags ^= game::native::FL_DEMI_GODMODE;
|
||||||
|
|
||||||
|
const auto* msg = (ent->flags & game::native::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF";
|
||||||
|
printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "demigod print", game::native::LOCMSG_SAFE));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("notarget", []()
|
||||||
|
{
|
||||||
|
auto* ent = &game::native::sp::g_entities[0];
|
||||||
|
|
||||||
|
if (ent->health < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(ent->s.eType == game::native::ET_PLAYER);
|
||||||
|
|
||||||
|
ent->flags ^= game::native::FL_NOTARGET;
|
||||||
|
|
||||||
|
const auto* msg = (ent->flags & game::native::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF";
|
||||||
|
printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "notarget print", game::native::LOCMSG_SAFE));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void command::post_load()
|
void command::post_load()
|
||||||
{
|
{
|
||||||
if (game::is_mp())
|
if (game::is_mp())
|
||||||
@ -172,7 +301,13 @@ void command::post_load()
|
|||||||
else if (game::is_dedi())
|
else if (game::is_dedi())
|
||||||
{
|
{
|
||||||
utils::hook(0x4F96B5, &command::client_command_dedi_stub, HOOK_CALL).install()->quick(); // SV_ExecuteClientCommand
|
utils::hook(0x4F96B5, &command::client_command_dedi_stub, HOOK_CALL).install()->quick(); // SV_ExecuteClientCommand
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
utils::hook(0x44BB50, &command::client_command_sp_stub, HOOK_JUMP).install()->quick();
|
||||||
|
utils::hook::nop(0x44BB55, 5); // Nop skipped instructions
|
||||||
|
add_sp_commands();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_MODULE(command);
|
REGISTER_MODULE(command);
|
||||||
|
@ -49,6 +49,7 @@ public:
|
|||||||
static void add(const char* name, const std::function<void()>& callback);
|
static void add(const char* name, const std::function<void()>& callback);
|
||||||
|
|
||||||
static void add_sv(const char* name, std::function<void(game::native::gentity_s*, const params_sv&)> callback);
|
static void add_sv(const char* name, std::function<void(game::native::gentity_s*, const params_sv&)> callback);
|
||||||
|
static void add_sp_sv(const char* name, std::function<void(game::native::sp::gentity_s*, const params_sv&)> callback);
|
||||||
|
|
||||||
void post_load() override;
|
void post_load() override;
|
||||||
|
|
||||||
@ -57,11 +58,16 @@ private:
|
|||||||
|
|
||||||
static std::unordered_map<std::string, std::function<void(const params&)>> handlers;
|
static std::unordered_map<std::string, std::function<void(const params&)>> handlers;
|
||||||
static std::unordered_map<std::string, std::function<void(game::native::gentity_s*, params_sv&)>> handlers_sv;
|
static std::unordered_map<std::string, std::function<void(game::native::gentity_s*, params_sv&)>> handlers_sv;
|
||||||
|
static std::unordered_map<std::string, std::function<void(game::native::sp::gentity_s*, params_sv&)>> handlers_sp_sv;
|
||||||
|
|
||||||
static void main_handler();
|
static void main_handler();
|
||||||
|
|
||||||
static void client_command_stub(int client_num);
|
static void client_command_stub(int client_num);
|
||||||
|
static void client_command_sp(int client_num, const char* s);
|
||||||
|
static void client_command_sp_stub();
|
||||||
static void client_command_dedi_stub();
|
static void client_command_dedi_stub();
|
||||||
|
|
||||||
static void add_raw(const char* name, void (*callback)());
|
static void add_raw(const char* name, void (*callback)());
|
||||||
|
|
||||||
|
static void add_sp_commands();
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/module_loader.hpp"
|
#include "loader/module_loader.hpp"
|
||||||
#include "game/structs.hpp"
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "utils/hook.hpp"
|
#include "utils/hook.hpp"
|
||||||
|
|
||||||
|
51
src/module/player_movement.cpp
Normal file
51
src/module/player_movement.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "player_movement.hpp"
|
||||||
|
|
||||||
|
#include "utils/hook.hpp"
|
||||||
|
|
||||||
|
const game::native::dvar_t* player_movement::player_sustainAmmo;
|
||||||
|
|
||||||
|
void player_movement::post_load()
|
||||||
|
{
|
||||||
|
if (game::is_mp()) this->patch_mp();
|
||||||
|
else if (game::is_sp()) this->patch_sp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_movement::pm_weapon_use_ammo(game::native::playerState_s* ps, const game::native::Weapon weapon,
|
||||||
|
bool is_alternate, int amount, game::native::PlayerHandIndex hand)
|
||||||
|
{
|
||||||
|
if (!player_movement::player_sustainAmmo->current.enabled)
|
||||||
|
{
|
||||||
|
game::native::PM_WeaponUseAmmo(ps, weapon, is_alternate, amount, hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const game::native::dvar_t* player_movement::dvar_register_player_sustain_ammo(const char* dvar_name,
|
||||||
|
bool value, unsigned __int16 /*flags*/, const char* description)
|
||||||
|
{
|
||||||
|
player_movement::player_sustainAmmo = game::native::Dvar_RegisterBool(dvar_name,
|
||||||
|
value, game::native::DVAR_CODINFO, description);
|
||||||
|
|
||||||
|
return player_movement::player_sustainAmmo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_movement::patch_mp()
|
||||||
|
{
|
||||||
|
utils::hook(0x418D9C, &player_movement::dvar_register_player_sustain_ammo, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
utils::hook(0x42B5DA, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
utils::hook(0x42B2BD, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
utils::hook(0x42AE95, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_movement::patch_sp()
|
||||||
|
{
|
||||||
|
player_movement::player_sustainAmmo = game::native::Dvar_RegisterBool("player_sustainAmmo",
|
||||||
|
false, game::native::DVAR_CODINFO, "Firing weapon will not decrease clip ammo");
|
||||||
|
|
||||||
|
utils::hook(0x648C3A, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
utils::hook(0x64891D, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
utils::hook(0x6484E2, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick();
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_MODULE(player_movement);
|
21
src/module/player_movement.hpp
Normal file
21
src/module/player_movement.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "loader/module_loader.hpp"
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
class player_movement final : public module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_load() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const game::native::dvar_t* player_sustainAmmo;
|
||||||
|
|
||||||
|
static void pm_weapon_use_ammo(game::native::playerState_s* ps, const game::native::Weapon weapon,
|
||||||
|
bool isAlternate, int amount, game::native::PlayerHandIndex hand);
|
||||||
|
|
||||||
|
static const game::native::dvar_t* dvar_register_player_sustain_ammo(const char* dvar_name,
|
||||||
|
bool value, unsigned __int16 flags, const char* description);
|
||||||
|
|
||||||
|
static void patch_mp();
|
||||||
|
static void patch_sp();
|
||||||
|
};
|
@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "loader/module_loader.hpp"
|
#include "loader/module_loader.hpp"
|
||||||
|
|
||||||
#include "game/structs.hpp"
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
class test_clients final : public module
|
class test_clients final : public module
|
||||||
|
Loading…
Reference in New Issue
Block a user