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