maint: April update
This commit is contained in:
@ -17,7 +17,7 @@ void load_map_entities(game::MapEnts* entry) {
|
||||
// Load ent file from raw if it exists
|
||||
if (ent_file.exists()) {
|
||||
map_entities = ent_file.get_buffer();
|
||||
entry->entityString = map_entities.data();
|
||||
entry->entityString = const_cast<char*>(map_entities.c_str());
|
||||
entry->numEntityChars = static_cast<int>(map_entities.size()) + 1;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ std::string get_hw_profile_guid() {
|
||||
}
|
||||
|
||||
std::string get_protected_data() {
|
||||
std::string input = "Alter-Ware-IW4-SP-Auth";
|
||||
std::string input = "Alter-Ware-IW4x-SP-Auth";
|
||||
|
||||
DATA_BLOB data_in{}, data_out{};
|
||||
data_in.pbData = reinterpret_cast<std::uint8_t*>(input.data());
|
||||
|
@ -2,17 +2,19 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#include <version.h>
|
||||
#include <version.hpp>
|
||||
|
||||
namespace branding {
|
||||
namespace {
|
||||
#ifdef _DEBUG
|
||||
constexpr auto* BUILD_TYPE = "IW4_DEV SP";
|
||||
constexpr auto* BUILD_TYPE = "IW4x_DEV SP";
|
||||
#else
|
||||
constexpr auto* BUILD_TYPE = "IW4 SP";
|
||||
constexpr auto* BUILD_TYPE = "IW4x SP";
|
||||
#endif
|
||||
|
||||
constexpr const char* get_build_number() {
|
||||
@ -49,14 +51,13 @@ void cg_draw_version() {
|
||||
font, font_scale);
|
||||
const auto height = game::UI_TextHeight(font, font_scale);
|
||||
|
||||
// clang-format off
|
||||
game::UI_DrawText(placement, (*dvars::version)->current.string, max_chars,
|
||||
font,
|
||||
1.0f - (dvars::cg_drawVersionX->current.value +
|
||||
static_cast<float>(width)),
|
||||
1.0f - (dvars::cg_drawVersionY->current.value +
|
||||
static_cast<float>(height)),
|
||||
3, 3, font_scale, shadow_color, 0);
|
||||
game::UI_DrawText(
|
||||
placement, (*dvars::version)->current.string, max_chars, font,
|
||||
1.0f -
|
||||
(dvars::cg_drawVersionX->current.value + static_cast<float>(width)),
|
||||
1.0f -
|
||||
(dvars::cg_drawVersionY->current.value + static_cast<float>(height)),
|
||||
3, 3, font_scale, shadow_color, 0);
|
||||
game::UI_DrawText(placement, (*dvars::version)->current.string, max_chars,
|
||||
font,
|
||||
(0.0f - static_cast<float>(width)) -
|
||||
@ -64,7 +65,6 @@ void cg_draw_version() {
|
||||
(0.0f - static_cast<float>(height)) -
|
||||
dvars::cg_drawVersionY->current.value,
|
||||
3, 3, font_scale, color, 0);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void cg_draw_full_screen_debug_overlays_stub(int local_client_num) {
|
||||
@ -76,6 +76,25 @@ void cg_draw_full_screen_debug_overlays_stub(int local_client_num) {
|
||||
|
||||
utils::hook::invoke<void>(0x44BD00, local_client_num);
|
||||
}
|
||||
|
||||
game::Font_s** small_font;
|
||||
void branding_loop() {
|
||||
float color[4] = {1.0f, 1.0f, 1.0f, 0.25f};
|
||||
const auto* text = "AlterWare IW4x-SP";
|
||||
|
||||
if (!*small_font) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* const scr_place =
|
||||
game::ScrPlace_GetActivePlacement(game::LOCAL_CLIENT_0);
|
||||
const auto x = scr_place->realViewportSize[0] -
|
||||
static_cast<float>(game::R_TextWidth(text, 0, *small_font)) -
|
||||
10.0f;
|
||||
|
||||
game::R_AddCmdDrawText(text, std::numeric_limits<int>::max(), *small_font, x,
|
||||
30.0f, 1.0f, 1.0f, 0.0f, color, 3);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
@ -83,13 +102,13 @@ public:
|
||||
void post_load() override {
|
||||
utils::hook(0x46F570, get_build_number, HOOK_JUMP).install()->quick();
|
||||
utils::hook(0x60429A, dvar_set_version_string, HOOK_CALL)
|
||||
.install()
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
utils::hook::set<const char*>(0x446A48, "iw4-sp: Console");
|
||||
utils::hook::set<const char*>(0x50C110, "iw4-sp: Game");
|
||||
utils::hook::set<const char*>(0x446A48, "iw4x-sp: Console");
|
||||
utils::hook::set<const char*>(0x50C110, "iw4x-sp: Game");
|
||||
|
||||
utils::hook::set<const char*>(0x579364, "iw4-sp: " SHORTVERSION "> ");
|
||||
utils::hook::set<const char*>(0x579364, "iw4x-sp: " SHORTVERSION "> ");
|
||||
|
||||
// Com_Init_Try_Block_Function
|
||||
utils::hook::set<const char*>(0x604004, BUILD_TYPE);
|
||||
@ -100,6 +119,9 @@ public:
|
||||
utils::hook(0x57DAFF, cg_draw_full_screen_debug_overlays_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
small_font = reinterpret_cast<game::Font_s**>(0x192A0DC);
|
||||
scheduler::loop(branding_loop, scheduler::pipeline::renderer);
|
||||
}
|
||||
|
||||
static void register_branding_dvars() {
|
||||
|
@ -130,9 +130,9 @@ void execute(std::string command, const bool sync) {
|
||||
command += "\n";
|
||||
|
||||
if (sync) {
|
||||
game::Cmd_ExecuteSingleCommand(0, 0, command.data());
|
||||
game::Cmd_ExecuteSingleCommand(0, 0, command.c_str());
|
||||
} else {
|
||||
game::Cbuf_AddText(0, command.data());
|
||||
game::Cbuf_AddText(0, command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,9 @@ void com_bug_f(const command::params& params) {
|
||||
*game::logfile = 0;
|
||||
}
|
||||
|
||||
game::FS_BuildOSPath(std::filesystem::current_path().string().data(), "",
|
||||
game::FS_BuildOSPath(std::filesystem::current_path().string().c_str(), "",
|
||||
"console.log", from_ospath);
|
||||
game::FS_BuildOSPath(std::filesystem::current_path().string().data(), "",
|
||||
game::FS_BuildOSPath(std::filesystem::current_path().string().c_str(), "",
|
||||
new_file_name, to_ospath);
|
||||
const auto result = CopyFileA(from_ospath, to_ospath, 0);
|
||||
game::Com_OpenLogFile();
|
||||
|
@ -142,7 +142,7 @@ const game::dvar_t* dvar_register_string_stub(const char* name,
|
||||
const char* description) {
|
||||
auto* var = find_dvar(override::register_string_overrides, name);
|
||||
if (var) {
|
||||
value = var->value.data();
|
||||
value = var->value.c_str();
|
||||
flags = var->flags;
|
||||
}
|
||||
|
||||
|
110
src/client/component/fastfile.cpp
Normal file
110
src/client/component/fastfile.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace fastfile {
|
||||
namespace {
|
||||
bool is_using_mods() {
|
||||
return (*dvars::fs_gameDirVar) && *(*dvars::fs_gameDirVar)->current.string;
|
||||
}
|
||||
|
||||
void db_build_os_path_from_source(const char* zone_name, game::FF_DIR source,
|
||||
unsigned int size, char* filename) {
|
||||
char user_map[game::MAX_QPATH]{};
|
||||
switch (source) {
|
||||
case game::FFD_DEFAULT:
|
||||
(void)sprintf_s(filename, size, "%s\\%s%s.ff",
|
||||
std::filesystem::current_path().string().c_str(),
|
||||
game::Sys_GetMapZoneDir(zone_name), zone_name);
|
||||
break;
|
||||
case game::FFD_MOD_DIR:
|
||||
assert(is_using_mods());
|
||||
|
||||
(void)sprintf_s(filename, size, "%s\\%s\\%s.ff",
|
||||
std::filesystem::current_path().string().c_str(),
|
||||
(*dvars::fs_gameDirVar)->current.string, zone_name);
|
||||
break;
|
||||
case game::FFD_USER_MAP:
|
||||
game::I_strncpyz(user_map, zone_name, sizeof(user_map));
|
||||
|
||||
(void)sprintf_s(filename, size, "%s\\%s\\%s\\%s.ff",
|
||||
std::filesystem::current_path().string().c_str(),
|
||||
"usermaps", user_map, zone_name);
|
||||
break;
|
||||
default:
|
||||
assert(false && "inconceivable");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool db_mod_file_exists() {
|
||||
if (!*(*dvars::fs_gameDirVar)->current.string)
|
||||
return false;
|
||||
|
||||
char filename[game::MAX_OSPATH]{};
|
||||
db_build_os_path_from_source("mod", game::FFD_MOD_DIR, sizeof(filename),
|
||||
filename);
|
||||
|
||||
if (auto zone_file = game::Sys_OpenFileReliable(filename);
|
||||
zone_file != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(zone_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void db_load_x_assets_stub(game::XZoneInfo* zone_info, unsigned int zone_count,
|
||||
int sync_mode) {
|
||||
std::vector<game::XZoneInfo> zones(zone_info, zone_info + zone_count);
|
||||
|
||||
if (db_mod_file_exists()) {
|
||||
zones.emplace_back("mod", game::DB_ZONE_COMMON, 0);
|
||||
}
|
||||
|
||||
game::DB_LoadXAssets(zones.data(), zones.size(), sync_mode);
|
||||
}
|
||||
|
||||
game::Sys_File sys_create_file_stub(const char* dir, const char* filename) {
|
||||
auto result = game::Sys_CreateFile(dir, filename);
|
||||
|
||||
if (result.handle != INVALID_HANDLE_VALUE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!is_using_mods()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// .ff extension was added previously
|
||||
if (!game::I_stricmp(filename, "mod.ff") && db_mod_file_exists()) {
|
||||
char file_path[game::MAX_OSPATH]{};
|
||||
db_build_os_path_from_source("mod", game::FFD_MOD_DIR, sizeof(file_path),
|
||||
file_path);
|
||||
|
||||
result.handle = game::Sys_OpenFileReliable(file_path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
static_assert(sizeof(game::Sys_File) == 4);
|
||||
|
||||
void post_load() override {
|
||||
utils::hook(0x50B637, db_load_x_assets_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
utils::hook(0x582FA2, sys_create_file_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
};
|
||||
} // namespace fastfile
|
||||
|
||||
REGISTER_COMPONENT(fastfile::component)
|
@ -11,7 +11,7 @@ namespace filesystem {
|
||||
namespace {
|
||||
const char* sys_default_install_path_stub() {
|
||||
static auto current_path = std::filesystem::current_path().string();
|
||||
return current_path.data();
|
||||
return current_path.c_str();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -20,7 +20,7 @@ std::vector<std::string> vectored_file_list(const std::string& path,
|
||||
std::vector<std::string> file_list;
|
||||
|
||||
auto num_files = 0;
|
||||
const auto** files = game::FS_ListFiles(path.data(), extension.data(),
|
||||
const auto** files = game::FS_ListFiles(path.c_str(), extension.c_str(),
|
||||
game::FS_LIST_ALL, &num_files, 10);
|
||||
|
||||
if (files) {
|
||||
@ -46,7 +46,7 @@ file::file(std::string name, game::FsThread thread) : name_(std::move(name)) {
|
||||
|
||||
auto handle = 0;
|
||||
const auto len =
|
||||
game::FS_FOpenFileReadForThread(name_.data(), &handle, thread);
|
||||
game::FS_FOpenFileReadForThread(name_.c_str(), &handle, thread);
|
||||
|
||||
if (!handle) {
|
||||
this->valid_ = false;
|
||||
@ -73,7 +73,7 @@ class component final : public component_interface {
|
||||
public:
|
||||
void post_load() override {
|
||||
utils::hook(0x465B90, sys_default_install_path_stub, HOOK_CALL)
|
||||
.install()
|
||||
.install() // hook*
|
||||
->quick(); // Sys_CreateFile
|
||||
}
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ void g_scr_log_print() {
|
||||
void g_init_game_stub() {
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER,
|
||||
"------- Game Initialization -------\n");
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER, "gamename: iw4-sp\n");
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER, "gamename: iw4x-sp\n");
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER, "gamedate: %s\n", __DATE__);
|
||||
|
||||
if (*dvars::g_log->current.string == '\0') {
|
||||
|
@ -34,7 +34,7 @@ game::BuiltinFunction built_in_get_function_stub(const char** p_name,
|
||||
} else {
|
||||
for (const auto& [name, func] : custom_scr_funcs) {
|
||||
game::Scr_RegisterFunction(reinterpret_cast<int>(func.actionFunc),
|
||||
name.data());
|
||||
name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ game::BuiltinMethod built_in_get_method_stub(const char** p_name, int* type) {
|
||||
} else {
|
||||
for (const auto& [name, meth] : custom_scr_meths) {
|
||||
game::Scr_RegisterFunction(reinterpret_cast<int>(meth.actionFunc),
|
||||
name.data());
|
||||
name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
@ -10,23 +11,27 @@ std::vector<int> main_handles;
|
||||
std::vector<int> init_handles;
|
||||
|
||||
// Do not use C++ objects because Scr_LoadScript may longjmp
|
||||
void g_scr_load_scripts_stub() {
|
||||
// Clear handles (from previous GSC loading session)
|
||||
main_handles.clear();
|
||||
init_handles.clear();
|
||||
|
||||
void load_scripts_from_folder(const char* dir) {
|
||||
char path[MAX_PATH]{};
|
||||
char search_path[MAX_PATH]{};
|
||||
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER,
|
||||
"Scanning directory '%s' for custom GSC scripts...\n", dir);
|
||||
|
||||
strncpy_s(search_path, dir, _TRUNCATE);
|
||||
strncat_s(search_path, "/", _TRUNCATE);
|
||||
|
||||
auto num_files = 0;
|
||||
const auto** files =
|
||||
game::FS_ListFiles("scripts/", "gsc", game::FS_LIST_ALL, &num_files, 10);
|
||||
game::FS_ListFiles(search_path, "gsc", game::FS_LIST_ALL, &num_files, 10);
|
||||
|
||||
for (auto i = 0; i < num_files; ++i) {
|
||||
const auto* script_file = files[i];
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER, "Loading script %s...\n",
|
||||
script_file);
|
||||
|
||||
const auto len = sprintf_s(path, "%s/%s", "scripts", script_file);
|
||||
const auto len = sprintf_s(path, "%s/%s", dir, script_file);
|
||||
if (len == -1) {
|
||||
continue;
|
||||
}
|
||||
@ -36,12 +41,13 @@ void g_scr_load_scripts_stub() {
|
||||
|
||||
if (!game::Scr_LoadScript(path)) {
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER,
|
||||
"Script %s encountered an error while loading\n", path);
|
||||
"Script '%s.gsc' encountered an error while loading\n",
|
||||
path);
|
||||
continue;
|
||||
}
|
||||
|
||||
game::Com_Printf(game::CON_CHANNEL_SERVER,
|
||||
"Script %s.gsc loaded successfully\n", path);
|
||||
"Script '%s.gsc' loaded successfully\n", path);
|
||||
|
||||
const auto main_handle = game::Scr_GetFunctionHandle(path, "main");
|
||||
if (main_handle) {
|
||||
@ -58,6 +64,21 @@ void g_scr_load_scripts_stub() {
|
||||
game::FS_FreeFileList(files, 10);
|
||||
}
|
||||
|
||||
void g_scr_load_scripts_stub() {
|
||||
// Clear handles (from previous GSC loading session)
|
||||
main_handles.clear();
|
||||
init_handles.clear();
|
||||
|
||||
load_scripts_from_folder("scripts");
|
||||
|
||||
load_scripts_from_folder("scripts/sp");
|
||||
|
||||
// Map specific
|
||||
const auto* dir =
|
||||
utils::string::va("scripts/sp/{0}", (*dvars::sv_mapname)->current.string);
|
||||
load_scripts_from_folder(dir);
|
||||
}
|
||||
|
||||
void scr_load_level_stub() {
|
||||
for (const auto& handle : main_handles) {
|
||||
const auto id = game::Scr_ExecThread(handle, 0);
|
||||
|
@ -29,6 +29,8 @@ void cl_start_multiplayer_f() {
|
||||
const char* live_get_local_client_name_stub() {
|
||||
return game::Dvar_FindVar("name")->current.string;
|
||||
}
|
||||
|
||||
bool g_exit_after_tool_complete_stub() { return false; }
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
@ -36,8 +38,24 @@ public:
|
||||
void post_load() override {
|
||||
utils::hook(0x6042A2, sys_init_stub, HOOK_CALL).install()->quick();
|
||||
|
||||
utils::hook(0x6216CC, g_exit_after_tool_complete_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick(); // UI_LoadMenuLists
|
||||
utils::hook(0x4E638C, g_exit_after_tool_complete_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick(); // Vehicle_Create
|
||||
utils::hook(0x65F54A, g_exit_after_tool_complete_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick(); // ??
|
||||
utils::hook(0x425F6F, g_exit_after_tool_complete_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick(); // ??
|
||||
utils::hook(0x663845, g_exit_after_tool_complete_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick(); // ??
|
||||
|
||||
utils::hook(0x492EF0, live_get_local_client_name_stub, HOOK_JUMP)
|
||||
.install()
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
patch_sp();
|
||||
|
@ -136,7 +136,8 @@ void __declspec(naked) jump_check_stub() {
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) p_move_single_stub() {
|
||||
// clang-format off
|
||||
void __declspec(naked) pm_move_single_stub() {
|
||||
__asm {
|
||||
push eax;
|
||||
mov eax, dvars::pm_snapVector;
|
||||
@ -161,6 +162,7 @@ void __declspec(naked) p_move_single_stub() {
|
||||
ret;
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
void g_scr_is_sprinting(const game::scr_entref_t entref) {
|
||||
const auto* client = game::GetEntity(entref)->client;
|
||||
@ -212,7 +214,7 @@ public:
|
||||
->quick(); // Vec3Scale
|
||||
utils::hook(0x4D25E8, jump_check_stub, HOOK_JUMP).install()->quick();
|
||||
|
||||
utils::hook(0x6530C3, p_move_single_stub, HOOK_JUMP).install()->quick();
|
||||
utils::hook(0x6530C3, pm_move_single_stub, HOOK_JUMP).install()->quick();
|
||||
|
||||
gsc::add_method("IsSprinting", g_scr_is_sprinting);
|
||||
register_dvars();
|
||||
|
@ -87,9 +87,9 @@ void g_glass_update_stub() {
|
||||
execute(pipeline::server);
|
||||
}
|
||||
|
||||
void r_end_frame_stub() {
|
||||
utils::hook::invoke<void>(0x50F540);
|
||||
void ui_refresh_full_screen_stub(const int local_client_num) {
|
||||
execute(pipeline::renderer);
|
||||
utils::hook::invoke<void>(0x4EF430, local_client_num);
|
||||
}
|
||||
|
||||
void main_frame_stub() {
|
||||
@ -148,7 +148,9 @@ public:
|
||||
void post_load() override {
|
||||
utils::hook(0x4EDBDD, g_glass_update_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x49C3AF, main_frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x57DB13, r_end_frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x57DAEC, ui_refresh_full_screen_stub, HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
|
||||
void pre_destroy() override {
|
||||
|
@ -33,9 +33,10 @@ public:
|
||||
static void patch_sp() {
|
||||
// Prevent stat loading from steam
|
||||
utils::hook::set<std::uint8_t>(0x43FB33, 0xC3);
|
||||
utils::hook::nop(0x43FB33 + 1, 0x5);
|
||||
|
||||
// Steam must be running
|
||||
utils::hook::nop(0x6040A3, 30);
|
||||
utils::hook::set<std::uint8_t>(0x6040A1, 0xEB);
|
||||
|
||||
// No-Steam
|
||||
utils::hook::nop(0x4E9458, 7);
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
this->clean_up_on_error();
|
||||
|
||||
try {
|
||||
this->start_mod("iw4-sp singleplayer", 10180);
|
||||
this->start_mod("iw4x-sp singleplayer", 10180);
|
||||
} catch (const std::exception& ex) {
|
||||
printf("Steam: %s\n", ex.what());
|
||||
}
|
||||
|
@ -36,8 +36,15 @@ private:
|
||||
// Ignore missing default weapon
|
||||
utils::hook::set<std::uint8_t>(0x659DBE, 0xEB);
|
||||
|
||||
// Skip double loading when fs_game is set
|
||||
utils::hook::set<std::uint8_t>(0x43E1AD, 0xEB);
|
||||
|
||||
// Clear weapons even if fs_game is set
|
||||
utils::hook::nop(0x4C3FBF, 2); // BG_ClearWeaponDefInterna
|
||||
utils::hook::nop(0x4C3FC6, 5); // Disable BG_FreeWeaponDefStrings
|
||||
|
||||
utils::hook(0x659E00, bg_load_weapon_variant_def_fast_file_stub, HOOK_JUMP)
|
||||
.install()
|
||||
.install() // hook*
|
||||
->quick();
|
||||
// Disable warning if raw weapon file cannot be found
|
||||
utils::hook::nop(0x659730, 5);
|
||||
|
@ -35,4 +35,7 @@ const game::dvar_t** com_developer =
|
||||
reinterpret_cast<const game::dvar_t**>(0x145D648);
|
||||
const game::dvar_t** com_developer_script =
|
||||
reinterpret_cast<const game::dvar_t**>(0x145EC58);
|
||||
|
||||
const game::dvar_t** fs_gameDirVar =
|
||||
reinterpret_cast<const game::dvar_t**>(0x1956138);
|
||||
} // namespace dvars
|
||||
|
@ -30,4 +30,6 @@ extern const game::dvar_t** version;
|
||||
|
||||
extern const game::dvar_t** com_developer;
|
||||
extern const game::dvar_t** com_developer_script;
|
||||
|
||||
extern const game::dvar_t** fs_gameDirVar;
|
||||
} // namespace dvars
|
||||
|
@ -87,6 +87,12 @@ void Sys_SnapVector(float* v) {
|
||||
v[2] = std::floorf(v[2] + 0.5f);
|
||||
}
|
||||
|
||||
HANDLE Sys_OpenFileReliable(const char* filename) {
|
||||
return ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, nullptr);
|
||||
}
|
||||
|
||||
int PC_Int_Parse(int handle, int* i) {
|
||||
const static DWORD PC_Int_Parse_t = 0x62DF10;
|
||||
int result{};
|
||||
@ -135,5 +141,4 @@ void Menu_FreeItemMemory(itemDef_s* item) {
|
||||
popad;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
@ -40,6 +40,7 @@ void Sys_LockRead(FastCriticalSection* critSect);
|
||||
void Sys_UnlockRead(FastCriticalSection* critSect);
|
||||
void Sys_UnlockWrite(FastCriticalSection* critSect);
|
||||
void Sys_SnapVector(float* v);
|
||||
HANDLE Sys_OpenFileReliable(const char* filename);
|
||||
|
||||
int PC_Int_Parse(int handle, int* i);
|
||||
int PC_Float_Parse(int handle, float* f);
|
||||
@ -54,6 +55,7 @@ constexpr auto MAX_POSSIBLE_LOCAL_CLIENTS = 1;
|
||||
constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
|
||||
|
||||
constexpr auto MAX_QPATH = 64;
|
||||
constexpr auto MAX_OSPATH = 256;
|
||||
|
||||
constexpr auto MAX_OPCODE_LOOKUP_SIZE = 0x1000000;
|
||||
constexpr auto MAX_SOURCEPOS_LOOKUP_SIZE = 0x800000;
|
||||
|
@ -9,6 +9,12 @@ typedef vec_t vec2_t[2];
|
||||
typedef vec_t vec3_t[3];
|
||||
typedef vec_t vec4_t[4];
|
||||
|
||||
enum LocalClientNum_t {
|
||||
LOCAL_CLIENT_0 = 0,
|
||||
LOCAL_CLIENT_LAST = 1,
|
||||
LOCAL_CLIENT_COUNT = 1,
|
||||
};
|
||||
|
||||
struct scr_entref_t {
|
||||
unsigned __int16 entnum;
|
||||
unsigned __int16 classnum;
|
||||
@ -1293,6 +1299,44 @@ struct XAssetEntry {
|
||||
|
||||
static_assert(sizeof(XAssetEntry) == 0x10);
|
||||
|
||||
struct GfxConfiguration {
|
||||
bool inited;
|
||||
unsigned int maxClientViews;
|
||||
unsigned int maxClientRenderViews;
|
||||
unsigned int entCount;
|
||||
unsigned int entnumNone;
|
||||
unsigned int entnumOrdinaryEnd;
|
||||
int threadContextCount;
|
||||
int critSectCount;
|
||||
const char* codeFastFileName;
|
||||
const char* localizedCodeFastFileName;
|
||||
const char* uiFastFileName;
|
||||
const char* localizedUiFastFileName;
|
||||
const char* commonFastFileName;
|
||||
const char* localizedCommonFastFileName;
|
||||
const char* patchFastFileName;
|
||||
bool defaultFullscreen;
|
||||
unsigned __int16 defaultFullscreenFlags;
|
||||
int defaultMode;
|
||||
unsigned int textureMinVRamTier1;
|
||||
unsigned int textureMinVRamTier2;
|
||||
};
|
||||
|
||||
enum FF_DIR {
|
||||
FFD_DEFAULT = 0x0,
|
||||
FFD_MOD_DIR = 0x1,
|
||||
FFD_USER_MAP = 0x2,
|
||||
};
|
||||
|
||||
enum {
|
||||
DB_ZONE_COMMON = 0x1,
|
||||
DB_ZONE_UI = 0x2,
|
||||
DB_ZONE_GAME = 0x4,
|
||||
DB_ZONE_LOAD = 0x8,
|
||||
DB_ZONE_DEV = 0x10,
|
||||
DB_ZONE_TRANSIENT = 0x20,
|
||||
};
|
||||
|
||||
struct XZoneInfo {
|
||||
const char* name;
|
||||
int allocFlags;
|
||||
@ -1685,6 +1729,15 @@ struct TraceThreadInfo {
|
||||
};
|
||||
|
||||
static_assert(sizeof(TraceThreadInfo) == 0x8);
|
||||
|
||||
struct localization_t {
|
||||
char* language;
|
||||
char* strings;
|
||||
};
|
||||
|
||||
struct Sys_File {
|
||||
HANDLE handle;
|
||||
};
|
||||
} // namespace game
|
||||
|
||||
#pragma warning(pop)
|
||||
|
@ -24,6 +24,10 @@ WEAK symbol<const char*(const char* fmt, ...)> va{0x4869F0};
|
||||
// Con
|
||||
WEAK symbol<bool(const char* cmd)> Con_IsDvarCommand{0x4B6610};
|
||||
|
||||
// ScrPlace
|
||||
WEAK symbol<ScreenPlacement*(int localClientNum)> ScrPlace_GetActivePlacement{
|
||||
0x4D2A60};
|
||||
|
||||
// Sys
|
||||
WEAK symbol<void(const char* exeName)> Sys_QuitAndStartProcess{0x4D69A0};
|
||||
WEAK symbol<void(CriticalSection critSect)> Sys_EnterCriticalSection{0x4A4CD0};
|
||||
@ -37,6 +41,9 @@ WEAK symbol<bool()> Sys_IsDatabaseThread{0x4C9380};
|
||||
WEAK symbol<void(int valueIndex, void* data)> Sys_SetValue{0x483310};
|
||||
WEAK symbol<void(int msec)> Sys_Sleep{0x4CFBE0};
|
||||
WEAK symbol<void(const char* error, ...)> Sys_Error{0x40BFF0};
|
||||
WEAK symbol<const char*(const char* zoneName)> Sys_GetMapZoneDir{0x4429F0};
|
||||
WEAK symbol<Sys_File(const char* dir, const char* filename)> Sys_CreateFile{
|
||||
0x465B80};
|
||||
|
||||
WEAK symbol<short(short l)> BigShort{0x40E7E0};
|
||||
WEAK symbol<short(short l)> ShortNoSwap{0x4261A0};
|
||||
@ -254,6 +261,8 @@ WEAK symbol<int(const char* s)> Info_Validate{0x425530};
|
||||
// IW functions, could use Microsoft specific functions but who cares
|
||||
WEAK symbol<int(const char* s0, const char* s1)> I_stricmp{0x409B80};
|
||||
WEAK symbol<int(const char* s0, const char* s1, int n)> I_strnicmp{0x491E60};
|
||||
WEAK symbol<void(char* dest, const char* src, int destsize)> I_strncpyz{
|
||||
0x416920};
|
||||
|
||||
WEAK symbol<void(field_t* edit)> Field_Clear{0x45C350};
|
||||
|
||||
@ -263,6 +272,14 @@ WEAK symbol<int(const char* string)> StringTable_HashString{0x498080};
|
||||
// Vec3
|
||||
WEAK symbol<void(const float* v, float scale, const float* result)> Vec3Scale{
|
||||
0x429220};
|
||||
WEAK symbol<void(const char* text, int maxChars, Font_s* font, float x, float y,
|
||||
float xScale, float yScale, float rotation, const float* color,
|
||||
int style)>
|
||||
R_AddCmdDrawText{0x50E7A0};
|
||||
|
||||
// Renderer
|
||||
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{
|
||||
0x508960};
|
||||
|
||||
// Variables
|
||||
WEAK symbol<CmdArgs> cmd_args{0x144FED0};
|
||||
@ -318,4 +335,6 @@ WEAK symbol<uiInfo_s> uiInfoArray{0x1920470};
|
||||
WEAK symbol<void*> DB_GetXAssetSizeHandlers{0x733408};
|
||||
WEAK symbol<void*> DB_XAssetPool{0x7337F8};
|
||||
WEAK symbol<unsigned int> g_poolSize{0x733510};
|
||||
|
||||
WEAK symbol<localization_t> localization{0x19ff820};
|
||||
} // namespace game
|
||||
|
@ -121,7 +121,7 @@ void loader::load_imports(const utils::nt::library& target,
|
||||
auto* import =
|
||||
PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
function_procname = function_name.data();
|
||||
function_procname = function_name.c_str();
|
||||
}
|
||||
|
||||
if (this->import_resolver_)
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "std_include.hpp"
|
||||
#include <utils/nt.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#include "loader/binary_loader.hpp"
|
||||
@ -12,6 +11,19 @@
|
||||
#include <version.hpp>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
std::string get_current_date() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto current_time = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm local_time{};
|
||||
|
||||
(void)localtime_s(&local_time, ¤t_time);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(&local_time, "%Y%m%d_%H%M%S");
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) {
|
||||
if (exception_info->ExceptionRecord->ExceptionCode == 0x406D1388) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
@ -32,8 +44,8 @@ LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) {
|
||||
| MiniDumpWithThreadInfo;
|
||||
|
||||
CreateDirectoryA("minidumps", nullptr);
|
||||
const auto* file_name =
|
||||
utils::string::va("minidumps\\iw4-sp_{0}.dmp", SHORTVERSION);
|
||||
const auto* file_name = utils::string::va("minidumps\\iw4x-sp_{0}_{1}.dmp",
|
||||
SHORTVERSION, get_current_date());
|
||||
constexpr auto file_share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
const auto file_handle =
|
||||
CreateFileA(file_name, GENERIC_WRITE | GENERIC_READ, file_share, nullptr,
|
||||
|
@ -65,12 +65,11 @@ BEGIN
|
||||
VALUE "CompanyName", "AlterWare"
|
||||
VALUE "FileDescription", "IW4 SP client modification"
|
||||
VALUE "FileVersion", VERSION_FILE
|
||||
VALUE "InternalName", "iw4-sp"
|
||||
VALUE "InternalName", "iw4x-sp"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023 AlterWare. All rights reserved."
|
||||
VALUE "Licence", "GPLv3"
|
||||
VALUE "Info", "https://alterware.dev"
|
||||
VALUE "OriginalFilename", "iw4-sp.exe"
|
||||
VALUE "ProductName", "iw4-sp"
|
||||
VALUE "OriginalFilename", "iw4x-sp.exe"
|
||||
VALUE "ProductName", "iw4x-sp"
|
||||
VALUE "ProductVersion", VERSION_PRODUCT
|
||||
END
|
||||
END
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#define BASEGAME "spdata"
|
||||
#define CLIENT_CONFIG "iw4_sp_config.cfg"
|
||||
#define CLIENT_CONFIG "iw4x_sp_config.cfg"
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
|
@ -93,7 +93,7 @@ unsigned __int64 user::RequestEncryptedAppTicket(void* pUserData,
|
||||
// Generate the authentication ticket
|
||||
const auto id = this->GetSteamID();
|
||||
|
||||
auth_ticket = "iw4-sp";
|
||||
auth_ticket = "iw4x-sp";
|
||||
auth_ticket.resize(32);
|
||||
auth_ticket.append(static_cast<char*>(pUserData), cbUserData);
|
||||
auth_ticket.append(reinterpret_cast<const char*>(&id.bits), sizeof(id.bits));
|
||||
|
@ -96,7 +96,7 @@ namespace zip {
|
||||
namespace {
|
||||
bool add_file(zipFile& zip_file, const std::string& filename,
|
||||
const std::string& data) {
|
||||
if (zipOpenNewFileInZip(zip_file, filename.data(), nullptr, nullptr, 0,
|
||||
if (zipOpenNewFileInZip(zip_file, filename.c_str(), nullptr, nullptr, 0,
|
||||
nullptr, 0, nullptr, Z_DEFLATED,
|
||||
Z_BEST_COMPRESSION) != ZIP_OK) {
|
||||
return false;
|
||||
@ -117,13 +117,13 @@ bool archive::write(const std::string& filename, const std::string& comment) {
|
||||
io::write_file(filename, {});
|
||||
io::remove_file(filename);
|
||||
|
||||
auto* zip_file = zipOpen(filename.data(), 0);
|
||||
auto* zip_file = zipOpen(filename.c_str(), 0);
|
||||
if (zip_file == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto _ = gsl::finally([&zip_file, &comment]() {
|
||||
zipClose(zip_file, comment.empty() ? nullptr : comment.data());
|
||||
zipClose(zip_file, comment.empty() ? nullptr : comment.c_str());
|
||||
});
|
||||
|
||||
for (const auto& file : this->files_) {
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
namespace utils::io {
|
||||
bool remove_file(const std::string& file) {
|
||||
return DeleteFileA(file.data()) == TRUE;
|
||||
return DeleteFileA(file.c_str()) == TRUE;
|
||||
}
|
||||
|
||||
bool move_file(const std::string& src, const std::string& target) {
|
||||
return MoveFileA(src.data(), target.data()) == TRUE;
|
||||
return MoveFileA(src.c_str(), target.c_str()) == TRUE;
|
||||
}
|
||||
|
||||
bool file_exists(const std::string& file) {
|
||||
|
@ -54,7 +54,7 @@ void* memory::allocate(const std::size_t length) {
|
||||
|
||||
char* memory::duplicate_string(const std::string& string) {
|
||||
const auto new_string = allocate_array<char>(string.size() + 1);
|
||||
std::memcpy(new_string, string.data(), string.size());
|
||||
std::memcpy(new_string, string.c_str(), string.size());
|
||||
return new_string;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace utils::nt {
|
||||
library library::load(const std::string& name) {
|
||||
return library(LoadLibraryA(name.data()));
|
||||
return library(LoadLibraryA(name.c_str()));
|
||||
}
|
||||
|
||||
library library::load(const std::filesystem::path& path) {
|
||||
@ -19,7 +19,7 @@ library library::get_by_address(void* address) {
|
||||
library::library() { this->module_ = GetModuleHandleA(nullptr); }
|
||||
|
||||
library::library(const std::string& name) {
|
||||
this->module_ = GetModuleHandleA(name.data());
|
||||
this->module_ = GetModuleHandleA(name.c_str());
|
||||
}
|
||||
|
||||
library::library(const HMODULE handle) { this->module_ = handle; }
|
||||
@ -161,7 +161,7 @@ void** library::get_iat_entry(const std::string& module_name,
|
||||
while (import_descriptor->Name) {
|
||||
if (!_stricmp(
|
||||
reinterpret_cast<char*>(this->get_ptr() + import_descriptor->Name),
|
||||
module_name.data())) {
|
||||
module_name.c_str())) {
|
||||
auto* original_thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(
|
||||
import_descriptor->OriginalFirstThunk + this->get_ptr());
|
||||
auto* thunk_data = reinterpret_cast<PIMAGE_THUNK_DATA>(
|
||||
@ -192,7 +192,7 @@ void** library::get_iat_entry(const std::string& module_name,
|
||||
}
|
||||
|
||||
void library::set_dll_directory(const std::string& directory) {
|
||||
SetDllDirectoryA(directory.data());
|
||||
SetDllDirectoryA(directory.c_str());
|
||||
}
|
||||
|
||||
std::string library::get_dll_directory() {
|
||||
@ -245,7 +245,7 @@ void launch_process(const std::string& process,
|
||||
char current_dir[MAX_PATH];
|
||||
GetCurrentDirectoryA(sizeof(current_dir), current_dir);
|
||||
|
||||
CreateProcessA(process.data(), const_cast<char*>(command_line.data()),
|
||||
CreateProcessA(process.c_str(), const_cast<char*>(command_line.c_str()),
|
||||
nullptr, nullptr, false, NULL, nullptr, current_dir,
|
||||
&startup_info, &process_info);
|
||||
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
template <typename T> T get_proc(const std::string& process) const {
|
||||
if (!this->is_valid())
|
||||
T{};
|
||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
|
||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process.c_str()));
|
||||
}
|
||||
|
||||
template <typename T> std::function<T> get(const std::string& process) const {
|
||||
|
@ -23,7 +23,7 @@ static const char* va(std::string_view fmt, Args&&... args) {
|
||||
|
||||
(sanitize_format_args(args), ...);
|
||||
std::vformat(fmt, std::make_format_args(args...)).swap(va_buffer);
|
||||
return va_buffer.data();
|
||||
return va_buffer.c_str();
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& s, char delim);
|
||||
|
@ -22,7 +22,7 @@ bool set_name(const HANDLE t, const std::string& name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SUCCEEDED(set_description(t, string::convert(name).data()));
|
||||
return SUCCEEDED(set_description(t, string::convert(name).c_str()));
|
||||
}
|
||||
|
||||
bool set_name(const DWORD id, const std::string& name) {
|
||||
|
Reference in New Issue
Block a user