43ca54ad9203899025b7d21636c881516d4d28bf
[xonotic/darkplaces.git] / clvm_cmds.c
1 #include "prvm_cmds.h"
2 #include "csprogs.h"
3 #include "cl_collision.h"
4 #include "r_shadow.h"
5
6 //============================================================================
7 // Client
8 //[515]: unsolved PROBLEMS
9 //- finish player physics code (cs_runplayerphysics)
10 //- EntWasFreed ?
11 //- RF_DEPTHHACK is not like it should be
12 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
13 //- finish lines support for R_Polygon***
14 //- insert selecttraceline into traceline somehow
15
16 //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
17 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
18
19 sfx_t *S_FindName(const char *name);
20 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                 // transparent stuff can't be lit during the opaque stage
1209                 if (staticent->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || staticent->render.alpha < 1)
1210                         staticent->render.flags |= RENDER_TRANSPARENT;
1211                 // double sided rendering mode causes backfaces to be visible
1212                 // (mostly useful on transparent stuff)
1213                 if (staticent->render.effects & EF_DOUBLESIDED)
1214                         staticent->render.flags |= RENDER_NOCULLFACE;
1215                 // either fullbright or lit
1216                 if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
1217                         staticent->render.flags |= RENDER_LIGHT;
1218                 // turn off shadows from transparent objects
1219                 if (!(staticent->render.effects & EF_NOSHADOW)
1220                  && !(staticent->render.flags & RENDER_TRANSPARENT))
1221                         staticent->render.flags |= RENDER_SHADOW;
1222         }
1223         else
1224                 Con_Printf("Too many static entities");
1225
1226 // throw the entity away now
1227         PRVM_ED_Free (ent);
1228 }
1229
1230 //=================================================================//
1231
1232 /*
1233 =================
1234 VM_CL_copyentity
1235
1236 copies data from one entity to another
1237
1238 copyentity(src, dst)
1239 =================
1240 */
1241 static void VM_CL_copyentity (void)
1242 {
1243         prvm_edict_t *in, *out;
1244         VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
1245         in = PRVM_G_EDICT(OFS_PARM0);
1246         if (in == prog->edicts)
1247         {
1248                 VM_Warning("copyentity: can not read world entity\n");
1249                 return;
1250         }
1251         if (in->priv.server->free)
1252         {
1253                 VM_Warning("copyentity: can not read free entity\n");
1254                 return;
1255         }
1256         out = PRVM_G_EDICT(OFS_PARM1);
1257         if (out == prog->edicts)
1258         {
1259                 VM_Warning("copyentity: can not modify world entity\n");
1260                 return;
1261         }
1262         if (out->priv.server->free)
1263         {
1264                 VM_Warning("copyentity: can not modify free entity\n");
1265                 return;
1266         }
1267         memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1268         CL_LinkEdict(out);
1269 }
1270
1271 //=================================================================//
1272
1273 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1274 static void VM_CL_effect (void)
1275 {
1276         VM_SAFEPARMCOUNT(5, VM_CL_effect);
1277         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));
1278 }
1279
1280 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1281 static void VM_CL_te_blood (void)
1282 {
1283         float   *pos;
1284         vec3_t  pos2;
1285         VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1286         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1287                 return;
1288         pos = PRVM_G_VECTOR(OFS_PARM0);
1289         CL_FindNonSolidLocation(pos, pos2, 4);
1290         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1291 }
1292
1293 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1294 static void VM_CL_te_bloodshower (void)
1295 {
1296         vec_t speed;
1297         vec3_t vel1, vel2;
1298         VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1299         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1300                 return;
1301         speed = PRVM_G_FLOAT(OFS_PARM2);
1302         vel1[0] = -speed;
1303         vel1[1] = -speed;
1304         vel1[2] = -speed;
1305         vel2[0] = speed;
1306         vel2[1] = speed;
1307         vel2[2] = speed;
1308         CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1309 }
1310
1311 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1312 static void VM_CL_te_explosionrgb (void)
1313 {
1314         float           *pos;
1315         vec3_t          pos2;
1316         matrix4x4_t     tempmatrix;
1317         VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1318         pos = PRVM_G_VECTOR(OFS_PARM0);
1319         CL_FindNonSolidLocation(pos, pos2, 10);
1320         CL_ParticleExplosion(pos2);
1321         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1322         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);
1323 }
1324
1325 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1326 static void VM_CL_te_particlecube (void)
1327 {
1328         VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1329         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));
1330 }
1331
1332 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1333 static void VM_CL_te_particlerain (void)
1334 {
1335         VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1336         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);
1337 }
1338
1339 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1340 static void VM_CL_te_particlesnow (void)
1341 {
1342         VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1343         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);
1344 }
1345
1346 // #411 void(vector org, vector vel, float howmany) te_spark
1347 static void VM_CL_te_spark (void)
1348 {
1349         float           *pos;
1350         vec3_t          pos2;
1351         VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1352
1353         pos = PRVM_G_VECTOR(OFS_PARM0);
1354         CL_FindNonSolidLocation(pos, pos2, 4);
1355         CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1356 }
1357
1358 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1359 static void VM_CL_te_gunshotquad (void)
1360 {
1361         float           *pos;
1362         vec3_t          pos2;
1363         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1364
1365         pos = PRVM_G_VECTOR(OFS_PARM0);
1366         CL_FindNonSolidLocation(pos, pos2, 4);
1367         CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1368 }
1369
1370 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1371 static void VM_CL_te_spikequad (void)
1372 {
1373         float           *pos;
1374         vec3_t          pos2;
1375         int                     rnd;
1376         VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1377
1378         pos = PRVM_G_VECTOR(OFS_PARM0);
1379         CL_FindNonSolidLocation(pos, pos2, 4);
1380         CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1381         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1382         else
1383         {
1384                 rnd = rand() & 3;
1385                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1386                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1387                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1388         }
1389 }
1390
1391 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1392 static void VM_CL_te_superspikequad (void)
1393 {
1394         float           *pos;
1395         vec3_t          pos2;
1396         int                     rnd;
1397         VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1398
1399         pos = PRVM_G_VECTOR(OFS_PARM0);
1400         CL_FindNonSolidLocation(pos, pos2, 4);
1401         CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1402         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1403         else
1404         {
1405                 rnd = rand() & 3;
1406                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1407                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1408                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1409         }
1410 }
1411
1412 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1413 static void VM_CL_te_explosionquad (void)
1414 {
1415         float           *pos;
1416         vec3_t          pos2;
1417         VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1418
1419         pos = PRVM_G_VECTOR(OFS_PARM0);
1420         CL_FindNonSolidLocation(pos, pos2, 10);
1421         CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1422         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1423 }
1424
1425 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1426 static void VM_CL_te_smallflash (void)
1427 {
1428         float           *pos;
1429         vec3_t          pos2;
1430         VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1431
1432         pos = PRVM_G_VECTOR(OFS_PARM0);
1433         CL_FindNonSolidLocation(pos, pos2, 10);
1434         CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1435 }
1436
1437 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1438 static void VM_CL_te_customflash (void)
1439 {
1440         float           *pos;
1441         vec3_t          pos2;
1442         matrix4x4_t     tempmatrix;
1443         VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1444
1445         pos = PRVM_G_VECTOR(OFS_PARM0);
1446         CL_FindNonSolidLocation(pos, pos2, 4);
1447         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1448         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);
1449 }
1450
1451 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1452 static void VM_CL_te_gunshot (void)
1453 {
1454         float           *pos;
1455         vec3_t          pos2;
1456         VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1457
1458         pos = PRVM_G_VECTOR(OFS_PARM0);
1459         CL_FindNonSolidLocation(pos, pos2, 4);
1460         CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1461 }
1462
1463 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1464 static void VM_CL_te_spike (void)
1465 {
1466         float           *pos;
1467         vec3_t          pos2;
1468         int                     rnd;
1469         VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1470
1471         pos = PRVM_G_VECTOR(OFS_PARM0);
1472         CL_FindNonSolidLocation(pos, pos2, 4);
1473         CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1474         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1475         else
1476         {
1477                 rnd = rand() & 3;
1478                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1479                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1480                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1481         }
1482 }
1483
1484 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1485 static void VM_CL_te_superspike (void)
1486 {
1487         float           *pos;
1488         vec3_t          pos2;
1489         int                     rnd;
1490         VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1491
1492         pos = PRVM_G_VECTOR(OFS_PARM0);
1493         CL_FindNonSolidLocation(pos, pos2, 4);
1494         CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1495         if (rand() % 5)                 S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1496         else
1497         {
1498                 rnd = rand() & 3;
1499                 if (rnd == 1)           S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1500                 else if (rnd == 2)      S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1501                 else                            S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1502         }
1503 }
1504
1505 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1506 static void VM_CL_te_explosion (void)
1507 {
1508         float           *pos;
1509         vec3_t          pos2;
1510         VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1511
1512         pos = PRVM_G_VECTOR(OFS_PARM0);
1513         CL_FindNonSolidLocation(pos, pos2, 10);
1514         CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1515         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1516 }
1517
1518 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1519 static void VM_CL_te_tarexplosion (void)
1520 {
1521         float           *pos;
1522         vec3_t          pos2;
1523         VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1524
1525         pos = PRVM_G_VECTOR(OFS_PARM0);
1526         CL_FindNonSolidLocation(pos, pos2, 10);
1527         CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1528         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1529 }
1530
1531 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1532 static void VM_CL_te_wizspike (void)
1533 {
1534         float           *pos;
1535         vec3_t          pos2;
1536         VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1537
1538         pos = PRVM_G_VECTOR(OFS_PARM0);
1539         CL_FindNonSolidLocation(pos, pos2, 4);
1540         CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1541         S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1542 }
1543
1544 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1545 static void VM_CL_te_knightspike (void)
1546 {
1547         float           *pos;
1548         vec3_t          pos2;
1549         VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1550
1551         pos = PRVM_G_VECTOR(OFS_PARM0);
1552         CL_FindNonSolidLocation(pos, pos2, 4);
1553         CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1554         S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1555 }
1556
1557 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1558 static void VM_CL_te_lavasplash (void)
1559 {
1560         VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1561         CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1562 }
1563
1564 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1565 static void VM_CL_te_teleport (void)
1566 {
1567         VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1568         CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1569 }
1570
1571 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1572 static void VM_CL_te_explosion2 (void)
1573 {
1574         float           *pos;
1575         vec3_t          pos2, color;
1576         matrix4x4_t     tempmatrix;
1577         int                     colorStart, colorLength;
1578         unsigned char           *tempcolor;
1579         VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1580
1581         pos = PRVM_G_VECTOR(OFS_PARM0);
1582         colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1583         colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1584         CL_FindNonSolidLocation(pos, pos2, 10);
1585         CL_ParticleExplosion2(pos2, colorStart, colorLength);
1586         tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
1587         color[0] = tempcolor[0] * (2.0f / 255.0f);
1588         color[1] = tempcolor[1] * (2.0f / 255.0f);
1589         color[2] = tempcolor[2] * (2.0f / 255.0f);
1590         Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1591         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);
1592         S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1593 }
1594
1595
1596 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1597 static void VM_CL_te_lightning1 (void)
1598 {
1599         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1600         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1601 }
1602
1603 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1604 static void VM_CL_te_lightning2 (void)
1605 {
1606         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1607         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1608 }
1609
1610 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1611 static void VM_CL_te_lightning3 (void)
1612 {
1613         VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1614         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1615 }
1616
1617 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1618 static void VM_CL_te_beam (void)
1619 {
1620         VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1621         CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1622 }
1623
1624 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1625 static void VM_CL_te_plasmaburn (void)
1626 {
1627         float           *pos;
1628         vec3_t          pos2;
1629         VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1630
1631         pos = PRVM_G_VECTOR(OFS_PARM0);
1632         CL_FindNonSolidLocation(pos, pos2, 4);
1633         CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1634 }
1635
1636 // #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
1637 static void VM_CL_te_flamejet (void)
1638 {
1639         float *pos;
1640         vec3_t pos2;
1641         VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
1642         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1643                 return;
1644         pos = PRVM_G_VECTOR(OFS_PARM0);
1645         CL_FindNonSolidLocation(pos, pos2, 4);
1646         CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1647 }
1648
1649
1650 //====================================================================
1651 //DP_QC_GETSURFACE
1652
1653 extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1654
1655 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
1656 {
1657         if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1658                 return NULL;
1659         return model->data_surfaces + surfacenum + model->firstmodelsurface;
1660 }
1661
1662 // #434 float(entity e, float s) getsurfacenumpoints
1663 static void VM_CL_getsurfacenumpoints(void)
1664 {
1665         model_t *model;
1666         msurface_t *surface;
1667         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
1668         // return 0 if no such surface
1669         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1670         {
1671                 PRVM_G_FLOAT(OFS_RETURN) = 0;
1672                 return;
1673         }
1674
1675         // note: this (incorrectly) assumes it is a simple polygon
1676         PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1677 }
1678
1679 // #435 vector(entity e, float s, float n) getsurfacepoint
1680 static void VM_CL_getsurfacepoint(void)
1681 {
1682         prvm_edict_t *ed;
1683         model_t *model;
1684         msurface_t *surface;
1685         int pointnum;
1686         VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
1687         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1688         ed = PRVM_G_EDICT(OFS_PARM0);
1689         if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1690                 return;
1691         // note: this (incorrectly) assumes it is a simple polygon
1692         pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1693         if (pointnum < 0 || pointnum >= surface->num_vertices)
1694                 return;
1695         // FIXME: implement rotation/scaling
1696         VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1697 }
1698
1699 // #436 vector(entity e, float s) getsurfacenormal
1700 static void VM_CL_getsurfacenormal(void)
1701 {
1702         model_t *model;
1703         msurface_t *surface;
1704         vec3_t normal;
1705         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
1706         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1707         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1708                 return;
1709         // FIXME: implement rotation/scaling
1710         // note: this (incorrectly) assumes it is a simple polygon
1711         // note: this only returns the first triangle, so it doesn't work very
1712         // well for curved surfaces or arbitrary meshes
1713         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);
1714         VectorNormalize(normal);
1715         VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1716 }
1717
1718 // #437 string(entity e, float s) getsurfacetexture
1719 static void VM_CL_getsurfacetexture(void)
1720 {
1721         model_t *model;
1722         msurface_t *surface;
1723         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
1724         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1725         if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1726                 return;
1727         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
1728 }
1729
1730 // #438 float(entity e, vector p) getsurfacenearpoint
1731 static void VM_CL_getsurfacenearpoint(void)
1732 {
1733         int surfacenum, best;
1734         vec3_t clipped, p;
1735         vec_t dist, bestdist;
1736         prvm_edict_t *ed;
1737         model_t *model = NULL;
1738         msurface_t *surface;
1739         vec_t *point;
1740         VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
1741         PRVM_G_FLOAT(OFS_RETURN) = -1;
1742         ed = PRVM_G_EDICT(OFS_PARM0);
1743         if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
1744                 return;
1745
1746         // FIXME: implement rotation/scaling
1747         point = PRVM_G_VECTOR(OFS_PARM1);
1748         VectorSubtract(point, ed->fields.client->origin, p);
1749         best = -1;
1750         bestdist = 1000000000;
1751         for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1752         {
1753                 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1754                 // first see if the nearest point on the surface's box is closer than the previous match
1755                 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1756                 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1757                 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1758                 dist = VectorLength2(clipped);
1759                 if (dist < bestdist)
1760                 {
1761                         // it is, check the nearest point on the actual geometry
1762                         clippointtosurface(model, surface, p, clipped);
1763                         VectorSubtract(clipped, p, clipped);
1764                         dist += VectorLength2(clipped);
1765                         if (dist < bestdist)
1766                         {
1767                                 // that's closer too, store it as the best match
1768                                 best = surfacenum;
1769                                 bestdist = dist;
1770                         }
1771                 }
1772         }
1773         PRVM_G_FLOAT(OFS_RETURN) = best;
1774 }
1775
1776 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
1777 static void VM_CL_getsurfaceclippedpoint(void)
1778 {
1779         prvm_edict_t *ed;
1780         model_t *model;
1781         msurface_t *surface;
1782         vec3_t p, out;
1783         VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
1784         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1785         ed = PRVM_G_EDICT(OFS_PARM0);
1786         if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1787                 return;
1788         // FIXME: implement rotation/scaling
1789         VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
1790         clippointtosurface(model, surface, p, out);
1791         // FIXME: implement rotation/scaling
1792         VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1793 }
1794
1795 // #443 void(entity e, entity tagentity, string tagname) setattachment
1796 static void VM_CL_setattachment (void)
1797 {
1798         prvm_edict_t *e;
1799         prvm_edict_t *tagentity;
1800         const char *tagname;
1801         prvm_eval_t *v;
1802         int modelindex;
1803         model_t *model;
1804         VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
1805
1806         e = PRVM_G_EDICT(OFS_PARM0);
1807         tagentity = PRVM_G_EDICT(OFS_PARM1);
1808         tagname = PRVM_G_STRING(OFS_PARM2);
1809
1810         if (e == prog->edicts)
1811         {
1812                 VM_Warning("setattachment: can not modify world entity\n");
1813                 return;
1814         }
1815         if (e->priv.server->free)
1816         {
1817                 VM_Warning("setattachment: can not modify free entity\n");
1818                 return;
1819         }
1820
1821         if (tagentity == NULL)
1822                 tagentity = prog->edicts;
1823
1824         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
1825         if (v)
1826                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
1827
1828         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
1829         if (v)
1830                 v->_float = 0;
1831         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
1832         {
1833                 modelindex = (int)tagentity->fields.client->modelindex;
1834                 model = CL_GetModelByIndex(modelindex);
1835                 if (model)
1836                 {
1837                         v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
1838                         if (v->_float == 0)
1839                                 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);
1840                 }
1841                 else
1842                         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));
1843         }
1844 }
1845
1846 /////////////////////////////////////////
1847 // DP_MD3_TAGINFO extension coded by VorteX
1848
1849 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
1850 {
1851         model_t *model = CL_GetModelFromEdict(e);
1852         if (model)
1853                 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
1854         else
1855                 return -1;
1856 };
1857
1858 // Warnings/errors code:
1859 // 0 - normal (everything all-right)
1860 // 1 - world entity
1861 // 2 - free entity
1862 // 3 - null or non-precached model
1863 // 4 - no tags with requested index
1864 // 5 - runaway loop at attachment chain
1865 extern cvar_t cl_bob;
1866 extern cvar_t cl_bobcycle;
1867 extern cvar_t cl_bobup;
1868 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
1869 {
1870         prvm_eval_t *val;
1871         int reqframe, attachloop;
1872         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
1873         prvm_edict_t *attachent;
1874         model_t *model;
1875
1876         *out = identitymatrix; // warnings and errors return identical matrix
1877
1878         if (ent == prog->edicts)
1879                 return 1;
1880         if (ent->priv.server->free)
1881                 return 2;
1882
1883         model = CL_GetModelFromEdict(ent);
1884
1885         if(!model)
1886                 return 3;
1887
1888         if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
1889                 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
1890         else
1891                 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
1892
1893         // get initial tag matrix
1894         if (tagindex)
1895         {
1896                 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
1897                 if (ret)
1898                         return ret;
1899         }
1900         else
1901                 tagmatrix = identitymatrix;
1902
1903         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
1904         { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
1905                 attachloop = 0;
1906                 do
1907                 {
1908                         attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
1909                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
1910
1911                         model = CL_GetModelFromEdict(attachent);
1912
1913                         if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
1914                                 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
1915                         else
1916                                 attachmatrix = identitymatrix;
1917
1918                         // apply transformation by child entity matrix
1919                         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1920                         if (val->_float == 0)
1921                                 val->_float = 1;
1922                         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);
1923                         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1924                         Matrix4x4_Copy(&tagmatrix, out);
1925
1926                         // finally transformate by matrix of tag on parent entity
1927                         Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
1928                         Matrix4x4_Copy(&tagmatrix, out);
1929
1930                         ent = attachent;
1931                         attachloop += 1;
1932                         if (attachloop > 255) // prevent runaway looping
1933                                 return 5;
1934                 }
1935                 while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
1936         }
1937
1938         // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
1939         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1940         if (val->_float == 0)
1941                 val->_float = 1;
1942         // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
1943         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);
1944         Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1945
1946         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
1947         {// RENDER_VIEWMODEL magic
1948                 Matrix4x4_Copy(&tagmatrix, out);
1949
1950                 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
1951                 if (val->_float == 0)
1952                         val->_float = 1;
1953
1954                 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
1955                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
1956
1957                 /*
1958                 // Cl_bob, ported from rendering code
1959                 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
1960                 {
1961                         double bob, cycle;
1962                         // LordHavoc: this code is *weird*, but not replacable (I think it
1963                         // should be done in QC on the server, but oh well, quake is quake)
1964                         // LordHavoc: figured out bobup: the time at which the sin is at 180
1965                         // degrees (which allows lengthening or squishing the peak or valley)
1966                         cycle = sv.time/cl_bobcycle.value;
1967                         cycle -= (int)cycle;
1968                         if (cycle < cl_bobup.value)
1969                                 cycle = sin(M_PI * cycle / cl_bobup.value);
1970                         else
1971                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
1972                         // bob is proportional to velocity in the xy plane
1973                         // (don't count Z, or jumping messes it up)
1974                         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;
1975                         bob = bob*0.3 + bob*0.7*cycle;
1976                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
1977                 }
1978                 */
1979         }
1980         return 0;
1981 }
1982
1983 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
1984 static void VM_CL_gettagindex (void)
1985 {
1986         prvm_edict_t *ent;
1987         const char *tag_name;
1988         int modelindex, tag_index;
1989
1990         VM_SAFEPARMCOUNT(2, VM_CL_gettagindex);
1991
1992         ent = PRVM_G_EDICT(OFS_PARM0);
1993         tag_name = PRVM_G_STRING(OFS_PARM1);
1994         if (ent == prog->edicts)
1995         {
1996                 VM_Warning("gettagindex: can't affect world entity\n");
1997                 return;
1998         }
1999         if (ent->priv.server->free)
2000         {
2001                 VM_Warning("gettagindex: can't affect free entity\n");
2002                 return;
2003         }
2004
2005         modelindex = (int)ent->fields.client->modelindex;
2006         if(modelindex < 0)
2007                 modelindex = -(modelindex+1);
2008         tag_index = 0;
2009         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2010                 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2011         else
2012         {
2013                 tag_index = CL_GetTagIndex(ent, tag_name);
2014                 if (tag_index == 0)
2015                         Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2016         }
2017         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2018 }
2019
2020 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2021 static void VM_CL_gettaginfo (void)
2022 {
2023         prvm_edict_t *e;
2024         int tagindex;
2025         matrix4x4_t tag_matrix;
2026         int returncode;
2027
2028         VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
2029
2030         e = PRVM_G_EDICT(OFS_PARM0);
2031         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2032         returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2033         Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2034
2035         switch(returncode)
2036         {
2037                 case 1:
2038                         VM_Warning("gettagindex: can't affect world entity\n");
2039                         break;
2040                 case 2:
2041                         VM_Warning("gettagindex: can't affect free entity\n");
2042                         break;
2043                 case 3:
2044                         Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2045                         break;
2046                 case 4:
2047                         Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2048                         break;
2049                 case 5:
2050                         Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2051                         break;
2052         }
2053 }
2054
2055 //============================================================================
2056
2057 //====================
2058 //QC POLYGON functions
2059 //====================
2060
2061 typedef struct
2062 {
2063         rtexture_t              *tex;
2064         float                   data[36];       //[515]: enough for polygons
2065         unsigned char                   flags;  //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
2066 }vm_polygon_t;
2067
2068 //static float                  vm_polygon_linewidth = 1;
2069 static mempool_t                *vm_polygons_pool = NULL;
2070 static unsigned char                    vm_current_vertices = 0;
2071 static qboolean                 vm_polygons_initialized = false;
2072 static vm_polygon_t             *vm_polygons = NULL;
2073 static unsigned long    vm_polygons_num = 0, vm_drawpolygons_num = 0;   //[515]: ok long on 64bit ?
2074 static qboolean                 vm_polygonbegin = false;        //[515]: for "no-crap-on-the-screen" check
2075 #define VM_DEFPOLYNUM 64        //[515]: enough for default ?
2076
2077 #define VM_POLYGON_FL3V         16      //more than 2 vertices (used only for lines)
2078 #define VM_POLYGON_FLLINES      32
2079 #define VM_POLYGON_FL2D         64
2080 #define VM_POLYGON_FL4V         128     //4 vertices
2081
2082 static void VM_InitPolygons (void)
2083 {
2084         vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
2085         vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
2086         memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
2087         vm_polygons_num = VM_DEFPOLYNUM;
2088         vm_drawpolygons_num = 0;
2089         vm_polygonbegin = false;
2090         vm_polygons_initialized = true;
2091 }
2092
2093 static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2094 {
2095         int surfacelistindex;
2096         // LordHavoc: FIXME: this is stupid code
2097         for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
2098         {
2099                 const vm_polygon_t      *p = &vm_polygons[surfacelist[surfacelistindex]];
2100                 int                                     flags = p->flags & 0x0f;
2101
2102                 if(flags == DRAWFLAG_ADDITIVE)
2103                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2104                 else if(flags == DRAWFLAG_MODULATE)
2105                         GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
2106                 else if(flags == DRAWFLAG_2XMODULATE)
2107                         GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
2108                 else
2109                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110
2111                 R_Mesh_TexBind(0, R_GetTexture(p->tex));
2112
2113                 CHECKGLERROR
2114                 //[515]: is speed is max ?
2115                 if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
2116                 {
2117                         qglLineWidth(p->data[13]);CHECKGLERROR
2118                         qglBegin(GL_LINE_LOOP);
2119                                 qglTexCoord1f   (p->data[12]);
2120                                 qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
2121                                 qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
2122
2123                                 qglTexCoord1f   (p->data[14]);
2124                                 qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
2125                                 qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
2126
2127                                 if(p->flags & VM_POLYGON_FL3V)
2128                                 {
2129                                         qglTexCoord1f   (p->data[16]);
2130                                         qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
2131                                         qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
2132
2133                                         if(p->flags & VM_POLYGON_FL4V)
2134                                         {
2135                                                 qglTexCoord1f   (p->data[18]);
2136                                                 qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
2137                                                 qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
2138                                         }
2139                                 }
2140                         qglEnd();
2141                         CHECKGLERROR
2142                 }
2143                 else
2144                 {
2145                         qglBegin(GL_POLYGON);
2146                                 qglTexCoord2f   (p->data[12], p->data[13]);
2147                                 qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
2148                                 qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
2149
2150                                 qglTexCoord2f   (p->data[14], p->data[15]);
2151                                 qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
2152                                 qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
2153
2154                                 qglTexCoord2f   (p->data[16], p->data[17]);
2155                                 qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
2156                                 qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
2157
2158                                 if(p->flags & VM_POLYGON_FL4V)
2159                                 {
2160                                         qglTexCoord2f   (p->data[18], p->data[19]);
2161                                         qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
2162                                         qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
2163                                 }
2164                         qglEnd();
2165                         CHECKGLERROR
2166                 }
2167         }
2168 }
2169
2170 static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p)
2171 {
2172         drawqueuemesh_t mesh;
2173         static int              picelements[6] = {0, 1, 2, 0, 2, 3};
2174
2175         mesh.texture = p->tex;
2176         mesh.data_element3i = picelements;
2177         mesh.data_vertex3f = p->data;
2178         mesh.data_texcoord2f = p->data + 12;
2179         mesh.data_color4f = p->data + 20;
2180         if(p->flags & VM_POLYGON_FL4V)
2181         {
2182                 mesh.num_vertices = 4;
2183                 mesh.num_triangles = 2;
2184         }
2185         else
2186         {
2187                 mesh.num_vertices = 3;
2188                 mesh.num_triangles = 1;
2189         }
2190         if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
2191                 DrawQ_LineLoop (&mesh, (p->flags&0x0f));
2192         else
2193                 DrawQ_Mesh (&mesh, (p->flags&0x0f));
2194 }
2195
2196 void VM_CL_AddPolygonsToMeshQueue (void)
2197 {
2198         int i;
2199         if(!vm_drawpolygons_num)
2200                 return;
2201         R_Mesh_Matrix(&identitymatrix);
2202         GL_CullFace(GL_NONE);
2203         for(i = 0;i < (int)vm_drawpolygons_num;i++)
2204                 VM_DrawPolygonCallback(NULL, NULL, 1, &i);
2205         vm_drawpolygons_num = 0;
2206 }
2207
2208 //void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon
2209 static void VM_CL_R_PolygonBegin (void)
2210 {
2211         vm_polygon_t    *p;
2212         const char              *picname;
2213         VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin);
2214
2215         if(!vm_polygons_initialized)
2216                 VM_InitPolygons();
2217         if(vm_polygonbegin)
2218         {
2219                 VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n");
2220                 return;
2221         }
2222         if(vm_drawpolygons_num >= vm_polygons_num)
2223         {
2224                 p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2225                 memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2226                 memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
2227                 Mem_Free(vm_polygons);
2228                 vm_polygons = p;
2229                 vm_polygons_num *= 2;
2230         }
2231         p = &vm_polygons[vm_drawpolygons_num];
2232         picname = PRVM_G_STRING(OFS_PARM0);
2233         if(picname[0])
2234                 p->tex = Draw_CachePic(picname, true)->tex;
2235         else
2236                 p->tex = r_texture_white;
2237         p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
2238         vm_current_vertices = 0;
2239         vm_polygonbegin = true;
2240         if(prog->argc >= 3)
2241         {
2242                 if(PRVM_G_FLOAT(OFS_PARM2))
2243                         p->flags |= VM_POLYGON_FL2D;
2244                 if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3))
2245                 {
2246                         p->data[13] = PRVM_G_FLOAT(OFS_PARM3);  //[515]: linewidth
2247                         p->flags |= VM_POLYGON_FLLINES;
2248                 }
2249         }
2250 }
2251
2252 //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2253 static void VM_CL_R_PolygonVertex (void)
2254 {
2255         float                   *coords, *tx, *rgb, alpha;
2256         vm_polygon_t    *p;
2257         VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
2258
2259         if(!vm_polygonbegin)
2260         {
2261                 VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
2262                 return;
2263         }
2264         coords  = PRVM_G_VECTOR(OFS_PARM0);
2265         tx              = PRVM_G_VECTOR(OFS_PARM1);
2266         rgb             = PRVM_G_VECTOR(OFS_PARM2);
2267         alpha = PRVM_G_FLOAT(OFS_PARM3);
2268
2269         p = &vm_polygons[vm_drawpolygons_num];
2270         if(vm_current_vertices > 4)
2271         {
2272                 VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n");
2273                 return;
2274         }
2275
2276         p->data[vm_current_vertices*3]          = coords[0];
2277         p->data[1+vm_current_vertices*3]        = coords[1];
2278         p->data[2+vm_current_vertices*3]        = coords[2];
2279
2280         p->data[12+vm_current_vertices*2]       = tx[0];
2281         if(!(p->flags & VM_POLYGON_FLLINES))
2282                 p->data[13+vm_current_vertices*2]       = tx[1];
2283
2284         p->data[20+vm_current_vertices*4]       = rgb[0];
2285         p->data[21+vm_current_vertices*4]       = rgb[1];
2286         p->data[22+vm_current_vertices*4]       = rgb[2];
2287         p->data[23+vm_current_vertices*4]       = alpha;
2288
2289         vm_current_vertices++;
2290         if(vm_current_vertices == 4)
2291                 p->flags |= VM_POLYGON_FL4V;
2292         else
2293                 if(vm_current_vertices == 3)
2294                         p->flags |= VM_POLYGON_FL3V;
2295 }
2296
2297 //void() R_EndPolygon
2298 static void VM_CL_R_PolygonEnd (void)
2299 {
2300         VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
2301         if(!vm_polygonbegin)
2302         {
2303                 VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
2304                 return;
2305         }
2306         vm_polygonbegin = false;
2307         if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
2308         {
2309                 if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
2310                         VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
2311                 else
2312                         vm_drawpolygons_num++;
2313         }
2314         else
2315                 VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
2316 }
2317
2318 void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
2319 {
2320         vm_polygon_t    *p;
2321
2322         if(!vm_polygons_initialized)
2323                 VM_InitPolygons();
2324         if(vm_polygonbegin)
2325         {
2326                 Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
2327                 return;
2328         }
2329         // limit polygons to a vaguely sane amount, beyond this each one just
2330         // replaces the last one
2331         vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
2332         if(vm_drawpolygons_num >= vm_polygons_num)
2333         {
2334                 p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2335                 memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
2336                 memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
2337                 Mem_Free(vm_polygons);
2338                 vm_polygons = p;
2339                 vm_polygons_num *= 2;
2340         }
2341         p = &vm_polygons[vm_drawpolygons_num];
2342         if(picname && picname[0])
2343                 p->tex = Draw_CachePic(picname, true)->tex;
2344         else
2345                 p->tex = r_texture_white;
2346         p->flags = flags;
2347         vm_current_vertices = 0;
2348         vm_polygonbegin = true;
2349         if(draw2d)
2350                 p->flags |= VM_POLYGON_FL2D;
2351         if(linewidth)
2352         {
2353                 p->data[13] = linewidth;        //[515]: linewidth
2354                 p->flags |= VM_POLYGON_FLLINES;
2355         }
2356 }
2357
2358 void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
2359 {
2360         vm_polygon_t    *p;
2361
2362         if(!vm_polygonbegin)
2363         {
2364                 Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
2365                 return;
2366         }
2367
2368         p = &vm_polygons[vm_drawpolygons_num];
2369         if(vm_current_vertices > 4)
2370         {
2371                 Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
2372                 return;
2373         }
2374
2375         p->data[vm_current_vertices*3]          = x;
2376         p->data[1+vm_current_vertices*3]        = y;
2377         p->data[2+vm_current_vertices*3]        = z;
2378
2379         p->data[12+vm_current_vertices*2]       = s;
2380         if(!(p->flags & VM_POLYGON_FLLINES))
2381                 p->data[13+vm_current_vertices*2]       = t;
2382
2383         p->data[20+vm_current_vertices*4]       = r;
2384         p->data[21+vm_current_vertices*4]       = g;
2385         p->data[22+vm_current_vertices*4]       = b;
2386         p->data[23+vm_current_vertices*4]       = a;
2387
2388         vm_current_vertices++;
2389         if(vm_current_vertices == 4)
2390                 p->flags |= VM_POLYGON_FL4V;
2391         else
2392                 if(vm_current_vertices == 3)
2393                         p->flags |= VM_POLYGON_FL3V;
2394 }
2395
2396 void Debug_PolygonEnd(void)
2397 {
2398         if(!vm_polygonbegin)
2399         {
2400                 Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
2401                 return;
2402         }
2403         vm_polygonbegin = false;
2404         if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
2405         {
2406                 if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D)    //[515]: don't use qcpolygons memory if 2D
2407                         VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
2408                 else
2409                         vm_drawpolygons_num++;
2410         }
2411         else
2412                 Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
2413 }
2414
2415 /*
2416 =============
2417 CL_CheckBottom
2418
2419 Returns false if any part of the bottom of the entity is off an edge that
2420 is not a staircase.
2421
2422 =============
2423 */
2424 qboolean CL_CheckBottom (prvm_edict_t *ent)
2425 {
2426         vec3_t  mins, maxs, start, stop;
2427         trace_t trace;
2428         int             x, y;
2429         float   mid, bottom;
2430
2431         VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
2432         VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
2433
2434 // if all of the points under the corners are solid world, don't bother
2435 // with the tougher checks
2436 // the corners must be within 16 of the midpoint
2437         start[2] = mins[2] - 1;
2438         for     (x=0 ; x<=1 ; x++)
2439                 for     (y=0 ; y<=1 ; y++)
2440                 {
2441                         start[0] = x ? maxs[0] : mins[0];
2442                         start[1] = y ? maxs[1] : mins[1];
2443                         if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
2444                                 goto realcheck;
2445                 }
2446
2447         return true;            // we got out easy
2448
2449 realcheck:
2450 //
2451 // check it for real...
2452 //
2453         start[2] = mins[2];
2454
2455 // the midpoint must be within 16 of the bottom
2456         start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
2457         start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
2458         stop[2] = start[2] - 2*sv_stepheight.value;
2459         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2460
2461         if (trace.fraction == 1.0)
2462                 return false;
2463         mid = bottom = trace.endpos[2];
2464
2465 // the corners must be within 16 of the midpoint
2466         for     (x=0 ; x<=1 ; x++)
2467                 for     (y=0 ; y<=1 ; y++)
2468                 {
2469                         start[0] = stop[0] = x ? maxs[0] : mins[0];
2470                         start[1] = stop[1] = y ? maxs[1] : mins[1];
2471
2472                         trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2473
2474                         if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
2475                                 bottom = trace.endpos[2];
2476                         if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
2477                                 return false;
2478                 }
2479
2480         return true;
2481 }
2482
2483 /*
2484 =============
2485 CL_movestep
2486
2487 Called by monster program code.
2488 The move will be adjusted for slopes and stairs, but if the move isn't
2489 possible, no move is done and false is returned
2490 =============
2491 */
2492 qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
2493 {
2494         float           dz;
2495         vec3_t          oldorg, neworg, end, traceendpos;
2496         trace_t         trace;
2497         int                     i;
2498         prvm_edict_t            *enemy;
2499         prvm_eval_t     *val;
2500
2501 // try the move
2502         VectorCopy (ent->fields.client->origin, oldorg);
2503         VectorAdd (ent->fields.client->origin, move, neworg);
2504
2505 // flying monsters don't step up
2506         if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
2507         {
2508         // try one move with vertical motion, then one without
2509                 for (i=0 ; i<2 ; i++)
2510                 {
2511                         VectorAdd (ent->fields.client->origin, move, neworg);
2512                         enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
2513                         if (i == 0 && enemy != prog->edicts)
2514                         {
2515                                 dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
2516                                 if (dz > 40)
2517                                         neworg[2] -= 8;
2518                                 if (dz < 30)
2519                                         neworg[2] += 8;
2520                         }
2521                         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);
2522                         if (settrace)
2523                                 VM_SetTraceGlobals(&trace);
2524
2525                         if (trace.fraction == 1)
2526                         {
2527                                 VectorCopy(trace.endpos, traceendpos);
2528                                 if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
2529                                         return false;   // swim monster left water
2530
2531                                 VectorCopy (traceendpos, ent->fields.client->origin);
2532                                 if (relink)
2533                                         CL_LinkEdict(ent);
2534                                 return true;
2535                         }
2536
2537                         if (enemy == prog->edicts)
2538                                 break;
2539                 }
2540
2541                 return false;
2542         }
2543
2544 // push down from a step height above the wished position
2545         neworg[2] += sv_stepheight.value;
2546         VectorCopy (neworg, end);
2547         end[2] -= sv_stepheight.value*2;
2548
2549         trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2550         if (settrace)
2551                 VM_SetTraceGlobals(&trace);
2552
2553         if (trace.startsolid)
2554         {
2555                 neworg[2] -= sv_stepheight.value;
2556                 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2557                 if (settrace)
2558                         VM_SetTraceGlobals(&trace);
2559                 if (trace.startsolid)
2560                         return false;
2561         }
2562         if (trace.fraction == 1)
2563         {
2564         // if monster had the ground pulled out, go ahead and fall
2565                 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2566                 {
2567                         VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
2568                         if (relink)
2569                                 CL_LinkEdict(ent);
2570                         ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
2571                         return true;
2572                 }
2573
2574                 return false;           // walked off an edge
2575         }
2576
2577 // check point traces down for dangling corners
2578         VectorCopy (trace.endpos, ent->fields.client->origin);
2579
2580         if (!CL_CheckBottom (ent))
2581         {
2582                 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2583                 {       // entity had floor mostly pulled out from underneath it
2584                         // and is trying to correct
2585                         if (relink)
2586                                 CL_LinkEdict(ent);
2587                         return true;
2588                 }
2589                 VectorCopy (oldorg, ent->fields.client->origin);
2590                 return false;
2591         }
2592
2593         if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2594                 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
2595
2596         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
2597                 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
2598
2599 // the move is ok
2600         if (relink)
2601                 CL_LinkEdict(ent);
2602         return true;
2603 }
2604
2605 /*
2606 ===============
2607 VM_CL_walkmove
2608
2609 float(float yaw, float dist[, settrace]) walkmove
2610 ===============
2611 */
2612 static void VM_CL_walkmove (void)
2613 {
2614         prvm_edict_t    *ent;
2615         float   yaw, dist;
2616         vec3_t  move;
2617         mfunction_t     *oldf;
2618         int     oldself;
2619         qboolean        settrace;
2620
2621         VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
2622
2623         // assume failure if it returns early
2624         PRVM_G_FLOAT(OFS_RETURN) = 0;
2625
2626         ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
2627         if (ent == prog->edicts)
2628         {
2629                 VM_Warning("walkmove: can not modify world entity\n");
2630                 return;
2631         }
2632         if (ent->priv.server->free)
2633         {
2634                 VM_Warning("walkmove: can not modify free entity\n");
2635                 return;
2636         }
2637         yaw = PRVM_G_FLOAT(OFS_PARM0);
2638         dist = PRVM_G_FLOAT(OFS_PARM1);
2639         settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
2640
2641         if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
2642                 return;
2643
2644         yaw = yaw*M_PI*2 / 360;
2645
2646         move[0] = cos(yaw)*dist;
2647         move[1] = sin(yaw)*dist;
2648         move[2] = 0;
2649
2650 // save program state, because CL_movestep may call other progs
2651         oldf = prog->xfunction;
2652         oldself = prog->globals.client->self;
2653
2654         PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
2655
2656
2657 // restore program state
2658         prog->xfunction = oldf;
2659         prog->globals.client->self = oldself;
2660 }
2661
2662 /*
2663 ===============
2664 VM_CL_serverkey
2665
2666 string(string key) serverkey
2667 ===============
2668 */
2669 void VM_CL_serverkey(void)
2670 {
2671         char string[VM_STRINGTEMP_LENGTH];
2672         VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
2673         InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2674         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2675 }
2676
2677 //============================================================================
2678
2679 prvm_builtin_t vm_cl_builtins[] = {
2680 NULL,                                                   // #0 NULL function (not callable) (QUAKE)
2681 VM_CL_makevectors,                              // #1 void(vector ang) makevectors (QUAKE)
2682 VM_CL_setorigin,                                // #2 void(entity e, vector o) setorigin (QUAKE)
2683 VM_CL_setmodel,                                 // #3 void(entity e, string m) setmodel (QUAKE)
2684 VM_CL_setsize,                                  // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2685 NULL,                                                   // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2686 VM_break,                                               // #6 void() break (QUAKE)
2687 VM_random,                                              // #7 float() random (QUAKE)
2688 VM_CL_sound,                                    // #8 void(entity e, float chan, string samp) sound (QUAKE)
2689 VM_normalize,                                   // #9 vector(vector v) normalize (QUAKE)
2690 VM_error,                                               // #10 void(string e) error (QUAKE)
2691 VM_objerror,                                    // #11 void(string e) objerror (QUAKE)
2692 VM_vlen,                                                // #12 float(vector v) vlen (QUAKE)
2693 VM_vectoyaw,                                    // #13 float(vector v) vectoyaw (QUAKE)
2694 VM_CL_spawn,                                    // #14 entity() spawn (QUAKE)
2695 VM_remove,                                              // #15 void(entity e) remove (QUAKE)
2696 VM_CL_traceline,                                // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2697 NULL,                                                   // #17 entity() checkclient (QUAKE)
2698 VM_find,                                                // #18 entity(entity start, .string fld, string match) find (QUAKE)
2699 VM_precache_sound,                              // #19 void(string s) precache_sound (QUAKE)
2700 VM_CL_precache_model,                   // #20 void(string s) precache_model (QUAKE)
2701 NULL,                                                   // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2702 VM_CL_findradius,                               // #22 entity(vector org, float rad) findradius (QUAKE)
2703 NULL,                                                   // #23 void(string s, ...) bprint (QUAKE)
2704 NULL,                                                   // #24 void(entity client, string s, ...) sprint (QUAKE)
2705 VM_dprint,                                              // #25 void(string s, ...) dprint (QUAKE)
2706 VM_ftos,                                                // #26 string(float f) ftos (QUAKE)
2707 VM_vtos,                                                // #27 string(vector v) vtos (QUAKE)
2708 VM_coredump,                                    // #28 void() coredump (QUAKE)
2709 VM_traceon,                                             // #29 void() traceon (QUAKE)
2710 VM_traceoff,                                    // #30 void() traceoff (QUAKE)
2711 VM_eprint,                                              // #31 void(entity e) eprint (QUAKE)
2712 VM_CL_walkmove,                                 // #32 float(float yaw, float dist) walkmove (QUAKE)
2713 NULL,                                                   // #33 (QUAKE)
2714 VM_CL_droptofloor,                              // #34 float() droptofloor (QUAKE)
2715 VM_CL_lightstyle,                               // #35 void(float style, string value) lightstyle (QUAKE)
2716 VM_rint,                                                // #36 float(float v) rint (QUAKE)
2717 VM_floor,                                               // #37 float(float v) floor (QUAKE)
2718 VM_ceil,                                                // #38 float(float v) ceil (QUAKE)
2719 NULL,                                                   // #39 (QUAKE)
2720 VM_CL_checkbottom,                              // #40 float(entity e) checkbottom (QUAKE)
2721 VM_CL_pointcontents,                    // #41 float(vector v) pointcontents (QUAKE)
2722 NULL,                                                   // #42 (QUAKE)
2723 VM_fabs,                                                // #43 float(float f) fabs (QUAKE)
2724 NULL,                                                   // #44 vector(entity e, float speed) aim (QUAKE)
2725 VM_cvar,                                                // #45 float(string s) cvar (QUAKE)
2726 VM_localcmd,                                    // #46 void(string s) localcmd (QUAKE)
2727 VM_nextent,                                             // #47 entity(entity e) nextent (QUAKE)
2728 VM_CL_particle,                                 // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2729 VM_changeyaw,                                   // #49 void() ChangeYaw (QUAKE)
2730 NULL,                                                   // #50 (QUAKE)
2731 VM_vectoangles,                                 // #51 vector(vector v) vectoangles (QUAKE)
2732 NULL,                                                   // #52 void(float to, float f) WriteByte (QUAKE)
2733 NULL,                                                   // #53 void(float to, float f) WriteChar (QUAKE)
2734 NULL,                                                   // #54 void(float to, float f) WriteShort (QUAKE)
2735 NULL,                                                   // #55 void(float to, float f) WriteLong (QUAKE)
2736 NULL,                                                   // #56 void(float to, float f) WriteCoord (QUAKE)
2737 NULL,                                                   // #57 void(float to, float f) WriteAngle (QUAKE)
2738 NULL,                                                   // #58 void(float to, string s) WriteString (QUAKE)
2739 NULL,                                                   // #59 (QUAKE)
2740 VM_sin,                                                 // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2741 VM_cos,                                                 // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2742 VM_sqrt,                                                // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2743 VM_changepitch,                                 // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2744 VM_CL_tracetoss,                                // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2745 VM_etos,                                                // #65 string(entity ent) etos (DP_QC_ETOS)
2746 NULL,                                                   // #66 (QUAKE)
2747 NULL,                                                   // #67 void(float step) movetogoal (QUAKE)
2748 VM_precache_file,                               // #68 string(string s) precache_file (QUAKE)
2749 VM_CL_makestatic,                               // #69 void(entity e) makestatic (QUAKE)
2750 NULL,                                                   // #70 void(string s) changelevel (QUAKE)
2751 NULL,                                                   // #71 (QUAKE)
2752 VM_cvar_set,                                    // #72 void(string var, string val) cvar_set (QUAKE)
2753 NULL,                                                   // #73 void(entity client, strings) centerprint (QUAKE)
2754 VM_CL_ambientsound,                             // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2755 VM_CL_precache_model,                   // #75 string(string s) precache_model2 (QUAKE)
2756 VM_precache_sound,                              // #76 string(string s) precache_sound2 (QUAKE)
2757 VM_precache_file,                               // #77 string(string s) precache_file2 (QUAKE)
2758 NULL,                                                   // #78 void(entity e) setspawnparms (QUAKE)
2759 NULL,                                                   // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2760 NULL,                                                   // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2761 VM_stof,                                                // #81 float(string s) stof (FRIK_FILE)
2762 NULL,                                                   // #82 void(vector where, float set) multicast (QUAKEWORLD)
2763 NULL,                                                   // #83 (QUAKE)
2764 NULL,                                                   // #84 (QUAKE)
2765 NULL,                                                   // #85 (QUAKE)
2766 NULL,                                                   // #86 (QUAKE)
2767 NULL,                                                   // #87 (QUAKE)
2768 NULL,                                                   // #88 (QUAKE)
2769 NULL,                                                   // #89 (QUAKE)
2770 VM_CL_tracebox,                                 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2771 VM_randomvec,                                   // #91 vector() randomvec (DP_QC_RANDOMVEC)
2772 VM_CL_getlight,                                 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2773 VM_registercvar,                                // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2774 VM_min,                                                 // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2775 VM_max,                                                 // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2776 VM_bound,                                               // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2777 VM_pow,                                                 // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2778 VM_findfloat,                                   // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2779 VM_checkextension,                              // #99 float(string s) checkextension (the basis of the extension system)
2780 // FrikaC and Telejano range #100-#199
2781 NULL,                                                   // #100
2782 NULL,                                                   // #101
2783 NULL,                                                   // #102
2784 NULL,                                                   // #103
2785 NULL,                                                   // #104
2786 NULL,                                                   // #105
2787 NULL,                                                   // #106
2788 NULL,                                                   // #107
2789 NULL,                                                   // #108
2790 NULL,                                                   // #109
2791 VM_fopen,                                               // #110 float(string filename, float mode) fopen (FRIK_FILE)
2792 VM_fclose,                                              // #111 void(float fhandle) fclose (FRIK_FILE)
2793 VM_fgets,                                               // #112 string(float fhandle) fgets (FRIK_FILE)
2794 VM_fputs,                                               // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2795 VM_strlen,                                              // #114 float(string s) strlen (FRIK_FILE)
2796 VM_strcat,                                              // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
2797 VM_substring,                                   // #116 string(string s, float start, float length) substring (FRIK_FILE)
2798 VM_stov,                                                // #117 vector(string) stov (FRIK_FILE)
2799 VM_strzone,                                             // #118 string(string s) strzone (FRIK_FILE)
2800 VM_strunzone,                                   // #119 void(string s) strunzone (FRIK_FILE)
2801 NULL,                                                   // #120
2802 NULL,                                                   // #121
2803 NULL,                                                   // #122
2804 NULL,                                                   // #123
2805 NULL,                                                   // #124
2806 NULL,                                                   // #125
2807 NULL,                                                   // #126
2808 NULL,                                                   // #127
2809 NULL,                                                   // #128
2810 NULL,                                                   // #129
2811 NULL,                                                   // #130
2812 NULL,                                                   // #131
2813 NULL,                                                   // #132
2814 NULL,                                                   // #133
2815 NULL,                                                   // #134
2816 NULL,                                                   // #135
2817 NULL,                                                   // #136
2818 NULL,                                                   // #137
2819 NULL,                                                   // #138
2820 NULL,                                                   // #139
2821 NULL,                                                   // #140
2822 NULL,                                                   // #141
2823 NULL,                                                   // #142
2824 NULL,                                                   // #143
2825 NULL,                                                   // #144
2826 NULL,                                                   // #145
2827 NULL,                                                   // #146
2828 NULL,                                                   // #147
2829 NULL,                                                   // #148
2830 NULL,                                                   // #149
2831 NULL,                                                   // #150
2832 NULL,                                                   // #151
2833 NULL,                                                   // #152
2834 NULL,                                                   // #153
2835 NULL,                                                   // #154
2836 NULL,                                                   // #155
2837 NULL,                                                   // #156
2838 NULL,                                                   // #157
2839 NULL,                                                   // #158
2840 NULL,                                                   // #159
2841 NULL,                                                   // #160
2842 NULL,                                                   // #161
2843 NULL,                                                   // #162
2844 NULL,                                                   // #163
2845 NULL,                                                   // #164
2846 NULL,                                                   // #165
2847 NULL,                                                   // #166
2848 NULL,                                                   // #167
2849 NULL,                                                   // #168
2850 NULL,                                                   // #169
2851 NULL,                                                   // #170
2852 NULL,                                                   // #171
2853 NULL,                                                   // #172
2854 NULL,                                                   // #173
2855 NULL,                                                   // #174
2856 NULL,                                                   // #175
2857 NULL,                                                   // #176
2858 NULL,                                                   // #177
2859 NULL,                                                   // #178
2860 NULL,                                                   // #179
2861 NULL,                                                   // #180
2862 NULL,                                                   // #181
2863 NULL,                                                   // #182
2864 NULL,                                                   // #183
2865 NULL,                                                   // #184
2866 NULL,                                                   // #185
2867 NULL,                                                   // #186
2868 NULL,                                                   // #187
2869 NULL,                                                   // #188
2870 NULL,                                                   // #189
2871 NULL,                                                   // #190
2872 NULL,                                                   // #191
2873 NULL,                                                   // #192
2874 NULL,                                                   // #193
2875 NULL,                                                   // #194
2876 NULL,                                                   // #195
2877 NULL,                                                   // #196
2878 NULL,                                                   // #197
2879 NULL,                                                   // #198
2880 NULL,                                                   // #199
2881 // FTEQW range #200-#299
2882 NULL,                                                   // #200
2883 NULL,                                                   // #201
2884 NULL,                                                   // #202
2885 NULL,                                                   // #203
2886 NULL,                                                   // #204
2887 NULL,                                                   // #205
2888 NULL,                                                   // #206
2889 NULL,                                                   // #207
2890 NULL,                                                   // #208
2891 NULL,                                                   // #209
2892 NULL,                                                   // #210
2893 NULL,                                                   // #211
2894 NULL,                                                   // #212
2895 NULL,                                                   // #213
2896 NULL,                                                   // #214
2897 NULL,                                                   // #215
2898 NULL,                                                   // #216
2899 NULL,                                                   // #217
2900 VM_bitshift,                                    // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2901 NULL,                                                   // #219
2902 NULL,                                                   // #220
2903 NULL,                                                   // #221
2904 VM_str2chr,                                             // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
2905 VM_chr2str,                                             // #223 string(float c, ...) chr2str (FTE_STRINGS)
2906 NULL,                                                   // #224
2907 NULL,                                                   // #225
2908 NULL,                                                   // #226
2909 NULL,                                                   // #227
2910 VM_strncmp,                                             // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2911 NULL,                                                   // #229
2912 NULL,                                                   // #230
2913 NULL,                                                   // #231
2914 NULL,                                                   // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2915 NULL,                                                   // #233
2916 NULL,                                                   // #234
2917 NULL,                                                   // #235
2918 NULL,                                                   // #236
2919 NULL,                                                   // #237
2920 NULL,                                                   // #238
2921 NULL,                                                   // #239
2922 NULL,                                                   // #240
2923 NULL,                                                   // #241
2924 NULL,                                                   // #242
2925 NULL,                                                   // #243
2926 NULL,                                                   // #244
2927 NULL,                                                   // #245
2928 NULL,                                                   // #246
2929 NULL,                                                   // #247
2930 NULL,                                                   // #248
2931 NULL,                                                   // #249
2932 NULL,                                                   // #250
2933 NULL,                                                   // #251
2934 NULL,                                                   // #252
2935 NULL,                                                   // #253
2936 NULL,                                                   // #254
2937 NULL,                                                   // #255
2938 NULL,                                                   // #256
2939 NULL,                                                   // #257
2940 NULL,                                                   // #258
2941 NULL,                                                   // #259
2942 NULL,                                                   // #260
2943 NULL,                                                   // #261
2944 NULL,                                                   // #262
2945 NULL,                                                   // #263
2946 NULL,                                                   // #264
2947 NULL,                                                   // #265
2948 NULL,                                                   // #266
2949 NULL,                                                   // #267
2950 NULL,                                                   // #268
2951 NULL,                                                   // #269
2952 NULL,                                                   // #270
2953 NULL,                                                   // #271
2954 NULL,                                                   // #272
2955 NULL,                                                   // #273
2956 NULL,                                                   // #274
2957 NULL,                                                   // #275
2958 NULL,                                                   // #276
2959 NULL,                                                   // #277
2960 NULL,                                                   // #278
2961 NULL,                                                   // #279
2962 NULL,                                                   // #280
2963 NULL,                                                   // #281
2964 NULL,                                                   // #282
2965 NULL,                                                   // #283
2966 NULL,                                                   // #284
2967 NULL,                                                   // #285
2968 NULL,                                                   // #286
2969 NULL,                                                   // #287
2970 NULL,                                                   // #288
2971 NULL,                                                   // #289
2972 NULL,                                                   // #290
2973 NULL,                                                   // #291
2974 NULL,                                                   // #292
2975 NULL,                                                   // #293
2976 NULL,                                                   // #294
2977 NULL,                                                   // #295
2978 NULL,                                                   // #296
2979 NULL,                                                   // #297
2980 NULL,                                                   // #298
2981 NULL,                                                   // #299
2982 // CSQC range #300-#399
2983 VM_CL_R_ClearScene,                             // #300 void() clearscene (EXT_CSQC)
2984 VM_CL_R_AddEntities,                    // #301 void(float mask) addentities (EXT_CSQC)
2985 VM_CL_R_AddEntity,                              // #302 void(entity ent) addentity (EXT_CSQC)
2986 VM_CL_R_SetView,                                // #303 float(float property, ...) setproperty (EXT_CSQC)
2987 VM_CL_R_RenderScene,                    // #304 void() renderscene (EXT_CSQC)
2988 VM_CL_R_AddDynamicLight,                // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2989 VM_CL_R_PolygonBegin,                   // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2990 VM_CL_R_PolygonVertex,                  // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2991 VM_CL_R_PolygonEnd,                             // #308 void() R_EndPolygon
2992 NULL,                                                   // #309
2993 VM_CL_unproject,                                // #310 vector (vector v) cs_unproject (EXT_CSQC)
2994 VM_CL_project,                                  // #311 vector (vector v) cs_project (EXT_CSQC)
2995 NULL,                                                   // #312
2996 NULL,                                                   // #313
2997 NULL,                                                   // #314
2998 VM_drawline,                                    // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2999 VM_iscachedpic,                                 // #316 float(string name) iscachedpic (EXT_CSQC)
3000 VM_precache_pic,                                // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3001 VM_getimagesize,                                // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3002 VM_freepic,                                             // #319 void(string name) freepic (EXT_CSQC)
3003 VM_drawcharacter,                               // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3004 VM_drawstring,                                  // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3005 VM_drawpic,                                             // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3006 VM_drawfill,                                    // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3007 VM_drawsetcliparea,                             // #324 void(float x, float y, float width, float height) drawsetcliparea
3008 VM_drawresetcliparea,                   // #325 void(void) drawresetcliparea
3009 NULL,                                                   // #326
3010 NULL,                                                   // #327
3011 NULL,                                                   // #328
3012 NULL,                                                   // #329
3013 VM_CL_getstatf,                                 // #330 float(float stnum) getstatf (EXT_CSQC)
3014 VM_CL_getstati,                                 // #331 float(float stnum) getstati (EXT_CSQC)
3015 VM_CL_getstats,                                 // #332 string(float firststnum) getstats (EXT_CSQC)
3016 VM_CL_setmodelindex,                    // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3017 VM_CL_modelnameforindex,                // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3018 VM_CL_particleeffectnum,                // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3019 VM_CL_trailparticles,                   // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3020 VM_CL_pointparticles,                   // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3021 VM_centerprint,                                 // #338 void(string s, ...) centerprint (EXT_CSQC)
3022 VM_print,                                               // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3023 VM_keynumtostring,                              // #340 string(float keynum) keynumtostring (EXT_CSQC)
3024 VM_stringtokeynum,                              // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3025 VM_CL_getkeybind,                               // #342 string(float keynum) getkeybind (EXT_CSQC)
3026 VM_CL_setcursormode,                    // #343 void(float usecursor) setcursormode (EXT_CSQC)
3027 VM_getmousepos,                                 // #344 vector() getmousepos (EXT_CSQC)
3028 VM_CL_getinputstate,                    // #345 float(float framenum) getinputstate (EXT_CSQC)
3029 VM_CL_setsensitivityscale,              // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3030 VM_CL_runplayerphysics,                 // #347 void() runstandardplayerphysics (EXT_CSQC)
3031 VM_CL_getplayerkey,                             // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3032 VM_CL_isdemo,                                   // #349 float() isdemo (EXT_CSQC)
3033 VM_isserver,                                    // #350 float() isserver (EXT_CSQC)
3034 VM_CL_setlistener,                              // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3035 VM_CL_registercmd,                              // #352 void(string cmdname) registercommand (EXT_CSQC)
3036 VM_wasfreed,                                    // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3037 VM_CL_serverkey,                                // #354 string(string key) serverkey (EXT_CSQC)
3038 NULL,                                                   // #355
3039 NULL,                                                   // #356
3040 NULL,                                                   // #357
3041 NULL,                                                   // #358
3042 NULL,                                                   // #359
3043 VM_CL_ReadByte,                                 // #360 float() readbyte (EXT_CSQC)
3044 VM_CL_ReadChar,                                 // #361 float() readchar (EXT_CSQC)
3045 VM_CL_ReadShort,                                // #362 float() readshort (EXT_CSQC)
3046 VM_CL_ReadLong,                                 // #363 float() readlong (EXT_CSQC)
3047 VM_CL_ReadCoord,                                // #364 float() readcoord (EXT_CSQC)
3048 VM_CL_ReadAngle,                                // #365 float() readangle (EXT_CSQC)
3049 VM_CL_ReadString,                               // #366 string() readstring (EXT_CSQC)
3050 VM_CL_ReadFloat,                                // #367 float() readfloat (EXT_CSQC)
3051 NULL,                                                   // #368
3052 NULL,                                                   // #369
3053 NULL,                                                   // #370
3054 NULL,                                                   // #371
3055 NULL,                                                   // #372
3056 NULL,                                                   // #373
3057 NULL,                                                   // #374
3058 NULL,                                                   // #375
3059 NULL,                                                   // #376
3060 NULL,                                                   // #377
3061 NULL,                                                   // #378
3062 NULL,                                                   // #379
3063 NULL,                                                   // #380
3064 NULL,                                                   // #381
3065 NULL,                                                   // #382
3066 NULL,                                                   // #383
3067 NULL,                                                   // #384
3068 NULL,                                                   // #385
3069 NULL,                                                   // #386
3070 NULL,                                                   // #387
3071 NULL,                                                   // #388
3072 NULL,                                                   // #389
3073 NULL,                                                   // #390
3074 NULL,                                                   // #391
3075 NULL,                                                   // #392
3076 NULL,                                                   // #393
3077 NULL,                                                   // #394
3078 NULL,                                                   // #395
3079 NULL,                                                   // #396
3080 NULL,                                                   // #397
3081 NULL,                                                   // #398
3082 NULL,                                                   // #399
3083 // LordHavoc's range #400-#499
3084 VM_CL_copyentity,                               // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3085 NULL,                                                   // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3086 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3087 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3088 VM_CL_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3089 VM_CL_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3090 VM_CL_te_bloodshower,   &