3
#include "clprogdefs.h"
5
#include "cl_collision.h"
9
//============================================================================
10
// Client prog handling
11
//[515]: omg !!! optimize it ! a lot of hacks here and there also :P
13
#define CSQC_RETURNVAL prog->globals.generic[OFS_RETURN]
14
#define CSQC_BEGIN csqc_tmpprog=prog;prog=0;PRVM_SetProg(PRVM_CLIENTPROG);
15
#define CSQC_END prog=csqc_tmpprog;
16
static prvm_prog_t *csqc_tmpprog;
18
//[515]: these are required funcs
19
static char *cl_required_func[] =
24
"CSQC_ConsoleCommand",
27
static int cl_numrequiredfunc = sizeof(cl_required_func) / sizeof(char*);
29
void CL_VM_Error (const char *format, ...) DP_FUNC_PRINTF(1);
30
void CL_VM_Error (const char *format, ...) //[515]: hope it will be never executed =)
32
char errorstring[4096];
35
va_start (argptr, format);
36
dpvsnprintf (errorstring, sizeof(errorstring), format, argptr);
38
// Con_Printf( "CL_VM_Error: %s\n", errorstring );
41
cl.csqc_loaded = false;
43
Cvar_SetValueQuick(&csqc_progcrc, -1);
44
Cvar_SetValueQuick(&csqc_progsize, -1);
46
// Host_AbortCurrentFrame(); //[515]: hmmm... if server says it needs csqc then client MUST disconnect
47
Host_Error(va("CL_VM_Error: %s", errorstring));
49
void CL_VM_UpdateDmgGlobals (int dmg_take, int dmg_save, vec3_t dmg_origin)
55
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_take);
57
val->_float = dmg_take;
58
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_save);
60
val->_float = dmg_save;
61
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_origin);
64
val->vector[0] = dmg_origin[0];
65
val->vector[1] = dmg_origin[1];
66
val->vector[2] = dmg_origin[2];
71
//[515]: set globals before calling R_UpdateView, WEIRD CRAP
72
static void CSQC_SetGlobals (void)
76
prog->globals.client->time = cl.time;
77
prog->globals.client->frametime = max(0, cl.time - cl.oldtime);
78
prog->globals.client->servercommandframe = cls.servermovesequence;
79
prog->globals.client->clientcommandframe = cl.movecmd[0].sequence;
80
VectorCopy(cl.viewangles, prog->globals.client->input_angles);
81
VectorCopy(cl.viewangles, cl.csqc_angles);
82
// // FIXME: this actually belongs into getinputstate().. [12/17/2007 Black]
83
prog->globals.client->input_buttons = cl.movecmd[0].buttons;
84
VectorSet(prog->globals.client->input_movevalues, cl.movecmd[0].forwardmove, cl.movecmd[0].sidemove, cl.movecmd[0].upmove);
85
//VectorCopy(cl.movement_origin, cl.csqc_origin);
86
Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, cl.csqc_origin);
88
// LordHavoc: Spike says not to do this, but without pmove_org the
89
// CSQC is useless as it can't alter the view origin without
90
// completely replacing it
91
VectorCopy(cl.csqc_origin, prog->globals.client->pmove_org);
92
VectorCopy(cl.velocity, prog->globals.client->pmove_vel);
94
if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.view_angles)))
95
VectorCopy(cl.viewangles, val->vector);
96
prog->globals.client->maxclients = cl.maxclients;
100
void CSQC_Predraw (prvm_edict_t *ed)
103
if(!ed->fields.client->predraw)
105
b = prog->globals.client->self;
106
prog->globals.client->self = PRVM_EDICT_TO_PROG(ed);
107
PRVM_ExecuteProgram(ed->fields.client->predraw, "CSQC_Predraw: NULL function\n");
108
prog->globals.client->self = b;
111
void CSQC_Think (prvm_edict_t *ed)
114
if(ed->fields.client->think)
115
if(ed->fields.client->nextthink && ed->fields.client->nextthink <= prog->globals.client->time)
117
ed->fields.client->nextthink = 0;
118
b = prog->globals.client->self;
119
prog->globals.client->self = PRVM_EDICT_TO_PROG(ed);
120
PRVM_ExecuteProgram(ed->fields.client->think, "CSQC_Think: NULL function\n");
121
prog->globals.client->self = b;
125
extern cvar_t cl_noplayershadow;
126
qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
132
entity_render_t *entrender;
134
matrix4x4_t tagmatrix, matrix2;
136
model = CL_GetModelFromEdict(ed);
140
entrender = CL_NewTempEntity();
144
entrender->model = model;
145
entrender->skinnum = (int)ed->fields.client->skin;
146
entrender->effects |= entrender->model->effects;
149
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
150
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float) entrender->alpha = val->_float;
151
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float) entrender->scale = scale = val->_float;
152
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, entrender->colormod);
153
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.effects)) && val->_float) entrender->effects |= (int)val->_float;
154
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.tag_entity)) && val->edict)
158
tagentity = val->edict;
159
if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.tag_index)) && val->_float)
160
tagindex = (int)val->_float;
161
CL_GetTagMatrix (&tagmatrix, PRVM_PROG_TO_EDICT(tagentity), tagindex);
164
Matrix4x4_CreateIdentity(&tagmatrix);
166
if (renderflags & RF_USEAXIS)
169
VectorNegate(prog->globals.client->v_right, left);
170
Matrix4x4_FromVectors(&matrix2, prog->globals.client->v_forward, left, prog->globals.client->v_up, ed->fields.client->origin);
171
Matrix4x4_Scale(&matrix2, scale, 1);
176
VectorCopy(ed->fields.client->angles, angles);
177
// if model is alias, reverse pitch direction
178
if (entrender->model->type == mod_alias)
179
angles[0] = -angles[0];
181
// set up the render matrix
182
Matrix4x4_CreateFromQuakeEntity(&matrix2, ed->fields.client->origin[0], ed->fields.client->origin[1], ed->fields.client->origin[2], angles[0], angles[1], angles[2], scale);
185
// set up the animation data
186
// self.frame is the interpolation target (new frame)
187
// self.frame1time is the animation base time for the interpolation target
188
// self.frame2 is the interpolation start (previous frame)
189
// self.frame2time is the animation base time for the interpolation start
190
entrender->frame1 = entrender->frame2 = ed->fields.client->frame;
191
if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2))) entrender->frame2 = val->_float;
192
if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame1time))) entrender->frame2time = val->_float;
193
if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2time))) entrender->frame1time = val->_float;
194
if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac))) entrender->framelerp = val->_float;
196
// concat the matrices to make the entity relative to its tag
197
Matrix4x4_Concat(&entrender->matrix, &tagmatrix, &matrix2);
201
if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL;
202
if(renderflags & RF_EXTERNALMODEL)entrender->flags |= RENDER_EXTERIORMODEL;
203
if(renderflags & RF_DEPTHHACK) entrender->effects |= EF_NODEPTHTEST;
204
if(renderflags & RF_ADDITIVE) entrender->effects |= EF_ADDITIVE;
207
c = (int)ed->fields.client->colormap;
209
CL_SetEntityColormapColors(entrender, -1);
210
else if (c <= cl.maxclients && cl.scores != NULL)
211
CL_SetEntityColormapColors(entrender, cl.scores[c-1].colors);
213
CL_SetEntityColormapColors(entrender, c);
215
// either fullbright or lit
216
if (!(entrender->effects & EF_FULLBRIGHT) && !r_fullbright.integer)
217
entrender->flags |= RENDER_LIGHT;
218
// hide player shadow during intermission or nehahra movie
219
if (!(entrender->effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST))
220
&& (entrender->alpha >= 1)
221
&& !(entrender->flags & RENDER_VIEWMODEL)
222
&& (!(entrender->flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
223
entrender->flags |= RENDER_SHADOW;
224
if (entrender->flags & RENDER_VIEWMODEL)
225
entrender->flags |= RENDER_NOSELFSHADOW;
227
// make the other useful stuff
228
CL_UpdateRenderEntity(entrender);
233
qboolean CL_VM_InputEvent (qboolean down, int key, int ascii)
241
if (!prog->funcoffsets.CSQC_InputEvent)
245
prog->globals.client->time = cl.time;
246
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
247
PRVM_G_FLOAT(OFS_PARM0) = !down; // 0 is down, 1 is up
248
PRVM_G_FLOAT(OFS_PARM1) = key;
249
PRVM_G_FLOAT(OFS_PARM2) = ascii;
250
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_InputEvent, "QC function CSQC_InputEvent is missing");
257
qboolean CL_VM_UpdateView (void)
267
//VectorCopy(cl.viewangles, oldangles);
268
prog->globals.client->time = cl.time;
269
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
271
// clear renderable entity and light lists to prevent crashes if the
272
// CSQC_UpdateView function does not call R_ClearScene as it should
273
r_refdef.scene.numentities = 0;
274
r_refdef.scene.numlights = 0;
275
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_UpdateView, "QC function CSQC_UpdateView is missing");
276
//VectorCopy(oldangles, cl.viewangles);
277
// Dresk : Reset Dmg Globals Here
278
CL_VM_UpdateDmgGlobals(0, 0, emptyvector);
283
extern sizebuf_t vm_tempstringsbuf;
284
qboolean CL_VM_ConsoleCommand (const char *cmd)
286
int restorevm_tempstringsbuf_cursize;
291
if (prog->funcoffsets.CSQC_ConsoleCommand)
293
prog->globals.client->time = cl.time;
294
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
295
restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
296
PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(cmd);
297
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_ConsoleCommand, "QC function CSQC_ConsoleCommand is missing");
298
vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
305
qboolean CL_VM_Parse_TempEntity (void)
312
if(prog->funcoffsets.CSQC_Parse_TempEntity)
315
prog->globals.client->time = cl.time;
316
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
317
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_TempEntity, "QC function CSQC_Parse_TempEntity is missing");
329
void CL_VM_Parse_StuffCmd (const char *msg)
331
int restorevm_tempstringsbuf_cursize;
337
// if this is setting a csqc variable, deprotect csqc_progcrc
338
// temporarily so that it can be set by the cvar command,
339
// and then reprotect it afterwards
340
int crcflags = csqc_progcrc.flags;
341
int sizeflags = csqc_progcrc.flags;
342
csqc_progcrc.flags &= ~CVAR_READONLY;
343
csqc_progsize.flags &= ~CVAR_READONLY;
344
Cmd_ExecuteString (msg, src_command);
345
csqc_progcrc.flags = crcflags;
346
csqc_progsize.flags = sizeflags;
355
if(prog->funcoffsets.CSQC_Parse_StuffCmd)
357
prog->globals.client->time = cl.time;
358
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
359
restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
360
PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
361
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_StuffCmd, "QC function CSQC_Parse_StuffCmd is missing");
362
vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
369
static void CL_VM_Parse_Print (const char *msg)
371
int restorevm_tempstringsbuf_cursize;
372
prog->globals.client->time = cl.time;
373
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
374
restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
375
PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
376
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_Print, "QC function CSQC_Parse_Print is missing");
377
vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
380
void CSQC_AddPrintText (const char *msg)
389
if(prog->funcoffsets.CSQC_Parse_Print)
391
// FIXME: is this bugged?
393
if(msg[i] != '\n' && msg[i] != '\r')
395
if(strlen(cl.csqc_printtextbuf)+i >= MAX_INPUTLINE)
397
CL_VM_Parse_Print(cl.csqc_printtextbuf);
398
cl.csqc_printtextbuf[0] = 0;
401
strlcat(cl.csqc_printtextbuf, msg, MAX_INPUTLINE);
404
strlcat(cl.csqc_printtextbuf, msg, MAX_INPUTLINE);
405
CL_VM_Parse_Print(cl.csqc_printtextbuf);
406
cl.csqc_printtextbuf[0] = 0;
413
void CL_VM_Parse_CenterPrint (const char *msg)
415
int restorevm_tempstringsbuf_cursize;
418
SCR_CenterPrint((char*)msg);
422
if(prog->funcoffsets.CSQC_Parse_CenterPrint)
424
prog->globals.client->time = cl.time;
425
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
426
restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
427
PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
428
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_CenterPrint, "QC function CSQC_Parse_CenterPrint is missing");
429
vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
432
SCR_CenterPrint((char*)msg);
436
void CL_VM_UpdateIntermissionState (int intermission)
442
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.intermission);
444
val->_float = intermission;
448
void CL_VM_UpdateShowingScoresState (int showingscores)
454
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.sb_showscores);
456
val->_float = showingscores;
460
qboolean CL_VM_Event_Sound(int sound_num, int volume, int channel, float attenuation, int ent, vec3_t pos)
466
if(prog->funcoffsets.CSQC_Event_Sound)
468
prog->globals.client->time = cl.time;
469
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
470
PRVM_G_FLOAT(OFS_PARM0) = ent;
471
PRVM_G_FLOAT(OFS_PARM1) = channel;
472
PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(cl.sound_name[sound_num] );
473
PRVM_G_FLOAT(OFS_PARM3) = volume;
474
PRVM_G_FLOAT(OFS_PARM4) = attenuation;
475
VectorCopy(pos, PRVM_G_VECTOR(OFS_PARM5) );
476
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Event_Sound, "QC function CSQC_Event_Sound is missing");
484
void CL_VM_UpdateCoopDeathmatchGlobals (int gametype)
486
// Avoid global names for clean(er) coding
493
if(gametype == GAME_COOP)
499
if(gametype == GAME_DEATHMATCH)
506
// How did the ServerInfo send an unknown gametype?
507
// Better just assign the globals as 0...
512
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.coop);
514
val->_float = localcoop;
515
val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.deathmatch);
517
val->_float = localdeathmatch;
521
float CL_VM_Event (float event) //[515]: needed ? I'd say "YES", but don't know for what :D
527
if(prog->funcoffsets.CSQC_Event)
529
prog->globals.client->time = cl.time;
530
prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity];
531
PRVM_G_FLOAT(OFS_PARM0) = event;
532
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Event, "QC function CSQC_Event is missing");
539
void CSQC_ReadEntities (void)
541
unsigned short entnum, oldself, realentnum;
544
Host_Error ("CSQC_ReadEntities: CSQC is not loaded");
549
prog->globals.client->time = cl.time;
550
oldself = prog->globals.client->self;
553
entnum = MSG_ReadShort();
554
if(!entnum || msg_badread)
556
realentnum = entnum & 0x7FFF;
557
prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum];
560
if(prog->globals.client->self)
562
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Remove, "QC function CSQC_Ent_Remove is missing");
563
cl.csqc_server2csqcentitynumber[realentnum] = 0;
566
Con_Printf("Bad csqc_server2csqcentitynumber map\n"); //[515]: never happens ?
570
if(!prog->globals.client->self)
572
if(!prog->funcoffsets.CSQC_Ent_Spawn)
575
ed = PRVM_ED_Alloc();
576
ed->fields.client->entnum = realentnum;
577
prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT_TO_PROG(ed);
581
// entity( float entnum ) CSQC_Ent_Spawn;
582
// the qc function should set entnum, too (this way it also can return world [2/1/2008 Andreas]
583
PRVM_G_FLOAT(OFS_PARM0) = (float) realentnum;
584
// make sure no one gets wrong ideas
585
prog->globals.client->self = 0;
586
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Spawn, "QC function CSQC_Ent_Spawn is missing");
587
prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT( PRVM_G_INT( OFS_RETURN ) );
589
PRVM_G_FLOAT(OFS_PARM0) = 1;
590
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Update, "QC function CSQC_Ent_Update is missing");
593
PRVM_G_FLOAT(OFS_PARM0) = 0;
594
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Update, "QC function CSQC_Ent_Update is missing");
598
prog->globals.client->self = oldself;
602
void CL_VM_CB_BeginIncreaseEdicts(void)
604
// links don't survive the transition, so unlink everything
605
World_UnlinkAll(&cl.world);
608
void CL_VM_CB_EndIncreaseEdicts(void)
613
// link every entity except world
614
for (i = 1, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
615
if (!ent->priv.server->free)
619
void CL_VM_CB_InitEdict(prvm_edict_t *e)
621
e->priv.server->move = false; // don't move on first frame
624
void CL_VM_CB_FreeEdict(prvm_edict_t *ed)
626
World_UnlinkEdict(ed);
627
memset(ed->fields.client, 0, sizeof(*ed->fields.client));
630
void CL_VM_CB_CountEdicts(void)
634
int active = 0, models = 0, solid = 0;
636
for (i=0 ; i<prog->num_edicts ; i++)
638
ent = PRVM_EDICT_NUM(i);
639
if (ent->priv.server->free)
642
if (ent->fields.client->solid)
644
if (ent->fields.client->model)
648
Con_Printf("num_edicts:%3i\n", prog->num_edicts);
649
Con_Printf("active :%3i\n", active);
650
Con_Printf("view :%3i\n", models);
651
Con_Printf("touch :%3i\n", solid);
654
qboolean CL_VM_CB_LoadEdict(prvm_edict_t *ent)
659
void Cmd_ClearCsqcFuncs (void);
661
void CL_VM_Init (void)
663
const char* csprogsfn;
664
unsigned char *csprogsdata;
665
fs_offset_t csprogsdatasize;
666
int csprogsdatacrc, requiredcrc;
670
// reset csqc_progcrc after reading it, so that changing servers doesn't
671
// expect csqc on the next server
672
requiredcrc = csqc_progcrc.integer;
673
requiredsize = csqc_progsize.integer;
674
Cvar_SetValueQuick(&csqc_progcrc, -1);
675
Cvar_SetValueQuick(&csqc_progsize, -1);
677
// if the server is not requesting a csprogs, then we're done here
681
// see if the requested csprogs.dat file matches the requested crc
683
csprogsfn = va("dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc);
684
csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
687
csprogsfn = csqc_progname.string;
688
csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
692
csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize);
693
Mem_Free(csprogsdata);
694
if (csprogsdatacrc != requiredcrc || csprogsdatasize != requiredsize)
696
if (cls.demoplayback)
698
Con_Printf("^1Warning: Your %s is not the same version as the demo was recorded with (CRC/size are %i/%i but should be %i/%i)\n", csqc_progname.string, csprogsdatacrc, (int)csprogsdatasize, requiredcrc, requiredsize);
703
Con_Printf("^1Your %s is not the same version as the server (CRC is %i/%i but should be %i/%i)\n", csqc_progname.string, csprogsdatacrc, (int)csprogsdatasize, requiredcrc, requiredsize);
711
if (requiredcrc >= 0)
713
if (cls.demoplayback)
714
Con_Printf("CL_VM_Init: demo requires CSQC, but \"%s\" wasn't found\n", csqc_progname.string);
716
Con_Printf("CL_VM_Init: server requires CSQC, but \"%s\" wasn't found\n", csqc_progname.string);
723
PRVM_InitProg(PRVM_CLIENTPROG);
725
// allocate the mempools
726
prog->progs_mempool = Mem_AllocPool(csqc_progname.string, 0, NULL);
727
prog->headercrc = CL_PROGHEADER_CRC;
728
prog->edictprivate_size = 0; // no private struct used
729
prog->name = CL_NAME;
730
prog->num_edicts = 1;
731
prog->max_edicts = 512;
732
prog->limit_edicts = CL_MAX_EDICTS;
733
prog->reserved_edicts = 0;
734
prog->edictprivate_size = sizeof(edict_engineprivate_t);
735
// TODO: add a shared extension string #define and add real support for csqc extension strings [12/5/2007 Black]
736
prog->extensionstring = vm_sv_extensions;
737
prog->builtins = vm_cl_builtins;
738
prog->numbuiltins = vm_cl_numbuiltins;
739
prog->begin_increase_edicts = CL_VM_CB_BeginIncreaseEdicts;
740
prog->end_increase_edicts = CL_VM_CB_EndIncreaseEdicts;
741
prog->init_edict = CL_VM_CB_InitEdict;
742
prog->free_edict = CL_VM_CB_FreeEdict;
743
prog->count_edicts = CL_VM_CB_CountEdicts;
744
prog->load_edict = CL_VM_CB_LoadEdict;
745
prog->init_cmd = VM_CL_Cmd_Init;
746
prog->reset_cmd = VM_CL_Cmd_Reset;
747
prog->error_cmd = CL_VM_Error;
749
PRVM_LoadProgs(csprogsfn, cl_numrequiredfunc, cl_required_func, 0, NULL, 0, NULL);
753
CL_VM_Error("CSQC %s ^2failed to load\n", csprogsfn);
759
Con_Printf("CSQC %s ^5loaded (crc=%i, size=%i)\n", csprogsfn, csprogsdatacrc, (int)csprogsdatasize);
761
// check if OP_STATE animation is possible in this dat file
762
if (prog->fieldoffsets.nextthink >= 0 && prog->fieldoffsets.frame >= 0 && prog->fieldoffsets.think >= 0 && prog->globaloffsets.self >= 0)
763
prog->flag |= PRVM_OP_STATE;
766
prog->globals.client->time = cl.time;
767
prog->globals.client->self = 0;
769
prog->globals.client->mapname = cl.worldmodel ? PRVM_SetEngineString(cl.worldmodel->name) : PRVM_SetEngineString("");
770
prog->globals.client->player_localentnum = cl.playerentity;
772
// set map description (use world entity 0)
773
val = PRVM_EDICTFIELDVALUE(prog->edicts, prog->fieldoffsets.message);
775
val->string = PRVM_SetEngineString(cl.levelname);
776
VectorCopy(cl.world.mins, prog->edicts->fields.client->mins);
777
VectorCopy(cl.world.maxs, prog->edicts->fields.client->maxs);
779
// call the prog init
780
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Init, "QC function CSQC_Init is missing");
783
cl.csqc_loaded = true;
785
cl.csqc_vidvars.drawcrosshair = false;
786
cl.csqc_vidvars.drawenginesbar = false;
788
// Update Coop and Deathmatch Globals (at this point the client knows them from ServerInfo)
789
CL_VM_UpdateCoopDeathmatchGlobals(cl.gametype);
792
void CL_VM_ShutDown (void)
794
Cmd_ClearCsqcFuncs();
795
Cvar_SetValueQuick(&csqc_progcrc, -1);
796
Cvar_SetValueQuick(&csqc_progsize, -1);
800
prog->globals.client->time = cl.time;
801
prog->globals.client->self = 0;
802
if (prog->funcoffsets.CSQC_Shutdown)
803
PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Shutdown, "QC function CSQC_Shutdown is missing");
806
Con_Print("CSQC ^1unloaded\n");
807
cl.csqc_loaded = false;