func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum) { dfunction_t *f=NULL; if (pnum == PR_ANY) { for (pnum = 0; (unsigned)pnum < maxprogs; pnum++) { if (!pr_progstate[pnum].progs) continue; f = ED_FindFunction(progfuncs, funcname, &pnum, pnum); if (f) break; } } else if (pnum == PR_ANYBACK) //run backwards { for (pnum = maxprogs-1; pnum >= 0; pnum--) { if (!pr_progstate[pnum].progs) continue; f = ED_FindFunction(progfuncs, funcname, &pnum, pnum); if (f) break; } } else f = ED_FindFunction(progfuncs, funcname, &pnum, pnum); if (!f) return 0; { ddef16_t *var16; ddef32_t *var32; switch(pr_progstate[pnum].structtype) { case PST_KKQWSV: case PST_DEFAULT: var16 = ED_FindTypeGlobalFromProgs16(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function. if (!var16) return (f - pr_progstate[pnum].functions) | (pnum << 24); return *(int *)&pr_progstate[pnum].globals[var16->ofs]; case PST_QTEST: case PST_FTE32: var32 = ED_FindTypeGlobalFromProgs32(progfuncs, funcname, pnum, ev_function); //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function. if (!var32) return (f - pr_progstate[pnum].functions) | (pnum << 24); return *(int *)&pr_progstate[pnum].globals[var32->ofs]; } Sys_Error("Error with def size (PR_FindFunc)"); } return 0; }
func_t ED_FindFunctionOffset (char *name) { dfunction_t *func; func = ED_FindFunction (name); return func ? (func_t)(func - pr_functions) : 0; }
/* ================== Host_QC_Exec Execute QC commands from the console ================== */ void Host_QC_Exec (void) { dfunction_t *f; if (cmd_source == src_command) { Cmd_ForwardToServer (); return; } if (!developer.value) return; f = 0; if ((f = ED_FindFunction(Cmd_Argv(1))) != NULL) { pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram ((func_t)(f - pr_functions)); } else Con_Printf("bad function\n"); }
/* ================ ED_LoadFromFile The entities are directly placed in the array, rather than allocated with ED_Alloc, because otherwise an error loading the map would have entity number references out of order. Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. Used for both fresh maps and savegame loads. A fresh map would also need to call ED_CallSpawnFunctions () to let the objects initialize themselves. ================ */ void ED_LoadFromFile (char *data) { extern cvar_t cl_curlybraces; edict_t *ent; int inhibit; dfunction_t *func; float curlybraces_oldvalue = cl_curlybraces.value; if (curlybraces_oldvalue) { Cvar_SetValue(&cl_curlybraces, 0); } ent = NULL; inhibit = 0; pr_global_struct->time = sv.time; // parse ents while (1) { // parse the opening brace data = COM_Parse (data); if (!data) break; if (com_token[0] != '{') SV_Error ("ED_LoadFromFile: found %s when expecting {",com_token); if (!ent) ent = EDICT_NUM(0); else ent = ED_Alloc (); data = ED_ParseEdict (data, ent); // remove things from different skill levels or deathmatch if ((int)deathmatch.value) { if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { ED_Free (ent); inhibit++; continue; } } else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY)) || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) ) { ED_Free (ent); inhibit++; continue; } // // immediately call spawn function // if (!ent->v.classname) { Con_Printf ("No classname for:\n"); ED_Print (ent); ED_Free (ent); continue; } // look for the spawn function func = ED_FindFunction ( PR_GetString(ent->v.classname) ); if (!func) { Con_Printf ("No spawn function for:\n"); ED_Print (ent); ED_Free (ent); continue; } pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (func - pr_functions); SV_FlushSignon(); } Con_DPrintf ("%i entities inhibited\n", inhibit); if (curlybraces_oldvalue) { Cvar_SetValue(&cl_curlybraces, curlybraces_oldvalue); } }
/* ============= 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_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; }