2023-01-09 10:53:51 -05:00
|
|
|
#include <std_include.hpp>
|
|
|
|
#include "loader/component_loader.hpp"
|
2023-03-13 15:33:59 -04:00
|
|
|
#include "chat.hpp"
|
2023-01-09 10:53:51 -05:00
|
|
|
#include "game/game.hpp"
|
2023-03-21 15:44:35 -04:00
|
|
|
#include "game/utils.hpp"
|
2023-01-09 10:53:51 -05:00
|
|
|
|
|
|
|
#include <utils/hook.hpp>
|
2023-03-13 15:33:59 -04:00
|
|
|
#include <utils/string.hpp>
|
2023-01-09 10:53:51 -05:00
|
|
|
|
|
|
|
#include "command.hpp"
|
|
|
|
#include "client_command.hpp"
|
|
|
|
|
|
|
|
namespace chat
|
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
void cmd_say_f(game::gentity_s* ent, const command::params_sv& params)
|
|
|
|
{
|
|
|
|
if (params.size() < 2)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto mode = 0;
|
|
|
|
if (std::strcmp(params[0], "say_team") == 0)
|
|
|
|
{
|
|
|
|
mode = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto p = params.join(1);
|
|
|
|
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, p.data() + 1); // Skip special char
|
|
|
|
game::Scr_Notify_Canon(ent, game::Scr_CanonHash(params[0]), 1);
|
|
|
|
|
|
|
|
game::G_Say(ent, nullptr, mode, p.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmd_chat_f(game::gentity_s* ent, const command::params_sv& params)
|
|
|
|
{
|
|
|
|
auto p = params.join(1);
|
|
|
|
|
|
|
|
// Not a mistake! + 2 is necessary for the GSC script to receive only the actual chat text
|
|
|
|
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, p.data() + 2);
|
|
|
|
game::Scr_Notify_Canon(ent, game::Scr_CanonHash(params[0]), 1);
|
|
|
|
|
2023-01-09 11:40:08 -05:00
|
|
|
utils::hook::invoke<void>(0x140298E70_g, ent, p.data());
|
2023-01-09 10:53:51 -05:00
|
|
|
}
|
2023-03-13 15:33:59 -04:00
|
|
|
|
2023-03-13 15:35:49 -04:00
|
|
|
uint64_t* divert_xuid_to_client_num_stub(int, int client_num, int)
|
2023-03-13 15:33:59 -04:00
|
|
|
{
|
2023-03-13 15:35:49 -04:00
|
|
|
static thread_local uint64_t value;
|
|
|
|
// zero xuid is invalid, so increase the clientnum to prevent 0 values
|
|
|
|
value = static_cast<uint64_t>(client_num) + 1;
|
|
|
|
return &value;
|
2023-03-13 15:33:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-21 14:19:01 -04:00
|
|
|
const char* get_client_name(const uint64_t xuid)
|
2023-03-13 15:33:59 -04:00
|
|
|
{
|
|
|
|
if (xuid < 19 && !game::is_server())
|
|
|
|
{
|
|
|
|
char buffer[256];
|
|
|
|
game::CL_GetClientName(0, static_cast<int>(xuid - 1), buffer, sizeof(buffer), true);
|
|
|
|
|
|
|
|
return utils::string::va("%s\n", buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown Soldier";
|
2023-01-09 10:53:51 -05:00
|
|
|
}
|
|
|
|
|
2023-03-13 15:33:59 -04:00
|
|
|
class component final : public generic_component
|
2023-01-09 10:53:51 -05:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
void post_unpack() override
|
|
|
|
{
|
2023-03-13 15:33:59 -04:00
|
|
|
utils::hook::call(game::select(0x141974B04, 0x14029908A), divert_xuid_to_client_num_stub);
|
2023-01-09 10:53:51 -05:00
|
|
|
|
2023-03-13 15:33:59 -04:00
|
|
|
if (game::is_server())
|
|
|
|
{
|
|
|
|
client_command::add("say", cmd_say_f);
|
|
|
|
client_command::add("say_team", cmd_say_f);
|
|
|
|
|
|
|
|
client_command::add("chat", cmd_chat_f);
|
2023-03-21 15:44:35 -04:00
|
|
|
|
|
|
|
command::add("say", [](const command::params& params)
|
|
|
|
{
|
|
|
|
if (!game::get_dvar_bool("sv_running"))
|
|
|
|
{
|
|
|
|
printf("Server is not running\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto text = params.join(1);
|
|
|
|
const auto* format = reinterpret_cast<const char*>(0x140E25180_g);
|
|
|
|
const auto* message = utils::string::va(format, 'O', text.data());
|
|
|
|
reinterpret_cast<void(*)(int64_t, uint64_t, const char*)>(0x140532CA0_g)(-1, 0, message);
|
|
|
|
});
|
|
|
|
|
|
|
|
command::add("tell", [](const command::params& params)
|
|
|
|
{
|
|
|
|
if (!game::get_dvar_bool("sv_running"))
|
|
|
|
{
|
|
|
|
printf("Server is not running\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params.size() < 2)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto client = atoi(params[1]);
|
|
|
|
|
|
|
|
const auto text = params.join(2);
|
|
|
|
const auto* format = reinterpret_cast<const char*>(0x140E25180_g);
|
|
|
|
const auto* message = utils::string::va(format, 'O', text.data());
|
|
|
|
reinterpret_cast<void(*)(int64_t, uint64_t, const char*)>(0x140532CA0_g)(client, 0, message);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Kill say and tell commands
|
|
|
|
utils::hook::nop(0x1405299FB_g, 5);
|
|
|
|
utils::hook::nop(0x140529A21_g, 5);
|
|
|
|
utils::hook::nop(0x140529A3B_g, 5);
|
|
|
|
utils::hook::nop(0x140529A07_g, 5);
|
|
|
|
utils::hook::nop(0x140529A55_g, 5);
|
|
|
|
utils::hook::nop(0x140529A6F_g, 5);
|
2023-03-13 15:33:59 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Ignore some check that suppresses the chat
|
|
|
|
utils::hook::nop(0x141DEA9BD_g, 2);
|
|
|
|
}
|
2023-01-09 10:53:51 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
REGISTER_COMPONENT(chat::component)
|