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