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