eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *name, evalc_t *cache) { fdef_t *var; if (!cache) { var = ED_FindField(progfuncs, name); if (!var) return NULL; return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]); } if (!cache->varname) { cache->varname = name; var = ED_FindField(progfuncs, name); if (!var) { cache->ofs32 = NULL; return NULL; } cache->ofs32 = var; cache->varname = var->name; if (!ed) return (void*)~0; //something not null return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]); } if (cache->ofs32 == NULL) return NULL; return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[cache->ofs32->ofs]); }
eval_t *GetEdictFieldValue(edict_t *ed, char *field) { ddef_t *def = NULL; int i; static int rep = 0; for (i=0 ; i<GEFV_CACHESIZE ; i++) { if (!strcmp(field, gefvCache[i].field)) { def = gefvCache[i].pcache; goto Done; } } def = ED_FindField (field); if (strlen(field) < MAX_FIELD_LEN) { gefvCache[rep].pcache = def; strlcpy (gefvCache[rep].field, field, MAX_FIELD_LEN); rep ^= 1; } Done: if (!def) return NULL; return (eval_t *)((char *)&ed->v + def->ofs*4); }
/* ============ ED_FindFieldOffset ============ */ int ED_FindFieldOffset (char *field) { ddef_t *d; d = ED_FindField(field); if (!d) return 0; return d->ofs*4; }
/* ==================== ED_ParseEdict Parses an edict out of the given string, returning the new position ed should be a properly initialized empty edict. Used for initial level load and for savegames. ==================== */ char *ED_ParseEdict (char *data, edict_t *ent) { ddef_t *key; qbool anglehack; qbool init; char keyname[256]; init = false; // clear it if (ent != sv.edicts) // hack memset (&ent->v, 0, progs->entityfields * 4); // go through all the dictionary pairs while (1) { // parse key data = COM_Parse (data); if (com_token[0] == '}') break; if (!data) SV_Error ("ED_ParseEntity: EOF without closing brace"); // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) if (!strcmp(com_token, "angle")) { strlcpy (com_token, "angles", MAX_COM_TOKEN); anglehack = true; } else anglehack = false; // FIXME: change light to _light to get rid of this hack if (!strcmp(com_token, "light")) strlcpy (com_token, "light_lev", MAX_COM_TOKEN); // hack for single light def strlcpy (keyname, com_token, sizeof(keyname)); // parse value data = COM_Parse (data); if (!data) SV_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') SV_Error ("ED_ParseEntity: closing brace without data"); init = true; // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake if (keyname[0] == '_') continue; key = ED_FindField (keyname); if (!key) { Con_Printf ("%s is not a field\n", keyname); continue; } if (anglehack) { char temp[32]; strlcpy (temp, com_token, sizeof(temp)); snprintf (com_token, MAX_COM_TOKEN, "0 %s 0", temp); } if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) SV_Error ("ED_ParseEdict: parse error"); } if (!init) ent->e->free = true; return data; }
/* ============= ED_ParseEval Can parse either fields or globals returns false if error ============= */ qbool ED_ParseEpair (void *base, ddef_t *key, char *s) { int i; char string[128]; ddef_t *def; char *v, *w; void *d; dfunction_t *func; d = (void *)((int *)base + key->ofs); switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: *(string_t *)d = PR_SetString(ED_NewString (s)); break; case ev_float: *(float *)d = Q_atof (s); break; case ev_vector: strlcpy (string, s, sizeof(string)); v = string; w = string; for (i=0 ; i<3 ; i++) { while (*v && *v != ' ') v++; *v = 0; ((float *)d)[i] = Q_atof (w); w = v = v+1; } break; case ev_entity: *(int *)d = EDICT_TO_PROG(EDICT_NUM(Q_atoi (s))); break; case ev_field: def = ED_FindField (s); if (!def) { Con_Printf ("Can't find field %s\n", s); return false; } *(int *)d = G_INT(def->ofs); break; case ev_function: func = ED_FindFunction (s); if (!func) { Con_Printf ("Can't find function %s\n", s); return false; } *(func_t *)d = func - pr_functions; break; default: break; } return true; }
/* ==================== ED_ParseEdict Parses an edict out of the given string, returning the new position ed should be a properly initialized empty edict. Used for initial level load and for savegames. ==================== */ const char *ED_ParseEdict (const char *data, edict_t *ent) { ddef_t *key; char keyname[256]; qboolean anglehack, init; int n; init = false; // clear it if (ent != sv.edicts) // hack memset (&ent->v, 0, progs->entityfields * 4); // go through all the dictionary pairs while (1) { // parse key data = COM_Parse (data); if (com_token[0] == '}') break; if (!data) Host_Error ("ED_ParseEntity: EOF without closing brace"); // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) if (!strcmp(com_token, "angle")) { strcpy (com_token, "angles"); anglehack = true; } else anglehack = false; // FIXME: change light to _light to get rid of this hack if (!strcmp(com_token, "light")) strcpy (com_token, "light_lev"); // hack for single light def strcpy (keyname, com_token); // another hack to fix keynames with trailing spaces n = strlen(keyname); while (n && keyname[n-1] == ' ') { keyname[n-1] = 0; n--; } // parse value data = COM_Parse (data); if (!data) Host_Error ("ED_ParseEntity: EOF without closing brace"); if (com_token[0] == '}') Host_Error ("ED_ParseEntity: closing brace without data"); init = true; // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake if (keyname[0] == '_') continue; //johnfitz -- hack to support .alpha even when progs.dat doesn't know about it if (!strcmp(keyname, "alpha")) ent->alpha = ENTALPHA_ENCODE(atof(com_token)); //johnfitz key = ED_FindField (keyname); if (!key) { //johnfitz -- HACK -- suppress error becuase fog/sky/alpha fields might not be mentioned in defs.qc if (strncmp(keyname, "sky", 3) && strcmp(keyname, "fog") && strcmp(keyname, "alpha")) Con_DPrintf ("\"%s\" is not a field\n", keyname); //johnfitz -- was Con_Printf continue; } if (anglehack) { char temp[32]; strcpy (temp, com_token); sprintf (com_token, "0 %s 0", temp); } if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) Host_Error ("ED_ParseEdict: parse error"); } if (!init) ent->free = true; return data; }
/* ============= ED_ParseEval Can parse either fields or globals returns false if error ============= */ static qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s) { int i; char string[128]; ddef_t *def; char *v, *w; void *d; dfunction_t *func; d = (void *)((int *)base + key->ofs); switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: *(string_t *)d = ED_NewString(s); break; case ev_float: *(float *)d = atof (s); break; case ev_vector: strcpy (string, s); v = string; w = string; for (i = 0; i < 3; i++) { while (*v && *v != ' ') v++; *v = 0; ((float *)d)[i] = atof (w); w = v = v+1; } break; case ev_entity: *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s))); break; case ev_field: def = ED_FindField (s); if (!def) { //johnfitz -- HACK -- suppress error becuase fog/sky fields might not be mentioned in defs.qc if (strncmp(s, "sky", 3) && strcmp(s, "fog")) Con_DPrintf ("Can't find field %s\n", s); return false; } *(int *)d = G_INT(def->ofs); break; case ev_function: func = ED_FindFunction (s); if (!func) { Con_Printf ("Can't find function %s\n", s); return false; } *(func_t *)d = func - pr_functions; break; default: break; } return true; }