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