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 // #16 float(vector v1, vector v2, float movetype, entity ignore) traceline
234 static void VM_CL_traceline (void)
241 VM_SAFEPARMCOUNTRANGE(4, 4, VM_CL_traceline);
243 prog->xfunction->builtinsprofile += 30;
245 v1 = PRVM_G_VECTOR(OFS_PARM0);
246 v2 = PRVM_G_VECTOR(OFS_PARM1);
247 move = (int)PRVM_G_FLOAT(OFS_PARM2);
248 ent = PRVM_G_EDICT(OFS_PARM3);
250 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]))
251 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));
253 trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
255 VM_SetTraceGlobals(&trace);
262 Used for use tracing and shot targeting
263 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
264 if the tryents flag is set.
266 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
269 // LordHavoc: added this for my own use, VERY useful, similar to traceline
270 static void VM_CL_tracebox (void)
272 float *v1, *v2, *m1, *m2;
277 VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion
279 prog->xfunction->builtinsprofile += 30;
281 v1 = PRVM_G_VECTOR(OFS_PARM0);
282 m1 = PRVM_G_VECTOR(OFS_PARM1);
283 m2 = PRVM_G_VECTOR(OFS_PARM2);
284 v2 = PRVM_G_VECTOR(OFS_PARM3);
285 move = (int)PRVM_G_FLOAT(OFS_PARM4);
286 ent = PRVM_G_EDICT(OFS_PARM5);
288 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]))
289 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));
291 trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
293 VM_SetTraceGlobals(&trace);
296 trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
301 vec3_t original_origin;
302 vec3_t original_velocity;
303 vec3_t original_angles;
304 vec3_t original_avelocity;
308 VectorCopy(tossent->fields.client->origin , original_origin );
309 VectorCopy(tossent->fields.client->velocity , original_velocity );
310 VectorCopy(tossent->fields.client->angles , original_angles );
311 VectorCopy(tossent->fields.client->avelocity, original_avelocity);
313 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
314 if (val != NULL && val->_float != 0)
315 gravity = val->_float;
318 gravity *= cl.movevars_gravity * 0.05;
320 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
322 tossent->fields.client->velocity[2] -= gravity;
323 VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles);
324 VectorScale (tossent->fields.client->velocity, 0.05, move);
325 VectorAdd (tossent->fields.client->origin, move, end);
326 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);
327 VectorCopy (trace.endpos, tossent->fields.client->origin);
329 if (trace.fraction < 1)
333 VectorCopy(original_origin , tossent->fields.client->origin );
334 VectorCopy(original_velocity , tossent->fields.client->velocity );
335 VectorCopy(original_angles , tossent->fields.client->angles );
336 VectorCopy(original_avelocity, tossent->fields.client->avelocity);
341 static void VM_CL_tracetoss (void)
345 prvm_edict_t *ignore;
347 prog->xfunction->builtinsprofile += 600;
349 VM_SAFEPARMCOUNT(2, VM_CL_tracetoss);
351 ent = PRVM_G_EDICT(OFS_PARM0);
352 if (ent == prog->edicts)
354 VM_Warning("tracetoss: can not use world entity\n");
357 ignore = PRVM_G_EDICT(OFS_PARM1);
359 trace = CL_Trace_Toss (ent, ignore);
361 VM_SetTraceGlobals(&trace);
365 // #20 void(string s) precache_model
366 void VM_CL_precache_model (void)
372 VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
374 name = PRVM_G_STRING(OFS_PARM0);
375 for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++)
377 if(!strcmp(cl.csqc_model_precache[i]->name, name))
379 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
383 PRVM_G_FLOAT(OFS_RETURN) = 0;
384 m = Mod_ForName(name, false, false, false);
387 for (i = 0;i < MAX_MODELS;i++)
389 if (!cl.csqc_model_precache[i])
391 cl.csqc_model_precache[i] = (dp_model_t*)m;
392 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
396 VM_Warning("VM_CL_precache_model: no free models\n");
399 VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
402 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
407 ent = PRVM_NEXT_EDICT(prog->edicts);
408 for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
410 if (ent->priv.required->free)
412 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
418 // #22 entity(vector org, float rad) findradius
419 static void VM_CL_findradius (void)
421 prvm_edict_t *ent, *chain;
422 vec_t radius, radius2;
423 vec3_t org, eorg, mins, maxs;
424 int i, numtouchedicts;
425 prvm_edict_t *touchedicts[MAX_EDICTS];
427 VM_SAFEPARMCOUNT(2, VM_CL_findradius);
429 chain = (prvm_edict_t *)prog->edicts;
431 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
432 radius = PRVM_G_FLOAT(OFS_PARM1);
433 radius2 = radius * radius;
435 mins[0] = org[0] - (radius + 1);
436 mins[1] = org[1] - (radius + 1);
437 mins[2] = org[2] - (radius + 1);
438 maxs[0] = org[0] + (radius + 1);
439 maxs[1] = org[1] + (radius + 1);
440 maxs[2] = org[2] + (radius + 1);
441 numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
442 if (numtouchedicts > MAX_EDICTS)
444 // this never happens //[515]: for what then ?
445 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
446 numtouchedicts = MAX_EDICTS;
448 for (i = 0;i < numtouchedicts;i++)
450 ent = touchedicts[i];
451 // Quake did not return non-solid entities but darkplaces does
452 // (note: this is the reason you can't blow up fallen zombies)
453 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
455 // LordHavoc: compare against bounding box rather than center so it
456 // doesn't miss large objects, and use DotProduct instead of Length
457 // for a major speedup
458 VectorSubtract(org, ent->fields.client->origin, eorg);
459 if (sv_gameplayfix_findradiusdistancetobox.integer)
461 eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
462 eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
463 eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
466 VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
467 if (DotProduct(eorg, eorg) < radius2)
469 ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
474 VM_RETURN_EDICT(chain);
477 // #34 float() droptofloor
478 static void VM_CL_droptofloor (void)
485 VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
487 // assume failure if it returns early
488 PRVM_G_FLOAT(OFS_RETURN) = 0;
490 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
491 if (ent == prog->edicts)
493 VM_Warning("droptofloor: can not modify world entity\n");
496 if (ent->priv.server->free)
498 VM_Warning("droptofloor: can not modify free entity\n");
502 VectorCopy (ent->fields.client->origin, end);
505 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);
507 if (trace.fraction != 1)
509 VectorCopy (trace.endpos, ent->fields.client->origin);
510 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
511 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
512 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
513 PRVM_G_FLOAT(OFS_RETURN) = 1;
514 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
515 // ent->priv.server->suspendedinairflag = true;
519 // #35 void(float style, string value) lightstyle
520 static void VM_CL_lightstyle (void)
525 VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
527 i = (int)PRVM_G_FLOAT(OFS_PARM0);
528 c = PRVM_G_STRING(OFS_PARM1);
529 if (i >= cl.max_lightstyle)
531 VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
534 strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map));
535 cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
536 cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
539 // #40 float(entity e) checkbottom
540 static void VM_CL_checkbottom (void)
542 static int cs_yes, cs_no;
544 vec3_t mins, maxs, start, stop;
549 VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
550 ent = PRVM_G_EDICT(OFS_PARM0);
551 PRVM_G_FLOAT(OFS_RETURN) = 0;
553 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
554 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
556 // if all of the points under the corners are solid world, don't bother
557 // with the tougher checks
558 // the corners must be within 16 of the midpoint
559 start[2] = mins[2] - 1;
560 for (x=0 ; x<=1 ; x++)
561 for (y=0 ; y<=1 ; y++)
563 start[0] = x ? maxs[0] : mins[0];
564 start[1] = y ? maxs[1] : mins[1];
565 if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
570 PRVM_G_FLOAT(OFS_RETURN) = true;
571 return; // we got out easy
576 // check it for real...
580 // the midpoint must be within 16 of the bottom
581 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
582 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
583 stop[2] = start[2] - 2*sv_stepheight.value;
584 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
586 if (trace.fraction == 1.0)
589 mid = bottom = trace.endpos[2];
591 // the corners must be within 16 of the midpoint
592 for (x=0 ; x<=1 ; x++)
593 for (y=0 ; y<=1 ; y++)
595 start[0] = stop[0] = x ? maxs[0] : mins[0];
596 start[1] = stop[1] = y ? maxs[1] : mins[1];
598 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
600 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
601 bottom = trace.endpos[2];
602 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
607 PRVM_G_FLOAT(OFS_RETURN) = true;
610 // #41 float(vector v) pointcontents
611 static void VM_CL_pointcontents (void)
613 VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
614 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
617 // #48 void(vector o, vector d, float color, float count) particle
618 static void VM_CL_particle (void)
623 VM_SAFEPARMCOUNT(4, VM_CL_particle);
625 org = PRVM_G_VECTOR(OFS_PARM0);
626 dir = PRVM_G_VECTOR(OFS_PARM1);
627 color = (int)PRVM_G_FLOAT(OFS_PARM2);
628 count = (int)PRVM_G_FLOAT(OFS_PARM3);
629 CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
632 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
633 static void VM_CL_ambientsound (void)
637 VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
638 s = S_FindName(PRVM_G_STRING(OFS_PARM0));
639 f = PRVM_G_VECTOR(OFS_PARM1);
640 S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
643 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
644 static void VM_CL_getlight (void)
646 vec3_t ambientcolor, diffusecolor, diffusenormal;
649 VM_SAFEPARMCOUNT(1, VM_CL_getlight);
651 p = PRVM_G_VECTOR(OFS_PARM0);
652 VectorClear(ambientcolor);
653 VectorClear(diffusecolor);
654 VectorClear(diffusenormal);
655 if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
656 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
657 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
661 //============================================================================
662 //[515]: SCENE MANAGER builtins
663 extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
665 static void CSQC_R_RecalcView (void)
667 extern matrix4x4_t viewmodelmatrix;
668 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);
669 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);
672 void CL_RelinkLightFlashes(void);
673 //#300 void() clearscene (EXT_CSQC)
674 void VM_CL_R_ClearScene (void)
676 VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
677 // clear renderable entity and light lists
678 r_refdef.scene.numentities = 0;
679 r_refdef.scene.numlights = 0;
680 // FIXME: restore these to the values from VM_CL_UpdateView
684 r_refdef.view.width = vid.width;
685 r_refdef.view.height = vid.height;
686 r_refdef.view.depth = 1;
687 // FIXME: restore frustum_x/frustum_y
688 r_refdef.view.useperspective = true;
689 r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
690 r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
691 r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
692 r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
693 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;
694 r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
695 r_refdef.view.clear = true;
696 r_refdef.view.isoverlay = false;
697 // FIXME: restore cl.csqc_origin
698 // FIXME: restore cl.csqc_angles
699 cl.csqc_vidvars.drawworld = true;
700 cl.csqc_vidvars.drawenginesbar = false;
701 cl.csqc_vidvars.drawcrosshair = false;
704 //#301 void(float mask) addentities (EXT_CSQC)
705 extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
706 extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
707 void VM_CL_R_AddEntities (void)
711 VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
712 drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
713 CSQC_RelinkAllEntities(drawmask);
714 CL_RelinkLightFlashes();
716 prog->globals.client->time = cl.time;
717 for(i=1;i<prog->num_edicts;i++)
719 ed = &prog->edicts[i];
720 if(ed->priv.required->free)
723 if(ed->priv.required->free)
725 // note that for RF_USEAXIS entities, Predraw sets v_forward/v_right/v_up globals that are read by CSQC_AddRenderEdict
727 if(ed->priv.required->free)
729 if(!((int)ed->fields.client->drawmask & drawmask))
731 CSQC_AddRenderEdict(ed);
735 //#302 void(entity ent) addentity (EXT_CSQC)
736 void VM_CL_R_AddEntity (void)
738 VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
739 CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
742 //#303 float(float property, ...) setproperty (EXT_CSQC)
743 void VM_CL_R_SetView (void)
749 VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView);
751 c = (int)PRVM_G_FLOAT(OFS_PARM0);
752 f = PRVM_G_VECTOR(OFS_PARM1);
753 k = PRVM_G_FLOAT(OFS_PARM1);
758 r_refdef.view.x = (int)(f[0]);
759 r_refdef.view.y = (int)(f[1]);
762 r_refdef.view.x = (int)(k);
765 r_refdef.view.y = (int)(k);
768 r_refdef.view.width = (int)(f[0]);
769 r_refdef.view.height = (int)(f[1]);
772 r_refdef.view.width = (int)(k);
775 r_refdef.view.height = (int)(k);
778 r_refdef.view.x = (int)(f[0]);
779 r_refdef.view.y = (int)(f[1]);
780 f = PRVM_G_VECTOR(OFS_PARM2);
781 r_refdef.view.width = (int)(f[0]);
782 r_refdef.view.height = (int)(f[1]);
785 r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0];
786 r_refdef.view.frustum_y = tan(f[1] * M_PI / 360.0);r_refdef.view.ortho_y = f[1];
789 r_refdef.view.frustum_x = tan(k * M_PI / 360.0);r_refdef.view.ortho_x = k;
792 r_refdef.view.frustum_y = tan(k * M_PI / 360.0);r_refdef.view.ortho_y = k;
795 VectorCopy(f, cl.csqc_origin);
799 cl.csqc_origin[0] = k;
803 cl.csqc_origin[1] = k;
807 cl.csqc_origin[2] = k;
811 VectorCopy(f, cl.csqc_angles);
815 cl.csqc_angles[0] = k;
819 cl.csqc_angles[1] = k;
823 cl.csqc_angles[2] = k;
827 cl.csqc_vidvars.drawworld = k;
829 case VF_DRAWENGINESBAR:
830 cl.csqc_vidvars.drawenginesbar = k;
832 case VF_DRAWCROSSHAIR:
833 cl.csqc_vidvars.drawcrosshair = k;
835 case VF_CL_VIEWANGLES:
836 VectorCopy(f, cl.viewangles);
838 case VF_CL_VIEWANGLES_X:
839 cl.viewangles[0] = k;
841 case VF_CL_VIEWANGLES_Y:
842 cl.viewangles[1] = k;
844 case VF_CL_VIEWANGLES_Z:
845 cl.viewangles[2] = k;
848 r_refdef.view.useperspective = k != 0;
851 r_refdef.view.isoverlay = !k;
854 PRVM_G_FLOAT(OFS_RETURN) = 0;
855 VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
858 PRVM_G_FLOAT(OFS_RETURN) = 1;
861 //#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC)
862 void VM_CL_R_AddDynamicLight (void)
868 const char *cubemapname = NULL;
869 int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC;
870 float coronaintensity = 1;
871 float coronasizescale = 0.25;
872 qboolean castshadow = true;
873 float ambientscale = 0;
874 float diffusescale = 1;
875 float specularscale = 1;
877 vec3_t forward, left, up;
878 VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight);
880 // if we've run out of dlights, just return
881 if (r_refdef.scene.numlights >= MAX_DLIGHTS)
884 org = PRVM_G_VECTOR(OFS_PARM0);
885 radius = PRVM_G_FLOAT(OFS_PARM1);
886 col = PRVM_G_VECTOR(OFS_PARM2);
889 style = (int)PRVM_G_FLOAT(OFS_PARM3);
890 if (style >= MAX_LIGHTSTYLES)
892 Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style);
897 cubemapname = PRVM_G_STRING(OFS_PARM4);
899 pflags = (int)PRVM_G_FLOAT(OFS_PARM5);
900 coronaintensity = (pflags & PFLAGS_CORONA) != 0;
901 castshadow = (pflags & PFLAGS_NOSHADOW) == 0;
903 VectorScale(prog->globals.client->v_forward, radius, forward);
904 VectorScale(prog->globals.client->v_right, -radius, left);
905 VectorScale(prog->globals.client->v_up, radius, up);
906 Matrix4x4_FromVectors(&matrix, forward, left, up, org);
908 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);
911 //============================================================================
913 //#310 vector (vector v) cs_unproject (EXT_CSQC)
914 static void VM_CL_unproject (void)
919 VM_SAFEPARMCOUNT(1, VM_CL_unproject);
920 f = PRVM_G_VECTOR(OFS_PARM0);
921 if(v_flipped.integer)
922 f[0] = r_refdef.view.x + r_refdef.view.width - f[0];
923 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);
924 Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
927 //#311 vector (vector v) cs_project (EXT_CSQC)
928 static void VM_CL_project (void)
934 VM_SAFEPARMCOUNT(1, VM_CL_project);
935 f = PRVM_G_VECTOR(OFS_PARM0);
936 Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
937 Matrix4x4_Transform(&m, f, v);
938 if(v_flipped.integer)
940 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]);
943 //#330 float(float stnum) getstatf (EXT_CSQC)
944 static void VM_CL_getstatf (void)
952 VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
953 i = (int)PRVM_G_FLOAT(OFS_PARM0);
954 if(i < 0 || i >= MAX_CL_STATS)
956 VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
960 PRVM_G_FLOAT(OFS_RETURN) = dat.f;
963 //#331 float(float stnum) getstati (EXT_CSQC)
964 static void VM_CL_getstati (void)
967 int firstbit, bitcount;
969 VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getstati);
971 index = (int)PRVM_G_FLOAT(OFS_PARM0);
974 firstbit = (int)PRVM_G_FLOAT(OFS_PARM1);
976 bitcount = (int)PRVM_G_FLOAT(OFS_PARM2);
986 if(index < 0 || index >= MAX_CL_STATS)
988 VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
992 if (bitcount != 32) //32 causes the mask to overflow, so there's nothing to subtract from.
993 i = (((unsigned int)i)&(((1<<bitcount)-1)<<firstbit))>>firstbit;
994 PRVM_G_FLOAT(OFS_RETURN) = i;
997 //#332 string(float firststnum) getstats (EXT_CSQC)
998 static void VM_CL_getstats (void)
1002 VM_SAFEPARMCOUNT(1, VM_CL_getstats);
1003 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1004 if(i < 0 || i > MAX_CL_STATS-4)
1006 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1007 VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
1010 strlcpy(t, (char*)&cl.stats[i], sizeof(t));
1011 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1014 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
1015 static void VM_CL_setmodelindex (void)
1019 struct model_s *model;
1021 VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
1023 t = PRVM_G_EDICT(OFS_PARM0);
1025 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1027 t->fields.client->model = 0;
1028 t->fields.client->modelindex = 0;
1033 model = CL_GetModelByIndex(i);
1036 VM_Warning("VM_CL_setmodelindex: null model\n");
1039 t->fields.client->model = PRVM_SetEngineString(model->name);
1040 t->fields.client->modelindex = i;
1042 // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
1045 SetMinMaxSize (t, model->normalmins, model->normalmaxs);
1048 SetMinMaxSize (t, vec3_origin, vec3_origin);
1051 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
1052 static void VM_CL_modelnameforindex (void)
1056 VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
1058 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1059 model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
1060 PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
1063 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1064 static void VM_CL_particleeffectnum (void)
1067 VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1068 i = CL_ParticleEffectIndexForName(PRVM_G_STRING(OFS_PARM0));
1071 PRVM_G_FLOAT(OFS_RETURN) = i;
1074 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1075 static void VM_CL_trailparticles (void)
1080 VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles);
1082 t = PRVM_G_EDICT(OFS_PARM0);
1083 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1084 start = PRVM_G_VECTOR(OFS_PARM2);
1085 end = PRVM_G_VECTOR(OFS_PARM3);
1089 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);
1092 //#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
1093 static void VM_CL_pointparticles (void)
1097 VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles);
1098 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1099 f = PRVM_G_VECTOR(OFS_PARM1);
1100 v = PRVM_G_VECTOR(OFS_PARM2);
1101 n = (int)PRVM_G_FLOAT(OFS_PARM3);
1104 CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
1107 //#342 string(float keynum) getkeybind (EXT_CSQC)
1108 static void VM_CL_getkeybind (void)
1110 VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1111 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
1114 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1115 static void VM_CL_setcursormode (void)
1117 VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1118 cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1119 cl_ignoremousemoves = 2;
1122 //#344 vector() getmousepos (EXT_CSQC)
1123 static void VM_CL_getmousepos(void)
1125 VM_SAFEPARMCOUNT(0,VM_CL_getmousepos);
1127 if (key_consoleactive || key_dest != key_game)
1128 VectorSet(PRVM_G_VECTOR(OFS_RETURN), 0, 0, 0);
1129 else if (cl.csqc_wantsmousemove)
1130 VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height, 0);
1132 VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height, 0);
1135 //#345 float(float framenum) getinputstate (EXT_CSQC)
1136 static void VM_CL_getinputstate (void)
1139 VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1140 frame = (int)PRVM_G_FLOAT(OFS_PARM0);
1141 for (i = 0;i < CL_MAX_USERCMDS;i++)
1143 if (cl.movecmd[i].sequence == frame)
1145 VectorCopy(cl.movecmd[i].viewangles, prog->globals.client->input_angles);
1146 prog->globals.client->input_buttons = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?)
1147 prog->globals.client->input_movevalues[0] = cl.movecmd[i].forwardmove;
1148 prog->globals.client->input_movevalues[1] = cl.movecmd[i].sidemove;
1149 prog->globals.client->input_movevalues[2] = cl.movecmd[i].upmove;
1150 prog->globals.client->input_timelength = cl.movecmd[i].frametime;
1151 if(cl.movecmd[i].crouch)
1153 VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
1154 VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
1158 VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
1159 VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
1165 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1166 static void VM_CL_setsensitivityscale (void)
1168 VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1169 cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1172 //#347 void() runstandardplayerphysics (EXT_CSQC)
1173 static void VM_CL_runplayerphysics (void)
1177 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1178 static void VM_CL_getplayerkey (void)
1184 VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1186 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1187 c = PRVM_G_STRING(OFS_PARM1);
1188 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1192 i = Sbar_GetSortedPlayerIndex(-1-i);
1193 if(i < 0 || i >= cl.maxclients)
1198 if(!strcasecmp(c, "name"))
1199 strlcpy(t, cl.scores[i].name, sizeof(t));
1201 if(!strcasecmp(c, "frags"))
1202 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags);
1204 if(!strcasecmp(c, "ping"))
1205 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping);
1207 if(!strcasecmp(c, "pl"))
1208 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss);
1210 if(!strcasecmp(c, "entertime"))
1211 dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime);
1213 if(!strcasecmp(c, "colors"))
1214 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors);
1216 if(!strcasecmp(c, "topcolor"))
1217 dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0);
1219 if(!strcasecmp(c, "bottomcolor"))
1220 dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4);
1222 if(!strcasecmp(c, "viewentity"))
1223 dpsnprintf(t, sizeof(t), "%i", i+1);
1226 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
1229 //#349 float() isdemo (EXT_CSQC)
1230 static void VM_CL_isdemo (void)
1232 VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
1233 PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1236 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1237 static void VM_CL_setlistener (void)
1239 VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1240 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));
1241 cl.csqc_usecsqclistener = true; //use csqc listener at this frame
1244 //#352 void(string cmdname) registercommand (EXT_CSQC)
1245 static void VM_CL_registercmd (void)
1248 VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1249 if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1253 alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
1254 t = (char *)Z_Malloc(alloclen);
1255 memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
1256 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1259 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1263 //#360 float() readbyte (EXT_CSQC)
1264 static void VM_CL_ReadByte (void)
1266 VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
1267 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1270 //#361 float() readchar (EXT_CSQC)
1271 static void VM_CL_ReadChar (void)
1273 VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
1274 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1277 //#362 float() readshort (EXT_CSQC)
1278 static void VM_CL_ReadShort (void)
1280 VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
1281 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1284 //#363 float() readlong (EXT_CSQC)
1285 static void VM_CL_ReadLong (void)
1287 VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
1288 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1291 //#364 float() readcoord (EXT_CSQC)
1292 static void VM_CL_ReadCoord (void)
1294 VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
1295 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1298 //#365 float() readangle (EXT_CSQC)
1299 static void VM_CL_ReadAngle (void)
1301 VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
1302 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1305 //#366 string() readstring (EXT_CSQC)
1306 static void VM_CL_ReadString (void)
1308 VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
1309 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
1312 //#367 float() readfloat (EXT_CSQC)
1313 static void VM_CL_ReadFloat (void)
1315 VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
1316 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1319 //#501 string() readpicture (DP_CSQC_READWRITEPICTURE)
1320 extern cvar_t cl_readpicture_force;
1321 static void VM_CL_ReadPicture (void)
1324 unsigned char *data;
1330 VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
1332 name = MSG_ReadString();
1333 size = MSG_ReadShort();
1335 // check if a texture of that name exists
1336 // if yes, it is used and the data is discarded
1337 // if not, the (low quality) data is used to build a new texture, whose name will get returned
1339 pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT);
1343 if(pic->tex == r_texture_notexture)
1344 pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic
1345 if(pic->tex && !cl_readpicture_force.integer)
1347 // texture found and loaded
1348 // skip over the jpeg as we don't need it
1349 for(i = 0; i < size; ++i)
1354 // texture not found
1355 // use the attached jpeg as texture
1356 buf = Mem_Alloc(tempmempool, size);
1357 MSG_ReadBytes(size, buf);
1358 data = JPEG_LoadImage_BGRA(buf, size);
1360 Draw_NewPic(name, image_width, image_height, false, data);
1365 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name);
1368 //////////////////////////////////////////////////////////
1370 static void VM_CL_makestatic (void)
1374 VM_SAFEPARMCOUNT(1, VM_CL_makestatic);
1376 ent = PRVM_G_EDICT(OFS_PARM0);
1377 if (ent == prog->edicts)
1379 VM_Warning("makestatic: can not modify world entity\n");
1382 if (ent->priv.server->free)
1384 VM_Warning("makestatic: can not modify free entity\n");
1388 if (cl.num_static_entities < cl.max_static_entities)
1392 entity_t *staticent = &cl.static_entities[cl.num_static_entities++];
1394 // copy it to the current state
1395 memset(staticent, 0, sizeof(*staticent));
1396 staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
1397 staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame;
1398 staticent->render.framelerp = 0;
1399 // make torchs play out of sync
1400 staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1);
1401 staticent->render.skinnum = (int)ent->fields.client->skin;
1402 staticent->render.effects = (int)ent->fields.client->effects;
1403 staticent->render.alpha = 1;
1404 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float;
1405 staticent->render.scale = 1;
1406 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float;
1407 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod);
1410 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float;
1411 if (renderflags & RF_USEAXIS)
1414 VectorNegate(prog->globals.client->v_right, left);
1415 Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin);
1416 Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1);
1419 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);
1421 // either fullbright or lit
1422 if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer)
1423 staticent->render.flags |= RENDER_LIGHT;
1424 // turn off shadows from transparent objects
1425 if (!(staticent->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (staticent->render.alpha >= 1))
1426 staticent->render.flags |= RENDER_SHADOW;
1428 CL_UpdateRenderEntity(&staticent->render);
1431 Con_Printf("Too many static entities");
1433 // throw the entity away now
1437 //=================================================================//
1443 copies data from one entity to another
1445 copyentity(src, dst)
1448 static void VM_CL_copyentity (void)
1450 prvm_edict_t *in, *out;
1451 VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
1452 in = PRVM_G_EDICT(OFS_PARM0);
1453 if (in == prog->edicts)
1455 VM_Warning("copyentity: can not read world entity\n");
1458 if (in->priv.server->free)
1460 VM_Warning("copyentity: can not read free entity\n");
1463 out = PRVM_G_EDICT(OFS_PARM1);
1464 if (out == prog->edicts)
1466 VM_Warning("copyentity: can not modify world entity\n");
1469 if (out->priv.server->free)
1471 VM_Warning("copyentity: can not modify free entity\n");
1474 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1478 //=================================================================//
1480 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1481 static void VM_CL_effect (void)
1483 VM_SAFEPARMCOUNT(5, VM_CL_effect);
1484 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));
1487 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1488 static void VM_CL_te_blood (void)
1492 VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1493 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1495 pos = PRVM_G_VECTOR(OFS_PARM0);
1496 CL_FindNonSolidLocation(pos, pos2, 4);
1497 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1500 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1501 static void VM_CL_te_bloodshower (void)
1505 VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1506 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1508 speed = PRVM_G_FLOAT(OFS_PARM2);
1515 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1518 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1519 static void VM_CL_te_explosionrgb (void)
1523 matrix4x4_t tempmatrix;
1524 VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1525 pos = PRVM_G_VECTOR(OFS_PARM0);
1526 CL_FindNonSolidLocation(pos, pos2, 10);
1527 CL_ParticleExplosion(pos2);
1528 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1529 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);
1532 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1533 static void VM_CL_te_particlecube (void)
1535 VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1536 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));
1539 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1540 static void VM_CL_te_particlerain (void)
1542 VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1543 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);
1546 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1547 static void VM_CL_te_particlesnow (void)
1549 VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1550 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);
1553 // #411 void(vector org, vector vel, float howmany) te_spark
1554 static void VM_CL_te_spark (void)
1558 VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1560 pos = PRVM_G_VECTOR(OFS_PARM0);
1561 CL_FindNonSolidLocation(pos, pos2, 4);
1562 CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1565 extern cvar_t cl_sound_ric_gunshot;
1566 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1567 static void VM_CL_te_gunshotquad (void)
1572 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1574 pos = PRVM_G_VECTOR(OFS_PARM0);
1575 CL_FindNonSolidLocation(pos, pos2, 4);
1576 CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1577 if(cl_sound_ric_gunshot.integer >= 2)
1579 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1583 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1584 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1585 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1590 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1591 static void VM_CL_te_spikequad (void)
1596 VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1598 pos = PRVM_G_VECTOR(OFS_PARM0);
1599 CL_FindNonSolidLocation(pos, pos2, 4);
1600 CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1601 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1605 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1606 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1607 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1611 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1612 static void VM_CL_te_superspikequad (void)
1617 VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1619 pos = PRVM_G_VECTOR(OFS_PARM0);
1620 CL_FindNonSolidLocation(pos, pos2, 4);
1621 CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1622 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1626 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1627 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1628 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1632 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1633 static void VM_CL_te_explosionquad (void)
1637 VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1639 pos = PRVM_G_VECTOR(OFS_PARM0);
1640 CL_FindNonSolidLocation(pos, pos2, 10);
1641 CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1642 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1645 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1646 static void VM_CL_te_smallflash (void)
1650 VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1652 pos = PRVM_G_VECTOR(OFS_PARM0);
1653 CL_FindNonSolidLocation(pos, pos2, 10);
1654 CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1657 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1658 static void VM_CL_te_customflash (void)
1662 matrix4x4_t tempmatrix;
1663 VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1665 pos = PRVM_G_VECTOR(OFS_PARM0);
1666 CL_FindNonSolidLocation(pos, pos2, 4);
1667 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1668 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);
1671 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1672 static void VM_CL_te_gunshot (void)
1677 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1679 pos = PRVM_G_VECTOR(OFS_PARM0);
1680 CL_FindNonSolidLocation(pos, pos2, 4);
1681 CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1682 if(cl_sound_ric_gunshot.integer == 1 || cl_sound_ric_gunshot.integer == 3)
1684 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1688 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1689 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1690 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1695 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1696 static void VM_CL_te_spike (void)
1701 VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1703 pos = PRVM_G_VECTOR(OFS_PARM0);
1704 CL_FindNonSolidLocation(pos, pos2, 4);
1705 CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1706 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1710 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1711 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1712 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1716 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1717 static void VM_CL_te_superspike (void)
1722 VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1724 pos = PRVM_G_VECTOR(OFS_PARM0);
1725 CL_FindNonSolidLocation(pos, pos2, 4);
1726 CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1727 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1731 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1732 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1733 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1737 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1738 static void VM_CL_te_explosion (void)
1742 VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1744 pos = PRVM_G_VECTOR(OFS_PARM0);
1745 CL_FindNonSolidLocation(pos, pos2, 10);
1746 CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1747 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1750 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1751 static void VM_CL_te_tarexplosion (void)
1755 VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1757 pos = PRVM_G_VECTOR(OFS_PARM0);
1758 CL_FindNonSolidLocation(pos, pos2, 10);
1759 CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1760 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1763 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1764 static void VM_CL_te_wizspike (void)
1768 VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1770 pos = PRVM_G_VECTOR(OFS_PARM0);
1771 CL_FindNonSolidLocation(pos, pos2, 4);
1772 CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1773 S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1776 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1777 static void VM_CL_te_knightspike (void)
1781 VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1783 pos = PRVM_G_VECTOR(OFS_PARM0);
1784 CL_FindNonSolidLocation(pos, pos2, 4);
1785 CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1786 S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1789 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1790 static void VM_CL_te_lavasplash (void)
1792 VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1793 CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1796 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1797 static void VM_CL_te_teleport (void)
1799 VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1800 CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1803 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1804 static void VM_CL_te_explosion2 (void)
1808 matrix4x4_t tempmatrix;
1809 int colorStart, colorLength;
1810 unsigned char *tempcolor;
1811 VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1813 pos = PRVM_G_VECTOR(OFS_PARM0);
1814 colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1815 colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1816 CL_FindNonSolidLocation(pos, pos2, 10);
1817 CL_ParticleExplosion2(pos2, colorStart, colorLength);
1818 tempcolor = palette_rgb[(rand()%colorLength) + colorStart];
1819 color[0] = tempcolor[0] * (2.0f / 255.0f);
1820 color[1] = tempcolor[1] * (2.0f / 255.0f);
1821 color[2] = tempcolor[2] * (2.0f / 255.0f);
1822 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1823 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);
1824 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1828 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1829 static void VM_CL_te_lightning1 (void)
1831 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1832 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1835 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1836 static void VM_CL_te_lightning2 (void)
1838 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1839 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1842 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1843 static void VM_CL_te_lightning3 (void)
1845 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1846 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1849 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1850 static void VM_CL_te_beam (void)
1852 VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1853 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1856 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1857 static void VM_CL_te_plasmaburn (void)
1861 VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1863 pos = PRVM_G_VECTOR(OFS_PARM0);
1864 CL_FindNonSolidLocation(pos, pos2, 4);
1865 CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1868 // #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
1869 static void VM_CL_te_flamejet (void)
1873 VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet);
1874 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1876 pos = PRVM_G_VECTOR(OFS_PARM0);
1877 CL_FindNonSolidLocation(pos, pos2, 4);
1878 CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1882 //====================================================================
1885 extern void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1887 static msurface_t *cl_getsurface(dp_model_t *model, int surfacenum)
1889 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1891 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1894 // #434 float(entity e, float s) getsurfacenumpoints
1895 static void VM_CL_getsurfacenumpoints(void)
1898 msurface_t *surface;
1899 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
1900 // return 0 if no such surface
1901 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1903 PRVM_G_FLOAT(OFS_RETURN) = 0;
1907 // note: this (incorrectly) assumes it is a simple polygon
1908 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1911 // #435 vector(entity e, float s, float n) getsurfacepoint
1912 static void VM_CL_getsurfacepoint(void)
1916 msurface_t *surface;
1918 VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
1919 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1920 ed = PRVM_G_EDICT(OFS_PARM0);
1921 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1923 // note: this (incorrectly) assumes it is a simple polygon
1924 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1925 if (pointnum < 0 || pointnum >= surface->num_vertices)
1927 // FIXME: implement rotation/scaling
1928 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1930 //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
1931 // float SPA_POSITION = 0;
1932 // float SPA_S_AXIS = 1;
1933 // float SPA_T_AXIS = 2;
1934 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
1935 // float SPA_TEXCOORDS0 = 4;
1936 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1937 // float SPA_LIGHTMAP0_COLOR = 6;
1938 // TODO: add some wrapper code and merge VM_CL/SV_getsurface* [12/16/2007 Black]
1939 static void VM_CL_getsurfacepointattribute(void)
1943 msurface_t *surface;
1947 VM_SAFEPARMCOUNT(4, VM_CL_getsurfacenumpoints);
1948 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1949 ed = PRVM_G_EDICT(OFS_PARM0);
1950 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1952 // note: this (incorrectly) assumes it is a simple polygon
1953 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1954 if (pointnum < 0 || pointnum >= surface->num_vertices)
1957 // FIXME: implement rotation/scaling
1958 attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
1960 switch( attributetype ) {
1961 // float SPA_POSITION = 0;
1963 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1965 // float SPA_S_AXIS = 1;
1967 VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1969 // float SPA_T_AXIS = 2;
1971 VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1973 // float SPA_R_AXIS = 3; // same as SPA_NORMAL
1975 VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
1977 // float SPA_TEXCOORDS0 = 4;
1979 float *ret = PRVM_G_VECTOR(OFS_RETURN);
1980 float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
1981 ret[0] = texcoord[0];
1982 ret[1] = texcoord[1];
1986 // float SPA_LIGHTMAP0_TEXCOORDS = 5;
1988 float *ret = PRVM_G_VECTOR(OFS_RETURN);
1989 float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
1990 ret[0] = texcoord[0];
1991 ret[1] = texcoord[1];
1995 // float SPA_LIGHTMAP0_COLOR = 6;
1997 // ignore alpha for now..
1998 VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
2001 VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
2005 // #436 vector(entity e, float s) getsurfacenormal
2006 static void VM_CL_getsurfacenormal(void)
2009 msurface_t *surface;
2011 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
2012 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2013 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2015 // FIXME: implement rotation/scaling
2016 // note: this (incorrectly) assumes it is a simple polygon
2017 // note: this only returns the first triangle, so it doesn't work very
2018 // well for curved surfaces or arbitrary meshes
2019 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);
2020 VectorNormalize(normal);
2021 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2024 // #437 string(entity e, float s) getsurfacetexture
2025 static void VM_CL_getsurfacetexture(void)
2028 msurface_t *surface;
2029 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
2030 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2031 if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2033 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2036 // #438 float(entity e, vector p) getsurfacenearpoint
2037 static void VM_CL_getsurfacenearpoint(void)
2039 int surfacenum, best;
2041 vec_t dist, bestdist;
2043 dp_model_t *model = NULL;
2044 msurface_t *surface;
2046 VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
2047 PRVM_G_FLOAT(OFS_RETURN) = -1;
2048 ed = PRVM_G_EDICT(OFS_PARM0);
2049 if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces)
2052 // FIXME: implement rotation/scaling
2053 point = PRVM_G_VECTOR(OFS_PARM1);
2054 VectorSubtract(point, ed->fields.client->origin, p);
2056 bestdist = 1000000000;
2057 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2059 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2060 // first see if the nearest point on the surface's box is closer than the previous match
2061 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2062 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2063 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2064 dist = VectorLength2(clipped);
2065 if (dist < bestdist)
2067 // it is, check the nearest point on the actual geometry
2068 clippointtosurface(model, surface, p, clipped);
2069 VectorSubtract(clipped, p, clipped);
2070 dist += VectorLength2(clipped);
2071 if (dist < bestdist)
2073 // that's closer too, store it as the best match
2079 PRVM_G_FLOAT(OFS_RETURN) = best;
2082 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
2083 static void VM_CL_getsurfaceclippedpoint(void)
2087 msurface_t *surface;
2089 VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
2090 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2091 ed = PRVM_G_EDICT(OFS_PARM0);
2092 if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2094 // FIXME: implement rotation/scaling
2095 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
2096 clippointtosurface(model, surface, p, out);
2097 // FIXME: implement rotation/scaling
2098 VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2101 // #443 void(entity e, entity tagentity, string tagname) setattachment
2102 void VM_CL_setattachment (void)
2105 prvm_edict_t *tagentity;
2106 const char *tagname;
2110 VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
2112 e = PRVM_G_EDICT(OFS_PARM0);
2113 tagentity = PRVM_G_EDICT(OFS_PARM1);
2114 tagname = PRVM_G_STRING(OFS_PARM2);
2116 if (e == prog->edicts)
2118 VM_Warning("setattachment: can not modify world entity\n");
2121 if (e->priv.server->free)
2123 VM_Warning("setattachment: can not modify free entity\n");
2127 if (tagentity == NULL)
2128 tagentity = prog->edicts;
2130 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2132 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2134 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2137 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2139 modelindex = (int)tagentity->fields.client->modelindex;
2140 model = CL_GetModelByIndex(modelindex);
2143 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
2145 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);
2148 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));
2152 /////////////////////////////////////////
2153 // DP_MD3_TAGINFO extension coded by VorteX
2155 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
2157 dp_model_t *model = CL_GetModelFromEdict(e);
2159 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
2164 // Warnings/errors code:
2165 // 0 - normal (everything all-right)
2168 // 3 - null or non-precached model
2169 // 4 - no tags with requested index
2170 // 5 - runaway loop at attachment chain
2171 extern cvar_t cl_bob;
2172 extern cvar_t cl_bobcycle;
2173 extern cvar_t cl_bobup;
2174 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2177 int reqframe, attachloop;
2178 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2179 prvm_edict_t *attachent;
2183 *out = identitymatrix; // warnings and errors return identical matrix
2185 if (ent == prog->edicts)
2187 if (ent->priv.server->free)
2190 model = CL_GetModelFromEdict(ent);
2195 if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2196 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2198 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2200 // get initial tag matrix
2203 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2208 tagmatrix = identitymatrix;
2210 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2211 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2215 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2216 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
2218 model = CL_GetModelFromEdict(attachent);
2220 if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2221 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
2223 attachmatrix = identitymatrix;
2225 // apply transformation by child entity matrix
2227 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2228 if (val && val->_float != 0)
2229 scale = val->_float;
2230 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);
2231 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2232 Matrix4x4_Copy(&tagmatrix, out);
2234 // finally transformate by matrix of tag on parent entity
2235 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2236 Matrix4x4_Copy(&tagmatrix, out);
2240 if (attachloop > 255) // prevent runaway looping
2243 while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
2246 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2248 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2249 if (val && val->_float != 0)
2250 scale = val->_float;
2251 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2252 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);
2253 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2255 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2256 {// RENDER_VIEWMODEL magic
2257 Matrix4x4_Copy(&tagmatrix, out);
2260 val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2261 if (val && val->_float != 0)
2262 scale = val->_float;
2264 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);
2265 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2268 // Cl_bob, ported from rendering code
2269 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2272 // LordHavoc: this code is *weird*, but not replacable (I think it
2273 // should be done in QC on the server, but oh well, quake is quake)
2274 // LordHavoc: figured out bobup: the time at which the sin is at 180
2275 // degrees (which allows lengthening or squishing the peak or valley)
2276 cycle = cl.time/cl_bobcycle.value;
2277 cycle -= (int)cycle;
2278 if (cycle < cl_bobup.value)
2279 cycle = sin(M_PI * cycle / cl_bobup.value);
2281 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2282 // bob is proportional to velocity in the xy plane
2283 // (don't count Z, or jumping messes it up)
2284 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;
2285 bob = bob*0.3 + bob*0.7*cycle;
2286 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2293 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2294 void VM_CL_gettagindex (void)
2297 const char *tag_name;
2298 int modelindex, tag_index;
2300 VM_SAFEPARMCOUNT(2, VM_CL_gettagindex);
2302 ent = PRVM_G_EDICT(OFS_PARM0);
2303 tag_name = PRVM_G_STRING(OFS_PARM1);
2304 if (ent == prog->edicts)
2306 VM_Warning("gettagindex: can't affect world entity\n");
2309 if (ent->priv.server->free)
2311 VM_Warning("gettagindex: can't affect free entity\n");
2315 modelindex = (int)ent->fields.client->modelindex;
2317 if (modelindex >= MAX_MODELS || (modelindex <= -MAX_MODELS /* client models */))
2318 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2321 tag_index = CL_GetTagIndex(ent, tag_name);
2323 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2325 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2328 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2329 void VM_CL_gettaginfo (void)
2333 matrix4x4_t tag_matrix;
2336 VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
2338 e = PRVM_G_EDICT(OFS_PARM0);
2339 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2340 returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2341 Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2346 VM_Warning("gettagindex: can't affect world entity\n");
2349 VM_Warning("gettagindex: can't affect free entity\n");
2352 Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2355 Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2358 Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2363 //============================================================================
2365 //====================
2366 //QC POLYGON functions
2367 //====================
2369 #define VMPOLYGONS_MAXPOINTS 64
2371 typedef struct vmpolygons_triangle_s
2373 rtexture_t *texture;
2375 unsigned short elements[3];
2376 }vmpolygons_triangle_t;
2378 typedef struct vmpolygons_s
2381 qboolean initialized;
2382 double progstarttime;
2386 float *data_vertex3f;
2387 float *data_color4f;
2388 float *data_texcoord2f;
2392 vmpolygons_triangle_t *data_triangles;
2393 unsigned short *data_sortedelement3s;
2395 qboolean begin_active;
2396 rtexture_t *begin_texture;
2399 float begin_vertex[VMPOLYGONS_MAXPOINTS][3];
2400 float begin_color[VMPOLYGONS_MAXPOINTS][4];
2401 float begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
2404 // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
2405 vmpolygons_t vmpolygons[PRVM_MAXPROGS];
2407 //#304 void() renderscene (EXT_CSQC)
2408 // moved that here to reset the polygons,
2409 // resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0
2411 void VM_CL_R_RenderScene (void)
2413 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2414 VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
2415 // we need to update any RENDER_VIEWMODEL entities at this point because
2416 // csqc supplies its own view matrix
2417 CL_UpdateViewEntities();
2421 polys->num_vertices = polys->num_triangles = 0;
2422 polys->progstarttime = prog->starttime;
2425 static void VM_ResizePolygons(vmpolygons_t *polys)
2427 float *oldvertex3f = polys->data_vertex3f;
2428 float *oldcolor4f = polys->data_color4f;
2429 float *oldtexcoord2f = polys->data_texcoord2f;
2430 vmpolygons_triangle_t *oldtriangles = polys->data_triangles;
2431 unsigned short *oldsortedelement3s = polys->data_sortedelement3s;
2432 polys->max_vertices = min(polys->max_triangles*3, 65536);
2433 polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3]));
2434 polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4]));
2435 polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2]));
2436 polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t));
2437 polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3]));
2438 if (polys->num_vertices)
2440 memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3]));
2441 memcpy(polys->data_color4f, oldcolor4f, polys->num_vertices*sizeof(float[4]));
2442 memcpy(polys->data_texcoord2f, oldtexcoord2f, polys->num_vertices*sizeof(float[2]));
2444 if (polys->num_triangles)
2446 memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t));
2447 memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3]));
2450 Mem_Free(oldvertex3f);
2452 Mem_Free(oldcolor4f);
2454 Mem_Free(oldtexcoord2f);
2456 Mem_Free(oldtriangles);
2457 if (oldsortedelement3s)
2458 Mem_Free(oldsortedelement3s);
2461 static void VM_InitPolygons (vmpolygons_t* polys)
2463 memset(polys, 0, sizeof(*polys));
2464 polys->pool = Mem_AllocPool("VMPOLY", 0, NULL);
2465 polys->max_triangles = 1024;
2466 VM_ResizePolygons(polys);
2467 polys->initialized = true;
2470 static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2472 int surfacelistindex;
2473 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2474 if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
2476 R_Mesh_ResetTextureState();
2477 R_Mesh_Matrix(&identitymatrix);
2478 GL_CullFace(GL_NONE);
2479 R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0);
2480 R_Mesh_ColorPointer(polys->data_color4f, 0, 0);
2481 R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0);
2482 R_SetupGenericShader(true);
2484 for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
2486 int numtriangles = 0;
2487 rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
2488 int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
2489 // this can't call _DrawQ_ProcessDrawFlag, but should be in sync with it
2490 // FIXME factor this out
2491 if(drawflag == DRAWFLAG_ADDITIVE)
2492 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2493 else if(drawflag == DRAWFLAG_MODULATE)
2494 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
2495 else if(drawflag == DRAWFLAG_2XMODULATE)
2496 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
2497 else if(drawflag == DRAWFLAG_SCREEN)
2498 GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
2500 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2501 R_Mesh_TexBind(0, R_GetTexture(tex));
2503 for (;surfacelistindex < numsurfaces;surfacelistindex++)
2505 if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag)
2507 VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles);
2510 R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0);
2514 void VMPolygons_Store(vmpolygons_t *polys)
2516 if (r_refdef.draw2dstage)
2518 // draw the polygon as 2D immediately
2519 drawqueuemesh_t mesh;
2520 mesh.texture = polys->begin_texture;
2521 mesh.num_vertices = polys->begin_vertices;
2522 mesh.num_triangles = polys->begin_vertices-2;
2523 mesh.data_element3s = polygonelements;
2524 mesh.data_vertex3f = polys->begin_vertex[0];
2525 mesh.data_color4f = polys->begin_color[0];
2526 mesh.data_texcoord2f = polys->begin_texcoord[0];
2527 DrawQ_Mesh(&mesh, polys->begin_drawflag);
2531 // queue the polygon as 3D for sorted transparent rendering later
2533 if (polys->max_triangles < polys->num_triangles + polys->begin_vertices-2)
2535 polys->max_triangles *= 2;
2536 VM_ResizePolygons(polys);
2538 if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices)
2540 // needle in a haystack!
2541 // polys->num_vertices was used for copying where we actually want to copy begin_vertices
2542 // that also caused it to not render the first polygon that is added
2544 memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3]));
2545 memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4]));
2546 memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2]));
2547 for (i = 0;i < polys->begin_vertices-2;i++)
2549 polys->data_triangles[polys->num_triangles].texture = polys->begin_texture;
2550 polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag;
2551 polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices;
2552 polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1;
2553 polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2;
2554 polys->num_triangles++;
2556 polys->num_vertices += polys->begin_vertices;
2559 polys->begin_active = false;
2562 // TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black]
2563 // LordHavoc: agreed, this is a mess
2564 void VM_CL_AddPolygonsToMeshQueue (void)
2567 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2570 // only add polygons of the currently active prog to the queue - if there is none, we're done
2574 if (!polys->num_triangles)
2577 for (i = 0;i < polys->num_triangles;i++)
2579 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);
2580 R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
2583 /*polys->num_triangles = 0; // now done after rendering the scene,
2584 polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */
2587 //void(string texturename, float flag) R_BeginPolygon
2588 void VM_CL_R_PolygonBegin (void)
2590 const char *picname;
2592 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2595 // TODO instead of using skinframes here (which provides the benefit of
2596 // better management of flags, and is more suited for 3D rendering), what
2597 // about supporting Q3 shaders?
2599 VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin);
2601 if (!polys->initialized)
2602 VM_InitPolygons(polys);
2603 if(polys->progstarttime != prog->starttime)
2605 // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid)
2606 polys->num_vertices = polys->num_triangles = 0;
2607 polys->progstarttime = prog->starttime;
2609 if (polys->begin_active)
2611 VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
2614 picname = PRVM_G_STRING(OFS_PARM0);
2620 if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP)
2625 sf = R_SkinFrame_FindNextByName(sf, picname);
2627 while(sf && sf->textureflags != tf);
2629 if(!sf || !sf->base)
2630 sf = R_SkinFrame_LoadExternal(picname, tf, true);
2633 R_SkinFrame_MarkUsed(sf);
2636 polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white;
2637 polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK;
2638 polys->begin_vertices = 0;
2639 polys->begin_active = true;
2642 //void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2643 void VM_CL_R_PolygonVertex (void)
2645 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2647 VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
2649 if (!polys->begin_active)
2651 VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
2655 if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS)
2657 VM_Warning("VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
2661 polys->begin_vertex[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM0)[0];
2662 polys->begin_vertex[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM0)[1];
2663 polys->begin_vertex[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM0)[2];
2664 polys->begin_texcoord[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM1)[0];
2665 polys->begin_texcoord[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM1)[1];
2666 polys->begin_color[polys->begin_vertices][0] = PRVM_G_VECTOR(OFS_PARM2)[0];
2667 polys->begin_color[polys->begin_vertices][1] = PRVM_G_VECTOR(OFS_PARM2)[1];
2668 polys->begin_color[polys->begin_vertices][2] = PRVM_G_VECTOR(OFS_PARM2)[2];
2669 polys->begin_color[polys->begin_vertices][3] = PRVM_G_FLOAT(OFS_PARM3);
2670 polys->begin_vertices++;
2673 //void() R_EndPolygon
2674 void VM_CL_R_PolygonEnd (void)
2676 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
2678 VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
2679 if (!polys->begin_active)
2681 VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
2684 polys->begin_active = false;
2685 if (polys->begin_vertices >= 3)
2686 VMPolygons_Store(polys);
2688 VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices);
2691 static vmpolygons_t debugPolys;
2693 void Debug_PolygonBegin(const char *picname, int drawflag)
2695 if(!debugPolys.initialized)
2696 VM_InitPolygons(&debugPolys);
2697 if(debugPolys.begin_active)
2699 Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
2702 debugPolys.begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
2703 debugPolys.begin_drawflag = drawflag;
2704 debugPolys.begin_vertices = 0;
2705 debugPolys.begin_active = true;
2708 void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a)
2710 if(!debugPolys.begin_active)
2712 Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
2716 if(debugPolys.begin_vertices > VMPOLYGONS_MAXPOINTS)
2718 Con_Printf("Debug_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
2722 debugPolys.begin_vertex[debugPolys.begin_vertices][0] = x;
2723 debugPolys.begin_vertex[debugPolys.begin_vertices][1] = y;
2724 debugPolys.begin_vertex[debugPolys.begin_vertices][2] = z;
2725 debugPolys.begin_texcoord[debugPolys.begin_vertices][0] = s;
2726 debugPolys.begin_texcoord[debugPolys.begin_vertices][1] = t;
2727 debugPolys.begin_color[debugPolys.begin_vertices][0] = r;
2728 debugPolys.begin_color[debugPolys.begin_vertices][1] = g;
2729 debugPolys.begin_color[debugPolys.begin_vertices][2] = b;
2730 debugPolys.begin_color[debugPolys.begin_vertices][3] = a;
2731 debugPolys.begin_vertices++;
2734 void Debug_PolygonEnd(void)
2736 if (!debugPolys.begin_active)
2738 Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
2741 debugPolys.begin_active = false;
2742 if (debugPolys.begin_vertices >= 3)
2743 VMPolygons_Store(&debugPolys);
2745 Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.begin_vertices);
2752 Returns false if any part of the bottom of the entity is off an edge that
2757 qboolean CL_CheckBottom (prvm_edict_t *ent)
2759 vec3_t mins, maxs, start, stop;
2764 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
2765 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
2767 // if all of the points under the corners are solid world, don't bother
2768 // with the tougher checks
2769 // the corners must be within 16 of the midpoint
2770 start[2] = mins[2] - 1;
2771 for (x=0 ; x<=1 ; x++)
2772 for (y=0 ; y<=1 ; y++)
2774 start[0] = x ? maxs[0] : mins[0];
2775 start[1] = y ? maxs[1] : mins[1];
2776 if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
2780 return true; // we got out easy
2784 // check it for real...
2788 // the midpoint must be within 16 of the bottom
2789 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
2790 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
2791 stop[2] = start[2] - 2*sv_stepheight.value;
2792 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2794 if (trace.fraction == 1.0)
2796 mid = bottom = trace.endpos[2];
2798 // the corners must be within 16 of the midpoint
2799 for (x=0 ; x<=1 ; x++)
2800 for (y=0 ; y<=1 ; y++)
2802 start[0] = stop[0] = x ? maxs[0] : mins[0];
2803 start[1] = stop[1] = y ? maxs[1] : mins[1];
2805 trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2807 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
2808 bottom = trace.endpos[2];
2809 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
2820 Called by monster program code.
2821 The move will be adjusted for slopes and stairs, but if the move isn't
2822 possible, no move is done and false is returned
2825 qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
2828 vec3_t oldorg, neworg, end, traceendpos;
2831 prvm_edict_t *enemy;
2835 VectorCopy (ent->fields.client->origin, oldorg);
2836 VectorAdd (ent->fields.client->origin, move, neworg);
2838 // flying monsters don't step up
2839 if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) )
2841 // try one move with vertical motion, then one without
2842 for (i=0 ; i<2 ; i++)
2844 VectorAdd (ent->fields.client->origin, move, neworg);
2845 enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy);
2846 if (i == 0 && enemy != prog->edicts)
2848 dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2];
2854 trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2856 VM_SetTraceGlobals(&trace);
2858 if (trace.fraction == 1)
2860 VectorCopy(trace.endpos, traceendpos);
2861 if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
2862 return false; // swim monster left water
2864 VectorCopy (traceendpos, ent->fields.client->origin);
2870 if (enemy == prog->edicts)
2877 // push down from a step height above the wished position
2878 neworg[2] += sv_stepheight.value;
2879 VectorCopy (neworg, end);
2880 end[2] -= sv_stepheight.value*2;
2882 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2884 VM_SetTraceGlobals(&trace);
2886 if (trace.startsolid)
2888 neworg[2] -= sv_stepheight.value;
2889 trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
2891 VM_SetTraceGlobals(&trace);
2892 if (trace.startsolid)
2895 if (trace.fraction == 1)
2897 // if monster had the ground pulled out, go ahead and fall
2898 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2900 VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin);
2903 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND;
2907 return false; // walked off an edge
2910 // check point traces down for dangling corners
2911 VectorCopy (trace.endpos, ent->fields.client->origin);
2913 if (!CL_CheckBottom (ent))
2915 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2916 { // entity had floor mostly pulled out from underneath it
2917 // and is trying to correct
2922 VectorCopy (oldorg, ent->fields.client->origin);
2926 if ( (int)ent->fields.client->flags & FL_PARTIALGROUND )
2927 ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND;
2929 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity)))
2930 val->edict = PRVM_EDICT_TO_PROG(trace.ent);
2942 float(float yaw, float dist[, settrace]) walkmove
2945 static void VM_CL_walkmove (void)
2954 VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove);
2956 // assume failure if it returns early
2957 PRVM_G_FLOAT(OFS_RETURN) = 0;
2959 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
2960 if (ent == prog->edicts)
2962 VM_Warning("walkmove: can not modify world entity\n");
2965 if (ent->priv.server->free)
2967 VM_Warning("walkmove: can not modify free entity\n");
2970 yaw = PRVM_G_FLOAT(OFS_PARM0);
2971 dist = PRVM_G_FLOAT(OFS_PARM1);
2972 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
2974 if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
2977 yaw = yaw*M_PI*2 / 360;
2979 move[0] = cos(yaw)*dist;
2980 move[1] = sin(yaw)*dist;
2983 // save program state, because CL_movestep may call other progs
2984 oldf = prog->xfunction;
2985 oldself = prog->globals.client->self;
2987 PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace);
2990 // restore program state
2991 prog->xfunction = oldf;
2992 prog->globals.client->self = oldself;
2999 string(string key) serverkey
3002 void VM_CL_serverkey(void)
3004 char string[VM_STRINGTEMP_LENGTH];
3005 VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
3006 InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
3007 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
3010 //============================================================================
3012 // To create a almost working builtin file from this replace:
3013 // "^NULL.*" with ""
3014 // "^{.*//.*}:Wh\(.*\)" with "\1"
3016 // "^.*//:Wh{\#:d*}:Wh{.*}" with "\2 = \1;"
3017 // "\n\n+" with "\n\n"
3019 prvm_builtin_t vm_cl_builtins[] = {
3020 NULL, // #0 NULL function (not callable) (QUAKE)
3021 VM_CL_makevectors, // #1 void(vector ang) makevectors (QUAKE)
3022 VM_CL_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
3023 VM_CL_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
3024 VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3025 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3026 VM_break, // #6 void() break (QUAKE)
3027 VM_random, // #7 float() random (QUAKE)
3028 VM_CL_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
3029 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
3030 VM_error, // #10 void(string e) error (QUAKE)
3031 VM_objerror, // #11 void(string e) objerror (QUAKE)
3032 VM_vlen, // #12 float(vector v) vlen (QUAKE)
3033 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
3034 VM_CL_spawn, // #14 entity() spawn (QUAKE)
3035 VM_remove, // #15 void(entity e) remove (QUAKE)
3036 VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents, entity ignoreentity) traceline (QUAKE)
3037 NULL, // #17 entity() checkclient (QUAKE)
3038 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
3039 VM_precache_sound, // #19 void(string s) precache_sound (QUAKE)
3040 VM_CL_precache_model, // #20 void(string s) precache_model (QUAKE)
3041 NULL, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3042 VM_CL_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
3043 NULL, // #23 void(string s, ...) bprint (QUAKE)
3044 NULL, // #24 void(entity client, string s, ...) sprint (QUAKE)
3045 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
3046 VM_ftos, // #26 string(float f) ftos (QUAKE)
3047 VM_vtos, // #27 string(vector v) vtos (QUAKE)
3048 VM_coredump, // #28 void() coredump (QUAKE)
3049 VM_traceon, // #29 void() traceon (QUAKE)
3050 VM_traceoff, // #30 void() traceoff (QUAKE)
3051 VM_eprint, // #31 void(entity e) eprint (QUAKE)
3052 VM_CL_walkmove, // #32 float(float yaw, float dist[, float settrace]) walkmove (QUAKE)
3053 NULL, // #33 (QUAKE)
3054 VM_CL_droptofloor, // #34 float() droptofloor (QUAKE)
3055 VM_CL_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
3056 VM_rint, // #36 float(float v) rint (QUAKE)
3057 VM_floor, // #37 float(float v) floor (QUAKE)
3058 VM_ceil, // #38 float(float v) ceil (QUAKE)
3059 NULL, // #39 (QUAKE)
3060 VM_CL_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
3061 VM_CL_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
3062 NULL, // #42 (QUAKE)
3063 VM_fabs, // #43 float(float f) fabs (QUAKE)
3064 NULL, // #44 vector(entity e, float speed) aim (QUAKE)
3065 VM_cvar, // #45 float(string s) cvar (QUAKE)
3066 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
3067 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
3068 VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3069 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
3070 NULL, // #50 (QUAKE)
3071 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
3072 NULL, // #52 void(float to, float f) WriteByte (QUAKE)
3073 NULL, // #53 void(float to, float f) WriteChar (QUAKE)
3074 NULL, // #54 void(float to, float f) WriteShort (QUAKE)
3075 NULL, // #55 void(float to, float f) WriteLong (QUAKE)
3076 NULL, // #56 void(float to, float f) WriteCoord (QUAKE)
3077 NULL, // #57 void(float to, float f) WriteAngle (QUAKE)
3078 NULL, // #58 void(float to, string s) WriteString (QUAKE)
3079 NULL, // #59 (QUAKE)
3080 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3081 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3082 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3083 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3084 VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3085 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3086 NULL, // #66 (QUAKE)
3087 NULL, // #67 void(float step) movetogoal (QUAKE)
3088 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
3089 VM_CL_makestatic, // #69 void(entity e) makestatic (QUAKE)
3090 NULL, // #70 void(string s) changelevel (QUAKE)
3091 NULL, // #71 (QUAKE)
3092 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
3093 NULL, // #73 void(entity client, strings) centerprint (QUAKE)
3094 VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3095 VM_CL_precache_model, // #75 string(string s) precache_model2 (QUAKE)
3096 VM_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
3097 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
3098 NULL, // #78 void(entity e) setspawnparms (QUAKE)
3099 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3100 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3101 VM_stof, // #81 float(string s) stof (FRIK_FILE)
3102 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
3103 NULL, // #83 (QUAKE)
3104 NULL, // #84 (QUAKE)
3105 NULL, // #85 (QUAKE)
3106 NULL, // #86 (QUAKE)
3107 NULL, // #87 (QUAKE)
3108 NULL, // #88 (QUAKE)
3109 NULL, // #89 (QUAKE)
3110 VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3111 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3112 VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3113 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3114 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3115 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3116 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3117 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3118 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3119 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3120 // FrikaC and Telejano range #100-#199
3131 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3132 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3133 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3134 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3135 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
3136 VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3137 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3138 VM_stov, // #117 vector(string) stov (FRIK_FILE)
3139 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
3140 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3221 // FTEQW range #200-#299
3240 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3243 VM_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3244 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3245 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
3246 VM_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3247 VM_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3248 VM_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3249 VM_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
3250 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3251 VM_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3252 VM_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3254 NULL, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3322 // CSQC range #300-#399
3323 VM_CL_R_ClearScene, // #300 void() clearscene (EXT_CSQC)
3324 VM_CL_R_AddEntities, // #301 void(float mask) addentities (EXT_CSQC)
3325 VM_CL_R_AddEntity, // #302 void(entity ent) addentity (EXT_CSQC)
3326 VM_CL_R_SetView, // #303 float(float property, ...) setproperty (EXT_CSQC)
3327 VM_CL_R_RenderScene, // #304 void() renderscene (EXT_CSQC)
3328 VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3329 VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3330 VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3331 VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
3332 NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
3333 VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC)
3334 VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC)
3338 VM_drawline, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3339 VM_iscachedpic, // #316 float(string name) iscachedpic (EXT_CSQC)
3340 VM_precache_pic, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3341 VM_getimagesize, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3342 VM_freepic, // #319 void(string name) freepic (EXT_CSQC)
3343 VM_drawcharacter, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3344 VM_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3345 VM_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3346 VM_drawfill, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3347 VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea
3348 VM_drawresetcliparea, // #325 void(void) drawresetcliparea
3349 VM_drawcolorcodedstring, // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
3350 VM_stringwidth, // #327 // FIXME is this okay?
3351 VM_drawsubpic, // #328 // FIXME is this okay?
3353 VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC)
3354 VM_CL_getstati, // #331 float(float stnum) getstati (EXT_CSQC)
3355 VM_CL_getstats, // #332 string(float firststnum) getstats (EXT_CSQC)
3356 VM_CL_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3357 VM_CL_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3358 VM_CL_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3359 VM_CL_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3360 VM_CL_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3361 VM_centerprint, // #338 void(string s, ...) centerprint (EXT_CSQC)
3362 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3363 VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3364 VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3365 VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
3366 VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3367 VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
3368 VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC)
3369 VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscale (EXT_CSQC)
3370 VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC)
3371 VM_CL_getplayerkey, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3372 VM_CL_isdemo, // #349 float() isdemo (EXT_CSQC)
3373 VM_isserver, // #350 float() isserver (EXT_CSQC)
3374 VM_CL_setlistener, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3375 VM_CL_registercmd, // #352 void(string cmdname) registercommand (EXT_CSQC)
3376 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3377 VM_CL_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3383 VM_CL_ReadByte, // #360 float() readbyte (EXT_CSQC)
3384 VM_CL_ReadChar, // #361 float() readchar (EXT_CSQC)
3385 VM_CL_ReadShort, // #362 float() readshort (EXT_CSQC)
3386 VM_CL_ReadLong, // #363 float() readlong (EXT_CSQC)
3387 VM_CL_ReadCoord, // #364 float() readcoord (EXT_CSQC)
3388 VM_CL_ReadAngle, // #365 float() readangle (EXT_CSQC)
3389 VM_CL_ReadString, // #366 string() readstring (EXT_CSQC)
3390 VM_CL_ReadFloat, // #367 float() readfloat (EXT_CSQC)
3423 // LordHavoc's range #400-#499
3424 VM_CL_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3425 NULL, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3426 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3427 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3428 VM_CL_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3429 VM_CL_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3430 VM_CL_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3431 VM_CL_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3432 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)
3433 VM_CL_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3434 VM_CL_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3435 VM_CL_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3436 VM_CL_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3437 VM_CL_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3438 VM_CL_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3439 VM_CL_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3440 VM_CL_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3441 VM_CL_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3442 VM_CL_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3443 VM_CL_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3444 VM_CL_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3445 VM_CL_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3446 VM_CL_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3447 VM_CL_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3448 VM_CL_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3449 VM_CL_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3450 VM_CL_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3451 VM_CL_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3452 VM_CL_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3453 VM_CL_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3454 VM_CL_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3455 VM_CL_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3456 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3457 VM_CL_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3458 VM_CL_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3459 VM_CL_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3460 VM_CL_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3461 VM_CL_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3462 VM_CL_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3463 VM_CL_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3464 NULL, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3465 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3466 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3467 VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3468 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3469 VM_search_end, // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3470 VM_search_getsize, // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3471 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3472 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3473 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3474 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3475 VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3476 VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3477 NULL, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3478 NULL, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3479 NULL, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3480 NULL, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3481 VM_CL_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet (DP_TE_FLAMEJET)
3483 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3484 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3485 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3486 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3487 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3488 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3489 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3490 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3491 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3492 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3493 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3494 NULL, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3495 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3496 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3497 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3498 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3499 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3500 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3501 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
3502 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3503 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3504 VM_strtolower, // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3505 VM_strtoupper, // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3506 VM_cvar_defstring, // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3507 VM_CL_pointsound, // #483 void(vector origin, string sample, float volume, float attenuation) pointsound (DP_SV_POINTSOUND)
3508 VM_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3509 VM_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3510 VM_CL_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute
3511 VM_gecko_create, // #487 float gecko_create( string name )
3512 VM_gecko_destroy, // #488 void gecko_destroy( string name )
3513 VM_gecko_navigate, // #489 void gecko_navigate( string name, string URI )
3514 VM_gecko_keyevent, // #490 float gecko_keyevent( string name, float key, float eventtype )
3515 VM_gecko_movemouse, // #491 void gecko_mousemove( string name, float x, float y )
3516 VM_gecko_resize, // #492 void gecko_resize( string name, float w, float h )
3517 VM_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name )
3518 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3519 VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3520 VM_numentityfields, // #496 float() numentityfields = #496; (QP_QC_ENTITYDATA)
3521 VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3522 VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3523 VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3524 VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3525 VM_CL_ReadPicture, // #501 string() ReadPicture = #501;
3527 VM_whichpack, // #503 string(string) whichpack = #503;
3534 VM_uri_escape, // #510 string(string in) uri_escape = #510;
3535 VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
3536 VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3537 VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET)
3544 VM_keynumtostring, // #520 string keynumtostring(float keynum)
3545 VM_findkeysforcommand, // #521 string findkeysforcommand(string command)
3548 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
3550 void VM_Polygons_Reset(void)
3552 vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
3554 // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
3555 if(polys->initialized)
3557 Mem_FreePool(&polys->pool);
3558 polys->initialized = false;
3562 void VM_CL_Cmd_Init(void)
3565 VM_Polygons_Reset();
3568 void VM_CL_Cmd_Reset(void)
3571 VM_Polygons_Reset();