diff options
| author | 2021-12-27 00:48:59 +0000 | |
|---|---|---|
| committer | 2021-12-27 00:48:59 +0000 | |
| commit | 6a784e08fe87af65fa9d10912bbd5c1a27a14ba5 (patch) | |
| tree | ae80ee63a2d47bedcdfb2b04341a008744002a9d /src | |
| parent | 39725b79404acb6a020b3653b59df3e7bf598e00 (diff) | |
| download | sst-6a784e08fe87af65fa9d10912bbd5c1a27a14ba5.tar.gz sst-6a784e08fe87af65fa9d10912bbd5c1a27a14ba5.zip  | |
Reintroduce autojump code
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__  | 
