mirror of
https://github.com/XLabsProject/s1x-client.git
synced 2023-08-02 15:02:12 +02:00
commit
648ccc2c23
47
appveyor.yml
47
appveyor.yml
@ -1,47 +0,0 @@
|
||||
# AppVeyor CI configuration
|
||||
|
||||
version: "#{build} ({branch})"
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
PREMAKE_ACTION: vs2019
|
||||
CI: 1
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
# Doesn't work :(
|
||||
#cache:
|
||||
# - build
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
platform: x64
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
Write-Host "Updating version information..." -ForegroundColor Cyan
|
||||
Update-AppveyorBuild -Version $(& tools/premake5.exe version | select -Last 1)
|
||||
- git submodule update --init --recursive
|
||||
- ps: |
|
||||
Write-Host "Generating project files with premake..." -ForegroundColor Cyan
|
||||
& "./tools/premake5.exe" $env:PREMAKE_ACTION
|
||||
Write-Host "Generated" -ForegroundColor Green
|
||||
|
||||
build:
|
||||
project: build/s1x.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
|
||||
artifacts:
|
||||
- path: build/version.txt
|
||||
- path: build/bin/**/s1x.exe
|
||||
# - path: build/bin/**/*.exe
|
||||
# - path: build/bin/**/*.pdb
|
3637
data/maps/mp/gametypes/_damage.gsc
Normal file
3637
data/maps/mp/gametypes/_damage.gsc
Normal file
File diff suppressed because it is too large
Load Diff
2250
data/maps/mp/gametypes/_playerlogic.gsc
Normal file
2250
data/maps/mp/gametypes/_playerlogic.gsc
Normal file
File diff suppressed because it is too large
Load Diff
23
data/scripts/_team_balance.gsc
Normal file
23
data/scripts/_team_balance.gsc
Normal file
@ -0,0 +1,23 @@
|
||||
init()
|
||||
{
|
||||
// define onteamselection callback function used in balanceteams()
|
||||
level.onteamselection = ::set_team;
|
||||
}
|
||||
|
||||
set_team(team)
|
||||
{
|
||||
if (team != self.pers["team"])
|
||||
{
|
||||
self.switching_teams = true;
|
||||
self.joining_team = team;
|
||||
self.leaving_team = self.pers["team"];
|
||||
}
|
||||
|
||||
if (self.sessionstate == "playing")
|
||||
{
|
||||
self suicide();
|
||||
}
|
||||
|
||||
maps\mp\gametypes\_menus::addtoteam(team);
|
||||
maps\mp\gametypes\_menus::endrespawnnotify();
|
||||
}
|
2
deps/GSL
vendored
2
deps/GSL
vendored
@ -1 +1 @@
|
||||
Subproject commit 9c4212aca46fb4fe5bda2921c2269d35d6d1860f
|
||||
Subproject commit 517ed29228d18cf2c5004d10826090108e06f049
|
2
deps/asmjit
vendored
2
deps/asmjit
vendored
@ -1 +1 @@
|
||||
Subproject commit 8f2c237b8315a7d662e0e67d06807296a7bbe5ab
|
||||
Subproject commit 0c03ed2f7497441ac0de232bda2e6b8cc041b2dc
|
2
deps/gsc-tool
vendored
2
deps/gsc-tool
vendored
@ -1 +1 @@
|
||||
Subproject commit 842f168a67878f18ea6a42b9d3ce56ff9fafff0d
|
||||
Subproject commit 7d374025b7675bada64c247ebe9378dd335a33da
|
2
deps/lua
vendored
2
deps/lua
vendored
@ -1 +1 @@
|
||||
Subproject commit c954db39241a8b21d7b32b42b87a066b4708f969
|
||||
Subproject commit be908a7d4d8130264ad67c5789169769f824c5d1
|
2
deps/sol2
vendored
2
deps/sol2
vendored
@ -1 +1 @@
|
||||
Subproject commit 0386513a2d59fefe448f4fc8742455ce1fc152ab
|
||||
Subproject commit f81643aa0c0c507c0cd8400b8cfedc74a34a19f6
|
@ -186,7 +186,7 @@ namespace command
|
||||
|
||||
std::string params_sv::join(const int index) const
|
||||
{
|
||||
std::string result = {};
|
||||
std::string result;
|
||||
|
||||
for (auto i = index; i < this->size(); i++)
|
||||
{
|
||||
|
@ -1,17 +1,16 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "console.hpp"
|
||||
#include "command.hpp"
|
||||
#include "network.hpp"
|
||||
#include "party.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#include <discord_rpc.h>
|
||||
#include <component/party.hpp>
|
||||
|
||||
namespace discord
|
||||
{
|
||||
|
@ -182,8 +182,7 @@ namespace dvar_cheats
|
||||
constexpr auto value = false;
|
||||
#endif
|
||||
|
||||
dvars::sv_cheats = game::Dvar_RegisterBool("sv_cheats", value, game::DVAR_FLAG_REPLICATED,
|
||||
"Allow cheat commands and dvars on this server");
|
||||
dvars::sv_cheats = game::Dvar_RegisterBool("sv_cheats", value, game::DVAR_FLAG_REPLICATED, "Allow cheat commands and dvars on this server");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -65,30 +65,13 @@ namespace filesystem
|
||||
game::FS_Startup(gamename);
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> get_paths(const std::filesystem::path& path)
|
||||
{
|
||||
std::vector<std::filesystem::path> paths{};
|
||||
|
||||
const auto code = game::SEH_GetCurrentLanguageName();
|
||||
|
||||
paths.push_back(path);
|
||||
|
||||
paths.push_back(path / code);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool can_insert_path(const std::filesystem::path& path)
|
||||
{
|
||||
for (const auto& path_ : get_search_paths_internal())
|
||||
const auto& paths = get_search_paths_internal();
|
||||
return std::ranges::none_of(paths.cbegin(), paths.cend(), [path](const auto& elem)
|
||||
{
|
||||
if (path_ == path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return elem == path;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,14 +173,10 @@ namespace filesystem
|
||||
return;
|
||||
}
|
||||
|
||||
const auto paths = get_paths(path);
|
||||
for (const auto& path_ : paths)
|
||||
if (can_insert_path(path))
|
||||
{
|
||||
if (can_insert_path(path_))
|
||||
{
|
||||
console::info("[FS] Registering path '%s'\n", path_.generic_string().data());
|
||||
get_search_paths_internal().push_front(path_);
|
||||
}
|
||||
console::info("[FS] Registering path '%s'\n", path.generic_string().data());
|
||||
get_search_paths_internal().push_front(path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,21 +187,17 @@ namespace filesystem
|
||||
return;
|
||||
}
|
||||
|
||||
const auto paths = get_paths(path);
|
||||
for (const auto& path_ : paths)
|
||||
auto& search_paths = get_search_paths_internal();
|
||||
for (auto i = search_paths.begin(); i != search_paths.end();)
|
||||
{
|
||||
auto& search_paths = get_search_paths_internal();
|
||||
for (auto i = search_paths.begin(); i != search_paths.end();)
|
||||
if (*i == path)
|
||||
{
|
||||
if (*i == path_)
|
||||
{
|
||||
console::info("[FS] Unregistering path '%s'\n", path_.generic_string().data());
|
||||
i = search_paths.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
console::info("[FS] Unregistering path '%s'\n", path.generic_string().data());
|
||||
i = search_paths.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ namespace fps
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const game::dvar_t* cg_drawFPS;
|
||||
const game::dvar_t* cg_drawPing;
|
||||
|
||||
float fps_color_good[4] = {0.6f, 1.0f, 0.0f, 1.0f};
|
||||
float fps_color_ok[4] = {1.0f, 0.7f, 0.3f, 1.0f};
|
||||
float fps_color_bad[4] = {1.0f, 0.3f, 0.3f, 1.0f};
|
||||
@ -45,7 +48,7 @@ namespace fps
|
||||
{
|
||||
data->history[data->index % 32] = value;
|
||||
data->instant = value;
|
||||
data->min = 0x7FFFFFFF;
|
||||
data->min = std::numeric_limits<int>::max();
|
||||
data->max = 0;
|
||||
data->average = 0.0f;
|
||||
data->variance = 0.0f;
|
||||
@ -93,11 +96,9 @@ namespace fps
|
||||
|
||||
void cg_draw_fps()
|
||||
{
|
||||
const auto* draw_fps = game::Dvar_FindVar("cg_drawFPS");
|
||||
|
||||
if (draw_fps && draw_fps->current.integer > 0)
|
||||
if (cg_drawFPS && cg_drawFPS->current.integer > 0)
|
||||
{
|
||||
const auto fps = fps::get_fps();
|
||||
const auto fps = get_fps();
|
||||
|
||||
auto* font = game::R_RegisterFont("fonts/consolefont");
|
||||
if (!font) return;
|
||||
@ -107,19 +108,18 @@ namespace fps
|
||||
const auto scale = 1.0f;
|
||||
|
||||
const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 10.0f) - game::R_TextWidth(
|
||||
fps_string, 0x7FFFFFFF, font) * scale;
|
||||
fps_string, std::numeric_limits<int>::max(), font) * scale;
|
||||
|
||||
const auto y = font->pixelHeight * 1.2f;
|
||||
|
||||
const auto fps_color = fps >= 60 ? fps_color_good : (fps >= 30 ? fps_color_ok : fps_color_bad);
|
||||
game::R_AddCmdDrawText(fps_string, 0x7FFFFFFF, font, x, y, scale, scale, 0.0f, fps_color, 6);
|
||||
game::R_AddCmdDrawText(fps_string, std::numeric_limits<int>::max(), font, x, y, scale, scale, 0.0f, fps_color, 6);
|
||||
}
|
||||
}
|
||||
|
||||
void cg_draw_ping()
|
||||
{
|
||||
const auto* draw_ping = game::Dvar_FindVar("cg_drawPing");
|
||||
if (draw_ping && draw_ping->current.integer > 0 && game::CL_IsCgameInitialized())
|
||||
if (cg_drawPing->current.integer > 0 && game::CL_IsCgameInitialized())
|
||||
{
|
||||
auto* font = game::R_RegisterFont("fonts/consolefont");
|
||||
if (!font) return;
|
||||
@ -129,26 +129,25 @@ namespace fps
|
||||
const auto scale = 1.0f;
|
||||
|
||||
const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 375.0f) - game::R_TextWidth(
|
||||
ping_string, 0x7FFFFFFF, font) * scale;
|
||||
ping_string, std::numeric_limits<int>::max(), font) * scale;
|
||||
|
||||
const auto y = font->pixelHeight * 1.2f;
|
||||
|
||||
game::R_AddCmdDrawText(ping_string, 0x7FFFFFFF, font, x, y, scale, scale, 0.0f, ping_color, 6);
|
||||
game::R_AddCmdDrawText(ping_string, std::numeric_limits<int>::max(), font, x, y, scale, scale, 0.0f, ping_color, 6);
|
||||
}
|
||||
}
|
||||
|
||||
void cg_draw_fps_register_stub(const char* name, const char** _enum, const int value, unsigned int /*flags*/,
|
||||
const char* desc)
|
||||
const game::dvar_t* cg_draw_fps_register_stub(const char* dvar_name, const char** value_list, const int default_index, unsigned int /*flags*/, const char* description)
|
||||
{
|
||||
game::Dvar_RegisterEnum(name, _enum, value, game::DVAR_FLAG_SAVED, desc);
|
||||
cg_drawFPS = game::Dvar_RegisterEnum(dvar_name, value_list, default_index, game::DVAR_FLAG_SAVED, description);
|
||||
return cg_drawFPS;
|
||||
}
|
||||
}
|
||||
|
||||
int get_fps()
|
||||
{
|
||||
return static_cast<std::int32_t>(static_cast<float>(1000.0f / static_cast<float>(cg_perf.
|
||||
average))
|
||||
+ 9.313225746154785e-10);
|
||||
return static_cast<std::int32_t>(static_cast<float>(1000.0f /
|
||||
static_cast<float>(cg_perf.average)) + 9.313225746154785e-10);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -174,7 +173,7 @@ namespace fps
|
||||
scheduler::loop(cg_draw_fps, scheduler::pipeline::renderer);
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
game::Dvar_RegisterInt("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, "Choose to draw ping");
|
||||
cg_drawPing = game::Dvar_RegisterInt("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, "Choose to draw ping");
|
||||
scheduler::loop(cg_draw_ping, scheduler::pipeline::renderer);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ namespace game_log
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsprintf_s(buffer, fmt, ap);
|
||||
vsnprintf_s(buffer, _TRUNCATE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
using namespace utils::string;
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
namespace
|
||||
@ -20,6 +22,38 @@ namespace gsc
|
||||
|
||||
std::string unknown_function_error;
|
||||
|
||||
// Array count confirmed at 0x1409BE0D0
|
||||
std::array<const char*, 27> var_typename =
|
||||
{
|
||||
"undefined",
|
||||
"object",
|
||||
"string",
|
||||
"localized string",
|
||||
"vector",
|
||||
"float",
|
||||
"int",
|
||||
"codepos",
|
||||
"precodepos",
|
||||
"function",
|
||||
"builtin function",
|
||||
"builtin method",
|
||||
"stack",
|
||||
"animation",
|
||||
"pre animation",
|
||||
"thread",
|
||||
"thread",
|
||||
"thread",
|
||||
"thread",
|
||||
"struct",
|
||||
"removed entity",
|
||||
"entity",
|
||||
"array",
|
||||
"removed thread",
|
||||
"<free>",
|
||||
"thread list",
|
||||
"endon list",
|
||||
};
|
||||
|
||||
void scr_emit_function_stub(unsigned int filename, unsigned int thread_name, char* code_pos)
|
||||
{
|
||||
current_filename = filename;
|
||||
@ -82,6 +116,23 @@ namespace gsc
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int scr_get_object(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (value->type == game::VAR_POINTER)
|
||||
{
|
||||
return value->u.pointerValue;
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not an object", var_typename[value->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int scr_get_const_string(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
@ -89,16 +140,146 @@ namespace gsc
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (game::Scr_CastString(value))
|
||||
{
|
||||
assert(value->type == game::SCRIPT_STRING);
|
||||
assert(value->type == game::VAR_STRING);
|
||||
return value->u.stringValue;
|
||||
}
|
||||
|
||||
game::Scr_ErrorInternal();
|
||||
}
|
||||
|
||||
scr_error(utils::string::va("Parameter %u does not exist", index + 1));
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int scr_get_const_istring(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (value->type == game::VAR_ISTRING)
|
||||
{
|
||||
return value->u.stringValue;
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not a localized string", var_typename[value->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scr_validate_localized_string_ref(int parm_index, const char* token, int token_len)
|
||||
{
|
||||
assert(token);
|
||||
assert(token_len >= 0);
|
||||
|
||||
if (token_len < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto char_iter = 0; char_iter < token_len; ++char_iter)
|
||||
{
|
||||
if (!std::isalnum(static_cast<unsigned char>(token[char_iter])) && token[char_iter] != '_')
|
||||
{
|
||||
scr_error(va("Illegal localized string reference: %s must contain only alpha-numeric characters and underscores", token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scr_get_vector(unsigned int index, float* vector_value)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (value->type == game::VAR_VECTOR)
|
||||
{
|
||||
std::memcpy(vector_value, value->u.vectorValue, sizeof(std::float_t[3]));
|
||||
return;
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not a vector", var_typename[value->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
}
|
||||
|
||||
int scr_get_int(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (value->type == game::VAR_INTEGER)
|
||||
{
|
||||
return value->u.intValue;
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not an int", var_typename[value->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
float scr_get_float(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
auto* value = game::scr_VmPub->top - index;
|
||||
if (value->type == game::VAR_FLOAT)
|
||||
{
|
||||
return value->u.floatValue;
|
||||
}
|
||||
|
||||
if (value->type == game::VAR_INTEGER)
|
||||
{
|
||||
return static_cast<float>(value->u.intValue);
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not a float", var_typename[value->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int scr_get_pointer_type(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
if ((game::scr_VmPub->top - index)->type == game::VAR_POINTER)
|
||||
{
|
||||
return static_cast<int>(game::GetObjectType((game::scr_VmPub->top - index)->u.uintValue));
|
||||
}
|
||||
|
||||
scr_error(va("Type %s is not an object", var_typename[(game::scr_VmPub->top - index)->type]));
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scr_get_type(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
return (game::scr_VmPub->top - index)->type;
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* scr_get_type_name(unsigned int index)
|
||||
{
|
||||
if (index < game::scr_VmPub->outparamcount)
|
||||
{
|
||||
return var_typename[(game::scr_VmPub->top - index)->type];
|
||||
}
|
||||
|
||||
scr_error(va("Parameter %u does not exist", index + 1));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, std::string>> find_function(const char* pos)
|
||||
@ -134,8 +315,18 @@ namespace gsc
|
||||
utils::hook::call(0x1403ED8E8, compile_error_stub); // LinkFile
|
||||
utils::hook::call(0x1403ED9DB, find_variable_stub); // Scr_EmitFunction
|
||||
|
||||
// Restore basic error messages to scr functions
|
||||
// Restore basic error messages for commonly used scr functions
|
||||
utils::hook::jump(0x1403F8990, scr_get_object);
|
||||
utils::hook::jump(0x1403F8510, scr_get_const_string);
|
||||
utils::hook::jump(0x1403F82F0, scr_get_const_istring);
|
||||
utils::hook::jump(0x140327870, scr_validate_localized_string_ref);
|
||||
utils::hook::jump(0x1403F8EC0, scr_get_vector);
|
||||
utils::hook::jump(0x1403F88D0, scr_get_int);
|
||||
utils::hook::jump(0x1403F8820, scr_get_float);
|
||||
|
||||
utils::hook::jump(0x1403F8BA0, scr_get_pointer_type);
|
||||
utils::hook::jump(0x1403F8D70, scr_get_type);
|
||||
utils::hook::jump(0x1403F8DE0, scr_get_type_name);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
|
@ -275,7 +275,7 @@ namespace gsc
|
||||
|
||||
override_function("assert", &assert_cmd);
|
||||
override_function("assertex", &assert_ex_cmd);
|
||||
override_function("assertmsg", &assert_ex_cmd);
|
||||
override_function("assertmsg", &assert_msg_cmd);
|
||||
|
||||
add_function("executecommand", []
|
||||
{
|
||||
|
@ -242,6 +242,11 @@ namespace gsc
|
||||
{
|
||||
utils::hook::invoke<void>(0x140323F20);
|
||||
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
fastfiles::enum_assets(game::ASSET_TYPE_RAWFILE, [](const game::XAssetHeader header)
|
||||
@ -276,11 +281,14 @@ namespace gsc
|
||||
|
||||
void g_load_structs_stub()
|
||||
{
|
||||
for (auto& function_handle : main_handles)
|
||||
if (!game::VirtualLobby_Loaded())
|
||||
{
|
||||
console::info("Executing '%s::main'\n", function_handle.first.data());
|
||||
const auto thread = game::Scr_ExecThread(function_handle.second, 0);
|
||||
game::RemoveRefToObject(thread);
|
||||
for (auto& function_handle : main_handles)
|
||||
{
|
||||
console::info("Executing '%s::main'\n", function_handle.first.data());
|
||||
const auto thread = game::Scr_ExecThread(function_handle.second, 0);
|
||||
game::RemoveRefToObject(thread);
|
||||
}
|
||||
}
|
||||
|
||||
utils::hook::invoke<void>(0x1403380D0);
|
||||
@ -290,6 +298,11 @@ namespace gsc
|
||||
{
|
||||
utils::hook::invoke<void>(0x140325B90);
|
||||
|
||||
if (game::VirtualLobby_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& function_handle : init_handles)
|
||||
{
|
||||
console::info("Executing '%s::init'\n", function_handle.first.data());
|
||||
@ -322,6 +335,9 @@ namespace gsc
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
// Load our scripts with an uncompressed stack
|
||||
utils::hook::call(SELECT_VALUE(0x14031ABB0, 0x1403F7380), db_get_raw_buffer_stub);
|
||||
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
@ -357,9 +373,6 @@ namespace gsc
|
||||
// GScr_LoadScripts
|
||||
utils::hook::call(0x140330B97, gscr_post_load_scripts_stub);
|
||||
|
||||
// Load our scripts with an uncompressed stack
|
||||
utils::hook::call(0x1403F7380, db_get_raw_buffer_stub);
|
||||
|
||||
// Exec script handles
|
||||
utils::hook::call(0x1402F71AE, g_load_structs_stub);
|
||||
utils::hook::call(0x1402F71C7, scr_load_level_stub);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "game_console.hpp"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "motd.hpp"
|
||||
#include "images.hpp"
|
||||
|
||||
@ -15,6 +17,7 @@ namespace motd
|
||||
{
|
||||
std::string motd_resource = utils::nt::load_resource(DW_MOTD);
|
||||
std::future<std::optional<std::string>> motd_future;
|
||||
std::string marketing_featured;
|
||||
}
|
||||
|
||||
std::string get_text()
|
||||
@ -30,21 +33,55 @@ namespace motd
|
||||
return motd_resource;
|
||||
}
|
||||
|
||||
utils::hook::detour marketing_get_message_hook;
|
||||
|
||||
bool marketing_get_message_stub(int /*controller_index*/, int /*location-id*/, char* message_text, int message_text_length)
|
||||
{
|
||||
if (marketing_featured.empty()) return false;
|
||||
|
||||
strncpy_s(message_text, message_text_length, marketing_featured.data(), _TRUNCATE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
motd_future = utils::http::get_data_async("https://xlabs.dev/s1/motd.txt");
|
||||
std::thread([]()
|
||||
std::thread([]
|
||||
{
|
||||
auto data = utils::http::get_data("https://xlabs.dev/s1/motd.png");
|
||||
if(data)
|
||||
if (data.has_value())
|
||||
{
|
||||
images::override_texture("iotd_image", data.value());
|
||||
}
|
||||
|
||||
auto featured_optional = utils::http::get_data("https://xlabs.dev/s1/featured_msg.json");
|
||||
if (featured_optional.has_value())
|
||||
{
|
||||
marketing_featured = featured_optional.value();
|
||||
}
|
||||
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Not sure why but in S1x, client doesn't ask for maketing messages from demonware even though marketing_active set to true
|
||||
marketing_get_message_hook.create(0x140126930, marketing_get_message_stub);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
marketing_get_message_hook.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "scheduler.hpp"
|
||||
#include "notifies.hpp"
|
||||
#include "scripting.hpp"
|
||||
#include "game_log.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
@ -164,10 +165,10 @@ namespace notifies
|
||||
|
||||
if (params[0] == "say"s || params[0] == "say_team"s)
|
||||
{
|
||||
std::string message(game::ConcatArgs(1));
|
||||
std::string message(params.join(1));
|
||||
|
||||
auto msg_index = 0;
|
||||
if (message[msg_index] == '\x15')
|
||||
if (message[msg_index] == '\x1F')
|
||||
{
|
||||
msg_index = 1;
|
||||
}
|
||||
@ -179,7 +180,7 @@ namespace notifies
|
||||
|
||||
if (msg_index == 1)
|
||||
{
|
||||
// Overwrite / with \x15 only if present
|
||||
// Overwrite / with \x1F only if present
|
||||
message[msg_index] = message[msg_index - 1];
|
||||
}
|
||||
// Skip over the first character
|
||||
@ -191,8 +192,17 @@ namespace notifies
|
||||
const scripting::entity level{*game::levelEntityId};
|
||||
const auto player = scripting::call("getEntByNum", {client_num}).as<scripting::entity>();
|
||||
|
||||
scripting::notify(level, params[0], {player, message});
|
||||
scripting::notify(player, params[0], {message});
|
||||
notify(level, params[0], {player, message});
|
||||
notify(player, params[0], {message});
|
||||
|
||||
game_log::g_log_printf("%s;%s;%i;%s;%s\n",
|
||||
params[0],
|
||||
player.call("getguid").as<const char*>(),
|
||||
client_num,
|
||||
player.get("name").as<const char*>(),
|
||||
message.data()
|
||||
);
|
||||
|
||||
}, scheduler::pipeline::server);
|
||||
|
||||
if (hidden)
|
||||
@ -235,7 +245,7 @@ namespace notifies
|
||||
std::vector<sol::lua_value> args;
|
||||
|
||||
const auto top = game::scr_function_stack->top;
|
||||
for (auto* value = top; value->type != game::SCRIPT_END; --value)
|
||||
for (auto* value = top; value->type != game::VAR_PRECODEPOS; --value)
|
||||
{
|
||||
args.push_back(scripting::lua::convert(state, *value));
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "party.hpp"
|
||||
#include "console.hpp"
|
||||
#include "command.hpp"
|
||||
@ -28,6 +30,7 @@ namespace party
|
||||
} connect_state;
|
||||
|
||||
std::string sv_motd;
|
||||
|
||||
int sv_maxclients;
|
||||
|
||||
void perform_game_initialization()
|
||||
@ -277,7 +280,7 @@ namespace party
|
||||
|
||||
int server_client_count()
|
||||
{
|
||||
return party::sv_maxclients;
|
||||
return sv_maxclients;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -431,7 +434,7 @@ namespace party
|
||||
{
|
||||
for (auto i = 0; i < *game::mp::svs_numclients; ++i)
|
||||
{
|
||||
scheduler::once([i, reason]()
|
||||
scheduler::once([i, reason]
|
||||
{
|
||||
game::SV_KickClientNum(i, reason.data());
|
||||
}, scheduler::pipeline::server);
|
||||
@ -519,10 +522,10 @@ namespace party
|
||||
|
||||
utils::hook::call(0x14048811C, didyouknow_stub); // allow custom didyouknow based on sv_motd
|
||||
|
||||
network::on("getInfo", [](const game::netadr_s& target, const std::string_view& data)
|
||||
network::on("getInfo", [](const game::netadr_s& target, const std::string& data)
|
||||
{
|
||||
utils::info_string info{};
|
||||
info.set("challenge", std::string{data});
|
||||
info.set("challenge", data);
|
||||
info.set("gamename", "S1");
|
||||
info.set("hostname", get_dvar_string("sv_hostname"));
|
||||
info.set("gametype", get_dvar_string("g_gametype"));
|
||||
@ -530,21 +533,26 @@ namespace party
|
||||
info.set("xuid", utils::string::va("%llX", steam::SteamUser()->GetSteamID().bits));
|
||||
info.set("mapname", get_dvar_string("mapname"));
|
||||
info.set("isPrivate", get_dvar_string("g_password").empty() ? "0" : "1");
|
||||
info.set("clients", utils::string::va("%i", get_client_count()));
|
||||
info.set("bots", utils::string::va("%i", get_bot_count()));
|
||||
info.set("sv_maxclients", utils::string::va("%i", *game::mp::svs_numclients));
|
||||
info.set("protocol", utils::string::va("%i", PROTOCOL));
|
||||
info.set("clients", std::to_string(get_client_count()));
|
||||
info.set("bots", std::to_string(get_bot_count()));
|
||||
info.set("sv_maxclients", std::to_string(*game::mp::svs_numclients));
|
||||
info.set("protocol", std::to_string(PROTOCOL));
|
||||
info.set("playmode", utils::string::va("%i", game::Com_GetCurrentCoDPlayMode()));
|
||||
info.set("sv_running", utils::string::va("%i", get_dvar_bool("sv_running")));
|
||||
info.set("dedicated", utils::string::va("%i", get_dvar_bool("dedicated")));
|
||||
info.set("sv_running", std::to_string(get_dvar_bool("sv_running")));
|
||||
info.set("dedicated", std::to_string(get_dvar_bool("dedicated")));
|
||||
info.set("shortversion", SHORTVERSION);
|
||||
|
||||
network::send(target, "infoResponse", info.build(), '\n');
|
||||
});
|
||||
|
||||
network::on("infoResponse", [](const game::netadr_s& target, const std::string_view& data)
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
const utils::info_string info{data};
|
||||
return;
|
||||
}
|
||||
|
||||
network::on("infoResponse", [](const game::netadr_s& target, const std::string& data)
|
||||
{
|
||||
const utils::info_string info(data);
|
||||
server_list::handle_info_response(target, info);
|
||||
|
||||
if (connect_state.host != target)
|
||||
@ -554,59 +562,67 @@ namespace party
|
||||
|
||||
if (info.get("challenge") != connect_state.challenge)
|
||||
{
|
||||
const auto str = "Invalid challenge.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Invalid challenge.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto gamename = info.get("gamename");
|
||||
if (gamename != "S1"s)
|
||||
{
|
||||
const auto str = "Invalid gamename.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Invalid gamename.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto playmode = info.get("playmode");
|
||||
if (game::CodPlayMode(std::atoi(playmode.data())) != game::Com_GetCurrentCoDPlayMode())
|
||||
if (std::atoi(playmode.data()) != game::Com_GetCurrentCoDPlayMode())
|
||||
{
|
||||
const auto str = "Invalid playmode.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Invalid playmode.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto sv_running = info.get("sv_running");
|
||||
if (!std::atoi(sv_running.data()))
|
||||
if (sv_running != "1"s)
|
||||
{
|
||||
const auto str = "Server not running.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Server not running.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto mapname = info.get("mapname");
|
||||
if (mapname.empty())
|
||||
{
|
||||
const auto str = "Invalid map.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Invalid map.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto gametype = info.get("gametype");
|
||||
if (gametype.empty())
|
||||
{
|
||||
const auto str = "Invalid gametype.";
|
||||
printf("%s\n", str);
|
||||
game::Com_Error(game::ERR_DROP, str);
|
||||
const auto* error_msg = "Invalid gametype.";
|
||||
console::error("%s\n", error_msg);
|
||||
game::Com_Error(game::ERR_DROP, "%s", error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
party::sv_motd = info.get("sv_motd");
|
||||
party::sv_maxclients = std::stoi(info.get("sv_maxclients"));
|
||||
sv_motd = info.get("sv_motd");
|
||||
|
||||
try
|
||||
{
|
||||
sv_maxclients = std::stoi(info.get("sv_maxclients"));
|
||||
}
|
||||
catch([[maybe_unused]] const std::exception& ex)
|
||||
{
|
||||
sv_maxclients = 1;
|
||||
}
|
||||
|
||||
connect_to_party(target, mapname, gametype);
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace party
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ namespace scripting
|
||||
e.name = string;
|
||||
e.entity = notify_list_owner_id;
|
||||
|
||||
for (auto* value = top; value->type != game::SCRIPT_END; --value)
|
||||
for (auto* value = top; value->type != game::VAR_PRECODEPOS; --value)
|
||||
{
|
||||
e.arguments.emplace_back(*value);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "server_list.hpp"
|
||||
#include "localized_strings.hpp"
|
||||
#include "network.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "party.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/string.hpp>
|
||||
@ -157,7 +158,7 @@ namespace server_list
|
||||
|
||||
void sort_serverlist()
|
||||
{
|
||||
std::stable_sort(servers.begin(), servers.end(), [](const server_info& a, const server_info& b)
|
||||
std::ranges::stable_sort(servers, [](const server_info& a, const server_info& b)
|
||||
{
|
||||
if (a.clients == b.clients)
|
||||
{
|
||||
@ -310,21 +311,21 @@ namespace server_list
|
||||
void handle_info_response(const game::netadr_s& address, const utils::info_string& info)
|
||||
{
|
||||
// Don't show servers that aren't dedicated!
|
||||
const auto dedicated = std::atoi(info.get("dedicated").data());
|
||||
if (!dedicated)
|
||||
const auto dedicated = info.get("dedicated");
|
||||
if (dedicated != "1"s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't show servers that aren't running!
|
||||
const auto sv_running = std::atoi(info.get("sv_running").data());
|
||||
if (!sv_running)
|
||||
const auto sv_running = info.get("sv_running");
|
||||
if (sv_running != "1"s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Only handle servers of the same playmode!
|
||||
const auto playmode = game::CodPlayMode(std::atoi(info.get("playmode").data()));
|
||||
const auto playmode = static_cast<game::CodPlayMode>(std::atoi(info.get("playmode").data()));
|
||||
if (game::Com_GetCurrentCoDPlayMode() != playmode)
|
||||
{
|
||||
return;
|
||||
@ -352,9 +353,9 @@ namespace server_list
|
||||
server.map_name = game::UI_GetMapDisplayName(info.get("mapname").data());
|
||||
server.game_type = game::UI_GetGameTypeDisplayName(info.get("gametype").data());
|
||||
server.play_mode = playmode;
|
||||
server.clients = atoi(info.get("clients").data());
|
||||
server.max_clients = atoi(info.get("sv_maxclients").data());
|
||||
server.bots = atoi(info.get("bots").data());
|
||||
server.clients = std::atoi(info.get("clients").data());
|
||||
server.max_clients = std::atoi(info.get("sv_maxclients").data());
|
||||
server.bots = std::atoi(info.get("bots").data());
|
||||
server.ping = std::min(now - start_time, 999);
|
||||
|
||||
server.in_game = 1;
|
||||
|
@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include <utils/info_string.hpp>
|
||||
|
||||
namespace server_list
|
||||
|
@ -90,7 +90,7 @@ namespace scripting
|
||||
{
|
||||
if (this->entity_id_)
|
||||
{
|
||||
game::AddRefToValue(game::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)});
|
||||
game::AddRefToValue(game::VAR_POINTER, {static_cast<int>(this->entity_id_)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ namespace scripting
|
||||
{
|
||||
if (this->entity_id_)
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPT_OBJECT, {static_cast<int>(this->entity_id_)});
|
||||
game::RemoveRefToValue(game::VAR_POINTER, {static_cast<int>(this->entity_id_)});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace scripting
|
||||
const auto field_str = game::SL_GetString(field.data(), 0);
|
||||
const auto _ = gsl::finally([field_str]()
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPT_STRING, {static_cast<int>(field_str)});
|
||||
game::RemoveRefToValue(game::VAR_STRING, {static_cast<int>(field_str)});
|
||||
});
|
||||
|
||||
const auto offset = game::FindVariable(class_id, field_str);
|
||||
|
@ -31,7 +31,7 @@ namespace scripting::lua
|
||||
{
|
||||
const auto var = game::scr_VarGlob->childVariableValue[i];
|
||||
|
||||
if (var.type == game::SCRIPT_NONE)
|
||||
if (var.type == game::VAR_UNDEFINED)
|
||||
{
|
||||
current = var.nextSibling;
|
||||
continue;
|
||||
@ -125,7 +125,7 @@ namespace scripting::lua
|
||||
notifies::set_lua_hook(index, function);
|
||||
|
||||
game::VariableValue func;
|
||||
func.type = game::SCRIPT_FUNCTION;
|
||||
func.type = game::VAR_FUNCTION;
|
||||
func.u.codePosValue = index;
|
||||
|
||||
return func;
|
||||
@ -208,7 +208,7 @@ namespace scripting::lua
|
||||
|
||||
game::VariableValue result{};
|
||||
result.u = variable.u.u;
|
||||
result.type = (game::scriptType_e)variable.type;
|
||||
result.type = variable.type;
|
||||
|
||||
return convert(s, result);
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ namespace scripting::safe_execution
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
|
||||
{
|
||||
value->type = game::SCRIPT_NONE;
|
||||
value->type = game::VAR_UNDEFINED;
|
||||
value->u.intValue = 0;
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
|
@ -17,7 +17,7 @@ namespace scripting
|
||||
script_value::script_value(const int value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_INTEGER;
|
||||
variable.type = game::VAR_INTEGER;
|
||||
variable.u.intValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
@ -26,7 +26,7 @@ namespace scripting
|
||||
script_value::script_value(const unsigned int value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_INTEGER;
|
||||
variable.type = game::VAR_INTEGER;
|
||||
variable.u.uintValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
@ -40,7 +40,7 @@ namespace scripting
|
||||
script_value::script_value(const float value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_FLOAT;
|
||||
variable.type = game::VAR_FLOAT;
|
||||
variable.u.floatValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
@ -54,7 +54,7 @@ namespace scripting
|
||||
script_value::script_value(const char* value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_STRING;
|
||||
variable.type = game::VAR_STRING;
|
||||
variable.u.stringValue = game::SL_GetString(value, 0);
|
||||
|
||||
const auto _ = gsl::finally([&variable]()
|
||||
@ -73,7 +73,7 @@ namespace scripting
|
||||
script_value::script_value(const entity& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_OBJECT;
|
||||
variable.type = game::VAR_POINTER;
|
||||
variable.u.pointerValue = value.get_entity_id();
|
||||
|
||||
this->value_ = variable;
|
||||
@ -82,7 +82,7 @@ namespace scripting
|
||||
script_value::script_value(const vector& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_VECTOR;
|
||||
variable.type = game::VAR_VECTOR;
|
||||
variable.u.vectorValue = game::Scr_AllocVector(value);
|
||||
|
||||
const auto _ = gsl::finally([&variable]()
|
||||
@ -100,7 +100,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<int>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_INTEGER;
|
||||
return this->get_raw().type == game::VAR_INTEGER;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -140,7 +140,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<float>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_FLOAT;
|
||||
return this->get_raw().type == game::VAR_FLOAT;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -158,7 +158,7 @@ namespace scripting
|
||||
template <>
|
||||
double script_value::get() const
|
||||
{
|
||||
return static_cast<double>(this->get_raw().u.floatValue);
|
||||
return this->get_raw().u.floatValue;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
@ -168,7 +168,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<const char*>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_STRING;
|
||||
return this->get_raw().type == game::VAR_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -196,7 +196,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<std::vector<script_value>>() const
|
||||
{
|
||||
if (this->get_raw().type != game::SCRIPT_OBJECT)
|
||||
if (this->get_raw().type != game::VAR_POINTER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -204,7 +204,7 @@ namespace scripting
|
||||
const auto id = this->get_raw().u.uintValue;
|
||||
const auto type = game::scr_VarGlob->objectVariableValue[id].w.type;
|
||||
|
||||
return type == game::SCRIPT_ARRAY;
|
||||
return type == game::VAR_ARRAY;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
@ -214,7 +214,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<std::map<std::string, script_value>>() const
|
||||
{
|
||||
if (this->get_raw().type != game::SCRIPT_OBJECT)
|
||||
if (this->get_raw().type != game::VAR_POINTER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -222,7 +222,7 @@ namespace scripting
|
||||
const auto id = this->get_raw().u.uintValue;
|
||||
const auto type = game::scr_VarGlob->objectVariableValue[id].w.type;
|
||||
|
||||
return type == game::SCRIPT_STRUCT;
|
||||
return type == game::VAR_OBJECT;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
@ -232,7 +232,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<std::function<void()>>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_FUNCTION;
|
||||
return this->get_raw().type == game::VAR_FUNCTION;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
@ -242,7 +242,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<entity>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_OBJECT;
|
||||
return this->get_raw().type == game::VAR_POINTER;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -258,7 +258,7 @@ namespace scripting
|
||||
template <>
|
||||
bool script_value::is<vector>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_VECTOR;
|
||||
return this->get_raw().type == game::VAR_VECTOR;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -35,7 +35,7 @@ namespace scripting
|
||||
{
|
||||
this->release();
|
||||
this->value_ = other.value_;
|
||||
other.value_.type = game::SCRIPT_NONE;
|
||||
other.value_.type = game::VAR_UNDEFINED;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -59,10 +59,10 @@ namespace scripting
|
||||
|
||||
void variable_value::release()
|
||||
{
|
||||
if (this->value_.type != game::SCRIPT_NONE)
|
||||
if (this->value_.type != game::VAR_UNDEFINED)
|
||||
{
|
||||
game::RemoveRefToValue(this->value_.type, this->value_.u);
|
||||
this->value_.type = game::SCRIPT_NONE;
|
||||
this->value_.type = game::VAR_UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,6 @@ namespace scripting
|
||||
void assign(const game::VariableValue& value);
|
||||
void release();
|
||||
|
||||
game::VariableValue value_{{0}, game::SCRIPT_NONE};
|
||||
game::VariableValue value_{{0}, game::VAR_UNDEFINED};
|
||||
};
|
||||
}
|
||||
|
@ -25,19 +25,39 @@ namespace game
|
||||
typedef void(*BuiltinMethod)(scr_entref_t);
|
||||
typedef void(*BuiltinFunction)();
|
||||
|
||||
enum scriptType_e
|
||||
enum
|
||||
{
|
||||
SCRIPT_NONE = 0,
|
||||
SCRIPT_OBJECT = 1,
|
||||
SCRIPT_STRING = 2,
|
||||
SCRIPT_ISTRING = 3,
|
||||
SCRIPT_VECTOR = 4,
|
||||
SCRIPT_FLOAT = 5,
|
||||
SCRIPT_INTEGER = 6,
|
||||
SCRIPT_END = 8,
|
||||
SCRIPT_FUNCTION = 9,
|
||||
SCRIPT_STRUCT = 19,
|
||||
SCRIPT_ARRAY = 22
|
||||
VAR_UNDEFINED = 0x0,
|
||||
VAR_BEGIN_REF = 0x1,
|
||||
VAR_POINTER = 0x1,
|
||||
VAR_STRING = 0x2,
|
||||
VAR_ISTRING = 0x3,
|
||||
VAR_VECTOR = 0x4,
|
||||
VAR_END_REF = 0x5,
|
||||
VAR_FLOAT = 0x5,
|
||||
VAR_INTEGER = 0x6,
|
||||
VAR_CODEPOS = 0x7,
|
||||
VAR_PRECODEPOS = 0x8,
|
||||
VAR_FUNCTION = 0x9,
|
||||
VAR_BUILTIN_FUNCTION = 0xA,
|
||||
VAR_BUILTIN_METHOD = 0xB,
|
||||
VAR_STACK = 0xC,
|
||||
VAR_ANIMATION = 0xD,
|
||||
VAR_PRE_ANIMATION = 0xE,
|
||||
VAR_THREAD = 0xF,
|
||||
VAR_NOTIFY_THREAD = 0x10,
|
||||
VAR_TIME_THREAD = 0x11,
|
||||
VAR_CHILD_THREAD = 0x12,
|
||||
VAR_OBJECT = 0x13,
|
||||
VAR_DEAD_ENTITY = 0x14,
|
||||
VAR_ENTITY = 0x15,
|
||||
VAR_ARRAY = 0x16,
|
||||
VAR_DEAD_THREAD = 0x17,
|
||||
VAR_COUNT = 0x18,
|
||||
VAR_FREE = 0x18,
|
||||
VAR_THREAD_LIST = 0x19,
|
||||
VAR_ENDON_LIST = 0x1A,
|
||||
VAR_TOTAL_COUNT = 0x1B,
|
||||
};
|
||||
|
||||
struct VariableStackBuffer
|
||||
|
@ -46,17 +46,17 @@ namespace game
|
||||
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x1400EE500, 0x1401A3050};
|
||||
WEAK symbol<void(int localClientNum, /*mp::cg_s**/void* cg, const char* dvar, const char* value)> CG_SetClientDvarFromServer{0, 0x1401BF0A0};
|
||||
|
||||
WEAK symbol<void(XAssetType type, void (__cdecl* func)(XAssetHeader, void*), void* inData, bool includeOverride)> DB_EnumXAssets_FastFile{0x14017D7C0, 0x14026EC10};
|
||||
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)> DB_EnumXAssets_Internal{0x14017D830, 0x14026EC80};
|
||||
WEAK symbol<void(XAssetType type, void (*func)(XAssetHeader, void*), void* inData, bool includeOverride)> DB_EnumXAssets_FastFile{0x14017D7C0, 0x14026EC10};
|
||||
WEAK symbol<void(XAssetType type, void(*func)(XAssetHeader, void*), const void* inData, bool includeOverride)> DB_EnumXAssets_Internal{0x14017D830, 0x14026EC80};
|
||||
WEAK symbol<XAssetEntry(XAssetType type, const char* name)> DB_FindXAssetEntry{0x14017D830, 0x14026F020};
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char *name, int allowCreateDefault)> DB_FindXAssetHeader{0x14017DCA0, 0x14026F0F0};
|
||||
WEAK symbol<const char* (const XAsset* asset)> DB_GetXAssetName{0x140151C00, 0x140240DD0};
|
||||
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x140151C00, 0x140240DD0};
|
||||
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x140151C20, 0x140240DF0};
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, unsigned int zoneCount, DBSyncMode syncMode)> DB_LoadXAssets{0x1402F8B50, 0x140270F30};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_XAssetExists{0x0, 0x1402750F0};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_IsXAssetDefault{0x0, 0x140270320};
|
||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x0, 0x14026FCC0};
|
||||
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x0, 0x14026FB90};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_XAssetExists{0x140182190, 0x1402750F0};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_IsXAssetDefault{0x14017EEF0, 0x140270320};
|
||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x14017E890, 0x14026FCC0};
|
||||
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x14017E750, 0x14026FB90};
|
||||
WEAK symbol<char*(const char* filename, char* buf, int size)> DB_ReadRawFile{0x140180E30, 0x140273080};
|
||||
|
||||
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x140370860, 0x1404BF8B0};
|
||||
|
@ -163,7 +163,7 @@ void limit_parallel_dll_loading()
|
||||
void apply_environment()
|
||||
{
|
||||
wchar_t* buffer{};
|
||||
size_t size{};
|
||||
std::size_t size{};
|
||||
if (_wdupenv_s(&buffer, &size, L"XLABS_AW_INSTALL") != 0 || buffer == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Please use the X Labs launcher to run the game!");
|
||||
@ -171,12 +171,11 @@ void apply_environment()
|
||||
|
||||
const auto _ = gsl::finally([&]
|
||||
{
|
||||
free(buffer);
|
||||
std::free(buffer);
|
||||
});
|
||||
|
||||
const std::wstring dir{buffer, size};
|
||||
SetCurrentDirectoryW(dir.data());
|
||||
SetDllDirectoryW(dir.data());
|
||||
SetCurrentDirectoryW(buffer);
|
||||
SetDllDirectoryW(buffer);
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -188,11 +187,11 @@ int main()
|
||||
// people will start with admin rights if it crashes.
|
||||
limit_parallel_dll_loading();
|
||||
|
||||
srand(uint32_t(time(nullptr)));
|
||||
std::srand(uint32_t(time(nullptr)));
|
||||
|
||||
{
|
||||
auto premature_shutdown = true;
|
||||
const auto _ = gsl::finally([&premature_shutdown]()
|
||||
const auto _ = gsl::finally([&premature_shutdown]
|
||||
{
|
||||
if (premature_shutdown)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user