entityDef: add support for condition based tweaks

This commit is contained in:
Marco Cawthorne 2023-06-14 06:44:37 -07:00
parent 3eb2ec1b37
commit 0dc8f4ec75
Signed by: eukara
GPG key ID: CE2032F0A2882A22

View file

@ -49,17 +49,32 @@
#define ENTITYDEF_MAX 128
#endif
var string g_lastSpawnData;
enum
{
EDEFTWEAK_EQ = 0,
EDEFTWEAK_LT,
EDEFTWEAK_GT,
EDEFTWEAK_NOT
};
typedef struct
{
string entClass;
string spawnClass;
string spawnData;
string inheritKeys;
string tweakDefs;
string tweakKeys;
} entityDef_t;
entityDef_t g_entDefTable[ENTITYDEF_MAX];
var int g_entDefCount;
string g_entDefInclude;
void
EntityDef_ReadFile(string filePath)
{
@ -73,6 +88,8 @@ EntityDef_ReadFile(string filePath)
currentDef.spawnClass = "";
currentDef.spawnData = "";
currentDef.inheritKeys = "";
currentDef.tweakDefs = "";
currentDef.tweakKeys = "";
/* bounds check */
if (g_entDefCount >= ENTITYDEF_MAX) {
@ -108,6 +125,8 @@ EntityDef_ReadFile(string filePath)
g_entDefTable[g_entDefCount].spawnClass = currentDef.spawnClass;
g_entDefTable[g_entDefCount].spawnData = currentDef.spawnData;
g_entDefTable[g_entDefCount].inheritKeys = currentDef.inheritKeys;
g_entDefTable[g_entDefCount].tweakDefs = currentDef.tweakDefs;
g_entDefTable[g_entDefCount].tweakKeys = currentDef.tweakKeys;
/* increment the def count */
if (g_entDefCount < ENTITYDEF_MAX)
@ -117,12 +136,23 @@ EntityDef_ReadFile(string filePath)
currentDef.spawnClass = "";
currentDef.spawnData = "";
currentDef.inheritKeys = "";
currentDef.tweakDefs = "";
currentDef.tweakKeys = "";
}
/* we came out of a tweak */
if (braceDepth == 1) {
if (currentDef.tweakDefs != "") {
currentDef.tweakKeys = strcat(currentDef.tweakKeys, ";"); /* mark the end of a key chain */
}
}
break;
default:
/* anything outside braces defines the classname for the next def */
if (braceDepth == 0 && lastWord == "entityDef") {
currentDef.entClass = word;
} else if (braceDepth == 0 && lastWord == "include") {
g_entDefInclude = strcat(g_entDefInclude, word, ";");
} else if (braceDepth == 1) {
/* spawnclass is reserved and the next keyword specs it */
if (word == "spawnclass") {
@ -134,9 +164,57 @@ EntityDef_ReadFile(string filePath)
} 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 */
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 */
currentDef.tweakKeys = strcat(currentDef.tweakKeys, "\"", word, "\"", " ");
}
}
}
lastWord = word;
@ -151,19 +229,36 @@ void
EntityDef_Init(void)
{
searchhandle pm;
g_entDefInclude = "";
pm = search_begin("def/*.def", TRUE, TRUE);
for (int i = 0; i < search_getsize(pm); i++) {
EntityDef_ReadFile(search_getfilename(pm, i));
}
search_end(pm);
//print(sprintf("includes: %S\n", g_entDefInclude));
if (g_entDefInclude != "") {
int includeCount = tokenizebyseparator(g_entDefInclude, ";");
for (int i = 0; i < (includeCount-1); i++) {
string fileName = strcat("def/", argv(i));
EntityDef_ReadFile(fileName);
includeCount = tokenizebyseparator(g_entDefInclude, ";");
}
}
#if 0
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));
print(sprintf("\tspawnclass: %S\n", g_entDefTable[i].spawnClass));
print(sprintf("\tinheritKeys: %S\n", g_entDefTable[i].inheritKeys));
print(sprintf("\tspawnData:\n", g_entDefTable[i].spawnData));
print(sprintf("\ttweakDefs %S\n", g_entDefTable[i].tweakDefs));
print(sprintf("\ttweakKeys %S\n", g_entDefTable[i].tweakKeys));
print("\tspawnData:\n");
for (int c = 0; c < numKeys; c+=2) {
print(sprintf("\t\t%S %S\n", argv(c), argv(c+1)));
@ -172,6 +267,54 @@ EntityDef_Init(void)
#endif
}
static bool
EntityDef_CheckCondition(int id, string keyWord, float tweakCondition, string keyValue)
{
int spawnWords = tokenize_console(g_lastSpawnData);
string key, value;
float tmp1, tmp2;
//print(sprintf("%i %S %d %S\n", id, keyWord, tweakCondition, keyValue));
for (int i = 1; i < (spawnWords - 1); i+= 2) {
key = argv(i);
value = argv(i+1);
//print(sprintf("comparing %S with %S\n", key, value));
/* fforward out */
if (key != keyWord)
continue;
switch (tweakCondition) {
case EDEFTWEAK_EQ:
if (key == keyWord && value == keyValue)
return true;
break;
case EDEFTWEAK_LT:
tmp1 = stof(keyValue);
tmp2 = stof(value);
if (key == keyWord && tmp2 < tmp1)
return true;
break;
case EDEFTWEAK_GT:
tmp1 = stof(keyValue);
tmp2 = stof(value);
if (key == keyWord && tmp2 > tmp1)
return true;
break;
case EDEFTWEAK_NOT:
if (key == keyWord && value != keyValue)
return true;
break;
}
}
return false;
}
static NSEntity
EntityDef_PrepareEntity(entity target, int id)
{
@ -226,27 +369,87 @@ EntityDef_PrepareEntity(entity target, int id)
}
/* now we load our own spawndata, which starts and ends with braces */
spawnWords = tokenize_console(__fullspawndata);
spawnWords = tokenize_console(g_lastSpawnData);
for (int i = 1; i < (spawnWords - 1); i+= 2) {
/* ignore this, always */
if (argv(i) != "classname")
targetEnt.SpawnKey(argv(i), argv(i+1));
}
/* now after everything else is done, check our entityDef tweaks */
spawnWords = tokenizebyseparator(g_entDefTable[id].tweakDefs, ";");
for (int i = 0; i < spawnWords; i++) {
string groupSegment = argv(i);
//print(sprintf("group: %S\n", groupSegment));
tokenize_console(groupSegment); /* split the group segment into 3 */
string keyWord = argv(0);
float tweakCondition = stof(argv(1));
string keyValue = argv(2);
/* iterate through a bunch of different data to check our condition */
if (EntityDef_CheckCondition(id, keyWord, tweakCondition, keyValue)) {
int tweakGroups = tokenizebyseparator(g_entDefTable[id].tweakKeys, ";");
//print(sprintf("%S passed the check\n", keyWord));
/* iterate through the ; key groups */
for (int x = 0; x < tweakGroups; x++) {
int tweakSpawns = tokenize_console(argv(x));
/* ignore any other key group */
if (x == i) {
/* iterate through key/value pairs within the ; key groups */
for (int y = 0; y < tweakSpawns; y+= 2) {
//print(sprintf("applying %S and %S\n", argv(y), argv(y+1)));
targetEnt.SpawnKey(argv(y), argv(y+1));
}
}
/* retokenize */
tweakGroups = tokenizebyseparator(g_entDefTable[id].tweakKeys, ";");
}
}
/* retokenize our condition */
spawnWords = tokenizebyseparator(g_entDefTable[id].tweakDefs, ";");
}
targetEnt.Spawned();
targetEnt.Respawn();
/* now we rename the classname for better visibility */
targetEnt.classname = g_entDefTable[id].entClass;
__fullspawndata = "";
g_lastSpawnData = "";
return targetEnt;
}
/* precache resources inside an entityDef */
static void
EntityDef_Precaches(int index)
{
int spawnWords = tokenize_console(g_entDefTable[index].spawnData);
for (int i = 0; i < spawnWords; i+= 2) {
string strKey = argv(i);
string strValue = argv(i+1);
if (substring(strKey, 0, 4) == "snd_") {
Sound_Precache(strValue);
spawnWords = tokenize_console(g_entDefTable[index].spawnData);
}
}
}
NSEntity
EntityDef_SpawnClassname(string className)
{
g_lastSpawnData = __fullspawndata;
for (int i = 0i; i < g_entDefCount; i++) {
if (className == g_entDefTable[i].entClass) {
EntityDef_Precaches(i);
return EntityDef_PrepareEntity(self, i);
}
}
@ -304,4 +507,16 @@ EntityDef_GetKeyValue(string className, string keyName)
}
return "";
}
bool
EntityDef_HasSpawnClass(string className)
{
for (int i = 0i; i < g_entDefCount; i++) {
if (className == g_entDefTable[i].entClass) {
return (g_entDefTable[i].spawnClass != "") ? true : false;
}
}
return false;
}