diff options
-rw-r--r-- | TODO/.autojump | 6 | ||||
-rw-r--r-- | TODO/autojump | 5 | ||||
-rw-r--r-- | compile | 1 | ||||
-rw-r--r-- | compile.bat | 5 | ||||
-rw-r--r-- | gamedata/gamelib.kv | 2 | ||||
-rw-r--r-- | src/autojump.c | 124 | ||||
-rw-r--r-- | src/autojump.h | 27 | ||||
-rw-r--r-- | src/sst.c | 6 |
8 files changed, 166 insertions, 10 deletions
diff --git a/TODO/.autojump b/TODO/.autojump new file mode 100644 index 0000000..1b41226 --- /dev/null +++ b/TODO/.autojump @@ -0,0 +1,6 @@ +Add back autojump +==== +I already wrote (and rewrote) the code long ago, but we kept it secret for a +long time to prevent L4D2 cheating. Now that proof standards are soon to +raised across the board, this is safe to include without having to worry about +verification headaches. diff --git a/TODO/autojump b/TODO/autojump deleted file mode 100644 index 7b9c8b4..0000000 --- a/TODO/autojump +++ /dev/null @@ -1,5 +0,0 @@ -Add back autojump -==== -I already wrote (and rewrote) the code long ago, but it's a secret until we -further raise the verification standard for L4D2. Stupid, but less stupid than -having no idea whether anyone's cheating, I guess. @@ -25,6 +25,7 @@ ld() { } src="\ + autojump.c \ con_.c \ demorec.c \ dbg.c \ diff --git a/compile.bat b/compile.bat index 06596b0..844ce01 100644 --- a/compile.bat +++ b/compile.bat @@ -24,8 +24,8 @@ clang -municode -O2 -fuse-ld=lld %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 -o .build/codegen.exe src/build/codegen.c src/build/cmeta.c src/os.c || exit /b
clang -municode -O2 -fuse-ld=lld %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
-o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c src/os.c || exit /b
-.build\codegen.exe src/con_.c src/demorec.c src/dbg.c src/fixes.c src/gamedata.c ^
-src/gameinfo.c src/hook.c src/kv.c src/os.c src/sst.c src/udis86.c || exit /b
+.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/dbg.c src/fixes.c ^
+src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/os.c src/sst.c src/udis86.c || exit /b
.build\mkgamedata.exe gamedata/engine.kv gamedata/gamelib.kv || exit /b
:: llvm-rc doesn't preprocess, looks like it might later:
:: https://reviews.llvm.org/D100755?id=339141
@@ -35,6 +35,7 @@ llvm-rc /FO .build\dll.res .build\dll.pp.rc || exit /b :: might as well remove the temp file afterwards
del .build\dll.pp.rc
clang -m32 -shared -fuse-ld=lld -O0 -w -o .build/tier0.dll src/tier0stub.c
+call :cc src/autojump.c || exit /b
call :cc src/con_.c || exit /b
call :cc src/demorec.c || exit /b
call :cc src/dbg.c || exit /b
diff --git a/gamedata/gamelib.kv b/gamedata/gamelib.kv index 388abb9..f6a989d 100644 --- a/gamedata/gamelib.kv +++ b/gamedata/gamelib.kv @@ -1,4 +1,4 @@ -// = client and server libaries = +// = client and server libraries = // CGameMovement vtidx_CheckJumpButton { 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__ |