mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-14 08:21:05 +00:00
ce3c561cfe
Particle system functions renamed a bit, a few other cleanups in that area. Console handling tweeked. Better rules for subconsoles and plugins. Commands are coloured if it'll be execed, which should help reduce occurences of chat being commands. tab compleation tweeked, partial compleation no longer changes the suggestion. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@895 fc73d0e0-1445-4013-8a0c-d673dee63da5
1483 lines
37 KiB
C
1483 lines
37 KiB
C
#include "quakedef.h"
|
|
|
|
#ifdef CSQC_DAT
|
|
|
|
#ifdef RGLQUAKE
|
|
#include "glquake.h" //evil to include this
|
|
#endif
|
|
|
|
progfuncs_t *csqcprogs;
|
|
|
|
unsigned int csqcchecksum;
|
|
|
|
#define csqcglobals \
|
|
globalfunction(init_function, "CSQC_Init"); \
|
|
globalfunction(shutdown_function, "CSQC_Shutdown"); \
|
|
globalfunction(draw_function, "CSQC_UpdateView"); \
|
|
globalfunction(keydown_function, "CSQC_KeyDown"); \
|
|
globalfunction(keyup_function, "CSQC_KeyUp"); \
|
|
globalfunction(parse_stuffcmd, "CSQC_Parse_StuffCmd"); \
|
|
globalfunction(parse_centerprint, "CSQC_Parse_CenterPrint"); \
|
|
\
|
|
globalfunction(ent_update, "CSQC_Ent_Update"); \
|
|
globalfunction(ent_remove, "CSQC_Ent_Remove"); \
|
|
\
|
|
/*These are pointers to the csqc's globals.*/ \
|
|
globalfloat(time, "time"); /*float Written before entering most qc functions*/ \
|
|
globalentity(self, "self"); /*entity Written before entering most qc functions*/ \
|
|
\
|
|
globalvector(forward, "v_forward"); /*vector written by anglevectors*/ \
|
|
globalvector(right, "v_right"); /*vector written by anglevectors*/ \
|
|
globalvector(up, "v_up"); /*vector written by anglevectors*/ \
|
|
\
|
|
globalfloat(trace_allsolid, "trace_allsolid"); /*bool written by traceline*/ \
|
|
globalfloat(trace_startsolid, "trace_startsolid"); /*bool written by traceline*/ \
|
|
globalfloat(trace_fraction, "trace_fraction"); /*float written by traceline*/ \
|
|
globalfloat(trace_inwater, "trace_inwater"); /*bool written by traceline*/ \
|
|
globalfloat(trace_inopen, "trace_inopen"); /*bool written by traceline*/ \
|
|
globalvector(trace_endpos, "trace_endpos"); /*vector written by traceline*/ \
|
|
globalvector(trace_plane_normal, "trace_plane_normal"); /*vector written by traceline*/ \
|
|
globalfloat(trace_plane_dist, "trace_plane_dist"); /*float written by traceline*/ \
|
|
globalentity(trace_ent, "trace_ent"); /*entity written by traceline*/ \
|
|
|
|
typedef struct {
|
|
#define globalfloat(name,qcname) float *name
|
|
#define globalvector(name,qcname) float *name
|
|
#define globalentity(name,qcname) int *name
|
|
#define globalstring(name,qcname) string_t *name
|
|
#define globalfunction(name,qcname) func_t name
|
|
//These are the functions the engine will call to, found by name.
|
|
|
|
csqcglobals
|
|
|
|
#undef globalfloat
|
|
#undef globalvector
|
|
#undef globalentity
|
|
#undef globalstring
|
|
#undef globalfunction
|
|
} csqcglobals_t;
|
|
static csqcglobals_t csqcg;
|
|
|
|
|
|
|
|
void CSQC_FindGlobals(void)
|
|
{
|
|
#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0);
|
|
#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0);
|
|
#define globalentity(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0);
|
|
#define globalstring(name,qcname) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, qcname, 0);
|
|
#define globalfunction(name,qcname) csqcg.name = PR_FindFunction(csqcprogs,qcname,PR_ANY);
|
|
|
|
csqcglobals
|
|
|
|
#undef globalfloat
|
|
#undef globalvector
|
|
#undef globalentity
|
|
#undef globalstring
|
|
#undef globalfunction
|
|
if (csqcg.time)
|
|
*csqcg.time = Sys_DoubleTime();
|
|
}
|
|
|
|
|
|
|
|
//this is the list for all the csqc fields.
|
|
//(the #define is so the list always matches the ones pulled out)
|
|
#define csqcfields \
|
|
fieldfloat(modelindex); \
|
|
fieldvector(origin); \
|
|
fieldvector(angles); \
|
|
fieldfloat(alpha); /*transparency*/ \
|
|
fieldfloat(scale); /*model scale*/ \
|
|
fieldfloat(fatness); /*expand models X units along thier normals.*/ \
|
|
fieldfloat(skin); \
|
|
fieldfloat(colormap); \
|
|
fieldfloat(frame); \
|
|
fieldfloat(oldframe); \
|
|
fieldfloat(lerpfrac); \
|
|
\
|
|
fieldfloat(drawmask); /*So that the qc can specify all rockets at once or all bannanas at once*/ \
|
|
fieldfunction(predraw); /*If present, is called just before it's drawn.*/ \
|
|
\
|
|
fieldstring(model);
|
|
|
|
|
|
//note: doesn't even have to match the clprogs.dat :)
|
|
typedef struct {
|
|
#define fieldfloat(name) float name
|
|
#define fieldvector(name) vec3_t name
|
|
#define fieldentity(name) int name
|
|
#define fieldstring(name) string_t name
|
|
#define fieldfunction(name) func_t name
|
|
csqcfields
|
|
#undef fieldfloat
|
|
#undef fieldvector
|
|
#undef fieldentity
|
|
#undef fieldstring
|
|
#undef fieldfunction
|
|
} csqcentvars_t;
|
|
|
|
typedef struct csqcedict_s
|
|
{
|
|
qboolean isfree;
|
|
float freetime; // sv.time when the object was freed
|
|
int entnum;
|
|
qboolean readonly; //world
|
|
|
|
csqcentvars_t v;
|
|
} csqcedict_t;
|
|
|
|
csqcedict_t *csqc_edicts; //consider this 'world'
|
|
|
|
|
|
void CSQC_InitFields(void)
|
|
{ //CHANGING THIS FUNCTION REQUIRES CHANGES TO csqcentvars_t
|
|
#define fieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, (int)&((csqcedict_t*)0)->v.name - (int)&((csqcedict_t*)0)->v, -1)
|
|
#define fieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, (int)&((csqcedict_t*)0)->v.name - (int)&((csqcedict_t*)0)->v, -1)
|
|
#define fieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, (int)&((csqcedict_t*)0)->v.name - (int)&((csqcedict_t*)0)->v, -1)
|
|
#define fieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, (int)&((csqcedict_t*)0)->v.name - (int)&((csqcedict_t*)0)->v, -1)
|
|
#define fieldfunction(name) PR_RegisterFieldVar(csqcprogs, ev_function, #name, (int)&((csqcedict_t*)0)->v.name - (int)&((csqcedict_t*)0)->v, -1)
|
|
csqcfields
|
|
#undef fieldfloat
|
|
#undef fieldvector
|
|
#undef fieldentity
|
|
#undef fieldstring
|
|
#undef fieldfunction
|
|
}
|
|
|
|
csqcedict_t *csqcent[MAX_EDICTS];
|
|
|
|
#define RETURN_SSTRING(s) (*(char **)&((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it.
|
|
char *PF_TempStr(void);
|
|
|
|
int csqcentsize;
|
|
|
|
//pr_cmds.c builtins that need to be moved to a common.
|
|
void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...);
|
|
void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_randomvec (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_Sin (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_Cos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_Sqrt (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_bound (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strlen(progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_findchainfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_traceon (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_traceoff (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
|
|
void PF_strstrofs (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
|
|
//these functions are from pr_menu.dat
|
|
void PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_precache_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_free_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawpic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawfill (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawsetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawresetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
void PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
|
|
|
#define MAXTEMPBUFFERLEN 1024
|
|
|
|
void PF_fclose_progs (progfuncs_t *prinst);
|
|
char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
|
|
|
|
|
|
static void PF_Remove_ (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *ed;
|
|
|
|
ed = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
|
|
|
|
if (ed->isfree)
|
|
{
|
|
Con_DPrintf("CSQC Tried removing free entity\n");
|
|
return;
|
|
}
|
|
|
|
ED_Free (prinst, (void*)ed);
|
|
}
|
|
|
|
static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
cvar_t *var;
|
|
char *str;
|
|
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
{
|
|
var = Cvar_Get(str, "", 0, "csqc cvars");
|
|
if (var)
|
|
G_FLOAT(OFS_RETURN) = var->value;
|
|
else
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
}
|
|
}
|
|
|
|
//too specific to the prinst's builtins.
|
|
static void PF_Fixme (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
Con_Printf("\n");
|
|
|
|
prinst->RunError(prinst, "\nBuiltin %i not implemented.\nMenu is not compatable.", prinst->lastcalledbuiltinnumber);
|
|
PR_BIError (prinst, "bulitin not implemented");
|
|
}
|
|
|
|
static void PF_csqc_centerprint (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *str = PF_VarString(prinst, 0, pr_globals);
|
|
SCR_CenterPrint(0, str);
|
|
}
|
|
|
|
static void PF_makevectors (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
if (!csqcg.forward || !csqcg.right || !csqcg.up)
|
|
Host_EndGame("PF_makevectors: one of v_forward, v_right or v_up was not defined\n");
|
|
AngleVectors (G_VECTOR(OFS_PARM0), csqcg.forward, csqcg.right, csqcg.up);
|
|
}
|
|
|
|
static void PF_R_AddEntity(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
entity_t ent;
|
|
int i;
|
|
model_t *model;
|
|
|
|
if (in->v.predraw)
|
|
{
|
|
int oldself = *csqcg.self;
|
|
*csqcg.self = EDICT_TO_PROG(prinst, (void*)in);
|
|
PR_ExecuteProgram(prinst, in->v.predraw);
|
|
*csqcg.self = oldself;
|
|
}
|
|
|
|
i = in->v.modelindex;
|
|
if (i == 0)
|
|
return;
|
|
else if (i > 0 && i < MAX_MODELS)
|
|
model = cl.model_precache[i];
|
|
else if (i < 0 && i > -MAX_CSQCMODELS)
|
|
model = cl.model_csqcprecache[-i];
|
|
else
|
|
return; //there might be other ent types later as an extension that stop this.
|
|
|
|
memset(&ent, 0, sizeof(ent));
|
|
ent.model = model;
|
|
|
|
if (!ent.model)
|
|
{
|
|
Con_Printf("PF_R_AddEntity: model wasn't precached!\n");
|
|
return;
|
|
}
|
|
|
|
|
|
ent.frame = in->v.frame;
|
|
ent.oldframe = in->v.oldframe;
|
|
ent.lerpfrac = in->v.lerpfrac;
|
|
|
|
ent.angles[0] = in->v.angles[0];
|
|
ent.angles[1] = in->v.angles[1];
|
|
ent.angles[2] = in->v.angles[2];
|
|
memcpy(ent.origin, in->v.origin, sizeof(vec3_t));
|
|
AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]);
|
|
VectorInverse(ent.axis[1]);
|
|
|
|
ent.alpha = in->v.alpha;
|
|
ent.scale = in->v.scale;
|
|
|
|
V_AddEntity(&ent);
|
|
}
|
|
|
|
static void PF_R_AddDynamicLight(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *org = G_VECTOR(OFS_PARM0);
|
|
float radius = G_FLOAT(OFS_PARM1);
|
|
float *rgb = G_VECTOR(OFS_PARM2);
|
|
V_AddLight(org, radius, rgb[0]/5, rgb[1]/5, rgb[2]/5);
|
|
}
|
|
|
|
#define MASK_ENGINE 1
|
|
static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int mask = G_FLOAT(OFS_PARM0);
|
|
csqcedict_t *ent;
|
|
int e;
|
|
|
|
for (e=1; e < *prinst->parms->sv_num_edicts; e++)
|
|
{
|
|
ent = (void*)EDICT_NUM(prinst, e);
|
|
if (ent->isfree)
|
|
continue;
|
|
|
|
if ((int)ent->v.drawmask & mask)
|
|
{
|
|
G_INT(OFS_PARM0) = EDICT_TO_PROG(prinst, (void*)ent);
|
|
PF_R_AddEntity(prinst, pr_globals);
|
|
}
|
|
}
|
|
|
|
if (mask & MASK_ENGINE && cl.worldmodel)
|
|
{
|
|
CL_LinkViewModel ();
|
|
CL_LinkPlayers ();
|
|
CL_LinkPacketEntities ();
|
|
CL_LinkProjectiles ();
|
|
CL_UpdateTEnts ();
|
|
}
|
|
}
|
|
|
|
//float CalcFov (float fov_x, float width, float height);
|
|
//clear scene, and set up the default stuff.
|
|
static void PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
extern frame_t *view_frame;
|
|
extern player_state_t *view_message;
|
|
|
|
CL_DecayLights ();
|
|
|
|
if (cl.worldmodel)
|
|
{
|
|
//work out which packet entities are solid
|
|
CL_SetSolidEntities ();
|
|
|
|
// Set up prediction for other players
|
|
CL_SetUpPlayerPrediction(false);
|
|
|
|
// do client side motion prediction
|
|
CL_PredictMove ();
|
|
|
|
// Set up prediction for other players
|
|
CL_SetUpPlayerPrediction(true);
|
|
}
|
|
|
|
CL_SwapEntityLists();
|
|
|
|
view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
|
view_message = &view_frame->playerstate[cl.playernum[0]];
|
|
V_CalcRefdef(0); //set up the defaults (for player 0)
|
|
/*
|
|
VectorCopy(cl.simangles[0], r_refdef.viewangles);
|
|
VectorCopy(cl.simorg[0], r_refdef.vieworg);
|
|
r_refdef.flags = 0;
|
|
|
|
r_refdef.vrect.x = 0;
|
|
r_refdef.vrect.y = 0;
|
|
r_refdef.vrect.width = vid.width;
|
|
r_refdef.vrect.height = vid.height;
|
|
|
|
r_refdef.fov_x = scr_fov.value;
|
|
r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
|
|
*/
|
|
}
|
|
|
|
static void PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *s = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
float *p = G_VECTOR(OFS_PARM1);
|
|
switch(*s)
|
|
{
|
|
case 'F':
|
|
if (!strcmp(s, "FOV")) //set both fov numbers
|
|
{
|
|
r_refdef.fov_x = p[0];
|
|
r_refdef.fov_y = p[1];
|
|
return;
|
|
}
|
|
if (!strcmp(s, "FOV_X"))
|
|
{
|
|
r_refdef.fov_x = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "FOV_Y"))
|
|
{
|
|
r_refdef.fov_y = *p;
|
|
return;
|
|
}
|
|
break;
|
|
case 'O':
|
|
if (!strcmp(s, "ORIGIN"))
|
|
{
|
|
VectorCopy(p, r_refdef.vieworg);
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ORIGIN_X"))
|
|
{
|
|
r_refdef.vieworg[0] = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ORIGIN_Y"))
|
|
{
|
|
r_refdef.vieworg[1] = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ORIGIN_Z"))
|
|
{
|
|
r_refdef.vieworg[2] = *p;
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'A':
|
|
if (!strcmp(s, "ANGLES"))
|
|
{
|
|
VectorCopy(p, r_refdef.viewangles);
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ANGLES_X"))
|
|
{
|
|
r_refdef.viewangles[0] = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ANGLES_Y"))
|
|
{
|
|
r_refdef.viewangles[1] = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "ANGLES_Z"))
|
|
{
|
|
r_refdef.viewangles[2] = *p;
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 'W':
|
|
if (!strcmp(s, "WIDTH"))
|
|
{
|
|
r_refdef.vrect.width = *p;
|
|
return;
|
|
}
|
|
break;
|
|
case 'H':
|
|
if (!strcmp(s, "HEIGHT"))
|
|
{
|
|
r_refdef.vrect.height = *p;
|
|
return;
|
|
}
|
|
break;
|
|
case 'S':
|
|
if (!strcmp(s, "SIZE"))
|
|
{
|
|
r_refdef.vrect.width = p[0];
|
|
r_refdef.vrect.height = p[1];
|
|
return;
|
|
}
|
|
break;
|
|
case 'M':
|
|
if (!strcmp(s, "MIN_X"))
|
|
{
|
|
r_refdef.vrect.x = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "MIN_Y"))
|
|
{
|
|
r_refdef.vrect.y = *p;
|
|
return;
|
|
}
|
|
if (!strcmp(s, "MIN"))
|
|
{
|
|
r_refdef.vrect.x = p[0];
|
|
r_refdef.vrect.y = p[1];
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
Con_DPrintf("SetViewFlag: %s not recognised\n", s);
|
|
}
|
|
|
|
static void PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
if (cl.worldmodel)
|
|
R_PushDlights ();
|
|
|
|
#ifdef RGLQUAKE
|
|
if (qrenderer == QR_OPENGL)
|
|
{
|
|
gl_ztrickdisabled|=16;
|
|
qglDisable(GL_ALPHA_TEST);
|
|
qglDisable(GL_BLEND);
|
|
}
|
|
#endif
|
|
R_RenderView();
|
|
#ifdef RGLQUAKE
|
|
if (qrenderer == QR_OPENGL)
|
|
{
|
|
gl_ztrickdisabled&=~16;
|
|
GL_Set2D ();
|
|
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
GL_TexEnv(GL_MODULATE);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RGLQUAKE
|
|
if (qrenderer == QR_OPENGL)
|
|
{
|
|
qglDisable(GL_ALPHA_TEST);
|
|
qglEnable(GL_BLEND);
|
|
}
|
|
#endif
|
|
|
|
vid.recalc_refdef = 1;
|
|
}
|
|
|
|
static void PF_cs_getstatf(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int stnum = G_FLOAT(OFS_PARM0);
|
|
float val = *(float*)&cl.stats[0][stnum]; //copy float into the stat
|
|
G_FLOAT(OFS_RETURN) = val;
|
|
}
|
|
static void PF_cs_getstati(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{ //convert an int stat into a qc float.
|
|
|
|
int stnum = G_FLOAT(OFS_PARM0);
|
|
int val = cl.stats[0][stnum];
|
|
if (*prinst->callargc > 1)
|
|
{
|
|
int first, count;
|
|
first = G_FLOAT(OFS_PARM1);
|
|
count = G_FLOAT(OFS_PARM2);
|
|
G_FLOAT(OFS_RETURN) = (((unsigned int)val)&(((1<<count)-1)<<first))>>first;
|
|
}
|
|
else
|
|
G_FLOAT(OFS_RETURN) = val;
|
|
}
|
|
static void PF_cs_getstats(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int stnum = G_FLOAT(OFS_PARM0);
|
|
char *out;
|
|
|
|
out = PF_TempStr();
|
|
|
|
//the network protocol byteswaps
|
|
|
|
((unsigned int*)out)[0] = LittleLong(cl.stats[0][stnum+0]);
|
|
((unsigned int*)out)[1] = LittleLong(cl.stats[0][stnum+1]);
|
|
((unsigned int*)out)[2] = LittleLong(cl.stats[0][stnum+2]);
|
|
((unsigned int*)out)[3] = LittleLong(cl.stats[0][stnum+3]);
|
|
((unsigned int*)out)[4] = 0; //make sure it's null terminated
|
|
|
|
RETURN_SSTRING(out);
|
|
}
|
|
|
|
static void PF_CSQC_SetOrigin(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
float *org = G_VECTOR(OFS_PARM1);
|
|
VectorCopy(org, ent->v.origin);
|
|
|
|
//fixme: add some sort of fast area grid
|
|
}
|
|
|
|
static void PF_CSQC_SetSize(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
float *mins = G_VECTOR(OFS_PARM1);
|
|
float *maxs = G_VECTOR(OFS_PARM1);
|
|
|
|
//fixme: set the size. :p
|
|
|
|
//fixme: add some sort of fast area grid
|
|
}
|
|
|
|
//FIXME: Not fully functional
|
|
static void PF_CSQC_traceline(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *v1, *v2, *mins, *maxs;
|
|
trace_t trace;
|
|
int nomonsters;
|
|
edict_t *ent;
|
|
// int savedhull;
|
|
|
|
v1 = G_VECTOR(OFS_PARM0);
|
|
v2 = G_VECTOR(OFS_PARM1);
|
|
nomonsters = G_FLOAT(OFS_PARM2);
|
|
ent = G_EDICT(prinst, OFS_PARM3);
|
|
|
|
// if (*prinst->callargc == 6)
|
|
// {
|
|
// mins = G_VECTOR(OFS_PARM4);
|
|
// maxs = G_VECTOR(OFS_PARM5);
|
|
// }
|
|
// else
|
|
{
|
|
mins = vec3_origin;
|
|
maxs = vec3_origin;
|
|
}
|
|
/*
|
|
savedhull = ent->v.hull;
|
|
ent->v.hull = 0;
|
|
trace = SV_Move (v1, mins, maxs, v2, nomonsters, ent);
|
|
ent->v.hull = savedhull;
|
|
*/
|
|
|
|
memset(&trace, 0, sizeof(trace));
|
|
trace.fraction = 1;
|
|
cl.worldmodel->hulls->funcs.RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, v1, v2, &trace);
|
|
|
|
*csqcg.trace_allsolid = trace.allsolid;
|
|
*csqcg.trace_startsolid = trace.startsolid;
|
|
*csqcg.trace_fraction = trace.fraction;
|
|
*csqcg.trace_inwater = trace.inwater;
|
|
*csqcg.trace_inopen = trace.inopen;
|
|
VectorCopy (trace.endpos, csqcg.trace_endpos);
|
|
VectorCopy (trace.plane.normal, csqcg.trace_plane_normal);
|
|
*csqcg.trace_plane_dist = trace.plane.dist;
|
|
// if (trace.ent)
|
|
// *csqcg.trace_ent = EDICT_TO_PROG(prinst, trace.ent);
|
|
// else
|
|
*csqcg.trace_ent = EDICT_TO_PROG(prinst, (void*)csqc_edicts);
|
|
}
|
|
|
|
static void PF_CSQC_pointcontents(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *v;
|
|
int cont;
|
|
|
|
v = G_VECTOR(OFS_PARM0);
|
|
|
|
cont = cl.worldmodel->hulls[0].funcs.HullPointContents(&cl.worldmodel->hulls[0], v);
|
|
if (cont & FTECONTENTS_SOLID)
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_SOLID;
|
|
else if (cont & FTECONTENTS_SKY)
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_SKY;
|
|
else if (cont & FTECONTENTS_LAVA)
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_LAVA;
|
|
else if (cont & FTECONTENTS_SLIME)
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_SLIME;
|
|
else if (cont & FTECONTENTS_WATER)
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_WATER;
|
|
else
|
|
G_FLOAT(OFS_RETURN) = Q1CONTENTS_EMPTY;
|
|
}
|
|
|
|
static int FindModel(char *name, int *free)
|
|
{
|
|
int i;
|
|
|
|
*free = 0;
|
|
|
|
for (i = 1; i < MAX_CSQCMODELS; i++)
|
|
{
|
|
if (!*cl.model_csqcname[i])
|
|
{
|
|
*free = -i;
|
|
break;
|
|
}
|
|
if (!strcmp(cl.model_csqcname[i], name))
|
|
return -i;
|
|
}
|
|
for (i = 1; i < MAX_MODELS; i++)
|
|
{
|
|
if (!strcmp(cl.model_name[i], name))
|
|
return i;
|
|
}
|
|
return 0;
|
|
}
|
|
static void PF_CSQC_SetModel(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
char *modelname = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
int freei;
|
|
int modelindex = FindModel(modelname, &freei);
|
|
|
|
if (!modelindex)
|
|
{
|
|
if (!freei)
|
|
Host_EndGame("CSQC ran out of model slots\n");
|
|
Con_DPrintf("Late caching model \"%s\"\n", modelname);
|
|
Q_strncpyz(cl.model_csqcname[-freei], modelname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now
|
|
modelindex = freei;
|
|
|
|
cl.model_csqcprecache[-freei] = Mod_ForName(cl.model_csqcname[-freei], false);
|
|
}
|
|
|
|
ent->v.modelindex = modelindex;
|
|
if (modelindex < 0)
|
|
ent->v.model = PR_SetString(prinst, cl.model_csqcname[-modelindex]);
|
|
else
|
|
ent->v.model = PR_SetString(prinst, cl.model_name[modelindex]);
|
|
}
|
|
static void PF_CSQC_SetModelIndex(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
int modelindex = G_FLOAT(OFS_PARM1);
|
|
|
|
ent->v.modelindex = modelindex;
|
|
if (modelindex < 0)
|
|
ent->v.model = PR_SetString(prinst, cl.model_csqcname[-modelindex]);
|
|
else
|
|
ent->v.model = PR_SetString(prinst, cl.model_name[modelindex]);
|
|
}
|
|
static void PF_CSQC_PrecacheModel(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int modelindex, freei;
|
|
char *modelname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
int i;
|
|
|
|
for (i = 1; i < MAX_MODELS; i++) //Make sure that the server specified model is loaded..
|
|
{
|
|
if (!*cl.model_name[i])
|
|
break;
|
|
if (!strcmp(cl.model_name[i], modelname))
|
|
{
|
|
cl.model_precache[i] = Mod_ForName(cl.model_name[i], false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
modelindex = FindModel(modelname, &freei); //now load it
|
|
|
|
if (!modelindex)
|
|
{
|
|
if (!freei)
|
|
Host_EndGame("CSQC ran out of model slots\n");
|
|
Q_strncpyz(cl.model_csqcname[-freei], modelname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now
|
|
modelindex = freei;
|
|
|
|
cl.model_csqcprecache[-freei] = Mod_ForName(cl.model_csqcname[-freei], false);
|
|
}
|
|
}
|
|
static void PF_CSQC_PrecacheSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *soundname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
S_PrecacheSound(soundname);
|
|
}
|
|
|
|
static void PF_CSQC_ModelnameForIndex(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int modelindex = G_FLOAT(OFS_PARM0);
|
|
|
|
if (modelindex < 0)
|
|
G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cl.model_csqcname[-modelindex]);
|
|
else
|
|
G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cl.model_name[modelindex]);
|
|
}
|
|
|
|
static void PF_ReadByte(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadByte();
|
|
}
|
|
|
|
static void PF_ReadChar(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadChar();
|
|
}
|
|
|
|
static void PF_ReadShort(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadShort();
|
|
}
|
|
|
|
static void PF_ReadLong(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadLong();
|
|
}
|
|
|
|
static void PF_ReadCoord(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadCoord();
|
|
}
|
|
|
|
static void PF_ReadString(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *str = PF_TempStr();
|
|
char *read = MSG_ReadString();
|
|
|
|
Q_strncpyz(str, read, MAXTEMPBUFFERLEN);
|
|
}
|
|
|
|
static void PF_ReadAngle(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = MSG_ReadAngle();
|
|
}
|
|
|
|
|
|
static void PF_objerror (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *s;
|
|
edict_t *ed;
|
|
|
|
s = PF_VarString(prinst, 0, pr_globals);
|
|
/* Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
|
|
*/ ed = PROG_TO_EDICT(prinst, pr_global_struct->self);
|
|
/* ED_Print (ed);
|
|
*/
|
|
ED_Print(prinst, ed);
|
|
Con_Printf("%s", s);
|
|
|
|
if (developer.value)
|
|
(*prinst->pr_trace) = 2;
|
|
else
|
|
{
|
|
ED_Free (prinst, ed);
|
|
|
|
prinst->AbortStack(prinst);
|
|
|
|
PR_BIError (prinst, "Program error: %s", s);
|
|
|
|
if (sv.time > 10)
|
|
Cbuf_AddText("restart\n", RESTRICT_LOCAL);
|
|
}
|
|
}
|
|
|
|
static void PF_cs_setsensativityscaler (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
in_sensitivityscale = G_FLOAT(OFS_PARM0);
|
|
}
|
|
|
|
static void PF_cs_pointparticles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *effectname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
float *org = G_VECTOR(OFS_PARM1);
|
|
float *vel = G_VECTOR(OFS_PARM2);
|
|
float count = G_FLOAT(OFS_PARM3);
|
|
int effectnum = P_AllocateParticleType(effectname);
|
|
|
|
if (*prinst->callargc < 3)
|
|
vel = vec3_origin;
|
|
if (*prinst->callargc < 4)
|
|
count = 1;
|
|
|
|
P_RunParticleEffectType(org, vel, count, effectnum);
|
|
}
|
|
|
|
static void PF_cs_particlesloaded (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *effectname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
G_FLOAT(OFS_RETURN) = P_DescriptionIsLoaded(effectname);
|
|
}
|
|
|
|
#define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme
|
|
|
|
//warning: functions that depend on globals are bad, mkay?
|
|
builtin_t csqc_builtins[] = {
|
|
//0
|
|
PF_Fixme,
|
|
PF_makevectors,
|
|
PF_CSQC_SetOrigin, //PF_setorigin
|
|
PF_CSQC_SetModel, //PF_setmodel
|
|
PF_CSQC_SetSize, //PF_setsize
|
|
PF_Fixme,
|
|
PF_Fixme, //PF_break,
|
|
PF_random,
|
|
PF_Fixme, //PF_sound,
|
|
PF_normalize,
|
|
//10
|
|
PF_error,
|
|
PF_objerror,
|
|
PF_vlen,
|
|
PF_vectoyaw,
|
|
PF_Spawn,
|
|
PF_Remove_, //PF_Remove,
|
|
PF_CSQC_traceline, //PF_traceline,
|
|
PF_Fixme, //PF_checkclient, (don't support)
|
|
PF_FindString,
|
|
PF_CSQC_PrecacheSound, //PF_precache_sound,
|
|
//20
|
|
PF_CSQC_PrecacheModel, //PF_precache_model,
|
|
PF_Fixme, //PF_stuffcmd, (don't support)
|
|
PF_Fixme, //PF_findradius,
|
|
PF_Fixme, //PF_bprint, (don't support)
|
|
PF_Fixme, //PF_sprint,
|
|
PF_dprint,
|
|
PF_ftos,
|
|
PF_vtos,
|
|
PF_coredump,
|
|
PF_traceon,
|
|
//30
|
|
PF_traceoff,
|
|
PF_eprint,
|
|
PF_Fixme, //PF_walkmove, (don't support yet)
|
|
PF_Fixme,
|
|
PF_Fixme, //PF_droptofloor,
|
|
PF_Fixme, //PF_lightstyle,
|
|
PF_rint,
|
|
PF_floor,
|
|
PF_ceil,
|
|
PF_Fixme,
|
|
//40
|
|
PF_Fixme, //PF_checkbottom,
|
|
PF_CSQC_pointcontents, //PF_pointcontents,
|
|
PF_Fixme,
|
|
PF_fabs,
|
|
PF_Fixme, //PF_aim, hehehe... (don't support)
|
|
PF_cvar,
|
|
PF_localcmd,
|
|
PF_nextent,
|
|
PF_Fixme, //PF_particle,
|
|
PF_Fixme, //PF_changeyaw,
|
|
//50
|
|
PF_Fixme,
|
|
PF_vectoangles,
|
|
|
|
PF_ReadByte,
|
|
PF_ReadChar,
|
|
PF_ReadShort,
|
|
PF_ReadLong,
|
|
PF_ReadCoord,
|
|
PF_ReadAngle,
|
|
PF_ReadString,
|
|
PF_Fixme,//PF_ReadEntity,
|
|
|
|
//60
|
|
PF_Fixme,
|
|
|
|
PF_Sin,
|
|
PF_Cos,
|
|
PF_Sqrt,
|
|
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
SV_MoveToGoal,
|
|
PF_Fixme, //PF_precache_file, (don't support)
|
|
PF_Fixme, //PF_makestatic,
|
|
//70
|
|
PF_Fixme, //PF_changelevel, (don't support)
|
|
PF_Fixme,
|
|
PF_cvar_set,
|
|
PF_Fixme, //PF_centerprint,
|
|
PF_Fixme, //PF_ambientsound,
|
|
|
|
PF_CSQC_PrecacheModel, //PF_precache_model,
|
|
PF_Fixme, //PF_precache_sound,
|
|
PF_Fixme, //PF_precache_file,
|
|
PF_Fixme, //PF_setspawnparms,
|
|
PF_Fixme, //PF_logfrag, (don't support)
|
|
//80
|
|
PF_Fixme, //PF_infokey,
|
|
PF_stof,
|
|
PF_Fixme, //PF_multicast, (don't support)
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
//90
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
//100
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
//110
|
|
PF_fopen,
|
|
PF_fclose,
|
|
PF_fgets,
|
|
PF_fputs,
|
|
PF_strlen,
|
|
|
|
PF_strcat,
|
|
PF_substring,
|
|
PF_stov,
|
|
PF_dupstring,
|
|
PF_forgetstring,
|
|
|
|
|
|
//120
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
//130
|
|
PF_R_ClearScene,
|
|
PF_R_AddEntityMask,
|
|
PF_R_AddEntity,
|
|
PF_R_SetViewFlag,
|
|
PF_R_RenderScene,
|
|
|
|
PF_R_AddDynamicLight,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
//140
|
|
PF_CL_is_cached_pic,//0
|
|
PF_CL_precache_pic,//1
|
|
PF_CL_free_pic,//2
|
|
PF_CL_drawcharacter,//3
|
|
PF_CL_drawstring,//4
|
|
PF_CL_drawpic,//5
|
|
PF_CL_drawfill,//6
|
|
PF_CL_drawsetcliparea,//7
|
|
PF_CL_drawresetcliparea,//8
|
|
PF_CL_drawgetimagesize,//9
|
|
|
|
//150
|
|
PF_cs_getstatf,
|
|
PF_cs_getstati,
|
|
PF_cs_getstats,
|
|
PF_CSQC_SetModelIndex,
|
|
PF_CSQC_ModelnameForIndex,
|
|
|
|
PF_cs_setsensativityscaler,
|
|
PF_csqc_centerprint,
|
|
PF_print,
|
|
PF_cs_pointparticles,
|
|
PF_cs_particlesloaded,
|
|
|
|
//160
|
|
PF_FixTen,
|
|
|
|
//170
|
|
PF_FixTen,
|
|
|
|
//180
|
|
PF_FixTen,
|
|
|
|
//190
|
|
PF_FixTen,
|
|
|
|
//200
|
|
PF_FixTen,
|
|
|
|
//210
|
|
PF_FixTen,
|
|
|
|
//220
|
|
PF_Fixme,
|
|
PF_strstrofs,
|
|
PF_str2chr,
|
|
PF_chr2str,
|
|
PF_strconv,
|
|
|
|
PF_infoadd,
|
|
PF_infoget,
|
|
PF_strncmp,
|
|
PF_strcasecmp,
|
|
PF_strncasecmp,
|
|
|
|
//230
|
|
PF_FixTen,
|
|
|
|
//240
|
|
PF_FixTen,
|
|
|
|
//250
|
|
PF_FixTen,
|
|
|
|
//260
|
|
PF_FixTen,
|
|
|
|
//270
|
|
PF_FixTen,
|
|
|
|
//280
|
|
PF_FixTen,
|
|
|
|
//290
|
|
PF_FixTen,
|
|
|
|
//300
|
|
PF_FixTen,
|
|
|
|
//310
|
|
PF_FixTen,
|
|
|
|
//320
|
|
PF_FixTen,
|
|
|
|
//330
|
|
PF_FixTen,
|
|
|
|
//340
|
|
PF_FixTen,
|
|
|
|
//350
|
|
PF_FixTen,
|
|
|
|
//360
|
|
PF_FixTen,
|
|
|
|
//370
|
|
PF_FixTen,
|
|
|
|
//380
|
|
PF_FixTen,
|
|
|
|
//390
|
|
PF_FixTen,
|
|
|
|
//400
|
|
PF_FixTen,
|
|
|
|
//410
|
|
PF_FixTen,
|
|
|
|
//420
|
|
PF_FixTen,
|
|
|
|
//430
|
|
PF_FixTen,
|
|
|
|
//440
|
|
PF_Fixme,
|
|
PF_Tokenize,
|
|
PF_ArgV,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
PF_Fixme,
|
|
};
|
|
int csqc_numbuiltins = sizeof(csqc_builtins)/sizeof(csqc_builtins[0]);
|
|
|
|
|
|
|
|
|
|
|
|
jmp_buf csqc_abort;
|
|
progparms_t csqcprogparms;
|
|
int num_csqc_edicts;
|
|
|
|
|
|
|
|
int COM_FileSize(char *path);
|
|
pbool QC_WriteFile(char *name, void *data, int len);
|
|
void *VARGS PR_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves.
|
|
void VARGS PR_Free(void *mem);
|
|
|
|
//Any menu builtin error or anything like that will come here.
|
|
void VARGS CSQC_Abort (char *format, ...) //an error occured.
|
|
{
|
|
va_list argptr;
|
|
char string[1024];
|
|
|
|
va_start (argptr, format);
|
|
_vsnprintf (string,sizeof(string)-1, format,argptr);
|
|
va_end (argptr);
|
|
|
|
Con_Printf("CSQC_Abort: %s\nShutting down csqc\n", string);
|
|
|
|
|
|
{
|
|
static char buffer[1024*1024*8];
|
|
int size = sizeof buffer;
|
|
csqcprogs->save_ents(csqcprogs, buffer, &size, 3);
|
|
COM_WriteFile("csqccore.txt", buffer, size);
|
|
}
|
|
|
|
Host_EndGame("csqc error");
|
|
}
|
|
|
|
void CSQC_Shutdown(void)
|
|
{
|
|
if (csqcprogs)
|
|
{
|
|
CloseProgs(csqcprogs);
|
|
Con_Printf("Closed csqc\n");
|
|
}
|
|
csqcprogs = NULL;
|
|
|
|
in_sensitivityscale = 1;
|
|
}
|
|
|
|
//when the qclib needs a file, it calls out to this function.
|
|
qbyte *CSQC_PRLoadFile (char *path, void *buffer, int bufsize)
|
|
{
|
|
qbyte *file;
|
|
//pretend it doesn't
|
|
file = COM_LoadStackFile(path, buffer, bufsize);
|
|
|
|
if (!strcmp(path, "csprogs.dat")) //Fail to load any csprogs who's checksum doesn't match.
|
|
if (Com_BlockChecksum(buffer, com_filesize) != csqcchecksum)
|
|
return NULL;
|
|
|
|
return file;
|
|
}
|
|
|
|
double csqctime;
|
|
qboolean CSQC_Init (unsigned int checksum)
|
|
{
|
|
csqcchecksum = checksum;
|
|
|
|
CSQC_Shutdown();
|
|
|
|
if (!qrenderer)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
memset(cl.model_csqcname, 0, sizeof(cl.model_csqcname));
|
|
memset(cl.model_csqcprecache, 0, sizeof(cl.model_csqcprecache));
|
|
|
|
csqcprogparms.progsversion = PROGSTRUCT_VERSION;
|
|
csqcprogparms.ReadFile = CSQC_PRLoadFile;//char *(*ReadFile) (char *fname, void *buffer, int *len);
|
|
csqcprogparms.FileSize = COM_FileSize;//int (*FileSize) (char *fname); //-1 if file does not exist
|
|
csqcprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len);
|
|
csqcprogparms.printf = (void *)Con_Printf;//Con_Printf;//void (*printf) (char *, ...);
|
|
csqcprogparms.Sys_Error = Sys_Error;
|
|
csqcprogparms.Abort = CSQC_Abort;
|
|
csqcprogparms.edictsize = sizeof(csqcedict_t)-sizeof(csqcentvars_t);
|
|
|
|
csqcprogparms.entspawn = NULL;//void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
|
|
csqcprogparms.entcanfree = NULL;//bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
|
|
csqcprogparms.stateop = NULL;//StateOp;//void (*stateop) (float var, func_t func);
|
|
csqcprogparms.cstateop = NULL;//CStateOp;
|
|
csqcprogparms.cwstateop = NULL;//CWStateOp;
|
|
csqcprogparms.thinktimeop = NULL;//ThinkTimeOp;
|
|
|
|
//used when loading a game
|
|
csqcprogparms.builtinsfor = NULL;//builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
|
|
csqcprogparms.loadcompleate = NULL;//void (*loadcompleate) (int edictsize); //notification to reset any pointers.
|
|
|
|
csqcprogparms.memalloc = PR_Malloc;//void *(*memalloc) (int size); //small string allocation malloced and freed randomly
|
|
csqcprogparms.memfree = PR_Free;//void (*memfree) (void * mem);
|
|
|
|
|
|
csqcprogparms.globalbuiltins = csqc_builtins;//builtin_t *globalbuiltins; //these are available to all progs
|
|
csqcprogparms.numglobalbuiltins = csqc_numbuiltins;
|
|
|
|
csqcprogparms.autocompile = PR_NOCOMPILE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile;
|
|
|
|
csqcprogparms.gametime = &csqctime;
|
|
|
|
csqcprogparms.sv_edicts = (edict_t **)&csqc_edicts;
|
|
csqcprogparms.sv_num_edicts = &num_csqc_edicts;
|
|
|
|
csqcprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
|
|
|
|
csqctime = Sys_DoubleTime();
|
|
if (!csqcprogs)
|
|
{
|
|
in_sensitivityscale = 1;
|
|
csqcprogs = InitProgs(&csqcprogparms);
|
|
PR_Configure(csqcprogs, NULL, -1, 1);
|
|
|
|
CSQC_InitFields(); //let the qclib know the field order that the engine needs.
|
|
|
|
if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) < 0) //no per-progs builtins.
|
|
{
|
|
CSQC_Shutdown();
|
|
//failed to load or something
|
|
return false;
|
|
}
|
|
if (setjmp(csqc_abort))
|
|
{
|
|
CSQC_Shutdown();
|
|
return false;
|
|
}
|
|
|
|
memset(csqcent, 0, sizeof(csqcent));
|
|
|
|
csqcentsize = PR_InitEnts(csqcprogs, 3072);
|
|
|
|
CSQC_FindGlobals();
|
|
|
|
ED_Alloc(csqcprogs); //we need a word entity.
|
|
//world edict becomes readonly
|
|
EDICT_NUM(csqcprogs, 0)->readonly = true;
|
|
EDICT_NUM(csqcprogs, 0)->isfree = false;
|
|
|
|
if (csqcg.init_function)
|
|
PR_ExecuteProgram(csqcprogs, csqcg.init_function);
|
|
|
|
Con_Printf("Loaded csqc\n");
|
|
}
|
|
|
|
return true; //success!
|
|
}
|
|
|
|
qboolean CSQC_DrawView(void)
|
|
{
|
|
if (!csqcg.draw_function || !csqcprogs || !cl.worldmodel)
|
|
return false;
|
|
|
|
r_secondaryview = 0;
|
|
|
|
if (cl.worldmodel)
|
|
R_LessenStains();
|
|
|
|
if (csqcg.time)
|
|
*csqcg.time = Sys_DoubleTime();
|
|
|
|
PR_ExecuteProgram(csqcprogs, csqcg.draw_function);
|
|
|
|
return true;
|
|
}
|
|
|
|
qboolean CSQC_StuffCmd(char *cmd)
|
|
{
|
|
void *pr_globals;
|
|
char *str;
|
|
if (!csqcprogs || !csqcg.parse_stuffcmd)
|
|
return false;
|
|
|
|
str = PF_TempStr();
|
|
Q_strncpyz(str, cmd, MAXTEMPBUFFERLEN);
|
|
|
|
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
|
|
(*(char **)&((int *)pr_globals)[OFS_PARM0] = PR_SetString(csqcprogs, str));
|
|
|
|
PR_ExecuteProgram (csqcprogs, csqcg.parse_stuffcmd);
|
|
return true;
|
|
}
|
|
qboolean CSQC_CenterPrint(char *cmd)
|
|
{
|
|
void *pr_globals;
|
|
char *str;
|
|
if (!csqcprogs || !csqcg.parse_centerprint)
|
|
return false;
|
|
|
|
str = PF_TempStr();
|
|
Q_strncpyz(str, cmd, MAXTEMPBUFFERLEN);
|
|
|
|
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
|
|
(*(char **)&((int *)pr_globals)[OFS_PARM0] = PR_SetString(csqcprogs, str));
|
|
|
|
PR_ExecuteProgram (csqcprogs, csqcg.parse_centerprint);
|
|
return G_FLOAT(OFS_RETURN);
|
|
}
|
|
|
|
//this protocol allows up to 32767 edicts.
|
|
#ifdef PEXT_CSQC
|
|
void CSQC_ParseEntities(void)
|
|
{
|
|
csqcedict_t *ent;
|
|
unsigned short entnum;
|
|
void *pr_globals;
|
|
|
|
if (!csqcprogs)
|
|
Host_EndGame("CSQC needs to be initialized for this server.\n");
|
|
|
|
if (!csqcg.ent_update)
|
|
Host_EndGame("CSQC is unable to parse entities\n");
|
|
|
|
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
|
|
|
|
if (csqcg.time)
|
|
*csqcg.time = Sys_DoubleTime();
|
|
|
|
for(;;)
|
|
{
|
|
entnum = MSG_ReadShort();
|
|
if (!entnum)
|
|
break;
|
|
if (entnum & 0x8000)
|
|
{ //remove
|
|
entnum &= ~0x8000;
|
|
|
|
if (!entnum)
|
|
Host_EndGame("CSQC cannot remove world!\n");
|
|
|
|
if (entnum >= MAX_EDICTS)
|
|
Host_EndGame("CSQC recieved too many edicts!\n");
|
|
|
|
ent = csqcent[entnum];
|
|
|
|
if (!ent) //hrm.
|
|
continue;
|
|
|
|
*csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent);
|
|
PR_ExecuteProgram(csqcprogs, csqcg.ent_remove);
|
|
csqcent[entnum] = NULL;
|
|
//the csqc is expected to call the remove builtin.
|
|
}
|
|
else
|
|
{
|
|
if (entnum >= MAX_EDICTS)
|
|
Host_EndGame("CSQC recieved too many edicts!\n");
|
|
|
|
ent = csqcent[entnum];
|
|
if (!ent)
|
|
{
|
|
ent = (csqcedict_t*)ED_Alloc(csqcprogs);
|
|
csqcent[entnum] = ent;
|
|
G_FLOAT(OFS_PARM0) = true;
|
|
}
|
|
else
|
|
G_FLOAT(OFS_PARM0) = false;
|
|
|
|
*csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent);
|
|
PR_ExecuteProgram(csqcprogs, csqcg.ent_update);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|