[Chat] Add say notify
This commit is contained in:
parent
cf281ed7e5
commit
b4b7c45624
@ -2,4 +2,4 @@
|
||||
|
||||
// The naming of the file enforces early linking and thus
|
||||
// a better placement in the tls segment
|
||||
__declspec(thread) char tls_data[TLS_PAYLOAD_SIZE];
|
||||
__declspec(thread) char tls_data[TLS_PAYLOAD_SIZE];
|
||||
|
@ -34,9 +34,12 @@ namespace game
|
||||
Scr_AddEntityNum_t Scr_AddEntityNum;
|
||||
|
||||
Scr_Notify_t Scr_Notify;
|
||||
Scr_NotifyLevel_t Scr_NotifyLevel;
|
||||
|
||||
Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
Sys_Error_t Sys_Error;
|
||||
|
||||
VM_Notify_t VM_Notify;
|
||||
|
||||
BG_NetDataChecksum_t BG_NetDataChecksum;
|
||||
@ -92,6 +95,7 @@ namespace game
|
||||
char** scrMemTreePub;
|
||||
char* scrMemTreeGlob;
|
||||
|
||||
scrVarPub_t* scr_VarPub;
|
||||
scrVmPub_t* scr_VmPub;
|
||||
|
||||
scr_call_t* scr_instanceFunctions;
|
||||
@ -255,7 +259,7 @@ namespace game
|
||||
(SELECT_VALUE(0x539550, 0x5BDCC0, 0x0))(dvarName);
|
||||
}
|
||||
|
||||
__declspec(naked) const dvar_t* Dvar_RegisterVariant(const char* dvarName, unsigned char type,
|
||||
__declspec(naked) const dvar_t* dvar_register_variant_dedicated(const char* dvar_name, unsigned char type,
|
||||
unsigned __int16 flags, DvarValue value, DvarLimits domain, const char* description)
|
||||
{
|
||||
static DWORD func = 0x531F70;
|
||||
@ -307,10 +311,23 @@ namespace game
|
||||
|
||||
dvar_value.value = value;
|
||||
|
||||
return Dvar_RegisterVariant(dvarName, dvar_type::DVAR_TYPE_FLOAT,
|
||||
return dvar_register_variant_dedicated(dvarName, dvar_type::DVAR_TYPE_FLOAT,
|
||||
flags, dvar_value, domain, description);
|
||||
}
|
||||
|
||||
void IncInParam()
|
||||
{
|
||||
Scr_ClearOutParams();
|
||||
|
||||
if (scr_VmPub->top == scr_VmPub->maxStack)
|
||||
{
|
||||
Sys_Error("Internal script stack overflow");
|
||||
}
|
||||
|
||||
scr_VmPub->top++;
|
||||
scr_VmPub->inparamcount++;
|
||||
}
|
||||
|
||||
const float* Scr_AllocVector(const float* v)
|
||||
{
|
||||
const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
|
||||
@ -396,16 +413,16 @@ namespace game
|
||||
{
|
||||
if (is_mp())
|
||||
{
|
||||
return scr_notify_id_multiplayer(id, stringValue, paramcount);
|
||||
scr_notify_id_multiplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else if (is_sp())
|
||||
{
|
||||
return scr_notify_id_singleplayer(id, stringValue, paramcount);
|
||||
scr_notify_id_singleplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(
|
||||
id, stringValue, paramcount);
|
||||
reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)
|
||||
(id, stringValue, paramcount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,7 +454,7 @@ namespace game
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void scr_add_string_dedi(const char* value)
|
||||
__declspec(naked) void scr_add_string_dedicated(const char* value)
|
||||
{
|
||||
static DWORD func = 0x4F1010;
|
||||
|
||||
@ -453,15 +470,23 @@ namespace game
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
scr_add_string_dedi(value);
|
||||
scr_add_string_dedicated(value);
|
||||
}
|
||||
else if (is_mp())
|
||||
else
|
||||
{
|
||||
reinterpret_cast<void(*)(const char*)>
|
||||
(0x56AC00)(value);
|
||||
(SELECT_VALUE(0x4A5600, 0x56AC00, 0x0))(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Scr_AddInt(int value)
|
||||
{
|
||||
IncInParam();
|
||||
|
||||
scr_VmPub->top->type = SCRIPT_INTEGER;
|
||||
scr_VmPub->top->u.intValue = value;
|
||||
}
|
||||
|
||||
const char* SL_ConvertToString(const unsigned int stringValue)
|
||||
{
|
||||
if (!stringValue) return nullptr;
|
||||
@ -472,7 +497,7 @@ namespace game
|
||||
|
||||
unsigned int SL_GetString(const char* str, const unsigned int user)
|
||||
{
|
||||
return SL_GetStringOfSize(str, user, strlen(str) + 1, 7);
|
||||
return SL_GetStringOfSize(str, user, std::strlen(str) + 1, 7);
|
||||
}
|
||||
|
||||
__declspec(naked) void sv_send_client_game_state_mp(mp::client_t* /*client*/)
|
||||
@ -544,7 +569,7 @@ namespace game
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void client_command_dedi(int client_num)
|
||||
__declspec(naked) void client_command_dedicated(int client_num)
|
||||
{
|
||||
static DWORD func = 0x47EA40;
|
||||
|
||||
@ -560,7 +585,7 @@ namespace game
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
client_command_dedi(clientNum);
|
||||
client_command_dedicated(clientNum);
|
||||
}
|
||||
else if (is_mp())
|
||||
{
|
||||
@ -578,7 +603,7 @@ namespace game
|
||||
addr->type = type;
|
||||
}
|
||||
|
||||
__declspec(naked) void cbuf_add_text_dedi(LocalClientNum_t local_client_num, const char* text)
|
||||
__declspec(naked) void cbuf_add_text_dedicated(LocalClientNum_t local_client_num, const char* text)
|
||||
{
|
||||
static DWORD func = 0x4CB5D0;
|
||||
|
||||
@ -596,7 +621,7 @@ namespace game
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
cbuf_add_text_dedi(localClientNum, text);
|
||||
cbuf_add_text_dedicated(localClientNum, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -605,7 +630,7 @@ namespace game
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void teleport_player_dedi(gentity_s* player, float* origin, float* angles)
|
||||
__declspec(naked) void teleport_player_dedicated(gentity_s* player, float* origin, float* angles)
|
||||
{
|
||||
static DWORD func = 0x48B840;
|
||||
|
||||
@ -624,7 +649,7 @@ namespace game
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
teleport_player_dedi(player, origin, angles);
|
||||
teleport_player_dedicated(player, origin, angles);
|
||||
}
|
||||
else if (is_mp())
|
||||
{
|
||||
@ -708,9 +733,12 @@ namespace game
|
||||
native::Scr_AddEntityNum = native::Scr_AddEntityNum_t(SELECT_VALUE(0x0, 0x56ABC0, 0x4EA2F0));
|
||||
|
||||
native::Scr_Notify = native::Scr_Notify_t(SELECT_VALUE(0x4895B0, 0x52B190, 0x0));
|
||||
native::Scr_NotifyLevel = native::Scr_NotifyLevel_t(SELECT_VALUE(0x445E10, 0x56B6B0, 0x0));
|
||||
|
||||
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
||||
|
||||
native::Sys_Error = native::Sys_Error_t(SELECT_VALUE(0x490D90, 0x5CC3B0, 0x539590));
|
||||
|
||||
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
|
||||
|
||||
native::BG_NetDataChecksum = native::BG_NetDataChecksum_t(SELECT_VALUE(0x0, 0x41BB20, 0x0));
|
||||
@ -774,6 +802,7 @@ namespace game
|
||||
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
|
||||
native::scrMemTreeGlob = reinterpret_cast<char*>(SELECT_VALUE(0x186DA00, 0x1D6FF00, 0x1C16600));
|
||||
|
||||
native::scr_VarPub = reinterpret_cast<native::scrVarPub_t*>(SELECT_VALUE(0x0, 0x208E188, 0x1CD8720));
|
||||
native::scr_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080));
|
||||
|
||||
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258,
|
||||
|
@ -55,12 +55,18 @@ namespace game
|
||||
typedef void (*Scr_AddEntityNum_t)(int entnum, unsigned int classnum);
|
||||
extern Scr_AddEntityNum_t Scr_AddEntityNum;
|
||||
|
||||
typedef void (*Scr_Notify_t)(gentity_s* ent, unsigned __int16 stringValue, unsigned int paramcount);
|
||||
typedef void (*Scr_Notify_t)(gentity_s* ent, unsigned int stringValue, unsigned int paramcount);
|
||||
extern Scr_Notify_t Scr_Notify;
|
||||
|
||||
typedef void (*Scr_NotifyLevel_t)(unsigned int stringValue, unsigned int paramcount);
|
||||
extern Scr_NotifyLevel_t Scr_NotifyLevel;
|
||||
|
||||
typedef void (*Sys_ShowConsole_t)();
|
||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
typedef void (*Sys_Error_t)(const char* error, ...);
|
||||
extern Sys_Error_t Sys_Error;
|
||||
|
||||
typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top);
|
||||
extern VM_Notify_t VM_Notify;
|
||||
|
||||
@ -145,6 +151,7 @@ namespace game
|
||||
extern char** scrMemTreePub;
|
||||
extern char* scrMemTreeGlob;
|
||||
|
||||
extern scrVarPub_t* scr_VarPub;
|
||||
extern scrVmPub_t* scr_VmPub;
|
||||
|
||||
extern scr_call_t* scr_instanceFunctions;
|
||||
@ -201,7 +208,6 @@ 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);
|
||||
@ -211,6 +217,7 @@ namespace game
|
||||
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount);
|
||||
int Scr_SetObjectField(unsigned int classnum, int entnum, int offset);
|
||||
void Scr_AddString(const char* value);
|
||||
void Scr_AddInt(int value);
|
||||
|
||||
const char* SL_ConvertToString(unsigned int stringValue);
|
||||
unsigned int SL_GetString(const char* str, unsigned int user);
|
||||
|
@ -14,19 +14,19 @@ namespace game::scripting
|
||||
const std::string string = native::SL_ConvertToString(value.u.stringValue);
|
||||
return chaiscript::var(string);
|
||||
}
|
||||
else if (value.type == native::SCRIPT_FLOAT)
|
||||
if (value.type == native::SCRIPT_FLOAT)
|
||||
{
|
||||
return chaiscript::var(value.u.floatValue);
|
||||
}
|
||||
else if (value.type == native::SCRIPT_INTEGER)
|
||||
if (value.type == native::SCRIPT_INTEGER)
|
||||
{
|
||||
return chaiscript::var(value.u.intValue);
|
||||
}
|
||||
else if (value.type == native::SCRIPT_OBJECT)
|
||||
if (value.type == native::SCRIPT_OBJECT)
|
||||
{
|
||||
return chaiscript::var(entity(this->context_, value.u.entityId));
|
||||
}
|
||||
else if (value.type == native::SCRIPT_VECTOR)
|
||||
if (value.type == native::SCRIPT_VECTOR)
|
||||
{
|
||||
std::vector<chaiscript::Boxed_Value> values;
|
||||
values.push_back(chaiscript::var(value.u.vectorValue[0]));
|
||||
@ -46,7 +46,7 @@ namespace game::scripting
|
||||
native::Scr_ClearOutParams();
|
||||
}
|
||||
|
||||
if (native::scr_VmPub->top == native::scr_VmPub->maxstack)
|
||||
if (native::scr_VmPub->top == native::scr_VmPub->maxStack)
|
||||
{
|
||||
throw std::runtime_error("Internal script stack overflow");
|
||||
}
|
||||
@ -75,6 +75,12 @@ namespace game::scripting
|
||||
value_ptr->type = native::SCRIPT_INTEGER;
|
||||
value_ptr->u.intValue = real_value;
|
||||
}
|
||||
else if (value.get_type_info() == typeid(unsigned int))
|
||||
{
|
||||
const auto real_value = this->context_->get_chai()->boxed_cast<unsigned int>(value);
|
||||
value_ptr->type = native::SCRIPT_INTEGER;
|
||||
value_ptr->u.intValue = static_cast<int>(real_value);
|
||||
}
|
||||
else if (value.get_type_info() == typeid(bool))
|
||||
{
|
||||
const auto real_value = this->context_->get_chai()->boxed_cast<bool>(value);
|
||||
|
@ -8,10 +8,10 @@ namespace game::scripting
|
||||
this->in_param_count_ = native::scr_VmPub->inparamcount;
|
||||
this->out_param_count_ = native::scr_VmPub->outparamcount;
|
||||
this->top_ = native::scr_VmPub->top;
|
||||
this->max_stack_ = native::scr_VmPub->maxstack;
|
||||
this->max_stack_ = native::scr_VmPub->maxStack;
|
||||
|
||||
native::scr_VmPub->top = this->stack_;
|
||||
native::scr_VmPub->maxstack = &this->stack_[ARRAYSIZE(this->stack_) - 1];
|
||||
native::scr_VmPub->maxStack = &this->stack_[ARRAYSIZE(this->stack_) - 1];
|
||||
native::scr_VmPub->inparamcount = 0;
|
||||
native::scr_VmPub->outparamcount = 0;
|
||||
}
|
||||
@ -22,6 +22,6 @@ namespace game::scripting
|
||||
native::scr_VmPub->inparamcount = this->in_param_count_;
|
||||
native::scr_VmPub->outparamcount = this->out_param_count_;
|
||||
native::scr_VmPub->top = this->top_;
|
||||
native::scr_VmPub->maxstack = this->max_stack_;
|
||||
native::scr_VmPub->maxStack = this->max_stack_;
|
||||
}
|
||||
}
|
||||
|
@ -468,9 +468,11 @@ namespace game
|
||||
SCRIPT_NONE = 0,
|
||||
SCRIPT_OBJECT = 1,
|
||||
SCRIPT_STRING = 2,
|
||||
SCRIPT_ISTRING = 2,
|
||||
SCRIPT_VECTOR = 4,
|
||||
SCRIPT_FLOAT = 5,
|
||||
SCRIPT_INTEGER = 6,
|
||||
SCRIPT_CODEPOS = 7,
|
||||
SCRIPT_END = 8,
|
||||
// Custom
|
||||
};
|
||||
@ -521,7 +523,7 @@ namespace game
|
||||
struct scrVmPub_t
|
||||
{
|
||||
unsigned int* localVars;
|
||||
VariableValue* maxstack;
|
||||
VariableValue* maxStack;
|
||||
int function_count;
|
||||
function_frame_t* function_frame;
|
||||
VariableValue* top;
|
||||
@ -537,6 +539,52 @@ namespace game
|
||||
VariableValue stack[2048];
|
||||
};
|
||||
|
||||
struct HunkUser
|
||||
{
|
||||
HunkUser* current;
|
||||
HunkUser* next;
|
||||
int maxSize;
|
||||
int end;
|
||||
int pos;
|
||||
const char* name;
|
||||
bool fixed;
|
||||
int type;
|
||||
unsigned char buf[1];
|
||||
};
|
||||
|
||||
static_assert(sizeof(HunkUser) == 0x24);
|
||||
|
||||
struct scrVarPub_t
|
||||
{
|
||||
const char* fieldBuffer;
|
||||
bool evaluate;
|
||||
unsigned int time;
|
||||
unsigned int timeArrayId;
|
||||
unsigned int pauseArrayId;
|
||||
unsigned int notifyArrayId;
|
||||
unsigned int objectStackId;
|
||||
unsigned int levelId;
|
||||
unsigned int gameId;
|
||||
unsigned int animId;
|
||||
unsigned int freeEntList;
|
||||
unsigned int tempVariable;
|
||||
unsigned int numScriptValues[2];
|
||||
bool bInited;
|
||||
bool abort;
|
||||
unsigned __int16 savecount;
|
||||
unsigned __int16 savecountMark;
|
||||
unsigned int entId;
|
||||
unsigned int entFieldName;
|
||||
unsigned int checksum;
|
||||
HunkUser* programHunkUser;
|
||||
HunkUser* canonicalStringHunkUser;
|
||||
const char* programBuffer;
|
||||
unsigned __int16 saveIdMap[36864];
|
||||
unsigned __int16 saveIdMapRev[36864];
|
||||
};
|
||||
|
||||
static_assert(sizeof(scrVarPub_t) == 0x24058);
|
||||
|
||||
struct scr_classStruct_t
|
||||
{
|
||||
unsigned __int16 id;
|
||||
@ -974,7 +1022,7 @@ namespace game
|
||||
int maxHealth;
|
||||
int damage;
|
||||
int count;
|
||||
unsigned char __pad2[0xc8];
|
||||
unsigned char __pad2[0xC8];
|
||||
};
|
||||
|
||||
static_assert(sizeof(gentity_s) == 0x274);
|
||||
|
48
src/module/chat.cpp
Normal file
48
src/module/chat.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include <std_include.hpp>
|
||||
#include <loader/module_loader.hpp>
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
static void notify_on_say(game::native::gentity_s* ent, int mode, const char* message)
|
||||
{
|
||||
game::native::Scr_AddString(message + 1); // First character has nothing to do with actual message
|
||||
game::native::Scr_AddInt(mode);
|
||||
game::native::Scr_AddEntityNum(ent->s.number, 0);
|
||||
|
||||
game::native::Scr_NotifyLevel(game::native::SL_GetString("say", 0), 3);
|
||||
}
|
||||
|
||||
static __declspec(naked) void g_say_stub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
push [esp + 0x20 + 0x108] // message
|
||||
push [esp + 0x20 + 0x108] // mode
|
||||
push ebp // ent
|
||||
call notify_on_say
|
||||
add esp, 0xC
|
||||
|
||||
popad
|
||||
|
||||
push 0x5C2940 // I_strncpyz
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
class chat final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_mp())
|
||||
{
|
||||
utils::hook(0x502BAF, &g_say_stub, HOOK_CALL).install()->quick(); // I_strncpyz
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(chat)
|
@ -61,7 +61,7 @@ game::native::gentity_s* test_clients::sv_add_test_client()
|
||||
game::native::SV_Cmd_EndTokenizedString();
|
||||
|
||||
// Find the bot
|
||||
auto idx = 1;
|
||||
int idx;
|
||||
for (idx = 0; idx < *game::native::svs_clientCount; idx++)
|
||||
{
|
||||
if (game::native::mp::svs_clients[idx].header.state == game::native::clientState_t::CS_FREE)
|
||||
@ -135,7 +135,7 @@ void test_clients::spawn(const int count)
|
||||
void test_clients::scr_shutdown_system_mp_stub(unsigned char sys)
|
||||
{
|
||||
game::native::SV_DropAllBots();
|
||||
reinterpret_cast<void (*)(unsigned char)>(0x569E30)(sys);
|
||||
reinterpret_cast<void(*)(unsigned char)>(0x569E30)(sys);
|
||||
}
|
||||
|
||||
__declspec(naked) void test_clients::reset_reliable_mp()
|
||||
|
Loading…
Reference in New Issue
Block a user