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