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