commit
4a44785941
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -45,3 +45,6 @@
|
||||
path = deps/zlib
|
||||
url = https://github.com/madler/zlib.git
|
||||
branch = develop
|
||||
[submodule "deps/curl"]
|
||||
path = deps/curl
|
||||
url = https://github.com/curl/curl.git
|
||||
|
@ -4,6 +4,7 @@ end
|
||||
|
||||
if (Engine.InFrontend()) then
|
||||
require("shaderdialog")
|
||||
require("gamemodes")
|
||||
end
|
||||
|
||||
-- defined in mp_hud/hudutils.lua
|
||||
|
@ -1,7 +1,3 @@
|
||||
if (game:issingleplayer() or not Engine.InFrontend()) then
|
||||
return
|
||||
end
|
||||
|
||||
Cac.GameModes.Data = {
|
||||
Standard = {
|
||||
Label = Engine.Localize("@MPUI_STANDARD_CAPS"),
|
@ -7,6 +7,8 @@ end
|
||||
|
||||
game:addlocalizedstring("MENU_NUMPLAYERS", "Players")
|
||||
game:addlocalizedstring("MENU_PING", "Ping")
|
||||
game:addlocalizedstring("SERVERLIST_PLAYER_COUNT", "&&1 Players")
|
||||
game:addlocalizedstring("SERVERLIST_SERVER_COUNT", "&&1 Servers")
|
||||
|
||||
local columns = {
|
||||
{
|
||||
@ -195,8 +197,33 @@ function menu_systemlink_join(f19_arg0, f19_arg1)
|
||||
SystemLinkJoinMenu.UpdateCounterText(menu, nil)
|
||||
Lobby.BuildServerList(Engine.GetFirstActiveController())
|
||||
|
||||
local playercount = LUI.UIText.new({
|
||||
rightAnchor = true,
|
||||
topAnchor = true,
|
||||
height = 18,
|
||||
bottom = 58,
|
||||
font = CoD.TextSettings.BodyFont.Font,
|
||||
width = 300,
|
||||
alignment = LUI.Alignment.Right,
|
||||
})
|
||||
menu:addElement(playercount)
|
||||
|
||||
local servercount = LUI.UIText.new({
|
||||
rightAnchor = true,
|
||||
topAnchor = true,
|
||||
height = 18,
|
||||
bottom = 58 - 25,
|
||||
font = CoD.TextSettings.BodyFont.Font,
|
||||
width = 300,
|
||||
alignment = LUI.Alignment.Right,
|
||||
})
|
||||
menu:addElement(servercount)
|
||||
|
||||
menu.list:registerEventHandler(LUI.UIScrollIndicator.UpdateEvent, function(element, event)
|
||||
SystemLinkJoinMenu.UpdateCounterText(menu, event)
|
||||
|
||||
playercount:setText(Engine.Localize("@SERVERLIST_PLAYER_COUNT", serverlist:getplayercount()))
|
||||
servercount:setText(Engine.Localize("@SERVERLIST_SERVER_COUNT", serverlist:getservercount()))
|
||||
end)
|
||||
|
||||
SystemLinkJoinMenu.UpdateGameList(menu)
|
||||
|
2
deps/asmjit
vendored
2
deps/asmjit
vendored
@ -1 +1 @@
|
||||
Subproject commit 06d0badec53710a4f572cf5642881ce570c5d274
|
||||
Subproject commit 35f92e8706db78c6aa7482b5e1cdb59c5972a965
|
1
deps/curl
vendored
Submodule
1
deps/curl
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e2e7f54b7bea521fa8373095d0f43261a720cda0
|
73
deps/premake/curl.lua
vendored
Normal file
73
deps/premake/curl.lua
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
curl = {
|
||||
source = path.join(dependencies.basePath, "curl"),
|
||||
}
|
||||
|
||||
function curl.import()
|
||||
links { "curl" }
|
||||
|
||||
filter "toolset:msc*"
|
||||
links { "Crypt32.lib" }
|
||||
filter {}
|
||||
|
||||
curl.includes()
|
||||
end
|
||||
|
||||
function curl.includes()
|
||||
filter "toolset:msc*"
|
||||
includedirs {
|
||||
path.join(curl.source, "include"),
|
||||
}
|
||||
|
||||
defines {
|
||||
"CURL_STRICTER",
|
||||
"CURL_STATICLIB",
|
||||
"CURL_DISABLE_LDAP",
|
||||
}
|
||||
filter {}
|
||||
end
|
||||
|
||||
function curl.project()
|
||||
if not os.istarget("windows") then
|
||||
return
|
||||
end
|
||||
|
||||
project "curl"
|
||||
language "C"
|
||||
|
||||
curl.includes()
|
||||
|
||||
includedirs {
|
||||
path.join(curl.source, "lib"),
|
||||
}
|
||||
|
||||
files {
|
||||
path.join(curl.source, "lib/**.c"),
|
||||
path.join(curl.source, "lib/**.h"),
|
||||
}
|
||||
|
||||
defines {
|
||||
"BUILDING_LIBCURL",
|
||||
}
|
||||
|
||||
filter "toolset:msc*"
|
||||
|
||||
defines {
|
||||
"USE_SCHANNEL",
|
||||
"USE_WINDOWS_SSPI",
|
||||
"USE_THREADS_WIN32",
|
||||
}
|
||||
|
||||
filter "toolset:not msc*"
|
||||
|
||||
defines {
|
||||
"USE_GNUTLS",
|
||||
"USE_THREADS_POSIX",
|
||||
}
|
||||
|
||||
filter {}
|
||||
|
||||
warnings "Off"
|
||||
kind "StaticLib"
|
||||
end
|
||||
|
||||
table.insert(dependencies, curl)
|
2
deps/sol2
vendored
2
deps/sol2
vendored
@ -1 +1 @@
|
||||
Subproject commit c9055478c7c437f9a97610329701652673ab8262
|
||||
Subproject commit dca62a0f02bb45f3de296de3ce00b1275eb34c25
|
@ -42,7 +42,7 @@ namespace auth
|
||||
|
||||
std::string get_protected_data()
|
||||
{
|
||||
std::string input = "X-Labs-H1Mod-Auth";
|
||||
std::string input = "H1Mod-Auth";
|
||||
|
||||
DATA_BLOB data_in{}, data_out{};
|
||||
data_in.pbData = reinterpret_cast<uint8_t*>(input.data());
|
||||
|
@ -138,21 +138,37 @@ namespace discord
|
||||
{
|
||||
const auto data = utils::http::get_data(
|
||||
utils::string::va(AVATAR_URL, id.data(), avatar.data()));
|
||||
if (data.has_value())
|
||||
if (!data.has_value())
|
||||
{
|
||||
materials::add(utils::string::va(AVATAR, id.data()), data.value());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value = data.value();
|
||||
if (value.code != CURLE_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
materials::add(utils::string::va(AVATAR, id.data()), value.buffer);
|
||||
}
|
||||
|
||||
bool has_default_avatar = false;
|
||||
void download_default_avatar()
|
||||
{
|
||||
const auto data = utils::http::get_data(DEFAULT_AVATAR_URL);
|
||||
if (data.has_value())
|
||||
if (!data.has_value())
|
||||
{
|
||||
has_default_avatar = true;
|
||||
materials::add(DEFAULT_AVATAR, data.value());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value = data.value();
|
||||
if (value.code != CURLE_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
has_default_avatar = true;
|
||||
materials::add(DEFAULT_AVATAR, value.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,16 +5,67 @@
|
||||
|
||||
#include "command.hpp"
|
||||
#include "console.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace lui
|
||||
{
|
||||
namespace
|
||||
{
|
||||
uint64_t event_count{};
|
||||
bool begin_game_message_event_stub(int a1, const char* name, void* a3)
|
||||
{
|
||||
if (event_count > 30)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
event_count++;
|
||||
}
|
||||
|
||||
return utils::hook::invoke<bool>(0x2655A0_b, a1, name, a3);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
// Patch game message overflow
|
||||
utils::hook::call(0x266E6B_b, begin_game_message_event_stub);
|
||||
|
||||
scheduler::loop([]()
|
||||
{
|
||||
if (event_count > 0)
|
||||
{
|
||||
event_count--;
|
||||
}
|
||||
}, scheduler::pipeline::lui, 50ms);
|
||||
}
|
||||
|
||||
// Increase max extra LUI memory
|
||||
/*const auto max_memory = 0x900000 * 2;
|
||||
utils::hook::set<uint32_t>(0x278E61_b - 4, max_memory);
|
||||
utils::hook::set<uint32_t>(0x27A2C5_b - 4, max_memory);
|
||||
utils::hook::set<uint32_t>(0x27A993_b - 4, max_memory);
|
||||
utils::hook::set<uint32_t>(0x27AB3A_b - 4, max_memory);
|
||||
utils::hook::set<uint32_t>(0x27AB35_b - 4, max_memory);
|
||||
utils::hook::set<uint32_t>(0x27C002_b - 4, max_memory);*/
|
||||
|
||||
// Increase max extra frontend memory
|
||||
/*const auto max_frontend_memory = 0x180000 * 2;
|
||||
utils::hook::set<uint32_t>(0x278EA6_b - 4, max_frontend_memory);
|
||||
utils::hook::set<uint32_t>(0x278F01_b - 4, max_frontend_memory);
|
||||
utils::hook::set<uint32_t>(0x27A2D4_b - 4, max_frontend_memory);
|
||||
utils::hook::set<uint32_t>(0x27A2E3_b - 4, max_frontend_memory);
|
||||
utils::hook::set<uint32_t>(0x27F9E9_b - 4, max_frontend_memory);
|
||||
utils::hook::set<uint32_t>(0x27FA84_b - 4, max_frontend_memory);*/
|
||||
|
||||
command::add("lui_open", [](const command::params& params)
|
||||
{
|
||||
if (params.size() <= 1)
|
||||
|
@ -123,9 +123,10 @@ namespace patches
|
||||
const auto menu_id = atoi(params.get(1));
|
||||
const auto client = &svs_clients[ent->s.entityNum];
|
||||
|
||||
// 22 => "end_game"
|
||||
if (menu_id == 22 && client->header.remoteAddress.type != game::NA_LOOPBACK)
|
||||
// 32 => "end_game"
|
||||
if (menu_id == 32 && client->header.remoteAddress.type != game::NA_LOOPBACK)
|
||||
{
|
||||
game::SV_DropClient_Internal(client, "PLATFORM_STEAM_KICK_CHEAT", true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -194,15 +195,74 @@ namespace patches
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
return utils::hook::invoke<int>(SELECT_VALUE(0x429200_b, 0x5AF0F0_b), dest, size, "%s", buffer);
|
||||
}
|
||||
|
||||
void create_2d_texture_stub_1(const char* fmt, ...)
|
||||
{
|
||||
fmt = "Create2DTexture( %s, %i, %i, %i, %i ) failed\n\n"
|
||||
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.";
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
game::Sys_Error("%s", buffer);
|
||||
}
|
||||
|
||||
void create_2d_texture_stub_2(game::errorParm code, const char* fmt, ...)
|
||||
{
|
||||
fmt = "Create2DTexture( %s, %i, %i, %i, %i ) failed\n\n"
|
||||
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.";
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
game::Com_Error(code, "%s", buffer);
|
||||
}
|
||||
|
||||
void swap_chain_stub(game::errorParm code, const char* fmt, ...)
|
||||
{
|
||||
fmt = "IDXGISwapChain::Present failed: %s\n\n"
|
||||
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.";
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
game::Com_Error(code, "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -242,13 +302,10 @@ namespace patches
|
||||
utils::hook::call(SELECT_VALUE(0x376EB5_b, 0x156D41_b), db_read_raw_file_stub);
|
||||
|
||||
// Remove useless information from errors + add additional help to common errors
|
||||
utils::hook::set<const char*>(SELECT_VALUE(0x7E3DF0_b, 0x937B80_b),
|
||||
"Create2DTexture( %s, %i, %i, %i, %i ) failed\n\n"
|
||||
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.");
|
||||
utils::hook::set<const char*>(SELECT_VALUE(0x800EA8_b, 0x954FF0_b),
|
||||
"IDXGISwapChain::Present failed: %s\n\n"
|
||||
"Disable shader caching, lower graphic settings, free up RAM, or update your GPU drivers.");
|
||||
utils::hook::call(SELECT_VALUE(0x457BC9_b, 0x1D8E09_b), out_of_memory_text_stub); // "Out of memory. You are probably low on disk space."
|
||||
utils::hook::call(SELECT_VALUE(0x55E919_b, 0x681A69_b), create_2d_texture_stub_1); // Sys_Error for "Create2DTexture( %s, %i, %i, %i, %i ) failed"
|
||||
utils::hook::call(SELECT_VALUE(0x55EACB_b, 0x681C1B_b), create_2d_texture_stub_2); // Com_Error for ^
|
||||
utils::hook::call(SELECT_VALUE(0x5B35BA_b, 0x6CB1BC_b), swap_chain_stub); // Com_Error for "IDXGISwapChain::Present failed: %s"
|
||||
utils::hook::call(SELECT_VALUE(0x457BC9_b, 0x1D8E09_b), out_of_memory_text_stub); // Com_sprintf for "Out of memory. You are probably low on disk space."
|
||||
|
||||
// "fix" for rare 'Out of memory error' error
|
||||
// this will *at least* generate the configs for mp/sp, which is the #1 issue
|
||||
|
@ -375,6 +375,23 @@ namespace server_list
|
||||
insert_server(std::move(server));
|
||||
}
|
||||
|
||||
int get_player_count()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
auto count = 0;
|
||||
for (const auto& server : servers)
|
||||
{
|
||||
count += server.clients - server.bots;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int get_server_count()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
return static_cast<int>(servers.size());
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -9,4 +9,7 @@ namespace server_list
|
||||
void handle_info_response(const game::netadr_s& address, const utils::info_string& info);
|
||||
|
||||
bool sl_key_event(int key, int down);
|
||||
|
||||
int get_player_count();
|
||||
int get_server_count();
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
#include "fastfiles.hpp"
|
||||
#include "scripting.hpp"
|
||||
#include "updater.hpp"
|
||||
#include "server_list.hpp"
|
||||
|
||||
#include "game/ui_scripting/execution.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
@ -342,6 +343,12 @@ namespace ui_scripting
|
||||
::game::Dvar_SetFromStringByNameFromSource("virtualLobbyPresentable", "1", ::game::DvarSetSource::DVAR_SOURCE_INTERNAL);
|
||||
};
|
||||
|
||||
auto server_list_table = table();
|
||||
lua["serverlist"] = server_list_table;
|
||||
|
||||
server_list_table["getplayercount"] = server_list::get_player_count;
|
||||
server_list_table["getservercount"] = server_list::get_server_count;
|
||||
|
||||
auto updater_table = table();
|
||||
lua["updater"] = updater_table;
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
#define DATA_PATH "data/"
|
||||
#define DATA_PATH_DEV "data-dev/"
|
||||
|
||||
#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates"
|
||||
#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates:\n%s"
|
||||
#define ERR_UPDATE_CHECK_FAIL_BAD_RESPONSE "Bad response"
|
||||
#define ERR_DOWNLOAD_FAIL "Failed to download file "
|
||||
#define ERR_DOWNLOAD_FAIL "Failed to download file %s:\n%s"
|
||||
#define ERR_WRITE_FAIL "Failed to write file "
|
||||
|
||||
#define BINARY_NAME "h1-mod.exe"
|
||||
@ -139,7 +139,7 @@ namespace updater
|
||||
return utils::string::va("%i", uint32_t(time(nullptr)));
|
||||
}
|
||||
|
||||
std::optional<std::string> download_file(const std::string& name)
|
||||
std::optional<utils::http::result> download_file(const std::string& name)
|
||||
{
|
||||
return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str());
|
||||
}
|
||||
@ -191,6 +191,12 @@ namespace updater
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string curl_error(CURLcode code)
|
||||
{
|
||||
const auto str_error = curl_easy_strerror(code);
|
||||
return utils::string::va("%s (%i)", str_error, code);
|
||||
}
|
||||
}
|
||||
|
||||
// workaround
|
||||
@ -337,12 +343,20 @@ namespace updater
|
||||
|
||||
if (!files_data.has_value())
|
||||
{
|
||||
set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL);
|
||||
set_update_check_status(true, false, utils::string::va(ERR_UPDATE_CHECK_FAIL, "Unknown error"));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value = files_data.value();
|
||||
if (value.code != CURLE_OK)
|
||||
{
|
||||
const auto error = curl_error(value.code);
|
||||
set_update_check_status(true, false, utils::string::va(ERR_UPDATE_CHECK_FAIL, error.data()));
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document j;
|
||||
j.Parse(files_data.value().data());
|
||||
j.Parse(value.buffer.data());
|
||||
|
||||
if (!j.IsArray())
|
||||
{
|
||||
@ -433,11 +447,19 @@ namespace updater
|
||||
|
||||
if (!data.has_value())
|
||||
{
|
||||
set_update_download_status(true, false, ERR_DOWNLOAD_FAIL + file);
|
||||
set_update_download_status(true, false, utils::string::va(ERR_DOWNLOAD_FAIL, file.data(), "Unknown error"));
|
||||
return;
|
||||
}
|
||||
|
||||
downloads.push_back({file, data.value()});
|
||||
const auto& value = data.value();
|
||||
if (value.code != CURLE_OK)
|
||||
{
|
||||
const auto error = curl_error(value.code);
|
||||
set_update_download_status(true, false, utils::string::va(ERR_DOWNLOAD_FAIL, file.data(), error.data()));
|
||||
return;
|
||||
}
|
||||
|
||||
downloads.push_back({file, value.buffer});
|
||||
}
|
||||
|
||||
for (const auto& download : downloads)
|
||||
|
@ -1500,12 +1500,12 @@ namespace scripting
|
||||
{"_meth_82e8", 0x82E8}, // SP 0x000000 MP 0x411730
|
||||
{"_meth_82e9", 0x82E9}, // SP 0x000000 MP 0x411720
|
||||
{"_meth_82ea", 0x82EA}, // SP 0x2905B0 MP 0x40BAD0
|
||||
{"_meth_82eb", 0x82EB}, // SP 0x28F5E0 MP 0x40AB90
|
||||
{"_meth_82ec", 0x82EC}, // SP 0x28F6D0 MP 0x40ACC0
|
||||
{"fragbuttonpressed", 0x82EB}, // SP 0x28F5E0 MP 0x40AB90
|
||||
{"secondaryoffhandbuttonpressed", 0x82EC}, // SP 0x28F6D0 MP 0x40ACC0
|
||||
{"issighted", 0x82ED}, // SP 0x2919D0 MP 0x40D2E0
|
||||
{"setvelocity", 0x82EE}, // SP 0x28DC30 MP 0x4090E0
|
||||
{"_meth_82ef", 0x82EF}, // SP 0x28E570 MP 0x409920
|
||||
{"_meth_82f0", 0x82F0}, // SP 0x28E980 MP 0x409B70
|
||||
{"getnormalizedmovement", 0x82F0}, // SP 0x28E980 MP 0x409B70
|
||||
{"playlocalsound", 0x82F1}, // SP 0x28DAC0 MP 0x409330
|
||||
{"stoplocalsound", 0x82F2}, // SP 0x28DBA0 MP 0x409420
|
||||
{"setweaponammoclip", 0x82F3}, // SP 0x2928A0 MP 0x405D60
|
||||
@ -1603,7 +1603,7 @@ namespace scripting
|
||||
{"botsetstance", 0x8350}, // SP 0x000000 MP 0x5473D0
|
||||
{"botsetscriptmove", 0x8351}, // SP 0x000000 MP 0x547250
|
||||
{"_meth_8352", 0x8352}, // SP 0x000000 MP 0x546EA0
|
||||
{"_meth_8353", 0x8353}, // SP 0x000000 MP 0x547090
|
||||
{"botsetscriptgoal", 0x8353}, // SP 0x000000 MP 0x547090
|
||||
{"botclearscriptgoal", 0x8354}, // SP 0x000000 MP 0x544F60
|
||||
{"getnearestnode", 0x8355}, // SP 0x000000 MP 0x546DE0
|
||||
{"botclearscriptenemy", 0x8356}, // SP 0x000000 MP 0x544EE0
|
||||
@ -1616,7 +1616,7 @@ namespace scripting
|
||||
{"_meth_835e", 0x835E}, // SP 0x000000 MP 0x5460F0
|
||||
{"botfindnoderandom", 0x835F}, // SP 0x000000 MP 0x544FE0
|
||||
{"botmemoryevent", 0x8360}, // SP 0x000000 MP 0x545E50
|
||||
{"_meth_8362", 0x8362}, // SP 0x000000 MP 0x546190
|
||||
{"botnodepick", 0x8362}, // SP 0x000000 MP 0x546190
|
||||
{"bothasscriptgoal", 0x8363}, // SP 0x000000 MP 0x545B70
|
||||
{"botgetpersonality", 0x8364}, // SP 0x000000 MP 0x545700
|
||||
{"_meth_8365", 0x8365}, // SP 0x000000 MP 0x5474A0
|
||||
@ -2890,10 +2890,10 @@ namespace scripting
|
||||
{"origin", 0x2DF},
|
||||
{"other", 0x2E0},
|
||||
{"over", 0x2E1},
|
||||
{"owner", 0x2E2},
|
||||
{"_not_owner", 0x2E2}, // was "owner"
|
||||
{"pacifist", 0x2E3},
|
||||
{"pacifistwait", 0x2E4},
|
||||
{"pain", 0x2E5},
|
||||
{"owner", 0x2E5}, // was "pain"
|
||||
{"pantssize", 0x2E6},
|
||||
{"parentindex", 0x2E7},
|
||||
{"parentname", 0x2E8},
|
||||
@ -2925,10 +2925,10 @@ namespace scripting
|
||||
{"perkrestricted", 0x302},
|
||||
{"perks", 0x303},
|
||||
{"perkslots", 0x304},
|
||||
{"pers", 0x305},
|
||||
{"_not_pers", 0x305}, // was "pers"
|
||||
{"persistentperksunlocked", 0x306},
|
||||
{"persistentweaponsunlocked", 0x307},
|
||||
{"phone_off", 0x308},
|
||||
{"pers", 0x308}, // was "phone_off"
|
||||
{"phone_on", 0x309},
|
||||
{"physics_finished", 0x30A},
|
||||
{"physics_impact", 0x30B},
|
||||
@ -3312,10 +3312,10 @@ namespace scripting
|
||||
{"tag_sight_off", 0x485},
|
||||
{"tag_sight_on", 0x486},
|
||||
{"tag_stow_back_mid_attach", 0x487},
|
||||
{"tag_stowed_back", 0x488},
|
||||
{"_not_tag_stowed_back", 0x488}, // was "tag_stowed_back"
|
||||
{"tag_stowed_hip_rear", 0x489},
|
||||
{"tag_sync", 0x48A},
|
||||
{"tag_tip", 0x48B},
|
||||
{"tag_stowed_back", 0x48B}, // was "tag_tip"
|
||||
{"tag_turret", 0x48C},
|
||||
{"tag_turret_base", 0x48D},
|
||||
{"tag_turret_pitch", 0x48E},
|
||||
@ -3340,10 +3340,10 @@ namespace scripting
|
||||
{"target", 0x4A1},
|
||||
{"target_script_trigger", 0x4A2},
|
||||
{"targetname", 0x4A3},
|
||||
{"team", 0x4A4},
|
||||
{"_not_team", 0x4A4}, // was "team"
|
||||
{"team3", 0x4A5},
|
||||
{"teambalanced", 0x4A6},
|
||||
{"teammode_axisallies", 0x4A7},
|
||||
{"team", 0x4A7}, // was "teammode_axisallies"
|
||||
{"teammode_ffa", 0x4A8},
|
||||
{"teammovewaittime", 0x4A9},
|
||||
{"their_score", 0x4AA},
|
||||
@ -3370,10 +3370,10 @@ namespace scripting
|
||||
{"traversecost", 0x4BF},
|
||||
{"traversesoonnotifydist", 0x4C0},
|
||||
{"trend", 0x4C1},
|
||||
{"trigger", 0x4C2},
|
||||
{"_not_trigger", 0x4C2}, // was "trigger"
|
||||
{"trigger_damage", 0x4C3},
|
||||
{"trigger_use", 0x4C4},
|
||||
{"trigger_use_touch", 0x4C5},
|
||||
{"trigger", 0x4C5}, // was "trigger_use_touch"
|
||||
{"truck_cam", 0x4C6},
|
||||
{"turnrate", 0x4C7},
|
||||
{"turret_deactivate", 0x4C8},
|
||||
@ -3492,5 +3492,97 @@ namespace scripting
|
||||
{"codescripts/struct", 0x53E},
|
||||
{"codescripts/message", 0x53F},
|
||||
{"maps/mp/gametypes/_callbacksetup", 0x540},
|
||||
|
||||
// additional findings from gametype/map scripts - mikey (6/26/2022)
|
||||
{"common_scripts/_fx", 0xA4FB},
|
||||
{"common_scripts/_pipes", 0xA4F9},
|
||||
{"common_scripts/utility", 0xA4FA},
|
||||
|
||||
{"QuickMessageToAll", 0x70a2},
|
||||
{"SetupCallbacks", 0x8301},
|
||||
{"_effect", 0x58f},
|
||||
{"_objective_delete", 0x603},
|
||||
{"addSpawnPoints", 0x82f},
|
||||
{"addStartSpawnPoints", 0x831},
|
||||
{"addToCharactersArray", 0x848},
|
||||
{"allowUse", 0xab2},
|
||||
{"applyLoadout", 0xcae}, // has applyLoadout notify like IW6's giveLoadout does at the end + similar logic
|
||||
{"characters", 0x1c8e},
|
||||
{"checkDynamicSpawns", 0x1cfa},
|
||||
{"clearOnVictimDisconnect", 0x1ef9},
|
||||
{"conf_fx", 0x20e9},
|
||||
{"console", 0x2153},
|
||||
{"createUseObject", 0x244c},
|
||||
{"curOrigin", 0x24c8},
|
||||
{"deleteObjPoint", 0x2859},
|
||||
{"dogtags", 0x2cdf},
|
||||
{"finalKill", 0x373e},
|
||||
{"findBoxCenter", 0x3779},
|
||||
{"forfeitInProgress", 0x39df},
|
||||
{"gamemodeModifyPlayerDamage", 0x3bf6},
|
||||
{"getNextObjID", 0x4041},
|
||||
{"getOtherTeam", 0x4067},
|
||||
{"getSpawnPoint", 0x40d2},
|
||||
{"getSpawnpoint_FreeForAll", 0x40d5},
|
||||
{"getTeamSpawnPoints", 0x411f},
|
||||
{"giveLoadout", 0x41e0}, // this may not even be giveLoadout but it's a wrapper for it and it does the same logic so
|
||||
{"guid", 0x4450},
|
||||
{"inGracePeriod", 0x4c6d},
|
||||
{"initSpawns", 0x4e26},
|
||||
{"initializeMatchRules", 0x4de0},
|
||||
{"initializeTagPathVariables", 0x4de3},
|
||||
{"mapCenter", 0x5986},
|
||||
{"maps/mp/_compass", 0xa731},
|
||||
{"maps/mp/_load", 0xa74c},
|
||||
{"maps/mp/_utility", 0xa764},
|
||||
{"maps/mp/gametypes/_class", 0xA78B},
|
||||
{"maps/mp/gametypes/_damage", 0xA78D},
|
||||
{"maps/mp/gametypes/_gameobjects", 0xA794},
|
||||
{"maps/mp/gametypes/_globallogic", 0xA797},
|
||||
{"maps/mp/gametypes/_menus", 0xa7a9},
|
||||
{"maps/mp/gametypes/_objpoints", 0xa7ac},
|
||||
{"maps/mp/gametypes/_spawnlogic", 0xa7b9},
|
||||
{"maps/mp/gametypes/_spawnscoring", 0xa7ba},
|
||||
{"matchRules_damageMultiplier", 0x59e6},
|
||||
{"matchRules_vampirism", 0x59eb},
|
||||
{"modifyPlayerDamage", 0x5d51},
|
||||
{"objId", 0x6304},
|
||||
{"onForfeit", 0x64af},
|
||||
{"onNormalDeath", 0x64bf},
|
||||
{"onPlayerScore", 0x64d5},
|
||||
{"onStartGameType", 0x64ec},
|
||||
{"onUse", 0x64f8},
|
||||
{"participants", 0x669d},
|
||||
{"reInitializeMatchRulesOnMigration", 0x7307},
|
||||
{"registerHalfTimeDvar", 0x72ef},
|
||||
{"registerNumLivesDvar", 0x72f4},
|
||||
{"registerRoundLimitDvar", 0x72f6},
|
||||
{"registerRoundSwitchDvar", 0x72f7},
|
||||
{"registerScoreLimitDvar", 0x72f8},
|
||||
{"registerTimeLimitDvar", 0x72f9},
|
||||
{"registerWinLimitDvar", 0x72fe},
|
||||
{"removeFromCharactersArray", 0x73a7},
|
||||
{"setClass", 0x7f3b},
|
||||
{"setCommonRulesFromMatchRulesData", 0x7f3f},
|
||||
{"setObjectiveHintText", 0x7fc3},
|
||||
{"setObjectiveScoreText", 0x7fc4},
|
||||
{"setObjectiveText", 0x7fc5},
|
||||
{"setUseTime", 0x834c},
|
||||
{"setupMiniMap", 0x8324},
|
||||
{"showToTeam", 0x8535},
|
||||
{"spawnDogTags", 0x899e},
|
||||
{"spawnMaxs", 0x89f3},
|
||||
{"spawnMins", 0x89f6},
|
||||
{"spawnPoints", 0x8a01},
|
||||
{"splitscreen", 0x8a7c},
|
||||
{"tag_stowed_hip", 0x90d3},
|
||||
{"tagTeamUpdater", 0x910a},
|
||||
{"teamBased", 0x91eb},
|
||||
{"teamNameList", 0x91f7},
|
||||
{"teamObjIds", 0x6305},
|
||||
{"teamSpawnPoints", 0x9201},
|
||||
{"v", 0x9c42},
|
||||
{"visuals", 0x9e9c},
|
||||
{"multiTeamBased", 0x5fec},
|
||||
};
|
||||
}
|
||||
|
@ -197,6 +197,7 @@ namespace game
|
||||
WEAK symbol<void(mp::client_t*, const char*, int)> SV_ExecuteClientCommand{0x0, 0x0};
|
||||
WEAK symbol<void(int localClientNum)> SV_FastRestart{0x0, 0x54BE00};
|
||||
WEAK symbol<void(void* cl, int type, const char* fmt, ...)> SV_SendServerCommand{0x0, 0x1CC040};
|
||||
WEAK symbol<void(mp::client_t* drop, const char* reason, bool tellThem)> SV_DropClient_Internal{0x0, 0x54E7F0};
|
||||
|
||||
WEAK symbol<void()> Sys_ShowConsole{0x0, 0x0};
|
||||
WEAK symbol<void(const char* error, ...)> Sys_Error{0x0, 0x1D8710};
|
||||
@ -295,6 +296,7 @@ namespace game
|
||||
WEAK symbol<int(lua_State* s, const char* what, lua_Debug* ar)> hksi_lua_getinfo{0xB84D0, 0x22FFE0};
|
||||
WEAK symbol<int(lua_State* s, int level, lua_Debug* ar)> hksi_lua_getstack{0xB87A0, 0x2302B0};
|
||||
WEAK symbol<void(lua_State* s, const char* fmt, ...)> hksi_luaL_error{0xBF120, 0x22F930};
|
||||
WEAK symbol<void(lua_State* s, int what, int data)> hksi_lua_gc{0, 0x236EF0};
|
||||
WEAK symbol<const char*> typenames{0x98CD20, 0x10AD750};
|
||||
}
|
||||
}
|
||||
|
@ -181,16 +181,6 @@ void limit_parallel_dll_loading()
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
// solution for other processes that may launch the mod
|
||||
void apply_proper_directory()
|
||||
{
|
||||
char module_path[MAX_PATH];
|
||||
GetModuleFileNameA(nullptr, module_path, MAX_PATH);
|
||||
PathRemoveFileSpecA(module_path);
|
||||
SetCurrentDirectoryA(module_path);
|
||||
SetDllDirectoryA(module_path);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
@ -217,8 +207,6 @@ int main()
|
||||
|
||||
try
|
||||
{
|
||||
//apply_proper_directory();
|
||||
|
||||
if (!component_loader::post_start()) return 0;
|
||||
|
||||
auto mode = detect_mode_from_arguments();
|
||||
|
@ -74,7 +74,7 @@ BEGIN
|
||||
VALUE "FileDescription", "H1-Mod"
|
||||
VALUE "FileVersion", VERSION_FILE
|
||||
VALUE "InternalName", "H1-Mod"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021 H1-Mod. All rights reserved."
|
||||
VALUE "LegalCopyright", "Copyright © 2022 H1-Mod. All rights reserved."
|
||||
VALUE "Licence", "GPLv3"
|
||||
VALUE "Info", "https://h1.gg"
|
||||
VALUE "OriginalFilename", "h1-mod.exe"
|
||||
|
@ -4,41 +4,61 @@
|
||||
|
||||
namespace utils::http
|
||||
{
|
||||
std::optional<std::string> get_data(const std::string& url)
|
||||
namespace
|
||||
{
|
||||
CComPtr<IStream> stream;
|
||||
size_t write_callback(void* contents, const size_t size, const size_t nmemb, void* userp)
|
||||
{
|
||||
auto* buffer = static_cast<std::string*>(userp);
|
||||
|
||||
if (FAILED(URLOpenBlockingStreamA(nullptr, url.data(), &stream, 0, nullptr)))
|
||||
const auto total_size = size * nmemb;
|
||||
buffer->append(static_cast<char*>(contents), total_size);
|
||||
return total_size;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<result> get_data(const std::string& url)
|
||||
{
|
||||
curl_slist* header_list = nullptr;
|
||||
auto* curl = curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
char buffer[0x1000];
|
||||
std::string result;
|
||||
|
||||
HRESULT status{};
|
||||
|
||||
do
|
||||
auto _ = gsl::finally([&]()
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
status = stream->Read(buffer, sizeof(buffer), &bytes_read);
|
||||
curl_slist_free_all(header_list);
|
||||
curl_easy_cleanup(curl);
|
||||
});
|
||||
|
||||
if (bytes_read > 0)
|
||||
std::string buffer{};
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.data());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
||||
|
||||
const auto code = curl_easy_perform(curl);
|
||||
|
||||
if (code == CURLE_OK)
|
||||
{
|
||||
result.append(buffer, bytes_read);
|
||||
}
|
||||
}
|
||||
while (SUCCEEDED(status) && status != S_FALSE);
|
||||
result result;
|
||||
result.code = code;
|
||||
result.buffer = std::move(buffer);
|
||||
|
||||
if (FAILED(status))
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
result result;
|
||||
result.code = code;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return {result};
|
||||
}
|
||||
|
||||
std::future<std::optional<std::string>> get_data_async(const std::string& url)
|
||||
std::future<std::optional<result>> get_data_async(const std::string& url)
|
||||
{
|
||||
return std::async(std::launch::async, [url]()
|
||||
{
|
||||
|
@ -3,9 +3,18 @@
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <future>
|
||||
#include <gsl/gsl>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace utils::http
|
||||
{
|
||||
std::optional<std::string> get_data(const std::string& url);
|
||||
std::future<std::optional<std::string>> get_data_async(const std::string& url);
|
||||
struct result
|
||||
{
|
||||
CURLcode code;
|
||||
std::string buffer;
|
||||
};
|
||||
|
||||
std::optional<result> get_data(const std::string& url);
|
||||
std::future<std::optional<result>> get_data_async(const std::string& url);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace utils
|
||||
|
||||
instance->setAppName(L"H1-Mod");
|
||||
instance->setAppUserModelId(
|
||||
WinToastLib::WinToast::configureAUMI(L"X Labs", L"H1-Mod", L"", L"20201212"));
|
||||
WinToastLib::WinToast::configureAUMI(L"H1-Mod", L"H1", L"", L"20201212"));
|
||||
|
||||
WinToastLib::WinToast::WinToastError error;
|
||||
success = instance->initialize(&error);
|
||||
|
@ -60,7 +60,7 @@ BEGIN
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "X Labs"
|
||||
VALUE "CompanyName", "H1-Mod"
|
||||
VALUE "FileDescription", "Steam mod runner"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "InternalName", "Runner"
|
||||
|
@ -60,7 +60,7 @@ BEGIN
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "X Labs"
|
||||
VALUE "CompanyName", "H1-Mod"
|
||||
VALUE "FileDescription", "TLS index allocation dll"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "InternalName", "TLS DLL"
|
||||
|
Loading…
Reference in New Issue
Block a user