]> icculus.org git repositories - divverent/darkplaces.git/blob - clvm_cmds.c
7b3900a6c2b1023a3e653aa017e71f5fb4d70ebf
[divverent/darkplaces.git] / clvm_cmds.c
1 #include "prvm_cmds.h"
2 #include "csprogs.h"
3 #include "cl_collision.h"
4
5 //============================================================================
6 // Client
7 //[515]: unsolved PROBLEMS
8 //- finish player physics code (cs_runplayerphysics)
9 //- fix R_AddDynamicLight
10 //- EntWasFreed ?
11 //- RF_DEPTHHACK is not like it should be
12 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
13 //- finish lines support for R_Polygon***
14 //- insert selecttraceline into traceline somehow
15
16 //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
17 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
18
19 #ifndef PF_WARNING
20 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
21 #endif
22
23 //[515]: really need new list ?
24 char *vm_cl_extensions =
25 "DP_CON_SET "
26 "DP_CON_SETA "
27 "DP_CON_STARTMAP "
28 "DP_EF_ADDITIVE "
29 "DP_EF_BLUE "
30 "DP_EF_FLAME "
31 "DP_EF_FULLBRIGHT "
32 "DP_EF_NODEPTHTEST "
33 "DP_EF_NODRAW "
34 "DP_EF_NOSHADOW "
35 "DP_EF_RED "
36 "DP_EF_STARDUST "
37 "DP_ENT_ALPHA "
38 "DP_ENT_CUSTOMCOLORMAP "
39 "DP_ENT_GLOW "
40 "DP_ENT_SCALE "
41 "DP_GFX_EXTERNALTEXTURES "
42 "DP_GFX_FOG "
43 "DP_GFX_QUAKE3MODELTAGS "
44 "DP_GFX_SKINFILES "
45 "DP_GFX_SKYBOX "
46 "DP_HALFLIFE_MAP "
47 "DP_HALFLIFE_MAP_CVAR "
48 "DP_HALFLIFE_SPRITE "
49 "DP_INPUTBUTTONS "
50 "DP_LITSPRITES "
51 "DP_LITSUPPORT "
52 "DP_MONSTERWALK "
53 "DP_MOVETYPEBOUNCEMISSILE "
54 "DP_MOVETYPEFOLLOW "
55 "DP_QC_CHANGEPITCH "
56 "DP_QC_COPYENTITY "
57 "DP_QC_CVAR_STRING "
58 "DP_QC_ETOS "
59 "DP_QC_FINDCHAIN "
60 "DP_QC_FINDCHAINFLAGS "
61 "DP_QC_FINDCHAINFLOAT "
62 "DP_QC_FINDFLAGS "
63 "DP_QC_FINDFLOAT "
64 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
65 "DP_QC_GETLIGHT "
66 "DP_QC_GETSURFACE "
67 "DP_QC_GETTAGINFO "
68 "DP_QC_MINMAXBOUND "
69 "DP_QC_MULTIPLETEMPSTRINGS "
70 "DP_QC_RANDOMVEC "
71 "DP_QC_SINCOSSQRTPOW "
72 //"DP_QC_STRINGBUFFERS "        //[515]: not needed ?
73 "DP_QC_TRACEBOX "
74 //"DP_QC_TRACETOSS "
75 "DP_QC_TRACE_MOVETYPE_HITMODEL "
76 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
77 "DP_QC_VECTORVECTORS "
78 "DP_QUAKE2_MODEL "
79 "DP_QUAKE2_SPRITE "
80 "DP_QUAKE3_MAP "
81 "DP_QUAKE3_MODEL "
82 "DP_REGISTERCVAR "
83 "DP_SND_DIRECTIONLESSATTNNONE "
84 "DP_SND_FAKETRACKS "
85 "DP_SND_OGGVORBIS "
86 "DP_SND_STEREOWAV "
87 "DP_SOLIDCORPSE "
88 "DP_SPRITE32 "
89 "DP_SV_EFFECT "
90 "DP_SV_ROTATINGBMODEL "
91 "DP_SV_SLOWMO "
92 "DP_TE_BLOOD "
93 "DP_TE_BLOODSHOWER "
94 "DP_TE_CUSTOMFLASH "
95 "DP_TE_EXPLOSIONRGB "
96 "DP_TE_FLAMEJET "
97 "DP_TE_PARTICLECUBE "
98 "DP_TE_PARTICLERAIN "
99 "DP_TE_PARTICLESNOW "
100 "DP_TE_PLASMABURN "
101 "DP_TE_QUADEFFECTS1 "
102 "DP_TE_SMALLFLASH "
103 "DP_TE_SPARK "
104 "DP_TE_STANDARDEFFECTBUILTINS "
105 "EXT_BITSHIFT "
106 "EXT_CSQC "
107 "FRIK_FILE "
108 "KRIMZON_SV_PARSECLIENTCOMMAND "
109 "NEH_CMD_PLAY2 "
110 "NXQ_GFX_LETTERBOX "
111 "PRYDON_CLIENTCURSOR "
112 "TENEBRAE_GFX_DLIGHTS "
113 "TW_SV_STEPCONTROL "
114 "NEXUIZ_PLAYERMODEL "
115 "NEXUIZ_PLAYERSKIN "
116 ;
117
118 sfx_t *S_FindName(const char *name);
119 int CL_PointQ1Contents(const vec3_t p);
120 void PF_registercvar (void);
121 int Sbar_GetPlayer (int index);
122 void Sbar_SortFrags (void);
123 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
124 void CL_ExpandCSQCEntities(int num);
125 void CSQC_RelinkAllEntities (int drawmask);
126 void CSQC_RelinkCSQCEntities (void);
127 char *Key_GetBind (int key);
128
129
130
131
132
133 // #1 void(vector ang) makevectors
134 void VM_CL_makevectors (void)
135 {
136         VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
137         AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
138 }
139
140 // #2 void(entity e, vector o) setorigin
141 void VM_CL_setorigin (void)
142 {
143         prvm_edict_t    *e;
144         float   *org;
145
146         e = PRVM_G_EDICT(OFS_PARM0);
147         if (e == prog->edicts)
148                 PF_WARNING("setorigin: can not modify world entity\n");
149         if (e->priv.required->free)
150                 PF_WARNING("setorigin: can not modify free entity\n");
151         org = PRVM_G_VECTOR(OFS_PARM1);
152         VectorCopy (org, e->fields.client->origin);
153 }
154
155 // #3 void(entity e, string m) setmodel
156 void VM_CL_setmodel (void)
157 {
158         prvm_edict_t    *e;
159         const char              *m;
160         struct model_s  *mod;
161         int                             i;
162
163         VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
164
165         e = PRVM_G_EDICT(OFS_PARM0);
166         m = PRVM_G_STRING(OFS_PARM1);
167         for(i=0;i<MAX_MODELS;i++)
168                 if(!cl.csqc_model_precache[i])
169                         break;
170                 else
171                 if(!strcmp(cl.csqc_model_precache[i]->name, m))
172                 {
173                         e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
174                         e->fields.client->modelindex = -(i+1);
175                         return;
176                 }
177
178         for (i=0, mod = cl.model_precache[0] ; i < MAX_MODELS ; i++, mod = cl.model_precache[i])
179                 if(mod)
180                 if(!strcmp(mod->name, m))
181                 {
182                         e->fields.client->model = PRVM_SetEngineString(mod->name);
183                         e->fields.client->modelindex = i;
184                         return;
185                 }
186         e->fields.client->modelindex = 0;
187         e->fields.client->model = 0;
188 }
189
190 // #4 void(entity e, vector min, vector max) setsize
191 void VM_CL_setsize (void)
192 {
193         prvm_edict_t    *e;
194         float                   *min, *max;
195         VM_SAFEPARMCOUNT(3, VM_CL_setsize);
196
197         e = PRVM_G_EDICT(OFS_PARM0);
198         if (e == prog->edicts)
199                 PF_WARNING("setsize: can not modify world entity\n");
200         if (e->priv.server->free)
201                 PF_WARNING("setsize: can not modify free entity\n");
202         min = PRVM_G_VECTOR(OFS_PARM1);
203         max = PRVM_G_VECTOR(OFS_PARM2);
204
205         VectorCopy (min, e->fields.client->mins);
206         VectorCopy (max, e->fields.client->maxs);
207         VectorSubtract (max, min, e->fields.client->size);
208 }
209
210 // #8 void(entity e, float chan, string samp) sound
211 void VM_CL_sound (void)
212 {
213         const char                      *sample;
214         int                                     channel;
215         prvm_edict_t            *entity;
216         int                             volume;
217         float                           attenuation;
218
219         VM_SAFEPARMCOUNT(5, VM_CL_sound);
220
221         entity = PRVM_G_EDICT(OFS_PARM0);
222         channel = PRVM_G_FLOAT(OFS_PARM1);
223         sample = PRVM_G_STRING(OFS_PARM2);
224         volume = PRVM_G_FLOAT(OFS_PARM3)*255;
225         attenuation = PRVM_G_FLOAT(OFS_PARM4);
226
227         if (volume < 0 || volume > 255)
228                 PF_WARNING("VM_CL_sound: volume must be in range 0-1\n");
229
230         if (attenuation < 0 || attenuation > 4)
231                 PF_WARNING("VM_CL_sound: attenuation must be in range 0-4\n");
232
233         if (channel < 0 || channel > 7)
234                 PF_WARNING("VM_CL_sound: channel must be in range 0-7\n");
235
236         S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
237 }
238
239 // #14 entity() spawn
240 void VM_CL_spawn (void)
241 {
242         prvm_edict_t *ed;
243         ed = PRVM_ED_Alloc();
244         ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed);     //[515]: not needed any more ?
245         VM_RETURN_EDICT(ed);
246 }
247
248 // #16 float(vector v1, vector v2, float tryents) traceline
249 void VM_CL_traceline (void)
250 {
251         float   *v1, *v2;
252         trace_t trace;
253         int             ent;
254
255         v1 = PRVM_G_VECTOR(OFS_PARM0);
256         v2 = PRVM_G_VECTOR(OFS_PARM1);
257
258         trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false);
259
260         prog->globals.client->trace_allsolid = trace.allsolid;
261         prog->globals.client->trace_startsolid = trace.startsolid;
262         prog->globals.client->trace_fraction = trace.fraction;
263         prog->globals.client->trace_inwater = trace.inwater;
264         prog->globals.client->trace_inopen = trace.inopen;
265         VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
266         VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
267         prog->globals.client->trace_plane_dist =  trace.plane.dist;
268         if (ent)
269                 prog->globals.client->trace_ent = ent;
270         else
271                 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
272 }
273
274 // #19 void(string s) precache_sound
275 void VM_CL_precache_sound (void)
276 {
277         const char *n;
278         VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
279         n = PRVM_G_STRING(OFS_PARM0);
280         S_PrecacheSound(n, true, false);
281 }
282
283 // #20 void(string s) precache_model
284 void VM_CL_precache_model (void)
285 {
286         const char      *name;
287         int                     i;
288         model_t         *m;
289
290         VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
291
292         name = PRVM_G_STRING(OFS_PARM0);
293         for(i=1;i<MAX_MODELS;i++)
294                 if(!cl.csqc_model_precache[i])
295                 {
296                         i = 0;
297                         break;
298                 }
299                 else
300                 if(!strcmp(cl.csqc_model_precache[i]->name, name))
301                 {
302                         i = -(i+1);
303                         break;
304                 }
305         if(i)
306         {
307                 PRVM_G_FLOAT(OFS_RETURN) = i;
308                 return;
309         }
310         PRVM_G_FLOAT(OFS_RETURN) = 0;
311         m = Mod_ForName(name, false, false, false);
312         if(m && m->loaded)
313         {
314                 for(i=1;i<MAX_MODELS;i++)
315                         if(!cl.csqc_model_precache[i])
316                                 break;
317                 if(i == MAX_MODELS)
318                         PF_WARNING("VM_CL_precache_model: no free models\n");
319                 cl.csqc_model_precache[i] = (model_t*)m;
320                 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
321                 return;
322         }
323         Con_Printf("VM_CL_precache_model: model \"%s\" not found\n", name);
324 }
325
326 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
327 {
328         prvm_edict_t    *ent;
329         int                             i, k;
330
331         ent = PRVM_NEXT_EDICT(prog->edicts);
332         for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
333         {
334                 if (ent->priv.required->free)
335                         continue;
336 //              VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
337 //              VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
338                 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
339                         list[k++] = ent;
340         }
341         return k;
342 }
343
344 // #22 entity(vector org, float rad) findradius
345 void VM_CL_findradius (void)
346 {
347         prvm_edict_t    *ent, *chain;
348         vec_t                   radius, radius2;
349         vec3_t                  org, eorg, mins, maxs;
350         int                             i, numtouchedicts;
351         prvm_edict_t    *touchedicts[MAX_EDICTS];
352
353         chain = (prvm_edict_t *)prog->edicts;
354
355         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
356         radius = PRVM_G_FLOAT(OFS_PARM1);
357         radius2 = radius * radius;
358
359         mins[0] = org[0] - (radius + 1);
360         mins[1] = org[1] - (radius + 1);
361         mins[2] = org[2] - (radius + 1);
362         maxs[0] = org[0] + (radius + 1);
363         maxs[1] = org[1] + (radius + 1);
364         maxs[2] = org[2] + (radius + 1);
365         numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
366         if (numtouchedicts > MAX_EDICTS)
367         {
368                 // this never happens   //[515]: for what then ?
369                 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
370                 numtouchedicts = MAX_EDICTS;
371         }
372         for (i = 0;i < numtouchedicts;i++)
373         {
374                 ent = touchedicts[i];
375                 // Quake did not return non-solid entities but darkplaces does
376                 // (note: this is the reason you can't blow up fallen zombies)
377                 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
378                         continue;
379                 // LordHavoc: compare against bounding box rather than center so it
380                 // doesn't miss large objects, and use DotProduct instead of Length
381                 // for a major speedup
382                 VectorSubtract(org, ent->fields.client->origin, eorg);
383                 if (sv_gameplayfix_findradiusdistancetobox.integer)
384                 {
385                         eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
386                         eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
387                         eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
388                 }
389                 else
390                         VectorMAMAM(1, eorg, 0.5f, ent->fields.client->mins, 0.5f, ent->fields.client->maxs, eorg);
391                 if (DotProduct(eorg, eorg) < radius2)
392                 {
393                         ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
394                         chain = ent;
395                 }
396         }
397
398         VM_RETURN_EDICT(chain);
399 }
400
401 // #34 float() droptofloor
402 void VM_CL_droptofloor (void)
403 {
404         prvm_edict_t            *ent;
405         vec3_t                          end;
406         trace_t                         trace;
407         int                                     i;
408
409         // assume failure if it returns early
410         PRVM_G_FLOAT(OFS_RETURN) = 0;
411
412         ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
413         if (ent == prog->edicts)
414                 PF_WARNING("droptofloor: can not modify world entity\n");
415         if (ent->priv.server->free)
416                 PF_WARNING("droptofloor: can not modify free entity\n");
417
418         VectorCopy (ent->fields.client->origin, end);
419         end[2] -= 256;
420
421         trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false);
422
423         if (trace.fraction != 1)
424         {
425                 VectorCopy (trace.endpos, ent->fields.client->origin);
426                 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
427 //              ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
428                 PRVM_G_FLOAT(OFS_RETURN) = 1;
429                 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
430 //              ent->priv.server->suspendedinairflag = true;
431         }
432 }
433
434 // #35 void(float style, string value) lightstyle
435 void VM_CL_lightstyle (void)
436 {
437         int                     i;
438         const char      *c;
439
440         VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
441
442         i = PRVM_G_FLOAT(OFS_PARM0);
443         c = PRVM_G_STRING(OFS_PARM1);
444         if (i >= cl_max_lightstyle)
445                 PF_WARNING("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
446         strlcpy (cl_lightstyle[i].map,  MSG_ReadString(), sizeof (cl_lightstyle[i].map));
447         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
448         cl_lightstyle[i].length = (int)strlen(cl_lightstyle[i].map);
449 }
450
451 // #40 float(entity e) checkbottom
452 void VM_CL_checkbottom (void)
453 {
454         static int              cs_yes, cs_no;
455         prvm_edict_t    *ent;
456         vec3_t                  mins, maxs, start, stop;
457         trace_t                 trace;
458         int                             x, y, hit;
459         float                   mid, bottom;
460
461         VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
462         ent = PRVM_G_EDICT(OFS_PARM0);
463         PRVM_G_FLOAT(OFS_RETURN) = 0;
464
465         VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
466         VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
467
468 // if all of the points under the corners are solid world, don't bother
469 // with the tougher checks
470 // the corners must be within 16 of the midpoint
471         start[2] = mins[2] - 1;
472         for     (x=0 ; x<=1 ; x++)
473                 for     (y=0 ; y<=1 ; y++)
474                 {
475                         start[0] = x ? maxs[0] : mins[0];
476                         start[1] = y ? maxs[1] : mins[1];
477                         if (!(CL_PointSuperContents(start) & SUPERCONTENTS_SOLID))
478                                 goto realcheck;
479                 }
480
481         cs_yes++;
482         PRVM_G_FLOAT(OFS_RETURN) = true;
483         return;         // we got out easy
484
485 realcheck:
486         cs_no++;
487 //
488 // check it for real...
489 //
490         start[2] = mins[2];
491
492 // the midpoint must be within 16 of the bottom
493         start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
494         start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
495         stop[2] = start[2] - 2*sv_stepheight.value;
496         trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
497
498         if (trace.fraction == 1.0)
499                 return;
500
501         mid = bottom = trace.endpos[2];
502
503 // the corners must be within 16 of the midpoint
504         for     (x=0 ; x<=1 ; x++)
505                 for     (y=0 ; y<=1 ; y++)
506                 {
507                         start[0] = stop[0] = x ? maxs[0] : mins[0];
508                         start[1] = stop[1] = y ? maxs[1] : mins[1];
509
510                         trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
511
512                         if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
513                                 bottom = trace.endpos[2];
514                         if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
515                                 return;
516                 }
517
518         cs_yes++;
519         PRVM_G_FLOAT(OFS_RETURN) = true;
520 }
521
522 // #41 float(vector v) pointcontents
523 void VM_CL_pointcontents (void)
524 {
525         VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
526         PRVM_G_FLOAT(OFS_RETURN) = CL_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
527 }
528
529 // #48 void(vector o, vector d, float color, float count) particle
530 void VM_CL_particle (void)
531 {
532         float   *org, *dir;
533         int             count;
534         unsigned char   color;
535         VM_SAFEPARMCOUNT(4, VM_CL_particle);
536
537         org = PRVM_G_VECTOR(OFS_PARM0);
538         dir = PRVM_G_VECTOR(OFS_PARM1);
539         color = PRVM_G_FLOAT(OFS_PARM2);
540         count = PRVM_G_FLOAT(OFS_PARM3);
541         if (cl_particles_blood_bloodhack.integer)
542         {
543                 if (color == 73)
544                 {
545                         // regular blood
546                         CL_BloodPuff(org, dir, count / 2);
547                         return;
548                 }
549                 if (color == 225)
550                 {
551                         // lightning blood
552                         CL_BloodPuff(org, dir, count / 2);
553                         return;
554                 }
555         }
556         CL_RunParticleEffect (org, dir, color, count);
557 }
558
559 // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
560 void VM_CL_changeyaw (void)
561 {
562         prvm_edict_t    *ent;
563         float                   ideal, current, move, speed;
564         VM_SAFEPARMCOUNT(3, VM_CL_changeyaw);
565
566         ent = PRVM_G_EDICT(OFS_PARM0);
567         if (ent == prog->edicts)
568                 PF_WARNING("changeyaw: can not modify world entity\n");
569         if (ent->priv.server->free)
570                 PF_WARNING("changeyaw: can not modify free entity\n");
571         current = ANGLEMOD(ent->fields.client->angles[1]);
572         ideal = PRVM_G_FLOAT(OFS_PARM1);
573         speed = PRVM_G_FLOAT(OFS_PARM2);
574
575         if (current == ideal)
576                 return;
577         move = ideal - current;
578         if (ideal > current)
579         {
580                 if (move >= 180)
581                         move = move - 360;
582         }
583         else
584         {
585                 if (move <= -180)
586                         move = move + 360;
587         }
588         if (move > 0)
589         {
590                 if (move > speed)
591                         move = speed;
592         }
593         else
594         {
595                 if (move < -speed)
596                         move = -speed;
597         }
598
599         ent->fields.client->angles[1] = ANGLEMOD (current + move);
600 }
601
602 // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
603 void VM_CL_changepitch (void)
604 {
605         prvm_edict_t            *ent;
606         float                           ideal, current, move, speed;
607         VM_SAFEPARMCOUNT(3, VM_CL_changepitch);
608
609         ent = PRVM_G_EDICT(OFS_PARM0);
610         if (ent == prog->edicts)
611                 PF_WARNING("changepitch: can not modify world entity\n");
612         if (ent->priv.server->free)
613                 PF_WARNING("changepitch: can not modify free entity\n");
614         current = ANGLEMOD( ent->fields.client->angles[0] );
615         ideal = PRVM_G_FLOAT(OFS_PARM1);
616         speed = PRVM_G_FLOAT(OFS_PARM2);
617
618         if (current == ideal)
619                 return;
620         move = ideal - current;
621         if (ideal > current)
622         {
623                 if (move >= 180)
624                         move = move - 360;
625         }
626         else
627         {
628                 if (move <= -180)
629                         move = move + 360;
630         }
631         if (move > 0)
632         {
633                 if (move > speed)
634                         move = speed;
635         }
636         else
637         {
638                 if (move < -speed)
639                         move = -speed;
640         }
641
642         ent->fields.client->angles[0] = ANGLEMOD (current + move);
643 }
644
645 // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
646 void VM_CL_tracetoss (void)
647 {
648 /*      trace_t trace;
649         prvm_edict_t    *ent;
650         prvm_edict_t    *ignore;
651
652         ent = PRVM_G_EDICT(OFS_PARM0);
653         if (ent == prog->edicts)
654                 PF_WARNING("tracetoss: can not use world entity\n");
655         ignore = PRVM_G_EDICT(OFS_PARM1);
656
657 //FIXME
658         trace = SV_Trace_Toss (ent, ignore);
659
660         prog->globals.server->trace_allsolid = trace.allsolid;
661         prog->globals.server->trace_startsolid = trace.startsolid;
662         prog->globals.server->trace_fraction = trace.fraction;
663         prog->globals.server->trace_inwater = trace.inwater;
664         prog->globals.server->trace_inopen = trace.inopen;
665         VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
666         VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
667         prog->globals.server->trace_plane_dist =  trace.plane.dist;
668         if (trace.ent)
669                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
670         else
671                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
672 */
673 }
674
675 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
676 void VM_CL_ambientsound (void)
677 {
678         float   *f;
679         sfx_t   *s;
680         VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
681         s = S_FindName(PRVM_G_STRING(OFS_PARM0));
682         f = PRVM_G_VECTOR(OFS_PARM1);
683         S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
684 }
685
686 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
687 void VM_CL_tracebox (void)
688 {
689         float   *v1, *v2, *m1, *m2;
690         trace_t trace;
691         int             ent;
692
693         v1 = PRVM_G_VECTOR(OFS_PARM0);
694         m1 = PRVM_G_VECTOR(OFS_PARM1);
695         m2 = PRVM_G_VECTOR(OFS_PARM2);
696         v2 = PRVM_G_VECTOR(OFS_PARM3);
697
698         trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false);
699
700         prog->globals.client->trace_allsolid = trace.allsolid;
701         prog->globals.client->trace_startsolid = trace.startsolid;
702         prog->globals.client->trace_fraction = trace.fraction;
703         prog->globals.client->trace_inwater = trace.inwater;
704         prog->globals.client->trace_inopen = trace.inopen;
705         VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
706         VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
707         prog->globals.client->trace_plane_dist =  trace.plane.dist;
708         if (ent)
709                 prog->globals.client->trace_ent = ent;
710         else
711                 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
712 }
713
714 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
715 void VM_CL_getlight (void)
716 {
717         vec3_t ambientcolor, diffusecolor, diffusenormal;
718         vec_t *p;
719
720         VM_SAFEPARMCOUNT(1, VM_CL_getlight);
721
722         p = PRVM_G_VECTOR(OFS_PARM0);
723         VectorClear(ambientcolor);
724         VectorClear(diffusecolor);
725         VectorClear(diffusenormal);
726         if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
727                 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
728         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
729 }
730
731
732 //============================================================================
733 //[515]: SCENE MANAGER builtins
734 void V_CalcRefdef (void);//view.c
735 void CSQC_R_ClearScreen (void);//gl_rmain.c
736 void CSQC_R_RenderScene (void);//gl_rmain.c
737 void CSQC_AddEntity (int n);//csprogs.c
738 void CSQC_ClearCSQCEntities (void);
739
740 matrix4x4_t csqc_listenermatrix;
741 qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
742 qboolean csqc_onground;
743
744 static char *particleeffect_names[] =
745 {
746         "TE_SPIKE",
747         "TE_SUPERSPIKE",
748         "TE_GUNSHOT",
749         "TE_EXPLOSION",
750         "TE_TAREXPLOSION",
751         "TE_LIGHTNING1",//trail
752         "TE_LIGHTNING2",//trail
753         "TE_WIZSPIKE",
754         "TE_KNIGHTSPIKE",
755         "TE_LIGHTNING3",//trail
756         "TE_LAVASPLASH",
757         "TE_TELEPORT",
758         "TE_EXPLOSION2",
759         "TE_BEAM",//trail
760         "TE_EXPLOSION3",
761         "",//TE_LIGHTNING4NEH
762         "TE_BLOOD",
763         "TE_SPARK",
764         "",//TE_BLOODSHOWER
765         "TE_EXPLOSIONRGB",
766         "",//unused
767         "",
768         "",
769         "TE_GUNSHOTQUAD",
770         "TE_SPIKEQUAD",
771         "TE_SUPERSPIKEQUAD",
772         "TE_EXPLOSIONQUAD",
773         "",
774         "",
775         "",
776         "TE_FLAMEJET",
777         "TE_PLASMABURN",
778         "TE_TEI_G3",
779         "TE_TEI_SMOKE",
780         "TE_TEI_BIGEXPLOSION",
781         "TE_TEI_PLASMAHIT",
782
783
784         //trail effects (as modelflags)
785         "EF_ROCKET",
786         "EF_GRENADE",
787         "EF_GIB",
788         "EF_TRACER",
789         "EF_ZOMGIB",
790         "EF_TRACER2",
791         "EF_TRACER3",
792         "EF_NEH_CIGAR",
793         "EF_NEXUIZ_PLASMA",
794         "EF_GLOWTRAIL",
795 };
796
797 #define CSQC_TRAILSTART 36
798 static const int particleeffects_num = sizeof(particleeffect_names)/sizeof(char*);
799
800 static void CSQC_R_RecalcView (void)
801 {
802         extern matrix4x4_t viewmodelmatrix;
803         viewmodelmatrix = identitymatrix;
804         r_refdef.viewentitymatrix = identitymatrix;
805         Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
806         Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 0.3);
807 }
808
809 //#300 void() clearscene (EXT_CSQC)
810 void VM_R_ClearScene (void)
811 {
812         VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
813 //      CSQC_R_RecalcView();
814         if(csqc_frame)
815                 CSQC_ClearCSQCEntities();
816         CSQC_R_ClearScreen();
817 }
818
819 //#301 void(float mask) addentities (EXT_CSQC)
820 void VM_R_AddEntities (void)
821 {
822         VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
823         csqc_drawmask = PRVM_G_FLOAT(OFS_PARM0);
824 }
825
826 //#302 void(entity ent) addentity (EXT_CSQC)
827 void VM_R_AddEntity (void)
828 {
829         VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
830         CSQC_AddEntity(PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)));
831 }
832
833 //#303 float(float property, ...) setproperty (EXT_CSQC)
834 void VM_R_SetView (void)
835 {
836         int             c;
837         float   *f;
838         float   k;
839
840         if(prog->argc < 2)
841                 VM_SAFEPARMCOUNT(2, VM_R_SetView);
842
843         c = PRVM_G_FLOAT(OFS_PARM0);
844         f = PRVM_G_VECTOR(OFS_PARM1);
845         k = PRVM_G_FLOAT(OFS_PARM1);
846
847         switch(c)
848         {
849         case VF_MIN:                    r_refdef.x = f[0];
850                                                         r_refdef.y = f[1];
851                                                         break;
852         case VF_MIN_X:                  r_refdef.x = k;
853                                                         break;
854         case VF_MIN_Y:                  r_refdef.y = k;
855                                                         break;
856         case VF_SIZE:                   r_refdef.width = f[0];
857                                                         r_refdef.height = f[1];
858                                                         break;
859         case VF_SIZE_Y:                 r_refdef.width = k;
860                                                         break;
861         case VF_SIZE_X:                 r_refdef.height = k;
862                                                         break;
863         case VF_VIEWPORT:               r_refdef.x = f[0];
864                                                         r_refdef.y = f[1];
865                                                         f = PRVM_G_VECTOR(OFS_PARM2);
866                                                         r_refdef.width = f[0];
867                                                         r_refdef.height = f[1];
868                                                         break;
869         case VF_FOV:                    //r_refdef.fov_x = f[0]; // FIXME!
870                                                         //r_refdef.fov_y = f[1]; // FIXME!
871                                                         break;
872         case VF_FOVX:                   //r_refdef.fov_x = k; // FIXME!
873                                                         break;
874         case VF_FOVY:                   //r_refdef.fov_y = k; // FIXME!
875                                                         break;
876         case VF_ORIGIN:                 VectorCopy(f, csqc_origin);
877                                                         CSQC_R_RecalcView();
878                                                         break;
879         case VF_ORIGIN_X:               csqc_origin[0] = k;
880                                                         CSQC_R_RecalcView();
881                                                         break;
882         case VF_ORIGIN_Y:               csqc_origin[1] = k;
883                                                         CSQC_R_RecalcView();
884                                                         break;
885         case VF_ORIGIN_Z:               csqc_origin[2] = k;
886                                                         CSQC_R_RecalcView();
887                                                         break;
888         case VF_ANGLES:                 VectorCopy(f, csqc_angles);
889                                                         CSQC_R_RecalcView();
890                                                         break;
891         case VF_ANGLES_X:               csqc_angles[0] = k;
892                                                         CSQC_R_RecalcView();
893                                                         break;
894         case VF_ANGLES_Y:               csqc_angles[1] = k;
895                                                         CSQC_R_RecalcView();
896                                                         break;
897         case VF_ANGLES_Z:               csqc_angles[2] = k;
898                                                         CSQC_R_RecalcView();
899                                                         break;
900         case VF_DRAWWORLD:              cl.csqc_vidvars.drawworld = k;
901                                                         break;
902         case VF_DRAWENGINESBAR: cl.csqc_vidvars.drawenginesbar = k;
903                                                         break;
904         case VF_DRAWCROSSHAIR:  cl.csqc_vidvars.drawcrosshair = k;
905                                                         break;
906
907         case VF_CL_VIEWANGLES:  VectorCopy(f, cl.viewangles);
908                                                         break;
909         case VF_CL_VIEWANGLES_X:cl.viewangles[0] = k;
910                                                         break;
911         case VF_CL_VIEWANGLES_Y:cl.viewangles[1] = k;
912                                                         break;
913         case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
914                                                         break;
915
916         default:                                Con_Printf("VM_R_SetView : unknown parm %i\n", c);
917                                                         PRVM_G_FLOAT(OFS_RETURN) = 0;
918                                                         return;
919         }
920         PRVM_G_FLOAT(OFS_RETURN) = 1;
921 }
922
923 //#304 void() renderscene (EXT_CSQC)
924 void VM_R_RenderScene (void) //#134
925 {
926         VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
927
928         if(csqc_frame)
929         {
930                 CSQC_RelinkCSQCEntities();
931                 CSQC_RelinkAllEntities(csqc_drawmask);
932         }
933
934         CSQC_R_RenderScene();
935 }
936
937 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
938 void VM_R_AddDynamicLight (void)
939 {
940         float           *pos, *col;
941         matrix4x4_t     tempmatrix;
942         VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
943
944         pos = PRVM_G_VECTOR(OFS_PARM0);
945         col = PRVM_G_VECTOR(OFS_PARM2);
946         Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
947         CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
948         //CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
949 }
950
951 //============================================================================
952
953 //#310 vector (vector v) cs_unproject (EXT_CSQC)
954 void VM_CL_unproject (void)
955 {
956         float   *f;
957         vec3_t  temp;
958
959         VM_SAFEPARMCOUNT(1, VM_CL_unproject);
960         f = PRVM_G_VECTOR(OFS_PARM0);
961         VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.frustum_x * 2.0 / r_refdef.width, f[1] * f[2] * -r_refdef.frustum_y * 2.0 / r_refdef.height);
962         Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, PRVM_G_VECTOR(OFS_RETURN));
963 }
964
965 //#311 vector (vector v) cs_project (EXT_CSQC)
966 void VM_CL_project (void)
967 {
968         float   *f;
969         vec3_t  v;
970         matrix4x4_t m;
971
972         VM_SAFEPARMCOUNT(1, VM_CL_project);
973         f = PRVM_G_VECTOR(OFS_PARM0);
974         Matrix4x4_Invert_Simple(&m, &r_refdef.viewentitymatrix);
975         Matrix4x4_Transform(&m, f, v);
976         VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.frustum_x*0.5*r_refdef.width, v[2]/v[0]/-r_refdef.frustum_y*r_refdef.height*0.5, v[0]);
977 }
978
979 //#330 float(float stnum) getstatf (EXT_CSQC)
980 void VM_CL_getstatf (void)
981 {
982         int i;
983         union
984         {
985                 float f;
986                 int l;
987         }dat;
988         VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
989         i = PRVM_G_FLOAT(OFS_PARM0);
990         if(i < 0 || i >= MAX_CL_STATS)
991         {
992                 Con_Printf("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
993                 return;
994         }
995         dat.l = cl.stats[i];
996         PRVM_G_FLOAT(OFS_RETURN) =  dat.f;
997 }
998
999 //#331 float(float stnum) getstati (EXT_CSQC)
1000 void VM_CL_getstati (void)
1001 {
1002         int i, index;
1003         VM_SAFEPARMCOUNT(1, VM_CL_getstati);
1004         index = PRVM_G_FLOAT(OFS_PARM0);
1005
1006         if(index < 0 || index >= MAX_CL_STATS)
1007         {
1008                 Con_Printf("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
1009                 return;
1010         }
1011         i = cl.stats[index];
1012         PRVM_G_FLOAT(OFS_RETURN) = i;
1013 }
1014
1015 //#332 string(float firststnum) getstats (EXT_CSQC)
1016 void VM_CL_getstats (void)
1017 {
1018         int i;
1019         char *t;
1020         VM_SAFEPARMCOUNT(1, VM_CL_getstats);
1021         i = PRVM_G_FLOAT(OFS_PARM0);
1022         if(i < 0 || i > MAX_CL_STATS-4)
1023         {
1024                 Con_Printf("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
1025                 return;
1026         }
1027         t = VM_GetTempString();
1028         strlcpy(t, (char*)&cl.stats[i], 16);
1029         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1030 }
1031
1032 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
1033 void VM_CL_setmodelindex (void)
1034 {
1035         int                             i;
1036         prvm_edict_t    *t;
1037         struct model_s  *m;
1038
1039         VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
1040
1041         t = PRVM_G_EDICT(OFS_PARM0);
1042         i = (int)PRVM_G_FLOAT(OFS_PARM1);
1043
1044         t->fields.client->model = 0;
1045         t->fields.client->modelindex = 0;
1046
1047         if(!i)
1048                 return;
1049         if(i<0)
1050         {
1051                 i = -(i+1);
1052                 if(i >= MAX_MODELS)
1053                         PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
1054                 m = cl.csqc_model_precache[i];
1055         }
1056         else
1057                 if(i >= MAX_MODELS)
1058                         PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
1059                 else
1060                         m = cl.model_precache[i];
1061         if(!m)
1062                 PF_WARNING("VM_CL_setmodelindex: null model\n");
1063         t->fields.client->model = PRVM_SetEngineString(m->name);
1064         t->fields.client->modelindex = i;
1065 }
1066
1067 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
1068 void VM_CL_modelnameforindex (void)
1069 {
1070         int i;
1071
1072         VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
1073
1074         PRVM_G_INT(OFS_RETURN) = 0;
1075         i = PRVM_G_FLOAT(OFS_PARM0);
1076         if(i<0)
1077         {
1078                 i = -(i+1);
1079                 if(i >= MAX_MODELS)
1080                         PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
1081                 if(cl.csqc_model_precache[i])
1082                         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
1083                 return;
1084         }
1085         if(i >= MAX_MODELS)
1086                 PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
1087         if(cl.model_precache[i])
1088                 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.model_precache[i]->name);
1089 }
1090
1091 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1092 void VM_CL_particleeffectnum (void)
1093 {
1094         const char      *n;
1095         int                     i;
1096         VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1097         n = PRVM_G_STRING(OFS_PARM0);
1098         for(i=0;i<particleeffects_num;i++)
1099                 if(!strcasecmp(particleeffect_names[i], n))
1100                 {
1101                         PRVM_G_FLOAT(OFS_RETURN) = i;
1102                         return;
1103                 }
1104         PRVM_G_FLOAT(OFS_RETURN) = -1;
1105 }
1106
1107 void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
1108 {
1109         int             i;
1110         beam_t  *b;
1111
1112         // override any beam with the same entity
1113         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1114         {
1115                 if (b->entity == ent && ent)
1116                 {
1117                         //b->entity = ent;
1118                         b->lightning = lightning;
1119                         b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1120                         b->model = m;
1121                         b->endtime = cl.time + 0.2;
1122                         VectorCopy (start, b->start);
1123                         VectorCopy (end, b->end);
1124                         return;
1125                 }
1126         }
1127
1128         // find a free beam
1129         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1130         {
1131                 if (!b->model || b->endtime < cl.time)
1132                 {
1133                         b->entity = ent;
1134                         b->lightning = lightning;
1135                         b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1136                         b->model = m;
1137                         b->endtime = cl.time + 0.2;
1138                         VectorCopy (start, b->start);
1139                         VectorCopy (end, b->end);
1140                         return;
1141                 }
1142         }
1143         Con_Print("beam list overflow!\n");
1144 }
1145
1146 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1147 void VM_CL_trailparticles (void)
1148 {
1149         int                             i, entnum, col;
1150         float                   *start, *end;
1151         entity_t                *ent;
1152         VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
1153
1154         entnum  = PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
1155         i               = PRVM_G_FLOAT(OFS_PARM1);
1156         start   = PRVM_G_VECTOR(OFS_PARM2);
1157         end             = PRVM_G_VECTOR(OFS_PARM3);
1158
1159         if(i >= particleeffects_num)
1160                 return;
1161         if (entnum >= MAX_EDICTS)
1162         {
1163                 Con_Printf("CSQC_ParseBeam: invalid entity number %i\n", entnum);
1164                 return;
1165         }
1166         if (entnum >= cl_max_csqcentities)
1167                 CL_ExpandCSQCEntities(entnum);
1168
1169         ent = &cl_csqcentities[entnum];
1170
1171         if(prog->argc > 4)
1172                 col = PRVM_G_FLOAT(OFS_PARM4);
1173         else
1174                 col = ent->state_current.glowcolor;
1175
1176         switch(i)
1177         {
1178         case TE_LIGHTNING1:
1179                 CSQC_ParseBeam(entnum, start, end, cl.model_bolt, true);
1180                 break;
1181         case TE_LIGHTNING2:
1182                 CSQC_ParseBeam(entnum, start, end, cl.model_bolt2, true);
1183                 break;
1184         case TE_LIGHTNING3:
1185                 CSQC_ParseBeam(entnum, start, end, cl.model_bolt3, false);
1186                 break;
1187         case TE_BEAM:
1188                 CSQC_ParseBeam(entnum, start, end, cl.model_beam, false);
1189                 break;
1190         default:
1191                 CL_RocketTrail(start, end, i-CSQC_TRAILSTART, col, ent);
1192                 break;
1193         }
1194 }
1195
1196 //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
1197 void VM_CL_pointparticles (void)
1198 {
1199         int                     i, n;
1200         float           *f, *v;
1201         if(prog->argc < 2)
1202                 VM_SAFEPARMCOUNT(2, VM_CL_pointparticles);
1203         i = PRVM_G_FLOAT(OFS_PARM0);
1204         f = PRVM_G_VECTOR(OFS_PARM1);
1205         if(prog->argc >= 4)
1206         {
1207                 v = PRVM_G_VECTOR(OFS_PARM2);
1208                 n = PRVM_G_FLOAT(OFS_PARM3);
1209         }
1210         else
1211         {
1212                 v = vec3_origin;
1213                 n = 15;
1214         }
1215
1216         if(i >= particleeffects_num)
1217                 return;
1218
1219         switch(i)
1220         {
1221         case TE_SPIKE:
1222         case TE_SPIKEQUAD:
1223         case TE_GUNSHOT:
1224         case TE_GUNSHOTQUAD:
1225                 CL_SparkShower(f, v, 15, 1, 0);
1226                 CL_Smoke(f, v, 15, 0);
1227                 if (cl_particles_bulletimpacts.integer)
1228                         CL_BulletMark(f);
1229                 break;
1230         case TE_SUPERSPIKE:
1231         case TE_SUPERSPIKEQUAD:
1232                 CL_SparkShower(f, v, 30, 1, 0);
1233                 CL_Smoke(f, v, 30, 0);
1234                 if (cl_particles_bulletimpacts.integer)
1235                         CL_BulletMark(f);
1236                 break;
1237         case TE_EXPLOSION:
1238         case TE_EXPLOSIONQUAD:
1239         case TE_TEI_BIGEXPLOSION:
1240                 CL_ParticleExplosion(f);
1241                 break;
1242         case TE_TAREXPLOSION:
1243                 CL_BlobExplosion(f);
1244                 break;
1245         case TE_WIZSPIKE:
1246                 CL_RunParticleEffect(f, v, 20, 30);
1247                 break;
1248         case TE_KNIGHTSPIKE:
1249                 CL_RunParticleEffect(f, v, 226, 20);
1250                 break;
1251         case TE_LAVASPLASH:
1252                 CL_LavaSplash(f);
1253                 break;
1254         case TE_TELEPORT:
1255                 CL_TeleportSplash(f);
1256                 break;
1257         case TE_EXPLOSION2:
1258         case TE_EXPLOSION3:
1259         case TE_EXPLOSIONRGB:
1260                 CL_ParticleExplosion2(f, v[0], v[1]);
1261                 break;
1262         case TE_BLOOD:
1263                 CL_BloodPuff(f, v, n);
1264                 break;
1265         case TE_SPARK:
1266                 CL_SparkShower(f, v, n, 1, 0);
1267                 break;
1268         case TE_FLAMEJET:
1269                 CL_Flames(f, v, n);
1270                 break;
1271         case TE_PLASMABURN:
1272                 CL_PlasmaBurn(f);
1273                 break;
1274         case TE_TEI_G3:
1275                 CL_BeamParticle(f, v, 8, 1, 1, 1, 1, 1);
1276                 break;
1277         case TE_TEI_SMOKE:
1278                 CL_Tei_Smoke(f, v, n);
1279                 break;
1280         case TE_TEI_PLASMAHIT:
1281                 CL_Tei_PlasmaHit(f, v, n);
1282                 break;
1283         default:break;
1284         }
1285 }
1286
1287 //#338 void(string s) cprint (EXT_CSQC)
1288 void VM_CL_centerprint (void)
1289 {
1290         char s[VM_STRINGTEMP_LENGTH];
1291         if(prog->argc < 1)
1292                 VM_SAFEPARMCOUNT(1, VM_CL_centerprint);
1293         VM_VarString(0, s, sizeof(s));
1294         SCR_CenterPrint(s);
1295 }
1296
1297 //#342 string(float keynum) getkeybind (EXT_CSQC)
1298 void VM_CL_getkeybind (void)
1299 {
1300         int i;
1301
1302         VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1303         i = PRVM_G_FLOAT(OFS_PARM0);
1304         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Key_GetBind(i));
1305 }
1306
1307 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1308 void VM_CL_setcursormode (void)
1309 {
1310         VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1311         cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1312         cl_ignoremousemove = true;
1313 }
1314
1315 //#345 float(float framenum) getinputstate (EXT_CSQC)
1316 void VM_CL_getinputstate (void)
1317 {
1318         int i, frame;
1319         VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1320         frame = PRVM_G_FLOAT(OFS_PARM0);
1321         for (i = 0;i < cl.movement_numqueue;i++)
1322                 if (cl.movement_queue[i].sequence == frame)
1323                 {
1324                         VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
1325                         //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
1326                         VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
1327                         prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
1328                         if(cl.movement_queue[i].crouch)
1329                         {
1330                                 VectorCopy(cl_playercrouchmins, prog->globals.client->pmove_mins);
1331                                 VectorCopy(cl_playercrouchmaxs, prog->globals.client->pmove_maxs);
1332                         }
1333                         else
1334                         {
1335                                 VectorCopy(cl_playerstandmins, prog->globals.client->pmove_mins);
1336                                 VectorCopy(cl_playerstandmaxs, prog->globals.client->pmove_maxs);
1337                         }
1338                 }
1339 }
1340
1341 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1342 void VM_CL_setsensitivityscale (void)
1343 {
1344         VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1345         cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1346 }
1347
1348 //#347 void() runstandardplayerphysics (EXT_CSQC)
1349 void VM_CL_runplayerphysics (void)
1350 {
1351 }
1352
1353 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1354 void VM_CL_getplayerkey (void)
1355 {
1356         int                     i;
1357         char            t[128];
1358         const char      *c;
1359         char            *temp;
1360
1361         VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1362
1363         i = PRVM_G_FLOAT(OFS_PARM0);
1364         c = PRVM_G_STRING(OFS_PARM1);
1365         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1366         Sbar_SortFrags();
1367
1368         i = Sbar_GetPlayer(i);
1369         if(i < 0)
1370                 return;
1371
1372         t[0] = 0;
1373
1374         if(!strcasecmp(c, "name"))
1375                 strcpy(t, cl.scores[i].name);
1376         else
1377                 if(!strcasecmp(c, "frags"))
1378                         sprintf(t, "%i", cl.scores[i].frags);
1379 //      else
1380 //              if(!strcasecmp(c, "ping"))
1381 //                      sprintf(t, "%i", cl.scores[i].ping);
1382 //      else
1383 //              if(!strcasecmp(c, "entertime"))
1384 //                      sprintf(t, "%f", cl.scores[i].entertime);
1385         else
1386                 if(!strcasecmp(c, "colors"))
1387                         sprintf(t, "%i", cl.scores[i].colors);
1388         else
1389                 if(!strcasecmp(c, "topcolor"))
1390                         sprintf(t, "%i", cl.scores[i].colors & 0xf0);
1391         else
1392                 if(!strcasecmp(c, "bottomcolor"))
1393                         sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
1394         else
1395                 if(!strcasecmp(c, "viewentity"))
1396                         sprintf(t, "%i", i+1);
1397         if(!t[0])
1398                 return;
1399         temp = VM_GetTempString();
1400         strcpy(temp, t);
1401         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
1402 }
1403
1404 //#349 float() isdemo (EXT_CSQC)
1405 void VM_CL_isdemo (void)
1406 {
1407         PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1408 }
1409
1410 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1411 void VM_CL_setlistener (void)
1412 {
1413         VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1414         Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1415         csqc_usecsqclistener = true;    //use csqc listener at this frame
1416 }
1417
1418 //#352 void(string cmdname) registercommand (EXT_CSQC)
1419 void VM_CL_registercmd (void)
1420 {
1421         char *t;
1422         VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1423         if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1424         {
1425                 t = Z_Malloc(strlen(PRVM_G_STRING(OFS_PARM0))+1);
1426                 strcpy(t, PRVM_G_STRING(OFS_PARM0));
1427                 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1428         }
1429         else
1430                 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1431
1432 }
1433
1434 //#354 float() playernum (EXT_CSQC)
1435 void VM_CL_playernum (void)
1436 {
1437         int i, k;
1438
1439         VM_SAFEPARMCOUNT(0, VM_CL_playernum);
1440
1441         for(i=k=0 ; i<cl.maxclients ; i++)
1442                 if(cl.scores[i].name[0])
1443                         k++;
1444         PRVM_G_FLOAT(OFS_RETURN) = k;
1445 }
1446
1447 //#355 float() cl_onground (EXT_CSQC)
1448 void VM_CL_onground (void)
1449 {
1450         PRVM_G_FLOAT(OFS_RETURN) = csqc_onground;
1451 }
1452
1453 //#360 float() readbyte (EXT_CSQC)
1454 void VM_CL_ReadByte (void)
1455 {
1456         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1457 }
1458
1459 //#361 float() readchar (EXT_CSQC)
1460 void VM_CL_ReadChar (void)
1461 {
1462         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1463 }
1464
1465 //#362 float() readshort (EXT_CSQC)
1466 void VM_CL_ReadShort (void)
1467 {
1468         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1469 }
1470
1471 //#363 float() readlong (EXT_CSQC)
1472 void VM_CL_ReadLong (void)
1473 {
1474         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1475 }
1476
1477 //#364 float() readcoord (EXT_CSQC)
1478 void VM_CL_ReadCoord (void)
1479 {
1480         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1481 }
1482
1483 //#365 float() readangle (EXT_CSQC)
1484 void VM_CL_ReadAngle (void)
1485 {
1486         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1487 }
1488
1489 //#366 string() readstring (EXT_CSQC)
1490 void VM_CL_ReadString (void)
1491 {
1492         char *t, *s;
1493         t = VM_GetTempString();
1494         s = MSG_ReadString();
1495         PRVM_G_INT(OFS_RETURN) = 0;
1496         if(s)
1497         {
1498                 strcpy(t, s);
1499                 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1500         }
1501 }
1502
1503 //#367 float() readfloat (EXT_CSQC)
1504 void VM_CL_ReadFloat (void)
1505 {
1506         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1507 }
1508
1509 //=================================================================//
1510
1511 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1512 void VM_CL_effect (void)
1513 {
1514         VM_SAFEPARMCOUNT(5, VM_CL_effect);
1515         CL_Effect(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1516 }
1517
1518 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1519 void VM_CL_te_blood (void)
1520 {
1521         float   *pos;
1522         vec3_t  pos2;
1523         VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1524         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1525                 return;
1526         pos = PRVM_G_VECTOR(OFS_PARM0);
1527         CL_FindNonSolidLocation(pos, pos2, 4);
1528         CL_BloodPuff(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1529 }
1530
1531 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1532 void VM_CL_te_bloodshower (void)
1533 {
1534         VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1535         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1536                 return;
1537         CL_BloodShower(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3));
1538 }
1539
1540 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1541 void VM_CL_te_explosionrgb (void)
1542 {
1543         float           *pos;
1544         vec3_t          pos2;
1545         matrix4x4_t     tempmatrix;
1546         VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1547         pos = PRVM_G_VECTOR(OFS_PARM0);
1548         CL_FindNonSolidLocation(pos, pos2, 10);
1549         CL_ParticleExplosion(pos2);
1550         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1551         CL_AllocDlight(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1552 }
1553
1554 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1555 void VM_CL_te_particlecube (void)
1556 {
1557         VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1558         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1559                 return;
1560         CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
1561 }
1562
1563 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1564 void VM_CL_te_particlerain (void)
1565 {
1566         VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1567         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1568                 return;
1569         CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 0);
1570 }
1571
1572 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1573 void VM_CL_te_particlesnow (void)
1574 {
1575         VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1576         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1577                 return;
1578         CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 1);
1579 }
1580
1581 // #411 void(vector org, vector vel, float howmany) te_spark
1582 void VM_CL_te_spark (void)
1583 {
1584         float           *pos;
1585         vec3_t          pos2;
1586         VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1587
1588         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1589                 return;
1590         pos = PRVM_G_VECTOR(OFS_PARM0);
1591         CL_FindNonSolidLocation(pos, pos2, 4);
1592         CL_SparkShower(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), 1, 0);
1593 }
1594
1595 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1596 void VM_CL_te_gunshotquad (void)
1597 {
1598         float           *pos;
1599         vec3_t          pos2;
1600         matrix4x4_t     tempmatrix;
1601         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1602
1603         pos = PRVM_G_VECTOR(OFS_PARM0);
1604         CL_FindNonSolidLocation(pos, pos2, 4);
1605         CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
1606         CL_Smoke(pos2, vec3_origin, 15, 0);
1607         CL_BulletMark(pos2);
1608         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1609         CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1610 }
1611
1612 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1613 void VM_CL_te_spikequad (void)
1614 {
1615         float           *pos;
1616         vec3_t          pos2;
1617         matrix4x4_t     tempmatrix;
1618         int                     rnd;
1619         VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1620
1621         pos = PRVM_G_VECTOR(OFS_PARM0);
1622         CL_FindNonSolidLocation(pos, pos2, 4);
1623         if (cl_particles_bulletimpacts.integer)
1624         {
1625                 CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
1626                 CL_Smoke(pos2, vec3_origin, 15, 0);
1627                 CL_BulletMark(pos2);
1628         }
1629         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1630         CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1631         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1632         else
1633         {
1634                 rnd = rand() & 3;
1635                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1636                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1637                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1638         }
1639 }
1640
1641 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1642 void VM_CL_te_superspikequad (void)
1643 {
1644         float           *pos;
1645         vec3_t          pos2;
1646         matrix4x4_t     tempmatrix;
1647         int                     rnd;
1648         VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1649
1650         pos = PRVM_G_VECTOR(OFS_PARM0);
1651         CL_FindNonSolidLocation(pos, pos2, 4);
1652         if (cl_particles_bulletimpacts.integer)
1653         {
1654                 CL_SparkShower(pos2, vec3_origin, 30, 1, 0);
1655                 CL_Smoke(pos2, vec3_origin, 30, 0);
1656                 CL_BulletMark(pos2);
1657         }
1658         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1659         CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1660         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1661         else
1662         {
1663                 rnd = rand() & 3;
1664                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1665                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1666                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1667         }
1668 }
1669
1670 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1671 void VM_CL_te_explosionquad (void)
1672 {
1673         float           *pos;
1674         vec3_t          pos2;
1675         matrix4x4_t     tempmatrix;
1676         VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1677
1678         pos = PRVM_G_VECTOR(OFS_PARM0);
1679         CL_FindNonSolidLocation(pos, pos2, 10);
1680         CL_ParticleExplosion(pos2);
1681         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1682         CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1683         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1684 }
1685
1686 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1687 void VM_CL_te_smallflash (void)
1688 {
1689         float           *pos;
1690         vec3_t          pos2;
1691         matrix4x4_t     tempmatrix;
1692         VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1693
1694         pos = PRVM_G_VECTOR(OFS_PARM0);
1695         CL_FindNonSolidLocation(pos, pos2, 10);
1696         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1697         CL_AllocDlight(NULL, &tempmatrix, 200, 2, 2, 2, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1698 }
1699
1700 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1701 void VM_CL_te_customflash (void)
1702 {
1703         float           *pos;
1704         vec3_t          pos2;
1705         matrix4x4_t     tempmatrix;
1706         VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1707
1708         pos = PRVM_G_VECTOR(OFS_PARM0);
1709         CL_FindNonSolidLocation(pos, pos2, 4);
1710         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1711         CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1712 }
1713
1714 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1715 void VM_CL_te_gunshot (void)
1716 {
1717         float           *pos;
1718         vec3_t          pos2;
1719         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1720
1721         pos = PRVM_G_VECTOR(OFS_PARM0);
1722         CL_FindNonSolidLocation(pos, pos2, 4);
1723         CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
1724         CL_Smoke(pos2, vec3_origin, 15, 0);
1725         CL_BulletMark(pos2);
1726 }
1727
1728 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1729 void VM_CL_te_spike (void)
1730 {
1731         float           *pos;
1732         vec3_t          pos2;
1733         int                     rnd;
1734         VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1735
1736         pos = PRVM_G_VECTOR(OFS_PARM0);
1737         CL_FindNonSolidLocation(pos, pos2, 4);
1738         if (cl_particles_bulletimpacts.integer)
1739         {
1740                 CL_SparkShower(pos2, vec3_origin, 15, 1, 0);
1741                 CL_Smoke(pos2, vec3_origin, 15, 0);
1742                 CL_BulletMark(pos2);
1743         }
1744         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1745         else
1746         {
1747                 rnd = rand() & 3;
1748                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1749                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1750                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1751         }
1752 }
1753
1754 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1755 void VM_CL_te_superspike (void)
1756 {
1757         float           *pos;
1758         vec3_t          pos2;
1759         int                     rnd;
1760         VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1761
1762         pos = PRVM_G_VECTOR(OFS_PARM0);
1763         CL_FindNonSolidLocation(pos, pos2, 4);
1764         if (cl_particles_bulletimpacts.integer)
1765         {
1766                 CL_SparkShower(pos2, vec3_origin, 30, 1, 0);
1767                 CL_Smoke(pos2, vec3_origin, 30, 0);
1768                 CL_BulletMark(pos2);
1769         }
1770         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1771         else
1772         {
1773                 rnd = rand() & 3;
1774                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1775                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1776                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1777         }
1778 }
1779
1780 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1781 void VM_CL_te_explosion (void)
1782 {
1783         float           *pos;
1784         vec3_t          pos2;
1785         matrix4x4_t     tempmatrix;
1786         VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1787
1788         pos = PRVM_G_VECTOR(OFS_PARM0);
1789         CL_FindNonSolidLocation(pos, pos2, 10);
1790         CL_ParticleExplosion(pos2);
1791         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1792         CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1793         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1794 }
1795
1796 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1797 void VM_CL_te_tarexplosion (void)
1798 {
1799         float           *pos;
1800         vec3_t          pos2;
1801         matrix4x4_t     tempmatrix;
1802         VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1803
1804         pos = PRVM_G_VECTOR(OFS_PARM0);
1805         CL_FindNonSolidLocation(pos, pos2, 10);
1806         CL_BlobExplosion(pos2);
1807         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1808         CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1809         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1810 }
1811
1812 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1813 void VM_CL_te_wizspike (void)
1814 {
1815         float           *pos;
1816         vec3_t          pos2;
1817         matrix4x4_t     tempmatrix;
1818         VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1819
1820         pos = PRVM_G_VECTOR(OFS_PARM0);
1821         CL_FindNonSolidLocation(pos, pos2, 4);
1822         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1823         CL_AllocDlight(NULL, &tempmatrix, 100, 0.12f, 0.50f, 0.12f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1824         CL_RunParticleEffect(pos2, vec3_origin, 20, 30);
1825         S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1826 }
1827
1828 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1829 void VM_CL_te_knightspike (void)
1830 {
1831         float           *pos;
1832         vec3_t          pos2;
1833         matrix4x4_t     tempmatrix;
1834         VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1835
1836         pos = PRVM_G_VECTOR(OFS_PARM0);
1837         CL_FindNonSolidLocation(pos, pos2, 4);
1838         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1839         CL_AllocDlight(NULL, &tempmatrix, 100, 0.50f, 0.30f, 0.10f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1840         CL_RunParticleEffect(pos2, vec3_origin, 226, 20);
1841         S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1842 }
1843
1844 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1845 void VM_CL_te_lavasplash (void)
1846 {
1847         VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1848         CL_LavaSplash(PRVM_G_VECTOR(OFS_PARM0));
1849 }
1850
1851 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1852 void VM_CL_te_teleport (void)
1853 {
1854         float           *pos;
1855         matrix4x4_t     tempmatrix;
1856         VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1857
1858         pos = PRVM_G_VECTOR(OFS_PARM0);
1859         Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1860         CL_AllocDlight(NULL, &tempmatrix, 200, 1.0f, 1.0f, 1.0f, 600, 99.0f, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1861         CL_TeleportSplash(pos);
1862 }
1863
1864 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1865 void VM_CL_te_explosion2 (void)
1866 {
1867         float           *pos;
1868         vec3_t          pos2, color;
1869         matrix4x4_t     tempmatrix;
1870         int                     colorStart, colorLength;
1871         unsigned char           *tempcolor;
1872         VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1873
1874         pos = PRVM_G_VECTOR(OFS_PARM0);
1875         colorStart = PRVM_G_FLOAT(OFS_PARM1);
1876         colorLength = PRVM_G_FLOAT(OFS_PARM2);
1877         CL_FindNonSolidLocation(pos, pos2, 10);
1878         CL_ParticleExplosion2(pos2, colorStart, colorLength);
1879         tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
1880         color[0] = tempcolor[0] * (2.0f / 255.0f);
1881         color[1] = tempcolor[1] * (2.0f / 255.0f);
1882         color[2] = tempcolor[2] * (2.0f / 255.0f);
1883         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1884         CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1885         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1886 }
1887
1888
1889 static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning)
1890 {
1891         beam_t  *b;
1892         int             i;
1893         extern entity_t *cl_csqcentities;
1894         extern int cl_max_csqcentities;
1895
1896         if (ent >= cl_max_csqcentities)
1897                 CL_ExpandCSQCEntities(ent);
1898
1899         // override any beam with the same entity
1900         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1901         {
1902                 if (b->entity == ent && ent)
1903                 {
1904                         //b->entity = ent;
1905                         b->lightning = lightning;
1906                         b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1907                         b->model = m;
1908                         b->endtime = cl.time + 0.2;
1909                         VectorCopy (start, b->start);
1910                         VectorCopy (end, b->end);
1911                         return;
1912                 }
1913         }
1914
1915         // find a free beam
1916         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1917         {
1918                 if (!b->model || b->endtime < cl.time)
1919                 {
1920                         b->entity = ent;
1921                         b->lightning = lightning;
1922                         b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1923                         b->model = m;
1924                         b->endtime = cl.time + 0.2;
1925                         VectorCopy (start, b->start);
1926                         VectorCopy (end, b->end);
1927                         return;
1928                 }
1929         }
1930         Con_Print("beam list overflow!\n");
1931 }
1932
1933 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1934 void VM_CL_te_lightning1 (void)
1935 {
1936         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1937         VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1938 }
1939
1940 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1941 void VM_CL_te_lightning2 (void)
1942 {
1943         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1944         VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1945 }
1946
1947 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1948 void VM_CL_te_lightning3 (void)
1949 {
1950         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1951         VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1952 }
1953
1954 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1955 void VM_CL_te_beam (void)
1956 {
1957         VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1958         VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1959 }
1960
1961 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1962 void VM_CL_te_plasmaburn (void)
1963 {
1964         float           *pos;
1965         vec3_t          pos2;
1966         matrix4x4_t     tempmatrix;
1967         VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1968
1969         pos = PRVM_G_VECTOR(OFS_PARM0);
1970         CL_FindNonSolidLocation(pos, pos2, 4);
1971         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1972         CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1973         CL_PlasmaBurn(pos2);
1974 }
1975
1976
1977 //====================================================================
1978 //DP_QC_GETSURFACE
1979
1980 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out);
1981 static msurface_t *cl_getsurface(prvm_edict_t *ed, int surfacenum)
1982 {
1983         int modelindex;
1984         model_t *model = NULL;
1985         if (!ed || ed->priv.server->free)
1986                 return NULL;
1987         modelindex = ed->fields.client->modelindex;
1988         if(!modelindex)
1989                 return NULL;
1990         if(modelindex<0)
1991         {
1992                 modelindex = -(modelindex+1);
1993                 if(modelindex < MAX_MODELS)
1994                         model = cl.csqc_model_precache[modelindex];
1995         }
1996         else
1997         {
1998                 if(modelindex < MAX_MODELS)
1999                         model = cl.model_precache[modelindex];
2000         }
2001         if(!model)
2002                 return NULL;
2003         if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2004                 return NULL;
2005         return model->data_surfaces + surfacenum + model->firstmodelsurface;
2006 }
2007
2008 // #434 float(entity e, float s) getsurfacenumpoints
2009 void VM_CL_getsurfacenumpoints(void)
2010 {
2011         msurface_t *surface;
2012         // return 0 if no such surface
2013         if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2014         {
2015                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2016                 return;
2017         }
2018
2019         // note: this (incorrectly) assumes it is a simple polygon
2020         PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2021 }
2022
2023 // #435 vector(entity e, float s, float n) getsurfacepoint
2024 void VM_CL_getsurfacepoint(void)
2025 {
2026         prvm_edict_t *ed;
2027         msurface_t *surface;
2028         int pointnum;
2029         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2030         ed = PRVM_G_EDICT(OFS_PARM0);
2031         if (!ed || ed->priv.server->free)
2032                 return;
2033         if (!(surface = cl_getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2034                 return;
2035         // note: this (incorrectly) assumes it is a simple polygon
2036         pointnum = PRVM_G_FLOAT(OFS_PARM2);
2037         if (pointnum < 0 || pointnum >= surface->num_vertices)
2038                 return;
2039         // FIXME: implement rotation/scaling
2040         VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2041 }
2042
2043 // #436 vector(entity e, float s) getsurfacenormal
2044 void VM_CL_getsurfacenormal(void)
2045 {
2046         msurface_t *surface;
2047         vec3_t normal;
2048         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2049         if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2050                 return;
2051         // FIXME: implement rotation/scaling
2052         // note: this (incorrectly) assumes it is a simple polygon
2053         // note: this only returns the first triangle, so it doesn't work very
2054         // well for curved surfaces or arbitrary meshes
2055         TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2056         VectorNormalize(normal);
2057         VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2058 }
2059
2060 // #437 string(entity e, float s) getsurfacetexture
2061 void VM_CL_getsurfacetexture(void)
2062 {
2063         msurface_t *surface;
2064         PRVM_G_INT(OFS_RETURN) = 0;
2065         if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2066                 return;
2067         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2068 }
2069
2070 // #438 float(entity e, vector p) getsurfacenearpoint
2071 void VM_CL_getsurfacenearpoint(void)
2072 {
2073         int surfacenum, best, modelindex;
2074         vec3_t clipped, p;
2075         vec_t dist, bestdist;
2076         prvm_edict_t *ed;
2077         model_t *model = NULL;
2078         msurface_t *surface;
2079         vec_t *point;
2080         PRVM_G_FLOAT(OFS_RETURN) = -1;
2081         ed = PRVM_G_EDICT(OFS_PARM0);
2082         point = PRVM_G_VECTOR(OFS_PARM1);
2083
2084         if (!ed || ed->priv.server->free)
2085                 return;
2086         modelindex = ed->fields.client->modelindex;
2087         if(!modelindex)
2088                 return;
2089         if(modelindex<0)
2090         {
2091                 modelindex = -(modelindex+1);
2092                 if(modelindex < MAX_MODELS)
2093                         model = cl.csqc_model_precache[modelindex];
2094         }
2095         else
2096                 if(modelindex < MAX_MODELS)
2097                         model = cl.model_precache[modelindex];
2098         if(!model)
2099                 return;
2100         if (!model->num_surfaces)
2101                 return;
2102
2103         // FIXME: implement rotation/scaling
2104         VectorSubtract(point, ed->fields.client->origin, p);
2105         best = -1;
2106         bestdist = 1000000000;
2107         for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2108         {
2109                 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2110                 // first see if the nearest point on the surface's box is closer than the previous match
2111                 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2112                 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2113                 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2114                 dist = VectorLength2(clipped);
2115                 if (dist < bestdist)
2116                 {
2117                         // it is, check the nearest point on the actual geometry
2118                         clippointtosurface(surface, p, clipped);
2119                         VectorSubtract(clipped, p, clipped);
2120                         dist += VectorLength2(clipped);
2121                         if (dist < bestdist)
2122                         {
2123                                 // that's closer too, store it as the best match
2124                                 best = surfacenum;
2125                                 bestdist = dist;
2126                         }
2127                 }
2128         }
2129         PRVM_G_FLOAT(OFS_RETURN) = best;
2130 }
2131
2132 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
2133 void VM_CL_getsurfaceclippedpoint(void)
2134 {
2135         prvm_edict_t *ed;
2136         msurface_t *surface;
2137         vec3_t p, out;
2138         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2139         ed = PRVM_G_EDICT(OFS_PARM0);
2140         if (!ed || ed->priv.server->free)
2141                 return;
2142         if (!(surface = cl_getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2143                 return;
2144         // FIXME: implement rotation/scaling
2145         VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
2146         clippointtosurface(surface, p, out);
2147         // FIXME: implement rotation/scaling
2148         VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2149 }
2150
2151 // #443 void(entity e, entity tagentity, string tagname) setattachment
2152 void VM_CL_setattachment (void)
2153 {
2154         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2155         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2156         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2157         prvm_eval_t *v;
2158         int modelindex;
2159         model_t *model;
2160
2161         if (e == prog->edicts)
2162                 PF_WARNING("setattachment: can not modify world entity\n");
2163         if (e->priv.server->free)
2164                 PF_WARNING("setattachment: can not modify free entity\n");
2165
2166         if (tagentity == NULL)
2167                 tagentity = prog->edicts;
2168
2169         v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_entity);
2170         if (v)
2171                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2172
2173         v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_index);
2174         if (v)
2175                 v->_float = 0;
2176         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2177         {
2178                 modelindex = (int)tagentity->fields.client->modelindex;
2179                 model = NULL;
2180
2181                 if(modelindex)
2182                 {
2183                         if(modelindex<0)
2184                         {
2185                                 modelindex = -(modelindex+1);
2186                                 if(modelindex < MAX_MODELS)
2187                                         model = cl.csqc_model_precache[modelindex];
2188                         }
2189                         else
2190                                 if(modelindex < MAX_MODELS)
2191                                         model = cl.model_precache[modelindex];
2192                 }
2193
2194                 if (model)
2195                 {
2196                         v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.client->skin, tagname);
2197                         if (v->_float == 0)
2198                                 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name);
2199                 }
2200                 else
2201                         Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity));
2202         }
2203 }
2204
2205 /////////////////////////////////////////
2206 // DP_MD3_TAGINFO extension coded by VorteX
2207
2208 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
2209 {
2210         int i;
2211         model_t *m;
2212
2213         i = e->fields.client->modelindex;
2214
2215         if(!i)
2216                 return -1;
2217         if(i<0)
2218         {
2219                 i = -(i+1);
2220                 if(i >= MAX_MODELS)
2221                         return -1;
2222                 m = cl.csqc_model_precache[i];
2223         }
2224         else
2225                 if(i >= MAX_MODELS)
2226                         return -1;
2227                 else
2228                         m = cl.model_precache[i];
2229
2230         return Mod_Alias_GetTagIndexForName(m, e->fields.client->skin, tagname);
2231 };
2232
2233 // Warnings/errors code:
2234 // 0 - normal (everything all-right)
2235 // 1 - world entity
2236 // 2 - free entity
2237 // 3 - null or non-precached model
2238 // 4 - no tags with requested index
2239 // 5 - runaway loop at attachment chain
2240 extern cvar_t cl_bob;
2241 extern cvar_t cl_bobcycle;
2242 extern cvar_t cl_bobup;
2243 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2244 {
2245         prvm_eval_t *val;
2246         int modelindex, reqframe, attachloop, i;
2247         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2248         prvm_edict_t *attachent;
2249         model_t *model;
2250
2251         *out = identitymatrix; // warnings and errors return identical matrix
2252
2253         if (ent == prog->edicts)
2254                 return 1;
2255         if (ent->priv.server->free)
2256                 return 2;
2257
2258         modelindex = (int)ent->fields.client->modelindex;
2259
2260         if(!modelindex)
2261                 return 3;
2262         if(modelindex<0)
2263         {
2264                 modelindex = -(modelindex+1);
2265                 if(modelindex >= MAX_MODELS)
2266                         return 3;
2267                 model = cl.csqc_model_precache[modelindex];
2268         }
2269         else
2270                 if(modelindex >= MAX_MODELS)
2271                         return 3;
2272                 else
2273                         model = cl.model_precache[modelindex];
2274
2275         if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2276                 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2277         else
2278                 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2279
2280         // get initial tag matrix
2281         if (tagindex)
2282         {
2283                 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2284                 if (ret)
2285                         return ret;
2286         }
2287         else
2288                 tagmatrix = identitymatrix;
2289
2290         if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict)
2291         { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2292                 attachloop = 0;
2293                 do
2294                 {
2295                         attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2296                         val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
2297
2298                         model = NULL;
2299                         i = attachent->fields.client->modelindex;
2300                         if(i<0)
2301                         {
2302                                 i = -(i+1);
2303                                 if(i < MAX_MODELS)
2304                                         model = cl.csqc_model_precache[i];
2305                         }
2306                         else
2307                                 if(i < MAX_MODELS)
2308                                         model = cl.model_precache[i];
2309
2310                         if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2311                                 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, val->_float - 1, &attachmatrix);
2312                         else
2313                                 attachmatrix = identitymatrix;
2314
2315                         // apply transformation by child entity matrix
2316                         val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2317                         if (val->_float == 0)
2318                                 val->_float = 1;
2319                         Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
2320                         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2321                         out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2322                         out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2323                         out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2324                         Matrix4x4_Copy(&tagmatrix, out);
2325
2326                         // finally transformate by matrix of tag on parent entity
2327                         Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2328                         out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
2329                         out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
2330                         out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
2331                         Matrix4x4_Copy(&tagmatrix, out);
2332
2333                         ent = attachent;
2334                         attachloop += 1;
2335                         if (attachloop > 255) // prevent runaway looping
2336                                 return 5;
2337                 }
2338                 while ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict);
2339         }
2340
2341         // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2342         val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2343         if (val->_float == 0)
2344                 val->_float = 1;
2345         // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2346         Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
2347         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2348         out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2349         out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2350         out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2351
2352         if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2353         {// RENDER_VIEWMODEL magic
2354                 Matrix4x4_Copy(&tagmatrix, out);
2355
2356                 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2357                 if (val->_float == 0)
2358                         val->_float = 1;
2359
2360                 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
2361                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2362                 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2363                 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2364                 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2365
2366                 /*
2367                 // Cl_bob, ported from rendering code
2368                 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2369                 {
2370                         double bob, cycle;
2371                         // LordHavoc: this code is *weird*, but not replacable (I think it
2372                         // should be done in QC on the server, but oh well, quake is quake)
2373                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2374                         // degrees (which allows lengthening or squishing the peak or valley)
2375                         cycle = sv.time/cl_bobcycle.value;
2376                         cycle -= (int)cycle;
2377                         if (cycle < cl_bobup.value)
2378                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2379                         else
2380                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2381                         // bob is proportional to velocity in the xy plane
2382                         // (don't count Z, or jumping messes it up)
2383                         bob = sqrt(ent->fields.client->velocity[0]*ent->fields.client->velocity[0] + ent->fields.client->velocity[1]*ent->fields.client->velocity[1])*cl_bob.value;
2384                         bob = bob*0.3 + bob*0.7*cycle;
2385                         out->m[2][3] += bound(-7, bob, 4);
2386                 }
2387                 */
2388         }
2389         return 0;
2390 }
2391
2392 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2393 void VM_CL_gettagindex (void)
2394 {
2395         prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2396         const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2397         int modelindex, tag_index;
2398
2399         if (ent == prog->edicts)
2400                 PF_WARNING("gettagindex: can't affect world entity\n");
2401         if (ent->priv.server->free)
2402                 PF_WARNING("gettagindex: can't affect free entity\n");
2403
2404         modelindex = (int)ent->fields.client->modelindex;
2405         if(modelindex < 0)
2406                 modelindex = -(modelindex+1);
2407         tag_index = 0;
2408         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2409                 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2410         else
2411         {
2412                 tag_index = CL_GetTagIndex(ent, tag_name);
2413                 if (tag_index == 0)
2414                         Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2415         }
2416         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2417 }
2418
2419 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2420 void VM_CL_gettaginfo (void)
2421 {
2422         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2423         int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2424         matrix4x4_t tag_matrix;
2425         int returncode;
2426
2427         returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2428         Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2429
2430         switch(returncode)
2431         {
2432                 case 1:
2433                         PF_WARNING("gettagindex: can't affect world entity\n");
2434                         break;
2435                 case 2:
2436                         PF_WARNING("gettagindex: can't affect free entity\n");
2437                         break;
2438                 case 3:
2439                         Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2440                         break;
2441                 case 4:
2442                         Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2443                         break;
2444                 case 5:
2445                         Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2446                         break;
2447         }
2448 }
2449
2450 //=================================================
2451 //[515]: here goes test/unfinished/etc.
2452
2453 //[515]: check if it is what it should be
2454 void VM_WasFreed (void)
2455 {
2456         prvm_edict_t    *e;
2457         VM_SAFEPARMCOUNT(1, VM_WasFreed);
2458
2459         e = PRVM_G_EDICT(OFS_PARM0);
2460         if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (*prog->time - e->priv.required->freetime) > 0.5 )))
2461                 PRVM_G_FLOAT(OFS_RETURN) = false;
2462         else
2463                 PRVM_G_FLOAT(OFS_RETURN) = true;
2464 }
2465
2466 void VM_CL_select_cube (void)
2467 {
2468         int             i;
2469         int             chain_of;
2470         float   *mins2, *maxs2;
2471         prvm_edict_t    *ent, *chain;
2472         vec3_t  mins1, maxs1;
2473
2474         VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
2475
2476         // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2477         if(!prog->flag & PRVM_FE_CHAIN)
2478                 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2479
2480         chain_of = PRVM_ED_FindField("chain")->ofs;
2481         chain = prog->edicts;
2482
2483         mins2 = PRVM_G_VECTOR(OFS_PARM0);
2484         maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2485
2486         ent = PRVM_NEXT_EDICT(prog->edicts);
2487         for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2488         {
2489                 if (ent->priv.required->free)
2490                         continue;
2491                 VectorCopy(ent->fields.client->origin, mins1);
2492                 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2493                 VectorAdd(mins1, ent->fields.client->mins, mins1);
2494                 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2495                         continue;
2496                 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2497                         continue;
2498                 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2499                 chain = ent;
2500         }
2501
2502         VM_RETURN_EDICT(chain);
2503 }
2504
2505 void VM_CL_select_super (void)
2506 {
2507 /*      int             i;
2508         int             chain_of;
2509         float   *v[8];
2510         prvm_edict_t    *ent, *chain;
2511         vec3_t  mins1, maxs1;
2512
2513         VM_SAFEPARMCOUNT(8, VM_findchain);
2514         for(i=0;i<8;i++)
2515                 v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
2516
2517         // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2518         if(!prog->flag & PRVM_FE_CHAIN)
2519                 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2520
2521         chain_of = PRVM_ED_FindField("chain")->ofs;
2522         chain = prog->edicts;
2523
2524         mins2 = PRVM_G_VECTOR(OFS_PARM0);
2525         maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2526
2527         ent = PRVM_NEXT_EDICT(prog->edicts);
2528         for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2529         {
2530                 if (ent->priv.required->free)
2531                         continue;
2532                 VectorCopy(ent->fields.client->origin, mins1);
2533                 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2534                 VectorAdd(mins1, ent->fields.client->mins, mins1);
2535                 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2536                         continue;
2537                 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2538                         continue;
2539                 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2540                 chain = ent;
2541         }
2542
2543         VM_RETURN_EDICT(chain);*/
2544 }
2545
2546 static int Is_Text_Color (char c, char t)
2547 {
2548         int a = 0;
2549         char c2 = c - (c & 128);
2550         char t2 = t - (t & 128);
2551
2552         if(c != '^' && c2 != '^')               return 0;
2553         if(t >= '0' && t <= '9')                a = 1;
2554         if(t2 >= '0' && t2 <= '9')              a = 1;
2555 /*      if(t >= 'A' && t <= 'Z')                a = 2;
2556         if(t2 >= 'A' && t2 <= 'Z')              a = 2;
2557
2558         if(a == 1 && scr_colortext.integer > 0)
2559                 return 1;
2560         if(a == 2 && scr_multifonts.integer > 0)
2561                 return 2;
2562 */
2563         return a;
2564 }
2565
2566 void VM_uncolorstring (void) //#170
2567 {
2568         const char      *in;
2569         char            *out;
2570         int                     k = 0, i = 0;
2571
2572         VM_SAFEPARMCOUNT(1, VM_uncolorstring);
2573         in = PRVM_G_STRING(OFS_PARM0);
2574         if(!in)
2575                 PRVM_ERROR ("VM_uncolorstring: %s: NULL\n", PRVM_NAME);
2576         VM_CheckEmptyString (in);
2577         out = VM_GetTempString();
2578
2579         while (in[k])
2580         {
2581                 if(in[k+1])
2582                 if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
2583                 {
2584                         k += 2;
2585                         continue;
2586                 }
2587                 out[i] = in[k];
2588                 ++k;
2589                 ++i;
2590         }
2591 }
2592
2593 void VM_CL_selecttraceline (void)
2594 {
2595         float   *v1, *v2;
2596         int             ent, ignore, csqcents;
2597
2598         v1 = PRVM_G_VECTOR(OFS_PARM0);
2599         v2 = PRVM_G_VECTOR(OFS_PARM1);
2600         ignore = PRVM_G_FLOAT(OFS_PARM2);
2601         csqcents = PRVM_G_FLOAT(OFS_PARM3);
2602         ent = 0;
2603
2604         if((csqcents && ignore > cl_num_csqcentities) || (!csqcents && ignore > cl_num_entities))
2605         {
2606                 Con_Printf("VM_CL_selecttraceline: out of entities\n");
2607                 return;
2608         }
2609         else
2610                 if(csqcents)
2611                         prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &prog->globals.client->trace_ent, &cl_csqcentities[ignore].render, csqcents);
2612                 else
2613                         prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl_entities[ignore].render, csqcents);
2614         PRVM_G_FLOAT(OFS_RETURN) = ent;
2615 }
2616
2617 void VM_charindex (void)
2618 {
2619         const char *s;
2620         s = PRVM_G_STRING(OFS_PARM0);
2621         if(!s)
2622                 return;
2623         if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
2624                 return;
2625         PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
2626 }
2627
2628 //#223 string(float c, ...) chr2str (FTE_STRINGS)
2629 void VM_chr2str (void)
2630 {
2631         char    *t;
2632         int             i;
2633         t = VM_GetTempString();
2634         for(i=0;i<prog->argc;i++)
2635                 t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
2636         t[i] = 0;
2637         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
2638 }
2639
2640 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2641 void VM_strncmp (void)
2642 {
2643         const char *s1, *s2;
2644         VM_SAFEPARMCOUNT(1, VM_strncmp);
2645         s1 = PRVM_G_STRING(OFS_PARM0);
2646         s2 = PRVM_G_STRING(OFS_PARM1);
2647         PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
2648 }
2649
2650 //============================================================================
2651 //============================================================================
2652
2653 prvm_builtin_t vm_cl_builtins[] = {
2654 0,  // to be consistent with the old vm
2655 VM_CL_makevectors,                      // #1 void(vector ang) makevectors
2656 VM_CL_setorigin,                        // #2 void(entity e, vector o) setorigin
2657 VM_CL_setmodel,                         // #3 void(entity e, string m) setmodel
2658 VM_CL_setsize,                          // #4 void(entity e, vector min, vector max) setsize
2659 0,
2660 VM_break,                                       // #6 void() break
2661 VM_random,                                      // #7 float() random
2662 VM_CL_sound,                            // #8 void(entity e, float chan, string samp) sound
2663 VM_normalize,                           // #9 vector(vector v) normalize
2664 VM_error,                                       // #10 void(string e) error
2665 VM_objerror,                            // #11 void(string e) objerror
2666 VM_vlen,                                        // #12 float(vector v) vlen
2667 VM_vectoyaw,                            // #13 float(vector v) vectoyaw
2668 VM_CL_spawn,                            // #14 entity() spawn
2669 VM_remove,                                      // #15 void(entity e) remove
2670 VM_CL_traceline,                        // #16 float(vector v1, vector v2, float tryents) traceline
2671 0,
2672 VM_find,                                        // #18 entity(entity start, .string fld, string match) find
2673 VM_CL_precache_sound,           // #19 void(string s) precache_sound
2674 VM_CL_precache_model,           // #20 void(string s) precache_model
2675 0,
2676 VM_CL_findradius,                       // #22 entity(vector org, float rad) findradius
2677 0,
2678 0,
2679 VM_dprint,                                      // #25 void(string s) dprint
2680 VM_ftos,                                        // #26 void(string s) ftos
2681 VM_vtos,                                        // #27 void(string s) vtos
2682 VM_coredump,                            // #28 void() coredump
2683 VM_traceon,                                     // #29 void() traceon
2684 VM_traceoff,                            // #30 void() traceoff
2685 VM_eprint,                                      // #31 void(entity e) eprint
2686 0,
2687 NULL,                                           // #33
2688 VM_CL_droptofloor,                      // #34 float() droptofloor
2689 VM_CL_lightstyle,                       // #35 void(float style, string value) lightstyle
2690 VM_rint,                                        // #36 float(float v) rint
2691 VM_floor,                                       // #37 float(float v) floor
2692 VM_ceil,                                        // #38 float(float v) ceil
2693 NULL,                                           // #39
2694 VM_CL_checkbottom,                      // #40 float(entity e) checkbottom
2695 VM_CL_pointcontents,            // #41 float(vector v) pointcontents
2696 NULL,                                           // #42
2697 VM_fabs,                                        // #43 float(float f) fabs
2698 0,
2699 VM_cvar,                                        // #45 float(string s) cvar
2700 VM_localcmd,                            // #46 void(string s) localcmd
2701 VM_nextent,                                     // #47 entity(entity e) nextent
2702 VM_CL_particle,                         // #48 void(vector o, vector d, float color, float count) particle
2703 VM_CL_changeyaw,                        // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
2704 NULL,                                           // #50
2705 VM_vectoangles,                         // #51 vector(vector v) vectoangles
2706 0,                      // #52 void(float to, float f) WriteByte
2707 0,                      // #53 void(float to, float f) WriteChar
2708 0,                      // #54 void(float to, float f) WriteShort
2709 0,                      // #55 void(float to, float f) WriteLong
2710 0,                      // #56 void(float to, float f) WriteCoord
2711 0,                      // #57 void(float to, float f) WriteAngle
2712 0,                      // #58 void(float to, string s) WriteString
2713 0,
2714 VM_sin,                                         // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2715 VM_cos,                                         // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2716 VM_sqrt,                                        // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2717 VM_CL_changepitch,                      // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
2718 VM_CL_tracetoss,                        // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2719 VM_etos,                                        // #65 string(entity ent) etos (DP_QC_ETOS)
2720 NULL,                                           // #66
2721 0,                                                              // #67
2722 0,                                                              // #68
2723 0,                                                              // #69
2724 0,                                                              // #70
2725 NULL,                                           // #71
2726 VM_cvar_set,                            // #72 void(string var, string val) cvar_set
2727 0,                                                              // #73
2728 VM_CL_ambientsound,                     // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2729 VM_CL_precache_model,           // #75 string(string s) precache_model2
2730 VM_CL_precache_sound,           // #76 string(string s) precache_sound2
2731 0,                                                              // #77
2732 VM_chr,                                         // #78
2733 NULL,                                           // #79
2734 NULL,                                           // #80
2735 VM_stof,                                        // #81 float(string s) stof (FRIK_FILE)
2736 NULL,                                           // #82
2737 NULL,                                           // #83
2738 NULL,                                           // #84
2739 NULL,                                           // #85
2740 NULL,                                           // #86
2741 NULL,                                           // #87
2742 NULL,                                           // #88
2743 NULL,                                           // #89
2744 VM_CL_tracebox,                         // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2745 VM_randomvec,                           // #91 vector() randomvec (DP_QC_RANDOMVEC)
2746 VM_CL_getlight,                         // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2747 PF_registercvar,                        // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2748 VM_min,                                         // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2749 VM_max,                                         // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2750 VM_bound,                                       // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2751 VM_pow,                                         // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2752 VM_findfloat,                           // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2753 VM_checkextension,                      // #99 float(string s) checkextension (the basis of the extension system)
2754 NULL,                                           // #100
2755 NULL,                                           // #101
2756 NULL,                                           // #102
2757 NULL,                                           // #103
2758 NULL,                                           // #104
2759 NULL,                                           // #105
2760 NULL,                                           // #106
2761 NULL,                                           // #107
2762 NULL,                                           // #108
2763 NULL,                                           // #109
2764 VM_fopen,                                       // #110 float(string filename, float mode) fopen (FRIK_FILE)
2765 VM_fclose,                                      // #111 void(float fhandle) fclose (FRIK_FILE)
2766 VM_fgets,                                       // #112 string(float fhandle) fgets (FRIK_FILE)
2767 VM_fputs,                                       // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2768 VM_strlen,                                      // #114 float(string s) strlen (FRIK_FILE)
2769 VM_strcat,                                      // #115 string(string s1, string s2) strcat (FRIK_FILE)
2770 VM_substring,                           // #116 string(string s, float start, float length) substring (FRIK_FILE)
2771 VM_stov,                                        // #117 vector(string) stov (FRIK_FILE)
2772 VM_strzone,                                     // #118 string(string s) strzone (FRIK_FILE)
2773 VM_strunzone,                           // #119 void(string s) strunzone (FRIK_FILE)
2774
2775 e10, e10, e10, e10, e10, e10, e10, e10,         // #120-199
2776 e10,    //#200-209
2777 0,      //#210
2778 0,      //#211
2779 0,      //#212
2780 0,      //#213
2781 0,      //#214
2782 0,      //#215
2783 0,      //#216
2784 0,      //#217
2785 VM_bitshift,                            //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2786 0,      //#219
2787 0,      //#220
2788 0,      //#221
2789 VM_charindex,                           //#222 float(string str, float ofs) str2chr (FTE_STRINGS)
2790 VM_chr2str,                                     //#223 string(float c, ...) chr2str (FTE_STRINGS)
2791 0,      //#224
2792 0,      //#225
2793 0,      //#226
2794 0,      //#227
2795 VM_strncmp,                                     //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2796 0,
2797 e10, e10, e10, e10, e10, e10, e10,      // #230-299
2798
2799 //======CSQC start=======//
2800 //3d world (buffer/buffering) operations
2801 VM_R_ClearScene,                        //#300 void() clearscene (EXT_CSQC)
2802 VM_R_AddEntities,                       //#301 void(float mask) addentities (EXT_CSQC)
2803 VM_R_AddEntity,                         //#302 void(entity ent) addentity (EXT_CSQC)
2804 VM_R_SetView,                           //#303 float(float property, ...) setproperty (EXT_CSQC)
2805 VM_R_RenderScene,                       //#304 void() renderscene (EXT_CSQC)
2806 VM_R_AddDynamicLight,           //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2807 VM_R_PolygonBegin,                      //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2808 VM_R_PolygonVertex,                     //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2809 VM_R_PolygonEnd,                        //#308 void() R_EndPolygon
2810 0,                      //#309
2811
2812 //maths stuff that uses the current view settings
2813 VM_CL_unproject,                        //#310 vector (vector v) cs_unproject (EXT_CSQC)
2814 VM_CL_project,                          //#311 vector (vector v) cs_project (EXT_CSQC)
2815 0,                      //#312
2816 0,                      //#313
2817 0,                      //#314
2818
2819 //2d (immediate) operations
2820 VM_drawline,                            //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2821 VM_iscachedpic,                         //#316 float(string name) iscachedpic (EXT_CSQC)
2822 VM_precache_pic,                        //#317 string(string name, float trywad) precache_pic (EXT_CSQC)
2823 VM_getimagesize,                        //#318 vector(string picname) draw_getimagesize (EXT_CSQC)
2824 VM_freepic,                                     //#319 void(string name) freepic (EXT_CSQC)
2825 VM_drawcharacter,                       //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
2826 VM_drawstring,                          //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
2827 VM_drawpic,                                     //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
2828 VM_drawfill,                            //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
2829 VM_drawsetcliparea,                     //#324 void(float x, float y, float width, float height) drawsetcliparea
2830 VM_drawresetcliparea,           //#325 void(void) drawresetcliparea
2831 0,                      //#326
2832 0,                      //#327
2833 0,                      //#328
2834 0,                      //#329
2835
2836 VM_CL_getstatf,                         //#330 float(float stnum) getstatf (EXT_CSQC)
2837 VM_CL_getstati,                         //#331 float(float stnum) getstati (EXT_CSQC)
2838 VM_CL_getstats,                         //#332 string(float firststnum) getstats (EXT_CSQC)
2839 VM_CL_setmodelindex,            //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2840 VM_CL_modelnameforindex,        //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2841 VM_CL_particleeffectnum,        //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2842 VM_CL_trailparticles,           //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2843 VM_CL_pointparticles,           //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
2844 VM_CL_centerprint,                      //#338 void(string s) cprint (EXT_CSQC)
2845 VM_print,                                       //#339 void(string s) print (EXT_CSQC)
2846 VM_keynumtostring,                      //#340 string(float keynum) keynumtostring (EXT_CSQC)
2847 VM_stringtokeynum,                      //#341 float(string keyname) stringtokeynum (EXT_CSQC)
2848 VM_CL_getkeybind,                       //#342 string(float keynum) getkeybind (EXT_CSQC)
2849 VM_CL_setcursormode,            //#343 void(float usecursor) setcursormode (EXT_CSQC)
2850 VM_getmousepos,                         //#344 vector() getmousepos (EXT_CSQC)
2851 VM_CL_getinputstate,            //#345 float(float framenum) getinputstate (EXT_CSQC)
2852 VM_CL_setsensitivityscale,      //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
2853 VM_CL_runplayerphysics,         //#347 void() runstandardplayerphysics (EXT_CSQC)
2854 VM_CL_getplayerkey,                     //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
2855 VM_CL_isdemo,                           //#349 float() isdemo (EXT_CSQC)
2856 VM_isserver,                            //#350 float() isserver (EXT_CSQC)
2857 VM_CL_setlistener,                      //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
2858 VM_CL_registercmd,                      //#352 void(string cmdname) registercommand (EXT_CSQC)
2859 VM_WasFreed,                            //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
2860 VM_CL_playernum,                        //#354 float() playernum
2861 VM_CL_onground,                         //#355 float() cl_onground (EXT_CSQC)
2862 VM_charindex,                           //#356 float(string s, float num) charindex
2863 VM_CL_selecttraceline,          //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline
2864 0,                      //#358
2865 0,                      //#359
2866 VM_CL_ReadByte,                         //#360 float() readbyte (EXT_CSQC)
2867 VM_CL_ReadChar,                         //#361 float() readchar (EXT_CSQC)
2868 VM_CL_ReadShort,                        //#362 float() readshort (EXT_CSQC)
2869 VM_CL_ReadLong,                         //#363 float() readlong (EXT_CSQC)
2870 VM_CL_ReadCoord,                        //#364 float() readcoord (EXT_CSQC)
2871 VM_CL_ReadAngle,                        //#365 float() readangle (EXT_CSQC)
2872 VM_CL_ReadString,                       //#366 string() readstring (EXT_CSQC)
2873 VM_CL_ReadFloat,                        //#367 float() readfloat (EXT_CSQC)
2874 0,                      //#368
2875 0,                      //#369
2876 0,                      //#370
2877 0,                      //#371
2878 0,                      //#372
2879 0,                      //#373
2880 0,                      //#374
2881 0,                      //#375
2882 0,                      //#376
2883 0,                      //#377
2884 0,                      //#378
2885 0,                      //#379
2886 0,                      //#380
2887 0,                      //#381
2888 0,                      //#382
2889 0,                      //#383
2890 0,                      //#384
2891 0,                      //#385
2892 0,                      //#386
2893 0,                      //#387
2894 0,                      //#388
2895 0,                      //#389
2896 0,                      //#390
2897 0,                      //#391
2898 0,                      //#392
2899 0,                      //#393
2900 0,                      //#394
2901 0,                      //#395
2902 0,                      //#396
2903 0,                      //#397
2904 0,                      //#398
2905 0,                      //#399
2906 //=========CSQC end========//
2907
2908 VM_copyentity,                                  // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2909 0,
2910 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2911 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2912 VM_CL_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2913 VM_CL_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2914 VM_CL_te_bloodshower,                   // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2915 VM_CL_te_explosionrgb,                  // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2916 VM_CL_te_particlecube,                  // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2917 VM_CL_te_particlerain,                  // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2918 VM_CL_te_particlesnow,                  // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2919 VM_CL_te_spark,                                 // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2920 VM_CL_te_gunshotquad,                   // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2921 VM_CL_te_spikequad,                             // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2922 VM_CL_te_superspikequad,                // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2923 VM_CL_te_explosionquad,                 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2924 VM_CL_te_smallflash,                    // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2925 VM_CL_te_customflash,                   // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2926 VM_CL_te_gunshot,                               // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2927 VM_CL_te_spike,                                 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2928 VM_CL_te_superspike,                    // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2929 VM_CL_te_explosion,                             // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2930 VM_CL_te_tarexplosion,                  // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2931 VM_CL_te_wizspike,                              // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2932 VM_CL_te_knightspike,                   // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2933 VM_CL_te_lavasplash,                    // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2934 VM_CL_te_teleport,                              // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2935 VM_CL_te_explosion2,                    // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2936 VM_CL_te_lightning1,                    // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2937 VM_CL_te_lightning2,                    // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2938 VM_CL_te_lightning3,                    // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2939 VM_CL_te_beam,                                  // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2940 VM_vectorvectors,                               // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2941 VM_CL_te_plasmaburn,                    // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2942 VM_CL_getsurfacenumpoints,              // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2943 VM_CL_getsurfacepoint,                  // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2944 VM_CL_getsurfacenormal,                 // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2945 VM_CL_getsurfacetexture,                // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2946 VM_CL_getsurfacenearpoint,              // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2947 VM_CL_getsurfaceclippedpoint,   // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2948 0,                                                                      // #440
2949 VM_tokenize,                            // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2950 VM_argv,                                        // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2951 VM_CL_setattachment,            // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2952 VM_search_begin,                        // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2953 VM_search_end,                          // #445 void(float handle) search_end (DP_FS_SEARCH)
2954 VM_search_getsize,                      // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2955 VM_search_getfilename,          // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2956 VM_cvar_string,                         // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2957 VM_findflags,                           // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2958 VM_findchainflags,                      // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2959 VM_CL_gettagindex,                      // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2960 VM_CL_gettaginfo,                       // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2961 0,                                                              // #453
2962 0,                                                              // #454
2963 0,                                                              // #455
2964 NULL,                                           // #456
2965 NULL,                                           // #457
2966 NULL,                                           // #458
2967 NULL,                                           // #459
2968 VM_buf_create,                          // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2969 VM_buf_del,                                     // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2970 VM_buf_getsize,                         // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2971 VM_buf_copy,                            // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2972 VM_buf_sort,                            // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2973 VM_buf_implode,                         // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2974 VM_bufstr_get,                          // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2975 VM_bufstr_set,                          // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2976 VM_bufstr_add,                          // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2977 VM_bufstr_free,                         // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2978 e10, e10, e10                   // #470-499 (LordHavoc)
2979 };
2980
2981 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2982
2983 void VM_CL_Cmd_Init(void)
2984 {
2985 }
2986
2987 void VM_CL_Cmd_Reset(void)
2988 {
2989 }
2990