summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-05-15 23:05:41 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-05-15 23:05:41 +0100
commit9009f75bf5fd33e13abae5762d31968b39f233c3 (patch)
tree99a65caf9b2199ad4a8d7bbc539867bfea254412
parent831862bec84dde31a0568ec8a2f2b0170e18a973 (diff)
Fix GetEngineBuildNumber and entity property stuff
I still haven't bothered to flesh out all the possible indices for GetEngineBuildNumber but we're back to being able to use it to detect The Last Stand (as a result of some old version testing Aciidz did - thanks again!). This means we can do away with the terrible map file- based hotfix. Also, turns out sst_l4d_testwarp doesn't work if the plugin gets loaded early via VDF because certain SendTable offsets start out negated, so we work around that too now.
-rw-r--r--gamedata/engine.kv11
-rw-r--r--src/build/mkentprops.c13
-rw-r--r--src/engineapi.c14
-rw-r--r--src/gametype.h1
4 files changed, 27 insertions, 12 deletions
diff --git a/gamedata/engine.kv b/gamedata/engine.kv
index 39fa1df..80caa74 100644
--- a/gamedata/engine.kv
+++ b/gamedata/engine.kv
@@ -26,16 +26,19 @@ vtidx_GetGameDirectory {
2013 35
}
Client013 {
- L4Dx 36 // AND THEN THEY CHANGED IT BACK LATER!
+ L4Dx 36 // AND THEN THEY CHANGED IT BACK LATER! (on 2.0.4.1)
default 35 // <- most things have this!
}
Client012 37 // dmomm, ep1, ...
}
-// TODO(compat): apparently this changed, in early versions it's NOT 99!
-// Come up with some way to detect it properly!?
vtidx_GetEngineBuildNumber {
- //L4D2 99
+ L4D2 {
+ Client013 99
+ //Client014 ??? // TODO(compat): find out what this (maybe 136?)
+ }
}
+
+// VEngineServer
vtidx_PEntityOfEntIndex { OrangeBox 19 } // probably OE too but???
sz_edict {
diff --git a/src/build/mkentprops.c b/src/build/mkentprops.c
index 5dd2fea..e99873b 100644
--- a/src/build/mkentprops.c
+++ b/src/build/mkentprops.c
@@ -144,11 +144,11 @@ _( "static void initentprops(struct ServerClass *class) {")
F( " for (int needclasses = %d; class; class = class->next) {", nclasses)
char *else1 = "";
for (struct class *c = classes.x[0]; c; c = c->hdr.x[0]) {
- // TODO(opt): some sort of PHF instead of chained strcmp, if we ever
- // have more than a few classes/properties?
+ // TODO(opt): some sort of PHF or trie instead of chained strcmp, if we
+ // ever have more than a few classes/properties?
F( " %sif (!strcmp(class->name, \"%s\")) {", else1, c->name)
_( " struct SendTable *st = class->table;")
- // christ this is awful :(
+ // XXX: christ this is all awful :(
F( " int needprops = %d;", c->props.sz)
_( " for (struct SendProp *p = st->props; (char *)p -")
_( " (char *)st->props < st->nprops * sz_SendProp;")
@@ -159,7 +159,12 @@ _( " p = mem_offset(p, sz_SendProp)) {")
F( " %sif (!strcmp(*(const char **)mem_offset(p, off_SP_varname), \"%s\")) {",
else2, (*pp)->propname) // ugh
F( " has_%s = true;", (*pp)->varname)
-F( " %s = *(int *)mem_offset(p, off_SP_offset);", (*pp)->varname)
+ // from AM L4D2 SDK headers:
+ // > SENDPROP_VECTORELEM makes [offset] negative to start with so we
+ // > can detect that and set the SPROP_IS_VECTOR_ELEM flag.
+ // apparently if we're loaded via VDF, it hasn't been flipped back
+ // yet. just calling abs() on it as an easy solution.
+F( " %s = abs(*(int *)mem_offset(p, off_SP_offset));", (*pp)->varname)
_( " if (!--needprops) break;")
_( " }")
else2 = "else ";
diff --git a/src/engineapi.c b/src/engineapi.c
index 369bebd..ec3d857 100644
--- a/src/engineapi.c
+++ b/src/engineapi.c
@@ -15,6 +15,7 @@
*/
#include <stdbool.h> // used in generated code
+#include <stdlib.h> // "
#include <string.h> // "
#include "con_.h"
@@ -43,6 +44,8 @@ void *globalvars;
DECL_VFUNC_DYN(void *, GetAllServerClasses)
DECL_VFUNC_DYN(int, GetEngineBuildNumber)
+DECL_VFUNC(int, GetEngineBuildNumber_newl4d2, 99) // duping gamedata entry, yuck
+
#include <entpropsinit.gen.h>
bool engineapi_init(int pluginver) {
@@ -84,9 +87,13 @@ bool engineapi_init(int pluginver) {
_gametype_tag |= _gametype_tag_Portal1;
}
- // TERRIBLE HACK: TODO(compat): come up with a better method later
- if (GAMETYPE_MATCHES(L4D2) && os_access(OS_LIT(
- "update/maps/c14m1_junkyard.bsp"), R_OK) != -1) {
+ // Ugly HACK: we want to call GetEngineBuildNumber to find out if we're on a
+ // Last Stand version (because they changed entity vtables for some reason),
+ // but that function also got moved in 2.0.4.1 which means we can't call it
+ // till gamedata is set up, so we have to have a bit of redundant logic here
+ // to bootstrap things.
+ if (GAMETYPE_MATCHES(L4D2) && GAMETYPE_MATCHES(Client013) &&
+ VCALL(engclient, GetEngineBuildNumber_newl4d2) >= 2200) {
_gametype_tag |= _gametype_tag_TheLastStand;
}
@@ -100,7 +107,6 @@ bool engineapi_init(int pluginver) {
has_off_SP_varname && has_off_SP_offset) {
initentprops(VCALL(srvdll, GetAllServerClasses));
}
-
return true;
}
diff --git a/src/gametype.h b/src/gametype.h
index c825ee6..2464000 100644
--- a/src/gametype.h
+++ b/src/gametype.h
@@ -59,6 +59,7 @@ extern u64 _gametype_tag;
#define _gametype_tag_L4Dbased (_gametype_tag_L4Dx | _gametype_tag_Portal2)
#define _gametype_tag_OrangeBoxbased \
(_gametype_tag_OrangeBox | _gametype_tag_2013)
+#define _gametype_tag_Portal (_gametype_tag_Portal1 | _gametype_tag_Portal2)
#define GAMETYPE_MATCHES(x) !!(_gametype_tag & (_gametype_tag_##x))