mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2026-08-01 04:40:34 +00:00
add settextunlimited()
This commit is contained in:
@@ -0,0 +1,148 @@
|
|||||||
|
#include <stdinc.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "gsc.hpp"
|
||||||
|
#include "scripting.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
namespace config_strings
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool reserved_config_strings[600]{};
|
||||||
|
std::uint32_t hudelem_config_strings[1024]{};
|
||||||
|
|
||||||
|
bool is_string_reserved(const std::uint32_t string_index)
|
||||||
|
{
|
||||||
|
if (string_index >= 600)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reserved_config_strings[string_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short get_scr_const_()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<unsigned short*>(0x1C8DF80);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t get_config_string()
|
||||||
|
{
|
||||||
|
auto index = 0;
|
||||||
|
const auto scr_const_ = get_scr_const_();
|
||||||
|
for (auto i = 1; i < 600; i++)
|
||||||
|
{
|
||||||
|
const auto string_value = game::sv_configstrings[i + 469];
|
||||||
|
if (string_value == scr_const_ && !reserved_config_strings[i])
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("out of config strings");
|
||||||
|
}
|
||||||
|
|
||||||
|
reserved_config_strings[index] = true;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::hook::detour scr_free_hud_elem_hook;
|
||||||
|
void scr_free_hud_elem_stub(game::game_hudelem_s* hud)
|
||||||
|
{
|
||||||
|
const auto _0 = gsl::finally([&]
|
||||||
|
{
|
||||||
|
scr_free_hud_elem_hook.invoke<void>(hud);
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto index = hud - &game::g_hudelems[0];
|
||||||
|
const auto string = hudelem_config_strings[index];
|
||||||
|
|
||||||
|
if (string != 0)
|
||||||
|
{
|
||||||
|
hudelem_config_strings[index] = 0;
|
||||||
|
reserved_config_strings[string] = false;
|
||||||
|
game::sv_configstrings[string + 469] = get_scr_const_();
|
||||||
|
game::SV_SetConfigString(string + 496, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void g_localized_string_index_stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
add esp, 4
|
||||||
|
pushad
|
||||||
|
lea ecx, [ecx - 469]
|
||||||
|
push ecx
|
||||||
|
call is_string_reserved
|
||||||
|
test al, al
|
||||||
|
jz not_reserved
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
popad
|
||||||
|
push 0x52D95E
|
||||||
|
retn
|
||||||
|
|
||||||
|
not_reserved:
|
||||||
|
pop ecx
|
||||||
|
popad
|
||||||
|
|
||||||
|
cmp eax, edx
|
||||||
|
push 0x52D958
|
||||||
|
retn
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void on_startup([[maybe_unused]] plugin::plugin* plugin) override
|
||||||
|
{
|
||||||
|
utils::hook::jump(0x52D953, g_localized_string_index_stub);
|
||||||
|
scr_free_hud_elem_hook.create(0x52B0F0, scr_free_hud_elem_stub);
|
||||||
|
|
||||||
|
scripting::on_shutdown([&]
|
||||||
|
{
|
||||||
|
std::memset(reserved_config_strings, 0, sizeof(reserved_config_strings));
|
||||||
|
std::memset(hudelem_config_strings, 0, sizeof(hudelem_config_strings));
|
||||||
|
});
|
||||||
|
|
||||||
|
gsc::method::add("settextunlimited", [](const game::scr_entref_t ent, const gsc::function_args& args)
|
||||||
|
-> scripting::script_value
|
||||||
|
{
|
||||||
|
if (ent.classnum != gsc::class_hudelem || ent.entnum >= 1024)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("not a hudelem");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto text = args[0].as<const char*>();
|
||||||
|
const auto hudelem = &game::g_hudelems[ent.entnum];
|
||||||
|
|
||||||
|
hudelem->type = 1;
|
||||||
|
hudelem->flags |= 1;
|
||||||
|
|
||||||
|
if (hudelem_config_strings[ent.entnum] == 0)
|
||||||
|
{
|
||||||
|
const auto index = get_config_string();
|
||||||
|
hudelem->text = index;
|
||||||
|
hudelem_config_strings[ent.entnum] = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hudelem->text = hudelem_config_strings[ent.entnum];
|
||||||
|
}
|
||||||
|
|
||||||
|
game::SV_SetConfigString(hudelem->text + 469, text);
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(config_strings::component)
|
||||||
@@ -426,4 +426,18 @@ namespace game
|
|||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(client_s) == 0x78698);
|
static_assert(sizeof(client_s) == 0x78698);
|
||||||
|
|
||||||
|
struct game_hudelem_s
|
||||||
|
{
|
||||||
|
unsigned int type;
|
||||||
|
char __pad0[128];
|
||||||
|
unsigned int text;
|
||||||
|
char __pad1[28];
|
||||||
|
unsigned int flags;
|
||||||
|
char __pad2[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(offsetof(game_hudelem_s, text) == 132);
|
||||||
|
static_assert(offsetof(game_hudelem_s, flags) == 164);
|
||||||
|
static_assert(sizeof(game_hudelem_s) == 180);
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,7 @@ namespace game
|
|||||||
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x573220};
|
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x573220};
|
||||||
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x5459F0};
|
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x5459F0};
|
||||||
WEAK symbol<void(client_s* drop, const char* reason, bool tellThem)> SV_DropClient{0x570980};
|
WEAK symbol<void(client_s* drop, const char* reason, bool tellThem)> SV_DropClient{0x570980};
|
||||||
|
WEAK symbol<void(unsigned int, const char*)> SV_SetConfigString{0x574BD0};
|
||||||
|
|
||||||
WEAK symbol<void(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top)> VM_Notify{0x569720};
|
WEAK symbol<void(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top)> VM_Notify{0x569720};
|
||||||
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x56DFE0};
|
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x56DFE0};
|
||||||
@@ -76,10 +77,12 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<scr_classStruct_t*> g_classMap{0x8B4300};
|
WEAK symbol<scr_classStruct_t*> g_classMap{0x8B4300};
|
||||||
|
|
||||||
|
WEAK symbol<game_hudelem_s> g_hudelems{0x1A39E00};
|
||||||
WEAK symbol<gentity_s> g_entities{0x1A66E28};
|
WEAK symbol<gentity_s> g_entities{0x1A66E28};
|
||||||
WEAK symbol<unsigned int> levelEntityId{0x208E1A4};
|
WEAK symbol<unsigned int> levelEntityId{0x208E1A4};
|
||||||
|
|
||||||
WEAK symbol<dvar_t> sv_maxclients{0x1BA0E4C};
|
WEAK symbol<dvar_t> sv_maxclients{0x1BA0E4C};
|
||||||
WEAK symbol<int> svs_clientCount{0x4B5CF8C};
|
WEAK symbol<int> svs_clientCount{0x4B5CF8C};
|
||||||
WEAK symbol<client_s> svs_clients{0x4B5CF90};
|
WEAK symbol<client_s> svs_clients{0x4B5CF90};
|
||||||
|
WEAK symbol<unsigned short> sv_configstrings{0x20FA3AE};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user