From 69d1498c8bd4d2205d33ddbbc8e67ac3e1be94d9 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Mon, 19 Jun 2023 10:35:24 -0700 Subject: [PATCH] EntityDef: support 'events' group, so developers can tie animation events to Inputs (Source Base I/O system) --- src/server/entityDef.qc | 78 +++++++++++++++++++------------- src/shared/NSEntity.h | 4 +- src/shared/NSEntity.qc | 11 ++--- src/shared/NSIO.h | 3 ++ src/shared/NSRenderableEntity.qc | 22 +++++++++ 5 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/server/entityDef.qc b/src/server/entityDef.qc index 6e4733ef..17c0a31c 100644 --- a/src/server/entityDef.qc +++ b/src/server/entityDef.qc @@ -42,6 +42,33 @@ "movetype" "0" } + + as you can see, key/value pairs can also split across multiple lines, + although that is discouraged. + + we also have things exclusive to our entityDef format: + + entityDef foobar { + [...] + + when "body" equals 1 { + "skin" "4" + } + } + + will allow developers to configure other fields when certain + conditions are met. + + this is also expanded to include model event callbacks to the tried + and true I/O system: + + entityDef foobar { + [...] + + events { + 1004 "SpawnDef" "foobar_projectile" + } + } */ /* games can feel free to set this to whatever you need. */ @@ -66,8 +93,10 @@ typedef struct string spawnData; string inheritKeys; - string tweakDefs; + string tweakDefs; /* when (field) equals/greater-than/less-than/is-not (value) */ string tweakKeys; + + string eventList; /* model events */ } entityDef_t; entityDef_t g_entDefTable[ENTITYDEF_MAX]; @@ -83,6 +112,7 @@ EntityDef_ReadFile(string filePath) entityDef_t currentDef; int braceDepth = 0i; string lastWord = __NULL__; + bool inEvent = false; currentDef.entClass = ""; currentDef.spawnClass = ""; @@ -90,6 +120,7 @@ EntityDef_ReadFile(string filePath) currentDef.inheritKeys = ""; currentDef.tweakDefs = ""; currentDef.tweakKeys = ""; + currentDef.eventList = ""; /* bounds check */ if (g_entDefCount >= ENTITYDEF_MAX) { @@ -127,6 +158,7 @@ EntityDef_ReadFile(string filePath) g_entDefTable[g_entDefCount].inheritKeys = currentDef.inheritKeys; g_entDefTable[g_entDefCount].tweakDefs = currentDef.tweakDefs; g_entDefTable[g_entDefCount].tweakKeys = currentDef.tweakKeys; + g_entDefTable[g_entDefCount].eventList = currentDef.eventList; /* increment the def count */ if (g_entDefCount < ENTITYDEF_MAX) @@ -138,13 +170,16 @@ EntityDef_ReadFile(string filePath) currentDef.inheritKeys = ""; currentDef.tweakDefs = ""; currentDef.tweakKeys = ""; + currentDef.eventList = ""; } /* we came out of a tweak */ if (braceDepth == 1) { - if (currentDef.tweakDefs != "") { + if (inEvent == false && currentDef.tweakKeys != "") { currentDef.tweakKeys = strcat(currentDef.tweakKeys, ";"); /* mark the end of a key chain */ + //currentDef.tweakKeys = ""; } + inEvent = false; } break; default: @@ -180,40 +215,19 @@ EntityDef_ReadFile(string filePath) break; } + inEvent = false; i+=3; + } else if (substring(word, 0, 6) == "events") { + inEvent = true; } else { /* rest gets dumped into spawndata */ currentDef.spawnData = strcat(currentDef.spawnData, "\"", word, "\"", " "); } } else if (braceDepth == 2) { - /* spawnclass is reserved and the next keyword specs it */ - if (word == "spawnclass") { - currentDef.spawnClass = argv(i+1); - i++; - } else if (word == "inherit") { - currentDef.inheritKeys = argv(i+1); - i++; - } else if (substring(word, 0, 7) == "editor_") { - /* do nothing */ - i++; - } else if (substring(word, 0, 4) == "when") { - switch (argv(i+2)) { - case "equals": - currentDef.tweakDefs = strcat(currentDef.tweakDefs, argv(i+1), " 0 ", argv(i+3), ";"); - break; - case "less-than": - currentDef.tweakDefs = strcat(currentDef.tweakDefs, argv(i+1), " 1 ", argv(i+3), ";"); - break; - case "greater-than": - currentDef.tweakDefs = strcat(currentDef.tweakDefs, argv(i+1), " 2 ", argv(i+3), ";"); - break; - case "is-not": - currentDef.tweakDefs = strcat(currentDef.tweakDefs, argv(i+1), " 3 ", argv(i+3), ";"); - break; - - } - i+=3; - } else { /* rest gets dumped into spawndata */ + /* it's a 'when' tweak */ + if (inEvent == false) { currentDef.tweakKeys = strcat(currentDef.tweakKeys, "\"", word, "\"", " "); + } else { /* it's a model event callback */ + currentDef.eventList = strcat(currentDef.eventList, "\"", word, "\"", " "); } } } @@ -250,7 +264,7 @@ EntityDef_Init(void) } } -#if 0 +#if 1 for (int i = 0i; i < g_entDefCount; i++) { int numKeys = tokenize_console(g_entDefTable[i].spawnData); print(sprintf("edef %i: %S\n", i, g_entDefTable[i].entClass)); @@ -258,6 +272,7 @@ EntityDef_Init(void) print(sprintf("\tinheritKeys: %S\n", g_entDefTable[i].inheritKeys)); print(sprintf("\ttweakDefs %S\n", g_entDefTable[i].tweakDefs)); print(sprintf("\ttweakKeys %S\n", g_entDefTable[i].tweakKeys)); + print(sprintf("\teventList %S\n", g_entDefTable[i].eventList)); print("\tspawnData:\n"); for (int c = 0; c < numKeys; c+=2) { @@ -417,6 +432,7 @@ EntityDef_PrepareEntity(entity target, int id) spawnWords = tokenizebyseparator(g_entDefTable[id].tweakDefs, ";"); } + targetEnt.m_strModelEventCB = g_entDefTable[id].eventList; /* pass over the event listing */ targetEnt.Spawned(); targetEnt.Respawn(); diff --git a/src/shared/NSEntity.h b/src/shared/NSEntity.h index 8df3f07c..a1505047 100644 --- a/src/shared/NSEntity.h +++ b/src/shared/NSEntity.h @@ -321,8 +321,8 @@ public: nonvirtual bool Visible(entity); /** Returns if the entity is visible from a given position and a field of view of 90 degrees. */ nonvirtual bool VisibleVec(vector); - /** Returns a normalized value of how far away the target is from the entity's view direction. 1 means dead-center. 0 means it's behind.*/ - nonvirtual bool DistanceFromYaw(vector); + /** Returns a normalized value of how far away the target is from the entity's view direction. 1 means dead-center. -1 means it's behind.*/ + nonvirtual float DistanceFromYaw(vector); /** Returns if the entity has any spawnflags set. */ nonvirtual bool HasSpawnFlags(float); /** Returns if the entity is aligned to the ground. */ diff --git a/src/shared/NSEntity.qc b/src/shared/NSEntity.qc index 60f67d4e..f715a25d 100644 --- a/src/shared/NSEntity.qc +++ b/src/shared/NSEntity.qc @@ -110,16 +110,13 @@ bool NSEntity::Visible( entity ent ) { return ( false ); } -bool NSEntity::DistanceFromYaw( vector targetPos ) { - vector flDelta; - float flFoV; - +float NSEntity::DistanceFromYaw( vector targetPos ) { + vector vecDelta; makevectors( angles ); - flDelta = normalize( targetPos - origin ); - return flDelta * v_forward; + vecDelta = normalize( targetPos - origin ); + return vecDelta * v_forward; } - bool NSEntity::HasSpawnFlags( float sf ) { return ( spawnflags & sf ) ? true : false; } diff --git a/src/shared/NSIO.h b/src/shared/NSIO.h index 9fe9e390..434b6cff 100644 --- a/src/shared/NSIO.h +++ b/src/shared/NSIO.h @@ -37,6 +37,9 @@ private: string m_strOnUser2; string m_strOnUser3; string m_strOnUser4; + + /* entityDef powered modelevent callbacks */ + string m_strModelEventCB; #endif public: diff --git a/src/shared/NSRenderableEntity.qc b/src/shared/NSRenderableEntity.qc index 45689f11..90913a13 100644 --- a/src/shared/NSRenderableEntity.qc +++ b/src/shared/NSRenderableEntity.qc @@ -755,7 +755,29 @@ NSRenderableEntity::HandleAnimEvent(float flTimeStamp, int iCode, string strData break; #endif default: +#ifdef SERVER + int eDefEvents = tokenize(m_strModelEventCB); + //print(sprintf("%i\n", eDefEvents)); + + for (int i = 0; i < eDefEvents; i+=3) { + int testCode = stoi(argv(i+0)); + string testInput = argv(i+1); + string testData = argv(i+2); + //print(sprintf("%i %s %s\n", testCode, testInput, testData)); + + /* this is kind of messy in that we can only pass one parm over another */ + if (iCode == testCode) { + if (testData != "") + Input(this, testInput, testData); + else + Input(this, testInput, strData); /* no parms passed. */ + + tokenize(m_strModelEventCB); /* ensure argv() is 'rewound'... */ + } + } +#else NSLog("Unknown model event: %f %i %S", flTimeStamp, iCode, strData); +#endif } }