diff --git a/src/client/component/gameplay.cpp b/src/client/component/gameplay.cpp index f1926661..18728c4f 100644 --- a/src/client/component/gameplay.cpp +++ b/src/client/component/gameplay.cpp @@ -87,6 +87,30 @@ namespace gameplay a.jmp(0x14067AE1A); } + + void pm_bouncing_stub_mp(utils::hook::assembler& a) + { + const auto no_bounce = a.newLabel(); + const auto loc_140691518 = a.newLabel(); + + a.push(rax); + + a.mov(rax, qword_ptr(reinterpret_cast(&dvars::pm_bouncing))); + a.mov(al, byte_ptr(rax, 0x10)); + a.cmp(byte_ptr(rbp, -0x5D), al); + + a.pop(rax); + a.jz(no_bounce); + a.jmp(0x140691481); + + a.bind(no_bounce); + a.cmp(dword_ptr(rsp, 0x44), 0); + a.jnz(loc_140691518); + a.jmp(0x14069146F); + + a.bind(loc_140691518); + a.jmp(0x140691518); + } } class component final : public component_interface @@ -103,6 +127,10 @@ namespace gameplay dvars::jump_spreadAdd = dvars::register_float("jump_spreadAdd", 64.0f, 0.0f, 512.0f, game::DVAR_FLAG_REPLICATED, "The amount of spread scale to add as a side effect of jumping"); + dvars::pm_bouncing = dvars::register_bool("pm_bouncing", false, + game::DVAR_FLAG_REPLICATED, "Enable bouncing"); + utils::hook::jump(0x14069145E, utils::hook::assemble(pm_bouncing_stub_mp), true); + // Influence PM_JitterPoint code flow so the trace->startsolid checks are 'ignored' pm_player_trace_hook.create(0x14068F0A0, &pm_player_trace_stub); diff --git a/src/client/component/gsc.cpp b/src/client/component/gsc.cpp index cc207a3c..36616409 100644 --- a/src/client/component/gsc.cpp +++ b/src/client/component/gsc.cpp @@ -10,6 +10,7 @@ #include "gsc.hpp" #include "scheduler.hpp" #include "fastfiles.hpp" +#include "command.hpp" #include "game/scripting/execution.hpp" #include "game/scripting/functions.hpp" @@ -109,7 +110,18 @@ namespace gsc } auto assembly = compiler->output(); - assembler->assemble(real_name, assembly); + + try + { + assembler->assemble(real_name, assembly); + } + catch (const std::exception& e) + { + console::error("*********** script compile error *************\n"); + console::error("failed to assemble '%s':\n%s", real_name.data(), e.what()); + console::error("**********************************************\n"); + return nullptr; + } const auto script_file_ptr = reinterpret_cast(allocate_buffer(sizeof(game::ScriptFile))); script_file_ptr->name = file_name; @@ -703,6 +715,12 @@ namespace gsc return game::Scr_AddInt(sound->head->soundFile->u.streamSnd.totalMsec); }); + add_function("executecommand", [](const game::scr_entref_t ref) + { + const auto cmd = get_argument(0).as(); + command::execute(cmd); + }); + scripting::on_shutdown([](int free_scripts) { if (free_scripts) diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index 5fc1e56b..17fe26f2 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -20,6 +20,8 @@ namespace dvars game::dvar_t* jump_ladderPushVel = nullptr; game::dvar_t* jump_spreadAdd = nullptr; + game::dvar_t* pm_bouncing = nullptr; + game::dvar_t* r_fullbright = nullptr; game::dvar_t* cg_legacyCrashHandling = nullptr; diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index ae7ceb08..82822fc6 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -28,6 +28,8 @@ namespace dvars extern game::dvar_t* jump_ladderPushVel; extern game::dvar_t* jump_spreadAdd; + extern game::dvar_t* pm_bouncing; + extern game::dvar_t* r_fullbright; extern game::dvar_t* cg_legacyCrashHandling;