mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2026-08-01 04:40:34 +00:00
Compare commits
1
Commits
930175e564
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b393d2eb54 |
@@ -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);
|
||||
|
||||
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 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(unsigned int, const char*)> SV_SetConfigString{0x574BD0};
|
||||
|
||||
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};
|
||||
@@ -76,10 +77,12 @@ namespace game
|
||||
|
||||
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<unsigned int> levelEntityId{0x208E1A4};
|
||||
|
||||
WEAK symbol<dvar_t> sv_maxclients{0x1BA0E4C};
|
||||
WEAK symbol<int> svs_clientCount{0x4B5CF8C};
|
||||
WEAK symbol<client_s> svs_clients{0x4B5CF90};
|
||||
WEAK symbol<unsigned short> sv_configstrings{0x20FA3AE};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user