summaryrefslogtreecommitdiffhomepage
path: root/src/autojump.c
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2021-12-27 00:48:59 +0000
committerMichael Smith <mikesmiffy128@gmail.com>2021-12-27 00:48:59 +0000
commit6a784e08fe87af65fa9d10912bbd5c1a27a14ba5 (patch)
treeae80ee63a2d47bedcdfb2b04341a008744002a9d /src/autojump.c
parent39725b79404acb6a020b3653b59df3e7bf598e00 (diff)
Reintroduce autojump code
Diffstat (limited to 'src/autojump.c')
-rw-r--r--src/autojump.c124
1 files changed, 124 insertions, 0 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