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