// rain - bleah. I don't like the way this works, but it's good enough // for now. #define MAX_DELETE_MATCHES 32 #define ELIMINATE(field, val, func) \ for (x = 0; x < numMatches; x++) { \ if (func(matches[x]->field, val)) \ matches[x] = NULL; \ } qboolean etpro_ScriptAction_DeleteEntity( gentity_t *ent, char *params ) { gentity_t *e = NULL; char *token; char *p; char key[MAX_TOKEN_CHARS], value[MAX_TOKEN_CHARS]; gentity_t *matches[MAX_DELETE_MATCHES]; int hash; int x, numMatches = 0; vec3_t vec; p = params; for (x = 0; x < MAX_DELETE_MATCHES; x++) matches[x] = NULL; if (g_scriptDebug.value) G_Printf("%d : (%s) Beginning entity deletion (from %s)\n", level.time, ent->scriptName, ent->scriptName); // Get each key/value pair while( 1 ) { token = COM_ParseExt( &p, qfalse ); if( !token[0] ) break; strcpy( key, token ); token = COM_ParseExt( &p, qfalse); if( !token[0] ) { G_Error("key \"%s\" has no value", key); break; } strcpy( value, token ); if (g_scriptDebug.integer) G_Printf("%d : (%s) Searching for entity to delete where \"%s\" = \"%s\"\n", level.time, ent->scriptName, key, value); if (!Q_stricmp(key, "origin")) sscanf(value, "%f %f %f", &vec[0], &vec[1], &vec[2]); if (!numMatches) { // first pass - we don't have any matches, so search the entire // entity list if (!Q_stricmp(key, "scriptname")) { e = NULL; while ((matches[numMatches] = e = G_Find(e, FOFS(scriptName), value)) != NULL) numMatches++; } else if (!Q_stricmp(key, "classname")) { while ((matches[numMatches] = e = G_Find(e, FOFS(classname), value)) != NULL) numMatches++; } else if (!Q_stricmp(key, "targetname")) { hash = BG_StringHashValue(value); while ((matches[numMatches] = e = G_FindByTargetnameFast(e, value, hash)) != NULL) numMatches++; } else if (!Q_stricmp(key, "origin")) { for (x = 0; x < level.num_entities; x++) { if (VectorCompare(g_entities[x].s.origin, vec)) { matches[numMatches] = &g_entities[x]; numMatches++; } } } else G_Printf("^3Warning: Can't match for \"%s\" while deleting.\n", key); } else { // second pass - eliminating entities that don't match from // our match list if (!Q_stricmp(key, "scriptname")) { ELIMINATE(scriptName, value, Q_stricmp) } else if (!Q_stricmp(key, "classname")) { ELIMINATE(classname, value, Q_stricmp) } else if (!Q_stricmp(key, "targetname")) { ELIMINATE(targetname, value, Q_stricmp) } else if (!Q_stricmp(key, "origin")) { ELIMINATE(s.origin, vec, !VectorCompare) } else G_Printf("^3Warning: Can't match for \"%s\" while deleting.\n", key); } } for (e = NULL, x = 0; x < numMatches; x++) { if (e != NULL && matches[x] != NULL) { G_Printf("^1Error: Too many matches while deleting entity\n"); return qfalse; } e = matches[x]; } if (e == NULL) { G_Printf("^1Error: No matches while deleting entity\n"); return qfalse; } if (g_scriptDebug.integer) G_Printf("%d : (%s) Freeing entity #%d (classname \"%s\", scriptname \"%s\", targetname \"%s\")\n", level.time, ent->scriptName, e->s.number, e->classname, e->scriptName, e->targetname); G_FreeEntity( e ); return qtrue; }