]> icculus.org git repositories - divverent/darkplaces.git/blob - clvm_cmds.c
fix a crash introduced in my BGRA commit (was providing no palette for a
[divverent/darkplaces.git] / clvm_cmds.c
1 #include "quakedef.h"
2
3 #include "prvm_cmds.h"
4 #include "csprogs.h"
5 #include "cl_collision.h"
6 #include "r_shadow.h"
7
8 //============================================================================
9 // Client
10 //[515]: unsolved PROBLEMS
11 //- finish player physics code (cs_runplayerphysics)
12 //- EntWasFreed ?
13 //- RF_DEPTHHACK is not like it should be
14 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
15 //- finish lines support for R_Polygon***
16 //- insert selecttraceline into traceline somehow
17
18 //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)
19 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
20
21 sfx_t *S_FindName(const char *name);
22 int Sbar_GetPlayer (int index);
23 void Sbar_SortFrags (void);
24 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
25 void CSQC_RelinkAllEntities (int drawmask);
26 void CSQC_RelinkCSQCEntities (void);
27 const char *Key_GetBind (int key);
28
29
30
31
32
33
34 // #1 void(vector ang) makevectors
35 static void VM_CL_makevectors (void)
36 {
37         VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
38         AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
39 }
40
41 // #2 void(entity e, vector o) setorigin
42 static void VM_CL_setorigin (void)
43 {
44         prvm_edict_t    *e;
45         float   *org;
46         VM_SAFEPARMCOUNT(2, VM_CL_setorigin);
47
48         e = PRVM_G_EDICT(OFS_PARM0);
49         if (e == prog->edicts)
50         {
51                 VM_Warning("setorigin: can not modify world entity\n");
52                 return;
53         }
54         if (e->priv.required->free)
55         {
56                 VM_Warning("setorigin: can not modify free entity\n");
57                 return;
58         }
59         org = PRVM_G_VECTOR(OFS_PARM1);
60         VectorCopy (org, e->fields.client->origin);
61         CL_LinkEdict(e);
62 }
63
64 // #3 void(entity e, string m) setmodel
65 static void VM_CL_setmodel (void)
66 {
67         prvm_edict_t    *e;
68         const char              *m;
69         struct model_s  *mod;
70         int                             i;
71
72         VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
73
74         e = PRVM_G_EDICT(OFS_PARM0);
75         m = PRVM_G_STRING(OFS_PARM1);
76         for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
77         {
78                 if (!strcmp(cl.csqc_model_precache[i]->name, m))
79                 {
80                         e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
81                         e->fields.client->modelindex = -(i+1);
82                         return;
83                 }
84         }
85
86         for (i = 0;i < MAX_MODELS;i++)
87         {
88                 mod = cl.model_precache[i];
89                 if (mod && !strcmp(mod->name, m))
90                 {
91                         e->fields.client->model = PRVM_SetEngineString(mod->name);
92                         e->fields.client->modelindex = i;
93                         return;
94                 }
95         }
96
97         e->fields.client->modelindex = 0;
98         e->fields.client->model = 0;
99 }
100
101 // #4 void(entity e, vector min, vector max) setsize
102 static void VM_CL_setsize (void)
103 {
104         prvm_edict_t    *e;
105         float                   *min, *max;
106         VM_SAFEPARMCOUNT(3, VM_CL_setsize);
107
108         e = PRVM_G_EDICT(OFS_PARM0);
109         if (e == prog->edicts)
110         {
111                 VM_Warning("setsize: can not modify world entity\n");
112                 return;
113         }
114         if (e->priv.server->free)
115         {
116                 VM_Warning("setsize: can not modify free entity\n");
117                 return;
118         }
119         min = PRVM_G_VECTOR(OFS_PARM1);
120         max = PRVM_G_VECTOR(OFS_PARM2);
121
122         VectorCopy (min, e->fields.client->mins);
123         VectorCopy (max, e->fields.client->maxs);
124         VectorSubtract (max, min, e->fields.client->size);
125
126         CL_LinkEdict(e);
127 }
128
129 // #8 void(entity e, float chan, string samp, float volume, float atten) sound
130 static void VM_CL_sound (void)
131 {
132         const char                      *sample;
133         int                                     channel;
134         prvm_edict_t            *entity;
135         float                           volume;
136         float                           attenuation;
137
138         VM_SAFEPARMCOUNT(5, VM_CL_sound);
139
140         entity = PRVM_G_EDICT(OFS_PARM0);
141         channel = (int)PRVM_G_FLOAT(OFS_PARM1);
142         sample = PRVM_G_STRING(OFS_PARM2);
143         volume = PRVM_G_FLOAT(OFS_PARM3);
144         attenuation = PRVM_G_FLOAT(OFS_PARM4);
145
146         if (volume < 0 || volume > 1)
147         {
148                 VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
149                 return;
150         }
151
152         if (attenuation < 0 || attenuation > 4)
153         {
154                 VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
155                 return;
156         }
157
158         if (channel < 0 || channel > 7)
159         {
160                 VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
161                 return;
162         }
163
164         S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
165 }
166
167 // #483 void(vector origin, string sample, float volume, float attenuation) pointsound
168 static void VM_CL_pointsound(void)
169 {
170         const char                      *sample;
171         float                           volume;
172         float                           attenuation;
173         vec3_t                          org;
174
175         VM_SAFEPARMCOUNT(4, VM_CL_pointsound);
176
177         VectorCopy( PRVM_G_VECTOR(OFS_PARM0), org);
178         sample = PRVM_G_STRING(OFS_PARM1);
179         volume = PRVM_G_FLOAT(OFS_PARM2);
180         attenuation = PRVM_G_FLOAT(OFS_PARM3);
181
182         if (volume < 0 || volume > 1)
183         {
184                 VM_Warning("VM_CL_pointsound: volume must be in range 0-1\n");
185                 return;
186         }
187
188         if (attenuation < 0 || attenuation > 4)
189         {
190                 VM_Warning("VM_CL_pointsound: attenuation must be in range 0-4\n");
191                 return;
192         }
193
194         // Send World Entity as Entity to Play Sound (for CSQC, that is 32768)
195         S_StartSound(32768, 0, S_FindName(sample), org, volume, attenuation);
196 }
197
198 // #14 entity() spawn
199 static void VM_CL_spawn (void)
200 {
201         prvm_edict_t *ed;
202         ed = PRVM_ED_Alloc();
203         // FIXME: WTF.. this should be removed imo.. entnum points to the server.. [12/17/2007 Black]
204         ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed);     //[515]: not needed any more ?
205         VM_RETURN_EDICT(ed);
206 }
207
208 // #16 float(vector v1, vector v2, float movetype, entity ignore) traceline
209 static void VM_CL_traceline (void)
210 {
211         float   *v1, *v2;
212         trace_t trace;
213         int             move;
214         prvm_edict_t    *ent;
215
216         VM_SAFEPARMCOUNTRANGE(4, 4, VM_CL_traceline);
217
218         prog->xfunction->builtinsprofile += 30;
219
220         v1 = PRVM_G_VECTOR(OFS_PARM0);
221         v2 = PRVM_G_VECTOR(OFS_PARM1);
222         move = (int)PRVM_G_FLOAT(OFS_PARM2);
223         ent = PRVM_G_EDICT(OFS_PARM3);
224
225         if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
226                 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
227
228         trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
229
230         VM_SetTraceGlobals(&trace);
231 }
232
233 /*
234 =================
235 VM_CL_tracebox
236
237 Used for use tracing and shot targeting
238 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
239 if the tryents flag is set.
240
241 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
242 =================
243 */
244 // LordHavoc: added this for my own use, VERY useful, similar to traceline
245 static void VM_CL_tracebox (void)
246 {
247         float   *v1, *v2, *m1, *m2;
248         trace_t trace;
249         int             move;
250         prvm_edict_t    *ent;
251
252         VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion
253
254         prog->xfunction->builtinsprofile += 30;
255
256         v1 = PRVM_G_VECTOR(OFS_PARM0);
257         m1 = PRVM_G_VECTOR(OFS_PARM1);
258         m2 = PRVM_G_VECTOR(OFS_PARM2);
259         v2 = PRVM_G_VECTOR(OFS_PARM3);
260         move = (int)PRVM_G_FLOAT(OFS_PARM4);
261         ent = PRVM_G_EDICT(OFS_PARM5);
262
263         if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
264                 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
265
266         trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
267
268         VM_SetTraceGlobals(&trace);
269 }
270
271 trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
272 {
273         int i;
274         float gravity;
275         vec3_t move, end;
276         vec3_t original_origin;
277         vec3_t original_velocity;
278         vec3_t original_angles;
279         vec3_t original_avelocity;
280         prvm_eval_t *val;
281         trace_t trace;
282
283         VectorCopy(tossent->fields.client->origin   , original_origin   );
284         VectorCopy(tossent->fields.client->velocity , original_velocity );
285         VectorCopy(tossent->fields.client->angles   , original_angles   );
286         VectorCopy(tossent->fields.client->avelocity, original_avelocity);
287
288         val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
289         if (val != NULL && val->_float != 0)
290                 gravity = val->_float;
291         else
292                 gravity = 1.0;
293         gravity *= cl.movevars_gravity * 0.05;
294
295         for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
296         {
297                 tossent->fields.client->velocity[2] -= gravity;
298                 VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
299                 VectorScale (tossent->fields.client->velocity, 0.05, move);
300                 VectorAdd (tossent->fields.client->origin, move, end);
301                 trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
302                 VectorCopy (trace.endpos, tossent->fields.client->origin);
303
304                 if (trace.fraction < 1)
305                         break;
306         }
307
308         VectorCopy(original_origin   , tossent->fields.client->origin   );
309         VectorCopy(original_velocity , tossent->fields.client->velocity );
310         VectorCopy(original_angles   , tossent->fields.client->angles   );
311         VectorCopy(original_avelocity, tossent->fields.client->avelocity);
312
313         return trace;
314 }
315
316 static void VM_CL_tracetoss (void)
317 {
318         trace_t trace;
319         prvm_edict_t    *ent;
320         prvm_edict_t    *ignore;
321
322         prog->xfunction->builtinsprofile += 600;
323
324         VM_SAFEPARMCOUNT(2, VM_CL_tracetoss);
325
326         ent = PRVM_G_EDICT(OFS_PARM0);
327         if (ent == prog->edicts)
328         {
329                 VM_Warning("tracetoss: can not use world entity\n");
330                 return;
331         }
332         ignore = PRVM_G_EDICT(OFS_PARM1);
333
334         trace = CL_Trace_Toss (ent, ignore);
335
336         VM_SetTraceGlobals(&trace);
337 }
338
339
340 // #20 void(string s) precache_model
341 static void VM_CL_precache_model (void)
342 {
343         const char      *name;
344         int                     i;
345         model_t         *m;
346
347         VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
348
349         name = PRVM_G_STRING(OFS_PARM0);
350         for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
351         {
352                 if(!strcmp(cl.csqc_model_precache[i]->name, name))
353                 {
354                         PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
355                         return;
356                 }
357         }
358         PRVM_G_FLOAT(OFS_RETURN) = 0;
359         m = Mod_ForName(name, false, false, false);
360         if(m && m->loaded)
361         {
362                 for (i = 0;i < MAX_MODELS;i++)
363                 {
364                         if (!cl.csqc_model_precache[i])
365                         {
366                                 cl.csqc_model_precache[i] = (model_t*)m;
367                                 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
368                                 return;
369                         }
370                 }
371                 VM_Warning("VM_CL_precache_model: no free models\n");
372                 return;
373         }
374         VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
375 }
376
377 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
378 {
379         prvm_edict_t    *ent;
380         int                             i, k;
381
382         ent = PRVM_NEXT_EDICT(prog->edicts);
383         for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
384         {
385                 if (ent->priv.required->free)
386                         continue;
387                 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
388                         list[k++] = ent;
389         }
390         return k;
391 }
392
393 // #22 entity(vector org, float rad) findradius
394 static void VM_CL_findradius (void)
395 {
396         prvm_edict_t    *ent, *chain;
397         vec_t                   radius, radius2;
398         vec3_t                  org, eorg, mins, maxs;
399         int                             i, numtouchedicts;
400         prvm_edict_t    *touchedicts[MAX_EDICTS];
401
402         VM_SAFEPARMCOUNT(2, VM_CL_findradius);
403
404         chain = (prvm_edict_t *)prog->edicts;
405
406         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
407         radius = PRVM_G_FLOAT(OFS_PARM1);
408         radius2 = radius * radius;
409
410         mins[0] = org[0] - (radius + 1);
411         mins[1] = org[1] - (radius + 1);
412         mins[2] = org[2] - (radius + 1);
413         maxs[0] = org[0] + (radius + 1);
414         maxs[1] = org[1] + (radius + 1);
415         maxs[2] = org[2] + (radius + 1);
416         numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
417         if (numtouchedicts > MAX_EDICTS)
418         {
419                 // this never happens   //[515]: for what then ?
420                 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
421                 numtouchedicts = MAX_EDICTS;
422         }
423         for (i = 0;i < numtouchedicts;i++)
424         {
425                 ent = touchedicts[i];
426                 // Quake did not return non-solid entities but darkplaces does
427                 // (note: this is the reason you can't blow up fallen zombies)
428                 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
429                         continue;
430                 // LordHavoc: compare against bounding box rather than center so it
431                 // doesn't miss large objects, and use DotProduct instead of Length
432                 // for a major speedup
433                 VectorSubtract(org, ent->fields.client->origin, eorg);
434                 if (sv_gameplayfix_findradiusdistancetobox.integer)
435                 {
436                         eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
437                         eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
438                         eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
439                 }
440                 else
441                         VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
442                 if (DotProduct(eorg, eorg) < radius2)
443                 {
444                         ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
445                         chain = ent;
446                 }
447         }
448
449         VM_RETURN_EDICT(chain);
450 }
451
452 // #34 float() droptofloor
453 static void VM_CL_droptofloor (void)
454 {
455         prvm_edict_t            *ent;
456         prvm_eval_t                     *val;
457         vec3_t                          end;
458         trace_t                         trace;
459
460         VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
461
462         // assume failure if it returns early
463         PRVM_G_FLOAT(OFS_RETURN) = 0;
464
465         ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
466         if (ent == prog->edicts)
467         {
468                 VM_Warning("droptofloor: can not modify world entity\n");
469                 return;
470         }
471         if (ent->priv.server->free)
472         {
473                 VM_Warning("droptofloor: can not modify free entity\n");
474                 return;
475         }
476
477         VectorCopy (ent->fields.client->origin, end);
478         end[2] -= 256;
479
480         trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
481
482         if (trace.fraction != 1)
483         {
484                 VectorCopy (trace.endpos, ent->fields.client->origin);
485                 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
486                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
487                         val->edict = PRVM_EDICT_TO_PROG(trace.ent);
488                 PRVM_G_FLOAT(OFS_RETURN) = 1;
489                 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
490 //              ent->priv.server->suspendedinairflag = true;
491         }
492 }
493
494 // #35 void(float style, string value) lightstyle
495 static void VM_CL_lightstyle (void)
496 {
497         int                     i;
498         const char      *c;
499
500         VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
501
502         i = (int)PRVM_G_FLOAT(OFS_PARM0);
503         c = PRVM_G_STRING(OFS_PARM1);
504         if (i >= cl.max_lightstyle)
505         {
506                 VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
507                 return;
508         }
509         strlcpy (cl.lightstyle[i].map,  MSG_ReadString(), sizeof (cl.lightstyle[i].map));
510         cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
511         cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
512 }
513
514 // #40 float(entity e) checkbottom
515 static void VM_CL_checkbottom (void)
516 {
517         static int              cs_yes, cs_no;
518         prvm_edict_t    *ent;
519         vec3_t                  mins, maxs, start, stop;
520         trace_t                 trace;
521         int                             x, y;
522         float                   mid, bottom;
523
524         VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
525         ent = PRVM_G_EDICT(OFS_PARM0);
526         PRVM_G_FLOAT(OFS_RETURN) = 0;
527
528         VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
529         VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
530
531 // if all of the points under the corners are solid world, don't bother
532 // with the tougher checks
533 // the corners must be within 16 of the midpoint
534         start[2] = mins[2] - 1;
535         for     (x=0 ; x<=1 ; x++)
536                 for     (y=0 ; y<=1 ; y++)
537                 {
538                         start[0] = x ? maxs[0] : mins[0];
539                         start[1] = y ? maxs[1] : mins[1];
540                         if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
541                                 goto realcheck;
542                 }
543
544         cs_yes++;
545         PRVM_G_FLOAT(OFS_RETURN) = true;
546         return;         // we got out easy
547
548 realcheck:
549         cs_no++;
550 //
551 // check it for real...
552 //
553         start[2] = mins[2];
554
555 // the midpoint must be within 16 of the bottom
556         start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
557         start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
558         stop[2] = start[2] - 2*sv_stepheight.value;
559         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
560
561         if (trace.fraction == 1.0)
562                 return;
563
564         mid = bottom = trace.endpos[2];
565
566 // the corners must be within 16 of the midpoint
567         for     (x=0 ; x<=1 ; x++)
568                 for     (y=0 ; y<=1 ; y++)
569                 {
570                         start[0] = stop[0] = x ? maxs[0] : mins[0];
571                         start[1] = stop[1] = y ? maxs[1] : mins[1];
572
573                         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
574
575                         if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
576                                 bottom = trace.endpos[2];
577                         if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
578                                 return;
579                 }
580
581         cs_yes++;
582         PRVM_G_FLOAT(OFS_RETURN) = true;
583 }
584
585 // #41 float(vector v) pointcontents
586 static void VM_CL_pointcontents (void)
587 {
588         VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
589         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
590 }
591
592 // #48 void(vector o, vector d, float color, float count) particle
593 static void VM_CL_particle (void)
594 {
595         float   *org, *dir;
596         int             count;
597         unsigned char   color;
598         VM_SAFEPARMCOUNT(4, VM_CL_particle);
599
600         org = PRVM_G_VECTOR(OFS_PARM0);
601         dir = PRVM_G_VECTOR(OFS_PARM1);
602         color = (int)PRVM_G_FLOAT(OFS_PARM2);
603         count = (int)PRVM_G_FLOAT(OFS_PARM3);
604         CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
605 }
606
607 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
608 static void VM_CL_ambientsound (void)
609 {
610         float   *f;
611         sfx_t   *s;
612         VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
613         s = S_FindName(PRVM_G_STRING(OFS_PARM0));
614         f = PRVM_G_VECTOR(OFS_PARM1);
615         S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
616 }
617
618 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
619 static void VM_CL_getlight (void)
620 {
621         vec3_t ambientcolor, diffusecolor, diffusenormal;
622         vec_t *p;
623
624         VM_SAFEPARMCOUNT(1, VM_CL_getlight);
625
626         p = PRVM_G_VECTOR(OFS_PARM0);
627         VectorClear(ambientcolor);
628         VectorClear(diffusecolor);
629         VectorClear(diffusenormal);
630         if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
631                 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
632         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
633 }
634
635
636 //============================================================================
637 //[515]: SCENE MANAGER builtins
638 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
639
640 static void CSQC_R_RecalcView (void)
641 {
642         extern matrix4x4_t viewmodelmatrix;
643         Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
644         Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
645 }
646
647 void CL_RelinkLightFlashes(void);
648 //#300 void() clearscene (EXT_CSQC)
649 static void VM_CL_R_ClearScene (void)
650 {
651         VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
652         // clear renderable entity and light lists
653         r_refdef.numentities = 0;
654         r_refdef.numlights = 0;
655         // FIXME: restore these to the values from VM_CL_UpdateView
656         r_view.x = 0;
657         r_view.y = 0;
658         r_view.z = 0;
659         r_view.width = vid.width;
660         r_view.height = vid.height;
661         r_view.depth = 1;
662         // FIXME: restore frustum_x/frustum_y
663         r_view.useperspective = true;
664         r_view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
665         r_view.frustum_x = r_view.frustum_y * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
666         r_view.frustum_x *= r_refdef.frustumscale_x;
667         r_view.frustum_y *= r_refdef.frustumscale_y;
668         r_view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
669         r_view.ortho_y = scr_fov.value * (3.0 / 4.0);
670         // FIXME: restore cl.csqc_origin
671         // FIXME: restore cl.csqc_angles
672         cl.csqc_vidvars.drawworld = true;
673         cl.csqc_vidvars.drawenginesbar = false;
674         cl.csqc_vidvars.drawcrosshair = false;
675 }
676
677 //#301 void(float mask) addentities (EXT_CSQC)
678 extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
679 extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
680 static void VM_CL_R_AddEntities (void)
681 {
682         int                     i, drawmask;
683         prvm_edict_t *ed;
684         VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
685         drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
686         CSQC_RelinkAllEntities(drawmask);
687         CL_RelinkLightFlashes();
688
689         prog->globals.client->time = cl.time;
690         for(i=1;i<prog->num_edicts;i++)
691         {
692                 ed = &prog->edicts[i];
693                 if(ed->priv.required->free)
694                         continue;
695                 CSQC_Think(ed);
696                 if(ed->priv.required->free)
697                         continue;
698                 // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
699                 CSQC_Predraw(ed);
700                 if(ed->priv.required->free)
701                         continue;
702                 if(!((int)ed->fields.client->drawmask & drawmask))
703                         continue;
704                 CSQC_AddRenderEdict(ed);
705         }
706 }
707
708 //#302 void(entity ent) addentity (EXT_CSQC)
709 static void VM_CL_R_AddEntity (void)
710 {
711         VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
712         CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
713 }
714
715 //#303 float(float property, ...) setproperty (EXT_CSQC)
716 static void VM_CL_R_SetView (void)
717 {
718         int             c;
719         float   *f;
720         float   k;
721
722         VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView);
723
724         c = (int)PRVM_G_FLOAT(OFS_PARM0);
725         f = PRVM_G_VECTOR(OFS_PARM1);
726         k = PRVM_G_FLOAT(OFS_PARM1);
727
728         switch(c)
729         {
730         case VF_MIN:
731                 r_view.x = (int)(f[0] * vid.width / vid_conwidth.value);
732                 r_view.y = (int)(f[1] * vid.height / vid_conheight.value);
733                 break;
734         case VF_MIN_X:
735                 r_view.x = (int)(k * vid.width / vid_conwidth.value);
736                 break;
737         case VF_MIN_Y:
738                 r_view.y = (int)(k * vid.height / vid_conheight.value);
739                 break;
740         case VF_SIZE:
741                 r_view.width = (int)(f[0] * vid.width / vid_conwidth.value);
742                 r_view.height = (int)(f[1] * vid.height / vid_conheight.value);
743                 break;
744         case VF_SIZE_Y:
745                 r_view.width = (int)(k * vid.width / vid_conwidth.value);
746                 break;
747         case VF_SIZE_X:
748                 r_view.height = (int)(k * vid.height / vid_conheight.value);
749                 break;
750         case VF_VIEWPORT:
751                 r_view.x = (int)(f[0] * vid.width / vid_conwidth.value);
752                 r_view.y = (int)(f[1] * vid.height / vid_conheight.value);
753                 f = PRVM_G_VECTOR(OFS_PARM2);
754                 r_view.width = (int)(f[0] * vid.width / vid_conwidth.value);
755                 r_view.height = (int)(f[1] * vid.height / vid_conheight.value);
756                 break;
757         case VF_FOV:
758                 r_view.frustum_x = tan(f[0] * M_PI / 360.0);r_view.ortho_x = f[0];
759                 r_view.frustum_y = tan(f[1] * M_PI / 360.0);r_view.ortho_y = f[1];
760                 break;
761         case VF_FOVX:
762                 r_view.frustum_x = tan(k * M_PI / 360.0);r_view.ortho_x = k;
763                 break;
764         case VF_FOVY:
765                 r_view.frustum_y = tan(k * M_PI / 360.0);r_view.ortho_y = k;
766                 break;
767         case VF_ORIGIN:
768                 VectorCopy(f, cl.csqc_origin);
769                 CSQC_R_RecalcView();
770                 break;
771         case VF_ORIGIN_X:
772                 cl.csqc_origin[0] = k;
773                 CSQC_R_RecalcView();
774                 break;
775         case VF_ORIGIN_Y:
776                 cl.csqc_origin[1] = k;
777                 CSQC_R_RecalcView();
778                 break;
779         case VF_ORIGIN_Z:
780                 cl.csqc_origin[2] = k;
781                 CSQC_R_RecalcView();
782                 break;
783         case VF_ANGLES:
784                 VectorCopy(f, cl.csqc_angles);
785                 CSQC_R_RecalcView();
786                 break;
787         case VF_ANGLES_X:
788                 cl.csqc_angles[0] = k;
789                 CSQC_R_RecalcView();
790                 break;
791         case VF_ANGLES_Y:
792                 cl.csqc_angles[1] = k;
793                 CSQC_R_RecalcView();
794                 break;
795         case VF_ANGLES_Z:
796                 cl.csqc_angles[2] = k;
797                 CSQC_R_RecalcView();
798                 break;
799         case VF_DRAWWORLD:
800                 cl.csqc_vidvars.drawworld = k;
801                 break;
802         case VF_DRAWENGINESBAR:
803                 cl.csqc_vidvars.drawenginesbar = k;
804                 break;
805         case VF_DRAWCROSSHAIR:
806                 cl.csqc_vidvars.drawcrosshair = k;
807                 break;
808         case VF_CL_VIEWANGLES:
809                 VectorCopy(f, cl.viewangles);
810                 break;
811         case VF_CL_VIEWANGLES_X:
812                 cl.viewangles[0] = k;
813                 break;
814         case VF_CL_VIEWANGLES_Y:
815                 cl.viewangles[1] = k;
816                 break;
817         case VF_CL_VIEWANGLES_Z:
818                 cl.viewangles[2] = k;
819                 break;
820         case VF_PERSPECTIVE:
821                 r_view.useperspective = k != 0;
822                 break;
823         default:
824                 PRVM_G_FLOAT(OFS_RETURN) = 0;
825                 VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
826                 return;
827         }
828         PRVM_G_FLOAT(OFS_RETURN) = 1;
829 }
830
831 //#304 void() renderscene (EXT_CSQC)
832 static void VM_CL_R_RenderScene (void)
833 {
834         VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
835         // we need to update any RENDER_VIEWMODEL entities at this point because
836         // csqc supplies its own view matrix
837         CL_UpdateViewEntities();
838         // now draw stuff!
839         R_RenderView();
840 }
841
842 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
843 static void VM_CL_R_AddDynamicLight (void)
844 {
845         float           *pos, *col;
846         matrix4x4_t     matrix;
847         VM_SAFEPARMCOUNTRANGE(3, 3, VM_CL_R_AddDynamicLight);
848
849         // if we've run out of dlights, just return
850         if (r_refdef.numlights >= MAX_DLIGHTS)
851                 return;
852
853         pos = PRVM_G_VECTOR(OFS_PARM0);
854         col = PRVM_G_VECTOR(OFS_PARM2);
855         Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
856         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);
857 }
858
859 //============================================================================
860
861 //#310 vector (vector v) cs_unproject (EXT_CSQC)
862 static void VM_CL_unproject (void)
863 {
864         float   *f;
865         vec3_t  temp;
866
867         VM_SAFEPARMCOUNT(1, VM_CL_unproject);
868         f = PRVM_G_VECTOR(OFS_PARM0);
869         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);
870         Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
871 }
872
873 //#311 vector (vector v) cs_project (EXT_CSQC)
874 static void VM_CL_project (void)
875 {
876         float   *f;
877         vec3_t  v;
878         matrix4x4_t m;
879
880         VM_SAFEPARMCOUNT(1, VM_CL_project);
881         f = PRVM_G_VECTOR(OFS_PARM0);
882         Matrix4x4_Invert_Simple(&m, &r_view.matrix);
883         Matrix4x4_Transform(&m, f, v);
884         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]);
885 }
886
887 //#330 float(float stnum) getstatf (EXT_CSQC)
888 static void VM_CL_getstatf (void)
889 {
890         int i;
891         union
892         {
893                 float f;
894                 int l;
895         }dat;
896         VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
897         i = (int)PRVM_G_FLOAT(OFS_PARM0);
898         if(i < 0 || i >= MAX_CL_STATS)
899         {
900                 VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
901                 return;
902         }
903         dat.l = cl.stats[i];
904         PRVM_G_FLOAT(OFS_RETURN) =  dat.f;
905 }
906
907 //#331 float(float stnum) getstati (EXT_CSQC)
908 static void VM_CL_getstati (void)
909 {
910         int i, index;
911         int firstbit, bitcount;
912
913         VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getstati);
914
915         index = (int)PRVM_G_FLOAT(OFS_PARM0);
916         if (prog->argc > 1)
917         {
918                 firstbit = (int)PRVM_G_FLOAT(OFS_PARM1);
919                 if (prog->argc > 2)
920                         bitcount = (int)PRVM_G_FLOAT(OFS_PARM2);
921                 else
922                         bitcount = 1;
923         }
924         else
925         {
926                 firstbit = 0;
927                 bitcount = 32;
928         }
929
930         if(index < 0 || index >= MAX_CL_STATS)
931         {
932                 VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
933                 return;
934         }
935         i = cl.stats[index];
936         if (bitcount != 32)     //32 causes the mask to overflow, so there's nothing to subtract from.
937                 i = (((unsigned int)i)&(((1<<bitcount)-1)<<firstbit))>>firstbit;
938         PRVM_G_FLOAT(OFS_RETURN) = i;
939 }
940
941 //#332 string(float firststnum) getstats (EXT_CSQC)
942 static void VM_CL_getstats (void)
943 {
944         int i;
945         char t[17];
946         VM_SAFEPARMCOUNT(1, VM_CL_getstats);
947         i = (int)PRVM_G_FLOAT(OFS_PARM0);
948         if(i < 0 || i > MAX_CL_STATS-4)
949         {
950                 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
951                 VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
952                 return;
953         }
954         strlcpy(t, (char*)&cl.stats[i], sizeof(t));
955         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
956 }
957
958 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
959 static void VM_CL_setmodelindex (void)
960 {
961         int                             i;
962         prvm_edict_t    *t;
963         struct model_s  *model;
964
965         VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
966
967         t = PRVM_G_EDICT(OFS_PARM0);
968
969         i = (int)PRVM_G_FLOAT(OFS_PARM1);
970
971         t->fields.client->model = 0;
972         t->fields.client->modelindex = 0;
973
974         if (!i)
975                 return;
976
977         model = CL_GetModelByIndex(i);
978         if (!model)
979         {
980                 VM_Warning("VM_CL_setmodelindex: null model\n");
981                 return;
982         }
983         t->fields.client->model = PRVM_SetEngineString(model->name);
984         t->fields.client->modelindex = i;
985 }
986
987 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
988 static void VM_CL_modelnameforindex (void)
989 {
990         model_t *model;
991
992         VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
993
994         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
995         model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
996         PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
997 }
998
999 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1000 static void VM_CL_particleeffectnum (void)
1001 {
1002         int                     i;
1003         VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1004         i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
1005         if (i == 0)
1006                 i = -1;
1007         PRVM_G_FLOAT(OFS_RETURN) = i;
1008 }
1009
1010 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1011 static void VM_CL_trailparticles (void)
1012 {
1013         int                             i;
1014         float                   *start, *end;
1015         prvm_edict_t    *t;
1016         VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
1017
1018         t = PRVM_G_EDICT(OFS_PARM0);
1019         i               = (int)PRVM_G_FLOAT(OFS_PARM1);
1020         start   = PRVM_G_VECTOR(OFS_PARM2);
1021         end             = PRVM_G_VECTOR(OFS_PARM3);
1022
1023         CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
1024 }
1025
1026 //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
1027 static void VM_CL_pointparticles (void)
1028 {
1029         int                     i, n;
1030         float           *f, *v;
1031         VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
1032         i = (int)PRVM_G_FLOAT(OFS_PARM0);
1033         f = PRVM_G_VECTOR(OFS_PARM1);
1034         v = PRVM_G_VECTOR(OFS_PARM2);
1035         n = (int)PRVM_G_FLOAT(OFS_PARM3);
1036         CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
1037 }
1038
1039 //#342 string(float keynum) getkeybind (EXT_CSQC)
1040 static void VM_CL_getkeybind (void)
1041 {
1042         VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1043         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
1044 }
1045
1046 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1047 static void VM_CL_setcursormode (void)
1048 {
1049         VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1050         cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1051         cl_ignoremousemove = true;
1052 }
1053
1054 //#345 float(float framenum) getinputstate (EXT_CSQC)
1055 static void VM_CL_getinputstate (void)
1056 {
1057         int i, frame;
1058         VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1059         frame = (int)PRVM_G_FLOAT(OFS_PARM0);
1060         for (i = 0;i < cl.movement_numqueue;i++)
1061                 if (cl.movement_queue[i].sequence == frame)
1062                 {
1063                         VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
1064                         //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
1065                         VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
1066                         prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
1067                         if(cl.movement_queue[i].crouch)
1068                         {
1069                                 VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
1070                                 VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
1071                         }
1072                         else
1073                         {
1074                                 VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
1075                                 VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
1076                         }
1077                 }
1078 }
1079
1080 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1081 static void VM_CL_setsensitivityscale (void)
1082 {
1083         VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1084         cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1085 }
1086
1087 //#347 void() runstandardplayerphysics (EXT_CSQC)
1088 static void VM_CL_runplayerphysics (void)
1089 {
1090 }
1091
1092 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1093 static void VM_CL_getplayerkey (void)
1094 {
1095         int                     i;
1096         char            t[128];
1097         const char      *c;
1098
1099         VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1100
1101         i = (int)PRVM_G_FLOAT(OFS_PARM0);
1102         c = PRVM_G_STRING(OFS_PARM1);
1103         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1104         Sbar_SortFrags();
1105
1106         i = Sbar_GetPlayer(i);
1107         if(i < 0)
1108                 return;
1109
1110         t[0] = 0;
1111
1112         if(!strcasecmp(c, "name"))
1113                 strlcpy(t, cl.scores[i].name, sizeof(t));
1114         else
1115                 if(!strcasecmp(c, "frags"))
1116                         sprintf(t, "%i", cl.scores[i].frags);
1117         else
1118                 if(!strcasecmp(c, "ping"))
1119                         sprintf(t, "%i", cl.scores[i].qw_ping);
1120         else
1121                 if(!strcasecmp(c, "pl"))
1122                         sprintf(t, "%i", cl.scores[i].qw_packetloss);
1123         else
1124                 if(!strcasecmp(c, "entertime"))
1125                         sprintf(t, "%f", cl.scores[i].qw_entertime);
1126         else
1127                 if(!strcasecmp(c, "colors"))
1128                         sprintf(t, "%i", cl.scores[i].colors);
1129         else
1130                 if(!strcasecmp(c, "topcolor"))
1131                         sprintf(t, "%i", cl.scores[i].colors & 0xf0);
1132         else
1133                 if(!strcasecmp(c, "bottomcolor"))
1134                         sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
1135         else
1136                 if(!strcasecmp(c, "viewentity"))
1137                         sprintf(t, "%i", i+1);
1138         if(!t[0])
1139                 return;
1140         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1141 }
1142
1143 //#349 float() isdemo (EXT_CSQC)
1144 static void VM_CL_isdemo (void)
1145 {
1146         VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
1147         PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1148 }
1149
1150 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1151 static void VM_CL_setlistener (void)
1152 {
1153         VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1154         Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1155         cl.csqc_usecsqclistener = true; //use csqc listener at this frame
1156 }
1157
1158 //#352 void(string cmdname) registercommand (EXT_CSQC)
1159 static void VM_CL_registercmd (void)
1160 {
1161         char *t;
1162         VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1163         if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1164         {
1165                 size_t alloclen;
1166
1167                 alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
1168                 t = (char *)Z_Malloc(alloclen);
1169                 memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
1170                 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1171         }
1172         else
1173                 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1174
1175 }
1176
1177 //#360 float() readbyte (EXT_CSQC)
1178 static void VM_CL_ReadByte (void)
1179 {
1180         VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
1181         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1182 }
1183
1184 //#361 float() readchar (EXT_CSQC)
1185 static void VM_CL_ReadChar (void)
1186 {
1187         VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
1188         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1189 }
1190
1191 //#362 float() readshort (EXT_CSQC)
1192 static void VM_CL_ReadShort (void)
1193 {
1194         VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
1195         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1196 }
1197
1198 //#363 float() readlong (EXT_CSQC)
1199 static void VM_CL_ReadLong (void)
1200 {
1201         VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
1202         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1203 }
1204
1205 //#364 float() readcoord (EXT_CSQC)
1206 static void VM_CL_ReadCoord (void)
1207 {
1208         VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
1209         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1210 }
1211
1212 //#365 float() readangle (EXT_CSQC)
1213 static void VM_CL_ReadAngle (void)
1214 {
1215         VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
1216         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1217 }
1218
1219 //#366 string() readstring (EXT_CSQC)
1220 static void VM_CL_ReadString (void)
1221 {
1222         VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
1223         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
1224 }
1225
1226 //#367 float() readfloat (EXT_CSQC)
1227 static void VM_CL_ReadFloat (void)
1228 {
1229         VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
1230         PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1231 }
1232
1233 //////////////////////////////////////////////////////////
1234
1235 static void VM_CL_makestatic (void)
1236 {
1237         prvm_edict_t *ent;
1238
1239         VM_SAFEPARMCOUNT(1, VM_CL_makestatic);
1240
1241         ent = PRVM_G_EDICT(OFS_PARM0);
1242         if (ent == prog->edicts)
1243         {
1244                 VM_Warning("makestatic: can not modify world entity\n");
1245                 return;
1246         }
1247         if (ent->priv.server->free)
1248         {
1249                 VM_Warning("makestatic: can not modify free entity\n");
1250                 return;
1251         }
1252
1253         if (cl.num_static_entities < cl.max_static_entities)
1254         {
1255                 int renderflags;
1256                 prvm_eval_t *val;
1257                 entity_t *staticent = &cl.static_entities[cl.num_static_entities++];
1258
1259                 // copy it to the current state
1260                 memset(staticent, 0, sizeof(*staticent));
1261                 staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
1262                 staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame;
1263                 staticent->render.framelerp = 0;
1264                 // make torchs play out of sync
1265                 staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1);
1266                 staticent->render.skinnum = (int)ent->fields.client->skin;
1267                 staticent->render.effects = (int)ent->fields.client->effects;
1268                 staticent->render.alpha = 1;
1269                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float;
1270                 staticent->render.scale = 1;
1271                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float;
1272                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod);
1273
1274                 renderflags = 0;
1275                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
1276                 if (renderflags & RF_USEAXIS)
1277                 {
1278                         vec3_t left;
1279                         VectorNegate(prog->globals.client->v_right, left);
1280                         Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin);
1281                         Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
1282                 }
1283                 else
1284                         Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, 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], staticent->render.scale);
1285
1286                 // either fullbright or lit
1287                 if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
1288                         staticent->render.flags |= RENDER_LIGHT;
1289                 // turn off shadows from transparent objects
1290                 if (!(staticent->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1))
1291                         staticent->render.flags |= RENDER_SHADOW;
1292
1293                 CL_UpdateRenderEntity(&staticent->render);
1294         }
1295         else
1296                 Con_Printf("Too many static entities");
1297
1298 // throw the entity away now
1299         PRVM_ED_Free (ent);
1300 }
1301
1302 //=================================================================//
1303
1304 /*
1305 =================
1306 VM_CL_copyentity
1307
1308 copies data from one entity to another
1309
1310 copyentity(src, dst)
1311 =================
1312 */
1313 static void VM_CL_copyentity (void)
1314 {
1315         prvm_edict_t *in, *out;
1316         VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
1317         in = PRVM_G_EDICT(OFS_PARM0);
1318         if (in == prog->edicts)
1319         {
1320                 VM_Warning("copyentity: can not read world entity\n");
1321                 return;
1322         }
1323         if (in->priv.server->free)
1324         {
1325                 VM_Warning("copyentity: can not read free entity\n");
1326                 return;
1327         }
1328         out = PRVM_G_EDICT(OFS_PARM1);
1329         if (out == prog->edicts)
1330         {
1331                 VM_Warning("copyentity: can not modify world entity\n");
1332                 return;
1333         }
1334         if (out->priv.server->free)
1335         {
1336                 VM_Warning("copyentity: can not modify free entity\n");
1337                 return;
1338         }
1339         memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1340         CL_LinkEdict(out);
1341 }
1342
1343 //=================================================================//
1344
1345 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1346 static void VM_CL_effect (void)
1347 {
1348         VM_SAFEPARMCOUNT(5, VM_CL_effect);
1349         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));
1350 }
1351
1352 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1353 static void VM_CL_te_blood (void)
1354 {
1355         float   *pos;
1356         vec3_t  pos2;
1357         VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1358         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1359                 return;
1360         pos = PRVM_G_VECTOR(OFS_PARM0);
1361         CL_FindNonSolidLocation(pos, pos2, 4);
1362         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1363 }
1364
1365 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1366 static void VM_CL_te_bloodshower (void)
1367 {
1368         vec_t speed;
1369         vec3_t vel1, vel2;
1370         VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1371         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1372                 return;
1373         speed = PRVM_G_FLOAT(OFS_PARM2);
1374         vel1[0] = -speed;
1375         vel1[1] = -speed;
1376         vel1[2] = -speed;
1377         vel2[0] = speed;
1378         vel2[1] = speed;
1379         vel2[2] = speed;
1380         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1381 }
1382
1383 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1384 static void VM_CL_te_explosionrgb (void)
1385 {
1386         float           *pos;
1387         vec3_t          pos2;
1388         matrix4x4_t     tempmatrix;
1389         VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1390         pos = PRVM_G_VECTOR(OFS_PARM0);
1391         CL_FindNonSolidLocation(pos, pos2, 10);
1392         CL_ParticleExplosion(pos2);
1393         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1394         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);
1395 }
1396
1397 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1398 static void VM_CL_te_particlecube (void)
1399 {
1400         VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1401         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));
1402 }
1403
1404 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1405 static void VM_CL_te_particlerain (void)
1406 {
1407         VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1408         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);
1409 }
1410
1411 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1412 static void VM_CL_te_particlesnow (void)
1413 {
1414         VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1415         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);
1416 }
1417
1418 // #411 void(vector org, vector vel, float howmany) te_spark
1419 static void VM_CL_te_spark (void)
1420 {
1421         float           *pos;
1422         vec3_t          pos2;
1423         VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1424
1425         pos = PRVM_G_VECTOR(OFS_PARM0);
1426         CL_FindNonSolidLocation(pos, pos2, 4);
1427         CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1428 }
1429
1430 extern cvar_t cl_sound_ric_gunshot;
1431 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1432 static void VM_CL_te_gunshotquad (void)
1433 {
1434         float           *pos;
1435         vec3_t          pos2;
1436         int                     rnd;
1437         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1438
1439         pos = PRVM_G_VECTOR(OFS_PARM0);
1440         CL_FindNonSolidLocation(pos, pos2, 4);
1441         CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1442         if(cl_sound_ric_gunshot.integer >= 2)
1443         {
1444                 if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1445                 else
1446                 {
1447                         rnd = rand() & 3;
1448                         if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1449                         else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1450                         else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1451                 }
1452         }
1453 }
1454
1455 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1456 static void VM_CL_te_spikequad (void)
1457 {
1458         float           *pos;
1459         vec3_t          pos2;
1460         int                     rnd;
1461         VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1462
1463         pos = PRVM_G_VECTOR(OFS_PARM0);
1464         CL_FindNonSolidLocation(pos, pos2, 4);
1465         CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1466         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1467         else
1468         {
1469                 rnd = rand() & 3;
1470                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1471                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1472                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1473         }
1474 }
1475
1476 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1477 static void VM_CL_te_superspikequad (void)
1478 {
1479         float           *pos;
1480         vec3_t          pos2;
1481         int                     rnd;
1482         VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1483
1484         pos = PRVM_G_VECTOR(OFS_PARM0);
1485         CL_FindNonSolidLocation(pos, pos2, 4);
1486         CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1487         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1488         else
1489         {
1490                 rnd = rand() & 3;
1491                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1492                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1493                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1494         }
1495 }
1496
1497 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1498 static void VM_CL_te_explosionquad (void)
1499 {
1500         float           *pos;
1501         vec3_t          pos2;
1502         VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1503
1504         pos = PRVM_G_VECTOR(OFS_PARM0);
1505         CL_FindNonSolidLocation(pos, pos2, 10);
1506         CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1507         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1508 }
1509
1510 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1511 static void VM_CL_te_smallflash (void)
1512 {
1513         float           *pos;
1514         vec3_t          pos2;
1515         VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1516
1517         pos = PRVM_G_VECTOR(OFS_PARM0);
1518         CL_FindNonSolidLocation(pos, pos2, 10);
1519         CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1520 }
1521
1522 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1523 static void VM_CL_te_customflash (void)
1524 {
1525         float           *pos;
1526         vec3_t          pos2;
1527         matrix4x4_t     tempmatrix;
1528         VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1529
1530         pos = PRVM_G_VECTOR(OFS_PARM0);
1531         CL_FindNonSolidLocation(pos, pos2, 4);
1532         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1533         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);
1534 }
1535
1536 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1537 static void VM_CL_te_gunshot (void)
1538 {
1539         float           *pos;
1540         vec3_t          pos2;
1541         int                     rnd;
1542         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1543
1544         pos = PRVM_G_VECTOR(OFS_PARM0);
1545         CL_FindNonSolidLocation(pos, pos2, 4);
1546         CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1547         if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3)
1548         {
1549                 if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1550                 else
1551                 {
1552                         rnd = rand() & 3;
1553                         if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1554                         else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1555                         else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1556                 }
1557         }
1558 }
1559
1560 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1561 static void VM_CL_te_spike (void)
1562 {
1563         float           *pos;
1564         vec3_t          pos2;
1565         int                     rnd;
1566         VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1567
1568         pos = PRVM_G_VECTOR(OFS_PARM0);
1569         CL_FindNonSolidLocation(pos, pos2, 4);
1570         CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1571         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1572         else
1573         {
1574                 rnd = rand() & 3;
1575                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1576                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1577                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1578         }
1579 }
1580
1581 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1582 static void VM_CL_te_superspike (void)
1583 {
1584         float           *pos;
1585         vec3_t          pos2;
1586         int                     rnd;
1587         VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1588
1589         pos = PRVM_G_VECTOR(OFS_PARM0);
1590         CL_FindNonSolidLocation(pos, pos2, 4);
1591         CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1592         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1593         else
1594         {
1595                 rnd = rand() & 3;
1596                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1597                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1598                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1599         }
1600 }
1601
1602 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1603 static void VM_CL_te_explosion (void)
1604 {
1605         float           *pos;
1606         vec3_t          pos2;
1607         VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1608
1609         pos = PRVM_G_VECTOR(OFS_PARM0);
1610         CL_FindNonSolidLocation(pos, pos2, 10);
1611         CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1612         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1613 }
1614
1615 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1616 static void VM_CL_te_tarexplosion (void)
1617 {
1618         float           *pos;
1619         vec3_t          pos2;
1620         VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1621
1622         pos = PRVM_G_VECTOR(OFS_PARM0);
1623         CL_FindNonSolidLocation(pos, pos2, 10);
1624         CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1625         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1626 }
1627
1628 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1629 static void VM_CL_te_wizspike (void)
1630 {
1631         float           *pos;
1632         vec3_t          pos2;
1633         VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1634
1635         pos = PRVM_G_VECTOR(OFS_PARM0);
1636         CL_FindNonSolidLocation(pos, pos2, 4);
1637         CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1638         S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1639 }
1640
1641 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1642 static void VM_CL_te_knightspike (void)
1643 {
1644         float           *pos;
1645         vec3_t          pos2;
1646         VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1647
1648         pos = PRVM_G_VECTOR(OFS_PARM0);
1649         CL_FindNonSolidLocation(pos, pos2, 4);
1650         CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1651         S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1652 }
1653
1654 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1655 static void VM_CL_te_lavasplash (void)
1656 {
1657         VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1658         CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1659 }
1660
1661 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1662 static void VM_CL_te_teleport (void)
1663 {
1664         VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1665         CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1666 }
1667
1668 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1669 static void VM_CL_te_explosion2 (void)
1670 {
1671         float           *pos;
1672         vec3_t          pos2, color;
1673         matrix4x4_t     tempmatrix;
1674         int                     colorStart, colorLength;
1675         unsigned char           *tempcolor;
1676         VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1677
1678         pos = PRVM_G_VECTOR(OFS_PARM0);
1679         colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1680         colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1681         CL_FindNonSolidLocation(pos, pos2, 10);
1682         CL_ParticleExplosion2(pos2, colorStart, colorLength);
1683         tempcolor = palette_rgb[(rand()%colorLength) + colorStart];
1684         color[0] = tempcolor[0] * (2.0f / 255.0f);
1685         color[1] = tempcolor[1] * (2.0f / 255.0f);
1686         color[2] = tempcolor[2] * (2.0f / 255.0f);
1687         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1688         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);
1689         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1690 }
1691
1692
1693 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1694 static void VM_CL_te_lightning1 (void)
1695 {
1696         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1697         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1698 }
1699
1700 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1701 static void VM_CL_te_lightning2 (void)
1702 {
1703         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1704         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1705 }
1706
1707 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1708 static void VM_CL_te_lightning3 (void)
1709 {
1710         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1711         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1712 }
1713
1714 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1715 static void VM_CL_te_beam (void)
1716 {
1717         VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1718         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1719 }
1720
1721 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1722 static void VM_CL_te_plasmaburn (void)
1723 {
1724         float           *pos;
1725         vec3_t          pos2;
1726         VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1727
1728         pos = PRVM_G_VECTOR(OFS_PARM0);
1729         CL_FindNonSolidLocation(pos, pos2, 4);
1730         CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1731 }
1732
1733 // #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
1734 static void VM_CL_te_flamejet (void)
1735 {
1736         float *pos;
1737         vec3_t pos2;
1738         VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
1739         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1740                 return;
1741         pos = PRVM_G_VECTOR(OFS_PARM0);
1742         CL_FindNonSolidLocation(pos, pos2, 4);
1743         CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1744 }
1745
1746
1747 //====================================================================
1748 //DP_QC_GETSURFACE
1749
1750 extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1751
1752 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
1753 {
1754         if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1755                 return NULL;
1756         return model->data_surfaces + surfacenum + model->firstmodelsurface;
1757 }
1758
1759 // #434 float(entity e, float s) getsurfacenumpoints
1760 static void VM_CL_getsurfacenumpoints(void)
1761 {
1762         model_t *model;
1763         msurface_t *surface;
1764         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
1765         // return 0 if no such surface
1766         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1767         {
1768                 PRVM_G_FLOAT(OFS_RETURN) = 0;
1769                 return;
1770         }
1771
1772         // note: this (incorrectly) assumes it is a simple polygon
1773         PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1774 }
1775
1776 // #435 vector(entity e, float s, float n) getsurfacepoint
1777 static void VM_CL_getsurfacepoint(void)
1778 {
1779         prvm_edict_t *ed;
1780         model_t *model;
1781         msurface_t *surface;
1782         int pointnum;
1783         VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
1784         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1785         ed = PRVM_G_EDICT(OFS_PARM0);
1786         if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1787                 return;
1788         // note: this (incorrectly) assumes it is a simple polygon
1789         pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1790         if (pointnum < 0 || pointnum >= surface->num_vertices)
1791                 return;
1792         // FIXME: implement rotation/scaling
1793         VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1794 }
1795 //PF_getsurfacepointattribute,     // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
1796 // float SPA_POSITION = 0;
1797 // float SPA_S_AXIS = 1;
1798 // float SPA_R_AXIS = 2;
1799 // float SPA_T_AXIS = 3; // same as SPA_NORMAL
1800 // float SPA_TEXCOORDS0 = 4;
1801 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1802 // float SPA_LIGHTMAP0_COLOR = 6;
1803 // TODO: add some wrapper code and merge VM_CL/SV_getsurface* [12/16/2007 Black]
1804 static void VM_CL_getsurfacepointattribute(void)
1805 {
1806         prvm_edict_t *ed;
1807         model_t *model;
1808         msurface_t *surface;
1809         int pointnum;
1810         int attributetype;
1811
1812         VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
1813         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1814         ed = PRVM_G_EDICT(OFS_PARM0);
1815         if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1816                 return;
1817         // note: this (incorrectly) assumes it is a simple polygon
1818         pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1819         if (pointnum < 0 || pointnum >= surface->num_vertices)
1820                 return;
1821
1822         // FIXME: implement rotation/scaling
1823         attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
1824
1825         switch( attributetype ) {
1826                 // float SPA_POSITION = 0;
1827                 case 0:
1828                         VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1829                         break;
1830                 // float SPA_S_AXIS = 1;
1831                 case 1:
1832                         VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1833                         break;
1834                 // float SPA_R_AXIS = 2;
1835                 case 2:
1836                         VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1837                         break;
1838                 // float SPA_T_AXIS = 3; // same as SPA_NORMAL
1839                 case 3:
1840                         VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1841                         break;
1842                 // float SPA_TEXCOORDS0 = 4;
1843                 case 4: {
1844                         float *ret = PRVM_G_VECTOR(OFS_RETURN);
1845                         float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
1846                         ret[0] = texcoord[0];
1847                         ret[1] = texcoord[1];
1848                         ret[2] = 0.0f;
1849                         break;
1850                 }
1851                 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1852                 case 5: {
1853                         float *ret = PRVM_G_VECTOR(OFS_RETURN);
1854                         float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
1855                         ret[0] = texcoord[0];
1856                         ret[1] = texcoord[1];
1857                         ret[2] = 0.0f;
1858                         break;
1859                 }
1860                 // float SPA_LIGHTMAP0_COLOR = 6;
1861                 case 6:
1862                         // ignore alpha for now..
1863                         VectorCopy( &(model->surfmesh.data_normal3f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
1864                         break;
1865                 default:
1866                         VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
1867                         break;
1868         }
1869 }
1870 // #436 vector(entity e, float s) getsurfacenormal
1871 static void VM_CL_getsurfacenormal(void)
1872 {
1873         model_t *model;
1874         msurface_t *surface;
1875         vec3_t normal;
1876         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
1877         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1878         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1879                 return;
1880         // FIXME: implement rotation/scaling
1881         // note: this (incorrectly) assumes it is a simple polygon
1882         // note: this only returns the first triangle, so it doesn't work very
1883         // well for curved surfaces or arbitrary meshes
1884         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);
1885         VectorNormalize(normal);
1886         VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1887 }
1888
1889 // #437 string(entity e, float s) getsurfacetexture
1890 static void VM_CL_getsurfacetexture(void)
1891 {
1892         model_t *model;
1893         msurface_t *surface;
1894         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
1895         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1896         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1897                 return;
1898         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
1899 }
1900
1901 // #438 float(entity e, vector p) getsurfacenearpoint
1902 static void VM_CL_getsurfacenearpoint(void)
1903 {
1904         int surfacenum, best;
1905         vec3_t clipped, p;
1906         vec_t dist, bestdist;
1907         prvm_edict_t *ed;
1908         model_t *model = NULL;
1909         msurface_t *surface;
1910         vec_t *point;
1911         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
1912         PRVM_G_FLOAT(OFS_RETURN) = -1;
1913         ed = PRVM_G_EDICT(OFS_PARM0);
1914         if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
1915                 return;
1916
1917         // FIXME: implement rotation/scaling
1918         point = PRVM_G_VECTOR(OFS_PARM1);
1919         VectorSubtract(point, ed->fields.client->origin, p);
1920         best = -1;
1921         bestdist = 1000000000;
1922         for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1923         {
1924                 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1925                 // first see if the nearest point on the surface's box is closer than the previous match
1926                 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1927                 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1928                 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1929                 dist = VectorLength2(clipped);
1930                 if (dist < bestdist)
1931                 {
1932                         // it is, check the nearest point on the actual geometry
1933                         clippointtosurface(model, surface, p, clipped);
1934                         VectorSubtract(clipped, p, clipped);
1935                         dist += VectorLength2(clipped);
1936                         if (dist < bestdist)
1937                         {
1938                                 // that's closer too, store it as the best match
1939                                 best = surfacenum;
1940                                 bestdist = dist;
1941                         }
1942                 }
1943         }
1944         PRVM_G_FLOAT(OFS_RETURN) = best;
1945 }
1946
1947 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
1948 static void VM_CL_getsurfaceclippedpoint(void)
1949 {
1950         prvm_edict_t *ed;
1951         model_t *model;
1952         msurface_t *surface;
1953         vec3_t p, out;
1954         VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
1955         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1956         ed = PRVM_G_EDICT(OFS_PARM0);
1957         if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1958                 return;
1959         // FIXME: implement rotation/scaling
1960         VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
1961         clippointtosurface(model, surface, p, out);
1962         // FIXME: implement rotation/scaling
1963         VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1964 }
1965
1966 // #443 void(entity e, entity tagentity, string tagname) setattachment
1967 static void VM_CL_setattachment (void)
1968 {
1969         prvm_edict_t *e;
1970         prvm_edict_t *tagentity;
1971         const char *tagname;
1972         prvm_eval_t *v;
1973         int modelindex;
1974         model_t *model;
1975         VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
1976
1977         e = PRVM_G_EDICT(OFS_PARM0);
1978         tagentity = PRVM_G_EDICT(OFS_PARM1);
1979         tagname = PRVM_G_STRING(OFS_PARM2);
1980
1981         if (e == prog->edicts)
1982         {
1983                 VM_Warning("setattachment: can not modify world entity\n");
1984                 return;
1985         }
1986         if (e->priv.server->free)
1987         {
1988                 VM_Warning("setattachment: can not modify free entity\n");
1989                 return;
1990         }
1991
1992         if (tagentity == NULL)
1993                 tagentity = prog->edicts;
1994
1995         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
1996         if (v)
1997                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
1998
1999         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2000         if (v)
2001                 v->_float = 0;
2002         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2003         {
2004                 modelindex = (int)tagentity->fields.client->modelindex;
2005                 model = CL_GetModelByIndex(modelindex);
2006                 if (model)
2007                 {
2008                         v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
2009                         if (v->_float == 0)
2010                                 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);
2011                 }
2012                 else
2013                         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));
2014         }
2015 }
2016
2017 /////////////////////////////////////////
2018 // DP_MD3_TAGINFO extension coded by VorteX
2019
2020 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
2021 {
2022         model_t *model = CL_GetModelFromEdict(e);
2023         if (model)
2024                 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
2025         else
2026                 return -1;
2027 };
2028
2029 // Warnings/errors code:
2030 // 0 - normal (everything all-right)
2031 // 1 - world entity
2032 // 2 - free entity
2033 // 3 - null or non-precached model
2034 // 4 - no tags with requested index
2035 // 5 - runaway loop at attachment chain
2036 extern cvar_t cl_bob;
2037 extern cvar_t cl_bobcycle;
2038 extern cvar_t cl_bobup;
2039 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2040 {
2041         prvm_eval_t *val;
2042         int reqframe, attachloop;
2043         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2044         prvm_edict_t *attachent;
2045         model_t *model;
2046
2047         *out = identitymatrix; // warnings and errors return identical matrix
2048
2049         if (ent == prog->edicts)
2050                 return 1;
2051         if (ent->priv.server->free)
2052                 return 2;
2053
2054         model = CL_GetModelFromEdict(ent);
2055
2056         if(!model)
2057                 return 3;
2058
2059         if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2060                 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2061         else
2062                 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2063
2064         // get initial tag matrix
2065         if (tagindex)
2066         {
2067                 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2068                 if (ret)
2069                         return ret;
2070         }
2071         else
2072                 tagmatrix = identitymatrix;
2073
2074         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2075         { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2076                 attachloop = 0;
2077                 do
2078                 {
2079                         attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2080                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
2081
2082                         model = CL_GetModelFromEdict(attachent);
2083
2084                         if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2085                                 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
2086                         else
2087                                 attachmatrix = identitymatrix;
2088
2089                         // apply transformation by child entity matrix
2090                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2091                         if (val->_float == 0)
2092                                 val->_float = 1;
2093                         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);
2094                         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2095                         Matrix4x4_Copy(&tagmatrix, out);
2096
2097                         // finally transformate by matrix of tag on parent entity
2098                         Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2099                         Matrix4x4_Copy(&tagmatrix, out);
2100
2101                         ent = attachent;
2102                         attachloop += 1;
2103                         if (attachloop > 255) // prevent runaway looping
2104                                 return 5;
2105                 }
2106                 while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
2107         }
2108
2109         // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2110         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2111         if (val->_float == 0)
2112                 val->_float = 1;
2113         // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2114         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);
2115         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2116
2117         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2118         {// RENDER_VIEWMODEL magic
2119                 Matrix4x4_Copy(&tagmatrix, out);
2120
2121                 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2122                 if (val->_float == 0)
2123                         val->_float = 1;
2124
2125                 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], val->_float);
2126                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2127
2128                 /*
2129                 // Cl_bob, ported from rendering code
2130                 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2131                 {
2132                         double bob, cycle;
2133                         // LordHavoc: this code is *weird*, but not replacable (I think it
2134                         // should be done in QC on the server, but oh well, quake is quake)
2135                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2136                         // degrees (which allows lengthening or squishing the peak or valley)
2137                         cycle = cl.time/cl_bobcycle.value;
2138                         cycle -= (int)cycle;
2139                         if (cycle < cl_bobup.value)
2140                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2141                         else
2142                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2143                         // bob is proportional to velocity in the xy plane
2144                         // (don't count Z, or jumping messes it up)
2145                         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;
2146                         bob = bob*0.3 + bob*0.7*cycle;
2147                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2148                 }
2149                 */
2150         }
2151         return 0;
2152 }
2153
2154 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2155 static void VM_CL_gettagindex (void)
2156 {
2157         prvm_edict_t *ent;
2158         const char *tag_name;
2159         int modelindex, tag_index;
2160
2161         VM_SAFEPARMCOUNT(2, VM_CL_gettagindex);
2162
2163         ent = PRVM_G_EDICT(OFS_PARM0);
2164         tag_name = PRVM_G_STRING(OFS_PARM1);
2165         if (ent == prog->edicts)
2166         {
2167                 VM_Warning("gettagindex: can't affect world entity\n");
2168                 return;
2169         }
2170         if (ent->priv.server->free)
2171         {
2172                 VM_Warning("gettagindex: can't affect free entity\n");
2173                 return;
2174         }
2175
2176         modelindex = (int)ent->fields.client->modelindex;
2177         if(modelindex < 0)
2178                 modelindex = -(modelindex+1);
2179         tag_index = 0;
2180         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2181                 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2182         else
2183         {
2184                 tag_index = CL_GetTagIndex(ent, tag_name);
2185                 if (tag_index == 0)
2186                         Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2187         }
2188         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2189 }
2190
2191 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2192 static void VM_CL_gettaginfo (void)
2193 {
2194         prvm_edict_t *e;
2195         int tagindex;
2196         matrix4x4_t tag_matrix;
2197         int returncode;
2198
2199         VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
2200
2201         e = PRVM_G_EDICT(OFS_PARM0);
2202         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2203         returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2204         Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2205
2206         switch(returncode)
2207         {
2208                 case 1:
2209                         VM_Warning("gettagindex: can't affect world entity\n");
2210                         break;
2211                 case 2:
2212                         VM_Warning("gettagindex: can't affect free entity\n");
2213                         break;
2214                 case 3:
2215                         Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2216                         break;
2217                 case 4:
2218                         Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2219                         break;
2220                 case 5:
2221                         Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2222                         break;
2223         }
2224 }
2225
2226 //============================================================================
2227
2228 //====================
2229 //QC POLYGON functions
2230 //====================
2231
2232 typedef struct
2233 {
2234         rtexture_t              *tex;
2235         float                   data[36];       //[515]: enough for polygons
2236         unsigned char                   flags;  //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
2237 }vm_polygon_t;
2238
2239 //static float                  vm_polygon_linewidth = 1;
2240 static mempool_t                *vm_polygons_pool = NULL;
2241 static unsigned char                    vm_current_vertices = 0;
2242 static qboolean                 vm_polygons_initialized = false;
2243 static vm_polygon_t             *vm_polygons = NULL;
2244 static unsigned long    vm_polygons_num = 0, vm_drawpolygons_num = 0;   //[515]: ok long on 64bit ?
2245 static qboolean                 vm_polygonbegin = false;        //[515]: for "no-crap-on-the-screen" check
2246 #define VM_DEFPOLYNUM 64        //[515]: enough for default ?
2247
2248 #define VM_POLYGON_FL3V         16      //more than 2 vertices (used only for lines)
2249 #define VM_POLYGON_FLLINES      32
2250 #define VM_POLYGON_FL2D         64
2251 #define VM_POLYGON_FL4V         128     //4 vertices
2252
2253 static void VM_InitPolygons (void)
2254 {
2255         vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
2256         vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
2257         memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
2258         vm_polygons_num = VM_DEFPOLYNUM;
2259         vm_drawpolygons_num = 0;
2260         vm_polygonbegin = false;
2261         vm_polygons_initialized = true;
2262 }
2263
2264 static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2265 {
2266         int surfacelistindex;
2267         // LordHavoc: FIXME: this is stupid code
2268         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
2269         {
2270                 const vm_polygon_t      *p = &vm_polygons[surfacelist[surfacelistindex]];
2271                 int                                     flags = p->flags & 0x0f;
2272
2273                 if(flags == DRAWFLAG_ADDITIVE)
2274                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2275                 else if(flags == DRAWFLAG_MODULATE)
2276                         GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
2277                 else if(flags == DRAWFLAG_2XMODULATE)
2278                         GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
2279                 else
2280                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2281
2282                 R_Mesh_TexBind(0, R_GetTexture(p->tex));
2283
2284                 CHECKGLERROR
2285                 //[515]: is speed is max ?
2286                 if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
2287                 {
2288                         qglLineWidth(p->data[13]);CHECKGLERROR
2289                         qglBegin(GL_LINE_LOOP);
2290                                 qglTexCoord1f   (p->data[12]);
2291                                 qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
2292                                 qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
2293
2294                                 qglTexCoord1f   (p->data[14]);
2295                                 qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
2296                                 qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
2297
2298                                 if(p->flags & VM_POLYGON_FL3V)
2299                                 {
2300                                         qglTexCoord1f   (p->data[16]);
2301                                         qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
2302                                         qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
2303
2304                                         if(p->flags & VM_POLYGON_FL4V)
2305                                         {
2306                                                 qglTexCoord1f   (p->data[18]);
2307                                                 qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
2308                                                 qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
2309                                         }
2310                                 }
2311                         qglEnd();
2312                         CHECKGLERROR
2313                 }
2314                 else
2315                 {
2316                         qglBegin(GL_POLYGON);
2317                                 qglTexCoord2f   (p->data[12], p->data[13]);
2318                                 qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
2319                                 qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
2320
2321                                 qglTexCoord2f   (p->data[14], p->data[15]);
2322                                 qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
2323                                 qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
2324
2325                                 qglTexCoord2f   (p->data[16], p->data[17]);
2326                                 qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
2327                                 qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
2328
2329                                 if(p->flags & VM_POLYGON_FL4V)
2330                                 {
2331                                         qglTexCoord2f   (p->data[18], p->data[19]);
2332                                         qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
2333                                         qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
2334                                 }
2335                         qglEnd();
2336                         CHECKGLERROR
2337                 }
2338         }
2339 }
2340
2341 static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p)
2342 {
2343         drawqueuemesh_t mesh;
2344         static int              picelements[6] = {0, 1, 2, 0, 2, 3};
2345
2346         mesh.texture = p->tex;
2347         mesh.data_element3i = picelements;
2348         mesh.data_vertex3f = p->data;
2349         mesh.data_texcoord2f = p->data + 12;
2350         mesh.data_color4f = p->data + 20;
2351         if(p->flags & VM_POLYGON_FL4V)
2352         {
2353                 mesh.num_vertices = 4;
2354                 mesh.num_triangles = 2;
2355         }
2356         else
2357         {
2358                 mesh.num_vertices = 3;
2359                 mesh.num_triangles = 1;
2360         }
2361         if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
2362                 DrawQ_LineLoop (&mesh, (p->flags&0x0f));
2363         else
2364                 DrawQ_Mesh (&mesh, (p->flags&0x0f));
2365 }
2366
2367 void VM_CL_AddPolygonsToMeshQueue (void)
2368 {
2369         int i;
2370         if(!vm_drawpolygons_num)
2371                 return;
2372         R_Mesh_Matrix(&identitymatrix);
2373         GL_CullFace(GL_NONE);
2374         for(i = 0;i < (int)vm_drawpolygons_num;i++)
2375                 VM_DrawPolygonCallback(NULL, NULL, 1, &i);
2376         vm_drawpolygons_num = 0;
2377 }
2378
2379 //void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon
2380 static void VM_CL_R_PolygonBegin (void)
2381 {
2382         vm_polygon_t    *p;
2383         const char              *picname;
2384         VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin);
2385
2386         if(!vm_polygons_initialized)
2387                 VM_InitPolygons();
2388         if(vm_polygonbegin)
2389         {
2390                 VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n");
2391                 return;
2392         }
2393         if(vm_drawpolygons_num >= vm_polygons_num)
2394         {
2395                 p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2396                 memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2397                 memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
2398                 Mem_Free(vm_polygons);
2399                 vm_polygons = p;
2400                 vm_polygons_num *= 2;
2401         }
2402         p = &vm_polygons[vm_drawpolygons_num];
2403         picname = PRVM_G_STRING(OFS_PARM0);
2404         if(picname[0])
2405                 p->tex = Draw_CachePic(picname, true)->tex;
2406         else
2407                 p->tex = r_texture_white;
2408         p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
2409         vm_current_vertices = 0;
2410         vm_polygonbegin = true;
2411         if(prog->argc >= 3)
2412         {
2413                 if(PRVM_G_FLOAT(OFS_PARM2))
2414                         p->flags |= VM_POLYGON_FL2D;
2415                 if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3))
2416                 {
2417                         p->data[13] = PRVM_G_FLOAT(OFS_PARM3);  //[515]: linewidth
2418                         p->flags |= VM_POLYGON_FLLINES;
2419                 }
2420         }
2421 }
2422
2423 //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2424 static void VM_CL_R_PolygonVertex (void)
2425 {
2426         float                   *coords, *tx, *rgb, alpha;
2427         vm_polygon_t    *p;
2428         VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
2429
2430         if(!vm_polygonbegin)
2431         {
2432                 VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
2433                 return;
2434         }
2435         coords  = PRVM_G_VECTOR(OFS_PARM0);
2436         tx              = PRVM_G_VECTOR(OFS_PARM1);
2437         rgb             = PRVM_G_VECTOR(OFS_PARM2);
2438         alpha = PRVM_G_FLOAT(OFS_PARM3);
2439
2440         p = &vm_polygons[vm_drawpolygons_num];
2441         if(vm_current_vertices > 4)
2442         {
2443                 VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n");
2444                 return;
2445         }
2446
2447         p->data[vm_current_vertices*3]          = coords[0];
2448         p->data[1+vm_current_vertices*3]        = coords[1];
2449         p->data[2+vm_current_vertices*3]        = coords[2];
2450
2451         p->data[12+vm_current_vertices*2]       = tx[0];
2452         if(!(p->flags & VM_POLYGON_FLLINES))
2453                 p->data[13+vm_current_vertices*2]       = tx[1];
2454
2455         p->data[20+vm_current_vertices*4]       = rgb[0];
2456         p->data[21+vm_current_vertices*4]       = rgb[1];
2457         p->data[22+vm_current_vertices*4]       = rgb[2];
2458         p->data[23+vm_current_vertices*4]       = alpha;
2459
2460         vm_current_vertices++;
2461         if(vm_current_vertices == 4)
2462                 p->flags |= VM_POLYGON_FL4V;
2463         else
2464                 if(vm_current_vertices == 3)
2465                         p->flags |= VM_POLYGON_FL3V;
2466 }
2467
2468 //void() R_EndPolygon
2469 static void VM_CL_R_PolygonEnd (void)
2470 {
2471         VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
2472         if(!vm_polygonbegin)
2473         {
2474                 VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
2475                 return;
2476         }
2477         vm_polygonbegin = false;
2478         if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
2479         {
2480                 if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
2481                         VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
2482                 else
2483                         vm_drawpolygons_num++;
2484         }
2485         else
2486                 VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
2487 }
2488
2489 void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
2490 {
2491         vm_polygon_t    *p;
2492
2493         if(!vm_polygons_initialized)
2494                 VM_InitPolygons();
2495         if(vm_polygonbegin)
2496         {
2497                 Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
2498                 return;
2499         }
2500         // limit polygons to a vaguely sane amount, beyond this each one just
2501         // replaces the last one
2502         vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
2503         if(vm_drawpolygons_num >= vm_polygons_num)
2504         {
2505                 p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2506                 memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2507                 memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
2508                 Mem_Free(vm_polygons);
2509                 vm_polygons = p;
2510                 vm_polygons_num *= 2;
2511         }
2512         p = &vm_polygons[vm_drawpolygons_num];
2513         if(picname && picname[0])
2514                 p->tex = Draw_CachePic(picname, true)->tex;
2515         else
2516                 p->tex = r_texture_white;
2517         p->flags = flags;
2518         vm_current_vertices = 0;
2519         vm_polygonbegin = true;
2520         if(draw2d)
2521                 p->flags |= VM_POLYGON_FL2D;
2522         if(linewidth)
2523         {
2524                 p->data[13] = linewidth;        //[515]: linewidth
2525                 p->flags |= VM_POLYGON_FLLINES;
2526         }
2527 }
2528
2529 void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
2530 {
2531         vm_polygon_t    *p;
2532
2533         if(!vm_polygonbegin)
2534         {
2535                 Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
2536                 return;
2537         }
2538
2539         p = &vm_polygons[vm_drawpolygons_num];
2540         if(vm_current_vertices > 4)
2541         {
2542                 Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
2543                 return;
2544         }
2545
2546         p->data[vm_current_vertices*3]          = x;
2547         p->data[1+vm_current_vertices*3]        = y;
2548         p->data[2+vm_current_vertices*3]        = z;
2549
2550         p->data[12+vm_current_vertices*2]       = s;
2551         if(!(p->flags & VM_POLYGON_FLLINES))
2552                 p->data[13+vm_current_vertices*2]       = t;
2553
2554         p->data[20+vm_current_vertices*4]       = r;
2555         p->data[21+vm_current_vertices*4]       = g;
2556         p->data[22+vm_current_vertices*4]       = b;
2557         p->data[23+vm_current_vertices*4]       = a;
2558
2559         vm_current_vertices++;
2560         if(vm_current_vertices == 4)
2561                 p->flags |= VM_POLYGON_FL4V;
2562         else
2563                 if(vm_current_vertices == 3)
2564                         p->flags |= VM_POLYGON_FL3V;
2565 }
2566
2567 void Debug_PolygonEnd(void)
2568 {
2569         if(!vm_polygonbegin)
2570         {
2571                 Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
2572                 return;
2573         }
2574         vm_polygonbegin = false;
2575         if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
2576         {
2577                 if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
2578                         VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
2579                 else
2580                         vm_drawpolygons_num++;
2581         }
2582         else
2583                 Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
2584 }
2585
2586 /*
2587 =============
2588 CL_CheckBottom
2589
2590 Returns false if any part of the bottom of the entity is off an edge that
2591 is not a staircase.
2592
2593 =============
2594 */
2595 qboolean CL_CheckBottom (prvm_edict_t *ent)
2596 {
2597         vec3_t  mins, maxs, start, stop;
2598         trace_t trace;
2599         int             x, y;
2600         float   mid, bottom;
2601
2602         VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
2603         VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
2604
2605 // if all of the points under the corners are solid world, don't bother
2606 // with the tougher checks
2607 // the corners must be within 16 of the midpoint
2608         start[2] = mins[2] - 1;
2609         for     (x=0 ; x<=1 ; x++)
2610                 for     (y=0 ; y<=1 ; y++)
2611                 {
2612                         start[0] = x ? maxs[0] : mins[0];
2613                         start[1] = y ? maxs[1] : mins[1];
2614                         if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
2615                                 goto realcheck;
2616                 }
2617
2618         return true;            // we got out easy
2619
2620 realcheck:
2621 //
2622 // check it for real...
2623 //
2624         start[2] = mins[2];
2625
2626 // the midpoint must be within 16 of the bottom
2627         start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
2628         start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
2629         stop[2] = start[2] - 2*sv_stepheight.value;
2630         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2631
2632         if (trace.fraction == 1.0)
2633                 return false;
2634         mid = bottom = trace.endpos[2];
2635
2636 // the corners must be within 16 of the midpoint
2637         for     (x=0 ; x<=1 ; x++)
2638                 for     (y=0 ; y<=1 ; y++)
2639                 {
2640                         start[0] = stop[0] = x ? maxs[0] : mins[0];
2641                         start[1] = stop[1] = y ? maxs[1] : mins[1];
2642
2643                         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2644
2645                         if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
2646                                 bottom = trace.endpos[2];
2647                         if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
2648                                 return false;
2649                 }
2650
2651         return true;
2652 }
2653
2654 /*
2655 =============
2656 CL_movestep
2657
2658 Called by monster program code.
2659 The move will be adjusted for slopes and stairs, but if the move isn't
2660 possible, no move is done and false is returned
2661 =============
2662 */
2663 qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
2664 {
2665         float           dz;
2666         vec3_t          oldorg, neworg, end, traceendpos;
2667         trace_t         trace;
2668         int                     i;
2669         prvm_edict_t            *enemy;
2670         prvm_eval_t     *val;
2671
2672 // try the move
2673         VectorCopy (ent->fields.client->origin, oldorg);
2674         VectorAdd (ent->fields.client->origin, move, neworg);
2675
2676 // flying monsters don't step up
2677         if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
2678         {
2679         // try one move with vertical motion, then one without
2680                 for (i=0 ; i<2 ; i++)
2681                 {
2682                         VectorAdd (ent->fields.client->origin, move, neworg);
2683                         enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
2684                         if (i == 0 && enemy != prog->edicts)
2685                         {
2686                                 dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
2687                                 if (dz > 40)
2688                                         neworg[2] -= 8;
2689                                 if (dz < 30)
2690                                         neworg[2] += 8;
2691                         }
2692                         trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2693                         if (settrace)
2694                                 VM_SetTraceGlobals(&trace);
2695
2696                         if (trace.fraction == 1)
2697                         {
2698                                 VectorCopy(trace.endpos, traceendpos);
2699                                 if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
2700                                         return false;   // swim monster left water
2701
2702                                 VectorCopy (traceendpos, ent->fields.client->origin);
2703                                 if (relink)
2704                                         CL_LinkEdict(ent);
2705                                 return true;
2706                         }
2707
2708                         if (enemy == prog->edicts)
2709                                 break;
2710                 }
2711
2712                 return false;
2713         }
2714
2715 // push down from a step height above the wished position
2716         neworg[2] += sv_stepheight.value;
2717         VectorCopy (neworg, end);
2718         end[2] -= sv_stepheight.value*2;
2719
2720         trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2721         if (settrace)
2722                 VM_SetTraceGlobals(&trace);
2723
2724         if (trace.startsolid)
2725         {
2726                 neworg[2] -= sv_stepheight.value;
2727                 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2728                 if (settrace)
2729                         VM_SetTraceGlobals(&trace);
2730                 if (trace.startsolid)
2731                         return false;
2732         }
2733         if (trace.fraction == 1)
2734         {
2735         // if monster had the ground pulled out, go ahead and fall
2736                 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2737                 {
2738                         VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
2739                         if (relink)
2740                                 CL_LinkEdict(ent);
2741                         ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
2742                         return true;
2743                 }
2744
2745                 return false;           // walked off an edge
2746         }
2747
2748 // check point traces down for dangling corners
2749         VectorCopy (trace.endpos, ent->fields.client->origin);
2750
2751         if (!CL_CheckBottom (ent))
2752         {
2753                 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2754                 {       // entity had floor mostly pulled out from underneath it
2755                         // and is trying to correct
2756                         if (relink)
2757                                 CL_LinkEdict(ent);
2758                         return true;
2759                 }
2760                 VectorCopy (oldorg, ent->fields.client->origin);
2761                 return false;
2762         }
2763
2764         if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2765                 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
2766
2767         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
2768                 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
2769
2770 // the move is ok
2771         if (relink)
2772                 CL_LinkEdict(ent);
2773         return true;
2774 }
2775
2776 /*
2777 ===============
2778 VM_CL_walkmove
2779
2780 float(float yaw, float dist[, settrace]) walkmove
2781 ===============
2782 */
2783 static void VM_CL_walkmove (void)
2784 {
2785         prvm_edict_t    *ent;
2786         float   yaw, dist;
2787         vec3_t  move;
2788         mfunction_t     *oldf;
2789         int     oldself;
2790         qboolean        settrace;
2791
2792         VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
2793
2794         // assume failure if it returns early
2795         PRVM_G_FLOAT(OFS_RETURN) = 0;
2796
2797         ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
2798         if (ent == prog->edicts)
2799         {
2800                 VM_Warning("walkmove: can not modify world entity\n");
2801                 return;
2802         }
2803         if (ent->priv.server->free)
2804         {
2805                 VM_Warning("walkmove: can not modify free entity\n");
2806                 return;
2807         }
2808         yaw = PRVM_G_FLOAT(OFS_PARM0);
2809         dist = PRVM_G_FLOAT(OFS_PARM1);
2810         settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
2811
2812         if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
2813                 return;
2814
2815         yaw = yaw*M_PI*2 / 360;
2816
2817         move[0] = cos(yaw)*dist;
2818         move[1] = sin(yaw)*dist;
2819         move[2] = 0;
2820
2821 // save program state, because CL_movestep may call other progs
2822         oldf = prog->xfunction;
2823         oldself = prog->globals.client->self;
2824
2825         PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
2826
2827
2828 // restore program state
2829         prog->xfunction = oldf;
2830         prog->globals.client->self = oldself;
2831 }
2832
2833 /*
2834 ===============
2835 VM_CL_serverkey
2836
2837 string(string key) serverkey
2838 ===============
2839 */
2840 void VM_CL_serverkey(void)
2841 {
2842         char string[VM_STRINGTEMP_LENGTH];
2843         VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
2844         InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2845         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2846 }
2847
2848 //============================================================================
2849
2850 prvm_builtin_t vm_cl_builtins[] = {
2851 NULL,                                                   // #0 NULL function (not callable) (QUAKE)
2852 VM_CL_makevectors,                              // #1 void(vector ang) makevectors (QUAKE)
2853 VM_CL_setorigin,                                // #2 void(entity e, vector o) setorigin (QUAKE)
2854 VM_CL_setmodel,                                 // #3 void(entity e, string m) setmodel (QUAKE)
2855 VM_CL_setsize,                                  // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2856 NULL,                                                   // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2857 VM_break,                                               // #6 void() break (QUAKE)
2858 VM_random,                                              // #7 float() random (QUAKE)
2859 VM_CL_sound,                                    // #8 void(entity e, float chan, string samp) sound (QUAKE)
2860 VM_normalize,                                   // #9 vector(vector v) normalize (QUAKE)
2861 VM_error,                                               // #10 void(string e) error (QUAKE)
2862 VM_objerror,                                    // #11 void(string e) objerror (QUAKE)
2863 VM_vlen,                                                // #12 float(vector v) vlen (QUAKE)
2864 VM_vectoyaw,                                    // #13 float(vector v) vectoyaw (QUAKE)
2865 VM_CL_spawn,                                    // #14 entity() spawn (QUAKE)
2866 VM_remove,                                              // #15 void(entity e) remove (QUAKE)
2867 VM_CL_traceline,                                // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2868 NULL,                                                   // #17 entity() checkclient (QUAKE)
2869 VM_find,                                                // #18 entity(entity start, .string fld, string match) find (QUAKE)
2870 VM_precache_sound,                              // #19 void(string s) precache_sound (QUAKE)
2871 VM_CL_precache_model,                   // #20 void(string s) precache_model (QUAKE)
2872 NULL,                                                   // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2873 VM_CL_findradius,                               // #22 entity(vector org, float rad) findradius (QUAKE)
2874 NULL,                                                   // #23 void(string s, ...) bprint (QUAKE)
2875 NULL,                                                   // #24 void(entity client, string s, ...) sprint (QUAKE)
2876 VM_dprint,                                              // #25 void(string s, ...) dprint (QUAKE)
2877 VM_ftos,                                                // #26 string(float f) ftos (QUAKE)
2878 VM_vtos,                                                // #27 string(vector v) vtos (QUAKE)
2879 VM_coredump,                                    // #28 void() coredump (QUAKE)
2880 VM_traceon,                                             // #29 void() traceon (QUAKE)
2881 VM_traceoff,                                    // #30 void() traceoff (QUAKE)
2882 VM_eprint,                                              // #31 void(entity e) eprint (QUAKE)
2883 VM_CL_walkmove,                                 // #32 float(float yaw, float dist) walkmove (QUAKE)
2884 NULL,                                                   // #33 (QUAKE)
2885 VM_CL_droptofloor,                              // #34 float() droptofloor (QUAKE)
2886 VM_CL_lightstyle,                               // #35 void(float style, string value) lightstyle (QUAKE)
2887 VM_rint,                                                // #36 float(float v) rint (QUAKE)
2888 VM_floor,                                               // #37 float(float v) floor (QUAKE)
2889 VM_ceil,                                                // #38 float(float v) ceil (QUAKE)
2890 NULL,                                                   // #39 (QUAKE)
2891 VM_CL_checkbottom,                              // #40 float(entity e) checkbottom (QUAKE)
2892 VM_CL_pointcontents,                    // #41 float(vector v) pointcontents (QUAKE)
2893 NULL,                                                   // #42 (QUAKE)
2894 VM_fabs,                                                // #43 float(float f) fabs (QUAKE)
2895 NULL,                                                   // #44 vector(entity e, float speed) aim (QUAKE)
2896 VM_cvar,                                                // #45 float(string s) cvar (QUAKE)
2897 VM_localcmd,                                    // #46 void(string s) localcmd (QUAKE)
2898 VM_nextent,                                             // #47 entity(entity e) nextent (QUAKE)
2899 VM_CL_particle,                                 // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2900 VM_changeyaw,                                   // #49 void() ChangeYaw (QUAKE)
2901 NULL,                                                   // #50 (QUAKE)
2902 VM_vectoangles,                                 // #51 vector(vector v) vectoangles (QUAKE)
2903 NULL,                                                   // #52 void(float to, float f) WriteByte (QUAKE)
2904 NULL,                                                   // #53 void(float to, float f) WriteChar (QUAKE)
2905 NULL,                                                   // #54 void(float to, float f) WriteShort (QUAKE)
2906 NULL,                                                   // #55 void(float to, float f) WriteLong (QUAKE)
2907 NULL,                                                   // #56 void(float to, float f) WriteCoord (QUAKE)
2908 NULL,                                                   // #57 void(float to, float f) WriteAngle (QUAKE)
2909 NULL,                                                   // #58 void(float to, string s) WriteString (QUAKE)
2910 NULL,                                                   // #59 (QUAKE)
2911 VM_sin,                                                 // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2912 VM_cos,                                                 // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2913 VM_sqrt,                                                // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2914 VM_changepitch,                                 // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2915 VM_CL_tracetoss,                                // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2916 VM_etos,                                                // #65 string(entity ent) etos (DP_QC_ETOS)
2917 NULL,                                                   // #66 (QUAKE)
2918 NULL,                                                   // #67 void(float step) movetogoal (QUAKE)
2919 VM_precache_file,                               // #68 string(string s) precache_file (QUAKE)
2920 VM_CL_makestatic,                               // #69 void(entity e) makestatic (QUAKE)
2921 NULL,                                                   // #70 void(string s) changelevel (QUAKE)
2922 NULL,                                                   // #71 (QUAKE)
2923 VM_cvar_set,                                    // #72 void(string var, string val) cvar_set (QUAKE)
2924 NULL,                                                   // #73 void(entity client, strings) centerprint (QUAKE)
2925 VM_CL_ambientsound,                             // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2926 VM_CL_precache_model,                   // #75 string(string s) precache_model2 (QUAKE)
2927 VM_precache_sound,                              // #76 string(string s) precache_sound2 (QUAKE)
2928 VM_precache_file,                               // #77 string(string s) precache_file2 (QUAKE)
2929 NULL,                                                   // #78 void(entity e) setspawnparms (QUAKE)
2930 NULL,                                                   // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2931 NULL,                                                   // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2932 VM_stof,                                                // #81 float(string s) stof (FRIK_FILE)
2933 NULL,                                                   // #82 void(vector where, float set) multicast (QUAKEWORLD)
2934 NULL,                                                   // #83 (QUAKE)
2935 NULL,                                                   // #84 (QUAKE)
2936 NULL,                                                   // #85 (QUAKE)
2937 NULL,                                                   // #86 (QUAKE)
2938 NULL,                                                   // #87 (QUAKE)
2939 NULL,                                                   // #88 (QUAKE)
2940 NULL,                                                   // #89 (QUAKE)
2941 VM_CL_tracebox,                                 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2942 VM_randomvec,                                   // #91 vector() randomvec (DP_QC_RANDOMVEC)
2943 VM_CL_getlight,                                 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2944 VM_registercvar,                                // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2945 VM_min,                                                 // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2946 VM_max,                                                 // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2947 VM_bound,                                               // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2948 VM_pow,                                                 // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2949 VM_findfloat,                                   // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2950 VM_checkextension,                              // #99 float(string s) checkextension (the basis of the extension system)
2951 // FrikaC and Telejano range #100-#199
2952 NULL,                                                   // #100
2953 NULL,                                                   // #101
2954 NULL,                                                   // #102
2955 NULL,                                                   // #103
2956 NULL,                                                   // #104
2957 NULL,                                                   // #105
2958 NULL,                                                   // #106
2959 NULL,                                                   // #107
2960 NULL,                                                   // #108
2961 NULL,                                                   // #109
2962 VM_fopen,                                               // #110 float(string filename, float mode) fopen (FRIK_FILE)
2963 VM_fclose,                                              // #111 void(float fhandle) fclose (FRIK_FILE)
2964 VM_fgets,                                               // #112 string(float fhandle) fgets (FRIK_FILE)
2965 VM_fputs,                                               // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2966 VM_strlen,                                              // #114 float(string s) strlen (FRIK_FILE)
2967 VM_strcat,                                              // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2968 VM_substring,                                   // #116 string(string s, float start, float length) substring (FRIK_FILE)
2969 VM_stov,                                                // #117 vector(string) stov (FRIK_FILE)
2970 VM_strzone,                                             // #118 string(string s) strzone (FRIK_FILE)
2971 VM_strunzone,                                   // #119 void(string s) strunzone (FRIK_FILE)
2972 NULL,                                                   // #120
2973 NULL,                                                   // #121
2974 NULL,                                                   // #122
2975 NULL,                                                   // #123
2976 NULL,                                                   // #124
2977 NULL,                                                   // #125
2978 NULL,                                                   // #126
2979 NULL,                                                   // #127
2980 NULL,                                                   // #128
2981 NULL,                                                   // #129
2982 NULL,                                                   // #130
2983 NULL,                                                   // #131
2984 NULL,                                                   // #132
2985 NULL,                                                   // #133
2986 NULL,                                                   // #134
2987 NULL,                                                   // #135
2988 NULL,                                                   // #136
2989 NULL,                                                   // #137
2990 NULL,                                                   // #138
2991 NULL,                                                   // #139
2992 NULL,                                                   // #140
2993 NULL,                                                   // #141
2994 NULL,                                                   // #142
2995 NULL,                                                   // #143
2996 NULL,                                                   // #144
2997 NULL,                                                   // #145
2998 NULL,                                                   // #146
2999 NULL,                                                   // #147
3000 NULL,                                                   // #148
3001 NULL,                                                   // #149
3002 NULL,                                                   // #150
3003 NULL,                                                   // #151
3004 NULL,                                                   // #152
3005 NULL,                                                   // #153
3006 NULL,                                                   // #154
3007 NULL,                                                   // #155
3008 NULL,                                                   // #156
3009 NULL,                                                   // #157
3010 NULL,                                                   // #158
3011 NULL,                                                   // #159
3012 NULL,                                                   // #160
3013 NULL,                                                   // #161
3014 NULL,                                                   // #162
3015 NULL,                                                   // #163
3016 NULL,                                                   // #164
3017 NULL,                                                   // #165
3018 NULL,                                                   // #166
3019 NULL,                                                   // #167
3020 NULL,                                                   // #168
3021 NULL,                                                   // #169
3022 NULL,                                                   // #170
3023 NULL,                                                   // #171
3024 NULL,                                                   // #172
3025 NULL,                                                   // #173
3026 NULL,                                                   // #174
3027 NULL,                                                   // #175
3028 NULL,                                                   // #176
3029 NULL,                                                   // #177
3030 NULL,                                                   // #178
3031 NULL,                                                   // #179
3032 NULL,                                                   // #180
3033 NULL,                                                   // #181
3034 NULL,                                                   // #182
3035 NULL,                                                   // #183
3036 NULL,                                                   // #184
3037 NULL,                                                   // #185
3038 NULL,                                                   // #186
3039 NULL,                                                   // #187
3040 NULL,                                                   // #188
3041 NULL,                                                   // #189
3042 NULL,                                                   // #190
3043 NULL,                                                   // #191
3044 NULL,                                                   // #192
3045 NULL,                                                   // #193
3046 NULL,                                                   // #194
3047 NULL,                                                   // #195
3048 NULL,                                                   // #196
3049 NULL,                                                   // #197
3050 NULL,                                                   // #198
3051 NULL,                                                   // #199
3052 // FTEQW range #200-#299
3053 NULL,                                                   // #200
3054 NULL,                                                   // #201
3055 NULL,                                                   // #202
3056 NULL,                                                   // #203
3057 NULL,                                                   // #204
3058 NULL,                                                   // #205
3059 NULL,                                                   // #206
3060 NULL,                                                   // #207
3061 NULL,                                                   // #208
3062 NULL,                                                   // #209
3063 NULL,                                                   // #210
3064 NULL,                                                   // #211
3065 NULL,                                                   // #212
3066 NULL,                                                   // #213
3067 NULL,                                                   // #214
3068 NULL,                                                   // #215
3069 NULL,                                                   // #216
3070 NULL,                                                   // #217
3071 VM_bitshift,                                    // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3072 NULL,                                                   // #219
3073 NULL,                                                   // #220
3074 VM_strstrofs,                                   // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3075 VM_str2chr,                                             // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3076 VM_chr2str,                                             // #223 string(float c, ...) chr2str (FTE_STRINGS)
3077 VM_strconv,                                             // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3078 VM_strpad,                                              // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3079 VM_infoadd,                                             // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3080 VM_infoget,                                             // #227 string(string info, string key) infoget (FTE_STRINGS)
3081 VM_strncmp,                                             // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3082 VM_strncasecmp,                                 // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3083 VM_strncasecmp,                                 // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3084 NULL,                                                   // #231
3085 NULL,                                                   // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3086 NULL,                                                   // #233
3087 NULL,                                                   // #234
3088 NULL,                                                   // #235
3089 NULL,                                                   // #236
3090 NULL,                                                   // #237
3091 NULL,                                                   // #238
3092 NULL,                                                   // #239
3093 NULL,                                                   // #240
3094 NULL,                                                   // #241
3095 NULL,                                                   // #242
3096 NULL,                                                   // #243
3097 NULL,                                                   // #244
3098 NULL,                                                   // #245
3099 NULL,                                                   // #246
3100 NULL,                                                   // #247
3101 NULL,                                                   // #248
3102 NULL,                                                   // #249
3103 NULL,                                                   // #250
3104 NULL,                                                   // #251
3105 NULL,                                                   // #252
3106 NULL,                                                   // #253
3107 NULL,                                                   // #254
3108 NULL,                                                   // #255
3109 NULL,                                                   // #256
3110 NULL,                                                   // #257
3111 NULL,                                                   // #258
3112 NULL,                                                   // #259
3113 NULL,                                                   // #260
3114 NULL,                                                   // #261
3115 NULL,                                                   // #262
3116 NULL,                                                   // #263
3117 NULL,                                                   // #264
3118 NULL,                                                   // #265
3119 NULL,                                                   // #266
3120 NULL,                                                   // #267
3121 NULL,                                                   // #268
3122 NULL,                                                   // #269
3123 NULL,                                                   // #270
3124 NULL,                                                   // #271
3125 NULL,                                                   // #272
3126 NULL,                                                   // #273
3127 NULL,                                                   // #274
3128 NULL,                                                   // #275
3129 NULL,                                                   // #276
3130 NULL,                                                   // #277
3131 NULL,                                                   // #278
3132 NULL,                                                   // #279
3133 NULL,                                                   // #280
3134 NULL,                                                   // #281
3135 NULL,                                                   // #282
3136 NULL,                                                   // #283
3137 NULL,                                                   // #284
3138 NULL,                                                   // #285
3139 NULL,                                                   // #286
3140 NULL,                                                   // #287
3141 NULL,                                                   // #288
3142 NULL,                                                   // #289
3143 NULL,                                                   // #290
3144 NULL,                                                   // #291
3145 NULL,                                                   // #292
3146 NULL,                                                   // #293
3147 NULL,                                                   // #294
3148 NULL,                                                   // #295
3149 NULL,                                                   // #296
3150 NULL,                                                   // #297
3151 NULL,                                                   // #298
3152 NULL,                                                   // #299
3153 // CSQC range #300-#399
3154 VM_CL_R_ClearScene,                             // #300 void() clearscene (EXT_CSQC)
3155 VM_CL_R_AddEntities,                    // #301 void(float mask) addentities (EXT_CSQC)
3156 VM_CL_R_AddEntity,                              // #302 void(entity ent) addentity (EXT_CSQC)
3157 VM_CL_R_SetView,                                // #303 float(float property, ...) setproperty (EXT_CSQC)
3158 VM_CL_R_RenderScene,                    // #304 void() renderscene (EXT_CSQC)
3159 VM_CL_R_AddDynamicLight,                // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3160 VM_CL_R_PolygonBegin,                   // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3161 VM_CL_R_PolygonVertex,                  // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3162 VM_CL_R_PolygonEnd,                             // #308 void() R_EndPolygon
3163 NULL,                                                   // #309
3164 VM_CL_unproject,                                // #310 vector (vector v) cs_unproject (EXT_CSQC)
3165 VM_CL_project,                                  // #311 vector (vector v) cs_project (EXT_CSQC)
3166 NULL,                                                   // #312
3167 NULL,                                                   // #313
3168 NULL,                                                   // #314
3169 VM_drawline,                                    // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3170 VM_iscachedpic,                                 // #316 float(string name) iscachedpic (EXT_CSQC)
3171 VM_precache_pic,                                // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3172 VM_getimagesize,                                // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3173 VM_freepic,                                             // #319 void(string name) freepic (EXT_CSQC)
3174 VM_drawcharacter,                               // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3175 VM_drawstring,                                  // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3176 VM_drawpic,                                             // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3177 VM_drawfill,                                    // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3178 VM_drawsetcliparea,                             // #324 void(float x, float y, float width, float height) drawsetcliparea
3179 VM_drawresetcliparea,                   // #325 void(void) drawresetcliparea
3180 VM_drawcolorcodedstring,                // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
3181 NULL,                                                   // #327 // FIXME add stringwidth() here?
3182 NULL,                                                   // #328 // FIXME add drawsubpic() here?
3183 NULL,                                                   // #329
3184 VM_CL_getstatf,                                 // #330 float(float stnum) getstatf (EXT_CSQC)
3185 VM_CL_getstati,                                 // #331 float(float stnum) getstati (EXT_CSQC)
3186 VM_CL_getstats,                                 // #332 string(float firststnum) getstats (EXT_CSQC)
3187 VM_CL_setmodelindex,                    // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3188 VM_CL_modelnameforindex,                // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3189 VM_CL_particleeffectnum,                // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3190 VM_CL_trailparticles,                   // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3191 VM_CL_pointparticles,                   // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3192 VM_centerprint,                                 // #338 void(string s, ...) centerprint (EXT_CSQC)
3193 VM_print,                                               // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3194 VM_keynumtostring,                              // #340 string(float keynum) keynumtostring (EXT_CSQC)
3195 VM_stringtokeynum,                              // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3196 VM_CL_getkeybind,                               // #342 string(float keynum) getkeybind (EXT_CSQC)
3197 VM_CL_setcursormode,                    // #343 void(float usecursor) setcursormode (EXT_CSQC)
3198 VM_getmousepos,                                 // #344 vector() getmousepos (EXT_CSQC)
3199 VM_CL_getinputstate,                    // #345 float(float framenum) getinputstate (EXT_CSQC)
3200 VM_CL_setsensitivityscale,              // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3201 VM_CL_runplayerphysics,                 // #347 void() runstandardplayerphysics (EXT_CSQC)
3202 VM_CL_getplayerkey,                             // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3203 VM_CL_isdemo,                                   // #349 float() isdemo (EXT_CSQC)
3204 VM_isserver,                                    // #350 float() isserver (EXT_CSQC)
3205 VM_CL_setlistener,                              // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3206 VM_CL_registercmd,                              // #352 void(string cmdname) registercommand (EXT_CSQC)
3207 VM_wasfreed,                                    // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3208 VM_CL_serverkey,                                // #354 string(string key) serverkey (EXT_CSQC)
3209 NULL,                                                   // #355
3210 NULL,                                                   // #356
3211 NULL,                                                   // #357
3212 NULL,                                                   // #358
3213 NULL,                                                   // #359
3214 VM_CL_ReadByte,                                 // #360 float() readbyte (EXT_CSQC)
3215 VM_CL_ReadChar,                                 // #361 float() readchar (EXT_CSQC)
3216 VM_CL_ReadShort,                                // #362 float() readshort (EXT_CSQC)
3217 VM_CL_ReadLong,                                 // #363 float() readlong (EXT_CSQC)
3218 VM_CL_ReadCoord,                                // #364 float() readcoord (EXT_CSQC)
3219 VM_CL_ReadAngle,                                // #365 float() readangle (EXT_CSQC)
3220 VM_CL_ReadString,                               // #366 string() readstring (EXT_CSQC)
3221 VM_CL_ReadFloat,                                // #367 float() readfloat (EXT_CSQC)
3222 NULL,                                                   // #368
3223 NULL,                                                   // #369
3224 NULL,                                                   // #370
3225 NULL,                                                   // #371
3226 NULL,                                                   // #372
3227 NULL,                                                   // #373
3228 NULL,                                                   // #374
3229 NULL,                                                   // #375
3230 NULL,                                                   // #376
3231 NULL,                                                   // #377
3232 NULL,                                                   // #378
3233 NULL,                                                   // #379
3234 NULL,                                                   // #380
3235 NULL,                                                   // #381
3236 NULL,                                                   // #382
3237 NULL,                                                   // #383
3238 NULL,                                                   // #384
3239 NULL,                                                   // #385
3240 NULL,                                                   // #386
3241 NULL,                                                   // #387
3242 NULL,                                                   // #388
3243 NULL,                                                   // #389
3244 NULL,                                                   // #390
3245 NULL,                                                   // #391
3246 NULL,                                                   // #392
3247 NULL,                                                   // #393
3248 NULL,                                                   // #394
3249 NULL,                                                   // #395
3250 NULL,                                                   // #396
3251 NULL,                                                   // #397
3252 NULL,                                                   // #398
3253 NULL,                                                   // #399
3254 // LordHavoc's range #400-#499
3255 VM_CL_copyentity,                               // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3256 NULL,                                                   // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3257 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3258 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3259 VM_CL_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3260 VM_CL_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3261 VM_CL_te_bloodshower,                   // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3262 VM_CL_te_explosionrgb,                  // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3263 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)
3264 VM_CL_te_particlerain,                  // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3265 VM_CL_te_particlesnow,                  // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3266 VM_CL_te_spark,                                 // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3267 VM_CL_te_gunshotquad,                   // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3268 VM_CL_te_spikequad,                             // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3269 VM_CL_te_superspikequad,                // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3270 VM_CL_te_explosionquad,                 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3271 VM_CL_te_smallflash,                    // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3272 VM_CL_te_customflash,                   // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3273 VM_CL_te_gunshot,                               // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3274 VM_CL_te_spike,                                 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3275 VM_CL_te_superspike,                    // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3276 VM_CL_te_explosion,                             // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3277 VM_CL_te_tarexplosion,                  // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3278 VM_CL_te_wizspike,                              // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3279 VM_CL_te_knightspike,                   // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3280 VM_CL_te_lavasplash,                    // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3281 VM_CL_te_teleport,                              // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3282 VM_CL_te_explosion2,                    // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3283 VM_CL_te_lightning1,                    // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3284 VM_CL_te_lightning2,                    // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3285 VM_CL_te_lightning3,                    // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3286 VM_CL_te_beam,                                  // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3287 VM_vectorvectors,                               // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3288 VM_CL_te_plasmaburn,                    // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3289 VM_CL_getsurfacenumpoints,              // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3290 VM_CL_getsurfacepoint,                  // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3291 VM_CL_getsurfacenormal,                 // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3292 VM_CL_getsurfacetexture,                // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3293 VM_CL_getsurfacenearpoint,              // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3294 VM_CL_getsurfaceclippedpoint,   // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3295 NULL,                                                   // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3296 VM_tokenize,                                    // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3297 VM_argv,                                                // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3298 VM_CL_setattachment,                    // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3299 VM_search_begin,                                // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3300 VM_search_end,                                  // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3301 VM_search_getsize,                              // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3302 VM_search_getfilename,                  // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3303 VM_cvar_string,                                 // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3304 VM_findflags,                                   // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3305 VM_findchainflags,                              // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3306 VM_CL_gettagindex,                              // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3307 VM_CL_gettaginfo,                               // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3308 NULL,                                                   // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3309 NULL,                                                   // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3310 NULL,                                                   // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3311 NULL,                                                   // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3312 VM_CL_te_flamejet,                              // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3313 NULL,                                                   // #458
3314 VM_ftoe,                                                // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3315 VM_buf_create,                                  // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3316 VM_buf_del,                                             // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3317 VM_buf_getsize,                                 // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3318 VM_buf_copy,                                    // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3319 VM_buf_sort,                                    // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3320 VM_buf_implode,                                 // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3321 VM_bufstr_get,                                  // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3322 VM_bufstr_set,                                  // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3323 VM_bufstr_add,                                  // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3324 VM_bufstr_free,                                 // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3325 NULL,                                                   // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3326 VM_asin,                                                // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3327 VM_acos,                                                // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3328 VM_atan,                                                // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3329 VM_atan2,                                               // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3330 VM_tan,                                                 // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3331 VM_strlennocol,                                 // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3332 VM_strdecolorize,                               // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
3333 VM_strftime,                                    // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3334 VM_tokenizebyseparator,                 // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3335 VM_strtolower,                                  // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3336 VM_strtoupper,                                  // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3337 VM_cvar_defstring,                              // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3338 VM_CL_pointsound,                               // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3339 VM_strreplace,                                  // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3340 VM_strireplace,                                 // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3341 VM_CL_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3342 #ifdef SUPPORT_GECKO
3343 VM_gecko_create,                                        // #487
3344 VM_gecko_destroy,                                       // #488
3345 VM_gecko_navigate,                              // #489
3346 VM_gecko_keyevent,                              // #490
3347 VM_gecko_movemouse,                             // #491
3348 #else
3349 NULL,                                                                   // #487
3350 NULL,                                                                   // #488
3351 NULL,                                                                   // #489
3352 NULL,                                                                   // #490
3353 NULL,                                                                   // #491
3354 #endif
3355 NULL,                                                   // #492
3356 NULL,                                                   // #493
3357 NULL,                                                   // #494
3358 NULL,                                                   // #495
3359 NULL,                                                   // #496
3360 NULL,                                                   // #497
3361 NULL,                                                   // #498
3362 NULL,                                                   // #499
3363 };
3364
3365 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3366
3367 void VM_CL_Cmd_Init(void)
3368 {
3369         VM_Cmd_Init();
3370         // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
3371         if(vm_polygons_initialized)
3372         {
3373                 Mem_FreePool(&vm_polygons_pool);
3374                 vm_polygons_initialized = false;
3375         }
3376 }
3377
3378 void VM_CL_Cmd_Reset(void)
3379 {
3380         VM_Cmd_Reset();
3381         if(vm_polygons_initialized)
3382         {
3383                 Mem_FreePool(&vm_polygons_pool);
3384                 vm_polygons_initialized = false;
3385         }
3386 }
3387