diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/autojump.c | 124 | ||||
-rw-r--r-- | src/autojump.h | 27 | ||||
-rw-r--r-- | src/sst.c | 6 |
3 files changed, 155 insertions, 2 deletions
diff --git a/src/autojump.c b/src/autojump.c new file mode 100644 index 0000000..fa0f4b5 --- /dev/null +++ b/src/autojump.c @@ -0,0 +1,124 @@ +/* + * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdbool.h> + +#include "con_.h" +#include "factory.h" +#include "gamedata.h" +#include "intdefs.h" +#include "hook.h" +#include "mem.h" +#include "os.h" +#include "vcall.h" + +DEF_CVAR(sst_autojump, "Jump upon hitting the group while holding space", "0", + CON_REPLICATE | CON_DEMO | CON_HIDDEN) + +struct vec3f { float x, y, z; }; +struct CMoveData { + bool firstrun : 1; + bool gamecodemoved : 1; + ulong playerhandle; + int impulse; + struct vec3f viewangles; + struct vec3f absviewangles; + int buttons; + int oldbuttons; + float mv_forward; + float mv_side; + float mv_up; + float maxspeed; + float clientmaxspeed; + struct vec3f vel; + struct vec3f angles; + struct vec3f oldangles; + float out_stepheight; + struct vec3f out_wishvel; + struct vec3f out_jumpvel; + struct vec3f constraint_center; + float constraint_radius; + float constraint_width; + float constraint_speedfactor; + struct vec3f origin; +}; + +#define IN_JUMP 2 +#define NIDX 256 // *completely* arbitrary lol +static bool justjumped[NIDX] = {0}; +static inline int handleidx(ulong h) { return h & (1 << 11) - 1; } + +static void *gmsv = 0, *gmcl = 0; +typedef bool (VCALLCONV *CheckJumpButton_f)(void *); +static CheckJumpButton_f origsv, origcl; + +static bool VCALLCONV hook(void *this) { + struct CMoveData **mvp = mem_offset(this, gamedata_off_mv), *mv = *mvp; + // use 0 idx for client side, as server indices start at 1 + // FIXME: does this account for splitscreen??? + int i = this == gmsv ? handleidx(mv->playerhandle) : 0; + if (con_getvari(sst_autojump) && !justjumped[i]) mv->oldbuttons &= ~IN_JUMP; + return justjumped[i] = (this == gmsv ? origsv : origcl)(this); +} + +static bool unprot(void *gm) { + void **vtable = *(void ***)gm; + bool ret = os_mprot(vtable + gamedata_vtidx_CheckJumpButton, + sizeof(void *), PAGE_EXECUTE_READWRITE); + if (!ret) con_warn("autojump: couldn't make memory writeable\n"); + return ret; +} + +bool autojump_init(void) { + // TODO(featgen): auto-check these factories + if (!factory_client || !factory_server) { + con_warn("autojump: missing required interfaces\n"); + return false; + } + if (!gamedata_has_vtidx_CheckJumpButton || !gamedata_has_off_mv) { + con_warn("autojump: missing gamedata entries for this engine\n"); + return false; + } + + gmsv = factory_server("GameMovement001", 0); + if (!gmsv) { + con_warn("autojump: couldn't get server-side game movement interface\n"); + return false; + } + if (!unprot(gmsv)) return false; + gmcl = factory_client("GameMovement001", 0); + if (!gmcl) { + con_warn("autojump: couldn't get client-side game movement interface\n"); + return false; + } + if (!unprot(gmcl)) return false; + origsv = (CheckJumpButton_f)hook_vtable(*(void ***)gmsv, + gamedata_vtidx_CheckJumpButton, (void *)&hook); + origcl = (CheckJumpButton_f)hook_vtable(*(void ***)gmcl, + gamedata_vtidx_CheckJumpButton, (void *)&hook); + + sst_autojump->base.flags &= ~CON_HIDDEN; + return true; +} + +void autojump_end(void) { + unhook_vtable(*(void ***)gmsv, gamedata_vtidx_CheckJumpButton, + (void *)origsv); + unhook_vtable(*(void ***)gmcl, gamedata_vtidx_CheckJumpButton, + (void *)origcl); +} + +// vi: sw=4 ts=4 noet tw=80 cc=80 diff --git a/src/autojump.h b/src/autojump.h new file mode 100644 index 0000000..efcde2e --- /dev/null +++ b/src/autojump.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2021 Michael Smith <mikesmiffy128@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INC_AUTOJUMP_H +#define INC_AUTOJUMP_H + +#include <stdbool.h> + +bool autojump_init(void); +void autojump_end(void); + +#endif + +// vi: sw=4 ts=4 noet tw=80 cc=80 @@ -17,6 +17,7 @@ #include <stdbool.h> #include <string.h> +#include "autojump.h" #include "con_.h" #include "demorec.h" #include "factory.h" @@ -65,6 +66,7 @@ ifacefactory factory_client = 0, factory_server = 0, factory_engine = 0; // figures out the dependencies at build time and generates all the init glue // but we want to actually release the plugin this decade so for now I'm just // plonking ~~some bools~~ one bool here and worrying about it later. :^) +static bool has_autojump = false; static bool has_demorec = false; // HACK: later versions of L4D2 show an annoying dialog on every plugin_load. @@ -122,7 +124,7 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) { } nc: gamedata_init(); - // TODO(autojump): we'd init that here + has_autojump = autojump_init(); has_demorec = demorec_init(); fixes_apply(); @@ -164,7 +166,7 @@ e: con_colourmsg(RGBA(64, 255, 64, 255), } static void do_unload(void) { - // TODO(autojump): we'd end that here + if (has_autojump) autojump_end(); if (has_demorec) demorec_end(); #ifdef __linux__ |