Custom font & material support
This commit is contained in:
parent
2dc8a30ea6
commit
964ceb5be9
56
src/client/component/filesystem.cpp
Normal file
56
src/client/component/filesystem.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
|
||||||
|
namespace filesystem
|
||||||
|
{
|
||||||
|
std::unordered_set<std::string>& get_search_paths()
|
||||||
|
{
|
||||||
|
static std::unordered_set<std::string> search_paths{};
|
||||||
|
return search_paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string read_file(const std::string& path)
|
||||||
|
{
|
||||||
|
for (const auto& search_path : get_search_paths())
|
||||||
|
{
|
||||||
|
const auto path_ = search_path + "/" + path;
|
||||||
|
if (utils::io::file_exists(path_))
|
||||||
|
{
|
||||||
|
return utils::io::read_file(path_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_file(const std::string& path, std::string* data)
|
||||||
|
{
|
||||||
|
for (const auto& search_path : get_search_paths())
|
||||||
|
{
|
||||||
|
const auto path_ = search_path + "/" + path;
|
||||||
|
if (utils::io::read_file(path_, data))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
get_search_paths().insert(".");
|
||||||
|
get_search_paths().insert("h2-mod");
|
||||||
|
get_search_paths().insert("data");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(filesystem::component)
|
8
src/client/component/filesystem.hpp
Normal file
8
src/client/component/filesystem.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace filesystem
|
||||||
|
{
|
||||||
|
std::unordered_set<std::string>& get_search_paths();
|
||||||
|
std::string read_file(const std::string& path);
|
||||||
|
bool read_file(const std::string& path, std::string* data);
|
||||||
|
}
|
131
src/client/component/fonts.cpp
Normal file
131
src/client/component/fonts.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "fonts.hpp"
|
||||||
|
#include "game_console.hpp"
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/memory.hpp>
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/image.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
namespace fonts
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct font_data_t
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, game::TTF*> fonts;
|
||||||
|
std::unordered_map<std::string, std::string> raw_fonts;
|
||||||
|
};
|
||||||
|
|
||||||
|
utils::concurrency::container<font_data_t> font_data;
|
||||||
|
|
||||||
|
game::TTF* create_font(const std::string& name, const std::string& data)
|
||||||
|
{
|
||||||
|
const auto font = utils::memory::get_allocator()->allocate<game::TTF>();
|
||||||
|
font->name = utils::memory::get_allocator()->duplicate_string(name);
|
||||||
|
font->buffer = utils::memory::get_allocator()->duplicate_string(data);
|
||||||
|
font->len = static_cast<int>(data.size());
|
||||||
|
font->fontFace = 0;
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_font(game::TTF* font)
|
||||||
|
{
|
||||||
|
utils::memory::get_allocator()->free(font->buffer);
|
||||||
|
utils::memory::get_allocator()->free(font->name);
|
||||||
|
utils::memory::get_allocator()->free(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::TTF* load_font(const std::string& name)
|
||||||
|
{
|
||||||
|
return font_data.access<game::TTF*>([&](font_data_t& data_) -> game::TTF*
|
||||||
|
{
|
||||||
|
if (const auto i = data_.fonts.find(name); i != data_.fonts.end())
|
||||||
|
{
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data{};
|
||||||
|
if (const auto i = data_.raw_fonts.find(name); i != data_.raw_fonts.end())
|
||||||
|
{
|
||||||
|
data = i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.empty() && !filesystem::read_file(name, &data))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto material = create_font(name, data);
|
||||||
|
data_.fonts[name] = material;
|
||||||
|
|
||||||
|
return material;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
game::TTF* try_load_font(const std::string& name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return load_font(name);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
game_console::print(game_console::con_type_error, "Failed to load font %s: %s\n", name.data(), e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::TTF* db_find_xasset_header_stub(game::XAssetType type, const char* name, int create_default)
|
||||||
|
{
|
||||||
|
auto result = try_load_font(name);
|
||||||
|
if (result == nullptr)
|
||||||
|
{
|
||||||
|
result = game::DB_FindXAssetHeader(type, name, create_default).ttf;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const std::string& name, const std::string& data)
|
||||||
|
{
|
||||||
|
font_data.access([&](font_data_t& data_)
|
||||||
|
{
|
||||||
|
data_.raw_fonts[name] = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
font_data.access([&](font_data_t& data_)
|
||||||
|
{
|
||||||
|
for (auto& font : data_.fonts)
|
||||||
|
{
|
||||||
|
free_font(font.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_.fonts.clear();
|
||||||
|
utils::hook::set<int>(0x14EE3ACB8, 0); // reset registered font count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
utils::hook::call(0x140747096, db_find_xasset_header_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(fonts::component)
|
7
src/client/component/fonts.hpp
Normal file
7
src/client/component/fonts.hpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace fonts
|
||||||
|
{
|
||||||
|
void add(const std::string& name, const std::string& data);
|
||||||
|
void clear();
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
|
||||||
#include "images.hpp"
|
#include "images.hpp"
|
||||||
#include "game_console.hpp"
|
#include "game_console.hpp"
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
@ -29,7 +32,7 @@ namespace images
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.empty() && !utils::io::read_file(utils::string::va("images/%s.png", image->name), &data))
|
if (data.empty() && !filesystem::read_file(utils::string::va("images/%s.png", image->name), &data))
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
200
src/client/component/materials.cpp
Normal file
200
src/client/component/materials.cpp
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "materials.hpp"
|
||||||
|
#include "game_console.hpp"
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/memory.hpp>
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/image.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
namespace materials
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::hook::detour db_material_streaming_fail_hook;
|
||||||
|
utils::hook::detour material_register_handle_hook;
|
||||||
|
utils::hook::detour db_get_material_index_hook;
|
||||||
|
|
||||||
|
struct material_data_t
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, game::Material*> materials;
|
||||||
|
std::unordered_map<std::string, std::string> images;
|
||||||
|
};
|
||||||
|
|
||||||
|
char constant_table[0x20] = {};
|
||||||
|
|
||||||
|
utils::concurrency::container<material_data_t> material_data;
|
||||||
|
|
||||||
|
game::GfxImage* setup_image(game::GfxImage* image, const utils::image& raw_image)
|
||||||
|
{
|
||||||
|
image->imageFormat = 0x1000003;
|
||||||
|
image->resourceSize = -1;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA data{};
|
||||||
|
data.SysMemPitch = raw_image.get_width() * 4;
|
||||||
|
data.SysMemSlicePitch = data.SysMemPitch * raw_image.get_height();
|
||||||
|
data.pSysMem = raw_image.get_buffer();
|
||||||
|
|
||||||
|
game::Image_Setup(image, raw_image.get_width(), raw_image.get_height(), image->depth, image->numElements,
|
||||||
|
image->imageFormat, DXGI_FORMAT_R8G8B8A8_UNORM, 0, image->name, &data);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Material* create_material(const std::string& name, const std::string& data)
|
||||||
|
{
|
||||||
|
const auto white = *reinterpret_cast<game::Material**>(0x141B09208);
|
||||||
|
|
||||||
|
const auto material = utils::memory::get_allocator()->allocate<game::Material>();
|
||||||
|
const auto texture_table = utils::memory::get_allocator()->allocate<game::MaterialTextureDef>();
|
||||||
|
const auto image = utils::memory::get_allocator()->allocate<game::GfxImage>();
|
||||||
|
|
||||||
|
std::memcpy(material, white, sizeof(game::Material));
|
||||||
|
std::memcpy(texture_table, white->textureTable, sizeof(game::MaterialTextureDef));
|
||||||
|
std::memcpy(image, white->textureTable->u.image, sizeof(game::GfxImage));
|
||||||
|
|
||||||
|
material->constantTable = &constant_table;
|
||||||
|
material->name = utils::memory::get_allocator()->duplicate_string(name);
|
||||||
|
image->name = material->name;
|
||||||
|
|
||||||
|
material->textureTable = texture_table;
|
||||||
|
material->textureTable->u.image = setup_image(image, data);
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_material(game::Material* material)
|
||||||
|
{
|
||||||
|
material->textureTable->u.image->textures.___u0.map->Release();
|
||||||
|
material->textureTable->u.image->textures.shaderView->Release();
|
||||||
|
utils::memory::get_allocator()->free(material->textureTable->u.image);
|
||||||
|
utils::memory::get_allocator()->free(material->textureTable);
|
||||||
|
utils::memory::get_allocator()->free(material->name);
|
||||||
|
utils::memory::get_allocator()->free(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Material* load_material(const std::string& name)
|
||||||
|
{
|
||||||
|
return material_data.access<game::Material*>([&](material_data_t& data_) -> game::Material*
|
||||||
|
{
|
||||||
|
if (const auto i = data_.materials.find(name); i != data_.materials.end())
|
||||||
|
{
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data{};
|
||||||
|
if (const auto i = data_.images.find(name); i != data_.images.end())
|
||||||
|
{
|
||||||
|
data = i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.empty() && !filesystem::read_file(utils::string::va("materials/%s.png", name.data()), &data))
|
||||||
|
{
|
||||||
|
data_.materials[name] = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto material = create_material(name, data);
|
||||||
|
data_.materials[name] = material;
|
||||||
|
|
||||||
|
return material;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Material* try_load_material(const std::string& name)
|
||||||
|
{
|
||||||
|
if (name == "white")
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return load_material(name);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
game_console::print(game_console::con_type_error, "Failed to load material %s: %s\n", name.data(), e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Material* material_register_handle_stub(const char* name)
|
||||||
|
{
|
||||||
|
auto result = try_load_material(name);
|
||||||
|
if (result == nullptr)
|
||||||
|
{
|
||||||
|
result = material_register_handle_hook.invoke<game::Material*>(name);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int db_material_streaming_fail_stub(game::Material* material)
|
||||||
|
{
|
||||||
|
if (material->constantTable == &constant_table)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return db_material_streaming_fail_hook.invoke<int>(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int db_get_material_index_stub(game::Material* material)
|
||||||
|
{
|
||||||
|
if (material->constantTable == &constant_table)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return db_get_material_index_hook.invoke<unsigned int>(material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const std::string& name, const std::string& data)
|
||||||
|
{
|
||||||
|
material_data.access([&](material_data_t& data_)
|
||||||
|
{
|
||||||
|
data_.images[name] = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
material_data.access([&](material_data_t& data_)
|
||||||
|
{
|
||||||
|
for (auto& material : data_.materials)
|
||||||
|
{
|
||||||
|
if (material.second == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_material(material.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_.materials.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
material_register_handle_hook.create(game::Material_RegisterHandle.get(), material_register_handle_stub);
|
||||||
|
db_material_streaming_fail_hook.create(0x14041D140, db_material_streaming_fail_stub);
|
||||||
|
db_get_material_index_hook.create(0x140413BC0, db_get_material_index_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(materials::component)
|
7
src/client/component/materials.hpp
Normal file
7
src/client/component/materials.hpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace materials
|
||||||
|
{
|
||||||
|
void add(const std::string& name, const std::string& data);
|
||||||
|
void clear();
|
||||||
|
}
|
@ -6,12 +6,35 @@
|
|||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "game_console.hpp"
|
#include "game_console.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
#include "materials.hpp"
|
||||||
|
#include "fonts.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
|
|
||||||
namespace mods
|
namespace mods
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::hook::detour db_release_xassets_hook;
|
||||||
|
|
||||||
|
void db_release_xassets_stub()
|
||||||
|
{
|
||||||
|
materials::clear();
|
||||||
|
fonts::clear();
|
||||||
|
db_release_xassets_hook.invoke<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void restart()
|
||||||
|
{
|
||||||
|
scheduler::once([]()
|
||||||
|
{
|
||||||
|
game::Com_Shutdown("");
|
||||||
|
}, scheduler::pipeline::main);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,6 +45,8 @@ namespace mods
|
|||||||
utils::io::create_directory("mods");
|
utils::io::create_directory("mods");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_release_xassets_hook.create(0x140416A80, db_release_xassets_stub);
|
||||||
|
|
||||||
command::add("loadmod", [](const command::params& params)
|
command::add("loadmod", [](const command::params& params)
|
||||||
{
|
{
|
||||||
if (params.size() < 2)
|
if (params.size() < 2)
|
||||||
@ -30,7 +55,7 @@ namespace mods
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::game::SV_Loaded())
|
if (!game::Com_InFrontend())
|
||||||
{
|
{
|
||||||
game_console::print(game_console::con_type_error, "Cannot load mod while in-game!\n");
|
game_console::print(game_console::con_type_error, "Cannot load mod while in-game!\n");
|
||||||
game::CG_GameMessage(0, "^1Cannot unload mod while in-game!");
|
game::CG_GameMessage(0, "^1Cannot unload mod while in-game!");
|
||||||
@ -46,12 +71,9 @@ namespace mods
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filesystem::get_search_paths().insert(path);
|
||||||
game::mod_folder = path;
|
game::mod_folder = path;
|
||||||
|
restart();
|
||||||
scheduler::once([]()
|
|
||||||
{
|
|
||||||
command::execute("lui_restart", true);
|
|
||||||
}, scheduler::pipeline::renderer);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
command::add("unloadmod", [](const command::params& params)
|
command::add("unloadmod", [](const command::params& params)
|
||||||
@ -62,7 +84,7 @@ namespace mods
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::game::SV_Loaded())
|
if (!game::Com_InFrontend())
|
||||||
{
|
{
|
||||||
game_console::print(game_console::con_type_error, "Cannot unload mod while in-game!\n");
|
game_console::print(game_console::con_type_error, "Cannot unload mod while in-game!\n");
|
||||||
game::CG_GameMessage(0, "^1Cannot unload mod while in-game!");
|
game::CG_GameMessage(0, "^1Cannot unload mod while in-game!");
|
||||||
@ -70,12 +92,9 @@ namespace mods
|
|||||||
}
|
}
|
||||||
|
|
||||||
game_console::print(game_console::con_type_info, "Unloading mod %s\n", game::mod_folder.data());
|
game_console::print(game_console::con_type_info, "Unloading mod %s\n", game::mod_folder.data());
|
||||||
|
filesystem::get_search_paths().erase(game::mod_folder);
|
||||||
game::mod_folder.clear();
|
game::mod_folder.clear();
|
||||||
|
restart();
|
||||||
scheduler::once([]()
|
|
||||||
{
|
|
||||||
command::execute("lui_restart", true);
|
|
||||||
}, scheduler::pipeline::renderer);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
|
|
||||||
#include "../../../component/notifies.hpp"
|
#include "../../../component/notifies.hpp"
|
||||||
|
#include "../../../component/filesystem.hpp"
|
||||||
#include "../execution.hpp"
|
#include "../execution.hpp"
|
||||||
|
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
@ -49,13 +50,9 @@ namespace scripting::lua::engine
|
|||||||
|
|
||||||
load_generic_script();
|
load_generic_script();
|
||||||
|
|
||||||
load_scripts("scripts/");
|
for (const auto& path : filesystem::get_search_paths())
|
||||||
load_scripts("h2-mod/scripts/");
|
|
||||||
load_scripts("data/scripts/");
|
|
||||||
|
|
||||||
if (!game::mod_folder.empty())
|
|
||||||
{
|
{
|
||||||
load_scripts(utils::string::va("%s/scripts/", game::mod_folder.data()));
|
load_scripts(path + "/scripts/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,11 +126,90 @@ namespace game
|
|||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GfxImage;
|
||||||
|
|
||||||
|
union MaterialTextureDefInfo
|
||||||
|
{
|
||||||
|
GfxImage* image;
|
||||||
|
void* water;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaterialTextureDef
|
||||||
|
{
|
||||||
|
unsigned int nameHash;
|
||||||
|
char nameStart;
|
||||||
|
char nameEnd;
|
||||||
|
char samplerState;
|
||||||
|
char semantic;
|
||||||
|
MaterialTextureDefInfo u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaterialPass
|
||||||
|
{
|
||||||
|
void* vertexShader;
|
||||||
|
void* vertexDecl;
|
||||||
|
void* hullShader;
|
||||||
|
void* domainShader;
|
||||||
|
void* pixelShader;
|
||||||
|
char pixelOutputMask;
|
||||||
|
char perPrimArgCount;
|
||||||
|
char perObjArgCount;
|
||||||
|
char stableArgCount;
|
||||||
|
unsigned __int16 perPrimArgSize;
|
||||||
|
unsigned __int16 perObjArgSize;
|
||||||
|
unsigned __int16 stableArgSize;
|
||||||
|
char zone;
|
||||||
|
char perPrimConstantBuffer;
|
||||||
|
char perObjConstantBuffer;
|
||||||
|
char stableConstantBuffer;
|
||||||
|
unsigned int customBufferFlags;
|
||||||
|
char customSamplerFlags;
|
||||||
|
char precompiledIndex;
|
||||||
|
char stageConfig;
|
||||||
|
void* args;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaterialTechnique
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
unsigned __int16 flags;
|
||||||
|
unsigned __int16 passCount;
|
||||||
|
MaterialPass passArray[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaterialTechniqueSet
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
unsigned __int16 flags;
|
||||||
|
char worldVertFormat;
|
||||||
|
char preDisplacementOnlyCount;
|
||||||
|
MaterialTechnique* techniques[309];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxStateBits
|
||||||
|
{
|
||||||
|
unsigned int loadBits[3];
|
||||||
|
char zone;
|
||||||
|
char depthStencilState[11];
|
||||||
|
char blendState;
|
||||||
|
char rasterizerState;
|
||||||
|
};
|
||||||
|
|
||||||
struct Material
|
struct Material
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
|
char __pad0[0x124];
|
||||||
|
char textureCount;
|
||||||
|
char __pad1[0xB];
|
||||||
|
MaterialTechniqueSet* techniqueSet;
|
||||||
|
MaterialTextureDef* textureTable;
|
||||||
|
void* constantTable;
|
||||||
|
GfxStateBits* stateBitsTable;
|
||||||
|
char __pad2[0x118];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(Material) == 0x270);
|
||||||
|
|
||||||
struct point
|
struct point
|
||||||
{
|
{
|
||||||
float x;
|
float x;
|
||||||
@ -678,6 +757,14 @@ namespace game
|
|||||||
const char* buffer;
|
const char* buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TTF
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
int len;
|
||||||
|
const char* buffer;
|
||||||
|
int fontFace;
|
||||||
|
};
|
||||||
|
|
||||||
union XAssetHeader
|
union XAssetHeader
|
||||||
{
|
{
|
||||||
void* data;
|
void* data;
|
||||||
@ -687,6 +774,7 @@ namespace game
|
|||||||
ScriptFile* scriptfile;
|
ScriptFile* scriptfile;
|
||||||
StringTable* stringTable;
|
StringTable* stringTable;
|
||||||
LuaFile* luaFile;
|
LuaFile* luaFile;
|
||||||
|
TTF* ttf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XAsset
|
struct XAsset
|
||||||
|
@ -27,7 +27,9 @@ namespace game
|
|||||||
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x14059ABA0};
|
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x14059ABA0};
|
||||||
|
|
||||||
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{0x1405A2D80};
|
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{0x1405A2D80};
|
||||||
|
WEAK symbol<void(char const* finalMessage)> Com_Shutdown{0x1405A62C0};
|
||||||
WEAK symbol<void()> Com_Quit_f{0x1405A50D0};
|
WEAK symbol<void()> Com_Quit_f{0x1405A50D0};
|
||||||
|
WEAK symbol<bool()> Com_InFrontend{0x140328BD0};
|
||||||
WEAK symbol<void()> Quit{0x1405A52A0};
|
WEAK symbol<void()> Quit{0x1405A52A0};
|
||||||
|
|
||||||
WEAK symbol<void(XAssetType type, void(__cdecl* func)(game::XAssetHeader, void*), const void* inData, bool includeOverride)>
|
WEAK symbol<void(XAssetType type, void(__cdecl* func)(game::XAssetHeader, void*), const void* inData, bool includeOverride)>
|
||||||
@ -117,6 +119,7 @@ namespace game
|
|||||||
WEAK symbol<Font_s*(const char* font, int size)> R_RegisterFont{0x140746FE0};
|
WEAK symbol<Font_s*(const char* font, int size)> R_RegisterFont{0x140746FE0};
|
||||||
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x1407472A0};
|
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x1407472A0};
|
||||||
WEAK symbol<void()> R_SyncRenderThread{0x14076E7D0};
|
WEAK symbol<void()> R_SyncRenderThread{0x14076E7D0};
|
||||||
|
WEAK symbol<void()> R_WaitWorkerCmds{0x140794330};
|
||||||
WEAK symbol<void(const void* obj, void* pose, unsigned int entnum, unsigned int renderFxFlags, float* lightingOrigin,
|
WEAK symbol<void(const void* obj, void* pose, unsigned int entnum, unsigned int renderFxFlags, float* lightingOrigin,
|
||||||
float materialTime, __int64 a7, __int64 a8)> R_AddDObjToScene{0x140775C40};
|
float materialTime, __int64 a7, __int64 a8)> R_AddDObjToScene{0x140775C40};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "../../../component/scheduler.hpp"
|
#include "../../../component/scheduler.hpp"
|
||||||
#include "../../../component/ui_scripting.hpp"
|
#include "../../../component/ui_scripting.hpp"
|
||||||
|
#include "../../../component/filesystem.hpp"
|
||||||
|
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
@ -73,13 +74,9 @@ namespace ui_scripting::lua::engine
|
|||||||
|
|
||||||
load_code(updater_script);
|
load_code(updater_script);
|
||||||
|
|
||||||
load_scripts("ui_scripts/");
|
for (const auto& path : filesystem::get_search_paths())
|
||||||
load_scripts("h2-mod/ui_scripts/");
|
|
||||||
load_scripts("data/ui_scripts/");
|
|
||||||
|
|
||||||
if (!game::mod_folder.empty())
|
|
||||||
{
|
{
|
||||||
load_scripts(utils::string::va("%s/ui_scripts/", game::mod_folder.data()));
|
load_scripts(path + "/ui_scripts/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user