21626ad48ec8e72062838ea02826443719c94d60
[xonotic/darkplaces.git] / clvm_cmds.c
1 #include "prvm_cmds.h"
2 #include "csprogs.h"
3 #include "cl_collision.h"
4 #include "r_shadow.h"
5
6 //============================================================================
7 // Client
8 //[515]: unsolved PROBLEMS
9 //- finish player physics code (cs_runplayerphysics)
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 sfx_t *S_FindName(const char *name);
20 void PF_registercvar (void);
21 int Sbar_GetPlayer (int index);
22 void Sbar_SortFrags (void);
23 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
24 void CSQC_RelinkAllEntities (int drawmask);
25 void CSQC_RelinkCSQCEntities (void);
26 char *Key_GetBind (int key);
27 model_t *CSQC_GetModelByIndex(int modelindex);
28 model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed);
29 void CL_LinkEdict(prvm_edict_t *ed);
30
31
32
33
34
35
36 // #1 void(vector ang) makevectors
37 void VM_CL_makevectors (void)
38 {
39         VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
40         AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
41 }
42
43 // #2 void(entity e, vector o) setorigin
44 void VM_CL_setorigin (void)
45 {
46         prvm_edict_t    *e;
47         float   *org;
48
49         e = PRVM_G_EDICT(OFS_PARM0);
50         if (e == prog->edicts)
51         {
52                 VM_Warning("setorigin: can not modify world entity\n");
53                 return;
54         }
55         if (e->priv.required->free)
56         {
57                 VM_Warning("setorigin: can not modify free entity\n");
58                 return;
59         }
60         org = PRVM_G_VECTOR(OFS_PARM1);
61         VectorCopy (org, e->fields.client->origin);
62         CL_LinkEdict(e);
63 }
64
65 // #3 void(entity e, string m) setmodel
66 void VM_CL_setmodel (void)
67 {
68         prvm_edict_t    *e;
69         const char              *m;
70         struct model_s  *mod;
71         int                             i;
72
73         VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
74
75         e = PRVM_G_EDICT(OFS_PARM0);
76         m = PRVM_G_STRING(OFS_PARM1);
77         for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
78         {
79                 if (!strcmp(cl.csqc_model_precache[i]->name, m))
80                 {
81                         e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
82                         e->fields.client->modelindex = -(i+1);
83                         return;
84                 }
85         }
86
87         for (i = 0;i < MAX_MODELS;i++)
88         {
89                 mod = cl.model_precache[i];
90                 if (mod && !strcmp(mod->name, m))
91                 {
92                         e->fields.client->model = PRVM_SetEngineString(mod->name);
93                         e->fields.client->modelindex = i;
94                         return;
95                 }
96         }
97
98         e->fields.client->modelindex = 0;
99         e->fields.client->model = 0;
100 }
101
102 // #4 void(entity e, vector min, vector max) setsize
103 void VM_CL_setsize (void)
104 {
105         prvm_edict_t    *e;
106         float                   *min, *max;
107         VM_SAFEPARMCOUNT(3, VM_CL_setsize);
108
109         e = PRVM_G_EDICT(OFS_PARM0);
110         if (e == prog->edicts)
111         {
112                 VM_Warning("setsize: can not modify world entity\n");
113                 return;
114         }
115         if (e->priv.server->free)
116         {
117                 VM_Warning("setsize: can not modify free entity\n");
118                 return;
119         }
120         min = PRVM_G_VECTOR(OFS_PARM1);
121         max = PRVM_G_VECTOR(OFS_PARM2);
122
123         VectorCopy (min, e->fields.client->mins);
124         VectorCopy (max, e->fields.client->maxs);
125         VectorSubtract (max, min, e->fields.client->size);
126
127         CL_LinkEdict(e);
128 }
129
130 // #8 void(entity e, float chan, string samp) sound
131 void VM_CL_sound (void)
132 {
133         const char                      *sample;
134         int                                     channel;
135         prvm_edict_t            *entity;
136         int                             volume;
137         float                           attenuation;
138
139         VM_SAFEPARMCOUNT(5, VM_CL_sound);
140
141         entity = PRVM_G_EDICT(OFS_PARM0);
142         channel = (int)PRVM_G_FLOAT(OFS_PARM1);
143         sample = PRVM_G_STRING(OFS_PARM2);
144         volume = (int)(PRVM_G_FLOAT(OFS_PARM3)*255.0f);
145         attenuation = PRVM_G_FLOAT(OFS_PARM4);
146
147         if (volume < 0 || volume > 255)
148         {
149                 VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
150                 return;
151         }
152
153         if (attenuation < 0 || attenuation > 4)
154         {
155                 VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
156                 return;
157         }
158
159         if (channel < 0 || channel > 7)
160         {
161                 VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
162                 return;
163         }
164
165         S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
166 }
167
168 // #14 entity() spawn
169 void VM_CL_spawn (void)
170 {
171         prvm_edict_t *ed;
172         ed = PRVM_ED_Alloc();
173         ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed);     //[515]: not needed any more ?
174         VM_RETURN_EDICT(ed);
175 }
176
177 // #16 float(vector v1, vector v2, float tryents) traceline
178 void VM_CL_traceline (void)
179 {
180         float   *v1, *v2;
181         trace_t trace;
182         int             ent;
183
184         v1 = PRVM_G_VECTOR(OFS_PARM0);
185         v2 = PRVM_G_VECTOR(OFS_PARM1);
186
187         trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false);
188
189         prog->globals.client->trace_allsolid = trace.allsolid;
190         prog->globals.client->trace_startsolid = trace.startsolid;
191         prog->globals.client->trace_fraction = trace.fraction;
192         prog->globals.client->trace_inwater = trace.inwater;
193         prog->globals.client->trace_inopen = trace.inopen;
194         VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
195         VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
196         prog->globals.client->trace_plane_dist =  trace.plane.dist;
197         if (ent)
198                 prog->globals.client->trace_ent = ent;
199         else
200                 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
201 }
202
203 // #19 void(string s) precache_sound
204 void VM_CL_precache_sound (void)
205 {
206         VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
207         S_PrecacheSound(PRVM_G_STRING(OFS_PARM0), true, false);
208 }
209
210 // #20 void(string s) precache_model
211 void VM_CL_precache_model (void)
212 {
213         const char      *name;
214         int                     i;
215         model_t         *m;
216
217         VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
218
219         name = PRVM_G_STRING(OFS_PARM0);
220         for (i = 1;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
221         {
222                 if(!strcmp(cl.csqc_model_precache[i]->name, name))
223                 {
224                         PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
225                         return;
226                 }
227         }
228         PRVM_G_FLOAT(OFS_RETURN) = 0;
229         m = Mod_ForName(name, false, false, false);
230         if(m && m->loaded)
231         {
232                 for (i = 1;i < MAX_MODELS;i++)
233                 {
234                         if (!cl.csqc_model_precache[i])
235                         {
236                                 cl.csqc_model_precache[i] = (model_t*)m;
237                                 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
238                                 return;
239                         }
240                 }
241                 VM_Warning("VM_CL_precache_model: no free models\n");
242                 return;
243         }
244         VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
245 }
246
247 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
248 {
249         prvm_edict_t    *ent;
250         int                             i, k;
251
252         ent = PRVM_NEXT_EDICT(prog->edicts);
253         for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
254         {
255                 if (ent->priv.required->free)
256                         continue;
257 //              VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
258 //              VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
259                 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
260                         list[k++] = ent;
261         }
262         return k;
263 }
264
265 // #22 entity(vector org, float rad) findradius
266 void VM_CL_findradius (void)
267 {
268         prvm_edict_t    *ent, *chain;
269         vec_t                   radius, radius2;
270         vec3_t                  org, eorg, mins, maxs;
271         int                             i, numtouchedicts;
272         prvm_edict_t    *touchedicts[MAX_EDICTS];
273
274         chain = (prvm_edict_t *)prog->edicts;
275
276         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
277         radius = PRVM_G_FLOAT(OFS_PARM1);
278         radius2 = radius * radius;
279
280         mins[0] = org[0] - (radius + 1);
281         mins[1] = org[1] - (radius + 1);
282         mins[2] = org[2] - (radius + 1);
283         maxs[0] = org[0] + (radius + 1);
284         maxs[1] = org[1] + (radius + 1);
285         maxs[2] = org[2] + (radius + 1);
286         numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
287         if (numtouchedicts > MAX_EDICTS)
288         {
289                 // this never happens   //[515]: for what then ?
290                 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
291                 numtouchedicts = MAX_EDICTS;
292         }
293         for (i = 0;i < numtouchedicts;i++)
294         {
295                 ent = touchedicts[i];
296                 // Quake did not return non-solid entities but darkplaces does
297                 // (note: this is the reason you can't blow up fallen zombies)
298                 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
299                         continue;
300                 // LordHavoc: compare against bounding box rather than center so it
301                 // doesn't miss large objects, and use DotProduct instead of Length
302                 // for a major speedup
303                 VectorSubtract(org, ent->fields.client->origin, eorg);
304                 if (sv_gameplayfix_findradiusdistancetobox.integer)
305                 {
306                         eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
307                         eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
308                         eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
309                 }
310                 else
311                         VectorMAMAM(1, eorg, 0.5f, ent->fields.client->mins, 0.5f, ent->fields.client->maxs, eorg);
312                 if (DotProduct(eorg, eorg) < radius2)
313                 {
314                         ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
315                         chain = ent;
316                 }
317         }
318
319         VM_RETURN_EDICT(chain);
320 }
321
322 // #34 float() droptofloor
323 void VM_CL_droptofloor (void)
324 {
325         prvm_edict_t            *ent;
326         vec3_t                          end;
327         trace_t                         trace;
328         int                                     i;
329
330         // assume failure if it returns early
331         PRVM_G_FLOAT(OFS_RETURN) = 0;
332
333         ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
334         if (ent == prog->edicts)
335         {
336                 VM_Warning("droptofloor: can not modify world entity\n");
337                 return;
338         }
339         if (ent->priv.server->free)
340         {
341                 VM_Warning("droptofloor: can not modify free entity\n");
342                 return;
343         }
344
345         VectorCopy (ent->fields.client->origin, end);
346         end[2] -= 256;
347
348         trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false);
349
350         if (trace.fraction != 1)
351         {
352                 VectorCopy (trace.endpos, ent->fields.client->origin);
353                 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
354 //              ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
355                 PRVM_G_FLOAT(OFS_RETURN) = 1;
356                 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
357 //              ent->priv.server->suspendedinairflag = true;
358         }
359 }
360
361 // #35 void(float style, string value) lightstyle
362 void VM_CL_lightstyle (void)
363 {
364         int                     i;
365         const char      *c;
366
367         VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
368
369         i = (int)PRVM_G_FLOAT(OFS_PARM0);
370         c = PRVM_G_STRING(OFS_PARM1);
371         if (i >= cl.max_lightstyle)
372         {
373                 VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
374                 return;
375         }
376         strlcpy (cl.lightstyle[i].map,  MSG_ReadString(), sizeof (cl.lightstyle[i].map));
377         cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
378         cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
379 }
380
381 // #40 float(entity e) checkbottom
382 void VM_CL_checkbottom (void)
383 {
384         static int              cs_yes, cs_no;
385         prvm_edict_t    *ent;
386         vec3_t                  mins, maxs, start, stop;
387         trace_t                 trace;
388         int                             x, y, hit;
389         float                   mid, bottom;
390
391         VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
392         ent = PRVM_G_EDICT(OFS_PARM0);
393         PRVM_G_FLOAT(OFS_RETURN) = 0;
394
395         VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
396         VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
397
398 // if all of the points under the corners are solid world, don't bother
399 // with the tougher checks
400 // the corners must be within 16 of the midpoint
401         start[2] = mins[2] - 1;
402         for     (x=0 ; x<=1 ; x++)
403                 for     (y=0 ; y<=1 ; y++)
404                 {
405                         start[0] = x ? maxs[0] : mins[0];
406                         start[1] = y ? maxs[1] : mins[1];
407                         if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
408                                 goto realcheck;
409                 }
410
411         cs_yes++;
412         PRVM_G_FLOAT(OFS_RETURN) = true;
413         return;         // we got out easy
414
415 realcheck:
416         cs_no++;
417 //
418 // check it for real...
419 //
420         start[2] = mins[2];
421
422 // the midpoint must be within 16 of the bottom
423         start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
424         start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
425         stop[2] = start[2] - 2*sv_stepheight.value;
426         trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
427
428         if (trace.fraction == 1.0)
429                 return;
430
431         mid = bottom = trace.endpos[2];
432
433 // the corners must be within 16 of the midpoint
434         for     (x=0 ; x<=1 ; x++)
435                 for     (y=0 ; y<=1 ; y++)
436                 {
437                         start[0] = stop[0] = x ? maxs[0] : mins[0];
438                         start[1] = stop[1] = y ? maxs[1] : mins[1];
439
440                         trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
441
442                         if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
443                                 bottom = trace.endpos[2];
444                         if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
445                                 return;
446                 }
447
448         cs_yes++;
449         PRVM_G_FLOAT(OFS_RETURN) = true;
450 }
451
452 // #41 float(vector v) pointcontents
453 void VM_CL_pointcontents (void)
454 {
455         VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
456         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
457 }
458
459 // #48 void(vector o, vector d, float color, float count) particle
460 void VM_CL_particle (void)
461 {
462         float   *org, *dir;
463         int             count;
464         unsigned char   color;
465         VM_SAFEPARMCOUNT(4, VM_CL_particle);
466
467         org = PRVM_G_VECTOR(OFS_PARM0);
468         dir = PRVM_G_VECTOR(OFS_PARM1);
469         color = (int)PRVM_G_FLOAT(OFS_PARM2);
470         count = (int)PRVM_G_FLOAT(OFS_PARM3);
471         CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
472 }
473
474 // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
475 void VM_CL_tracetoss (void)
476 {
477 /*      trace_t trace;
478         prvm_edict_t    *ent;
479         prvm_edict_t    *ignore;
480
481         ent = PRVM_G_EDICT(OFS_PARM0);
482         if (ent == prog->edicts)
483         {
484                 VM_Warning("tracetoss: can not use world entity\n");
485                 return;
486         }
487         ignore = PRVM_G_EDICT(OFS_PARM1);
488
489 //FIXME
490         trace = SV_Trace_Toss (ent, ignore);
491
492         prog->globals.server->trace_allsolid = trace.allsolid;
493         prog->globals.server->trace_startsolid = trace.startsolid;
494         prog->globals.server->trace_fraction = trace.fraction;
495         prog->globals.server->trace_inwater = trace.inwater;
496         prog->globals.server->trace_inopen = trace.inopen;
497         VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
498         VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
499         prog->globals.server->trace_plane_dist =  trace.plane.dist;
500         if (trace.ent)
501                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
502         else
503                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
504 */
505 }
506
507 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
508 void VM_CL_ambientsound (void)
509 {
510         float   *f;
511         sfx_t   *s;
512         VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
513         s = S_FindName(PRVM_G_STRING(OFS_PARM0));
514         f = PRVM_G_VECTOR(OFS_PARM1);
515         S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
516 }
517
518 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
519 void VM_CL_tracebox (void)
520 {
521         float   *v1, *v2, *m1, *m2;
522         trace_t trace;
523         int             ent;
524
525         v1 = PRVM_G_VECTOR(OFS_PARM0);
526         m1 = PRVM_G_VECTOR(OFS_PARM1);
527         m2 = PRVM_G_VECTOR(OFS_PARM2);
528         v2 = PRVM_G_VECTOR(OFS_PARM3);
529
530         trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false);
531
532         prog->globals.client->trace_allsolid = trace.allsolid;
533         prog->globals.client->trace_startsolid = trace.startsolid;
534         prog->globals.client->trace_fraction = trace.fraction;
535         prog->globals.client->trace_inwater = trace.inwater;
536         prog->globals.client->trace_inopen = trace.inopen;
537         VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
538         VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
539         prog->globals.client->trace_plane_dist =  trace.plane.dist;
540         if (ent)
541                 prog->globals.client->trace_ent = ent;
542         else
543                 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
544 }
545
546 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
547 void VM_CL_getlight (void)
548 {
549         vec3_t ambientcolor, diffusecolor, diffusenormal;
550         vec_t *p;
551
552         VM_SAFEPARMCOUNT(1, VM_CL_getlight);
553
554         p = PRVM_G_VECTOR(OFS_PARM0);
555         VectorClear(ambientcolor);
556         VectorClear(diffusecolor);
557         VectorClear(diffusenormal);
558         if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
559                 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
560         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
561 }
562
563
564 //============================================================================
565 //[515]: SCENE MANAGER builtins
566 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
567
568 matrix4x4_t csqc_listenermatrix;
569 qboolean csqc_usecsqclistener = false;//[515]: per-frame
570
571 static void CSQC_R_RecalcView (void)
572 {
573         extern matrix4x4_t viewmodelmatrix;
574         Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
575         Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], cl_viewmodel_scale.value);
576 }
577
578 void CL_RelinkLightFlashes(void);
579 //#300 void() clearscene (EXT_CSQC)
580 void VM_R_ClearScene (void)
581 {
582         VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
583         // clear renderable entity and light lists
584         r_refdef.numentities = 0;
585         r_refdef.numlights = 0;
586 }
587
588 //#301 void(float mask) addentities (EXT_CSQC)
589 extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
590 extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
591 void VM_R_AddEntities (void)
592 {
593         int                     i, drawmask;
594         prvm_edict_t *ed;
595         VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
596         drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
597         CSQC_RelinkAllEntities(drawmask);
598         CL_RelinkLightFlashes();
599
600         prog->globals.client->time = cl.time;
601         for(i=1;i<prog->num_edicts;i++)
602         {
603                 ed = &prog->edicts[i];
604                 if(ed->priv.required->free)
605                         continue;
606                 VectorAdd(ed->fields.client->origin, ed->fields.client->mins, ed->fields.client->absmin);
607                 VectorAdd(ed->fields.client->origin, ed->fields.client->maxs, ed->fields.client->absmax);
608                 CSQC_Think(ed);
609                 if(ed->priv.required->free)
610                         continue;
611                 // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
612                 CSQC_Predraw(ed);
613                 if(ed->priv.required->free)
614                         continue;
615                 if(!((int)ed->fields.client->drawmask & drawmask))
616                         continue;
617                 CSQC_AddRenderEdict(ed);
618         }
619 }
620
621 //#302 void(entity ent) addentity (EXT_CSQC)
622 void VM_R_AddEntity (void)
623 {
624         VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
625         CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
626 }
627
628 //#303 float(float property, ...) setproperty (EXT_CSQC)
629 void VM_R_SetView (void)
630 {
631         int             c;
632         float   *f;
633         float   k;
634
635         if(prog->argc < 2)
636                 VM_SAFEPARMCOUNT(2, VM_R_SetView);
637
638         c = (int)PRVM_G_FLOAT(OFS_PARM0);
639         f = PRVM_G_VECTOR(OFS_PARM1);
640         k = PRVM_G_FLOAT(OFS_PARM1);
641
642         switch(c)
643         {
644         case VF_MIN:                    r_view.x = (int)f[0];
645                                                         r_view.y = (int)f[1];
646                                                         break;
647         case VF_MIN_X:                  r_view.x = (int)k;
648                                                         break;
649         case VF_MIN_Y:                  r_view.y = (int)k;
650                                                         break;
651         case VF_SIZE:                   r_view.width = (int)f[0];
652                                                         r_view.height = (int)f[1];
653                                                         break;
654         case VF_SIZE_Y:                 r_view.width = (int)k;
655                                                         break;
656         case VF_SIZE_X:                 r_view.height = (int)k;
657                                                         break;
658         case VF_VIEWPORT:               r_view.x = (int)f[0];
659                                                         r_view.y = (int)f[1];
660                                                         r_view.z = 0;
661                                                         // TODO: make sure that view_z and view_depth are set properly even if csqc does not set them!
662                                                         f = PRVM_G_VECTOR(OFS_PARM2);
663                                                         r_view.width = (int)f[0];
664                                                         r_view.height = (int)f[1];
665                                                         r_view.depth = 1;
666                                                         break;
667         case VF_FOV:                    //r_refdef.fov_x = f[0]; // FIXME!
668                                                         //r_refdef.fov_y = f[1]; // FIXME!
669                                                         break;
670         case VF_FOVX:                   //r_refdef.fov_x = k; // FIXME!
671                                                         break;
672         case VF_FOVY:                   //r_refdef.fov_y = k; // FIXME!
673                                                         break;
674         case VF_ORIGIN:                 VectorCopy(f, csqc_origin);
675                                                         CSQC_R_RecalcView();
676                                                         break;
677         case VF_ORIGIN_X:               csqc_origin[0] = k;
678                                                         CSQC_R_RecalcView();
679                                                         break;
680         case VF_ORIGIN_Y:               csqc_origin[1] = k;
681                                                         CSQC_R_RecalcView();
682                                                         break;
683         case VF_ORIGIN_Z:               csqc_origin[2] = k;
684                                                         CSQC_R_RecalcView();
685                                                         break;
686         case VF_ANGLES:                 VectorCopy(f, csqc_angles);
687                                                         CSQC_R_RecalcView();
688                                                         break;
689         case VF_ANGLES_X:               csqc_angles[0] = k;
690                                                         CSQC_R_RecalcView();
691                                                         break;
692         case VF_ANGLES_Y:               csqc_angles[1] = k;
693                                                         CSQC_R_RecalcView();
694                                                         break;
695         case VF_ANGLES_Z:               csqc_angles[2] = k;
696                                                         CSQC_R_RecalcView();
697                                                         break;
698         case VF_DRAWWORLD:              cl.csqc_vidvars.drawworld = k;
699                                                         break;
700         case VF_DRAWENGINESBAR: cl.csqc_vidvars.drawenginesbar = k;
701                                                         break;
702         case VF_DRAWCROSSHAIR:  cl.csqc_vidvars.drawcrosshair = k;
703                                                         break;
704
705         case VF_CL_VIEWANGLES:  VectorCopy(f, cl.viewangles);
706                                                         break;
707         case VF_CL_VIEWANGLES_X:cl.viewangles[0] = k;
708                                                         break;
709         case VF_CL_VIEWANGLES_Y:cl.viewangles[1] = k;
710                                                         break;
711         case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
712                                                         break;
713
714         default:                                PRVM_G_FLOAT(OFS_RETURN) = 0;
715                                                         VM_Warning("VM_R_SetView : unknown parm %i\n", c);
716                                                         return;
717         }
718         PRVM_G_FLOAT(OFS_RETURN) = 1;
719 }
720
721 extern void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit);
722 //#304 void() renderscene (EXT_CSQC)
723 void VM_R_RenderScene (void) //#134
724 {
725         int i;
726         VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
727         // we need to update any RENDER_VIEWMODEL entities at this point because
728         // csqc supplies its own view matrix
729         for (i = 1;i < cl.num_entities;i++)
730         {
731                 if (cl.entities_active[i])
732                 {
733                         entity_t *ent = cl.entities + i;
734                         if ((ent->render.flags & RENDER_VIEWMODEL) || ent->state_current.tagentity)
735                                 CL_UpdateNetworkEntity(ent, 32);
736                 }
737         }
738         // and of course the engine viewmodel needs updating as well
739         CL_UpdateNetworkEntity(&cl.viewent, 32);
740         // now draw stuff!
741         R_RenderView();
742 }
743
744 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
745 void VM_R_AddDynamicLight (void)
746 {
747         float           *pos, *col;
748         matrix4x4_t     matrix;
749         VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
750
751         // if we've run out of dlights, just return
752         if (r_refdef.numlights >= MAX_DLIGHTS)
753                 return;
754
755         pos = PRVM_G_VECTOR(OFS_PARM0);
756         col = PRVM_G_VECTOR(OFS_PARM2);
757         Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
758         R_RTLight_Update(&r_refdef.lights[r_refdef.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
759 }
760
761 //============================================================================
762
763 //#310 vector (vector v) cs_unproject (EXT_CSQC)
764 void VM_CL_unproject (void)
765 {
766         float   *f;
767         vec3_t  temp;
768
769         VM_SAFEPARMCOUNT(1, VM_CL_unproject);
770         f = PRVM_G_VECTOR(OFS_PARM0);
771         VectorSet(temp, f[2], f[0] * f[2] * -r_view.frustum_x * 2.0 / r_view.width, f[1] * f[2] * -r_view.frustum_y * 2.0 / r_view.height);
772         Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
773 }
774
775 //#311 vector (vector v) cs_project (EXT_CSQC)
776 void VM_CL_project (void)
777 {
778         float   *f;
779         vec3_t  v;
780         matrix4x4_t m;
781
782         VM_SAFEPARMCOUNT(1, VM_CL_project);
783         f = PRVM_G_VECTOR(OFS_PARM0);
784         Matrix4x4_Invert_Simple(&m, &r_view.matrix);
785         Matrix4x4_Transform(&m, f, v);
786         VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_view.frustum_x*0.5*r_view.width, v[2]/v[0]/-r_view.frustum_y*r_view.height*0.5, v[0]);
787 }
788
789 //#330 float(float stnum) getstatf (EXT_CSQC)
790 void VM_CL_getstatf (void)
791 {
792         int i;
793         union
794         {
795                 float f;
796                 int l;
797         }dat;
798         VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
799         i = (int)PRVM_G_FLOAT(OFS_PARM0);
800         if(i < 0 || i >= MAX_CL_STATS)
801         {
802                 VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
803                 return;
804         }
805         dat.l = cl.stats[i];
806         PRVM_G_FLOAT(OFS_RETURN) =  dat.f;
807 }
808
809 //#331 float(float stnum) getstati (EXT_CSQC)
810 void VM_CL_getstati (void)
811 {
812         int i, index;
813         VM_SAFEPARMCOUNT(1, VM_CL_getstati);
814         index = (int)PRVM_G_FLOAT(OFS_PARM0);
815
816         if(index < 0 || index >= MAX_CL_STATS)
817         {
818                 VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
819                 return;
820         }
821         i = cl.stats[index];
822         PRVM_G_FLOAT(OFS_RETURN) = i;
823 }
824
825 //#332 string(float firststnum) getstats (EXT_CSQC)
826 void VM_CL_getstats (void)
827 {
828         int i;
829         char t[17];
830         VM_SAFEPARMCOUNT(1, VM_CL_getstats);
831         i = (int)PRVM_G_FLOAT(OFS_PARM0);
832         if(i < 0 || i > MAX_CL_STATS-4)
833         {
834                 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
835                 VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
836                 return;
837         }
838         strlcpy(t, (char*)&cl.stats[i], sizeof(t));
839         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
840 }
841
842 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
843 void VM_CL_setmodelindex (void)
844 {
845         int                             i;
846         prvm_edict_t    *t;
847         struct model_s  *model;
848
849         VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
850
851         t = PRVM_G_EDICT(OFS_PARM0);
852
853         i = (int)PRVM_G_FLOAT(OFS_PARM1);
854
855         t->fields.client->model = 0;
856         t->fields.client->modelindex = 0;
857
858         if (!i)
859                 return;
860
861         model = CSQC_GetModelByIndex(i);
862         if (!model)
863         {
864                 VM_Warning("VM_CL_setmodelindex: null model\n");
865                 return;
866         }
867         t->fields.client->model = PRVM_SetEngineString(model->name);
868         t->fields.client->modelindex = i;
869 }
870
871 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
872 void VM_CL_modelnameforindex (void)
873 {
874         model_t *model;
875
876         VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
877
878         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
879         model = CSQC_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
880         PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
881 }
882
883 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
884 void VM_CL_particleeffectnum (void)
885 {
886         int                     i;
887         VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
888         i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
889         if (i == 0)
890                 i = -1;
891         PRVM_G_FLOAT(OFS_RETURN) = i;
892 }
893
894 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
895 void VM_CL_trailparticles (void)
896 {
897         int                             i;
898         float                   *start, *end;
899         prvm_edict_t    *t;
900         VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
901
902         t = PRVM_G_EDICT(OFS_PARM0);
903         i               = (int)PRVM_G_FLOAT(OFS_PARM1);
904         start   = PRVM_G_VECTOR(OFS_PARM2);
905         end             = PRVM_G_VECTOR(OFS_PARM3);
906
907         CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, (int)PRVM_G_FLOAT(OFS_PARM4));
908 }
909
910 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
911 void VM_CL_pointparticles (void)
912 {
913         int                     i, n;
914         float           *f, *v;
915         VM_SAFEPARMCOUNT(4, VM_CL_pointparticles);
916         i = (int)PRVM_G_FLOAT(OFS_PARM0);
917         f = PRVM_G_VECTOR(OFS_PARM1);
918         v = PRVM_G_VECTOR(OFS_PARM2);
919         n = (int)PRVM_G_FLOAT(OFS_PARM3);
920         CL_ParticleEffect(i, n, f, f, v, v, NULL, 0);
921 }
922
923 //#338 void(string s) cprint (EXT_CSQC)
924 void VM_CL_centerprint (void)
925 {
926         char s[VM_STRINGTEMP_LENGTH];
927         if(prog->argc < 1)
928                 VM_SAFEPARMCOUNT(1, VM_CL_centerprint);
929         VM_VarString(0, s, sizeof(s));
930         SCR_CenterPrint(s);
931 }
932
933 //#342 string(float keynum) getkeybind (EXT_CSQC)
934 void VM_CL_getkeybind (void)
935 {
936         VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
937         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
938 }
939
940 //#343 void(float usecursor) setcursormode (EXT_CSQC)
941 void VM_CL_setcursormode (void)
942 {
943         VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
944         cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
945         cl_ignoremousemove = true;
946 }
947
948 //#345 float(float framenum) getinputstate (EXT_CSQC)
949 void VM_CL_getinputstate (void)
950 {
951         int i, frame;
952         VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
953         frame = (int)PRVM_G_FLOAT(OFS_PARM0);
954         for (i = 0;i < cl.movement_numqueue;i++)
955                 if (cl.movement_queue[i].sequence == frame)
956                 {
957                         VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
958                         //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
959                         VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
960                         prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
961                         if(cl.movement_queue[i].crouch)
962                         {
963                                 VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
964                                 VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
965                         }
966                         else
967                         {
968                                 VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
969                                 VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
970                         }
971                 }
972 }
973
974 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
975 void VM_CL_setsensitivityscale (void)
976 {
977         VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
978         cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
979 }
980
981 //#347 void() runstandardplayerphysics (EXT_CSQC)
982 void VM_CL_runplayerphysics (void)
983 {
984 }
985
986 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
987 void VM_CL_getplayerkey (void)
988 {
989         int                     i;
990         char            t[128];
991         const char      *c;
992
993         VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
994
995         i = (int)PRVM_G_FLOAT(OFS_PARM0);
996         c = PRVM_G_STRING(OFS_PARM1);
997         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
998         Sbar_SortFrags();
999
1000         i = Sbar_GetPlayer(i);
1001         if(i < 0)
1002                 return;
1003
1004         t[0] = 0;
1005
1006         if(!strcasecmp(c, "name"))
1007                 strlcpy(t, cl.scores[i].name, sizeof(t));
1008         else
1009                 if(!strcasecmp(c, "frags"))
1010                         sprintf(t, "%i", cl.scores[i].frags);
1011         else
1012                 if(!strcasecmp(c, "ping"))
1013                         sprintf(t, "%i", cl.scores[i].qw_ping);
1014         else
1015                 if(!strcasecmp(c, "entertime"))
1016                         sprintf(t, "%f", cl.scores[i].qw_entertime);
1017         else
1018                 if(!strcasecmp(c, "colors"))
1019                         sprintf(t, "%i", cl.scores[i].colors);
1020         else
1021                 if(!strcasecmp(c, "topcolor"))
1022                         sprintf(t, "%i", cl.scores[i].colors & 0xf0);
1023         else
1024                 if(!strcasecmp(c, "bottomcolor"))
1025                         sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
1026         else
1027                 if(!strcasecmp(c, "viewentity"))
1028                         sprintf(t, "%i", i+1);
1029         if(!t[0])
1030                 return;
1031         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1032 }
1033
1034 //#349 float() isdemo (EXT_CSQC)
1035 void VM_CL_isdemo (void)
1036 {
1037         PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1038 }
1039
1040 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1041 void VM_CL_setlistener (void)
1042 {
1043         VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1044         Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1045         csqc_usecsqclistener = true;    //use csqc listener at this frame
1046 }
1047
1048 //#352 void(string cmdname) registercommand (EXT_CSQC)
1049 void VM_CL_registercmd (void)
1050 {
1051         char *t;
1052         VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1053         if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1054         {
1055                 size_t alloclen;
1056
1057                 alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
1058                 t = (char *)Z_Malloc(alloclen);
1059                 memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
1060                 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1061         }
1062         else
1063                 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1064
1065 }
1066
1067 //#354 float() playernum (EXT_CSQC)
1068 void VM_CL_playernum (void)
1069 {
1070         int i, k;
1071
1072         VM_SAFEPARMCOUNT(0, VM_CL_playernum);
1073
1074         for(i=k=0 ; i<cl.maxclients ; i++)
1075                 if(cl.scores[i].name[0])
1076                         k++;
1077         PRVM_G_FLOAT(OFS_RETURN) = k;
1078 }
1079
1080 //#355 float() cl_onground (EXT_CSQC)
1081 void VM_CL_onground (void)
1082 {
1083         PRVM_G_FLOAT(OFS_RETURN) = cl.onground;
1084 }
1085
1086 //#360 float() readbyte (EXT_CSQC)
1087 void VM_CL_ReadByte (void)
1088 {
1089         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1090 }
1091
1092 //#361 float() readchar (EXT_CSQC)
1093 void VM_CL_ReadChar (void)
1094 {
1095         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1096 }
1097
1098 //#362 float() readshort (EXT_CSQC)
1099 void VM_CL_ReadShort (void)
1100 {
1101         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1102 }
1103
1104 //#363 float() readlong (EXT_CSQC)
1105 void VM_CL_ReadLong (void)
1106 {
1107         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1108 }
1109
1110 //#364 float() readcoord (EXT_CSQC)
1111 void VM_CL_ReadCoord (void)
1112 {
1113         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1114 }
1115
1116 //#365 float() readangle (EXT_CSQC)
1117 void VM_CL_ReadAngle (void)
1118 {
1119         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1120 }
1121
1122 //#366 string() readstring (EXT_CSQC)
1123 void VM_CL_ReadString (void)
1124 {
1125         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
1126 }
1127
1128 //#367 float() readfloat (EXT_CSQC)
1129 void VM_CL_ReadFloat (void)
1130 {
1131         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1132 }
1133
1134 //=================================================================//
1135
1136 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1137 void VM_CL_effect (void)
1138 {
1139         VM_SAFEPARMCOUNT(5, VM_CL_effect);
1140         CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1141 }
1142
1143 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1144 void VM_CL_te_blood (void)
1145 {
1146         float   *pos;
1147         vec3_t  pos2;
1148         VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1149         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1150                 return;
1151         pos = PRVM_G_VECTOR(OFS_PARM0);
1152         CL_FindNonSolidLocation(pos, pos2, 4);
1153         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1154 }
1155
1156 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1157 void VM_CL_te_bloodshower (void)
1158 {
1159         vec_t speed;
1160         vec3_t vel1, vel2;
1161         VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1162         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1163                 return;
1164         speed = PRVM_G_FLOAT(OFS_PARM2);
1165         vel1[0] = -speed;
1166         vel1[1] = -speed;
1167         vel1[2] = -speed;
1168         vel2[0] = speed;
1169         vel2[1] = speed;
1170         vel2[2] = speed;
1171         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1172 }
1173
1174 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1175 void VM_CL_te_explosionrgb (void)
1176 {
1177         float           *pos;
1178         vec3_t          pos2;
1179         matrix4x4_t     tempmatrix;
1180         VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1181         pos = PRVM_G_VECTOR(OFS_PARM0);
1182         CL_FindNonSolidLocation(pos, pos2, 10);
1183         CL_ParticleExplosion(pos2);
1184         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1185         CL_AllocLightFlash(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);
1186 }
1187
1188 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1189 void VM_CL_te_particlecube (void)
1190 {
1191         VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1192         CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
1193 }
1194
1195 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1196 void VM_CL_te_particlerain (void)
1197 {
1198         VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1199         CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
1200 }
1201
1202 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1203 void VM_CL_te_particlesnow (void)
1204 {
1205         VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1206         CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
1207 }
1208
1209 // #411 void(vector org, vector vel, float howmany) te_spark
1210 void VM_CL_te_spark (void)
1211 {
1212         float           *pos;
1213         vec3_t          pos2;
1214         VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1215
1216         pos = PRVM_G_VECTOR(OFS_PARM0);
1217         CL_FindNonSolidLocation(pos, pos2, 4);
1218         CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1219 }
1220
1221 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1222 void VM_CL_te_gunshotquad (void)
1223 {
1224         float           *pos;
1225         vec3_t          pos2;
1226         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1227
1228         pos = PRVM_G_VECTOR(OFS_PARM0);
1229         CL_FindNonSolidLocation(pos, pos2, 4);
1230         CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1231 }
1232
1233 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1234 void VM_CL_te_spikequad (void)
1235 {
1236         float           *pos;
1237         vec3_t          pos2;
1238         int                     rnd;
1239         VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1240
1241         pos = PRVM_G_VECTOR(OFS_PARM0);
1242         CL_FindNonSolidLocation(pos, pos2, 4);
1243         CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1244         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1245         else
1246         {
1247                 rnd = rand() & 3;
1248                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1249                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1250                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1251         }
1252 }
1253
1254 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1255 void VM_CL_te_superspikequad (void)
1256 {
1257         float           *pos;
1258         vec3_t          pos2;
1259         int                     rnd;
1260         VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1261
1262         pos = PRVM_G_VECTOR(OFS_PARM0);
1263         CL_FindNonSolidLocation(pos, pos2, 4);
1264         CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1265         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1266         else
1267         {
1268                 rnd = rand() & 3;
1269                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1270                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1271                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1272         }
1273 }
1274
1275 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1276 void VM_CL_te_explosionquad (void)
1277 {
1278         float           *pos;
1279         vec3_t          pos2;
1280         VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1281
1282         pos = PRVM_G_VECTOR(OFS_PARM0);
1283         CL_FindNonSolidLocation(pos, pos2, 10);
1284         CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1285         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1286 }
1287
1288 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1289 void VM_CL_te_smallflash (void)
1290 {
1291         float           *pos;
1292         vec3_t          pos2;
1293         VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1294
1295         pos = PRVM_G_VECTOR(OFS_PARM0);
1296         CL_FindNonSolidLocation(pos, pos2, 10);
1297         CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1298 }
1299
1300 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1301 void VM_CL_te_customflash (void)
1302 {
1303         float           *pos;
1304         vec3_t          pos2;
1305         matrix4x4_t     tempmatrix;
1306         VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1307
1308         pos = PRVM_G_VECTOR(OFS_PARM0);
1309         CL_FindNonSolidLocation(pos, pos2, 4);
1310         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1311         CL_AllocLightFlash(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);
1312 }
1313
1314 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1315 void VM_CL_te_gunshot (void)
1316 {
1317         float           *pos;
1318         vec3_t          pos2;
1319         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1320
1321         pos = PRVM_G_VECTOR(OFS_PARM0);
1322         CL_FindNonSolidLocation(pos, pos2, 4);
1323         CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1324 }
1325
1326 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1327 void VM_CL_te_spike (void)
1328 {
1329         float           *pos;
1330         vec3_t          pos2;
1331         int                     rnd;
1332         VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1333
1334         pos = PRVM_G_VECTOR(OFS_PARM0);
1335         CL_FindNonSolidLocation(pos, pos2, 4);
1336         CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1337         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1338         else
1339         {
1340                 rnd = rand() & 3;
1341                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1342                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1343                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1344         }
1345 }
1346
1347 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1348 void VM_CL_te_superspike (void)
1349 {
1350         float           *pos;
1351         vec3_t          pos2;
1352         int                     rnd;
1353         VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1354
1355         pos = PRVM_G_VECTOR(OFS_PARM0);
1356         CL_FindNonSolidLocation(pos, pos2, 4);
1357         CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1358         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1359         else
1360         {
1361                 rnd = rand() & 3;
1362                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1363                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1364                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1365         }
1366 }
1367
1368 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1369 void VM_CL_te_explosion (void)
1370 {
1371         float           *pos;
1372         vec3_t          pos2;
1373         VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1374
1375         pos = PRVM_G_VECTOR(OFS_PARM0);
1376         CL_FindNonSolidLocation(pos, pos2, 10);
1377         CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1378         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1379 }
1380
1381 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1382 void VM_CL_te_tarexplosion (void)
1383 {
1384         float           *pos;
1385         vec3_t          pos2;
1386         VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1387
1388         pos = PRVM_G_VECTOR(OFS_PARM0);
1389         CL_FindNonSolidLocation(pos, pos2, 10);
1390         CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1391         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1392 }
1393
1394 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1395 void VM_CL_te_wizspike (void)
1396 {
1397         float           *pos;
1398         vec3_t          pos2;
1399         VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1400
1401         pos = PRVM_G_VECTOR(OFS_PARM0);
1402         CL_FindNonSolidLocation(pos, pos2, 4);
1403         CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1404         S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1405 }
1406
1407 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1408 void VM_CL_te_knightspike (void)
1409 {
1410         float           *pos;
1411         vec3_t          pos2;
1412         VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1413
1414         pos = PRVM_G_VECTOR(OFS_PARM0);
1415         CL_FindNonSolidLocation(pos, pos2, 4);
1416         CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1417         S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1418 }
1419
1420 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1421 void VM_CL_te_lavasplash (void)
1422 {
1423         VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1424         CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1425 }
1426
1427 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1428 void VM_CL_te_teleport (void)
1429 {
1430         VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1431         CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1432 }
1433
1434 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1435 void VM_CL_te_explosion2 (void)
1436 {
1437         float           *pos;
1438         vec3_t          pos2, color;
1439         matrix4x4_t     tempmatrix;
1440         int                     colorStart, colorLength;
1441         unsigned char           *tempcolor;
1442         VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1443
1444         pos = PRVM_G_VECTOR(OFS_PARM0);
1445         colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1446         colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1447         CL_FindNonSolidLocation(pos, pos2, 10);
1448         CL_ParticleExplosion2(pos2, colorStart, colorLength);
1449         tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
1450         color[0] = tempcolor[0] * (2.0f / 255.0f);
1451         color[1] = tempcolor[1] * (2.0f / 255.0f);
1452         color[2] = tempcolor[2] * (2.0f / 255.0f);
1453         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1454         CL_AllocLightFlash(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);
1455         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1456 }
1457
1458
1459 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1460 void VM_CL_te_lightning1 (void)
1461 {
1462         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1463         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1464 }
1465
1466 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1467 void VM_CL_te_lightning2 (void)
1468 {
1469         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1470         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1471 }
1472
1473 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1474 void VM_CL_te_lightning3 (void)
1475 {
1476         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1477         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1478 }
1479
1480 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1481 void VM_CL_te_beam (void)
1482 {
1483         VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1484         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1485 }
1486
1487 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1488 void VM_CL_te_plasmaburn (void)
1489 {
1490         float           *pos;
1491         vec3_t          pos2;
1492         VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1493
1494         pos = PRVM_G_VECTOR(OFS_PARM0);
1495         CL_FindNonSolidLocation(pos, pos2, 4);
1496         CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1497 }
1498
1499
1500 //====================================================================
1501 //DP_QC_GETSURFACE
1502
1503 extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1504
1505 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
1506 {
1507         if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1508                 return NULL;
1509         return model->data_surfaces + surfacenum + model->firstmodelsurface;
1510 }
1511
1512 // #434 float(entity e, float s) getsurfacenumpoints
1513 void VM_CL_getsurfacenumpoints(void)
1514 {
1515         model_t *model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0));
1516         msurface_t *surface;
1517         // return 0 if no such surface
1518         if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1519         {
1520                 PRVM_G_FLOAT(OFS_RETURN) = 0;
1521                 return;
1522         }
1523
1524         // note: this (incorrectly) assumes it is a simple polygon
1525         PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1526 }
1527
1528 // #435 vector(entity e, float s, float n) getsurfacepoint
1529 void VM_CL_getsurfacepoint(void)
1530 {
1531         prvm_edict_t *ed;
1532         model_t *model;
1533         msurface_t *surface;
1534         int pointnum;
1535         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1536         ed = PRVM_G_EDICT(OFS_PARM0);
1537         if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1538                 return;
1539         // note: this (incorrectly) assumes it is a simple polygon
1540         pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1541         if (pointnum < 0 || pointnum >= surface->num_vertices)
1542                 return;
1543         // FIXME: implement rotation/scaling
1544         VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1545 }
1546
1547 // #436 vector(entity e, float s) getsurfacenormal
1548 void VM_CL_getsurfacenormal(void)
1549 {
1550         model_t *model;
1551         msurface_t *surface;
1552         vec3_t normal;
1553         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1554         if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1555                 return;
1556         // FIXME: implement rotation/scaling
1557         // note: this (incorrectly) assumes it is a simple polygon
1558         // note: this only returns the first triangle, so it doesn't work very
1559         // well for curved surfaces or arbitrary meshes
1560         TriangleNormal((model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 3, (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
1561         VectorNormalize(normal);
1562         VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1563 }
1564
1565 // #437 string(entity e, float s) getsurfacetexture
1566 void VM_CL_getsurfacetexture(void)
1567 {
1568         model_t *model;
1569         msurface_t *surface;
1570         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1571         if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1572                 return;
1573         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
1574 }
1575
1576 // #438 float(entity e, vector p) getsurfacenearpoint
1577 void VM_CL_getsurfacenearpoint(void)
1578 {
1579         int surfacenum, best;
1580         vec3_t clipped, p;
1581         vec_t dist, bestdist;
1582         prvm_edict_t *ed;
1583         model_t *model = NULL;
1584         msurface_t *surface;
1585         vec_t *point;
1586         PRVM_G_FLOAT(OFS_RETURN) = -1;
1587         ed = PRVM_G_EDICT(OFS_PARM0);
1588         if(!(model = CSQC_GetModelFromEntity(ed)) || !model->num_surfaces)
1589                 return;
1590
1591         // FIXME: implement rotation/scaling
1592         point = PRVM_G_VECTOR(OFS_PARM1);
1593         VectorSubtract(point, ed->fields.client->origin, p);
1594         best = -1;
1595         bestdist = 1000000000;
1596         for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1597         {
1598                 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1599                 // first see if the nearest point on the surface's box is closer than the previous match
1600                 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1601                 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1602                 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1603                 dist = VectorLength2(clipped);
1604                 if (dist < bestdist)
1605                 {
1606                         // it is, check the nearest point on the actual geometry
1607                         clippointtosurface(model, surface, p, clipped);
1608                         VectorSubtract(clipped, p, clipped);
1609                         dist += VectorLength2(clipped);
1610                         if (dist < bestdist)
1611                         {
1612                                 // that's closer too, store it as the best match
1613                                 best = surfacenum;
1614                                 bestdist = dist;
1615                         }
1616                 }
1617         }
1618         PRVM_G_FLOAT(OFS_RETURN) = best;
1619 }
1620
1621 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
1622 void VM_CL_getsurfaceclippedpoint(void)
1623 {
1624         prvm_edict_t *ed;
1625         model_t *model;
1626         msurface_t *surface;
1627         vec3_t p, out;
1628         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1629         ed = PRVM_G_EDICT(OFS_PARM0);
1630         if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1631                 return;
1632         // FIXME: implement rotation/scaling
1633         VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
1634         clippointtosurface(model, surface, p, out);
1635         // FIXME: implement rotation/scaling
1636         VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1637 }
1638
1639 // #443 void(entity e, entity tagentity, string tagname) setattachment
1640 void VM_CL_setattachment (void)
1641 {
1642         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1643         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1644         const char *tagname = PRVM_G_STRING(OFS_PARM2);
1645         prvm_eval_t *v;
1646         int modelindex;
1647         model_t *model;
1648
1649         if (e == prog->edicts)
1650         {
1651                 VM_Warning("setattachment: can not modify world entity\n");
1652                 return;
1653         }
1654         if (e->priv.server->free)
1655         {
1656                 VM_Warning("setattachment: can not modify free entity\n");
1657                 return;
1658         }
1659
1660         if (tagentity == NULL)
1661                 tagentity = prog->edicts;
1662
1663         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
1664         if (v)
1665                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
1666
1667         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
1668         if (v)
1669                 v->_float = 0;
1670         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
1671         {
1672                 modelindex = (int)tagentity->fields.client->modelindex;
1673                 model = CSQC_GetModelByIndex(modelindex);
1674                 if (model)
1675                 {
1676                         v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
1677                         if (v->_float == 0)
1678                                 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);
1679                 }
1680                 else
1681                         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));
1682         }
1683 }
1684
1685 /////////////////////////////////////////
1686 // DP_MD3_TAGINFO extension coded by VorteX
1687
1688 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
1689 {
1690         model_t *model = CSQC_GetModelFromEntity(e);
1691         if (model)
1692                 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
1693         else
1694                 return -1;
1695 };
1696
1697 // Warnings/errors code:
1698 // 0 - normal (everything all-right)
1699 // 1 - world entity
1700 // 2 - free entity
1701 // 3 - null or non-precached model
1702 // 4 - no tags with requested index
1703 // 5 - runaway loop at attachment chain
1704 extern cvar_t cl_bob;
1705 extern cvar_t cl_bobcycle;
1706 extern cvar_t cl_bobup;
1707 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
1708 {
1709         prvm_eval_t *val;
1710         int reqframe, attachloop;
1711         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
1712         prvm_edict_t *attachent;
1713         model_t *model;
1714
1715         *out = identitymatrix; // warnings and errors return identical matrix
1716
1717         if (ent == prog->edicts)
1718                 return 1;
1719         if (ent->priv.server->free)
1720                 return 2;
1721
1722         model = CSQC_GetModelFromEntity(ent);
1723
1724         if(!model)
1725                 return 3;
1726
1727         if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
1728                 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
1729         else
1730                 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
1731
1732         // get initial tag matrix
1733         if (tagindex)
1734         {
1735                 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
1736                 if (ret)
1737                         return ret;
1738         }
1739         else
1740                 tagmatrix = identitymatrix;
1741
1742         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
1743         { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
1744                 attachloop = 0;
1745                 do
1746                 {
1747                         attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
1748                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
1749
1750                         model = CSQC_GetModelFromEntity(attachent);
1751
1752                         if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
1753                                 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
1754                         else
1755                                 attachmatrix = identitymatrix;
1756
1757                         // apply transformation by child entity matrix
1758                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1759                         if (val->_float == 0)
1760                                 val->_float = 1;
1761                         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);
1762                         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1763                         Matrix4x4_Copy(&tagmatrix, out);
1764
1765                         // finally transformate by matrix of tag on parent entity
1766                         Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
1767                         Matrix4x4_Copy(&tagmatrix, out);
1768
1769                         ent = attachent;
1770                         attachloop += 1;
1771                         if (attachloop > 255) // prevent runaway looping
1772                                 return 5;
1773                 }
1774                 while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
1775         }
1776
1777         // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
1778         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1779         if (val->_float == 0)
1780                 val->_float = 1;
1781         // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
1782         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);
1783         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1784
1785         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
1786         {// RENDER_VIEWMODEL magic
1787                 Matrix4x4_Copy(&tagmatrix, out);
1788
1789                 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1790                 if (val->_float == 0)
1791                         val->_float = 1;
1792
1793                 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
1794                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1795
1796                 /*
1797                 // Cl_bob, ported from rendering code
1798                 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
1799                 {
1800                         double bob, cycle;
1801                         // LordHavoc: this code is *weird*, but not replacable (I think it
1802                         // should be done in QC on the server, but oh well, quake is quake)
1803                         // LordHavoc: figured out bobup: the time at which the sin is at 180
1804                         // degrees (which allows lengthening or squishing the peak or valley)
1805                         cycle = sv.time/cl_bobcycle.value;
1806                         cycle -= (int)cycle;
1807                         if (cycle < cl_bobup.value)
1808                                 cycle = sin(M_PI * cycle / cl_bobup.value);
1809                         else
1810                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
1811                         // bob is proportional to velocity in the xy plane
1812                         // (don't count Z, or jumping messes it up)
1813                         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;
1814                         bob = bob*0.3 + bob*0.7*cycle;
1815                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
1816                 }
1817                 */
1818         }
1819         return 0;
1820 }
1821
1822 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
1823 void VM_CL_gettagindex (void)
1824 {
1825         prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
1826         const char *tag_name = PRVM_G_STRING(OFS_PARM1);
1827         int modelindex, tag_index;
1828
1829         if (ent == prog->edicts)
1830         {
1831                 VM_Warning("gettagindex: can't affect world entity\n");
1832                 return;
1833         }
1834         if (ent->priv.server->free)
1835         {
1836                 VM_Warning("gettagindex: can't affect free entity\n");
1837                 return;
1838         }
1839
1840         modelindex = (int)ent->fields.client->modelindex;
1841         if(modelindex < 0)
1842                 modelindex = -(modelindex+1);
1843         tag_index = 0;
1844         if (modelindex <= 0 || modelindex >= MAX_MODELS)
1845                 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
1846         else
1847         {
1848                 tag_index = CL_GetTagIndex(ent, tag_name);
1849                 if (tag_index == 0)
1850                         Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
1851         }
1852         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
1853 }
1854
1855 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
1856 void VM_CL_gettaginfo (void)
1857 {
1858         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1859         int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
1860         matrix4x4_t tag_matrix;
1861         int returncode;
1862
1863         returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
1864         Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
1865
1866         switch(returncode)
1867         {
1868                 case 1:
1869                         VM_Warning("gettagindex: can't affect world entity\n");
1870                         break;
1871                 case 2:
1872                         VM_Warning("gettagindex: can't affect free entity\n");
1873                         break;
1874                 case 3:
1875                         Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
1876                         break;
1877                 case 4:
1878                         Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
1879                         break;
1880                 case 5:
1881                         Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
1882                         break;
1883         }
1884 }
1885
1886 //=================================================
1887 //[515]: here goes test/unfinished/etc.
1888
1889 //[515]: check if it is what it should be
1890 void VM_WasFreed (void)
1891 {
1892         prvm_edict_t    *e;
1893         VM_SAFEPARMCOUNT(1, VM_WasFreed);
1894
1895         e = PRVM_G_EDICT(OFS_PARM0);
1896         if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (prog->globals.client->time - e->priv.required->freetime) > 0.5 )))
1897                 PRVM_G_FLOAT(OFS_RETURN) = false;
1898         else
1899                 PRVM_G_FLOAT(OFS_RETURN) = true;
1900 }
1901
1902 void VM_CL_select_cube (void)
1903 {
1904         int             i;
1905         float   *mins2, *maxs2;
1906         prvm_edict_t    *ent, *chain;
1907         vec3_t  mins1, maxs1;
1908
1909         VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
1910
1911         if (prog->fieldoffsets.chain < 0)
1912                 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1913
1914         chain = prog->edicts;
1915
1916         mins2 = PRVM_G_VECTOR(OFS_PARM0);
1917         maxs2 = PRVM_G_VECTOR(OFS_PARM1);
1918
1919         ent = PRVM_NEXT_EDICT(prog->edicts);
1920         for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1921         {
1922                 if (ent->priv.required->free)
1923                         continue;
1924                 VectorCopy(ent->fields.client->origin, mins1);
1925                 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
1926                 VectorAdd(mins1, ent->fields.client->mins, mins1);
1927                 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
1928                         continue;
1929                 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
1930                         continue;
1931                 PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
1932                 chain = ent;
1933         }
1934
1935         VM_RETURN_EDICT(chain);
1936 }
1937
1938 void VM_CL_select_super (void)
1939 {
1940 /*      int             i;
1941         float   *v[8];
1942         prvm_edict_t    *ent, *chain;
1943         vec3_t  mins1, maxs1;
1944
1945         VM_SAFEPARMCOUNT(8, VM_findchain);
1946         for(i=0;i<8;i++)
1947                 v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
1948
1949         if (prog->fieldoffsets.chain < 0)
1950                 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
1951
1952         chain = prog->edicts;
1953
1954         mins2 = PRVM_G_VECTOR(OFS_PARM0);
1955         maxs2 = PRVM_G_VECTOR(OFS_PARM1);
1956
1957         ent = PRVM_NEXT_EDICT(prog->edicts);
1958         for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1959         {
1960                 if (ent->priv.required->free)
1961                         continue;
1962                 VectorCopy(ent->fields.client->origin, mins1);
1963                 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
1964                 VectorAdd(mins1, ent->fields.client->mins, mins1);
1965                 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
1966                         continue;
1967                 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
1968                         continue;
1969                 PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain);
1970                 chain = ent;
1971         }
1972
1973         VM_RETURN_EDICT(chain);*/
1974 }
1975
1976 static int Is_Text_Color (char c, char t)
1977 {
1978         int a = 0;
1979         char c2 = c - (c & 128);
1980         char t2 = t - (t & 128);
1981
1982         if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG)             return 0;
1983         if(t >= '0' && t <= '9')                a = 1;
1984         if(t2 >= '0' && t2 <= '9')              a = 1;
1985 /*      if(t >= 'A' && t <= 'Z')                a = 2;
1986         if(t2 >= 'A' && t2 <= 'Z')              a = 2;
1987
1988         if(a == 1 && scr_colortext.integer > 0)
1989                 return 1;
1990         if(a == 2 && scr_multifonts.integer > 0)
1991                 return 2;
1992 */
1993         return a;
1994 }
1995
1996 void VM_uncolorstring (void) //#170
1997 {
1998         const char      *in;
1999         char            out[VM_STRINGTEMP_LENGTH];
2000         int                     k = 0, i = 0;
2001
2002         VM_SAFEPARMCOUNT(1, VM_uncolorstring);
2003         in = PRVM_G_STRING(OFS_PARM0);
2004         VM_CheckEmptyString (in);
2005
2006         while (in[k])
2007         {
2008                 if(in[k+1])
2009                 if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
2010                 {
2011                         k += 2;
2012                         continue;
2013                 }
2014                 out[i] = in[k];
2015                 ++k;
2016                 ++i;
2017         }
2018         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
2019 }
2020
2021 void VM_CL_selecttraceline (void)
2022 {
2023         float   *v1, *v2;
2024         int             ent, ignore, csqcents;
2025
2026         v1 = PRVM_G_VECTOR(OFS_PARM0);
2027         v2 = PRVM_G_VECTOR(OFS_PARM1);
2028         ignore = (int)PRVM_G_FLOAT(OFS_PARM2);
2029         csqcents = (int)PRVM_G_FLOAT(OFS_PARM3);
2030         ent = 0;
2031
2032         if (csqcents)
2033         {
2034                 VM_Warning("VM_CL_selecttraceline: csqcents flag not supported anymore, and this function is deprecated\n");
2035                 return;
2036         }
2037         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);
2038         PRVM_G_FLOAT(OFS_RETURN) = ent;
2039 }
2040
2041 void VM_charindex (void)
2042 {
2043         const char *s;
2044         s = PRVM_G_STRING(OFS_PARM0);
2045         if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
2046                 return;
2047         PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
2048 }
2049
2050 //#223 string(float c, ...) chr2str (FTE_STRINGS)
2051 void VM_chr2str (void)
2052 {
2053         char    t[128];
2054         int             i;
2055         for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
2056                 t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
2057         t[i] = 0;
2058         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
2059 }
2060
2061 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2062 void VM_strncmp (void)
2063 {
2064         const char *s1, *s2;
2065         VM_SAFEPARMCOUNT(1, VM_strncmp);
2066         s1 = PRVM_G_STRING(OFS_PARM0);
2067         s2 = PRVM_G_STRING(OFS_PARM1);
2068         PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
2069 }
2070
2071 //============================================================================
2072 //============================================================================
2073
2074 prvm_builtin_t vm_cl_builtins[] = {
2075 0,  // to be consistent with the old vm
2076 VM_CL_makevectors,                      // #1 void(vector ang) makevectors
2077 VM_CL_setorigin,                        // #2 void(entity e, vector o) setorigin
2078 VM_CL_setmodel,                         // #3 void(entity e, string m) setmodel
2079 VM_CL_setsize,                          // #4 void(entity e, vector min, vector max) setsize
2080 0,
2081 VM_break,                                       // #6 void() break
2082 VM_random,                                      // #7 float() random
2083 VM_CL_sound,                            // #8 void(entity e, float chan, string samp) sound
2084 VM_normalize,                           // #9 vector(vector v) normalize
2085 VM_error,                                       // #10 void(string e) error
2086 VM_objerror,                            // #11 void(string e) objerror
2087 VM_vlen,                                        // #12 float(vector v) vlen
2088 VM_vectoyaw,                            // #13 float(vector v) vectoyaw
2089 VM_CL_spawn,                            // #14 entity() spawn
2090 VM_remove,                                      // #15 void(entity e) remove
2091 VM_CL_traceline,                        // #16 float(vector v1, vector v2, float tryents) traceline
2092 0,
2093 VM_find,                                        // #18 entity(entity start, .string fld, string match) find
2094 VM_CL_precache_sound,           // #19 void(string s) precache_sound
2095 VM_CL_precache_model,           // #20 void(string s) precache_model
2096 0,
2097 VM_CL_findradius,                       // #22 entity(vector org, float rad) findradius
2098 0,
2099 0,
2100 VM_dprint,                                      // #25 void(string s) dprint
2101 VM_ftos,                                        // #26 void(string s) ftos
2102 VM_vtos,                                        // #27 void(string s) vtos
2103 VM_coredump,                            // #28 void() coredump
2104 VM_traceon,                                     // #29 void() traceon
2105 VM_traceoff,                            // #30 void() traceoff
2106 VM_eprint,                                      // #31 void(entity e) eprint
2107 0,
2108 NULL,                                           // #33
2109 VM_CL_droptofloor,                      // #34 float() droptofloor
2110 VM_CL_lightstyle,                       // #35 void(float style, string value) lightstyle
2111 VM_rint,                                        // #36 float(float v) rint
2112 VM_floor,                                       // #37 float(float v) floor
2113 VM_ceil,                                        // #38 float(float v) ceil
2114 NULL,                                           // #39
2115 VM_CL_checkbottom,                      // #40 float(entity e) checkbottom
2116 VM_CL_pointcontents,            // #41 float(vector v) pointcontents
2117 NULL,                                           // #42
2118 VM_fabs,                                        // #43 float(float f) fabs
2119 0,
2120 VM_cvar,                                        // #45 float(string s) cvar
2121 VM_localcmd,                            // #46 void(string s) localcmd
2122 VM_nextent,                                     // #47 entity(entity e) nextent
2123 VM_CL_particle,                         // #48 void(vector o, vector d, float color, float count) particle
2124 VM_changeyaw,                           // #49 void(entity ent) ChangeYaw
2125 NULL,                                           // #50
2126 VM_vectoangles,                         // #51 vector(vector v) vectoangles
2127 0,                      // #52 void(float to, float f) WriteByte
2128 0,                      // #53 void(float to, float f) WriteChar
2129 0,                      // #54 void(float to, float f) WriteShort
2130 0,                      // #55 void(float to, float f) WriteLong
2131 0,                      // #56 void(float to, float f) WriteCoord
2132 0,                      // #57 void(float to, float f) WriteAngle
2133 0,                      // #58 void(float to, string s) WriteString
2134 0,
2135 VM_sin,                                         // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2136 VM_cos,                                         // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2137 VM_sqrt,                                        // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2138 VM_changepitch,                         // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2139 VM_CL_tracetoss,                        // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2140 VM_etos,                                        // #65 string(entity ent) etos (DP_QC_ETOS)
2141 NULL,                                           // #66
2142 0,                                                              // #67
2143 0,                                                              // #68
2144 0,                                                              // #69
2145 0,                                                              // #70
2146 NULL,                                           // #71
2147 VM_cvar_set,                            // #72 void(string var, string val) cvar_set
2148 0,                                                              // #73
2149 VM_CL_ambientsound,                     // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2150 VM_CL_precache_model,           // #75 string(string s) precache_model2
2151 VM_CL_precache_sound,           // #76 string(string s) precache_sound2
2152 0,                                                              // #77
2153 VM_chr,                                         // #78
2154 NULL,                                           // #79
2155 NULL,                                           // #80
2156 VM_stof,                                        // #81 float(string s) stof (FRIK_FILE)
2157 NULL,                                           // #82
2158 NULL,                                           // #83
2159 NULL,                                           // #84
2160 NULL,                                           // #85
2161 NULL,                                           // #86
2162 NULL,                                           // #87
2163 NULL,                                           // #88
2164 NULL,                                           // #89
2165 VM_CL_tracebox,                         // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2166 VM_randomvec,                           // #91 vector() randomvec (DP_QC_RANDOMVEC)
2167 VM_CL_getlight,                         // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2168 PF_registercvar,                        // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2169 VM_min,                                         // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2170 VM_max,                                         // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2171 VM_bound,                                       // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2172 VM_pow,                                         // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2173 VM_findfloat,                           // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2174 VM_checkextension,                      // #99 float(string s) checkextension (the basis of the extension system)
2175 NULL,                                           // #100
2176 NULL,                                           // #101
2177 NULL,                                           // #102
2178 NULL,                                           // #103
2179 NULL,                                           // #104
2180 NULL,                                           // #105
2181 NULL,                                           // #106
2182 NULL,                                           // #107
2183 NULL,                                           // #108
2184 NULL,                                           // #109
2185 VM_fopen,                                       // #110 float(string filename, float mode) fopen (FRIK_FILE)
2186 VM_fclose,                                      // #111 void(float fhandle) fclose (FRIK_FILE)
2187 VM_fgets,                                       // #112 string(float fhandle) fgets (FRIK_FILE)
2188 VM_fputs,                                       // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2189 VM_strlen,                                      // #114 float(string s) strlen (FRIK_FILE)
2190 VM_strcat,                                      // #115 string(string s1, string s2) strcat (FRIK_FILE)
2191 VM_substring,                           // #116 string(string s, float start, float length) substring (FRIK_FILE)
2192 VM_stov,                                        // #117 vector(string) stov (FRIK_FILE)
2193 VM_strzone,                                     // #118 string(string s) strzone (FRIK_FILE)
2194 VM_strunzone,                           // #119 void(string s) strunzone (FRIK_FILE)
2195
2196 e10, e10, e10, e10, e10, e10, e10, e10,         // #120-199
2197 e10,    //#200-209
2198 0,      //#210
2199 0,      //#211
2200 0,      //#212
2201 0,      //#213
2202 0,      //#214
2203 0,      //#215
2204 0,      //#216
2205 0,      //#217
2206 VM_bitshift,                            //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2207 0,      //#219
2208 0,      //#220
2209 0,      //#221
2210 VM_charindex,                           //#222 float(string str, float ofs) str2chr (FTE_STRINGS)
2211 VM_chr2str,                                     //#223 string(float c, ...) chr2str (FTE_STRINGS)
2212 0,      //#224
2213 0,      //#225
2214 0,      //#226
2215 0,      //#227
2216 VM_strncmp,                                     //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2217 0,
2218 e10, e10, e10, e10, e10, e10, e10,      // #230-299
2219
2220 //======CSQC start=======//
2221 //3d world (buffer/buffering) operations
2222 VM_R_ClearScene,                        //#300 void() clearscene (EXT_CSQC)
2223 VM_R_AddEntities,                       //#301 void(float mask) addentities (EXT_CSQC)
2224 VM_R_AddEntity,                         //#302 void(entity ent) addentity (EXT_CSQC)
2225 VM_R_SetView,                           //#303 float(float property, ...) setproperty (EXT_CSQC)
2226 VM_R_RenderScene,                       //#304 void() renderscene (EXT_CSQC)
2227 VM_R_AddDynamicLight,           //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2228 VM_R_PolygonBegin,                      //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2229 VM_R_PolygonVertex,                     //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2230 VM_R_PolygonEnd,                        //#308 void() R_EndPolygon
2231 0,                      //#309
2232
2233 //maths stuff that uses the current view settings
2234 VM_CL_unproject,                        //#310 vector (vector v) cs_unproject (EXT_CSQC)
2235 VM_CL_project,                          //#311 vector (vector v) cs_project (EXT_CSQC)
2236 0,                      //#312
2237 0,                      //#313
2238 0,                      //#314
2239
2240 //2d (immediate) operations
2241 VM_drawline,                            //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2242 VM_iscachedpic,                         //#316 float(string name) iscachedpic (EXT_CSQC)
2243 VM_precache_pic,                        //#317 string(string name, float trywad) precache_pic (EXT_CSQC)
2244 VM_getimagesize,                        //#318 vector(string picname) draw_getimagesize (EXT_CSQC)
2245 VM_freepic,                                     //#319 void(string name) freepic (EXT_CSQC)
2246 VM_drawcharacter,                       //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
2247 VM_drawstring,                          //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
2248 VM_drawpic,                                     //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
2249 VM_drawfill,                            //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
2250 VM_drawsetcliparea,                     //#324 void(float x, float y, float width, float height) drawsetcliparea
2251 VM_drawresetcliparea,           //#325 void(void) drawresetcliparea
2252 0,                      //#326
2253 0,                      //#327
2254 0,                      //#328
2255 0,                      //#329
2256
2257 VM_CL_getstatf,                         //#330 float(float stnum) getstatf (EXT_CSQC)
2258 VM_CL_getstati,                         //#331 float(float stnum) getstati (EXT_CSQC)
2259 VM_CL_getstats,                         //#332 string(float firststnum) getstats (EXT_CSQC)
2260 VM_CL_setmodelindex,            //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2261 VM_CL_modelnameforindex,        //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2262 VM_CL_particleeffectnum,        //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2263 VM_CL_trailparticles,           //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2264 VM_CL_pointparticles,           //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
2265 VM_CL_centerprint,                      //#338 void(string s) cprint (EXT_CSQC)
2266 VM_print,                                       //#339 void(string s) print (EXT_CSQC)
2267 VM_keynumtostring,                      //#340 string(float keynum) keynumtostring (EXT_CSQC)
2268 VM_stringtokeynum,                      //#341 float(string keyname) stringtokeynum (EXT_CSQC)
2269 VM_CL_getkeybind,                       //#342 string(float keynum) getkeybind (EXT_CSQC)
2270 VM_CL_setcursormode,            //#343 void(float usecursor) setcursormode (EXT_CSQC)
2271 VM_getmousepos,                         //#344 vector() getmousepos (EXT_CSQC)
2272 VM_CL_getinputstate,            //#345 float(float framenum) getinputstate (EXT_CSQC)
2273 VM_CL_setsensitivityscale,      //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
2274 VM_CL_runplayerphysics,         //#347 void() runstandardplayerphysics (EXT_CSQC)
2275 VM_CL_getplayerkey,                     //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
2276 VM_CL_isdemo,                           //#349 float() isdemo (EXT_CSQC)
2277 VM_isserver,                            //#350 float() isserver (EXT_CSQC)
2278 VM_CL_setlistener,                      //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
2279 VM_CL_registercmd,                      //#352 void(string cmdname) registercommand (EXT_CSQC)
2280 VM_WasFreed,                            //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
2281 VM_CL_playernum,                        //#354 float() playernum
2282 VM_CL_onground,                         //#355 float() cl_onground (EXT_CSQC)
2283 VM_charindex,                           //#356 float(string s, float num) charindex
2284 VM_CL_selecttraceline,          //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline
2285 0,                      //#358
2286 0,                      //#359
2287 VM_CL_ReadByte,                         //#360 float() readbyte (EXT_CSQC)
2288 VM_CL_ReadChar,                         //#361 float() readchar (EXT_CSQC)
2289 VM_CL_ReadShort,                        //#362 float() readshort (EXT_CSQC)
2290 VM_CL_ReadLong,                         //#363 float() readlong (EXT_CSQC)
2291 VM_CL_ReadCoord,                        //#364 float() readcoord (EXT_CSQC)
2292 VM_CL_ReadAngle,                        //#365 float() readangle (EXT_CSQC)
2293 VM_CL_ReadString,                       //#366 string() readstring (EXT_CSQC)
2294 VM_CL_ReadFloat,                        //#367 float() readfloat (EXT_CSQC)
2295 0,                      //#368
2296 0,                      //#369
2297 0,                      //#370
2298 0,                      //#371
2299 0,                      //#372
2300 0,                      //#373
2301 0,                      //#374
2302 0,                      //#375
2303 0,                      //#376
2304 0,                      //#377
2305 0,                      //#378
2306 0,                      //#379
2307 0,                      //#380
2308 0,                      //#381
2309 0,                      //#382
2310 0,                      //#383
2311 0,                      //#384
2312 0,                      //#385
2313 0,                      //#386
2314 0,                      //#387
2315 0,                      //#388
2316 0,                      //#389
2317 0,                      //#390
2318 0,                      //#391
2319 0,                      //#392
2320 0,                      //#393
2321 0,                      //#394
2322 0,                      //#395
2323 0,                      //#396
2324 0,                      //#397
2325 0,                      //#398
2326 0,                      //#399
2327 //=========CSQC end========//
2328
2329 VM_copyentity,                                  // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2330 0,
2331 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2332 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2333 VM_CL_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2334 VM_CL_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2335 VM_CL_te_bloodshower,                   // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2336 VM_CL_te_explosionrgb,                  // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2337 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)
2338 VM_CL_te_particlerain,                  // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2339 VM_CL_te_particlesnow,                  // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2340 VM_CL_te_spark,                                 // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2341 VM_CL_te_gunshotquad,                   // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2342 VM_CL_te_spikequad,                             // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2343 VM_CL_te_superspikequad,                // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2344 VM_CL_te_explosionquad,                 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2345 VM_CL_te_smallflash,                    // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2346 VM_CL_te_customflash,                   // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2347 VM_CL_te_gunshot,                               // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2348 VM_CL_te_spike,                                 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2349 VM_CL_te_superspike,                    // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2350 VM_CL_te_explosion,                             // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2351 VM_CL_te_tarexplosion,                  // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2352 VM_CL_te_wizspike,                              // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2353 VM_CL_te_knightspike,                   // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2354 VM_CL_te_lavasplash,                    // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2355 VM_CL_te_teleport,                              // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2356 VM_CL_te_explosion2,                    // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2357 VM_CL_te_lightning1,                    // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2358 VM_CL_te_lightning2,                    // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2359 VM_CL_te_lightning3,                    // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2360 VM_CL_te_beam,                                  // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2361 VM_vectorvectors,                               // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2362 VM_CL_te_plasmaburn,                    // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2363 VM_CL_getsurfacenumpoints,              // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2364 VM_CL_getsurfacepoint,                  // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2365 VM_CL_getsurfacenormal,                 // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2366 VM_CL_getsurfacetexture,                // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2367 VM_CL_getsurfacenearpoint,              // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2368 VM_CL_getsurfaceclippedpoint,   // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2369 0,                                                                      // #440
2370 VM_tokenize,                            // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2371 VM_argv,                                        // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2372 VM_CL_setattachment,            // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2373 VM_search_begin,                        // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2374 VM_search_end,                          // #445 void(float handle) search_end (DP_FS_SEARCH)
2375 VM_search_getsize,                      // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2376 VM_search_getfilename,          // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2377 VM_cvar_string,                         // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2378 VM_findflags,                           // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2379 VM_findchainflags,                      // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2380 VM_CL_gettagindex,                      // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2381 VM_CL_gettaginfo,                       // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2382 0,                                                              // #453
2383 0,                                                              // #454
2384 0,                                                              // #455
2385 NULL,                                           // #456
2386 NULL,                                           // #457
2387 NULL,                                           // #458
2388 NULL,                                           // #459
2389 VM_buf_create,                          // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2390 VM_buf_del,                                     // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2391 VM_buf_getsize,                         // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2392 VM_buf_copy,                            // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2393 VM_buf_sort,                            // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2394 VM_buf_implode,                         // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2395 VM_bufstr_get,                          // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2396 VM_bufstr_set,                          // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2397 VM_bufstr_add,                          // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2398 VM_bufstr_free,                         // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2399 NULL,                                           // #470
2400 VM_asin,                                        // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2401 VM_acos,                                        // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2402 VM_atan,                                        // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2403 VM_atan2,                                       // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2404 VM_tan,                                         // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2405 VM_strlennocol,                         // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2406 VM_strdecolorize,                       // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
2407 VM_strftime,                            // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
2408 NULL,                                           // #479
2409 e10, e10                        // #480-499 (LordHavoc)
2410 };
2411
2412 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2413
2414 void VM_CL_Cmd_Init(void)
2415 {
2416 }
2417
2418 void VM_CL_Cmd_Reset(void)
2419 {
2420 }
2421