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