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