Custom weapon cac stuff + fixes
This commit is contained in:
@ -346,6 +346,8 @@ namespace fastfiles
|
||||
|
||||
// code_pre_gfx
|
||||
|
||||
try_load_zone("h1_mod_code_pre_gfx", true);
|
||||
|
||||
game::DB_LoadXAssets(data.data(), static_cast<std::uint32_t>(data.size()), syncMode);
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,27 @@ namespace gsc
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <size_t rva>
|
||||
void safe_func()
|
||||
{
|
||||
static utils::hook::detour hook;
|
||||
|
||||
const auto stub = []()
|
||||
{
|
||||
__try
|
||||
{
|
||||
hook.invoke<void>();
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
game::Scr_ErrorInternal();
|
||||
}
|
||||
};
|
||||
|
||||
const auto ptr = rva + 0_b;
|
||||
hook.create(ptr, stub);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos)
|
||||
@ -111,6 +132,8 @@ namespace gsc
|
||||
utils::hook::call(SELECT_VALUE(0x3BD626_b, 0x504606_b), unknown_function_stub); // CompileError (LinkFile)
|
||||
utils::hook::call(SELECT_VALUE(0x3BD672_b, 0x504652_b), unknown_function_stub); // ^
|
||||
utils::hook::call(SELECT_VALUE(0x3BD75A_b, 0x50473A_b), find_variable_stub); // Scr_EmitFunction
|
||||
|
||||
safe_func<0xBA7A0>(); // fix vlobby cac crash
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
|
@ -109,18 +109,20 @@ namespace gsc
|
||||
return false;
|
||||
}
|
||||
|
||||
bool force_load = false;
|
||||
|
||||
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
||||
{
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (loaded_scripts.contains(real_name))
|
||||
{
|
||||
return loaded_scripts[real_name];
|
||||
}
|
||||
|
||||
if (game::VirtualLobby_Loaded() && !force_load)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string source_buffer;
|
||||
if (!read_scriptfile(real_name + ".gsc", &source_buffer) || source_buffer.empty())
|
||||
{
|
||||
@ -283,21 +285,27 @@ namespace gsc
|
||||
{
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x2B9DA0_b, 0x18BC00_b), a1, a2);
|
||||
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& path : filesystem::get_search_paths())
|
||||
{
|
||||
load_scripts(path, "scripts/");
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
load_scripts(path, "scripts/sp/");
|
||||
load_scripts(path, "scripts/");
|
||||
}
|
||||
else
|
||||
{
|
||||
load_scripts(path, "scripts/mp/");
|
||||
if (!game::VirtualLobby_Loaded())
|
||||
{
|
||||
load_scripts(path, "scripts/mp/");
|
||||
load_scripts(path, "scripts/");
|
||||
}
|
||||
|
||||
force_load = true;
|
||||
const auto _0 = gsl::finally([&]
|
||||
{
|
||||
force_load = false;
|
||||
});
|
||||
load_scripts(path, "scripts/mp_patches/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,20 +97,16 @@ namespace scripting
|
||||
game::G_LogPrintf("InitGame\n");
|
||||
|
||||
lua::engine::start();
|
||||
|
||||
gsc::load_main_handles();
|
||||
}
|
||||
|
||||
gsc::load_main_handles();
|
||||
|
||||
g_load_structs_hook.invoke<void>();
|
||||
}
|
||||
|
||||
void scr_load_level_stub()
|
||||
{
|
||||
if (!game::VirtualLobby_Loaded())
|
||||
{
|
||||
gsc::load_init_handles();
|
||||
}
|
||||
|
||||
gsc::load_init_handles();
|
||||
scr_load_level_hook.invoke<void>();
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,26 @@ namespace ui_scripting
|
||||
|
||||
setup_functions();
|
||||
|
||||
lua["print"] = function(reinterpret_cast<game::hks::lua_function>(SELECT_VALUE(0x93490_b, 0x209EB0_b)));
|
||||
lua["print"] = [](const variadic_args& va)
|
||||
{
|
||||
std::string buffer{};
|
||||
const auto to_string = get_globals()["tostring"];
|
||||
|
||||
for (auto i = 0; i < va.size(); i++)
|
||||
{
|
||||
const auto& arg = va[i];
|
||||
const auto str = to_string(arg)[0].as<std::string>();
|
||||
buffer.append(str);
|
||||
|
||||
if (i < va.size() - 1)
|
||||
{
|
||||
buffer.append("\t");
|
||||
}
|
||||
}
|
||||
|
||||
console::info("%s\n", buffer.data());
|
||||
};
|
||||
|
||||
lua["table"]["unpack"] = lua["unpack"];
|
||||
lua["luiglobals"] = lua;
|
||||
|
||||
|
@ -116,6 +116,122 @@ namespace weapon
|
||||
{
|
||||
set_weapon_field<bool>(weapon_name, field, value);
|
||||
}
|
||||
|
||||
int compare_hash(const void* a, const void* b)
|
||||
{
|
||||
const auto hash_a = reinterpret_cast<game::DDLHash*>(
|
||||
reinterpret_cast<size_t>(a))->hash;
|
||||
const auto hash_b = reinterpret_cast<game::DDLHash*>(
|
||||
reinterpret_cast<size_t>(b))->hash;
|
||||
|
||||
if (hash_a < hash_b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (hash_a > hash_b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
utils::memory::allocator ddl_allocator;
|
||||
|
||||
std::vector<const char*> get_stringtable_entries(const std::string& name)
|
||||
{
|
||||
std::vector<const char*> entries;
|
||||
|
||||
const auto string_table = game::DB_FindXAssetHeader(
|
||||
game::ASSET_TYPE_STRINGTABLE, name.data(), false).stringTable;
|
||||
|
||||
if (string_table == nullptr)
|
||||
{
|
||||
return entries;
|
||||
}
|
||||
|
||||
for (auto row = 0; row < string_table->rowCount; row++)
|
||||
{
|
||||
if (string_table->columnCount <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto index = (row * string_table->columnCount);
|
||||
const auto weapon = string_table->values[index].string;
|
||||
entries.push_back(ddl_allocator.duplicate_string(weapon));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
void add_entries_to_enum(game::DDLEnum* enum_, const std::vector<const char*> entries)
|
||||
{
|
||||
const auto new_size = enum_->memberCount + entries.size();
|
||||
const auto members = ddl_allocator.allocate_array<const char*>(new_size);
|
||||
const auto hash_list = ddl_allocator.allocate_array<game::DDLHash>(new_size);
|
||||
|
||||
std::memcpy(members, enum_->members, 8 * enum_->memberCount);
|
||||
std::memcpy(hash_list, enum_->hashTable.list, 8 * enum_->hashTable.count);
|
||||
|
||||
for (auto i = 0; i < entries.size(); i++)
|
||||
{
|
||||
const auto hash = utils::hook::invoke<unsigned int>(0x794FB0_b, entries[i], 0);
|
||||
const auto index = enum_->memberCount + i;
|
||||
hash_list[index].index = index;
|
||||
hash_list[index].hash = hash;
|
||||
members[index] = entries[i];
|
||||
}
|
||||
|
||||
std::qsort(hash_list, new_size, sizeof(game::DDLHash), compare_hash);
|
||||
|
||||
enum_->members = members;
|
||||
enum_->hashTable.list = hash_list;
|
||||
enum_->memberCount = static_cast<int>(new_size);
|
||||
enum_->hashTable.count = static_cast<int>(new_size);
|
||||
}
|
||||
|
||||
void load_ddl_asset_stub(game::DDLRoot** asset)
|
||||
{
|
||||
static std::unordered_set<void*> modified_enums;
|
||||
|
||||
const auto root = *asset;
|
||||
if (!root->ddlDef)
|
||||
{
|
||||
return utils::hook::invoke<void>(0x39BE20_b, root);
|
||||
}
|
||||
|
||||
auto ddl_def = root->ddlDef;
|
||||
while (ddl_def)
|
||||
{
|
||||
for (auto i = 0; i < ddl_def->enumCount; i++)
|
||||
{
|
||||
const auto enum_ = &ddl_def->enumList[i];
|
||||
if (modified_enums.contains(enum_))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((enum_->name == "WeaponStats"s || enum_->name == "Weapon"s))
|
||||
{
|
||||
static const auto weapons = get_stringtable_entries("mp/customWeapons.csv");
|
||||
add_entries_to_enum(enum_, weapons);
|
||||
modified_enums.insert(enum_);
|
||||
}
|
||||
|
||||
if (enum_->name == "AttachmentBase"s)
|
||||
{
|
||||
static const auto attachments = get_stringtable_entries("mp/customAttachments.csv");
|
||||
add_entries_to_enum(enum_, attachments);
|
||||
modified_enums.insert(enum_);
|
||||
}
|
||||
}
|
||||
|
||||
ddl_def = ddl_def->next;
|
||||
}
|
||||
|
||||
utils::hook::invoke<void>(0x39BE20_b, asset);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -137,6 +253,8 @@ namespace weapon
|
||||
|
||||
// patch attachment configstring so it will create if not found
|
||||
utils::hook::call(0x41C595_b, g_find_config_string_index_stub);
|
||||
|
||||
utils::hook::call(0x36B4D4_b, load_ddl_asset_stub);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
Reference in New Issue
Block a user