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