5 #include "cl_collision.h"
10 //============================================================================
12 //[515]: unsolved PROBLEMS
13 //- finish player physics code (cs_runplayerphysics)
15 //- RF_DEPTHHACK is not like it should be
16 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
17 //- finish lines support for R_Polygon***
18 //- insert selecttraceline into traceline somehow
20 //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)
21 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
23 extern cvar_t v_flipped;
25 sfx_t *S_FindName(const char *name);
26 int Sbar_GetSortedPlayerIndex (int index);
27 void Sbar_SortFrags (void);
28 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
29 void CSQC_RelinkAllEntities (int drawmask);
30 void CSQC_RelinkCSQCEntities (void);
31 const char *Key_GetBind (int key);
33 // #1 void(vector ang) makevectors
34 static void VM_CL_makevectors (void)
36 VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
37 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
40 // #2 void(entity e, vector o) setorigin
41 void VM_CL_setorigin (void)
45 VM_SAFEPARMCOUNT(2, VM_CL_setorigin);
47 e = PRVM_G_EDICT(OFS_PARM0);
48 if (e == prog->edicts)
50 VM_Warning("setorigin: can not modify world entity\n");
53 if (e->priv.required->free)
55 VM_Warning("setorigin: can not modify free entity\n");
58 org = PRVM_G_VECTOR(OFS_PARM1);
59 VectorCopy (org, e->fields.client->origin);
63 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
69 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
72 VectorCopy (min, e->fields.client->mins);
73 VectorCopy (max, e->fields.client->maxs);
74 VectorSubtract (max, min, e->fields.client->size);
79 // #3 void(entity e, string m) setmodel
80 void VM_CL_setmodel (void)
87 VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
89 e = PRVM_G_EDICT(OFS_PARM0);
90 e->fields.client->modelindex = 0;
91 e->fields.client->model = 0;
93 m = PRVM_G_STRING(OFS_PARM1);
95 for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
97 if (!strcmp(cl.csqc_model_precache[i]->name, m))
99 mod = cl.csqc_model_precache[i];
100 e->fields.client->model = PRVM_SetEngineString(mod->name);
101 e->fields.client->modelindex = -(i+1);
107 for (i = 0;i < MAX_MODELS;i++)
109 mod = cl.model_precache[i];
110 if (mod && !strcmp(mod->name, m))
112 e->fields.client->model = PRVM_SetEngineString(mod->name);
113 e->fields.client->modelindex = i;
120 // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
121 //SetMinMaxSize (e, mod->normalmins, mod->normalmaxs);
125 SetMinMaxSize (e, vec3_origin, vec3_origin);
126 VM_Warning ("setmodel: model '%s' not precached\n", m);
130 // #4 void(entity e, vector min, vector max) setsize
131 static void VM_CL_setsize (void)
135 VM_SAFEPARMCOUNT(3, VM_CL_setsize);
137 e = PRVM_G_EDICT(OFS_PARM0);
138 if (e == prog->edicts)
140 VM_Warning("setsize: can not modify world entity\n");
143 if (e->priv.server->free)
145 VM_Warning("setsize: can not modify free entity\n");
148 min = PRVM_G_VECTOR(OFS_PARM1);
149 max = PRVM_G_VECTOR(OFS_PARM2);
151 SetMinMaxSize( e, min, max );
156 // #8 void(entity e, float chan, string samp, float volume, float atten) sound
157 static void VM_CL_sound (void)
161 prvm_edict_t *entity;
165 VM_SAFEPARMCOUNT(5, VM_CL_sound);
167 entity = PRVM_G_EDICT(OFS_PARM0);
168 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
169 sample = PRVM_G_STRING(OFS_PARM2);
170 volume = PRVM_G_FLOAT(OFS_PARM3);
171 attenuation = PRVM_G_FLOAT(OFS_PARM4);
173 if (volume < 0 || volume > 1)
175 VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
179 if (attenuation < 0 || attenuation > 4)
181 VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
185 if (channel < 0 || channel > 7)
187 VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
191 S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
194 // #483 void(vector origin, string sample, float volume, float attenuation) pointsound
195 static void VM_CL_pointsound(void)
202 VM_SAFEPARMCOUNT(4, VM_CL_pointsound);
204 VectorCopy( PRVM_G_VECTOR(OFS_PARM0), org);
205 sample = PRVM_G_STRING(OFS_PARM1);
206 volume = PRVM_G_FLOAT(OFS_PARM2);
207 attenuation = PRVM_G_FLOAT(OFS_PARM3);
209 if (volume < 0 || volume > 1)
211 VM_Warning("VM_CL_pointsound: volume must be in range 0-1\n");
215 if (attenuation < 0 || attenuation > 4)
217 VM_Warning("VM_CL_pointsound: attenuation must be in range 0-4\n");
221 // Send World Entity as Entity to Play Sound (for CSQC, that is 32768)
222 S_StartSound(32768, 0, S_FindName(sample), org, volume, attenuation);
225 // #14 entity() spawn
226 static void VM_CL_spawn (void)
229 ed = PRVM_ED_Alloc();
233 void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
236 VM_SetTraceGlobals(trace);
237 if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_networkentity)))
241 // #16 float(vector v1, vector v2, float movetype, entity ignore) traceline
242 static void VM_CL_traceline (void)
249 VM_SAFEPARMCOUNTRANGE(4, 4, VM_CL_traceline);
251 prog->xfunction->builtinsprofile += 30;
253 v1 = PRVM_G_VECTOR(OFS_PARM0);
254 v2 = PRVM_G_VECTOR(OFS_PARM1);
255 move = (int)PRVM_G_FLOAT(OFS_PARM2);
256 ent = PRVM_G_EDICT(OFS_PARM3);
258 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
259 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
261 trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
263 CL_VM_SetTraceGlobals(&trace, svent);
270 Used for use tracing and shot targeting
271 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
272 if the tryents flag is set.
274 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
277 // LordHavoc: added this for my own use, VERY useful, similar to traceline
278 static void VM_CL_tracebox (void)
280 float *v1, *v2, *m1, *m2;
285 VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion
287 prog->xfunction->builtinsprofile += 30;
289 v1 = PRVM_G_VECTOR(OFS_PARM0);
290 m1 = PRVM_G_VECTOR(OFS_PARM1);
291 m2 = PRVM_G_VECTOR(OFS_PARM2);
292 v2 = PRVM_G_VECTOR(OFS_PARM3);
293 move = (int)PRVM_G_FLOAT(OFS_PARM4);
294 ent = PRVM_G_EDICT(OFS_PARM5);
296 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
297 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
299 trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
301 CL_VM_SetTraceGlobals(&trace, svent);
304 trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
309 vec3_t original_origin;
310 vec3_t original_velocity;
311 vec3_t original_angles;
312 vec3_t original_avelocity;
316 VectorCopy(tossent->fields.client->origin , original_origin );
317 VectorCopy(tossent->fields.client->velocity , original_velocity );
318 VectorCopy(tossent->fields.client->angles , original_angles );
319 VectorCopy(tossent->fields.client->avelocity, original_avelocity);
321 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
322 if (val != NULL && val->_float != 0)
323 gravity = val->_float;
326 gravity *= cl.movevars_gravity * 0.05;
328 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
330 tossent->fields.client->velocity[2] -= gravity;
331 VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
332 VectorScale (tossent->fields.client->velocity, 0.05, move);
333 VectorAdd (tossent->fields.client->origin, move, end);
334 trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true);
335 VectorCopy (trace.endpos, tossent->fields.client->origin);
337 if (trace.fraction < 1)
341 VectorCopy(original_origin , tossent->fields.client->origin );
342 VectorCopy(original_velocity , tossent->fields.client->velocity );
343 VectorCopy(original_angles , tossent->fields.client->angles );
344 VectorCopy(original_avelocity, tossent->fields.client->avelocity);
349 static void VM_CL_tracetoss (void)
353 prvm_edict_t *ignore;
356 prog->xfunction->builtinsprofile += 600;
358 VM_SAFEPARMCOUNT(2, VM_CL_tracetoss);
360 ent = PRVM_G_EDICT(OFS_PARM0);
361 if (ent == prog->edicts)
363 VM_Warning("tracetoss: can not use world entity\n");
366 ignore = PRVM_G_EDICT(OFS_PARM1);
368 trace = CL_Trace_Toss (ent, ignore, &svent);
370 CL_VM_SetTraceGlobals(&trace, svent);
374 // #20 void(string s) precache_model
375 void VM_CL_precache_model (void)
381 VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
383 name = PRVM_G_STRING(OFS_PARM0);
384 for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
386 if(!strcmp(cl.csqc_model_precache[i]->name, name))
388 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
392 PRVM_G_FLOAT(OFS_RETURN) = 0;
393 m = Mod_ForName(name, false, false, false);
396 for (i = 0;i < MAX_MODELS;i++)
398 if (!cl.csqc_model_precache[i])
400 cl.csqc_model_precache[i] = (dp_model_t*)m;
401 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
405 VM_Warning("VM_CL_precache_model: no free models\n");
408 VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
411 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
416 ent = PRVM_NEXT_EDICT(prog->edicts);
417 for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
419 if (ent->priv.required->free)
421 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
427 // #22 entity(vector org, float rad) findradius
428 static void VM_CL_findradius (void)
430 prvm_edict_t *ent, *chain;
431 vec_t radius, radius2;
432 vec3_t org, eorg, mins, maxs;
433 int i, numtouchedicts;
434 prvm_edict_t *touchedicts[MAX_EDICTS];
436 VM_SAFEPARMCOUNT(2, VM_CL_findradius);
438 chain = (prvm_edict_t *)prog->edicts;
440 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
441 radius = PRVM_G_FLOAT(OFS_PARM1);
442 radius2 = radius * radius;
444 mins[0] = org[0] - (radius + 1);
445 mins[1] = org[1] - (radius + 1);
446 mins[2] = org[2] - (radius + 1);
447 maxs[0] = org[0] + (radius + 1);
448 maxs[1] = org[1] + (radius + 1);
449 maxs[2] = org[2] + (radius + 1);
450 numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
451 if (numtouchedicts > MAX_EDICTS)
453 // this never happens //[515]: for what then ?
454 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
455 numtouchedicts = MAX_EDICTS;
457 for (i = 0;i < numtouchedicts;i++)
459 ent = touchedicts[i];
460 // Quake did not return non-solid entities but darkplaces does
461 // (note: this is the reason you can't blow up fallen zombies)
462 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
464 // LordHavoc: compare against bounding box rather than center so it
465 // doesn't miss large objects, and use DotProduct instead of Length
466 // for a major speedup
467 VectorSubtract(org, ent->fields.client->origin, eorg);
468 if (sv_gameplayfix_findradiusdistancetobox.integer)
470 eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
471 eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
472 eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
475 VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
476 if (DotProduct(eorg, eorg) < radius2)
478 ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
483 VM_RETURN_EDICT(chain);
486 // #34 float() droptofloor
487 static void VM_CL_droptofloor (void)
494 VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
496 // assume failure if it returns early
497 PRVM_G_FLOAT(OFS_RETURN) = 0;
499 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
500 if (ent == prog->edicts)
502 VM_Warning("droptofloor: can not modify world entity\n");
505 if (ent->priv.server->free)
507 VM_Warning("droptofloor: can not modify free entity\n");
511 VectorCopy (ent->fields.client->origin, end);
514 trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
516 if (trace.fraction != 1)
518 VectorCopy (trace.endpos, ent->fields.client->origin);
519 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
520 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
521 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
522 PRVM_G_FLOAT(OFS_RETURN) = 1;
523 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
524 // ent->priv.server->suspendedinairflag = true;
528 // #35 void(float style, string value) lightstyle
529 static void VM_CL_lightstyle (void)
534 VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
536 i = (int)PRVM_G_FLOAT(OFS_PARM0);
537 c = PRVM_G_STRING(OFS_PARM1);
538 if (i >= cl.max_lightstyle)
540 VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
543 strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map));
544 cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
545 cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
548 // #40 float(entity e) checkbottom
549 static void VM_CL_checkbottom (void)
551 static int cs_yes, cs_no;
553 vec3_t mins, maxs, start, stop;
558 VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
559 ent = PRVM_G_EDICT(OFS_PARM0);
560 PRVM_G_FLOAT(OFS_RETURN) = 0;
562 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
563 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
565 // if all of the points under the corners are solid world, don't bother
566 // with the tougher checks
567 // the corners must be within 16 of the midpoint
568 start[2] = mins[2] - 1;
569 for (x=0 ; x<=1 ; x++)
570 for (y=0 ; y<=1 ; y++)
572 start[0] = x ? maxs[0] : mins[0];
573 start[1] = y ? maxs[1] : mins[1];
574 if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
579 PRVM_G_FLOAT(OFS_RETURN) = true;
580 return; // we got out easy
585 // check it for real...
589 // the midpoint must be within 16 of the bottom
590 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
591 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
592 stop[2] = start[2] - 2*sv_stepheight.value;
593 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
595 if (trace.fraction == 1.0)
598 mid = bottom = trace.endpos[2];
600 // the corners must be within 16 of the midpoint
601 for (x=0 ; x<=1 ; x++)
602 for (y=0 ; y<=1 ; y++)
604 start[0] = stop[0] = x ? maxs[0] : mins[0];
605 start[1] = stop[1] = y ? maxs[1] : mins[1];
607 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
609 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
610 bottom = trace.endpos[2];
611 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
616 PRVM_G_FLOAT(OFS_RETURN) = true;
619 // #41 float(vector v) pointcontents
620 static void VM_CL_pointcontents (void)
622 VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
623 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
626 // #48 void(vector o, vector d, float color, float count) particle
627 static void VM_CL_particle (void)
632 VM_SAFEPARMCOUNT(4, VM_CL_particle);
634 org = PRVM_G_VECTOR(OFS_PARM0);
635 dir = PRVM_G_VECTOR(OFS_PARM1);
636 color = (int)PRVM_G_FLOAT(OFS_PARM2);
637 count = (int)PRVM_G_FLOAT(OFS_PARM3);
638 CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
641 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
642 static void VM_CL_ambientsound (void)
646 VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
647 s = S_FindName(PRVM_G_STRING(OFS_PARM0));
648 f = PRVM_G_VECTOR(OFS_PARM1);
649 S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
652 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
653 static void VM_CL_getlight (void)
655 vec3_t ambientcolor, diffusecolor, diffusenormal;
658 VM_SAFEPARMCOUNT(1, VM_CL_getlight);
660 p = PRVM_G_VECTOR(OFS_PARM0);
661 VectorClear(ambientcolor);
662 VectorClear(diffusecolor);
663 VectorClear(diffusenormal);
664 if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
665 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
666 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
670 //============================================================================
671 //[515]: SCENE MANAGER builtins
672 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
674 static void CSQC_R_RecalcView (void)
676 extern matrix4x4_t viewmodelmatrix;
677 Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
678 Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
681 void CL_RelinkLightFlashes(void);
682 //#300 void() clearscene (EXT_CSQC)
683 void VM_CL_R_ClearScene (void)
685 VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
686 // clear renderable entity and light lists
687 r_refdef.scene.numentities = 0;
688 r_refdef.scene.numlights = 0;
689 // FIXME: restore these to the values from VM_CL_UpdateView
693 r_refdef.view.width = vid.width;
694 r_refdef.view.height = vid.height;
695 r_refdef.view.depth = 1;
696 // FIXME: restore frustum_x/frustum_y
697 r_refdef.view.useperspective = true;
698 r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
699 r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
700 r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
701 r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
702 r_refdef.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
703 r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
704 r_refdef.view.clear = true;
705 r_refdef.view.isoverlay = false;
706 // FIXME: restore cl.csqc_origin
707 // FIXME: restore cl.csqc_angles
708 cl.csqc_vidvars.drawworld = true;
709 cl.csqc_vidvars.drawenginesbar = false;
710 cl.csqc_vidvars.drawcrosshair = false;
713 //#301 void(float mask) addentities (EXT_CSQC)
714 extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
715 extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
716 void VM_CL_R_AddEntities (void)
720 VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
721 drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
722 CSQC_RelinkAllEntities(drawmask);
723 CL_RelinkLightFlashes();
725 prog->globals.client->time = cl.time;
726 for(i=1;i<prog->num_edicts;i++)
728 ed = &prog->edicts[i];
729 if(ed->priv.required->free)
732 if(ed->priv.required->free)
734 // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
736 if(ed->priv.required->free)
738 if(!((int)ed->fields.client->drawmask & drawmask))
740 CSQC_AddRenderEdict(ed);
744 //#302 void(entity ent) addentity (EXT_CSQC)
745 void VM_CL_R_AddEntity (void)
747 VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
748 CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
751 //#303 float(float property, ...) setproperty (EXT_CSQC)
752 void VM_CL_R_SetView (void)
758 VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView);
760 c = (int)PRVM_G_FLOAT(OFS_PARM0);
761 f = PRVM_G_VECTOR(OFS_PARM1);
762 k = PRVM_G_FLOAT(OFS_PARM1);
767 r_refdef.view.x = (int)(f[0]);
768 r_refdef.view.y = (int)(f[1]);
771 r_refdef.view.x = (int)(k);
774 r_refdef.view.y = (int)(k);
777 r_refdef.view.width = (int)(f[0]);
778 r_refdef.view.height = (int)(f[1]);
781 r_refdef.view.width = (int)(k);
784 r_refdef.view.height = (int)(k);
787 r_refdef.view.x = (int)(f[0]);
788 r_refdef.view.y = (int)(f[1]);
789 f = PRVM_G_VECTOR(OFS_PARM2);
790 r_refdef.view.width = (int)(f[0]);
791 r_refdef.view.height = (int)(f[1]);
794 r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0];
795 r_refdef.view.frustum_y = tan(f[1] * M_PI / 360.0);r_refdef.view.ortho_y = f[1];
798 r_refdef.view.frustum_x = tan(k * M_PI / 360.0);r_refdef.view.ortho_x = k;
801 r_refdef.view.frustum_y = tan(k * M_PI / 360.0);r_refdef.view.ortho_y = k;
804 VectorCopy(f, cl.csqc_origin);
808 cl.csqc_origin[0] = k;
812 cl.csqc_origin[1] = k;
816 cl.csqc_origin[2] = k;
820 VectorCopy(f, cl.csqc_angles);
824 cl.csqc_angles[0] = k;
828 cl.csqc_angles[1] = k;
832 cl.csqc_angles[2] = k;
836 cl.csqc_vidvars.drawworld = k;
838 case VF_DRAWENGINESBAR:
839 cl.csqc_vidvars.drawenginesbar = k;
841 case VF_DRAWCROSSHAIR:
842 cl.csqc_vidvars.drawcrosshair = k;
844 case VF_CL_VIEWANGLES:
845 VectorCopy(f, cl.viewangles);
847 case VF_CL_VIEWANGLES_X:
848 cl.viewangles[0] = k;
850 case VF_CL_VIEWANGLES_Y:
851 cl.viewangles[1] = k;
853 case VF_CL_VIEWANGLES_Z:
854 cl.viewangles[2] = k;
857 r_refdef.view.useperspective = k != 0;
860 r_refdef.view.isoverlay = !k;
863 PRVM_G_FLOAT(OFS_RETURN) = 0;
864 VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
867 PRVM_G_FLOAT(OFS_RETURN) = 1;
870 //#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC)
871 void VM_CL_R_AddDynamicLight (void)
877 const char *cubemapname = NULL;
878 int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC;
879 float coronaintensity = 1;
880 float coronasizescale = 0.25;
881 qboolean castshadow = true;
882 float ambientscale = 0;
883 float diffusescale = 1;
884 float specularscale = 1;
886 vec3_t forward, left, up;
887 VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight);
889 // if we've run out of dlights, just return
890 if (r_refdef.scene.numlights >= MAX_DLIGHTS)
893 org = PRVM_G_VECTOR(OFS_PARM0);
894 radius = PRVM_G_FLOAT(OFS_PARM1);
895 col = PRVM_G_VECTOR(OFS_PARM2);
898 style = (int)PRVM_G_FLOAT(OFS_PARM3);
899 if (style >= MAX_LIGHTSTYLES)
901 Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style);
906 cubemapname = PRVM_G_STRING(OFS_PARM4);
908 pflags = (int)PRVM_G_FLOAT(OFS_PARM5);
909 coronaintensity = (pflags & PFLAGS_CORONA) != 0;
910 castshadow = (pflags & PFLAGS_NOSHADOW) == 0;
912 VectorScale(prog->globals.client->v_forward, radius, forward);
913 VectorScale(prog->globals.client->v_right, -radius, left);
914 VectorScale(prog->globals.client->v_up, radius, up);
915 Matrix4x4_FromVectors(&matrix, forward, left, up, org);
917 R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
920 //============================================================================
922 //#310 vector (vector v) cs_unproject (EXT_CSQC)
923 static void VM_CL_unproject (void)
928 VM_SAFEPARMCOUNT(1, VM_CL_unproject);
929 f = PRVM_G_VECTOR(OFS_PARM0);
930 if(v_flipped.integer)
931 f[0] = r_refdef.view.x + r_refdef.view.width - f[0];
932 VectorSet(temp, f[2], (-1.0 + 2.0 * (f[0] - r_refdef.view.x)) / r_refdef.view.width * f[2] * -r_refdef.view.frustum_x, (-1.0 + 2.0 * (f[1] - r_refdef.view.y)) / r_refdef.view.height * f[2] * -r_refdef.view.frustum_y);
933 Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
936 //#311 vector (vector v) cs_project (EXT_CSQC)
937 static void VM_CL_project (void)
943 VM_SAFEPARMCOUNT(1, VM_CL_project);
944 f = PRVM_G_VECTOR(OFS_PARM0);
945 Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
946 Matrix4x4_Transform(&m, f, v);
947 if(v_flipped.integer)
949 VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.x + r_refdef.view.width*0.5*(1.0+v[1]/v[0]/-r_refdef.view.frustum_x), r_refdef.view.y + r_refdef.view.height*0.5*(1.0+v[2]/v[0]/-r_refdef.view.frustum_y), v[0]);
952 //#330 float(float stnum) getstatf (EXT_CSQC)
953 static void VM_CL_getstatf (void)
961 VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
962 i = (int)PRVM_G_FLOAT(OFS_PARM0);
963 if(i < 0 || i >= MAX_CL_STATS)
965 VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
969 PRVM_G_FLOAT(OFS_RETURN) = dat.f;
972 //#331 float(float stnum) getstati (EXT_CSQC)
973 static void VM_CL_getstati (void)
976 int firstbit, bitcount;
978 VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getstati);
980 index = (int)PRVM_G_FLOAT(OFS_PARM0);
983 firstbit = (int)PRVM_G_FLOAT(OFS_PARM1);
985 bitcount = (int)PRVM_G_FLOAT(OFS_PARM2);
995 if(index < 0 || index >= MAX_CL_STATS)
997 VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
1000 i = cl.stats[index];
1001 if (bitcount != 32) //32 causes the mask to overflow, so there's nothing to subtract from.
1002 i = (((unsigned int)i)&(((1<<bitcount)-1)<<firstbit))>>firstbit;
1003 PRVM_G_FLOAT(OFS_RETURN) = i;
1006 //#332 string(float firststnum) getstats (EXT_CSQC)
1007 static void VM_CL_getstats (void)
1011 VM_SAFEPARMCOUNT(1, VM_CL_getstats);
1012 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1013 if(i < 0 || i > MAX_CL_STATS-4)
1015 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1016 VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
1019 strlcpy(t, (char*)&cl.stats[i], sizeof(t));
1020 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1023 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
1024 static void VM_CL_setmodelindex (void)
1028 struct model_s *model;
1030 VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
1032 t = PRVM_G_EDICT(OFS_PARM0);
1034 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1036 t->fields.client->model = 0;
1037 t->fields.client->modelindex = 0;
1042 model = CL_GetModelByIndex(i);
1045 VM_Warning("VM_CL_setmodelindex: null model\n");
1048 t->fields.client->model = PRVM_SetEngineString(model->name);
1049 t->fields.client->modelindex = i;
1051 // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
1054 SetMinMaxSize (t, model->normalmins, model->normalmaxs);
1057 SetMinMaxSize (t, vec3_origin, vec3_origin);
1060 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
1061 static void VM_CL_modelnameforindex (void)
1065 VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
1067 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1068 model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
1069 PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
1072 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1073 static void VM_CL_particleeffectnum (void)
1076 VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1077 i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
1080 PRVM_G_FLOAT(OFS_RETURN) = i;
1083 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1084 static void VM_CL_trailparticles (void)
1089 VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
1091 t = PRVM_G_EDICT(OFS_PARM0);
1092 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1093 start = PRVM_G_VECTOR(OFS_PARM2);
1094 end = PRVM_G_VECTOR(OFS_PARM3);
1098 CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
1101 //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
1102 static void VM_CL_pointparticles (void)
1106 VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
1107 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1108 f = PRVM_G_VECTOR(OFS_PARM1);
1109 v = PRVM_G_VECTOR(OFS_PARM2);
1110 n = (int)PRVM_G_FLOAT(OFS_PARM3);
1113 CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
1116 //#342 string(float keynum) getkeybind (EXT_CSQC)
1117 static void VM_CL_getkeybind (void)
1119 VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1120 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
1123 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1124 static void VM_CL_setcursormode (void)
1126 VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1127 cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1128 cl_ignoremousemoves = 2;
1131 //#344 vector() getmousepos (EXT_CSQC)
1132 static void VM_CL_getmousepos(void)
1134 VM_SAFEPARMCOUNT(0,VM_CL_getmousepos);
1136 if (key_consoleactive || key_dest != key_game)
1137 VectorSet(PRVM_G_VECTOR(OFS_RETURN), 0, 0, 0);
1138 else if (cl.csqc_wantsmousemove)
1139 VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height, 0);
1141 VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height, 0);
1144 //#345 float(float framenum) getinputstate (EXT_CSQC)
1145 static void VM_CL_getinputstate (void)
1148 VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1149 frame = (int)PRVM_G_FLOAT(OFS_PARM0);
1150 for (i = 0;i < CL_MAX_USERCMDS;i++)
1152 if (cl.movecmd[i].sequence == frame)
1154 VectorCopy(cl.movecmd[i].viewangles, prog->globals.client->input_angles);
1155 prog->globals.client->input_buttons = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?)
1156 prog->globals.client->input_movevalues[0] = cl.movecmd[i].forwardmove;
1157 prog->globals.client->input_movevalues[1] = cl.movecmd[i].sidemove;
1158 prog->globals.client->input_movevalues[2] = cl.movecmd[i].upmove;
1159 prog->globals.client->input_timelength = cl.movecmd[i].frametime;
1160 if(cl.movecmd[i].crouch)
1162 VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
1163 VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
1167 VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
1168 VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
1174 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1175 static void VM_CL_setsensitivityscale (void)
1177 VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1178 cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1181 //#347 void() runstandardplayerphysics (EXT_CSQC)
1182 static void VM_CL_runplayerphysics (void)
1186 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1187 static void VM_CL_getplayerkey (void)
1193 VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1195 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1196 c = PRVM_G_STRING(OFS_PARM1);
1197 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1201 i = Sbar_GetSortedPlayerIndex(-1-i);
1202 if(i < 0 || i >= cl.maxclients)
1207 if(!strcasecmp(c, "name"))
1208 strlcpy(t, cl.scores[i].name, sizeof(t));
1210 if(!strcasecmp(c, "frags"))
1211 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags);
1213 if(!strcasecmp(c, "ping"))
1214 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping);
1216 if(!strcasecmp(c, "pl"))
1217 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss);
1219 if(!strcasecmp(c, "entertime"))
1220 dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime);
1222 if(!strcasecmp(c, "colors"))
1223 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors);
1225 if(!strcasecmp(c, "topcolor"))
1226 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0);
1228 if(!strcasecmp(c, "bottomcolor"))
1229 dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4);
1231 if(!strcasecmp(c, "viewentity"))
1232 dpsnprintf(t, sizeof(t), "%i", i+1);
1235 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1238 //#349 float() isdemo (EXT_CSQC)
1239 static void VM_CL_isdemo (void)
1241 VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
1242 PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1245 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1246 static void VM_CL_setlistener (void)
1248 VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1249 Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1250 cl.csqc_usecsqclistener = true; //use csqc listener at this frame
1253 //#352 void(string cmdname) registercommand (EXT_CSQC)
1254 static void VM_CL_registercmd (void)
1257 VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1258 if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1262 alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
1263 t = (char *)Z_Malloc(alloclen);
1264 memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
1265 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1268 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1272 //#360 float() readbyte (EXT_CSQC)
1273 static void VM_CL_ReadByte (void)
1275 VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
1276 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1279 //#361 float() readchar (EXT_CSQC)
1280 static void VM_CL_ReadChar (void)
1282 VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
1283 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1286 //#362 float() readshort (EXT_CSQC)
1287 static void VM_CL_ReadShort (void)
1289 VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
1290 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1293 //#363 float() readlong (EXT_CSQC)
1294 static void VM_CL_ReadLong (void)
1296 VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
1297 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1300 //#364 float() readcoord (EXT_CSQC)
1301 static void VM_CL_ReadCoord (void)
1303 VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
1304 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1307 //#365 float() readangle (EXT_CSQC)
1308 static void VM_CL_ReadAngle (void)
1310 VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
1311 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1314 //#366 string() readstring (EXT_CSQC)
1315 static void VM_CL_ReadString (void)
1317 VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
1318 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
1321 //#367 float() readfloat (EXT_CSQC)
1322 static void VM_CL_ReadFloat (void)
1324 VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
1325 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1328 //#501 string() readpicture (DP_CSQC_READWRITEPICTURE)
1329 extern cvar_t cl_readpicture_force;
1330 static void VM_CL_ReadPicture (void)
1333 unsigned char *data;
1339 VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
1341 name = MSG_ReadString();
1342 size = MSG_ReadShort();
1344 // check if a texture of that name exists
1345 // if yes, it is used and the data is discarded
1346 // if not, the (low quality) data is used to build a new texture, whose name will get returned
1348 pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT);
1352 if(pic->tex == r_texture_notexture)
1353 pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic
1354 if(pic->tex && !cl_readpicture_force.integer)
1356 // texture found and loaded
1357 // skip over the jpeg as we don't need it
1358 for(i = 0; i < size; ++i)
1363 // texture not found
1364 // use the attached jpeg as texture
1365 buf = (unsigned char *) Mem_Alloc(tempmempool, size);
1366 MSG_ReadBytes(size, buf);
1367 data = JPEG_LoadImage_BGRA(buf, size);
1369 Draw_NewPic(name, image_width, image_height, false, data);
1374 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name);
1377 //////////////////////////////////////////////////////////
1379 static void VM_CL_makestatic (void)
1383 VM_SAFEPARMCOUNT(1, VM_CL_makestatic);
1385 ent = PRVM_G_EDICT(OFS_PARM0);
1386 if (ent == prog->edicts)
1388 VM_Warning("makestatic: can not modify world entity\n");
1391 if (ent->priv.server->free)
1393 VM_Warning("makestatic: can not modify free entity\n");
1397 if (cl.num_static_entities < cl.max_static_entities)
1401 entity_t *staticent = &cl.static_entities[cl.num_static_entities++];
1403 // copy it to the current state
1404 memset(staticent, 0, sizeof(*staticent));
1405 staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
1406 staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame;
1407 staticent->render.framelerp = 0;
1408 // make torchs play out of sync
1409 staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1);
1410 staticent->render.skinnum = (int)ent->fields.client->skin;
1411 staticent->render.effects = (int)ent->fields.client->effects;
1412 staticent->render.alpha = 1;
1413 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float;
1414 staticent->render.scale = 1;
1415 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float;
1416 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod);
1419 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
1420 if (renderflags & RF_USEAXIS)
1423 VectorNegate(prog->globals.client->v_right, left);
1424 Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin);
1425 Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
1428 Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, 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], staticent->render.scale);
1430 // either fullbright or lit
1431 if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
1432 staticent->render.flags |= RENDER_LIGHT;
1433 // turn off shadows from transparent objects
1434 if (!(staticent->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1))
1435 staticent->render.flags |= RENDER_SHADOW;
1437 CL_UpdateRenderEntity(&staticent->render);
1440 Con_Printf("Too many static entities");
1442 // throw the entity away now
1446 //=================================================================//
1452 copies data from one entity to another
1454 copyentity(src, dst)
1457 static void VM_CL_copyentity (void)
1459 prvm_edict_t *in, *out;
1460 VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
1461 in = PRVM_G_EDICT(OFS_PARM0);
1462 if (in == prog->edicts)
1464 VM_Warning("copyentity: can not read world entity\n");
1467 if (in->priv.server->free)
1469 VM_Warning("copyentity: can not read free entity\n");
1472 out = PRVM_G_EDICT(OFS_PARM1);
1473 if (out == prog->edicts)
1475 VM_Warning("copyentity: can not modify world entity\n");
1478 if (out->priv.server->free)
1480 VM_Warning("copyentity: can not modify free entity\n");
1483 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1487 //=================================================================//
1489 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1490 static void VM_CL_effect (void)
1492 VM_SAFEPARMCOUNT(5, VM_CL_effect);
1493 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));
1496 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1497 static void VM_CL_te_blood (void)
1501 VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1502 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1504 pos = PRVM_G_VECTOR(OFS_PARM0);
1505 CL_FindNonSolidLocation(pos, pos2, 4);
1506 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1509 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1510 static void VM_CL_te_bloodshower (void)
1514 VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1515 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1517 speed = PRVM_G_FLOAT(OFS_PARM2);
1524 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1527 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1528 static void VM_CL_te_explosionrgb (void)
1532 matrix4x4_t tempmatrix;
1533 VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1534 pos = PRVM_G_VECTOR(OFS_PARM0);
1535 CL_FindNonSolidLocation(pos, pos2, 10);
1536 CL_ParticleExplosion(pos2);
1537 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1538 CL_AllocLightFlash(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);
1541 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1542 static void VM_CL_te_particlecube (void)
1544 VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1545 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));
1548 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1549 static void VM_CL_te_particlerain (void)
1551 VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1552 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);
1555 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1556 static void VM_CL_te_particlesnow (void)
1558 VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1559 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);
1562 // #411 void(vector org, vector vel, float howmany) te_spark
1563 static void VM_CL_te_spark (void)
1567 VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1569 pos = PRVM_G_VECTOR(OFS_PARM0);
1570 CL_FindNonSolidLocation(pos, pos2, 4);
1571 CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1574 extern cvar_t cl_sound_ric_gunshot;
1575 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1576 static void VM_CL_te_gunshotquad (void)
1581 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1583 pos = PRVM_G_VECTOR(OFS_PARM0);
1584 CL_FindNonSolidLocation(pos, pos2, 4);
1585 CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1586 if(cl_sound_ric_gunshot.integer >= 2)
1588 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1592 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1593 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1594 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1599 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1600 static void VM_CL_te_spikequad (void)
1605 VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1607 pos = PRVM_G_VECTOR(OFS_PARM0);
1608 CL_FindNonSolidLocation(pos, pos2, 4);
1609 CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1610 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1614 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1615 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1616 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1620 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1621 static void VM_CL_te_superspikequad (void)
1626 VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1628 pos = PRVM_G_VECTOR(OFS_PARM0);
1629 CL_FindNonSolidLocation(pos, pos2, 4);
1630 CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1631 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1635 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1636 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1637 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1641 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1642 static void VM_CL_te_explosionquad (void)
1646 VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1648 pos = PRVM_G_VECTOR(OFS_PARM0);
1649 CL_FindNonSolidLocation(pos, pos2, 10);
1650 CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1651 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1654 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1655 static void VM_CL_te_smallflash (void)
1659 VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1661 pos = PRVM_G_VECTOR(OFS_PARM0);
1662 CL_FindNonSolidLocation(pos, pos2, 10);
1663 CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1666 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1667 static void VM_CL_te_customflash (void)
1671 matrix4x4_t tempmatrix;
1672 VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1674 pos = PRVM_G_VECTOR(OFS_PARM0);
1675 CL_FindNonSolidLocation(pos, pos2, 4);
1676 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1677 CL_AllocLightFlash(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);
1680 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1681 static void VM_CL_te_gunshot (void)
1686 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1688 pos = PRVM_G_VECTOR(OFS_PARM0);
1689 CL_FindNonSolidLocation(pos, pos2, 4);
1690 CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1691 if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3)
1693 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1697 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1698 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1699 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1704 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1705 static void VM_CL_te_spike (void)
1710 VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1712 pos = PRVM_G_VECTOR(OFS_PARM0);
1713 CL_FindNonSolidLocation(pos, pos2, 4);
1714 CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1715 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1719 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1720 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1721 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1725 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1726 static void VM_CL_te_superspike (void)
1731 VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1733 pos = PRVM_G_VECTOR(OFS_PARM0);
1734 CL_FindNonSolidLocation(pos, pos2, 4);
1735 CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1736 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1740 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1741 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1742 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1746 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1747 static void VM_CL_te_explosion (void)
1751 VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1753 pos = PRVM_G_VECTOR(OFS_PARM0);
1754 CL_FindNonSolidLocation(pos, pos2, 10);
1755 CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1756 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1759 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1760 static void VM_CL_te_tarexplosion (void)
1764 VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1766 pos = PRVM_G_VECTOR(OFS_PARM0);
1767 CL_FindNonSolidLocation(pos, pos2, 10);
1768 CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1769 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1772 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1773 static void VM_CL_te_wizspike (void)
1777 VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1779 pos = PRVM_G_VECTOR(OFS_PARM0);
1780 CL_FindNonSolidLocation(pos, pos2, 4);
1781 CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1782 S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1785 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1786 static void VM_CL_te_knightspike (void)
1790 VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1792 pos = PRVM_G_VECTOR(OFS_PARM0);
1793 CL_FindNonSolidLocation(pos, pos2, 4);
1794 CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1795 S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1798 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1799 static void VM_CL_te_lavasplash (void)
1801 VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1802 CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1805 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1806 static void VM_CL_te_teleport (void)
1808 VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1809 CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1812 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1813 static void VM_CL_te_explosion2 (void)
1817 matrix4x4_t tempmatrix;
1818 int colorStart, colorLength;
1819 unsigned char *tempcolor;
1820 VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1822 pos = PRVM_G_VECTOR(OFS_PARM0);
1823 colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1824 colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1825 CL_FindNonSolidLocation(pos, pos2, 10);
1826 CL_ParticleExplosion2(pos2, colorStart, colorLength);
1827 tempcolor = palette_rgb[(rand()%colorLength) + colorStart];
1828 color[0] = tempcolor[0] * (2.0f / 255.0f);
1829 color[1] = tempcolor[1] * (2.0f / 255.0f);
1830 color[2] = tempcolor[2] * (2.0f / 255.0f);
1831 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1832 CL_AllocLightFlash(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);
1833 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1837 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1838 static void VM_CL_te_lightning1 (void)
1840 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1841 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1844 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1845 static void VM_CL_te_lightning2 (void)
1847 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1848 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1851 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1852 static void VM_CL_te_lightning3 (void)
1854 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1855 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1858 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1859 static void VM_CL_te_beam (void)
1861 VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1862 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1865 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1866 static void VM_CL_te_plasmaburn (void)
1870 VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1872 pos = PRVM_G_VECTOR(OFS_PARM0);
1873 CL_FindNonSolidLocation(pos, pos2, 4);
1874 CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1877 // #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
1878 static void VM_CL_te_flamejet (void)
1882 VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
1883 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1885 pos = PRVM_G_VECTOR(OFS_PARM0);
1886 CL_FindNonSolidLocation(pos, pos2, 4);
1887 CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1891 //====================================================================
1894 extern void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1896 static msurface_t *cl_getsurface(dp_model_t *model, int surfacenum)
1898 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1900 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1903 // #434 float(entity e, float s) getsurfacenumpoints
1904 static void VM_CL_getsurfacenumpoints(void)
1907 msurface_t *surface;
1908 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
1909 // return 0 if no such surface
1910 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1912 PRVM_G_FLOAT(OFS_RETURN) = 0;
1916 // note: this (incorrectly) assumes it is a simple polygon
1917 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1920 // #435 vector(entity e, float s, float n) getsurfacepoint
1921 static void VM_CL_getsurfacepoint(void)
1925 msurface_t *surface;
1927 VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
1928 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1929 ed = PRVM_G_EDICT(OFS_PARM0);
1930 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1932 // note: this (incorrectly) assumes it is a simple polygon
1933 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1934 if (pointnum < 0 || pointnum >= surface->num_vertices)
1936 // FIXME: implement rotation/scaling
1937 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1939 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
1940 // float SPA_POSITION = 0;
1941 // float SPA_S_AXIS = 1;
1942 // float SPA_T_AXIS = 2;
1943 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
1944 // float SPA_TEXCOORDS0 = 4;
1945 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1946 // float SPA_LIGHTMAP0_COLOR = 6;
1947 // TODO: add some wrapper code and merge VM_CL/SV_getsurface* [12/16/2007 Black]
1948 static void VM_CL_getsurfacepointattribute(void)
1952 msurface_t *surface;
1956 VM_SAFEPARMCOUNT(4, VM_CL_getsurfacenumpoints);
1957 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1958 ed = PRVM_G_EDICT(OFS_PARM0);
1959 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1961 // note: this (incorrectly) assumes it is a simple polygon
1962 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1963 if (pointnum < 0 || pointnum >= surface->num_vertices)
1966 // FIXME: implement rotation/scaling
1967 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
1969 switch( attributetype ) {
1970 // float SPA_POSITION = 0;
1972 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1974 // float SPA_S_AXIS = 1;
1976 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1978 // float SPA_T_AXIS = 2;
1980 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1982 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
1984 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1986 // float SPA_TEXCOORDS0 = 4;
1988 float *ret = PRVM_G_VECTOR(OFS_RETURN);
1989 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
1990 ret[0] = texcoord[0];
1991 ret[1] = texcoord[1];
1995 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1997 float *ret = PRVM_G_VECTOR(OFS_RETURN);
1998 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
1999 ret[0] = texcoord[0];
2000 ret[1] = texcoord[1];
2004 // float SPA_LIGHTMAP0_COLOR = 6;
2006 // ignore alpha for now..
2007 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2010 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2014 // #436 vector(entity e, float s) getsurfacenormal
2015 static void VM_CL_getsurfacenormal(void)
2018 msurface_t *surface;
2020 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
2021 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2022 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2024 // FIXME: implement rotation/scaling
2025 // note: this (incorrectly) assumes it is a simple polygon
2026 // note: this only returns the first triangle, so it doesn't work very
2027 // well for curved surfaces or arbitrary meshes
2028 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);
2029 VectorNormalize(normal);
2030 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2033 // #437 string(entity e, float s) getsurfacetexture
2034 static void VM_CL_getsurfacetexture(void)
2037 msurface_t *surface;
2038 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
2039 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2040 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2042 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2045 // #438 float(entity e, vector p) getsurfacenearpoint
2046 static void VM_CL_getsurfacenearpoint(void)
2048 int surfacenum, best;
2050 vec_t dist, bestdist;
2052 dp_model_t *model = NULL;
2053 msurface_t *surface;
2055 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
2056 PRVM_G_FLOAT(OFS_RETURN) = -1;
2057 ed = PRVM_G_EDICT(OFS_PARM0);
2058 if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
2061 // FIXME: implement rotation/scaling
2062 point = PRVM_G_VECTOR(OFS_PARM1);
2063 VectorSubtract(point, ed->fields.client->origin, p);
2065 bestdist = 1000000000;
2066 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2068 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2069 // first see if the nearest point on the surface's box is closer than the previous match
2070 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2071 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2072 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2073 dist = VectorLength2(clipped);
2074 if (dist < bestdist)
2076 // it is, check the nearest point on the actual geometry
2077 clippointtosurface(model, surface, p, clipped);
2078 VectorSubtract(clipped, p, clipped);
2079 dist += VectorLength2(clipped);
2080 if (dist < bestdist)
2082 // that's closer too, store it as the best match
2088 PRVM_G_FLOAT(OFS_RETURN) = best;
2091 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
2092 static void VM_CL_getsurfaceclippedpoint(void)
2096 msurface_t *surface;
2098 VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
2099 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2100 ed = PRVM_G_EDICT(OFS_PARM0);
2101 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2103 // FIXME: implement rotation/scaling
2104 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
2105 clippointtosurface(model, surface, p, out);
2106 // FIXME: implement rotation/scaling
2107 VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2110 // #443 void(entity e, entity tagentity, string tagname) setattachment
2111 void VM_CL_setattachment (void)
2114 prvm_edict_t *tagentity;
2115 const char *tagname;
2119 VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
2121 e = PRVM_G_EDICT(OFS_PARM0);
2122 tagentity = PRVM_G_EDICT(OFS_PARM1);
2123 tagname = PRVM_G_STRING(OFS_PARM2);
2125 if (e == prog->edicts)
2127 VM_Warning("setattachment: can not modify world entity\n");
2130 if (e->priv.server->free)
2132 VM_Warning("setattachment: can not modify free entity\n");
2136 if (tagentity == NULL)
2137 tagentity = prog->edicts;
2139 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2141 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2143 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2146 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2148 modelindex = (int)tagentity->fields.client->modelindex;
2149 model = CL_GetModelByIndex(modelindex);
2152 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
2154 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);
2157 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));
2161 /////////////////////////////////////////
2162 // DP_MD3_TAGINFO extension coded by VorteX
2164 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
2166 dp_model_t *model = CL_GetModelFromEdict(e);
2168 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
2173 // Warnings/errors code:
2174 // 0 - normal (everything all-right)
2177 // 3 - null or non-precached model
2178 // 4 - no tags with requested index
2179 // 5 - runaway loop at attachment chain
2180 extern cvar_t cl_bob;
2181 extern cvar_t cl_bobcycle;
2182 extern cvar_t cl_bobup;
2183 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2186 int reqframe, attachloop;
2187 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2188 prvm_edict_t *attachent;
2192 *out = identitymatrix; // warnings and errors return identical matrix
2194 if (ent == prog->edicts)
2196 if (ent->priv.server->free)
2199 model = CL_GetModelFromEdict(ent);
2204 if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2205 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2207 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2209 // get initial tag matrix
2212 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2217 tagmatrix = identitymatrix;
2219 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2220 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2224 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2225 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
2227 model = CL_GetModelFromEdict(attachent);
2229 if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2230 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
2232 attachmatrix = identitymatrix;
2234 // apply transformation by child entity matrix
2236 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2237 if (val && val->_float != 0)
2238 scale = val->_float;
2239 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], scale);
2240 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2241 Matrix4x4_Copy(&tagmatrix, out);
2243 // finally transformate by matrix of tag on parent entity
2244 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2245 Matrix4x4_Copy(&tagmatrix, out);
2249 if (attachloop > 255) // prevent runaway looping
2252 while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
2255 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2257 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2258 if (val && val->_float != 0)
2259 scale = val->_float;
2260 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2261 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], scale);
2262 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2264 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2265 {// RENDER_VIEWMODEL magic
2266 Matrix4x4_Copy(&tagmatrix, out);
2269 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2270 if (val && val->_float != 0)
2271 scale = val->_float;
2273 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale);
2274 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2277 // Cl_bob, ported from rendering code
2278 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2281 // LordHavoc: this code is *weird*, but not replacable (I think it
2282 // should be done in QC on the server, but oh well, quake is quake)
2283 // LordHavoc: figured out bobup: the time at which the sin is at 180
2284 // degrees (which allows lengthening or squishing the peak or valley)
2285 cycle = cl.time/cl_bobcycle.value;
2286 cycle -= (int)cycle;
2287 if (cycle < cl_bobup.value)
2288 cycle = sin(M_PI * cycle / cl_bobup.value);
2290 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2291 // bob is proportional to velocity in the xy plane
2292 // (don't count Z, or jumping messes it up)
2293 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;
2294 bob = bob*0.3 + bob*0.7*cycle;
2295 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2302 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2303 void VM_CL_gettagindex (void)
2306 const char *tag_name;
2307 int modelindex, tag_index;
2309 VM_SAFEPARMCOUNT(2, VM_CL_gettagindex);
2311 ent = PRVM_G_EDICT(OFS_PARM0);
2312 tag_name = PRVM_G_STRING(OFS_PARM1);
2313 if (ent == prog->edicts)
2315 VM_Warning("gettagindex: can't affect world entity\n");
2318 if (ent->priv.server->free)
2320 VM_Warning("gettagindex: can't affect free entity\n");
2324 modelindex = (int)ent->fields.client->modelindex;
2326 if (modelindex >= MAX_MODELS || (modelindex <= -MAX_MODELS /* client models */))
2327 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2330 tag_index = CL_GetTagIndex(ent, tag_name);
2332 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2334 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2337 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2338 void VM_CL_gettaginfo (void)
2342 matrix4x4_t tag_matrix;
2345 VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
2347 e = PRVM_G_EDICT(OFS_PARM0);
2348 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2349 returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2350 Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2355 VM_Warning("gettagindex: can't affect world entity\n");
2358 VM_Warning("gettagindex: can't affect free entity\n");
2361 Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2364 Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2367 Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2372 //============================================================================
2374 //====================
2375 //QC POLYGON functions
2376 //====================
2378 #define VMPOLYGONS_MAXPOINTS 64
2380 typedef struct vmpolygons_triangle_s
2382 rtexture_t *texture;
2384 unsigned short elements[3];
2385 }vmpolygons_triangle_t;
2387 typedef struct vmpolygons_s
2390 qboolean initialized;
2391 double progstarttime;
2395 float *data_vertex3f;
2396 float *data_color4f;
2397 float *data_texcoord2f;
2401 vmpolygons_triangle_t *data_triangles;
2402 unsigned short *data_sortedelement3s;
2404 qboolean begin_active;
2405 rtexture_t *begin_texture;
2408 float begin_vertex[VMPOLYGONS_MAXPOINTS][3];
2409 float begin_color[VMPOLYGONS_MAXPOINTS][4];
2410 float begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
2413 // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
2414 vmpolygons_t vmpolygons[PRVM_MAXPROGS];
2416 //#304 void() renderscene (EXT_CSQC)
2417 // moved that here to reset the polygons,
2418 // resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0
2420 void VM_CL_R_RenderScene (void)
2422 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2423 VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
2424 // we need to update any RENDER_VIEWMODEL entities at this point because
2425 // csqc supplies its own view matrix
2426 CL_UpdateViewEntities();
2430 polys->num_vertices = polys->num_triangles = 0;
2431 polys->progstarttime = prog->starttime;
2434 static void VM_ResizePolygons(vmpolygons_t *polys)
2436 float *oldvertex3f = polys->data_vertex3f;
2437 float *oldcolor4f = polys->data_color4f;
2438 float *oldtexcoord2f = polys->data_texcoord2f;
2439 vmpolygons_triangle_t *oldtriangles = polys->data_triangles;
2440 unsigned short *oldsortedelement3s = polys->data_sortedelement3s;
2441 polys->max_vertices = min(polys->max_triangles*3, 65536);
2442 polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3]));
2443 polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4]));
2444 polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2]));
2445 polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t));
2446 polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3]));
2447 if (polys->num_vertices)
2449 memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3]));
2450 memcpy(polys->data_color4f, oldcolor4f, polys->num_vertices*sizeof(float[4]));
2451 memcpy(polys->data_texcoord2f, oldtexcoord2f, polys->num_vertices*sizeof(float[2]));
2453 if (polys->num_triangles)
2455 memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t));
2456 memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3]));
2459 Mem_Free(oldvertex3f);
2461 Mem_Free(oldcolor4f);
2463 Mem_Free(oldtexcoord2f);
2465 Mem_Free(oldtriangles);
2466 if (oldsortedelement3s)
2467 Mem_Free(oldsortedelement3s);
2470 static void VM_InitPolygons (vmpolygons_t* polys)
2472 memset(polys, 0, sizeof(*polys));
2473 polys->pool = Mem_AllocPool("VMPOLY", 0, NULL);
2474 polys->max_triangles = 1024;
2475 VM_ResizePolygons(polys);
2476 polys->initialized = true;
2479 static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2481 int surfacelistindex;
2482 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2483 if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
2485 R_Mesh_ResetTextureState();
2486 R_Mesh_Matrix(&identitymatrix);
2487 GL_CullFace(GL_NONE);
2488 R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0);
2489 R_Mesh_ColorPointer(polys->data_color4f, 0, 0);
2490 R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0);
2491 R_SetupGenericShader(true);
2493 for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
2495 int numtriangles = 0;
2496 rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
2497 int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
2498 // this can't call _DrawQ_ProcessDrawFlag, but should be in sync with it
2499 // FIXME factor this out
2500 if(drawflag == DRAWFLAG_ADDITIVE)
2501 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2502 else if(drawflag == DRAWFLAG_MODULATE)
2503 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
2504 else if(drawflag == DRAWFLAG_2XMODULATE)
2505 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
2506 else if(drawflag == DRAWFLAG_SCREEN)
2507 GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
2509 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2510 R_Mesh_TexBind(0, R_GetTexture(tex));
2512 for (;surfacelistindex < numsurfaces;surfacelistindex++)
2514 if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag)
2516 VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles);
2519 R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0);
2523 void VMPolygons_Store(vmpolygons_t *polys)
2525 if (r_refdef.draw2dstage)
2527 // draw the polygon as 2D immediately
2528 drawqueuemesh_t mesh;
2529 mesh.texture = polys->begin_texture;
2530 mesh.num_vertices = polys->begin_vertices;
2531 mesh.num_triangles = polys->begin_vertices-2;
2532 mesh.data_element3s = polygonelements;
2533 mesh.data_vertex3f = polys->begin_vertex[0];
2534 mesh.data_color4f = polys->begin_color[0];
2535 mesh.data_texcoord2f = polys->begin_texcoord[0];
2536 DrawQ_Mesh(&mesh, polys->begin_drawflag);
2540 // queue the polygon as 3D for sorted transparent rendering later
2542 if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
2544 polys->max_triangles *= 2;
2545 VM_ResizePolygons(polys);
2547 if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices)
2549 // needle in a haystack!
2550 // polys->num_vertices was used for copying where we actually want to copy begin_vertices
2551 // that also caused it to not render the first polygon that is added
2553 memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3]));
2554 memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4]));
2555 memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2]));
2556 for (i = 0;i < polys->begin_vertices-2;i++)
2558 polys->data_triangles[polys->num_triangles].texture = polys->begin_texture;
2559 polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag;
2560 polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices;
2561 polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1;
2562 polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2;
2563 polys->num_triangles++;
2565 polys->num_vertices += polys->begin_vertices;
2568 polys->begin_active = false;
2571 // TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black]
2572 // LordHavoc: agreed, this is a mess
2573 void VM_CL_AddPolygonsToMeshQueue (void)
2576 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2579 // only add polygons of the currently active prog to the queue - if there is none, we're done
2583 if (!polys->num_triangles)
2586 for (i = 0;i < polys->num_triangles;i++)
2588 VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center);
2589 R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
2592 /*polys->num_triangles = 0; // now done after rendering the scene,
2593 polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */
2596 //void(string texturename, float flag) R_BeginPolygon
2597 void VM_CL_R_PolygonBegin (void)
2599 const char *picname;
2601 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2604 // TODO instead of using skinframes here (which provides the benefit of
2605 // better management of flags, and is more suited for 3D rendering), what
2606 // about supporting Q3 shaders?
2608 VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin);
2610 if (!polys->initialized)
2611 VM_InitPolygons(polys);
2612 if(polys->progstarttime != prog->starttime)
2614 // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid)
2615 polys->num_vertices = polys->num_triangles = 0;
2616 polys->progstarttime = prog->starttime;
2618 if (polys->begin_active)
2620 VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
2623 picname = PRVM_G_STRING(OFS_PARM0);
2629 if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP)
2634 sf = R_SkinFrame_FindNextByName(sf, picname);
2636 while(sf && sf->textureflags != tf);
2638 if(!sf || !sf->base)
2639 sf = R_SkinFrame_LoadExternal(picname, tf, true);
2642 R_SkinFrame_MarkUsed(sf);
2645 polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white;
2646 polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK;
2647 polys->begin_vertices = 0;
2648 polys->begin_active = true;
2651 //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2652 void VM_CL_R_PolygonVertex (void)
2654 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2656 VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
2658 if (!polys->begin_active)
2660 VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
2664 if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS)
2666 VM_Warning("VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
2670 polys->begin_vertex[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM0)[0];
2671 polys->begin_vertex[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM0)[1];
2672 polys->begin_vertex[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM0)[2];
2673 polys->begin_texcoord[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM1)[0];
2674 polys->begin_texcoord[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM1)[1];
2675 polys->begin_color[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM2)[0];
2676 polys->begin_color[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM2)[1];
2677 polys->begin_color[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM2)[2];
2678 polys->begin_color[polys->begin_vertices][3] = PRVM_G_FLOAT(OFS_PARM3);
2679 polys->begin_vertices++;
2682 //void() R_EndPolygon
2683 void VM_CL_R_PolygonEnd (void)
2685 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2687 VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
2688 if (!polys->begin_active)
2690 VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
2693 polys->begin_active = false;
2694 if (polys->begin_vertices >= 3)
2695 VMPolygons_Store(polys);
2697 VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices);
2700 static vmpolygons_t debugPolys;
2702 void Debug_PolygonBegin(const char *picname, int drawflag)
2704 if(!debugPolys.initialized)
2705 VM_InitPolygons(&debugPolys);
2706 if(debugPolys.begin_active)
2708 Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
2711 debugPolys.begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
2712 debugPolys.begin_drawflag = drawflag;
2713 debugPolys.begin_vertices = 0;
2714 debugPolys.begin_active = true;
2717 void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
2719 if(!debugPolys.begin_active)
2721 Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
2725 if(debugPolys.begin_vertices > VMPOLYGONS_MAXPOINTS)
2727 Con_Printf("Debug_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
2731 debugPolys.begin_vertex[debugPolys.begin_vertices][0] = x;
2732 debugPolys.begin_vertex[debugPolys.begin_vertices][1] = y;
2733 debugPolys.begin_vertex[debugPolys.begin_vertices][2] = z;
2734 debugPolys.begin_texcoord[debugPolys.begin_vertices][0] = s;
2735 debugPolys.begin_texcoord[debugPolys.begin_vertices][1] = t;
2736 debugPolys.begin_color[debugPolys.begin_vertices][0] = r;
2737 debugPolys.begin_color[debugPolys.begin_vertices][1] = g;
2738 debugPolys.begin_color[debugPolys.begin_vertices][2] = b;
2739 debugPolys.begin_color[debugPolys.begin_vertices][3] = a;
2740 debugPolys.begin_vertices++;
2743 void Debug_PolygonEnd(void)
2745 if (!debugPolys.begin_active)
2747 Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
2750 debugPolys.begin_active = false;
2751 if (debugPolys.begin_vertices >= 3)
2752 VMPolygons_Store(&debugPolys);
2754 Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.begin_vertices);
2761 Returns false if any part of the bottom of the entity is off an edge that
2766 qboolean CL_CheckBottom (prvm_edict_t *ent)
2768 vec3_t mins, maxs, start, stop;
2773 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
2774 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
2776 // if all of the points under the corners are solid world, don't bother
2777 // with the tougher checks
2778 // the corners must be within 16 of the midpoint
2779 start[2] = mins[2] - 1;
2780 for (x=0 ; x<=1 ; x++)
2781 for (y=0 ; y<=1 ; y++)
2783 start[0] = x ? maxs[0] : mins[0];
2784 start[1] = y ? maxs[1] : mins[1];
2785 if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
2789 return true; // we got out easy
2793 // check it for real...
2797 // the midpoint must be within 16 of the bottom
2798 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
2799 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
2800 stop[2] = start[2] - 2*sv_stepheight.value;
2801 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2803 if (trace.fraction == 1.0)
2805 mid = bottom = trace.endpos[2];
2807 // the corners must be within 16 of the midpoint
2808 for (x=0 ; x<=1 ; x++)
2809 for (y=0 ; y<=1 ; y++)
2811 start[0] = stop[0] = x ? maxs[0] : mins[0];
2812 start[1] = stop[1] = y ? maxs[1] : mins[1];
2814 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2816 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
2817 bottom = trace.endpos[2];
2818 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
2829 Called by monster program code.
2830 The move will be adjusted for slopes and stairs, but if the move isn't
2831 possible, no move is done and false is returned
2834 qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
2837 vec3_t oldorg, neworg, end, traceendpos;
2840 prvm_edict_t *enemy;
2844 VectorCopy (ent->fields.client->origin, oldorg);
2845 VectorAdd (ent->fields.client->origin, move, neworg);
2847 // flying monsters don't step up
2848 if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
2850 // try one move with vertical motion, then one without
2851 for (i=0 ; i<2 ; i++)
2853 VectorAdd (ent->fields.client->origin, move, neworg);
2854 enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
2855 if (i == 0 && enemy != prog->edicts)
2857 dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
2863 trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
2865 CL_VM_SetTraceGlobals(&trace, svent);
2867 if (trace.fraction == 1)
2869 VectorCopy(trace.endpos, traceendpos);
2870 if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
2871 return false; // swim monster left water
2873 VectorCopy (traceendpos, ent->fields.client->origin);
2879 if (enemy == prog->edicts)
2886 // push down from a step height above the wished position
2887 neworg[2] += sv_stepheight.value;
2888 VectorCopy (neworg, end);
2889 end[2] -= sv_stepheight.value*2;
2891 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
2893 CL_VM_SetTraceGlobals(&trace, svent);
2895 if (trace.startsolid)
2897 neworg[2] -= sv_stepheight.value;
2898 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
2900 CL_VM_SetTraceGlobals(&trace, svent);
2901 if (trace.startsolid)
2904 if (trace.fraction == 1)
2906 // if monster had the ground pulled out, go ahead and fall
2907 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2909 VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
2912 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
2916 return false; // walked off an edge
2919 // check point traces down for dangling corners
2920 VectorCopy (trace.endpos, ent->fields.client->origin);
2922 if (!CL_CheckBottom (ent))
2924 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2925 { // entity had floor mostly pulled out from underneath it
2926 // and is trying to correct
2931 VectorCopy (oldorg, ent->fields.client->origin);
2935 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2936 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
2938 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
2939 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
2951 float(float yaw, float dist[, settrace]) walkmove
2954 static void VM_CL_walkmove (void)
2963 VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
2965 // assume failure if it returns early
2966 PRVM_G_FLOAT(OFS_RETURN) = 0;
2968 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
2969 if (ent == prog->edicts)
2971 VM_Warning("walkmove: can not modify world entity\n");
2974 if (ent->priv.server->free)
2976 VM_Warning("walkmove: can not modify free entity\n");
2979 yaw = PRVM_G_FLOAT(OFS_PARM0);
2980 dist = PRVM_G_FLOAT(OFS_PARM1);
2981 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
2983 if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
2986 yaw = yaw*M_PI*2 / 360;
2988 move[0] = cos(yaw)*dist;
2989 move[1] = sin(yaw)*dist;
2992 // save program state, because CL_movestep may call other progs
2993 oldf = prog->xfunction;
2994 oldself = prog->globals.client->self;
2996 PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
2999 // restore program state
3000 prog->xfunction = oldf;
3001 prog->globals.client->self = oldself;
3008 string(string key) serverkey
3011 void VM_CL_serverkey(void)
3013 char string[VM_STRINGTEMP_LENGTH];
3014 VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
3015 InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
3016 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
3019 //============================================================================
3021 // To create a almost working builtin file from this replace:
3022 // "^NULL.*" with ""
3023 // "^{.*//.*}:Wh\(.*\)" with "\1"
3025 // "^.*//:Wh{\#:d*}:Wh{.*}" with "\2 = \1;"
3026 // "\n\n+" with "\n\n"
3028 prvm_builtin_t vm_cl_builtins[] = {
3029 NULL, // #0 NULL function (not callable) (QUAKE)
3030 VM_CL_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3031 VM_CL_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3032 VM_CL_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3033 VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3034 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3035 VM_break, // #6 void() break (QUAKE)
3036 VM_random, // #7 float() random (QUAKE)
3037 VM_CL_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3038 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3039 VM_error, // #10 void(string e) error (QUAKE)
3040 VM_objerror, // #11 void(string e) objerror (QUAKE)
3041 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3042 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3043 VM_CL_spawn, // #14 entity() spawn (QUAKE)
3044 VM_remove, // #15 void(entity e) remove (QUAKE)
3045 VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents, entity ignoreentity) traceline (QUAKE)
3046 NULL, // #17 entity() checkclient (QUAKE)
3047 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3048 VM_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3049 VM_CL_precache_model, // #20 void(string s) precache_model (QUAKE)
3050 NULL, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3051 VM_CL_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3052 NULL, // #23 void(string s, ...) bprint (QUAKE)
3053 NULL, // #24 void(entity client, string s, ...) sprint (QUAKE)
3054 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3055 VM_ftos, // #26 string(float f) ftos (QUAKE)
3056 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3057 VM_coredump, // #28 void() coredump (QUAKE)
3058 VM_traceon, // #29 void() traceon (QUAKE)
3059 VM_traceoff, // #30 void() traceoff (QUAKE)
3060 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3061 VM_CL_walkmove, // #32 float(float yaw, float dist[, float settrace]) walkmove (QUAKE)
3062 NULL, // #33 (QUAKE)
3063 VM_CL_droptofloor, // #34 float() droptofloor (QUAKE)
3064 VM_CL_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3065 VM_rint, // #36 float(float v) rint (QUAKE)
3066 VM_floor, // #37 float(float v) floor (QUAKE)
3067 VM_ceil, // #38 float(float v) ceil (QUAKE)
3068 NULL, // #39 (QUAKE)
3069 VM_CL_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3070 VM_CL_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3071 NULL, // #42 (QUAKE)
3072 VM_fabs, // #43 float(float f) fabs (QUAKE)
3073 NULL, // #44 vector(entity e, float speed) aim (QUAKE)
3074 VM_cvar, // #45 float(string s) cvar (QUAKE)
3075 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3076 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3077 VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3078 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3079 NULL, // #50 (QUAKE)
3080 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3081 NULL, // #52 void(float to, float f) WriteByte (QUAKE)
3082 NULL, // #53 void(float to, float f) WriteChar (QUAKE)
3083 NULL, // #54 void(float to, float f) WriteShort (QUAKE)
3084 NULL, // #55 void(float to, float f) WriteLong (QUAKE)
3085 NULL, // #56 void(float to, float f) WriteCoord (QUAKE)
3086 NULL, // #57 void(float to, float f) WriteAngle (QUAKE)
3087 NULL, // #58 void(float to, string s) WriteString (QUAKE)
3088 NULL, // #59 (QUAKE)
3089 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3090 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3091 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3092 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3093 VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3094 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3095 NULL, // #66 (QUAKE)
3096 NULL, // #67 void(float step) movetogoal (QUAKE)
3097 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3098 VM_CL_makestatic, // #69 void(entity e) makestatic (QUAKE)
3099 NULL, // #70 void(string s) changelevel (QUAKE)
3100 NULL, // #71 (QUAKE)
3101 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3102 NULL, // #73 void(entity client, strings) centerprint (QUAKE)
3103 VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3104 VM_CL_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3105 VM_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3106 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3107 NULL, // #78 void(entity e) setspawnparms (QUAKE)
3108 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3109 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3110 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3111 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3112 NULL, // #83 (QUAKE)
3113 NULL, // #84 (QUAKE)
3114 NULL, // #85 (QUAKE)
3115 NULL, // #86 (QUAKE)
3116 NULL, // #87 (QUAKE)
3117 NULL, // #88 (QUAKE)
3118 NULL, // #89 (QUAKE)
3119 VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3120 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3121 VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3122 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3123 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3124 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3125 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3126 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3127 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3128 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3129 // FrikaC and Telejano range #100-#199
3140 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3141 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3142 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3143 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3144 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3145 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3146 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3147 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3148 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3149 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3230 // FTEQW range #200-#299
3249 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3252 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3253 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3254 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3255 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3256 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3257 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3258 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3259 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3260 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3261 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3263 NULL, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3331 // CSQC range #300-#399
3332 VM_CL_R_ClearScene, // #300 void() clearscene (EXT_CSQC)
3333 VM_CL_R_AddEntities, // #301 void(float mask) addentities (EXT_CSQC)
3334 VM_CL_R_AddEntity, // #302 void(entity ent) addentity (EXT_CSQC)
3335 VM_CL_R_SetView, // #303 float(float property, ...) setproperty (EXT_CSQC)
3336 VM_CL_R_RenderScene, // #304 void() renderscene (EXT_CSQC)
3337 VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3338 VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3339 VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3340 VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
3341 NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
3342 VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3343 VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC)
3347 VM_drawline, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3348 VM_iscachedpic, // #316 float(string name) iscachedpic (EXT_CSQC)
3349 VM_precache_pic, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3350 VM_getimagesize, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3351 VM_freepic, // #319 void(string name) freepic (EXT_CSQC)
3352 VM_drawcharacter, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3353 VM_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3354 VM_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3355 VM_drawfill, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3356 VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea
3357 VM_drawresetcliparea, // #325 void(void) drawresetcliparea
3358 VM_drawcolorcodedstring, // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
3359 VM_stringwidth, // #327 // FIXME is this okay?
3360 VM_drawsubpic, // #328 // FIXME is this okay?
3362 VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC)
3363 VM_CL_getstati, // #331 float(float stnum) getstati (EXT_CSQC)
3364 VM_CL_getstats, // #332 string(float firststnum) getstats (EXT_CSQC)
3365 VM_CL_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3366 VM_CL_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3367 VM_CL_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3368 VM_CL_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3369 VM_CL_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3370 VM_centerprint, // #338 void(string s, ...) centerprint (EXT_CSQC)
3371 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3372 VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3373 VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3374 VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
3375 VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3376 VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
3377 VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC)
3378 VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscale (EXT_CSQC)
3379 VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC)
3380 VM_CL_getplayerkey, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3381 VM_CL_isdemo, // #349 float() isdemo (EXT_CSQC)
3382 VM_isserver, // #350 float() isserver (EXT_CSQC)
3383 VM_CL_setlistener, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3384 VM_CL_registercmd, // #352 void(string cmdname) registercommand (EXT_CSQC)
3385 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3386 VM_CL_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3392 VM_CL_ReadByte, // #360 float() readbyte (EXT_CSQC)
3393 VM_CL_ReadChar, // #361 float() readchar (EXT_CSQC)
3394 VM_CL_ReadShort, // #362 float() readshort (EXT_CSQC)
3395 VM_CL_ReadLong, // #363 float() readlong (EXT_CSQC)
3396 VM_CL_ReadCoord, // #364 float() readcoord (EXT_CSQC)
3397 VM_CL_ReadAngle, // #365 float() readangle (EXT_CSQC)
3398 VM_CL_ReadString, // #366 string() readstring (EXT_CSQC)
3399 VM_CL_ReadFloat, // #367 float() readfloat (EXT_CSQC)
3432 // LordHavoc's range #400-#499
3433 VM_CL_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3434 NULL, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3435 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3436 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3437 VM_CL_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3438 VM_CL_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3439 VM_CL_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3440 VM_CL_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3441 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)
3442 VM_CL_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3443 VM_CL_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3444 VM_CL_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3445 VM_CL_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3446 VM_CL_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3447 VM_CL_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3448 VM_CL_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3449 VM_CL_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3450 VM_CL_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3451 VM_CL_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3452 VM_CL_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3453 VM_CL_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3454 VM_CL_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3455 VM_CL_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3456 VM_CL_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3457 VM_CL_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3458 VM_CL_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3459 VM_CL_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3460 VM_CL_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3461 VM_CL_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3462 VM_CL_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3463 VM_CL_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3464 VM_CL_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3465 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3466 VM_CL_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3467 VM_CL_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3468 VM_CL_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3469 VM_CL_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3470 VM_CL_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3471 VM_CL_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3472 VM_CL_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3473 NULL, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3474 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3475 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3476 VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3477 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3478 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3479 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3480 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3481 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3482 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3483 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3484 VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3485 VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3486 NULL, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3487 NULL, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3488 NULL, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3489 NULL, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3490 VM_CL_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet (DP_TE_FLAMEJET)
3492 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3493 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3494 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3495 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3496 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3497 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3498 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3499 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3500 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3501 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3502 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3503 NULL, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3504 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3505 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3506 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3507 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3508 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3509 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3510 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
3511 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3512 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3513 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3514 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3515 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3516 VM_CL_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) pointsound (DP_SV_POINTSOUND)
3517 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3518 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3519 VM_CL_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute
3520 VM_gecko_create, // #487 float gecko_create( string name )
3521 VM_gecko_destroy, // #488 void gecko_destroy( string name )
3522 VM_gecko_navigate, // #489 void gecko_navigate( string name, string URI )
3523 VM_gecko_keyevent, // #490 float gecko_keyevent( string name, float key, float eventtype )
3524 VM_gecko_movemouse, // #491 void gecko_mousemove( string name, float x, float y )
3525 VM_gecko_resize, // #492 void gecko_resize( string name, float w, float h )
3526 VM_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name )
3527 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3528 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3529 VM_numentityfields, // #496 float() numentityfields = #496; (QP_QC_ENTITYDATA)
3530 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3531 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3532 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3533 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3534 VM_CL_ReadPicture, // #501 string() ReadPicture = #501;
3536 VM_whichpack, // #503 string(string) whichpack = #503;
3543 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3544 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3545 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3546 VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET)
3547 VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3548 VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3549 VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3550 VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3551 VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3553 VM_keynumtostring, // #520 string keynumtostring(float keynum)
3554 VM_findkeysforcommand, // #521 string findkeysforcommand(string command)
3557 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3559 void VM_Polygons_Reset(void)
3561 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
3563 // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
3564 if(polys->initialized)
3566 Mem_FreePool(&polys->pool);
3567 polys->initialized = false;
3571 void VM_CL_Cmd_Init(void)
3574 VM_Polygons_Reset();
3577 void VM_CL_Cmd_Reset(void)
3580 VM_Polygons_Reset();