feat: admen abooze
This commit is contained in:
@@ -103,9 +103,7 @@ namespace arxan
|
|||||||
|
|
||||||
BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context)
|
BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context)
|
||||||
{
|
{
|
||||||
if (!game::environment::is_sp()
|
if (game::dwGetLogOnStatus(0) == game::DW_LIVE_CONNECTED && context->ContextFlags == CONTEXT_DEBUG_REGISTERS)
|
||||||
&& game::dwGetLogOnStatus(0) == game::DW_LIVE_CONNECTED
|
|
||||||
&& context->ContextFlags == CONTEXT_DEBUG_REGISTERS)
|
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -142,8 +140,6 @@ namespace arxan
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
utils::hook::jump(0x1404FE1E0, 0x1404FE2D0); // idk
|
utils::hook::jump(0x1404FE1E0, 0x1404FE2D0); // idk
|
||||||
utils::hook::jump(0x140558C20, 0x140558CB0); // dwNetPump
|
utils::hook::jump(0x140558C20, 0x140558CB0); // dwNetPump
|
||||||
utils::hook::jump(0x140591850, 0x1405918E0); // dwLobbyPump
|
utils::hook::jump(0x140591850, 0x1405918E0); // dwLobbyPump
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ namespace weapons
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
// Kill Scr_PrecacheItem (We are going to do this from code)
|
// Kill Scr_PrecacheItem (We are going to do this from code)
|
||||||
utils::hook::nop(0x1403BDB10, 4);
|
utils::hook::nop(0x1403BDB10, 4);
|
||||||
utils::hook::set<std::uint8_t>(0x1403BDB10, 0xC3);
|
utils::hook::set<std::uint8_t>(0x1403BDB10, 0xC3);
|
||||||
|
|||||||
@@ -272,23 +272,14 @@ namespace auth
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Patch steam id bit check
|
// Patch steam id bit check
|
||||||
if (game::environment::is_sp())
|
utils::hook::jump(0x140585410, 0x140585466);
|
||||||
{
|
utils::hook::jump(0x140142252, 0x140142293);
|
||||||
utils::hook::jump(0x1404BF3F0, 0x1404BF446);
|
utils::hook::jump(0x140142334, 0x140142389);
|
||||||
utils::hook::jump(0x1404C02AF, 0x1404C02F0);
|
utils::hook::jump(0x1405864EF, 0x140586530);
|
||||||
utils::hook::jump(0x1404C07F4, 0x1404C0842);
|
utils::hook::jump(0x140586A80, 0x140586AC6);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
utils::hook::jump(0x140585410, 0x140585466);
|
|
||||||
utils::hook::jump(0x140142252, 0x140142293);
|
|
||||||
utils::hook::jump(0x140142334, 0x140142389);
|
|
||||||
utils::hook::jump(0x1405864EF, 0x140586530);
|
|
||||||
utils::hook::jump(0x140586A80, 0x140586AC6);
|
|
||||||
|
|
||||||
utils::hook::jump(0x140479636, get_direct_connect_stub(), true);
|
utils::hook::jump(0x140479636, get_direct_connect_stub(), true);
|
||||||
utils::hook::call(0x1402C4F8E, send_connect_data_stub);
|
utils::hook::call(0x1402C4F8E, send_connect_data_stub);
|
||||||
}
|
|
||||||
|
|
||||||
command::add("guid", []() -> void
|
command::add("guid", []() -> void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,13 +115,13 @@ namespace binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write all bindings to config file
|
// write all bindings to config file
|
||||||
utils::hook::call(SELECT_VALUE(0x14023DF2B, 0x1402C465B), key_write_bindings_to_buffer_stub);
|
utils::hook::call(0x1402C465B, key_write_bindings_to_buffer_stub);
|
||||||
|
|
||||||
// links a custom command to an index
|
// links a custom command to an index
|
||||||
utils::hook::jump(SELECT_VALUE(0x14023D6E0, 0x1402C3E50), key_get_binding_for_cmd_stub);
|
utils::hook::jump(0x1402C3E50, key_get_binding_for_cmd_stub);
|
||||||
|
|
||||||
// execute custom binds
|
// execute custom binds
|
||||||
cl_execute_key_hook.create(SELECT_VALUE(0x140239970, 0x1402BF0E0), &cl_execute_key_stub);
|
cl_execute_key_hook.create(0x1402BF0E0, &cl_execute_key_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,11 +160,6 @@ namespace bots
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_bot_name_hook.create(game::SV_BotGetRandomName, get_random_bot_name);
|
get_bot_name_hook.create(game::SV_BotGetRandomName, get_random_bot_name);
|
||||||
|
|
||||||
command::add("spawnBot", [](const command::params& params)
|
command::add("spawnBot", [](const command::params& params)
|
||||||
|
|||||||
@@ -40,9 +40,8 @@ namespace branding
|
|||||||
|
|
||||||
localized_strings::override("LUA_MENU_LEGAL_COPYRIGHT", "iw6-mod: " VERSION " by AlterWare.\n");
|
localized_strings::override("LUA_MENU_LEGAL_COPYRIGHT", "iw6-mod: " VERSION " by AlterWare.\n");
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1403BDABA, 0x140414424), dvar_set_string_stub);
|
utils::hook::call(0x140414424, dvar_set_string_stub);
|
||||||
ui_get_formatted_build_number_hook.create(
|
ui_get_formatted_build_number_hook.create(0x1404D7C00, ui_get_formatted_build_number_stub);
|
||||||
SELECT_VALUE(0x140415FD0, 0x1404D7C00), ui_get_formatted_build_number_stub);
|
|
||||||
|
|
||||||
scheduler::loop([]()
|
scheduler::loop([]()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,11 +28,6 @@ namespace bullet
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dvars::bg_surfacePenetration = game::Dvar_RegisterFloat("bg_surfacePenetration", 0.0f,
|
dvars::bg_surfacePenetration = game::Dvar_RegisterFloat("bg_surfacePenetration", 0.0f,
|
||||||
0.0f, std::numeric_limits<float>::max(), game::DVAR_FLAG_SAVED,
|
0.0f, std::numeric_limits<float>::max(), game::DVAR_FLAG_SAVED,
|
||||||
"Set to a value greater than 0 to override the surface penetration depth");
|
"Set to a value greater than 0 to override the surface penetration depth");
|
||||||
|
|||||||
@@ -126,11 +126,11 @@ namespace colors
|
|||||||
|
|
||||||
if (index == '8')
|
if (index == '8')
|
||||||
{
|
{
|
||||||
*color = *reinterpret_cast<DWORD*>(SELECT_VALUE(0x145FFD958, 0x1480E85BC));
|
*color = *reinterpret_cast<DWORD*>(0x1480E85BC);
|
||||||
}
|
}
|
||||||
else if (index == '9')
|
else if (index == '9')
|
||||||
{
|
{
|
||||||
*color = *reinterpret_cast<DWORD*>(SELECT_VALUE(0x145FFD95C, 0x1480E85C0));
|
*color = *reinterpret_cast<DWORD*>(0x1480E85C0);
|
||||||
}
|
}
|
||||||
else if (index == ':')
|
else if (index == ':')
|
||||||
{
|
{
|
||||||
@@ -138,7 +138,7 @@ namespace colors
|
|||||||
}
|
}
|
||||||
else if (index == ';')
|
else if (index == ';')
|
||||||
{
|
{
|
||||||
*color = *reinterpret_cast<DWORD*>(SELECT_VALUE(0x145FFD964, 0x1480E85C8));
|
*color = *reinterpret_cast<DWORD*>(0x1480E85C8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -157,25 +157,22 @@ namespace colors
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!game::environment::is_sp())
|
// allows colored name in-game
|
||||||
{
|
utils::hook::call(0x1403881CF, com_clean_name_stub);
|
||||||
// allows colored name in-game
|
utils::hook::call(0x140388224, com_clean_name_stub);
|
||||||
utils::hook::call(0x1403881CF, com_clean_name_stub);
|
|
||||||
utils::hook::call(0x140388224, com_clean_name_stub);
|
|
||||||
|
|
||||||
// don't apply colors to overhead names
|
// don't apply colors to overhead names
|
||||||
utils::hook::call(0x14025CE79, cl_get_client_name_and_clan_tag_stub);
|
utils::hook::call(0x14025CE79, cl_get_client_name_and_clan_tag_stub);
|
||||||
|
|
||||||
// don't apply colors to overhead names of agents (like dogs or juggernauts)
|
// don't apply colors to overhead names of agents (like dogs or juggernauts)
|
||||||
// hook Com_sprintf in CL_GetAgentName
|
// hook Com_sprintf in CL_GetAgentName
|
||||||
utils::hook::call(0x1402CF760, com_sprintf_stub);
|
utils::hook::call(0x1402CF760, com_sprintf_stub);
|
||||||
|
|
||||||
// patch I_CleanStr
|
// patch I_CleanStr
|
||||||
utils::hook::jump(0x1404F63C0, i_clean_str_stub);
|
utils::hook::jump(0x1404F63C0, i_clean_str_stub);
|
||||||
}
|
|
||||||
|
|
||||||
// force new colors
|
// force new colors
|
||||||
utils::hook::jump(SELECT_VALUE(0x14055DCC0, 0x14062AE80), rb_lookup_color_stub);
|
utils::hook::jump(0x14062AE80, rb_lookup_color_stub);
|
||||||
|
|
||||||
// add colors
|
// add colors
|
||||||
add(0, 0, 0); // 0 - Black
|
add(0, 0, 0); // 0 - Black
|
||||||
|
|||||||
@@ -253,16 +253,9 @@ namespace command
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
utils::hook::call(0x14041213C, &parse_commandline_stub);
|
||||||
{
|
|
||||||
add_sp_commands();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
utils::hook::call(0x14041213C, &parse_commandline_stub);
|
|
||||||
|
|
||||||
add_mp_commands();
|
add_mp_commands();
|
||||||
}
|
|
||||||
add_commands_generic();
|
add_commands_generic();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,93 +442,6 @@ namespace command
|
|||||||
execute(dvar->current.string);
|
execute(dvar->current.string);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_sp_commands()
|
|
||||||
{
|
|
||||||
add("god", []
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::sp::g_entities[0].flags ^= game::FL_GODMODE;
|
|
||||||
game::CG_GameMessage(0, utils::string::va("godmode %s", game::sp::g_entities[0].flags & game::FL_GODMODE ? "^2on" : "^1off"));
|
|
||||||
});
|
|
||||||
|
|
||||||
add("notarget", []
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::sp::g_entities[0].flags ^= game::FL_NOTARGET;
|
|
||||||
game::CG_GameMessage(0, utils::string::va("notarget %s", game::sp::g_entities[0].flags & game::FL_NOTARGET ? "^2on" : "^1off"));
|
|
||||||
});
|
|
||||||
|
|
||||||
add("noclip", []
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::sp::g_entities[0].client->flags ^= 1;
|
|
||||||
game::CG_GameMessage(0, utils::string::va("noclip %s", game::sp::g_entities[0].client->flags & 1 ? "^2on" : "^1off"));
|
|
||||||
});
|
|
||||||
|
|
||||||
add("ufo", []
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::sp::g_entities[0].client->flags ^= 2;
|
|
||||||
game::CG_GameMessage(0, utils::string::va("ufo %s", game::sp::g_entities[0].client->flags & 2 ? "^2on" : "^1off"));
|
|
||||||
});
|
|
||||||
|
|
||||||
add("give", [](const params& params)
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.size() < 2)
|
|
||||||
{
|
|
||||||
game::CG_GameMessage(0, "You did not specify a weapon name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ps = game::SV_GetPlayerstateForClientNum(0);
|
|
||||||
auto wp = game::G_GetWeaponForName(params.get(1));
|
|
||||||
if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0))
|
|
||||||
{
|
|
||||||
game::G_InitializeAmmo(ps, wp, 0);
|
|
||||||
game::G_SelectWeapon(0, wp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add("take", [](const params& params)
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.size() < 2)
|
|
||||||
{
|
|
||||||
game::CG_GameMessage(0, "You did not specify a weapon name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ps = game::SV_GetPlayerstateForClientNum(0);
|
|
||||||
auto wp = game::G_GetWeaponForName(params.get(1));
|
|
||||||
game::G_TakePlayerWeapon(ps, wp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_mp_commands()
|
static void add_mp_commands()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace console
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Redirect input (]command)
|
// Redirect input (]command)
|
||||||
utils::hook::jump(SELECT_VALUE(0x14043DFA0, 0x140502A80), append_text);
|
utils::hook::jump(0x140502A80, append_text);
|
||||||
|
|
||||||
utils::hook::jump(printf, print_stub);
|
utils::hook::jump(printf, print_stub);
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ namespace console
|
|||||||
|
|
||||||
HWND get_window()
|
HWND get_window()
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<HWND*>((SELECT_VALUE(0x145A7B490, 0x147AD1DB0)));
|
return *reinterpret_cast<HWND*>(0x147AD1DB0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_title(std::string title)
|
void set_title(std::string title)
|
||||||
@@ -241,7 +241,7 @@ namespace console
|
|||||||
|
|
||||||
SetWindowPos(get_window(), nullptr, rect.left, rect.top, width, height, 0);
|
SetWindowPos(get_window(), nullptr, rect.left, rect.top, width, height, 0);
|
||||||
|
|
||||||
auto* const logo_window = *reinterpret_cast<HWND*>(SELECT_VALUE(0x145A7B4A0, 0x147AD1DC0));
|
auto* const logo_window = *reinterpret_cast<HWND*>(0x147AD1DC0);
|
||||||
SetWindowPos(logo_window, nullptr, 5, 5, width - 25, 60, 0);
|
SetWindowPos(logo_window, nullptr, 5, 5, width - 25, 60, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace cursor
|
|||||||
{
|
{
|
||||||
// This is the legacy cursor
|
// This is the legacy cursor
|
||||||
// TODO: Find the new cursor drawing...
|
// TODO: Find the new cursor drawing...
|
||||||
utils::hook::call(SELECT_VALUE(0x14040117E, 0x1404BB119), draw_cursor_stub);
|
utils::hook::call(0x1404BB119, draw_cursor_stub);
|
||||||
|
|
||||||
scheduler::loop([]()
|
scheduler::loop([]()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ namespace demonware
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::jump(SELECT_VALUE(0x140602230, 0x1406F54D0), bd_logger_stub);
|
utils::hook::jump(0x1406F54D0, bd_logger_stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace discord
|
|||||||
|
|
||||||
if (!game::CL_IsCgameInitialized())
|
if (!game::CL_IsCgameInitialized())
|
||||||
{
|
{
|
||||||
discord_presence.details = game::environment::is_sp() ? "Singleplayer" : "Multiplayer";
|
discord_presence.details = "Multiplayer";
|
||||||
discord_presence.state = "Main Menu";
|
discord_presence.state = "Main Menu";
|
||||||
|
|
||||||
discord_presence.partySize = 0;
|
discord_presence.partySize = 0;
|
||||||
@@ -47,8 +47,6 @@ namespace discord
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
const auto* gametype = game::UI_LocalizeGametype(game::Dvar_FindVar("ui_gametype")->current.string);
|
const auto* gametype = game::UI_LocalizeGametype(game::Dvar_FindVar("ui_gametype")->current.string);
|
||||||
const auto* map = game::UI_LocalizeMapname(game::Dvar_FindVar("ui_mapname")->current.string);
|
const auto* map = game::UI_LocalizeMapname(game::Dvar_FindVar("ui_mapname")->current.string);
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,6 @@ namespace dvar_cheats
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
utils::hook::nop(0x1404F0D13, 4); // let our stub handle zero-source sets
|
utils::hook::nop(0x1404F0D13, 4); // let our stub handle zero-source sets
|
||||||
utils::hook::jump(0x1404F0D1A, dvar_flag_checks_stub, true); // check extra dvar flags when setting values
|
utils::hook::jump(0x1404F0D1A, dvar_flag_checks_stub, true); // check extra dvar flags when setting values
|
||||||
|
|
||||||
|
|||||||
@@ -143,15 +143,16 @@ namespace fastfiles
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
db_try_load_x_file_internal_hook.create(SELECT_VALUE(0x140275850, 0x1403237F0), &db_try_load_x_file_internal);
|
db_try_load_x_file_internal_hook.create(0x1403237F0, &db_try_load_x_file_internal);
|
||||||
|
|
||||||
db_find_x_asset_header_hook.create(game::DB_FindXAssetHeader, db_find_x_asset_header_stub);
|
db_find_x_asset_header_hook.create(game::DB_FindXAssetHeader, db_find_x_asset_header_stub);
|
||||||
dvars::g_dump_scripts = game::Dvar_RegisterBool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts to binary format");
|
dvars::g_dump_scripts = game::Dvar_RegisterBool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts to binary format");
|
||||||
dvars::g_dump_string_tables = game::Dvar_RegisterBool("g_dumpStringTables", false, game::DVAR_FLAG_NONE, "Dump CSV files");
|
dvars::g_dump_string_tables = game::Dvar_RegisterBool("g_dumpStringTables", false, game::DVAR_FLAG_NONE, "Dump CSV files");
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1402752DF, 0x140156350), p_mem_free_stub);
|
utils::hook::call(0x140156350, p_mem_free_stub);
|
||||||
utils::hook::call(SELECT_VALUE(0x140276004, 0x140324259), p_mem_free_stub);
|
utils::hook::call(0x140324259, p_mem_free_stub);
|
||||||
|
|
||||||
|
// who asked for this this ?
|
||||||
command::add("materiallist", [](const command::params& params)
|
command::add("materiallist", [](const command::params& params)
|
||||||
{
|
{
|
||||||
game::DB_EnumXAssets_FastFile(game::ASSET_TYPE_MATERIAL, [](const game::XAssetHeader header, void*)
|
game::DB_EnumXAssets_FastFile(game::ASSET_TYPE_MATERIAL, [](const game::XAssetHeader header, void*)
|
||||||
@@ -163,17 +164,14 @@ namespace fastfiles
|
|||||||
}, nullptr, false);
|
}, nullptr, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!game::environment::is_sp())
|
reallocate_asset_pool(game::ASSET_TYPE_WEAPON, 320);
|
||||||
{
|
|
||||||
reallocate_asset_pool(game::ASSET_TYPE_WEAPON, 320);
|
|
||||||
|
|
||||||
// Fixes ("Exceeded limit of 16 'font' assets.") new steam files use a 32 font pool (2026)
|
// Fixes ("Exceeded limit of 16 'font' assets.") new steam files use a 32 font pool (2026)
|
||||||
reallocate_asset_pool(game::ASSET_TYPE_FONT, 32);
|
reallocate_asset_pool(game::ASSET_TYPE_FONT, 32);
|
||||||
|
|
||||||
// Allow loading of unsigned fastfiles
|
// Allow loading of unsigned fastfiles
|
||||||
utils::hook::set<uint8_t>(0x1402FBF23, 0xEB); // DB_LoadXFile
|
utils::hook::set<uint8_t>(0x1402FBF23, 0xEB); // DB_LoadXFile
|
||||||
utils::hook::nop(0x1402FC445, 2); // DB_SetFileLoadCompressor
|
utils::hook::nop(0x1402FC445, 2); // DB_SetFileLoadCompressor
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,29 +275,18 @@ namespace filesystem
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Set fs_basegame
|
// Set fs_basegame
|
||||||
utils::hook::inject(SELECT_VALUE(0x14041C053, 0x1404DDA13), "iw6");
|
utils::hook::inject(0x1404DDA13, "iw6");
|
||||||
|
|
||||||
#ifndef INJECT_HOST_AS_LIB
|
#ifndef INJECT_HOST_AS_LIB
|
||||||
utils::hook::jump(SELECT_VALUE(0x1404351B0, 0x1404F96C0), sys_default_install_path_stub);
|
utils::hook::jump(0x1404F96C0, sys_default_install_path_stub);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
utils::hook::call(0x1404DD704, fs_startup_stub);
|
||||||
{
|
utils::hook::call(0x1404DDB43, fs_startup_stub);
|
||||||
utils::hook::call(0x14041B744, fs_startup_stub);
|
|
||||||
|
|
||||||
utils::hook::call(0x14041CD00, register_custom_path_stub);
|
utils::hook::call(0x1404DE550, register_custom_path_stub);
|
||||||
utils::hook::call(0x14041CD20, register_custom_path_stub);
|
utils::hook::call(0x1404DE570, register_custom_path_stub);
|
||||||
utils::hook::call(0x14041CD5F, register_custom_path_stub);
|
utils::hook::call(0x1404DE5AF, register_custom_path_stub);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
utils::hook::call(0x1404DD704, fs_startup_stub);
|
|
||||||
utils::hook::call(0x1404DDB43, fs_startup_stub);
|
|
||||||
|
|
||||||
utils::hook::call(0x1404DE550, register_custom_path_stub);
|
|
||||||
utils::hook::call(0x1404DE570, register_custom_path_stub);
|
|
||||||
utils::hook::call(0x1404DE5AF, register_custom_path_stub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace fps
|
|||||||
|
|
||||||
perf_calc_fps(&cg_perf, cg_perf.frame_ms);
|
perf_calc_fps(&cg_perf, cg_perf.frame_ms);
|
||||||
|
|
||||||
utils::hook::invoke<void>(SELECT_VALUE(0x1405806E0, 0x140658E30));
|
utils::hook::invoke<void>(0x140658E30);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cg_draw_fps()
|
void cg_draw_fps()
|
||||||
@@ -167,10 +167,10 @@ namespace fps
|
|||||||
|
|
||||||
// fps setup
|
// fps setup
|
||||||
cg_perf.perf_start = std::chrono::high_resolution_clock::now();
|
cg_perf.perf_start = std::chrono::high_resolution_clock::now();
|
||||||
utils::hook::call(SELECT_VALUE(0x140242C11, 0x1402CF457), &perf_update);
|
utils::hook::call(0x1402CF457, &perf_update);
|
||||||
|
|
||||||
// change cg_drawfps flags to saved
|
// change cg_drawfps flags to saved
|
||||||
utils::hook::call(SELECT_VALUE(0x1401F400A, 0x140272B98), &cg_draw_fps_register_stub);
|
utils::hook::call(0x140272B98, &cg_draw_fps_register_stub);
|
||||||
|
|
||||||
cg_drawPing = game::Dvar_RegisterInt("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, "Draw ping");
|
cg_drawPing = game::Dvar_RegisterInt("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, "Draw ping");
|
||||||
|
|
||||||
|
|||||||
@@ -63,11 +63,6 @@ namespace game_log
|
|||||||
public:
|
public:
|
||||||
void post_load() override
|
void post_load() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::set<game::BuiltinFunction>(0x1409E8A20, gscr_log_print);
|
utils::hook::set<game::BuiltinFunction>(0x1409E8A20, gscr_log_print);
|
||||||
|
|
||||||
scheduler::once([]
|
scheduler::once([]
|
||||||
|
|||||||
@@ -65,30 +65,6 @@ namespace gameplay
|
|||||||
a.jmp(0x140383796);
|
a.jmp(0x140383796);
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto pm_bouncing_stub_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
const auto no_bounce = a.newLabel();
|
|
||||||
const auto loc_14046ED26 = a.newLabel();
|
|
||||||
|
|
||||||
a.push(rax);
|
|
||||||
|
|
||||||
a.mov(rax, qword_ptr(reinterpret_cast<int64_t>(&dvars::pm_bouncing)));
|
|
||||||
a.mov(al, byte_ptr(rax, 0x10));
|
|
||||||
a.cmp(ptr(rbp, -0x40), al);
|
|
||||||
|
|
||||||
a.pop(rax);
|
|
||||||
a.jz(no_bounce);
|
|
||||||
a.jmp(0x14046EC7E);
|
|
||||||
|
|
||||||
a.bind(no_bounce);
|
|
||||||
a.cmp(ptr(rbp, -0x80), r13d);
|
|
||||||
a.jnz(loc_14046ED26);
|
|
||||||
a.jmp(0x14046EC6C);
|
|
||||||
|
|
||||||
a.bind(loc_14046ED26);
|
|
||||||
a.jmp(0x14046ED26);
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto pm_bouncing_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
const auto pm_bouncing_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
{
|
{
|
||||||
const auto no_bounce = a.newLabel();
|
const auto no_bounce = a.newLabel();
|
||||||
@@ -327,21 +303,13 @@ namespace gameplay
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Implement bouncing dvar
|
// Implement bouncing dvar
|
||||||
if (game::environment::is_sp())
|
utils::hook::jump(0x140228FFF, pm_bouncing_stub_mp, true);
|
||||||
{
|
|
||||||
utils::hook::nop(0x14046EC5C, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::jump(
|
|
||||||
SELECT_VALUE(0x14046EC5C, 0x140228FFF), SELECT_VALUE(pm_bouncing_stub_sp, pm_bouncing_stub_mp), true);
|
|
||||||
dvars::pm_bouncing = game::Dvar_RegisterBool("pm_bouncing", false,
|
dvars::pm_bouncing = game::Dvar_RegisterBool("pm_bouncing", false,
|
||||||
game::DVAR_FLAG_REPLICATED, "Enable bouncing");
|
game::DVAR_FLAG_REPLICATED, "Enable bouncing");
|
||||||
|
|
||||||
dvars::player_sustainAmmo = game::Dvar_RegisterBool("player_sustainAmmo", false,
|
dvars::player_sustainAmmo = game::Dvar_RegisterBool("player_sustainAmmo", false,
|
||||||
game::DVAR_FLAG_REPLICATED, "Firing weapon will not decrease clip ammo.");
|
game::DVAR_FLAG_REPLICATED, "Firing weapon will not decrease clip ammo.");
|
||||||
pm_weapon_use_ammo_hook.create(SELECT_VALUE(0x140479640, 0x140238A90), &pm_weapon_use_ammo_stub);
|
pm_weapon_use_ammo_hook.create(0x140238A90, &pm_weapon_use_ammo_stub);
|
||||||
|
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
// Implement player ejection dvar
|
// Implement player ejection dvar
|
||||||
dvars::g_playerEjection = game::Dvar_RegisterBool("g_playerEjection", true, game::DVAR_FLAG_REPLICATED, "Flag whether player ejection is on or off");
|
dvars::g_playerEjection = game::Dvar_RegisterBool("g_playerEjection", true, game::DVAR_FLAG_REPLICATED, "Flag whether player ejection is on or off");
|
||||||
|
|||||||
@@ -303,11 +303,11 @@ namespace gsc
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
scr_emit_function_hook.create(SELECT_VALUE(0x1403D3350, 0x14042E150), &scr_emit_function_stub);
|
scr_emit_function_hook.create(0x14042E150, &scr_emit_function_stub);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1403D32E4, 0x14042E0E4), compile_error_stub); // LinkFile
|
utils::hook::call(0x14042E0E4, compile_error_stub); // LinkFile
|
||||||
utils::hook::call(SELECT_VALUE(0x1403D3338, 0x14042E138), compile_error_stub); // LinkFile
|
utils::hook::call(0x14042E138, compile_error_stub); // LinkFile
|
||||||
utils::hook::call(SELECT_VALUE(0x1403D342A, 0x14042E22B), find_variable_stub); // Scr_EmitFunction
|
utils::hook::call(0x14042E22B, find_variable_stub); // Scr_EmitFunction
|
||||||
|
|
||||||
// Restore basic error messages to scr functions
|
// Restore basic error messages to scr functions
|
||||||
utils::hook::jump(game::Scr_GetObject, scr_get_object);
|
utils::hook::jump(game::Scr_GetObject, scr_get_object);
|
||||||
@@ -317,16 +317,13 @@ namespace gsc
|
|||||||
utils::hook::jump(game::Scr_GetInt, scr_get_int);
|
utils::hook::jump(game::Scr_GetInt, scr_get_int);
|
||||||
utils::hook::jump(game::Scr_GetFloat, scr_get_float);
|
utils::hook::jump(game::Scr_GetFloat, scr_get_float);
|
||||||
|
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403DE150, 0x1404390B0), scr_get_pointer_type);
|
utils::hook::jump(0x1404390B0, scr_get_pointer_type);
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403DE320, 0x140439280), scr_get_type);
|
utils::hook::jump(0x140439280, scr_get_type);
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403DE390, 0x1404392F0), scr_get_type_name);
|
utils::hook::jump(0x1404392F0, scr_get_type_name);
|
||||||
|
|
||||||
if (game::environment::is_mp())
|
utils::hook::call(0x14038A4F7, player_cmd_set_client_dvar_is_valid_name);
|
||||||
{
|
utils::hook::call(0x14038A52F, player_cmd_set_client_dvar_server_dvar);
|
||||||
utils::hook::call(0x14038A4F7, player_cmd_set_client_dvar_is_valid_name);
|
utils::hook::call(0x14038A53A, player_cmd_set_client_dvar_non_writable_dvar);
|
||||||
utils::hook::call(0x14038A52F, player_cmd_set_client_dvar_server_dvar);
|
|
||||||
utils::hook::call(0x14038A53A, player_cmd_set_client_dvar_non_writable_dvar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
|
|
||||||
console::warn("******* script runtime error ********\n");
|
console::warn("******* script runtime error ********\n");
|
||||||
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(SELECT_VALUE(0x1455BE740, 0x144D57840));
|
const auto opcode_id = *reinterpret_cast<std::uint8_t*>(0x144D57840);
|
||||||
|
|
||||||
const std::string error = gsc_error_msg.has_value() ? std::format(": {}", gsc_error_msg.value()) : std::string();
|
const std::string error = gsc_error_msg.has_value() ? std::format(": {}", gsc_error_msg.value()) : std::string();
|
||||||
|
|
||||||
@@ -360,21 +360,21 @@ namespace gsc
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::set<game::BuiltinFunction>(SELECT_VALUE(0x14086F468, 0x1409E6CE8), scr_print);
|
utils::hook::set<game::BuiltinFunction>(0x1409E6CE8, scr_print);
|
||||||
utils::hook::set<game::BuiltinFunction>(SELECT_VALUE(0x14086F480, 0x1409E6D00), scr_print_ln);
|
utils::hook::set<game::BuiltinFunction>(0x1409E6D00, scr_print_ln);
|
||||||
|
|
||||||
utils::hook::set<std::uint32_t>(SELECT_VALUE(0x1403D353B + 1, 0x14042E33B + 1), 0x1000); // Scr_RegisterFunction
|
utils::hook::set<std::uint32_t>(0x14042E33B + 1, 0x1000); // Scr_RegisterFunction
|
||||||
|
|
||||||
utils::hook::set<std::uint32_t>(SELECT_VALUE(0x1403D3542 + 4, 0x14042E342 + 4), RVA(&func_table)); // Scr_RegisterFunction
|
utils::hook::set<std::uint32_t>(0x14042E342 + 4, RVA(&func_table)); // Scr_RegisterFunction
|
||||||
// utils::hook::set<std::uint32_t>(SELECT_VALUE(0x1403E0BDD + 3, 0x14043BBBE + 3), RVA(&func_table)); // VM_Execute_0
|
// utils::hook::set<std::uint32_t>(0x14043BBBE + 3, RVA(&func_table)); // VM_Execute_0
|
||||||
utils::hook::inject(SELECT_VALUE(0x1403D38E4 + 3, 0x14042E734 + 3), &func_table); // Scr_BeginLoadScripts
|
utils::hook::inject(0x14042E734 + 3, &func_table); // Scr_BeginLoadScripts
|
||||||
|
|
||||||
utils::hook::nop(SELECT_VALUE(0x1403E0BDD + 5, 0x14043BBBE + 5), 2);
|
utils::hook::nop(0x14043BBBE + 5, 2);
|
||||||
utils::hook::call(SELECT_VALUE(0x1403E0BDD, 0x14043BBBE), vm_call_builtin_function);
|
utils::hook::call(0x14043BBBE, vm_call_builtin_function);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1403D391F, 0x14042E76F), scr_get_function_stub);
|
utils::hook::call(0x14042E76F, scr_get_function_stub);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1403E1ED0, 0x14043CEB1), vm_error_stub);
|
utils::hook::call(0x14043CEB1, vm_error_stub);
|
||||||
|
|
||||||
add_function("replacefunc", []
|
add_function("replacefunc", []
|
||||||
{
|
{
|
||||||
@@ -392,11 +392,6 @@ namespace gsc
|
|||||||
command::execute(cmd);
|
command::execute(cmd);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::set<game::BuiltinFunction>(0x1409E6E38, assert_ex_cmd);
|
utils::hook::set<game::BuiltinFunction>(0x1409E6E38, assert_ex_cmd);
|
||||||
utils::hook::set<game::BuiltinFunction>(0x1409E6E50, assert_msg_cmd);
|
utils::hook::set<game::BuiltinFunction>(0x1409E6E50, assert_msg_cmd);
|
||||||
utils::hook::set<game::BuiltinFunction>(0x1409E6E20, assert_cmd);
|
utils::hook::set<game::BuiltinFunction>(0x1409E6E20, assert_cmd);
|
||||||
|
|||||||
@@ -224,26 +224,15 @@ namespace gsc
|
|||||||
load(base_dir);
|
load(base_dir);
|
||||||
|
|
||||||
const auto* map_name = game::Dvar_FindVar("mapname");
|
const auto* map_name = game::Dvar_FindVar("mapname");
|
||||||
|
|
||||||
|
const std::filesystem::path game_folder = "mp";
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
load(base_dir / game_folder);
|
||||||
{
|
|
||||||
const std::filesystem::path game_folder = "sp";
|
|
||||||
|
|
||||||
load(base_dir / game_folder);
|
load(base_dir / game_folder / map_name->current.string);
|
||||||
|
|
||||||
load(base_dir / game_folder / map_name->current.string);
|
const auto* game_type = game::Dvar_FindVar("g_gametype");
|
||||||
}
|
load(base_dir / game_folder / game_type->current.string);
|
||||||
else
|
|
||||||
{
|
|
||||||
const std::filesystem::path game_folder = "mp";
|
|
||||||
|
|
||||||
load(base_dir / game_folder);
|
|
||||||
|
|
||||||
load(base_dir / game_folder / map_name->current.string);
|
|
||||||
|
|
||||||
const auto* game_type = game::Dvar_FindVar("g_gametype");
|
|
||||||
load(base_dir / game_folder / game_type->current.string);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int db_is_x_asset_default(game::XAssetType type, const char* name)
|
int db_is_x_asset_default(game::XAssetType type, const char* name)
|
||||||
@@ -369,14 +358,14 @@ namespace gsc
|
|||||||
return {{}, script_data};
|
return {{}, script_data};
|
||||||
});
|
});
|
||||||
|
|
||||||
utils::hook::invoke<void>(SELECT_VALUE(0x1403D3860, 0x14042E6B0));
|
utils::hook::invoke<void>(0x14042E6B0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scr_end_load_scripts_stub()
|
void scr_end_load_scripts_stub()
|
||||||
{
|
{
|
||||||
gsc_ctx->cleanup();
|
gsc_ctx->cleanup();
|
||||||
|
|
||||||
utils::hook::invoke<void>(SELECT_VALUE(0x140603C00, 0x14042E7E0));
|
utils::hook::invoke<void>(0x14042E7E0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,17 +397,17 @@ namespace gsc
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
dvars::com_developer = reinterpret_cast<game::dvar_t**>(SELECT_VALUE(0x141603850, 0x1419A9700));
|
dvars::com_developer = reinterpret_cast<game::dvar_t**>(0x1419A9700);
|
||||||
|
|
||||||
// Load our scripts with an uncompressed stack
|
// Load our scripts with an uncompressed stack
|
||||||
utils::hook::call(SELECT_VALUE(0x1403DC8F0, 0x140437940), db_get_raw_buffer_stub);
|
utils::hook::call(0x140437940, db_get_raw_buffer_stub);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x14032D1E0, 0x1403CCED9), scr_begin_load_scripts_stub); // GScr_LoadScripts
|
utils::hook::call(0x1403CCED9, scr_begin_load_scripts_stub); // GScr_LoadScripts
|
||||||
utils::hook::call(SELECT_VALUE(0x14032D345, 0x1403CD08D), scr_end_load_scripts_stub); // GScr_LoadScripts
|
utils::hook::call(0x1403CD08D, scr_end_load_scripts_stub); // GScr_LoadScripts
|
||||||
|
|
||||||
// ProcessScript
|
// ProcessScript
|
||||||
utils::hook::call(SELECT_VALUE(0x1403DC887, 0x1404378D7), find_script);
|
utils::hook::call(0x1404378D7, find_script);
|
||||||
utils::hook::call(SELECT_VALUE(0x1403DC897, 0x1404378E7), db_is_x_asset_default);
|
utils::hook::call(0x1404378E7, db_is_x_asset_default);
|
||||||
|
|
||||||
dvars::com_developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments");
|
dvars::com_developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments");
|
||||||
|
|
||||||
@@ -430,21 +419,12 @@ namespace gsc
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
// GScr_LoadScripts
|
||||||
{
|
utils::hook::call(0x1403CD009, gscr_load_game_type_script_stub);
|
||||||
utils::hook::call(0x14034996F, g_scr_load_script_and_label_stub);
|
|
||||||
|
|
||||||
utils::hook::call(0x140316591, scr_load_level_singleplayer_stub);
|
// Exec script handles
|
||||||
}
|
utils::hook::call(0x14039F64E, g_load_structs_stub);
|
||||||
else
|
utils::hook::call(0x14039F653, scr_load_level_multiplayer_stub);
|
||||||
{
|
|
||||||
// GScr_LoadScripts
|
|
||||||
utils::hook::call(0x1403CD009, gscr_load_game_type_script_stub);
|
|
||||||
|
|
||||||
// Exec script handles
|
|
||||||
utils::hook::call(0x14039F64E, g_load_structs_stub);
|
|
||||||
utils::hook::call(0x14039F653, scr_load_level_multiplayer_stub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ namespace input
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl_char_event_hook.create(SELECT_VALUE(0x14023CE50, 0x1402C2AE0), cl_char_event_stub);
|
cl_char_event_hook.create(0x1402C2AE0, cl_char_event_stub);
|
||||||
cl_key_event_hook.create(SELECT_VALUE(0x14023D070, 0x1402C2CE0), cl_key_event_stub);
|
cl_key_event_hook.create(0x1402C2CE0, cl_key_event_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace localized_strings
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Change some localized strings
|
// Change some localized strings
|
||||||
seh_string_ed_get_string_hook.create(SELECT_VALUE(0x1403F42D0, 0x1404A5F60), &seh_string_ed_get_string);
|
seh_string_ed_get_string_hook.create(0x1404A5F60, &seh_string_ed_get_string);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ namespace logger
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make havok script's print function actually print
|
// Make havok script's print function actually print
|
||||||
utils::hook::jump(SELECT_VALUE(0x1406283A4, 0x140732184), print);
|
utils::hook::jump(0x140732184, print);
|
||||||
|
|
||||||
logger_dev = game::Dvar_RegisterBool("logger_dev", false, game::DVAR_FLAG_NONE, "Print dev stuff");
|
logger_dev = game::Dvar_RegisterBool("logger_dev", false, game::DVAR_FLAG_NONE, "Print dev stuff");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,17 +168,12 @@ namespace mods
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
dvars::fs_gameDirVar = reinterpret_cast<game::dvar_t**>(SELECT_VALUE(0x145856D38, 0x147876000));
|
dvars::fs_gameDirVar = reinterpret_cast<game::dvar_t**>(0x147876000);
|
||||||
|
|
||||||
// Remove DVAR_INIT from fs_game
|
// Remove DVAR_INIT from fs_game
|
||||||
utils::hook::set<std::uint32_t>(SELECT_VALUE(0x14041C085 + 2, 0x1404DDA45 + 2), SELECT_VALUE(game::DVAR_FLAG_NONE, game::DVAR_FLAG_SERVERINFO));
|
utils::hook::set<std::uint32_t>(0x1404DDA45 + 2, game::DVAR_FLAG_SERVERINFO);
|
||||||
|
|
||||||
utils::hook::inject(SELECT_VALUE(0x14041C097 + 3, 0x1404DDA57 + 3), &fs_game_dir_domain_func);
|
utils::hook::inject(0x1404DDA57 + 3, &fs_game_dir_domain_func);
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't load eng_ + patch_ with loadzone
|
// Don't load eng_ + patch_ with loadzone
|
||||||
utils::hook::nop(0x1403217B1, 15);
|
utils::hook::nop(0x1403217B1, 15);
|
||||||
|
|||||||
@@ -210,11 +210,6 @@ namespace network
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// redirect dw_sendto to raw socket
|
// redirect dw_sendto to raw socket
|
||||||
utils::hook::jump(0x140501A00, dw_send_to_stub);
|
utils::hook::jump(0x140501A00, dw_send_to_stub);
|
||||||
|
|
||||||
|
|||||||
@@ -63,12 +63,10 @@ namespace notifies
|
|||||||
const auto* guid = game::SV_GetGuid(client_num);
|
const auto* guid = game::SV_GetGuid(client_num);
|
||||||
const auto* name = game::mp::svs_clients[client_num].name;
|
const auto* name = game::mp::svs_clients[client_num].name;
|
||||||
|
|
||||||
game_log::g_log_printf("%s;%s;%i;%s;%s\n",
|
game_log::g_log_printf("%s;%s;%i;%s;%s\n", params.get(0), guid,
|
||||||
params.get(0),
|
|
||||||
guid,
|
|
||||||
client_num,
|
client_num,
|
||||||
name,
|
name,
|
||||||
message.data()
|
message.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
}, scheduler::pipeline::server);
|
}, scheduler::pipeline::server);
|
||||||
@@ -126,7 +124,7 @@ namespace notifies
|
|||||||
a.lea(eax, dword_ptr(r15, -0x17));
|
a.lea(eax, dword_ptr(r15, -0x17));
|
||||||
a.mov(dword_ptr(rbp, 0x60), r15d);
|
a.mov(dword_ptr(rbp, 0x60), r15d);
|
||||||
|
|
||||||
a.jmp(SELECT_VALUE(0x1403DF5B3, 0x14043A593));
|
a.jmp(0x14043A593);
|
||||||
|
|
||||||
a.bind(replace);
|
a.bind(replace);
|
||||||
|
|
||||||
@@ -174,7 +172,7 @@ namespace notifies
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403DF5A4, 0x14043A584), utils::hook::assemble(vm_execute_stub), true);
|
utils::hook::jump(0x14043A584, utils::hook::assemble(vm_execute_stub), true);
|
||||||
|
|
||||||
scripting::on_shutdown([](const int clear_scripts, const int post_shutdown) -> void
|
scripting::on_shutdown([](const int clear_scripts, const int post_shutdown) -> void
|
||||||
{
|
{
|
||||||
@@ -184,11 +182,6 @@ namespace notifies
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::call(0x1404724DD, client_command_stub);
|
utils::hook::call(0x1404724DD, client_command_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,11 +40,6 @@ namespace party
|
|||||||
|
|
||||||
void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype)
|
void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype)
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game::Live_SyncOnlineDataFlags(0))
|
if (game::Live_SyncOnlineDataFlags(0))
|
||||||
{
|
{
|
||||||
scheduler::once([=]()
|
scheduler::once([=]()
|
||||||
@@ -201,11 +196,6 @@ namespace party
|
|||||||
|
|
||||||
void connect(const game::netadr_s& target)
|
void connect(const game::netadr_s& target)
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
command::execute("lui_open popup_acceptinginvite", false);
|
command::execute("lui_open popup_acceptinginvite", false);
|
||||||
|
|
||||||
connect_state.host = target;
|
connect_state.host = target;
|
||||||
@@ -230,11 +220,6 @@ namespace party
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hook disconnect command function
|
// hook disconnect command function
|
||||||
utils::hook::jump(0x1402C6370, disconnect_stub);
|
utils::hook::jump(0x1402C6370, disconnect_stub);
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,13 @@ namespace patches
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sv_kick_client_num_hook.invoke<void>(clientNum, reason);
|
return sv_kick_client_num_hook.invoke<void>(clientNum, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_login_username()
|
std::string get_login_username()
|
||||||
{
|
{
|
||||||
char username[UNLEN + 1];
|
char username[UNLEN + 1]{};
|
||||||
DWORD username_len = UNLEN + 1;
|
DWORD username_len = UNLEN + 1;
|
||||||
if (!GetUserNameA(username, &username_len))
|
if (!GetUserNameA(username, &username_len))
|
||||||
{
|
{
|
||||||
@@ -55,7 +56,7 @@ namespace patches
|
|||||||
if (game::environment::is_mp())
|
if (game::environment::is_mp())
|
||||||
{
|
{
|
||||||
// Make name save
|
// Make name save
|
||||||
game::Dvar_RegisterString("name", get_login_username().data(), game::DVAR_FLAG_SAVED, "Player name.");
|
game::Dvar_RegisterString("name", get_login_username().c_str(), game::DVAR_FLAG_SAVED, "Player name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return com_register_dvars_hook.invoke<void>();
|
return com_register_dvars_hook.invoke<void>();
|
||||||
@@ -106,23 +107,6 @@ namespace patches
|
|||||||
a.jmp(0x1403F7574);
|
a.jmp(0x1403F7574);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto cmd_exec_stub_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
const auto success = a.newLabel();
|
|
||||||
|
|
||||||
a.pushad64();
|
|
||||||
a.call_aligned(cmd_exec_patch);
|
|
||||||
a.test(al, al);
|
|
||||||
a.popad64();
|
|
||||||
|
|
||||||
a.jz(success);
|
|
||||||
a.mov(edx, 0x18000);
|
|
||||||
a.jmp(0x1403B39C0);
|
|
||||||
|
|
||||||
a.bind(success);
|
|
||||||
a.jmp(0x1403B3A04);
|
|
||||||
});
|
|
||||||
|
|
||||||
int dvar_command_patch() // game makes this return an int and compares with eax instead of al -_-
|
int dvar_command_patch() // game makes this return an int and compares with eax instead of al -_-
|
||||||
{
|
{
|
||||||
const command::params args{};
|
const command::params args{};
|
||||||
@@ -235,14 +219,10 @@ namespace patches
|
|||||||
LoadLibraryA("PhysXUpdateLoader64.dll");
|
LoadLibraryA("PhysXUpdateLoader64.dll");
|
||||||
|
|
||||||
// Unlock fps in main menu
|
// Unlock fps in main menu
|
||||||
utils::hook::set<std::uint8_t>(SELECT_VALUE(0x140242DDB, 0x1402CF58B), 0xEB);
|
utils::hook::set<std::uint8_t>(0x1402CF58B, 0xEB);
|
||||||
|
|
||||||
// Unlock cg_fov
|
// Unlock cg_fov
|
||||||
utils::hook::call(SELECT_VALUE(0x1401F3E96, 0x14027273C), register_cg_fov_stub);
|
utils::hook::call(0x14027273C, register_cg_fov_stub);
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
utils::hook::call(0x1401F3EC7, register_cg_fov_stub);
|
|
||||||
}
|
|
||||||
|
|
||||||
// changed max value from 85 -> 1000
|
// changed max value from 85 -> 1000
|
||||||
if (!game::environment::is_dedi())
|
if (!game::environment::is_dedi())
|
||||||
@@ -250,11 +230,8 @@ namespace patches
|
|||||||
dvars::override::register_int("com_maxfps", 85, 0, 1000, game::DVAR_FLAG_SAVED);
|
dvars::override::register_int("com_maxfps", 85, 0, 1000, game::DVAR_FLAG_SAVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!game::environment::is_sp())
|
// increased max limit for sv_network_fps, the lower limit is the default one. Original range is from 20 to 200 times a second.
|
||||||
{
|
utils::hook::call(0x140476F4F, register_network_fps_stub);
|
||||||
//increased max limit for sv_network_fps, the lower limit is the default one. Original range is from 20 to 200 times a second.
|
|
||||||
utils::hook::call(0x140476F4F, register_network_fps_stub);
|
|
||||||
}
|
|
||||||
|
|
||||||
// register cg_gun_ dvars with new values and flags
|
// register cg_gun_ dvars with new values and flags
|
||||||
// maybe _x can stay usable within a reasonable range? it can make scoped weapons DRASTICALLY better on high FOVs
|
// maybe _x can stay usable within a reasonable range? it can make scoped weapons DRASTICALLY better on high FOVs
|
||||||
@@ -266,29 +243,18 @@ namespace patches
|
|||||||
dvars::override::register_float("cg_fovScale", 1.0f, 0.1f, 5.0f, game::DVAR_FLAG_SAVED);
|
dvars::override::register_float("cg_fovScale", 1.0f, 0.1f, 5.0f, game::DVAR_FLAG_SAVED);
|
||||||
|
|
||||||
// Patch Dvar_Command to print out values how CoD4 does it
|
// Patch Dvar_Command to print out values how CoD4 does it
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403BFCB0, 0x140416A60), dvar_command_patch);
|
utils::hook::jump(0x140416A60, dvar_command_patch);
|
||||||
|
|
||||||
// Allow executing custom cfg files with the "exec" command
|
// Allow executing custom cfg files with the "exec" command
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403B39BB, 0x1403F752B), SELECT_VALUE(0x1403B3A12, 0x1403F7582));
|
utils::hook::jump(0x1403F752B, 0x1403F7582);
|
||||||
//Use a relative jump to empty memory first
|
//Use a relative jump to empty memory first
|
||||||
utils::hook::jump(SELECT_VALUE(0x1403B3A12, 0x1403F7582), SELECT_VALUE(cmd_exec_stub_sp, cmd_exec_stub_mp), true);
|
utils::hook::jump(0x1403F7582, cmd_exec_stub_mp, true);
|
||||||
// Use empty memory to go to our stub first (can't do close jump, so need space for 12 bytes)
|
// Use empty memory to go to our stub first (can't do close jump, so need space for 12 bytes)
|
||||||
|
|
||||||
// Fix mouse lag
|
// nop call to SetThreadExecutionState for good luck (???)
|
||||||
utils::hook::nop(SELECT_VALUE(0x14043E6CB, 0x140504A2B), 6);
|
utils::hook::nop(0x140504A2B, 6);
|
||||||
scheduler::loop([]()
|
|
||||||
{
|
|
||||||
SetThreadExecutionState(ES_DISPLAY_REQUIRED);
|
|
||||||
}, scheduler::pipeline::main);
|
|
||||||
|
|
||||||
if (game::environment::is_sp())
|
patch_mp();
|
||||||
{
|
|
||||||
patch_sp();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
patch_mp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void patch_mp()
|
static void patch_mp()
|
||||||
@@ -377,13 +343,6 @@ namespace patches
|
|||||||
// Disable Com_Error in NET_SendPacket
|
// Disable Com_Error in NET_SendPacket
|
||||||
utils::hook::nop(0x140501AE3, 5);
|
utils::hook::nop(0x140501AE3, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void patch_sp()
|
|
||||||
{
|
|
||||||
// SP doesn't initialize WSA
|
|
||||||
WSADATA wsa_data;
|
|
||||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,11 +74,6 @@ namespace ranked
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game::environment::is_mp())
|
if (game::environment::is_mp())
|
||||||
{
|
{
|
||||||
// This must be registered as 'true' to avoid crash when starting a private match
|
// This must be registered as 'true' to avoid crash when starting a private match
|
||||||
|
|||||||
@@ -181,16 +181,15 @@ namespace raw_mouse
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x14043845F, 0x1404FC3FB), &in_mouse_move);
|
utils::hook::call(0x1404FC3FB, &in_mouse_move);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x140519F71, 0x1405E69A1), &create_window_ex_a_stub);
|
utils::hook::call(0x1405E69A1, &create_window_ex_a_stub);
|
||||||
utils::hook::set<std::uint8_t>(SELECT_VALUE(0x140519F76, 0x1405E69A6), 0x90);
|
utils::hook::set<std::uint8_t>(0x1405E69A6, 0x90);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x14043BF04, 0x140500824), ®ister_class_ex_a_stub);
|
utils::hook::call(0x140500824, ®ister_class_ex_a_stub);
|
||||||
utils::hook::set<std::uint8_t>(SELECT_VALUE(0x14043BF09, 0x140500829), 0x90);
|
utils::hook::set<std::uint8_t>(0x140500829, 0x90);
|
||||||
|
|
||||||
cl_rawInput = game::Dvar_RegisterBool("cl_rawInput", true,
|
cl_rawInput = game::Dvar_RegisterBool("cl_rawInput", true, game::DVAR_FLAG_SAVED, "Use Raw Input for mouse. This fixes mouse acceleration issue");
|
||||||
game::DVAR_FLAG_SAVED, "Use Raw Input for mouse input. This fixes mouse acceleration issue");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,8 +123,6 @@ namespace rcon
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
scheduler::once([]()
|
scheduler::once([]()
|
||||||
{
|
{
|
||||||
game::Dvar_RegisterString("rcon_password", "", game::DvarFlags::DVAR_FLAG_NONE,
|
game::Dvar_RegisterString("rcon_password", "", game::DvarFlags::DVAR_FLAG_NONE,
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ namespace renderer
|
|||||||
dvars::r_fullbright = game::Dvar_RegisterBool("r_fullbright", false, game::DVAR_FLAG_CHEAT,
|
dvars::r_fullbright = game::Dvar_RegisterBool("r_fullbright", false, game::DVAR_FLAG_CHEAT,
|
||||||
"Toggles rendering without lighting");
|
"Toggles rendering without lighting");
|
||||||
|
|
||||||
r_init_draw_method_hook.create(SELECT_VALUE(0x1404FF600, 0x1405CB470), &r_init_draw_method_stub);
|
r_init_draw_method_hook.create(0x1405CB470, &r_init_draw_method_stub);
|
||||||
r_update_front_end_dvar_options_hook.create(SELECT_VALUE(0x140535FF0, 0x140603240), &r_update_front_end_dvar_options_stub);
|
r_update_front_end_dvar_options_hook.create(0x140603240, &r_update_front_end_dvar_options_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace scheduler
|
|||||||
{
|
{
|
||||||
schedule([=]()
|
schedule([=]()
|
||||||
{
|
{
|
||||||
const auto dw_init = game::environment::is_sp() || game::Live_SyncOnlineDataFlags(0) == 0;
|
const auto dw_init = game::Live_SyncOnlineDataFlags(0) == 0;
|
||||||
if (dw_init && game::Sys_IsDatabaseReady2())
|
if (dw_init && game::Sys_IsDatabaseReady2())
|
||||||
{
|
{
|
||||||
once(callback, type, delay);
|
once(callback, type, delay);
|
||||||
@@ -177,10 +177,10 @@ namespace scheduler
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
r_end_frame_hook.create(SELECT_VALUE(0x140534860, 0x140601AA0), scheduler::r_end_frame_stub);
|
r_end_frame_hook.create(0x140601AA0, scheduler::r_end_frame_stub);
|
||||||
|
|
||||||
utils::hook::call(SELECT_VALUE(0x1403BC922, 0x140413142), scheduler::main_frame_stub);
|
utils::hook::call(0x140413142, scheduler::main_frame_stub);
|
||||||
utils::hook::call(SELECT_VALUE(0x1403185FD, 0x1403A0AF9), scheduler::server_frame_stub);
|
utils::hook::call(0x1403A0AF9, scheduler::server_frame_stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
|
|||||||
@@ -195,24 +195,20 @@ namespace scripting
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// SP address is wrong, but should be ok
|
scr_load_level_hook.create(0x1403C4E60, &scr_load_level_stub);
|
||||||
scr_load_level_hook.create(SELECT_VALUE(0x14013D5D0, 0x1403C4E60), &scr_load_level_stub);
|
g_shutdown_game_hook.create(0x1403A0DF0, &g_shutdown_game_stub);
|
||||||
g_shutdown_game_hook.create(SELECT_VALUE(0x140318C10, 0x1403A0DF0), &g_shutdown_game_stub);
|
|
||||||
|
|
||||||
scr_set_thread_position_hook.create(SELECT_VALUE(0x1403D3560, 0x14042E360), &scr_set_thread_position_stub);
|
scr_set_thread_position_hook.create(0x14042E360, &scr_set_thread_position_stub);
|
||||||
process_script_hook.create(SELECT_VALUE(0x1403DC870, 0x1404378C0), &process_script_stub);
|
process_script_hook.create(0x1404378C0, &process_script_stub);
|
||||||
sl_get_canonical_string_hook.create(game::SL_GetCanonicalString, &sl_get_canonical_string_stub);
|
sl_get_canonical_string_hook.create(game::SL_GetCanonicalString, &sl_get_canonical_string_stub);
|
||||||
|
|
||||||
if (!game::environment::is_sp())
|
// Make some room for pre_main hook
|
||||||
{
|
utils::hook::jump(0x1402084A0, has_config_string_index);
|
||||||
// Make some room for pre_main hook
|
|
||||||
utils::hook::jump(0x1402084A0, has_config_string_index);
|
|
||||||
|
|
||||||
// Allow precaching anytime
|
// Allow precaching anytime
|
||||||
utils::hook::jump(0x1402084A5, is_pre_main_stub);
|
utils::hook::jump(0x1402084A5, is_pre_main_stub);
|
||||||
utils::hook::set<uint16_t>(0x1402084D0, 0xD3EB); // jump to 0x1402084A5
|
utils::hook::set<uint16_t>(0x1402084D0, 0xD3EB); // jump to 0x1402084A5
|
||||||
g_find_config_string_index.create(0x140161F90, &g_find_config_string_index_stub);
|
g_find_config_string_index.create(0x140161F90, &g_find_config_string_index_stub);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,9 +105,7 @@ namespace security
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// sprinf
|
// sprinf
|
||||||
utils::hook::call(SELECT_VALUE(0x140310D0F, 0x140399B0F), hud_elem_set_enum_string_stub);
|
utils::hook::call(0x140399B0F, hud_elem_set_enum_string_stub);
|
||||||
|
|
||||||
if (game::environment::is_sp()) return;
|
|
||||||
|
|
||||||
// Patch vulnerability in PlayerCards_SetCachedPlayerData
|
// Patch vulnerability in PlayerCards_SetCachedPlayerData
|
||||||
utils::hook::call(0x140287C5C, set_cached_playerdata_stub);
|
utils::hook::call(0x140287C5C, set_cached_playerdata_stub);
|
||||||
|
|||||||
@@ -83,11 +83,6 @@ namespace slowmotion
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_sp())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
command::add("timescale", com_timescale_f);
|
command::add("timescale", com_timescale_f);
|
||||||
|
|
||||||
if (!game::environment::is_dedi())
|
if (!game::environment::is_dedi())
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace splash
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Disable native splash screen
|
// Disable native splash screen
|
||||||
utils::hook::nop(SELECT_VALUE(0x14043C15B, 0x140500ADB), 5);
|
utils::hook::nop(0x140500ADB, 5);
|
||||||
utils::hook::jump(SELECT_VALUE(0x14043D5A0, 0x140502000), destroy_stub);
|
utils::hook::jump(0x140502000, destroy_stub);
|
||||||
utils::hook::jump(SELECT_VALUE(0x14043D5E0, 0x140502040), destroy_stub);
|
utils::hook::jump(0x140502040, destroy_stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
|
|||||||
@@ -46,16 +46,27 @@ namespace steam_proxy
|
|||||||
#ifndef DEV_BUILD
|
#ifndef DEV_BUILD
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const std::string game_type = game::environment::is_sp() ? "singleplayer" : "multiplayer";
|
const std::string game_type = "multiplayer";
|
||||||
state_ = this->start_mod("\xF0\x9F\x92\x8E" " iw6-mod: " + (game_type), game::environment::is_sp() ? 209160 : 209170);
|
state_ = this->start_mod("\xF0\x9F\x92\x8E" " iw6-mod: " + (game_type), 209170);
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex)
|
catch (const std::exception& ex)
|
||||||
{
|
{
|
||||||
state_ = ownership_state::error;
|
state_ = ownership_state::error;
|
||||||
printf("Steam: %s\n", ex.what());
|
printf("Steam: %s\n", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STEAM_OWNERSHIP_CHECK
|
||||||
|
if (utils::nt::is_wine())
|
||||||
|
{
|
||||||
|
state_ = ownership_state::success;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STEAM_OWNERSHIP_CHECK
|
||||||
|
evaluate_ownership_state(state_);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
(void)state_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
@@ -212,6 +223,23 @@ namespace steam_proxy
|
|||||||
return scheduler::cond_end;
|
return scheduler::cond_end;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STEAM_OWNERSHIP_CHECK
|
||||||
|
void evaluate_ownership_state(const ownership_state state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ownership_state::nosteam:
|
||||||
|
throw std::runtime_error("Steam must be running to play this game!");
|
||||||
|
case ownership_state::unowned:
|
||||||
|
throw std::runtime_error("You must own the game on Steam to play this mod!");
|
||||||
|
case ownership_state::error:
|
||||||
|
throw std::runtime_error("Failed to verify ownership of the game!");
|
||||||
|
case ownership_state::success:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,15 +32,13 @@ namespace ui_scripting
|
|||||||
std::string root;
|
std::string root;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct globals
|
struct
|
||||||
{
|
{
|
||||||
std::string in_require_script;
|
std::string in_require_script;
|
||||||
std::vector<script> loaded_scripts;
|
std::vector<script> loaded_scripts;
|
||||||
bool load_raw_script{};
|
bool load_raw_script{};
|
||||||
std::string raw_script_name{};
|
std::string raw_script_name{};
|
||||||
};
|
} globals;
|
||||||
|
|
||||||
globals globals;
|
|
||||||
|
|
||||||
bool is_loaded_script(const std::string& name)
|
bool is_loaded_script(const std::string& name)
|
||||||
{
|
{
|
||||||
@@ -156,7 +154,7 @@ namespace ui_scripting
|
|||||||
|
|
||||||
game_type["issingleplayer"] = [](const game&)
|
game_type["issingleplayer"] = [](const game&)
|
||||||
{
|
{
|
||||||
return ::game::environment::is_sp();
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
game_type["ismultiplayer"] = [](const game&)
|
game_type["ismultiplayer"] = [](const game&)
|
||||||
@@ -297,7 +295,7 @@ namespace ui_scripting
|
|||||||
|
|
||||||
void* lua_atpanic_stub(void* l, [[maybe_unused]] void* panicf)
|
void* lua_atpanic_stub(void* l, [[maybe_unused]] void* panicf)
|
||||||
{
|
{
|
||||||
return utils::hook::invoke<void*>(SELECT_VALUE(0x1401851F0, 0x1401A4730), l, SELECT_VALUE(0x1401789A0, 0x140197BC0));
|
return utils::hook::invoke<void*>(0x1401A4730, l, 0x140197BC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int luaopen_stub([[maybe_unused]] void* l)
|
int luaopen_stub([[maybe_unused]] void* l)
|
||||||
@@ -362,31 +360,31 @@ namespace ui_scripting
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// Disable debug breakpoints in the assembly of hksDefaultPanic
|
// Disable debug breakpoints in the assembly of hksDefaultPanic
|
||||||
utils::hook::set<std::uint8_t>(SELECT_VALUE(0x140178C5E, 0x140197E7E), 0x90);
|
utils::hook::set<std::uint8_t>(0x140197E7E, 0x90);
|
||||||
|
|
||||||
// Restore hksDefaultPanic for complete error messages
|
// Restore hksDefaultPanic for complete error messages
|
||||||
utils::hook::call(SELECT_VALUE(0x1401B0028, 0x1401CE6C8), lua_atpanic_stub);
|
utils::hook::call(0x1401CE6C8, lua_atpanic_stub);
|
||||||
|
|
||||||
// Do not allow the HKS vm to open LUA's libraries
|
// Do not allow the HKS vm to open LUA's libraries
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015BD10, 0x14017E040), luaopen_stub); // io
|
utils::hook::jump(0x14017E040, luaopen_stub); // io
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015C3D0, 0x14017E700), luaopen_stub); // os
|
utils::hook::jump(0x14017E700, luaopen_stub); // os
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015D400, 0x14017F730), luaopen_stub); // serialize
|
utils::hook::jump(0x14017F730, luaopen_stub); // serialize
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015D3D0, 0x14017F700), luaopen_stub); // havokscript
|
utils::hook::jump(0x14017F700, luaopen_stub); // havokscript
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015C930, 0x14017EC60), luaopen_stub); // debug
|
utils::hook::jump(0x14017EC60, luaopen_stub); // debug
|
||||||
|
|
||||||
utils::hook::nop(SELECT_VALUE(0x14015B639, 0x14017D969), 5); // coroutine
|
utils::hook::nop(0x14017D969, 5); // coroutine
|
||||||
|
|
||||||
// Disable unsafe functions
|
// Disable unsafe functions
|
||||||
utils::hook::jump(SELECT_VALUE(0x140158C20, 0x14017AF50), hks_base_stub); // base_loadfile
|
utils::hook::jump(0x14017AF50, hks_base_stub); // base_loadfile
|
||||||
utils::hook::jump(SELECT_VALUE(0x140158B10, 0x14017AE40), hks_base_stub); // base_dofile
|
utils::hook::jump(0x14017AE40, hks_base_stub); // base_dofile
|
||||||
utils::hook::jump(SELECT_VALUE(0x14015D7E0, 0x14017FB10), hks_base_stub); // base_load
|
utils::hook::jump(0x14017FB10, hks_base_stub); // base_load
|
||||||
|
|
||||||
utils::hook::jump(SELECT_VALUE(0x1401569D0, 0x140178CF0), hks_base_stub); // package_loadlib
|
utils::hook::jump(0x140178CF0, hks_base_stub); // package_loadlib
|
||||||
utils::hook::jump(SELECT_VALUE(0x140163CD0, 0x140177E00), hks_base_stub); // package_c_loader
|
utils::hook::jump(0x140177E00, hks_base_stub); // package_c_loader
|
||||||
utils::hook::jump(SELECT_VALUE(0x140163DE0, 0x140177F10), hks_base_stub); // package_all_in_one_loader
|
utils::hook::jump(0x140177F10, hks_base_stub); // package_all_in_one_loader
|
||||||
|
|
||||||
utils::hook::jump(SELECT_VALUE(0x140157DA0, 0x14017A0D0), hks_base_stub); // string_dump
|
utils::hook::jump(0x14017A0D0, hks_base_stub); // string_dump
|
||||||
utils::hook::jump(SELECT_VALUE(0x1401606A0, 0x1401747D0), hks_base_stub); // os_execute
|
utils::hook::jump(0x1401747D0, hks_base_stub); // os_execute
|
||||||
|
|
||||||
if (!game::environment::is_mp())
|
if (!game::environment::is_mp())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,19 +59,6 @@ namespace ultrawide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// general aspect ratio
|
|
||||||
auto ultrawide_spawn_window_stub_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.call_aligned(0x140519430); // og - setup hwnd struct
|
|
||||||
|
|
||||||
a.lea(rcx, ptr(rsp, 0x0A0));
|
|
||||||
a.call_aligned(ultrawide_patch);
|
|
||||||
|
|
||||||
a.mov(edi, ptr(rsp, 0x0B0)); // mov edi, [rsp+0B0h]
|
|
||||||
|
|
||||||
a.jmp(0x140519ED3);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto ultrawide_spawn_window_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
auto ultrawide_spawn_window_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
{
|
{
|
||||||
a.call_aligned(0x1405E5E70); // og - setup hwnd struct
|
a.call_aligned(0x1405E5E70); // og - setup hwnd struct
|
||||||
@@ -84,27 +71,6 @@ namespace ultrawide
|
|||||||
a.jmp(0x1405E6903);
|
a.jmp(0x1405E6903);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// menu aspect ratio + left offset
|
|
||||||
auto ultrawide_menu_stub_01_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.push(eax);
|
|
||||||
a.mov(eax, dword_ptr(reinterpret_cast<int64_t>(&hud_aspect_ratio)));
|
|
||||||
a.movd(xmm5, eax);
|
|
||||||
|
|
||||||
a.divss(xmm0, xmm5); // divss xmm0, cs:FLOAT_1_77778 // -> custom aspect ratio
|
|
||||||
a.subss(xmm1, xmm0); // subss xmm1, xmm0
|
|
||||||
a.movaps(xmm0, xmm3); // movaps xmm0, xmm3
|
|
||||||
|
|
||||||
a.mov(eax, dword_ptr(reinterpret_cast<int64_t>(&hud_aspect_ratio_inv)));
|
|
||||||
a.movd(xmm5, eax);
|
|
||||||
a.mulss(xmm0, xmm5); // mulss xmm0, cs:dword_14083D47C // -1.77778 // -> left menu offset
|
|
||||||
|
|
||||||
a.pop(eax);
|
|
||||||
|
|
||||||
a.jmp(0x1401CD772);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto ultrawide_menu_stub_01_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
auto ultrawide_menu_stub_01_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
{
|
{
|
||||||
a.push(eax);
|
a.push(eax);
|
||||||
@@ -124,22 +90,6 @@ namespace ultrawide
|
|||||||
a.jmp(0x1402008D2);
|
a.jmp(0x1402008D2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// menu aspect ratio right offset
|
|
||||||
auto ultrawide_menu_stub_02_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.push(eax);
|
|
||||||
a.mov(eax, dword_ptr(reinterpret_cast<int64_t>(&hud_aspect_ratio)));
|
|
||||||
a.movd(xmm5, eax);
|
|
||||||
|
|
||||||
a.mulss(xmm0, xmm5); // mulss xmm0, cs:FLOAT_1_77778 // -> custom aspect ratio
|
|
||||||
a.mulss(xmm0, xmm1); // mulss xmm0, xmm1
|
|
||||||
|
|
||||||
a.pop(eax);
|
|
||||||
|
|
||||||
a.jmp(0x1401CD79F);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto ultrawide_menu_stub_02_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
auto ultrawide_menu_stub_02_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
{
|
{
|
||||||
a.push(eax);
|
a.push(eax);
|
||||||
@@ -154,22 +104,6 @@ namespace ultrawide
|
|||||||
a.jmp(0x1402008FF);
|
a.jmp(0x1402008FF);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// fix loadscreen and in-game hud aspect ratio
|
|
||||||
auto ultrawide_hud_stub_sp = utils::hook::assemble([](utils::hook::assembler& a)
|
|
||||||
{
|
|
||||||
a.push(eax);
|
|
||||||
a.mov(eax, dword_ptr(reinterpret_cast<int64_t>(&hud_aspect_ratio)));
|
|
||||||
a.movd(xmm5, eax);
|
|
||||||
|
|
||||||
a.divss(xmm6, xmm5); // divss xmm6, cs:FLOAT_1_77778
|
|
||||||
a.mulss(xmm6, xmm3); // mulss xmm6, xmm3
|
|
||||||
|
|
||||||
a.pop(eax);
|
|
||||||
|
|
||||||
a.jmp(0x14024D32F);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto ultrawide_hud_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
auto ultrawide_hud_stub_mp = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
{
|
{
|
||||||
a.push(eax);
|
a.push(eax);
|
||||||
@@ -191,46 +125,38 @@ namespace ultrawide
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
// ultrawide patches
|
// ultrawide patches
|
||||||
utils::hook::call(SELECT_VALUE(0x140510D0E, 0x1405DCF58), dvar_register_aspect_ratio);
|
utils::hook::call(0x1405DCF58, dvar_register_aspect_ratio);
|
||||||
// register r_aspectRatioCustom
|
// register r_aspectRatioCustom
|
||||||
utils::hook::jump(
|
utils::hook::jump(0x1405E68F7, ultrawide_spawn_window_stub_mp, true);
|
||||||
SELECT_VALUE(0x140519EC7, 0x1405E68F7),
|
|
||||||
SELECT_VALUE(ultrawide_spawn_window_stub_sp, ultrawide_spawn_window_stub_mp), true);
|
|
||||||
// apply general aspect ratio
|
// apply general aspect ratio
|
||||||
utils::hook::jump(
|
utils::hook::jump(0x1402008BB, ultrawide_menu_stub_01_mp, true);
|
||||||
SELECT_VALUE(0x1401CD75B, 0x1402008BB),
|
|
||||||
SELECT_VALUE(ultrawide_menu_stub_01_sp, ultrawide_menu_stub_01_mp), true);
|
|
||||||
// fix menu aspect ratio and left offset
|
// fix menu aspect ratio and left offset
|
||||||
utils::hook::jump(
|
utils::hook::jump(0x1402008F3, ultrawide_menu_stub_02_mp, true);
|
||||||
SELECT_VALUE(0x1401CD793, 0x1402008F3),
|
|
||||||
SELECT_VALUE(ultrawide_menu_stub_02_sp, ultrawide_menu_stub_02_mp), true);
|
|
||||||
// fix menu aspect ratio right offset
|
// fix menu aspect ratio right offset
|
||||||
utils::hook::jump(
|
utils::hook::jump(0x1402F7043, ultrawide_hud_stub_mp, true); // fix aspect ratio for loadscreen and general in-game hud
|
||||||
SELECT_VALUE(0x14024D323, 0x1402F7043), SELECT_VALUE(ultrawide_hud_stub_sp, ultrawide_hud_stub_mp),
|
|
||||||
true); // fix aspect ratio for loadscreen and general in-game hud
|
|
||||||
|
|
||||||
// safeArea_adjusted dvars :: disable resets (in-game hud padding)
|
// safeArea_adjusted dvars :: disable resets (in-game hud padding)
|
||||||
utils::hook::nop(SELECT_VALUE(0x14024AEF2, 0x1402D4FB2), 5); // safeArea_adjusted_horizontal
|
utils::hook::nop(0x1402D4FB2, 5); // safeArea_adjusted_horizontal
|
||||||
utils::hook::nop(SELECT_VALUE(0x14024D655, 0x1402F7375), 5); // safeArea_adjusted_horizontal
|
utils::hook::nop(0x1402F7375, 5); // safeArea_adjusted_horizontal
|
||||||
|
|
||||||
utils::hook::nop(SELECT_VALUE(0x14024AF19, 0x1402D4FD9), 5);
|
utils::hook::nop(0x1402D4FD9, 5);
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024AF19, 0x1402D4FD9), 0xC3);
|
utils::hook::set<uint8_t>(0x1402D4FD9, 0xC3);
|
||||||
// safeArea_adjusted_vertical :: return instead of jumping to Dvar_SetFloat
|
// safeArea_adjusted_vertical :: return instead of jumping to Dvar_SetFloat
|
||||||
utils::hook::nop(SELECT_VALUE(0x14024D664, 0x1402F7384), 5); // safeArea_adjusted_vertical
|
utils::hook::nop(0x1402F7384, 5); // safeArea_adjusted_vertical
|
||||||
|
|
||||||
// safeArea_ dvars :: remove cheat protection + add saved flag
|
// safeArea_ dvars :: remove cheat protection + add saved flag
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D19F + 4, 0x1402F6EBF + 4), 0x1);
|
utils::hook::set<uint8_t>(0x1402F6EBF + 4, 0x1);
|
||||||
// register safeArea_horizontal (mov dword ptr [rsp+20h], 4)
|
// register safeArea_horizontal (mov dword ptr [rsp+20h], 4)
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D1D7 + 4, 0x1402F6EF7 + 4), 0x1);
|
utils::hook::set<uint8_t>(0x1402F6EF7 + 4, 0x1);
|
||||||
// register safeArea_vertical (mov dword ptr [rsp+20h], 4)
|
// register safeArea_vertical (mov dword ptr [rsp+20h], 4)
|
||||||
|
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D207 + 5, 0x1402F6F27 + 5), 0x0);
|
utils::hook::set<uint8_t>(0x1402F6F27 + 5, 0x0);
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D207 + 4, 0x1402F6F27 + 4), 0x1);
|
utils::hook::set<uint8_t>(0x1402F6F27 + 4, 0x1);
|
||||||
// register safeArea_adjusted_horizontal (mov dword ptr [rsp+20h], 2000h)
|
// register safeArea_adjusted_horizontal (mov dword ptr [rsp+20h], 2000h)
|
||||||
|
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D237 + 5, 0x1402F6F57 + 5), 0x0);
|
utils::hook::set<uint8_t>(0x1402F6F57 + 5, 0x0);
|
||||||
utils::hook::set<BYTE>(SELECT_VALUE(0x14024D237 + 4, 0x1402F6F57 + 4), 0x1);
|
utils::hook::set<uint8_t>(0x1402F6F57 + 4, 0x1);
|
||||||
// register safeArea_adjusted_vertical (mov dword ptr [rsp+20h], 2000h)
|
// register safeArea_adjusted_vertical (mov dword ptr [rsp+20h], 2000h)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,11 +56,6 @@ namespace game
|
|||||||
return get_mode() == launcher::mode::multiplayer;
|
return get_mode() == launcher::mode::multiplayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_sp()
|
|
||||||
{
|
|
||||||
return get_mode() == launcher::mode::singleplayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_mode(const launcher::mode _mode)
|
void set_mode(const launcher::mode _mode)
|
||||||
{
|
{
|
||||||
mode = _mode;
|
mode = _mode;
|
||||||
@@ -77,9 +72,6 @@ namespace game
|
|||||||
case launcher::mode::multiplayer:
|
case launcher::mode::multiplayer:
|
||||||
return "Multiplayer";
|
return "Multiplayer";
|
||||||
|
|
||||||
case launcher::mode::singleplayer:
|
|
||||||
return "Multiplayer";
|
|
||||||
|
|
||||||
case launcher::mode::none:
|
case launcher::mode::none:
|
||||||
return "None";
|
return "None";
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "structs.hpp"
|
#include "structs.hpp"
|
||||||
#include "launcher/launcher.hpp"
|
|
||||||
|
|
||||||
#define SELECT_VALUE(sp, mp) (game::environment::is_sp() ? (sp) : (mp))
|
namespace launcher
|
||||||
|
{
|
||||||
|
enum class mode
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
multiplayer,
|
||||||
|
server,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#define SERVER_CD_KEY "iw6-mod-CD-Key"
|
#define SERVER_CD_KEY "iw6-mod-CD-Key"
|
||||||
|
|
||||||
@@ -14,7 +21,6 @@ namespace game
|
|||||||
launcher::mode get_mode();
|
launcher::mode get_mode();
|
||||||
|
|
||||||
bool is_mp();
|
bool is_mp();
|
||||||
bool is_sp();
|
|
||||||
bool is_dedi();
|
bool is_dedi();
|
||||||
|
|
||||||
void set_mode(launcher::mode mode);
|
void set_mode(launcher::mode mode);
|
||||||
@@ -34,11 +40,6 @@ namespace game
|
|||||||
|
|
||||||
T* get() const
|
T* get() const
|
||||||
{
|
{
|
||||||
if (environment::is_sp())
|
|
||||||
{
|
|
||||||
return sp_object_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mp_object_;
|
return mp_object_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace scripting
|
|||||||
script_function get_function_by_index(const std::uint32_t index)
|
script_function get_function_by_index(const std::uint32_t index)
|
||||||
{
|
{
|
||||||
static const auto function_table = &gsc::func_table;
|
static const auto function_table = &gsc::func_table;
|
||||||
static const auto method_table = SELECT_VALUE(0x144E1F9E0, 0x1446B8A90);
|
static const auto method_table = 0x1446B8A90;
|
||||||
|
|
||||||
if (index <= 0x1000)
|
if (index <= 0x1000)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
||||||
{
|
|
||||||
auto client_site = this->frame_->get_client_site();
|
|
||||||
if (client_site)
|
|
||||||
{
|
|
||||||
return client_site->QueryInterface(riid, ppvObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG doc_host_ui_handler::AddRef()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG doc_host_ui_handler::Release()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/,
|
|
||||||
IDispatch* /*pdispReserved*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/,
|
|
||||||
IOleCommandTarget* /*pCommandTarget*/,
|
|
||||||
IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::HideUI()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::UpdateUI()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/,
|
|
||||||
BOOL /*fRameWindow*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/)
|
|
||||||
{
|
|
||||||
pguidCmdGroup = nullptr;
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch)
|
|
||||||
{
|
|
||||||
*ppDispatch = this->frame_->get_html_dispatch();
|
|
||||||
return (*ppDispatch) ? S_OK : S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet)
|
|
||||||
{
|
|
||||||
*ppDORet = nullptr;
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/,
|
|
||||||
OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut)
|
|
||||||
{
|
|
||||||
*ppchURLOut = nullptr;
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo)
|
|
||||||
{
|
|
||||||
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
|
|
||||||
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE /*| DOCHOSTUIFLAG_SCROLL_NO*/;
|
|
||||||
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_frame;
|
|
||||||
|
|
||||||
class doc_host_ui_handler final : public IDocHostUIHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
doc_host_ui_handler(html_frame* frame);
|
|
||||||
virtual ~doc_host_ui_handler() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
html_frame* frame_;
|
|
||||||
|
|
||||||
public: // IDocHostUIHandler interface
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override;
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
|
||||||
ULONG STDMETHODCALLTYPE Release() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ShowContextMenu(
|
|
||||||
DWORD dwID,
|
|
||||||
POINT __RPC_FAR * ppt,
|
|
||||||
IUnknown __RPC_FAR * pcmdtReserved,
|
|
||||||
IDispatch __RPC_FAR * pdispReserved) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ShowUI(
|
|
||||||
DWORD dwID,
|
|
||||||
IOleInPlaceActiveObject __RPC_FAR * pActiveObject,
|
|
||||||
IOleCommandTarget __RPC_FAR * pCommandTarget,
|
|
||||||
IOleInPlaceFrame __RPC_FAR * pFrame,
|
|
||||||
IOleInPlaceUIWindow __RPC_FAR * pDoc) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE HideUI() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE UpdateUI() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow,
|
|
||||||
BOOL fRameWindow) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID)
|
|
||||||
override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget,
|
|
||||||
IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn,
|
|
||||||
OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet)
|
|
||||||
override;
|
|
||||||
};
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_argument.hpp"
|
|
||||||
|
|
||||||
html_argument::html_argument(VARIANT* val) : value_(val)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_argument::is_empty() const
|
|
||||||
{
|
|
||||||
return this->value_ == nullptr || this->value_->vt == VT_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_argument::is_string() const
|
|
||||||
{
|
|
||||||
if (this->is_empty()) return false;
|
|
||||||
return this->value_->vt == VT_BSTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_argument::is_number() const
|
|
||||||
{
|
|
||||||
if (this->is_empty()) return false;
|
|
||||||
return this->value_->vt == VT_I4;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_argument::is_bool() const
|
|
||||||
{
|
|
||||||
if (this->is_empty()) return false;
|
|
||||||
return this->value_->vt == VT_BOOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string html_argument::get_string() const
|
|
||||||
{
|
|
||||||
if (!this->is_string()) return {};
|
|
||||||
std::wstring wide_string(this->value_->bstrVal);
|
|
||||||
return std::string(wide_string.begin(), wide_string.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
int html_argument::get_number() const
|
|
||||||
{
|
|
||||||
if (!this->is_number()) return 0;
|
|
||||||
return this->value_->intVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_argument::get_bool() const
|
|
||||||
{
|
|
||||||
if (!this->is_bool()) return false;
|
|
||||||
return this->value_->boolVal != FALSE;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_argument final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
html_argument(VARIANT* val);
|
|
||||||
|
|
||||||
bool is_empty() const;
|
|
||||||
|
|
||||||
bool is_string() const;
|
|
||||||
bool is_number() const;
|
|
||||||
bool is_bool() const;
|
|
||||||
|
|
||||||
std::string get_string() const;
|
|
||||||
int get_number() const;
|
|
||||||
bool get_bool() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
VARIANT* value_;
|
|
||||||
};
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
html_dispatch::html_dispatch(html_frame* frame) : frame_(frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj)
|
|
||||||
{
|
|
||||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
|
||||||
!memcmp(&riid, &IID_IDispatch, sizeof(GUID)))
|
|
||||||
{
|
|
||||||
*ppvObj = this;
|
|
||||||
this->AddRef();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppvObj = nullptr;
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG html_dispatch::AddRef()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG html_dispatch::Release()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < cNames; ++i)
|
|
||||||
{
|
|
||||||
std::wstring wide_name(rgszNames[i]);
|
|
||||||
std::string name(wide_name.begin(), wide_name.end());
|
|
||||||
|
|
||||||
rgDispId[i] = this->frame_->get_callback_id(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
|
||||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
|
|
||||||
{
|
|
||||||
html_frame::callback_params params(pDispParams, pVarResult);
|
|
||||||
this->frame_->invoke_callback(dispIdMember, ¶ms);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_frame;
|
|
||||||
|
|
||||||
class html_dispatch final : public IDispatch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
html_dispatch(html_frame* frame);
|
|
||||||
virtual ~html_dispatch() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
html_frame* frame_;
|
|
||||||
|
|
||||||
public: // IDispatch interface
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
|
||||||
ULONG STDMETHODCALLTYPE Release() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
|
||||||
override;
|
|
||||||
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
|
||||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
|
|
||||||
};
|
|
||||||
@@ -1,320 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
#include <utils/nt.hpp>
|
|
||||||
#include <utils/hook.hpp>
|
|
||||||
|
|
||||||
std::atomic<int> html_frame::frame_count_ = 0;
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
void* original_func{};
|
|
||||||
GUID browser_emulation_guid{0xac969931, 0x3566, 0x4b50, {0xae, 0x48, 0x71, 0xb9, 0x6a, 0x75, 0xc8, 0x79}};
|
|
||||||
|
|
||||||
int WINAPI co_internet_feature_value_internal_stub(const GUID* guid, uint32_t* result)
|
|
||||||
{
|
|
||||||
const auto res = static_cast<decltype(co_internet_feature_value_internal_stub)*>(original_func)(guid, result);
|
|
||||||
|
|
||||||
if (IsEqualGUID(*guid, browser_emulation_guid))
|
|
||||||
{
|
|
||||||
*result = 11000;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_ie_hook()
|
|
||||||
{
|
|
||||||
static const auto _ = []
|
|
||||||
{
|
|
||||||
const auto urlmon = utils::nt::library::load("urlmon.dll"s);
|
|
||||||
const auto target = urlmon.get_iat_entry("iertutil.dll", MAKEINTRESOURCEA(700));
|
|
||||||
|
|
||||||
original_func = *target;
|
|
||||||
utils::hook::set(target, co_internet_feature_value_internal_stub);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}();
|
|
||||||
(void)_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res)
|
|
||||||
{
|
|
||||||
for (auto i = params->cArgs; i > 0; --i)
|
|
||||||
{
|
|
||||||
auto param = ¶ms->rgvarg[i - 1];
|
|
||||||
this->arguments.emplace_back(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this),
|
|
||||||
html_dispatch_(this)
|
|
||||||
{
|
|
||||||
setup_ie_hook();
|
|
||||||
if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Unable to initialize the OLE library");
|
|
||||||
}
|
|
||||||
|
|
||||||
set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
|
|
||||||
set_browser_feature("FEATURE_GPU_RENDERING", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
html_frame::~html_frame()
|
|
||||||
{
|
|
||||||
if (--frame_count_ <= 0)
|
|
||||||
{
|
|
||||||
frame_count_ = 0;
|
|
||||||
OleUninitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::object_deleter(IUnknown* object)
|
|
||||||
{
|
|
||||||
if (object)
|
|
||||||
{
|
|
||||||
object->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND html_frame::get_window() const
|
|
||||||
{
|
|
||||||
return this->window_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IOleObject> html_frame::get_browser_object() const
|
|
||||||
{
|
|
||||||
return this->browser_object_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ole_in_place_frame* html_frame::get_in_place_frame()
|
|
||||||
{
|
|
||||||
return &this->in_place_frame_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ole_in_place_site* html_frame::get_in_place_site()
|
|
||||||
{
|
|
||||||
return &this->in_place_site_;
|
|
||||||
}
|
|
||||||
|
|
||||||
doc_host_ui_handler* html_frame::get_ui_handler()
|
|
||||||
{
|
|
||||||
return &this->ui_handler_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ole_client_site* html_frame::get_client_site()
|
|
||||||
{
|
|
||||||
return &this->client_site_;
|
|
||||||
}
|
|
||||||
|
|
||||||
html_dispatch* html_frame::get_html_dispatch()
|
|
||||||
{
|
|
||||||
return &this->html_dispatch_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const
|
|
||||||
{
|
|
||||||
if (!this->browser_object_) return {};
|
|
||||||
|
|
||||||
IWebBrowser2* web_browser = nullptr;
|
|
||||||
if (FAILED(this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)))
|
|
||||||
|| !web_browser)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IDispatch> html_frame::get_dispatch() const
|
|
||||||
{
|
|
||||||
const auto web_browser = this->get_web_browser();
|
|
||||||
if (!web_browser) return {};
|
|
||||||
|
|
||||||
IDispatch* dispatch = nullptr;
|
|
||||||
if (FAILED(web_browser->get_Document(&dispatch)) || !dispatch) return {};
|
|
||||||
|
|
||||||
return std::shared_ptr<IDispatch>(dispatch, object_deleter);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IHTMLDocument2> html_frame::get_document() const
|
|
||||||
{
|
|
||||||
const auto dispatch = this->get_dispatch();
|
|
||||||
if (!dispatch) return {};
|
|
||||||
|
|
||||||
IHTMLDocument2* document = nullptr;
|
|
||||||
if (FAILED(dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)))
|
|
||||||
|| !document)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return std::shared_ptr<IHTMLDocument2>(document, object_deleter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::initialize(const HWND window)
|
|
||||||
{
|
|
||||||
if (this->window_) return;
|
|
||||||
this->window_ = window;
|
|
||||||
|
|
||||||
this->create_browser();
|
|
||||||
this->initialize_browser();
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::create_browser()
|
|
||||||
{
|
|
||||||
LPCLASSFACTORY class_factory = nullptr;
|
|
||||||
if (FAILED(
|
|
||||||
CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
|
|
||||||
reinterpret_cast<void **>(&class_factory))) || !class_factory)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Unable to get the class factory");
|
|
||||||
}
|
|
||||||
|
|
||||||
IOleObject* browser_object = nullptr;
|
|
||||||
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object));
|
|
||||||
class_factory->Release();
|
|
||||||
|
|
||||||
if (!browser_object)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Unable to create browser object");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object)
|
|
||||||
{
|
|
||||||
if (browser_object)
|
|
||||||
{
|
|
||||||
browser_object->Close(OLECLOSE_NOSAVE);
|
|
||||||
object_deleter(browser_object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::initialize_browser()
|
|
||||||
{
|
|
||||||
this->browser_object_->SetClientSite(this->get_client_site());
|
|
||||||
this->browser_object_->SetHostNames(L"Hostname", nullptr);
|
|
||||||
|
|
||||||
RECT rect;
|
|
||||||
GetClientRect(this->get_window(), &rect);
|
|
||||||
OleSetContainedObject(this->browser_object_.get(), TRUE);
|
|
||||||
|
|
||||||
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect);
|
|
||||||
this->resize(rect.right, rect.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_frame::set_browser_feature(const std::string& feature, DWORD value)
|
|
||||||
{
|
|
||||||
const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature;
|
|
||||||
|
|
||||||
HKEY key = nullptr;
|
|
||||||
if (RegCreateKeyA(HKEY_CURRENT_USER, registry_path.data(), &key) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
RegCloseKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
key = nullptr;
|
|
||||||
if (RegOpenKeyExA(
|
|
||||||
HKEY_CURRENT_USER, registry_path.data(), 0,
|
|
||||||
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
return false; // Error :(
|
|
||||||
}
|
|
||||||
|
|
||||||
const utils::nt::library self;
|
|
||||||
const auto name = self.get_name();
|
|
||||||
|
|
||||||
DWORD type{};
|
|
||||||
auto is_new = true;
|
|
||||||
if (RegQueryValueExA(key, name.data(), nullptr, &type, nullptr, nullptr) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
is_new = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
|
||||||
RegCloseKey(key);
|
|
||||||
|
|
||||||
return is_new;
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::resize(const DWORD width, const DWORD height) const
|
|
||||||
{
|
|
||||||
auto web_browser = this->get_web_browser();
|
|
||||||
if (web_browser)
|
|
||||||
{
|
|
||||||
web_browser->put_Left(0);
|
|
||||||
web_browser->put_Top(0);
|
|
||||||
web_browser->put_Width(width);
|
|
||||||
web_browser->put_Height(height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_frame::load_url(const std::string& url) const
|
|
||||||
{
|
|
||||||
auto web_browser = this->get_web_browser();
|
|
||||||
if (!web_browser) return false;
|
|
||||||
|
|
||||||
std::wstring wide_url(url.begin(), url.end());
|
|
||||||
|
|
||||||
VARIANT my_url;
|
|
||||||
VariantInit(&my_url);
|
|
||||||
my_url.vt = VT_BSTR;
|
|
||||||
my_url.bstrVal = SysAllocString(wide_url.data());
|
|
||||||
|
|
||||||
const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); });
|
|
||||||
if (!my_url.bstrVal) return false;
|
|
||||||
|
|
||||||
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool html_frame::load_html(const std::string& html) const
|
|
||||||
{
|
|
||||||
if (!this->load_url("about:blank")) return false;
|
|
||||||
|
|
||||||
const auto document = this->get_document();
|
|
||||||
if (!document) return false;
|
|
||||||
|
|
||||||
SAFEARRAYBOUND safe_array_bound = {1, 0};
|
|
||||||
auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound);
|
|
||||||
if (!safe_array) return false;
|
|
||||||
|
|
||||||
const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); });
|
|
||||||
|
|
||||||
VARIANT* variant = nullptr;
|
|
||||||
if (FAILED(SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant))) || !variant) return false;
|
|
||||||
|
|
||||||
std::wstring wide_html(html.begin(), html.end());
|
|
||||||
|
|
||||||
variant->vt = VT_BSTR;
|
|
||||||
variant->bstrVal = SysAllocString(wide_html.data());
|
|
||||||
if (!variant->bstrVal) return false;
|
|
||||||
|
|
||||||
document->write(safe_array);
|
|
||||||
document->close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int html_frame::get_callback_id(const std::string& name)
|
|
||||||
{
|
|
||||||
for (auto i = 0u; i < this->callbacks_.size(); ++i)
|
|
||||||
{
|
|
||||||
if (this->callbacks_[i].first == name)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::invoke_callback(const int id, callback_params* params)
|
|
||||||
{
|
|
||||||
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
|
|
||||||
{
|
|
||||||
this->callbacks_[id].second(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback)
|
|
||||||
{
|
|
||||||
this->callbacks_.emplace_back(name, callback);
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ole_in_place_frame.hpp"
|
|
||||||
#include "ole_in_place_site.hpp"
|
|
||||||
#include "doc_host_ui_handler.hpp"
|
|
||||||
#include "ole_client_site.hpp"
|
|
||||||
#include "html_dispatch.hpp"
|
|
||||||
#include "html_argument.hpp"
|
|
||||||
|
|
||||||
class html_frame
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class callback_params final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
callback_params(DISPPARAMS* params, VARIANT* res);
|
|
||||||
|
|
||||||
std::vector<html_argument> arguments;
|
|
||||||
html_argument result;
|
|
||||||
};
|
|
||||||
|
|
||||||
html_frame();
|
|
||||||
virtual ~html_frame();
|
|
||||||
|
|
||||||
void initialize(HWND window);
|
|
||||||
|
|
||||||
void resize(DWORD width, DWORD height) const;
|
|
||||||
bool load_url(const std::string& url) const;
|
|
||||||
bool load_html(const std::string& html) const;
|
|
||||||
|
|
||||||
HWND get_window() const;
|
|
||||||
|
|
||||||
std::shared_ptr<IOleObject> get_browser_object() const;
|
|
||||||
std::shared_ptr<IWebBrowser2> get_web_browser() const;
|
|
||||||
std::shared_ptr<IDispatch> get_dispatch() const;
|
|
||||||
std::shared_ptr<IHTMLDocument2> get_document() const;
|
|
||||||
|
|
||||||
ole_in_place_frame* get_in_place_frame();
|
|
||||||
ole_in_place_site* get_in_place_site();
|
|
||||||
doc_host_ui_handler* get_ui_handler();
|
|
||||||
ole_client_site* get_client_site();
|
|
||||||
html_dispatch* get_html_dispatch();
|
|
||||||
|
|
||||||
int get_callback_id(const std::string& name);
|
|
||||||
void invoke_callback(int id, callback_params* params);
|
|
||||||
|
|
||||||
void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HWND window_ = nullptr;
|
|
||||||
std::shared_ptr<IOleObject> browser_object_;
|
|
||||||
|
|
||||||
ole_in_place_frame in_place_frame_;
|
|
||||||
ole_in_place_site in_place_site_;
|
|
||||||
doc_host_ui_handler ui_handler_;
|
|
||||||
ole_client_site client_site_;
|
|
||||||
html_dispatch html_dispatch_;
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_;
|
|
||||||
|
|
||||||
void create_browser();
|
|
||||||
void initialize_browser();
|
|
||||||
|
|
||||||
static bool set_browser_feature(const std::string& feature, DWORD value);
|
|
||||||
static void object_deleter(IUnknown* object);
|
|
||||||
|
|
||||||
static std::atomic<int> frame_count_;
|
|
||||||
};
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_window.hpp"
|
|
||||||
|
|
||||||
window* html_window::get_window()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
html_frame* html_window::get_html_frame()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
|
||||||
{
|
|
||||||
if (message == WM_SIZE)
|
|
||||||
{
|
|
||||||
this->resize(LOWORD(l_param), HIWORD(l_param));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message == WM_CREATE)
|
|
||||||
{
|
|
||||||
this->initialize(*this);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window::processor(message, w_param, l_param);
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "../window.hpp"
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
class html_window final : public window, public html_frame
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~html_window() = default;
|
|
||||||
|
|
||||||
window* get_window();
|
|
||||||
html_frame* get_html_frame();
|
|
||||||
|
|
||||||
private:
|
|
||||||
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override;
|
|
||||||
};
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
ole_client_site::ole_client_site(html_frame* frame): frame_(frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject)
|
|
||||||
{
|
|
||||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
|
||||||
!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
|
|
||||||
{
|
|
||||||
*ppvObject = this;
|
|
||||||
this->AddRef();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
|
|
||||||
{
|
|
||||||
auto in_place_site = this->frame_->get_in_place_site();
|
|
||||||
in_place_site->AddRef();
|
|
||||||
*ppvObject = in_place_site;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID)))
|
|
||||||
{
|
|
||||||
auto ui_handler = this->frame_->get_ui_handler();
|
|
||||||
ui_handler->AddRef();
|
|
||||||
*ppvObject = ui_handler;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppvObject = nullptr;
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_client_site::AddRef()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_client_site::Release()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::SaveObject()
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer)
|
|
||||||
{
|
|
||||||
*ppContainer = nullptr;
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::ShowObject()
|
|
||||||
{
|
|
||||||
return NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_client_site::RequestNewObjectLayout()
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_frame;
|
|
||||||
|
|
||||||
class ole_client_site final : public IOleClientSite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ole_client_site(html_frame* frame);
|
|
||||||
virtual ~ole_client_site() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
html_frame* frame_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override;
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
|
||||||
ULONG STDMETHODCALLTYPE Release() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE SaveObject() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ShowObject() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override;
|
|
||||||
};
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_in_place_frame::AddRef()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_in_place_frame::Release()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd)
|
|
||||||
{
|
|
||||||
*lphwnd = this->frame_->get_window();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_frame;
|
|
||||||
|
|
||||||
class ole_in_place_frame final : public IOleInPlaceFrame
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ole_in_place_frame(html_frame* frame);
|
|
||||||
virtual ~ole_in_place_frame() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
html_frame* frame_;
|
|
||||||
|
|
||||||
public: // IOleInPlaceFrame interface
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
|
||||||
ULONG STDMETHODCALLTYPE Release() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override;
|
|
||||||
};
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "html_frame.hpp"
|
|
||||||
|
|
||||||
ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
|
||||||
{
|
|
||||||
auto client_site = this->frame_->get_client_site();
|
|
||||||
if (client_site)
|
|
||||||
{
|
|
||||||
return client_site->QueryInterface(riid, ppvObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_in_place_site::AddRef()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG ole_in_place_site::Release()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::GetWindow(HWND* lphwnd)
|
|
||||||
{
|
|
||||||
*lphwnd = this->frame_->get_window();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::CanInPlaceActivate()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::OnInPlaceActivate()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::OnUIActivate()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
|
|
||||||
LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/,
|
|
||||||
LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
|
||||||
{
|
|
||||||
*lplpFrame = this->frame_->get_in_place_frame();
|
|
||||||
*lplpDoc = nullptr;
|
|
||||||
|
|
||||||
lpFrameInfo->fMDIApp = FALSE;
|
|
||||||
lpFrameInfo->hwndFrame = this->frame_->get_window();
|
|
||||||
lpFrameInfo->haccel = nullptr;
|
|
||||||
lpFrameInfo->cAccelEntries = 0;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/)
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/)
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::OnInPlaceDeactivate()
|
|
||||||
{
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::DiscardUndoState()
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::DeactivateAndUndo()
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect)
|
|
||||||
{
|
|
||||||
IOleInPlaceObject* in_place = nullptr;
|
|
||||||
if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place)))
|
|
||||||
{
|
|
||||||
in_place->SetObjectRects(lprcPosRect, lprcPosRect);
|
|
||||||
in_place->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class html_frame;
|
|
||||||
|
|
||||||
class ole_in_place_site final : public IOleInPlaceSite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ole_in_place_site(html_frame* frame);
|
|
||||||
virtual ~ole_in_place_site() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
html_frame* frame_;
|
|
||||||
|
|
||||||
public: // IOleInPlaceSite interface
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
|
||||||
ULONG STDMETHODCALLTYPE Release() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnUIActivate() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc,
|
|
||||||
LPRECT lprcPosRect, LPRECT lprcClipRect,
|
|
||||||
LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE DiscardUndoState() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override;
|
|
||||||
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override;
|
|
||||||
};
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "launcher.hpp"
|
|
||||||
|
|
||||||
#include <utils/nt.hpp>
|
|
||||||
|
|
||||||
launcher::launcher()
|
|
||||||
{
|
|
||||||
this->create_main_menu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void launcher::create_main_menu()
|
|
||||||
{
|
|
||||||
this->main_window_.register_callback("openUrl", [](html_frame::callback_params* params)
|
|
||||||
{
|
|
||||||
if (params->arguments.empty()) return;
|
|
||||||
|
|
||||||
const auto param = params->arguments[0];
|
|
||||||
if (!param.is_string()) return;
|
|
||||||
|
|
||||||
const auto url = param.get_string();
|
|
||||||
ShellExecuteA(nullptr, "open", url.data(), nullptr, nullptr, SW_SHOWNORMAL);
|
|
||||||
});
|
|
||||||
|
|
||||||
this->main_window_.register_callback("selectMode", [this](html_frame::callback_params* params)
|
|
||||||
{
|
|
||||||
if (params->arguments.empty()) return;
|
|
||||||
|
|
||||||
const auto param = params->arguments[0];
|
|
||||||
if (!param.is_number()) return;
|
|
||||||
|
|
||||||
const auto number = static_cast<mode>(param.get_number());
|
|
||||||
if (number == mode::singleplayer || number == mode::multiplayer)
|
|
||||||
{
|
|
||||||
this->select_mode(number);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this->main_window_.set_callback(
|
|
||||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
|
||||||
{
|
|
||||||
if (message == WM_CLOSE)
|
|
||||||
{
|
|
||||||
window::close_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProcA(*window, message, w_param, l_param);
|
|
||||||
});
|
|
||||||
|
|
||||||
this->main_window_.create("iw6-mod", 750, 420);
|
|
||||||
this->main_window_.load_html(load_content(MENU_MAIN));
|
|
||||||
this->main_window_.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
launcher::mode launcher::run() const
|
|
||||||
{
|
|
||||||
window::run();
|
|
||||||
return this->mode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void launcher::select_mode(const mode mode)
|
|
||||||
{
|
|
||||||
this->mode_ = mode;
|
|
||||||
this->main_window_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string launcher::load_content(const int res)
|
|
||||||
{
|
|
||||||
return utils::nt::load_resource(res);
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "html/html_window.hpp"
|
|
||||||
|
|
||||||
class launcher final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum class mode
|
|
||||||
{
|
|
||||||
none,
|
|
||||||
singleplayer,
|
|
||||||
multiplayer,
|
|
||||||
server,
|
|
||||||
};
|
|
||||||
|
|
||||||
launcher();
|
|
||||||
|
|
||||||
mode run() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mode mode_ = mode::none;
|
|
||||||
|
|
||||||
html_window main_window_;
|
|
||||||
|
|
||||||
void select_mode(mode mode);
|
|
||||||
|
|
||||||
void create_main_menu();
|
|
||||||
|
|
||||||
static std::string load_content(int res);
|
|
||||||
};
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
#include <std_include.hpp>
|
|
||||||
#include "window.hpp"
|
|
||||||
|
|
||||||
#include <utils/nt.hpp>
|
|
||||||
|
|
||||||
std::mutex window::mutex_;
|
|
||||||
std::vector<window*> window::windows_;
|
|
||||||
|
|
||||||
window::window()
|
|
||||||
{
|
|
||||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
|
||||||
|
|
||||||
this->classname_ = "window-base-" + std::to_string(time(nullptr));
|
|
||||||
|
|
||||||
this->wc_.cbSize = sizeof(this->wc_);
|
|
||||||
this->wc_.style = CS_HREDRAW | CS_VREDRAW;
|
|
||||||
this->wc_.lpfnWndProc = static_processor;
|
|
||||||
this->wc_.hInstance = GetModuleHandle(nullptr);
|
|
||||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
|
||||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
|
||||||
this->wc_.hIconSm = this->wc_.hIcon;
|
|
||||||
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
|
|
||||||
this->wc_.lpszClassName = this->classname_.data();
|
|
||||||
RegisterClassEx(&this->wc_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::create(const std::string& title, const int width, const int height, const long flags)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::lock_guard _(mutex_);
|
|
||||||
windows_.push_back(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
|
||||||
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
|
||||||
|
|
||||||
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr,
|
|
||||||
nullptr, this->wc_.hInstance, this);
|
|
||||||
|
|
||||||
SendMessageA(this->handle_, WM_DPICHANGED, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
window::~window()
|
|
||||||
{
|
|
||||||
this->close();
|
|
||||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::close()
|
|
||||||
{
|
|
||||||
if (!this->handle_) return;
|
|
||||||
|
|
||||||
SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL);
|
|
||||||
this->handle_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::run()
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
while (GetMessage(&msg, nullptr, 0, 0))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::close_all()
|
|
||||||
{
|
|
||||||
std::unique_lock lock(mutex_);
|
|
||||||
auto window_list = windows_;
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
const auto current_thread_id = GetCurrentThreadId();
|
|
||||||
for (auto& window : window_list)
|
|
||||||
{
|
|
||||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
|
||||||
|
|
||||||
if (thread_id == current_thread_id)
|
|
||||||
{
|
|
||||||
window->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::remove_window(const window* window)
|
|
||||||
{
|
|
||||||
std::lock_guard _(mutex_);
|
|
||||||
|
|
||||||
for (auto i = windows_.begin(); i != windows_.end(); ++i)
|
|
||||||
{
|
|
||||||
if (*i == window)
|
|
||||||
{
|
|
||||||
windows_.erase(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int window::get_window_count()
|
|
||||||
{
|
|
||||||
std::lock_guard _(mutex_);
|
|
||||||
|
|
||||||
auto count = 0;
|
|
||||||
const auto current_thread_id = GetCurrentThreadId();
|
|
||||||
|
|
||||||
for (const auto& window : windows_)
|
|
||||||
{
|
|
||||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
|
||||||
|
|
||||||
if (thread_id == current_thread_id)
|
|
||||||
{
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::show() const
|
|
||||||
{
|
|
||||||
ShowWindow(this->handle_, SW_SHOW);
|
|
||||||
UpdateWindow(this->handle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::hide() const
|
|
||||||
{
|
|
||||||
ShowWindow(this->handle_, SW_HIDE);
|
|
||||||
UpdateWindow(this->handle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback)
|
|
||||||
{
|
|
||||||
this->callback_ = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
|
||||||
{
|
|
||||||
if (message == WM_DPICHANGED)
|
|
||||||
{
|
|
||||||
const utils::nt::library user32{"user32.dll"};
|
|
||||||
const auto get_dpi = user32 ? user32.get_proc<UINT(WINAPI *)(HWND)>("GetDpiForWindow") : nullptr;
|
|
||||||
|
|
||||||
if (get_dpi)
|
|
||||||
{
|
|
||||||
const auto dpi = get_dpi(*this);
|
|
||||||
if (dpi != this->last_dpi_)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
GetWindowRect(*this, &rect);
|
|
||||||
|
|
||||||
const auto scale = dpi * 1.0 / this->last_dpi_;
|
|
||||||
this->last_dpi_ = dpi;
|
|
||||||
|
|
||||||
const auto width = rect.right - rect.left;
|
|
||||||
const auto height = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
MoveWindow(*this, rect.left, rect.top, int(width * scale), int(height * scale), TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message == WM_DESTROY)
|
|
||||||
{
|
|
||||||
remove_window(this);
|
|
||||||
|
|
||||||
if (get_window_count() == 0)
|
|
||||||
{
|
|
||||||
PostQuitMessage(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message == WM_KILL_WINDOW)
|
|
||||||
{
|
|
||||||
DestroyWindow(*this);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->callback_)
|
|
||||||
{
|
|
||||||
return this->callback_(this, message, w_param, l_param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(*this, message, w_param, l_param);
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
|
|
||||||
{
|
|
||||||
if (message == WM_CREATE)
|
|
||||||
{
|
|
||||||
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
|
|
||||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
|
|
||||||
|
|
||||||
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
|
||||||
if (self) return self->processor(message, w_param, l_param);
|
|
||||||
|
|
||||||
return DefWindowProc(hwnd, message, w_param, l_param);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
window::operator HWND() const
|
|
||||||
{
|
|
||||||
return this->handle_;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define WM_KILL_WINDOW (WM_USER+0)
|
|
||||||
|
|
||||||
class window
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
window();
|
|
||||||
virtual ~window();
|
|
||||||
|
|
||||||
void create(const std::string& title, int width, int height,
|
|
||||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
|
||||||
|
|
||||||
void close();
|
|
||||||
|
|
||||||
void show() const;
|
|
||||||
void hide() const;
|
|
||||||
|
|
||||||
void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback);
|
|
||||||
|
|
||||||
operator HWND() const;
|
|
||||||
|
|
||||||
static void run();
|
|
||||||
static void close_all();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t last_dpi_ = 96;
|
|
||||||
|
|
||||||
WNDCLASSEX wc_{};
|
|
||||||
HWND handle_ = nullptr;
|
|
||||||
std::string classname_;
|
|
||||||
std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_;
|
|
||||||
|
|
||||||
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
|
|
||||||
|
|
||||||
static std::mutex mutex_;
|
|
||||||
static std::vector<window*> windows_;
|
|
||||||
|
|
||||||
static void remove_window(const window* window);
|
|
||||||
static int get_window_count();
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <utils/nt.hpp>
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
#include "launcher/launcher.hpp"
|
|
||||||
|
|
||||||
class loader final
|
class loader final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
+1
-12
@@ -1,5 +1,4 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "launcher/launcher.hpp"
|
|
||||||
#include "loader/loader.hpp"
|
#include "loader/loader.hpp"
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
@@ -109,11 +108,6 @@ launcher::mode detect_mode_from_arguments()
|
|||||||
return launcher::mode::multiplayer;
|
return launcher::mode::multiplayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utils::flags::has_flag("singleplayer"))
|
|
||||||
{
|
|
||||||
return launcher::mode::singleplayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return launcher::mode::none;
|
return launcher::mode::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,9 +148,6 @@ FARPROC load_binary(const launcher::mode mode)
|
|||||||
case launcher::mode::multiplayer:
|
case launcher::mode::multiplayer:
|
||||||
binary = "iw6mp64_ship.exe";
|
binary = "iw6mp64_ship.exe";
|
||||||
break;
|
break;
|
||||||
case launcher::mode::singleplayer:
|
|
||||||
binary = "iw6sp64_ship.exe";
|
|
||||||
break;
|
|
||||||
case launcher::mode::none:
|
case launcher::mode::none:
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid game mode!");
|
throw std::runtime_error("Invalid game mode!");
|
||||||
@@ -277,9 +268,7 @@ int main()
|
|||||||
auto mode = detect_mode_from_arguments();
|
auto mode = detect_mode_from_arguments();
|
||||||
if (mode == launcher::mode::none)
|
if (mode == launcher::mode::none)
|
||||||
{
|
{
|
||||||
const launcher launcher;
|
mode = launcher::mode::multiplayer;
|
||||||
mode = launcher.run();
|
|
||||||
if (mode == launcher::mode::none) return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
game::environment::set_mode(mode);
|
game::environment::set_mode(mode);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ BEGIN
|
|||||||
VALUE "FileDescription", "iw6-mod"
|
VALUE "FileDescription", "iw6-mod"
|
||||||
VALUE "FileVersion", VERSION_FILE
|
VALUE "FileVersion", VERSION_FILE
|
||||||
VALUE "InternalName", "iw6-mod"
|
VALUE "InternalName", "iw6-mod"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2023 AlterWare. All rights reserved."
|
VALUE "LegalCopyright", "Copyright (C) 2026 AlterWare. All rights reserved."
|
||||||
VALUE "Licence", "GPLv3"
|
VALUE "Licence", "GPLv3"
|
||||||
VALUE "Info", "https://alterware.dev"
|
VALUE "Info", "https://alterware.dev"
|
||||||
VALUE "OriginalFilename", "iw6-mod.exe"
|
VALUE "OriginalFilename", "iw6-mod.exe"
|
||||||
|
|||||||
Reference in New Issue
Block a user