Custom weapon cac stuff + fixes

This commit is contained in:
fed
2023-01-27 00:26:05 +01:00
parent d5cbad5c81
commit f01aa5ba59
9 changed files with 623 additions and 20 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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/");
}
}
}

View File

@ -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>();
}

View File

@ -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;

View File

@ -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