3 #include "cl_collision.h"
5 //============================================================================
7 //[515]: unsolved PROBLEMS
8 //- finish player physics code (cs_runplayerphysics)
9 //- fix R_AddDynamicLight
11 //- RF_DEPTHHACK is not like it should be
12 //- add builtin that sets cl.viewangles instead of reading "input_angles" global
13 //- finish lines support for R_Polygon***
14 //- insert selecttraceline into traceline somehow
16 //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
17 //4 feature darkplaces csqc: add builtins to clientside qc for gl calls
19 //[515]: really need new list ?
20 char *vm_cl_extensions =
34 "DP_ENT_CUSTOMCOLORMAP "
37 "DP_GFX_EXTERNALTEXTURES "
38 "DP_GFX_EXTERNALTEXTURES_PERMAP "
40 "DP_GFX_QUAKE3MODELTAGS "
44 "DP_HALFLIFE_MAP_CVAR "
50 "DP_MOVETYPEBOUNCEMISSILE "
57 "DP_QC_FINDCHAINFLAGS "
58 "DP_QC_FINDCHAINFLOAT "
61 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
66 "DP_QC_MULTIPLETEMPSTRINGS "
68 "DP_QC_SINCOSSQRTPOW "
69 //"DP_QC_STRINGBUFFERS " //[515]: not needed ?
72 "DP_QC_TRACE_MOVETYPE_HITMODEL "
73 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
74 "DP_QC_VECTORVECTORS "
80 "DP_SND_DIRECTIONLESSATTNNONE "
87 "DP_SV_ROTATINGBMODEL "
101 "DP_TE_STANDARDEFFECTBUILTINS "
105 "KRIMZON_SV_PARSECLIENTCOMMAND "
108 "PRYDON_CLIENTCURSOR "
109 "TENEBRAE_GFX_DLIGHTS "
111 "NEXUIZ_PLAYERMODEL "
115 sfx_t *S_FindName(const char *name);
116 void PF_registercvar (void);
117 int Sbar_GetPlayer (int index);
118 void Sbar_SortFrags (void);
119 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
120 void CL_ExpandCSQCEntities(int num);
121 void CSQC_RelinkAllEntities (int drawmask);
122 void CSQC_RelinkCSQCEntities (void);
123 char *Key_GetBind (int key);
129 // #1 void(vector ang) makevectors
130 void VM_CL_makevectors (void)
132 VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
133 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
136 // #2 void(entity e, vector o) setorigin
137 void VM_CL_setorigin (void)
142 e = PRVM_G_EDICT(OFS_PARM0);
143 if (e == prog->edicts)
145 VM_Warning("setorigin: can not modify world entity\n");
148 if (e->priv.required->free)
150 VM_Warning("setorigin: can not modify free entity\n");
153 org = PRVM_G_VECTOR(OFS_PARM1);
154 VectorCopy (org, e->fields.client->origin);
157 // #3 void(entity e, string m) setmodel
158 void VM_CL_setmodel (void)
165 VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
167 e = PRVM_G_EDICT(OFS_PARM0);
168 m = PRVM_G_STRING(OFS_PARM1);
169 for(i=0;i<MAX_MODELS;i++)
170 if(!cl.csqc_model_precache[i])
173 if(!strcmp(cl.csqc_model_precache[i]->name, m))
175 e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
176 e->fields.client->modelindex = -(i+1);
180 for (i=0, mod = cl.model_precache[0] ; i < MAX_MODELS ; i++, mod = cl.model_precache[i])
182 if(!strcmp(mod->name, m))
184 e->fields.client->model = PRVM_SetEngineString(mod->name);
185 e->fields.client->modelindex = i;
188 e->fields.client->modelindex = 0;
189 e->fields.client->model = 0;
192 // #4 void(entity e, vector min, vector max) setsize
193 void VM_CL_setsize (void)
197 VM_SAFEPARMCOUNT(3, VM_CL_setsize);
199 e = PRVM_G_EDICT(OFS_PARM0);
200 if (e == prog->edicts)
202 VM_Warning("setsize: can not modify world entity\n");
205 if (e->priv.server->free)
207 VM_Warning("setsize: can not modify free entity\n");
210 min = PRVM_G_VECTOR(OFS_PARM1);
211 max = PRVM_G_VECTOR(OFS_PARM2);
213 VectorCopy (min, e->fields.client->mins);
214 VectorCopy (max, e->fields.client->maxs);
215 VectorSubtract (max, min, e->fields.client->size);
218 // #8 void(entity e, float chan, string samp) sound
219 void VM_CL_sound (void)
223 prvm_edict_t *entity;
227 VM_SAFEPARMCOUNT(5, VM_CL_sound);
229 entity = PRVM_G_EDICT(OFS_PARM0);
230 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
231 sample = PRVM_G_STRING(OFS_PARM2);
232 volume = (int)(PRVM_G_FLOAT(OFS_PARM3)*255.0f);
233 attenuation = PRVM_G_FLOAT(OFS_PARM4);
235 if (volume < 0 || volume > 255)
237 VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
241 if (attenuation < 0 || attenuation > 4)
243 VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
247 if (channel < 0 || channel > 7)
249 VM_Warning("VM_CL_sound: channel must be in range 0-7\n");
253 S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
256 // #14 entity() spawn
257 void VM_CL_spawn (void)
260 ed = PRVM_ED_Alloc();
261 ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed); //[515]: not needed any more ?
265 // #16 float(vector v1, vector v2, float tryents) traceline
266 void VM_CL_traceline (void)
272 v1 = PRVM_G_VECTOR(OFS_PARM0);
273 v2 = PRVM_G_VECTOR(OFS_PARM1);
275 trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false);
277 prog->globals.client->trace_allsolid = trace.allsolid;
278 prog->globals.client->trace_startsolid = trace.startsolid;
279 prog->globals.client->trace_fraction = trace.fraction;
280 prog->globals.client->trace_inwater = trace.inwater;
281 prog->globals.client->trace_inopen = trace.inopen;
282 VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
283 VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
284 prog->globals.client->trace_plane_dist = trace.plane.dist;
286 prog->globals.client->trace_ent = ent;
288 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
291 // #19 void(string s) precache_sound
292 void VM_CL_precache_sound (void)
295 VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
296 n = PRVM_G_STRING(OFS_PARM0);
297 S_PrecacheSound(n, true, false);
300 // #20 void(string s) precache_model
301 void VM_CL_precache_model (void)
307 VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
309 name = PRVM_G_STRING(OFS_PARM0);
310 for(i=1;i<MAX_MODELS;i++)
311 if(!cl.csqc_model_precache[i])
317 if(!strcmp(cl.csqc_model_precache[i]->name, name))
324 PRVM_G_FLOAT(OFS_RETURN) = i;
327 PRVM_G_FLOAT(OFS_RETURN) = 0;
328 m = Mod_ForName(name, false, false, false);
331 for(i=1;i<MAX_MODELS;i++)
332 if(!cl.csqc_model_precache[i])
336 VM_Warning("VM_CL_precache_model: no free models\n");
339 cl.csqc_model_precache[i] = (model_t*)m;
340 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
343 VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
346 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
351 ent = PRVM_NEXT_EDICT(prog->edicts);
352 for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
354 if (ent->priv.required->free)
356 // VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
357 // VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
358 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
364 // #22 entity(vector org, float rad) findradius
365 void VM_CL_findradius (void)
367 prvm_edict_t *ent, *chain;
368 vec_t radius, radius2;
369 vec3_t org, eorg, mins, maxs;
370 int i, numtouchedicts;
371 prvm_edict_t *touchedicts[MAX_EDICTS];
373 chain = (prvm_edict_t *)prog->edicts;
375 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
376 radius = PRVM_G_FLOAT(OFS_PARM1);
377 radius2 = radius * radius;
379 mins[0] = org[0] - (radius + 1);
380 mins[1] = org[1] - (radius + 1);
381 mins[2] = org[2] - (radius + 1);
382 maxs[0] = org[0] + (radius + 1);
383 maxs[1] = org[1] + (radius + 1);
384 maxs[2] = org[2] + (radius + 1);
385 numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
386 if (numtouchedicts > MAX_EDICTS)
388 // this never happens //[515]: for what then ?
389 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
390 numtouchedicts = MAX_EDICTS;
392 for (i = 0;i < numtouchedicts;i++)
394 ent = touchedicts[i];
395 // Quake did not return non-solid entities but darkplaces does
396 // (note: this is the reason you can't blow up fallen zombies)
397 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
399 // LordHavoc: compare against bounding box rather than center so it
400 // doesn't miss large objects, and use DotProduct instead of Length
401 // for a major speedup
402 VectorSubtract(org, ent->fields.client->origin, eorg);
403 if (sv_gameplayfix_findradiusdistancetobox.integer)
405 eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
406 eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
407 eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
410 VectorMAMAM(1, eorg, 0.5f, ent->fields.client->mins, 0.5f, ent->fields.client->maxs, eorg);
411 if (DotProduct(eorg, eorg) < radius2)
413 ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
418 VM_RETURN_EDICT(chain);
421 // #34 float() droptofloor
422 void VM_CL_droptofloor (void)
429 // assume failure if it returns early
430 PRVM_G_FLOAT(OFS_RETURN) = 0;
432 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
433 if (ent == prog->edicts)
435 VM_Warning("droptofloor: can not modify world entity\n");
438 if (ent->priv.server->free)
440 VM_Warning("droptofloor: can not modify free entity\n");
444 VectorCopy (ent->fields.client->origin, end);
447 trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false);
449 if (trace.fraction != 1)
451 VectorCopy (trace.endpos, ent->fields.client->origin);
452 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
453 // ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
454 PRVM_G_FLOAT(OFS_RETURN) = 1;
455 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
456 // ent->priv.server->suspendedinairflag = true;
460 // #35 void(float style, string value) lightstyle
461 void VM_CL_lightstyle (void)
466 VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
468 i = (int)PRVM_G_FLOAT(OFS_PARM0);
469 c = PRVM_G_STRING(OFS_PARM1);
470 if (i >= cl.max_lightstyle)
472 VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
475 strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map));
476 cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
477 cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
480 // #40 float(entity e) checkbottom
481 void VM_CL_checkbottom (void)
483 static int cs_yes, cs_no;
485 vec3_t mins, maxs, start, stop;
490 VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
491 ent = PRVM_G_EDICT(OFS_PARM0);
492 PRVM_G_FLOAT(OFS_RETURN) = 0;
494 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
495 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
497 // if all of the points under the corners are solid world, don't bother
498 // with the tougher checks
499 // the corners must be within 16 of the midpoint
500 start[2] = mins[2] - 1;
501 for (x=0 ; x<=1 ; x++)
502 for (y=0 ; y<=1 ; y++)
504 start[0] = x ? maxs[0] : mins[0];
505 start[1] = y ? maxs[1] : mins[1];
506 if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
511 PRVM_G_FLOAT(OFS_RETURN) = true;
512 return; // we got out easy
517 // check it for real...
521 // the midpoint must be within 16 of the bottom
522 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
523 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
524 stop[2] = start[2] - 2*sv_stepheight.value;
525 trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
527 if (trace.fraction == 1.0)
530 mid = bottom = trace.endpos[2];
532 // the corners must be within 16 of the midpoint
533 for (x=0 ; x<=1 ; x++)
534 for (y=0 ; y<=1 ; y++)
536 start[0] = stop[0] = x ? maxs[0] : mins[0];
537 start[1] = stop[1] = y ? maxs[1] : mins[1];
539 trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
541 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
542 bottom = trace.endpos[2];
543 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
548 PRVM_G_FLOAT(OFS_RETURN) = true;
551 // #41 float(vector v) pointcontents
552 void VM_CL_pointcontents (void)
554 VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
555 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
558 // #48 void(vector o, vector d, float color, float count) particle
559 void VM_CL_particle (void)
564 VM_SAFEPARMCOUNT(4, VM_CL_particle);
566 org = PRVM_G_VECTOR(OFS_PARM0);
567 dir = PRVM_G_VECTOR(OFS_PARM1);
568 color = (int)PRVM_G_FLOAT(OFS_PARM2);
569 count = (int)PRVM_G_FLOAT(OFS_PARM3);
570 CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color);
573 // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
574 void VM_CL_changeyaw (void)
577 float ideal, current, move, speed;
578 VM_SAFEPARMCOUNT(3, VM_CL_changeyaw);
580 ent = PRVM_G_EDICT(OFS_PARM0);
581 if (ent == prog->edicts)
583 VM_Warning("changeyaw: can not modify world entity\n");
586 if (ent->priv.server->free)
588 VM_Warning("changeyaw: can not modify free entity\n");
591 current = ANGLEMOD(ent->fields.client->angles[1]);
592 ideal = PRVM_G_FLOAT(OFS_PARM1);
593 speed = PRVM_G_FLOAT(OFS_PARM2);
595 if (current == ideal)
597 move = ideal - current;
619 ent->fields.client->angles[1] = ANGLEMOD (current + move);
622 // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
623 void VM_CL_changepitch (void)
626 float ideal, current, move, speed;
627 VM_SAFEPARMCOUNT(3, VM_CL_changepitch);
629 ent = PRVM_G_EDICT(OFS_PARM0);
630 if (ent == prog->edicts)
632 VM_Warning("changepitch: can not modify world entity\n");
635 if (ent->priv.server->free)
637 VM_Warning("changepitch: can not modify free entity\n");
640 current = ANGLEMOD( ent->fields.client->angles[0] );
641 ideal = PRVM_G_FLOAT(OFS_PARM1);
642 speed = PRVM_G_FLOAT(OFS_PARM2);
644 if (current == ideal)
646 move = ideal - current;
668 ent->fields.client->angles[0] = ANGLEMOD (current + move);
671 // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
672 void VM_CL_tracetoss (void)
676 prvm_edict_t *ignore;
678 ent = PRVM_G_EDICT(OFS_PARM0);
679 if (ent == prog->edicts)
681 VM_Warning("tracetoss: can not use world entity\n");
684 ignore = PRVM_G_EDICT(OFS_PARM1);
687 trace = SV_Trace_Toss (ent, ignore);
689 prog->globals.server->trace_allsolid = trace.allsolid;
690 prog->globals.server->trace_startsolid = trace.startsolid;
691 prog->globals.server->trace_fraction = trace.fraction;
692 prog->globals.server->trace_inwater = trace.inwater;
693 prog->globals.server->trace_inopen = trace.inopen;
694 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
695 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
696 prog->globals.server->trace_plane_dist = trace.plane.dist;
698 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
700 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
704 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
705 void VM_CL_ambientsound (void)
709 VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
710 s = S_FindName(PRVM_G_STRING(OFS_PARM0));
711 f = PRVM_G_VECTOR(OFS_PARM1);
712 S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
715 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
716 void VM_CL_tracebox (void)
718 float *v1, *v2, *m1, *m2;
722 v1 = PRVM_G_VECTOR(OFS_PARM0);
723 m1 = PRVM_G_VECTOR(OFS_PARM1);
724 m2 = PRVM_G_VECTOR(OFS_PARM2);
725 v2 = PRVM_G_VECTOR(OFS_PARM3);
727 trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false);
729 prog->globals.client->trace_allsolid = trace.allsolid;
730 prog->globals.client->trace_startsolid = trace.startsolid;
731 prog->globals.client->trace_fraction = trace.fraction;
732 prog->globals.client->trace_inwater = trace.inwater;
733 prog->globals.client->trace_inopen = trace.inopen;
734 VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
735 VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
736 prog->globals.client->trace_plane_dist = trace.plane.dist;
738 prog->globals.client->trace_ent = ent;
740 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
743 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
744 void VM_CL_getlight (void)
746 vec3_t ambientcolor, diffusecolor, diffusenormal;
749 VM_SAFEPARMCOUNT(1, VM_CL_getlight);
751 p = PRVM_G_VECTOR(OFS_PARM0);
752 VectorClear(ambientcolor);
753 VectorClear(diffusecolor);
754 VectorClear(diffusenormal);
755 if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
756 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
757 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
761 //============================================================================
762 //[515]: SCENE MANAGER builtins
763 void V_CalcRefdef (void);//view.c
764 void CSQC_R_ClearScreen (void);//gl_rmain.c
765 void CSQC_R_RenderScene (void);//gl_rmain.c
766 void CSQC_AddEntity (int n);//csprogs.c
767 void CSQC_ClearCSQCEntities (void);
769 matrix4x4_t csqc_listenermatrix;
770 qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
771 qboolean csqc_onground;
773 static void CSQC_R_RecalcView (void)
775 extern matrix4x4_t viewmodelmatrix;
776 viewmodelmatrix = identitymatrix;
777 r_view.matrix = identitymatrix;
778 Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
779 Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 0.3);
782 //#300 void() clearscene (EXT_CSQC)
783 void VM_R_ClearScene (void)
785 VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
786 // CSQC_R_RecalcView();
788 CSQC_ClearCSQCEntities();
789 CSQC_R_ClearScreen();
792 //#301 void(float mask) addentities (EXT_CSQC)
793 void VM_R_AddEntities (void)
795 VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
796 csqc_drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
799 //#302 void(entity ent) addentity (EXT_CSQC)
800 void VM_R_AddEntity (void)
802 VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
803 CSQC_AddEntity(PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)));
806 //#303 float(float property, ...) setproperty (EXT_CSQC)
807 void VM_R_SetView (void)
814 VM_SAFEPARMCOUNT(2, VM_R_SetView);
816 c = (int)PRVM_G_FLOAT(OFS_PARM0);
817 f = PRVM_G_VECTOR(OFS_PARM1);
818 k = PRVM_G_FLOAT(OFS_PARM1);
822 case VF_MIN: r_view.x = (int)f[0];
823 r_view.y = (int)f[1];
825 case VF_MIN_X: r_view.x = (int)k;
827 case VF_MIN_Y: r_view.y = (int)k;
829 case VF_SIZE: r_view.width = (int)f[0];
830 r_view.height = (int)f[1];
832 case VF_SIZE_Y: r_view.width = (int)k;
834 case VF_SIZE_X: r_view.height = (int)k;
836 case VF_VIEWPORT: r_view.x = (int)f[0];
837 r_view.y = (int)f[1];
839 // TODO: make sure that view_z and view_depth are set properly even if csqc does not set them!
840 f = PRVM_G_VECTOR(OFS_PARM2);
841 r_view.width = (int)f[0];
842 r_view.height = (int)f[1];
845 case VF_FOV: //r_refdef.fov_x = f[0]; // FIXME!
846 //r_refdef.fov_y = f[1]; // FIXME!
848 case VF_FOVX: //r_refdef.fov_x = k; // FIXME!
850 case VF_FOVY: //r_refdef.fov_y = k; // FIXME!
852 case VF_ORIGIN: VectorCopy(f, csqc_origin);
855 case VF_ORIGIN_X: csqc_origin[0] = k;
858 case VF_ORIGIN_Y: csqc_origin[1] = k;
861 case VF_ORIGIN_Z: csqc_origin[2] = k;
864 case VF_ANGLES: VectorCopy(f, csqc_angles);
867 case VF_ANGLES_X: csqc_angles[0] = k;
870 case VF_ANGLES_Y: csqc_angles[1] = k;
873 case VF_ANGLES_Z: csqc_angles[2] = k;
876 case VF_DRAWWORLD: cl.csqc_vidvars.drawworld = k;
878 case VF_DRAWENGINESBAR: cl.csqc_vidvars.drawenginesbar = k;
880 case VF_DRAWCROSSHAIR: cl.csqc_vidvars.drawcrosshair = k;
883 case VF_CL_VIEWANGLES: VectorCopy(f, cl.viewangles);
885 case VF_CL_VIEWANGLES_X:cl.viewangles[0] = k;
887 case VF_CL_VIEWANGLES_Y:cl.viewangles[1] = k;
889 case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
892 default: PRVM_G_FLOAT(OFS_RETURN) = 0;
893 VM_Warning("VM_R_SetView : unknown parm %i\n", c);
896 PRVM_G_FLOAT(OFS_RETURN) = 1;
899 //#304 void() renderscene (EXT_CSQC)
900 void VM_R_RenderScene (void) //#134
902 VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
906 CSQC_RelinkCSQCEntities();
907 CSQC_RelinkAllEntities(csqc_drawmask);
910 CSQC_R_RenderScene();
913 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
914 void VM_R_AddDynamicLight (void)
917 matrix4x4_t tempmatrix;
918 VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
920 pos = PRVM_G_VECTOR(OFS_PARM0);
921 col = PRVM_G_VECTOR(OFS_PARM2);
922 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
923 CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
924 //CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), col[0], col[1], col[2], 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
927 //============================================================================
929 //#310 vector (vector v) cs_unproject (EXT_CSQC)
930 void VM_CL_unproject (void)
935 VM_SAFEPARMCOUNT(1, VM_CL_unproject);
936 f = PRVM_G_VECTOR(OFS_PARM0);
937 VectorSet(temp, f[2], f[0] * f[2] * -r_view.frustum_x * 2.0 / r_view.width, f[1] * f[2] * -r_view.frustum_y * 2.0 / r_view.height);
938 Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
941 //#311 vector (vector v) cs_project (EXT_CSQC)
942 void VM_CL_project (void)
948 VM_SAFEPARMCOUNT(1, VM_CL_project);
949 f = PRVM_G_VECTOR(OFS_PARM0);
950 Matrix4x4_Invert_Simple(&m, &r_view.matrix);
951 Matrix4x4_Transform(&m, f, v);
952 VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_view.frustum_x*0.5*r_view.width, v[2]/v[0]/-r_view.frustum_y*r_view.height*0.5, v[0]);
955 //#330 float(float stnum) getstatf (EXT_CSQC)
956 void VM_CL_getstatf (void)
964 VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
965 i = (int)PRVM_G_FLOAT(OFS_PARM0);
966 if(i < 0 || i >= MAX_CL_STATS)
968 VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
972 PRVM_G_FLOAT(OFS_RETURN) = dat.f;
975 //#331 float(float stnum) getstati (EXT_CSQC)
976 void VM_CL_getstati (void)
979 VM_SAFEPARMCOUNT(1, VM_CL_getstati);
980 index = (int)PRVM_G_FLOAT(OFS_PARM0);
982 if(index < 0 || index >= MAX_CL_STATS)
984 VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
988 PRVM_G_FLOAT(OFS_RETURN) = i;
991 //#332 string(float firststnum) getstats (EXT_CSQC)
992 void VM_CL_getstats (void)
996 VM_SAFEPARMCOUNT(1, VM_CL_getstats);
997 i = (int)PRVM_G_FLOAT(OFS_PARM0);
998 if(i < 0 || i > MAX_CL_STATS-4)
1000 VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
1003 t = VM_GetTempString();
1004 strlcpy(t, (char*)&cl.stats[i], 16);
1005 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1008 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
1009 void VM_CL_setmodelindex (void)
1015 VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
1017 t = PRVM_G_EDICT(OFS_PARM0);
1018 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1020 t->fields.client->model = 0;
1021 t->fields.client->modelindex = 0;
1030 VM_Warning("VM_CL_setmodelindex >= MAX_MODELS\n");
1033 m = cl.csqc_model_precache[i];
1038 VM_Warning("VM_CL_setmodelindex >= MAX_MODELS\n");
1042 m = cl.model_precache[i];
1045 VM_Warning("VM_CL_setmodelindex: null model\n");
1048 t->fields.client->model = PRVM_SetEngineString(m->name);
1049 t->fields.client->modelindex = i;
1052 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
1053 void VM_CL_modelnameforindex (void)
1057 VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
1059 PRVM_G_INT(OFS_RETURN) = 0;
1060 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1066 VM_Warning("VM_CL_modelnameforindex >= MAX_MODELS\n");
1069 if(cl.csqc_model_precache[i])
1070 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
1075 VM_Warning("VM_CL_modelnameforindex >= MAX_MODELS\n");
1078 if(cl.model_precache[i])
1079 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.model_precache[i]->name);
1082 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1083 void VM_CL_particleeffectnum (void)
1087 VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1088 n = PRVM_G_STRING(OFS_PARM0);
1089 i = CL_ParticleEffectIndexForName(n);
1092 PRVM_G_FLOAT(OFS_RETURN) = i;
1095 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1096 void VM_CL_trailparticles (void)
1101 VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
1103 t = PRVM_G_EDICT(OFS_PARM0);
1104 entnum = PRVM_NUM_FOR_EDICT(t);
1105 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1106 start = PRVM_G_VECTOR(OFS_PARM2);
1107 end = PRVM_G_VECTOR(OFS_PARM3);
1109 if (entnum >= MAX_EDICTS)
1111 VM_Warning("CSQC_ParseBeam: invalid entity number %i\n", entnum);
1114 if (entnum >= cl.max_csqcentities)
1115 CL_ExpandCSQCEntities(entnum);
1117 CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, &cl.csqcentities[entnum], (int)PRVM_G_FLOAT(OFS_PARM4));
1120 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
1121 void VM_CL_pointparticles (void)
1125 VM_SAFEPARMCOUNT(4, VM_CL_pointparticles);
1126 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1127 f = PRVM_G_VECTOR(OFS_PARM1);
1128 v = PRVM_G_VECTOR(OFS_PARM2);
1129 n = (int)PRVM_G_FLOAT(OFS_PARM3);
1130 CL_ParticleEffect(i, n, f, f, v, v, NULL, 0);
1133 //#338 void(string s) cprint (EXT_CSQC)
1134 void VM_CL_centerprint (void)
1136 char s[VM_STRINGTEMP_LENGTH];
1138 VM_SAFEPARMCOUNT(1, VM_CL_centerprint);
1139 VM_VarString(0, s, sizeof(s));
1143 //#342 string(float keynum) getkeybind (EXT_CSQC)
1144 void VM_CL_getkeybind (void)
1148 VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1149 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1150 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Key_GetBind(i));
1153 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1154 void VM_CL_setcursormode (void)
1156 VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1157 cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1158 cl_ignoremousemove = true;
1161 //#345 float(float framenum) getinputstate (EXT_CSQC)
1162 void VM_CL_getinputstate (void)
1165 VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1166 frame = (int)PRVM_G_FLOAT(OFS_PARM0);
1167 for (i = 0;i < cl.movement_numqueue;i++)
1168 if (cl.movement_queue[i].sequence == frame)
1170 VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
1171 //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
1172 VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
1173 prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
1174 if(cl.movement_queue[i].crouch)
1176 VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
1177 VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
1181 VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
1182 VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
1187 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1188 void VM_CL_setsensitivityscale (void)
1190 VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1191 cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1194 //#347 void() runstandardplayerphysics (EXT_CSQC)
1195 void VM_CL_runplayerphysics (void)
1199 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1200 void VM_CL_getplayerkey (void)
1207 VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1209 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1210 c = PRVM_G_STRING(OFS_PARM1);
1211 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1214 i = Sbar_GetPlayer(i);
1220 if(!strcasecmp(c, "name"))
1221 strlcpy(t, cl.scores[i].name, sizeof(t));
1223 if(!strcasecmp(c, "frags"))
1224 sprintf(t, "%i", cl.scores[i].frags);
1226 // if(!strcasecmp(c, "ping"))
1227 // sprintf(t, "%i", cl.scores[i].ping);
1229 // if(!strcasecmp(c, "entertime"))
1230 // sprintf(t, "%f", cl.scores[i].entertime);
1232 if(!strcasecmp(c, "colors"))
1233 sprintf(t, "%i", cl.scores[i].colors);
1235 if(!strcasecmp(c, "topcolor"))
1236 sprintf(t, "%i", cl.scores[i].colors & 0xf0);
1238 if(!strcasecmp(c, "bottomcolor"))
1239 sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
1241 if(!strcasecmp(c, "viewentity"))
1242 sprintf(t, "%i", i+1);
1245 temp = VM_GetTempString();
1246 strlcpy(temp, t, VM_STRINGTEMP_LENGTH);
1247 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
1250 //#349 float() isdemo (EXT_CSQC)
1251 void VM_CL_isdemo (void)
1253 PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1256 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1257 void VM_CL_setlistener (void)
1259 VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1260 Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1261 csqc_usecsqclistener = true; //use csqc listener at this frame
1264 //#352 void(string cmdname) registercommand (EXT_CSQC)
1265 void VM_CL_registercmd (void)
1268 VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1269 if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1273 alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
1274 t = (char *)Z_Malloc(alloclen);
1275 memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
1276 Cmd_AddCommand(t, NULL, "console command created by QuakeC");
1279 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
1283 //#354 float() playernum (EXT_CSQC)
1284 void VM_CL_playernum (void)
1288 VM_SAFEPARMCOUNT(0, VM_CL_playernum);
1290 for(i=k=0 ; i<cl.maxclients ; i++)
1291 if(cl.scores[i].name[0])
1293 PRVM_G_FLOAT(OFS_RETURN) = k;
1296 //#355 float() cl_onground (EXT_CSQC)
1297 void VM_CL_onground (void)
1299 PRVM_G_FLOAT(OFS_RETURN) = csqc_onground;
1302 //#360 float() readbyte (EXT_CSQC)
1303 void VM_CL_ReadByte (void)
1305 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1308 //#361 float() readchar (EXT_CSQC)
1309 void VM_CL_ReadChar (void)
1311 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1314 //#362 float() readshort (EXT_CSQC)
1315 void VM_CL_ReadShort (void)
1317 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1320 //#363 float() readlong (EXT_CSQC)
1321 void VM_CL_ReadLong (void)
1323 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1326 //#364 float() readcoord (EXT_CSQC)
1327 void VM_CL_ReadCoord (void)
1329 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
1332 //#365 float() readangle (EXT_CSQC)
1333 void VM_CL_ReadAngle (void)
1335 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
1338 //#366 string() readstring (EXT_CSQC)
1339 void VM_CL_ReadString (void)
1342 t = VM_GetTempString();
1343 s = MSG_ReadString();
1344 PRVM_G_INT(OFS_RETURN) = 0;
1347 strlcpy(t, s, VM_STRINGTEMP_LENGTH);
1348 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1352 //#367 float() readfloat (EXT_CSQC)
1353 void VM_CL_ReadFloat (void)
1355 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1358 //=================================================================//
1360 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1361 void VM_CL_effect (void)
1363 VM_SAFEPARMCOUNT(5, VM_CL_effect);
1364 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));
1367 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1368 void VM_CL_te_blood (void)
1372 VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1373 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1375 pos = PRVM_G_VECTOR(OFS_PARM0);
1376 CL_FindNonSolidLocation(pos, pos2, 4);
1377 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1380 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1381 void VM_CL_te_bloodshower (void)
1385 VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1386 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1388 speed = PRVM_G_FLOAT(OFS_PARM2);
1395 CL_ParticleEffect(EFFECT_TE_BLOOD, PRVM_G_FLOAT(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), vel1, vel2, NULL, 0);
1398 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1399 void VM_CL_te_explosionrgb (void)
1403 matrix4x4_t tempmatrix;
1404 VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1405 pos = PRVM_G_VECTOR(OFS_PARM0);
1406 CL_FindNonSolidLocation(pos, pos2, 10);
1407 CL_ParticleExplosion(pos2);
1408 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1409 CL_AllocDlight(NULL, &tempmatrix, 350, PRVM_G_VECTOR(OFS_PARM1)[0], PRVM_G_VECTOR(OFS_PARM1)[1], PRVM_G_VECTOR(OFS_PARM1)[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1412 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1413 void VM_CL_te_particlecube (void)
1415 VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1416 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));
1419 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1420 void VM_CL_te_particlerain (void)
1422 VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1423 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);
1426 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1427 void VM_CL_te_particlesnow (void)
1429 VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1430 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);
1433 // #411 void(vector org, vector vel, float howmany) te_spark
1434 void VM_CL_te_spark (void)
1438 VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1440 pos = PRVM_G_VECTOR(OFS_PARM0);
1441 CL_FindNonSolidLocation(pos, pos2, 4);
1442 CL_ParticleEffect(EFFECT_TE_SPARK, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0);
1445 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1446 void VM_CL_te_gunshotquad (void)
1450 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1452 pos = PRVM_G_VECTOR(OFS_PARM0);
1453 CL_FindNonSolidLocation(pos, pos2, 4);
1454 CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1457 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1458 void VM_CL_te_spikequad (void)
1463 VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1465 pos = PRVM_G_VECTOR(OFS_PARM0);
1466 CL_FindNonSolidLocation(pos, pos2, 4);
1467 CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1468 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1472 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1473 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1474 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1478 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1479 void VM_CL_te_superspikequad (void)
1484 VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1486 pos = PRVM_G_VECTOR(OFS_PARM0);
1487 CL_FindNonSolidLocation(pos, pos2, 4);
1488 CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1489 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1493 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1494 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1495 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1499 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1500 void VM_CL_te_explosionquad (void)
1504 VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1506 pos = PRVM_G_VECTOR(OFS_PARM0);
1507 CL_FindNonSolidLocation(pos, pos2, 10);
1508 CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1509 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1512 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1513 void VM_CL_te_smallflash (void)
1517 VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1519 pos = PRVM_G_VECTOR(OFS_PARM0);
1520 CL_FindNonSolidLocation(pos, pos2, 10);
1521 CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1524 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1525 void VM_CL_te_customflash (void)
1529 matrix4x4_t tempmatrix;
1530 VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1532 pos = PRVM_G_VECTOR(OFS_PARM0);
1533 CL_FindNonSolidLocation(pos, pos2, 4);
1534 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1535 CL_AllocDlight(NULL, &tempmatrix, PRVM_G_FLOAT(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM3)[0], PRVM_G_VECTOR(OFS_PARM3)[1], PRVM_G_VECTOR(OFS_PARM3)[2], PRVM_G_FLOAT(OFS_PARM1) / PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM2), 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1538 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1539 void VM_CL_te_gunshot (void)
1543 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1545 pos = PRVM_G_VECTOR(OFS_PARM0);
1546 CL_FindNonSolidLocation(pos, pos2, 4);
1547 CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1550 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1551 void VM_CL_te_spike (void)
1556 VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1558 pos = PRVM_G_VECTOR(OFS_PARM0);
1559 CL_FindNonSolidLocation(pos, pos2, 4);
1560 CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1561 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1565 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1566 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1567 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1571 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1572 void VM_CL_te_superspike (void)
1577 VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1579 pos = PRVM_G_VECTOR(OFS_PARM0);
1580 CL_FindNonSolidLocation(pos, pos2, 4);
1581 CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1582 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1586 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1587 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1588 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1592 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1593 void VM_CL_te_explosion (void)
1597 VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1599 pos = PRVM_G_VECTOR(OFS_PARM0);
1600 CL_FindNonSolidLocation(pos, pos2, 10);
1601 CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1602 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1605 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1606 void VM_CL_te_tarexplosion (void)
1610 VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1612 pos = PRVM_G_VECTOR(OFS_PARM0);
1613 CL_FindNonSolidLocation(pos, pos2, 10);
1614 CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1615 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1618 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1619 void VM_CL_te_wizspike (void)
1623 VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1625 pos = PRVM_G_VECTOR(OFS_PARM0);
1626 CL_FindNonSolidLocation(pos, pos2, 4);
1627 CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1628 S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1631 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1632 void VM_CL_te_knightspike (void)
1636 VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1638 pos = PRVM_G_VECTOR(OFS_PARM0);
1639 CL_FindNonSolidLocation(pos, pos2, 4);
1640 CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1641 S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1644 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1645 void VM_CL_te_lavasplash (void)
1647 VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1648 CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1651 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1652 void VM_CL_te_teleport (void)
1654 VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1655 CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
1658 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1659 void VM_CL_te_explosion2 (void)
1663 matrix4x4_t tempmatrix;
1664 int colorStart, colorLength;
1665 unsigned char *tempcolor;
1666 VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1668 pos = PRVM_G_VECTOR(OFS_PARM0);
1669 colorStart = (int)PRVM_G_FLOAT(OFS_PARM1);
1670 colorLength = (int)PRVM_G_FLOAT(OFS_PARM2);
1671 CL_FindNonSolidLocation(pos, pos2, 10);
1672 CL_ParticleExplosion2(pos2, colorStart, colorLength);
1673 tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
1674 color[0] = tempcolor[0] * (2.0f / 255.0f);
1675 color[1] = tempcolor[1] * (2.0f / 255.0f);
1676 color[2] = tempcolor[2] * (2.0f / 255.0f);
1677 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1678 CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1679 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1683 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1684 void VM_CL_te_lightning1 (void)
1686 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1687 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1690 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1691 void VM_CL_te_lightning2 (void)
1693 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1694 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1697 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1698 void VM_CL_te_lightning3 (void)
1700 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1701 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1704 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1705 void VM_CL_te_beam (void)
1707 VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1708 CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1711 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1712 void VM_CL_te_plasmaburn (void)
1716 VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1718 pos = PRVM_G_VECTOR(OFS_PARM0);
1719 CL_FindNonSolidLocation(pos, pos2, 4);
1720 CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0);
1724 //====================================================================
1727 extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
1728 static model_t *cl_getmodel(prvm_edict_t *ed)
1731 model_t *model = NULL;
1732 if (!ed || ed->priv.server->free)
1734 modelindex = (int)ed->fields.client->modelindex;
1739 modelindex = -(modelindex+1);
1740 if(modelindex < MAX_MODELS)
1741 model = cl.csqc_model_precache[modelindex];
1745 if(modelindex < MAX_MODELS)
1746 model = cl.model_precache[modelindex];
1751 static msurface_t *cl_getsurface(model_t *model, int surfacenum)
1753 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1755 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1758 // #434 float(entity e, float s) getsurfacenumpoints
1759 void VM_CL_getsurfacenumpoints(void)
1761 model_t *model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0));
1762 msurface_t *surface;
1763 // return 0 if no such surface
1764 if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1766 PRVM_G_FLOAT(OFS_RETURN) = 0;
1770 // note: this (incorrectly) assumes it is a simple polygon
1771 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1774 // #435 vector(entity e, float s, float n) getsurfacepoint
1775 void VM_CL_getsurfacepoint(void)
1779 msurface_t *surface;
1781 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1782 ed = PRVM_G_EDICT(OFS_PARM0);
1783 if (!(model = cl_getmodel(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1785 // note: this (incorrectly) assumes it is a simple polygon
1786 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
1787 if (pointnum < 0 || pointnum >= surface->num_vertices)
1789 // FIXME: implement rotation/scaling
1790 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1793 // #436 vector(entity e, float s) getsurfacenormal
1794 void VM_CL_getsurfacenormal(void)
1797 msurface_t *surface;
1799 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1800 if (!(model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1802 // FIXME: implement rotation/scaling
1803 // note: this (incorrectly) assumes it is a simple polygon
1804 // note: this only returns the first triangle, so it doesn't work very
1805 // well for curved surfaces or arbitrary meshes
1806 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);
1807 VectorNormalize(normal);
1808 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1811 // #437 string(entity e, float s) getsurfacetexture
1812 void VM_CL_getsurfacetexture(void)
1815 msurface_t *surface;
1816 PRVM_G_INT(OFS_RETURN) = 0;
1817 if (!(model = cl_getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1819 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1822 // #438 float(entity e, vector p) getsurfacenearpoint
1823 void VM_CL_getsurfacenearpoint(void)
1825 int surfacenum, best;
1827 vec_t dist, bestdist;
1829 model_t *model = NULL;
1830 msurface_t *surface;
1832 PRVM_G_FLOAT(OFS_RETURN) = -1;
1833 ed = PRVM_G_EDICT(OFS_PARM0);
1834 if(!(model = cl_getmodel(ed)) || !model->num_surfaces)
1837 // FIXME: implement rotation/scaling
1838 point = PRVM_G_VECTOR(OFS_PARM1);
1839 VectorSubtract(point, ed->fields.client->origin, p);
1841 bestdist = 1000000000;
1842 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1844 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1845 // first see if the nearest point on the surface's box is closer than the previous match
1846 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1847 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1848 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1849 dist = VectorLength2(clipped);
1850 if (dist < bestdist)
1852 // it is, check the nearest point on the actual geometry
1853 clippointtosurface(model, surface, p, clipped);
1854 VectorSubtract(clipped, p, clipped);
1855 dist += VectorLength2(clipped);
1856 if (dist < bestdist)
1858 // that's closer too, store it as the best match
1864 PRVM_G_FLOAT(OFS_RETURN) = best;
1867 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
1868 void VM_CL_getsurfaceclippedpoint(void)
1872 msurface_t *surface;
1874 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1875 ed = PRVM_G_EDICT(OFS_PARM0);
1876 if (!(model = cl_getmodel(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
1878 // FIXME: implement rotation/scaling
1879 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
1880 clippointtosurface(model, surface, p, out);
1881 // FIXME: implement rotation/scaling
1882 VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
1885 // #443 void(entity e, entity tagentity, string tagname) setattachment
1886 void VM_CL_setattachment (void)
1888 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1889 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1890 const char *tagname = PRVM_G_STRING(OFS_PARM2);
1895 if (e == prog->edicts)
1897 VM_Warning("setattachment: can not modify world entity\n");
1900 if (e->priv.server->free)
1902 VM_Warning("setattachment: can not modify free entity\n");
1906 if (tagentity == NULL)
1907 tagentity = prog->edicts;
1909 v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_entity);
1911 v->edict = PRVM_EDICT_TO_PROG(tagentity);
1913 v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_index);
1916 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
1918 modelindex = (int)tagentity->fields.client->modelindex;
1925 modelindex = -(modelindex+1);
1926 if(modelindex < MAX_MODELS)
1927 model = cl.csqc_model_precache[modelindex];
1930 if(modelindex < MAX_MODELS)
1931 model = cl.model_precache[modelindex];
1936 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname);
1938 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);
1941 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));
1945 /////////////////////////////////////////
1946 // DP_MD3_TAGINFO extension coded by VorteX
1948 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
1953 i = (int)e->fields.client->modelindex;
1962 m = cl.csqc_model_precache[i];
1968 m = cl.model_precache[i];
1970 return Mod_Alias_GetTagIndexForName(m, (int)e->fields.client->skin, tagname);
1973 // Warnings/errors code:
1974 // 0 - normal (everything all-right)
1977 // 3 - null or non-precached model
1978 // 4 - no tags with requested index
1979 // 5 - runaway loop at attachment chain
1980 extern cvar_t cl_bob;
1981 extern cvar_t cl_bobcycle;
1982 extern cvar_t cl_bobup;
1983 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
1986 int modelindex, reqframe, attachloop, i;
1987 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
1988 prvm_edict_t *attachent;
1991 *out = identitymatrix; // warnings and errors return identical matrix
1993 if (ent == prog->edicts)
1995 if (ent->priv.server->free)
1998 modelindex = (int)ent->fields.client->modelindex;
2004 modelindex = -(modelindex+1);
2005 if(modelindex >= MAX_MODELS)
2007 model = cl.csqc_model_precache[modelindex];
2010 if(modelindex >= MAX_MODELS)
2013 model = cl.model_precache[modelindex];
2015 if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2016 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2018 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2020 // get initial tag matrix
2023 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2028 tagmatrix = identitymatrix;
2030 if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict)
2031 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2035 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2036 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
2039 i = (int)attachent->fields.client->modelindex;
2044 model = cl.csqc_model_precache[i];
2048 model = cl.model_precache[i];
2050 if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2051 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
2053 attachmatrix = identitymatrix;
2055 // apply transformation by child entity matrix
2056 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2057 if (val->_float == 0)
2059 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
2060 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2061 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2062 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2063 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2064 Matrix4x4_Copy(&tagmatrix, out);
2066 // finally transformate by matrix of tag on parent entity
2067 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2068 out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
2069 out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
2070 out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
2071 Matrix4x4_Copy(&tagmatrix, out);
2075 if (attachloop > 255) // prevent runaway looping
2078 while ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict);
2081 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2082 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2083 if (val->_float == 0)
2085 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2086 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], val->_float);
2087 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2088 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2089 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2090 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2092 if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2093 {// RENDER_VIEWMODEL magic
2094 Matrix4x4_Copy(&tagmatrix, out);
2096 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2097 if (val->_float == 0)
2100 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
2101 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2102 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2103 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2104 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2107 // Cl_bob, ported from rendering code
2108 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2111 // LordHavoc: this code is *weird*, but not replacable (I think it
2112 // should be done in QC on the server, but oh well, quake is quake)
2113 // LordHavoc: figured out bobup: the time at which the sin is at 180
2114 // degrees (which allows lengthening or squishing the peak or valley)
2115 cycle = sv.time/cl_bobcycle.value;
2116 cycle -= (int)cycle;
2117 if (cycle < cl_bobup.value)
2118 cycle = sin(M_PI * cycle / cl_bobup.value);
2120 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2121 // bob is proportional to velocity in the xy plane
2122 // (don't count Z, or jumping messes it up)
2123 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;
2124 bob = bob*0.3 + bob*0.7*cycle;
2125 out->m[2][3] += bound(-7, bob, 4);
2132 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2133 void VM_CL_gettagindex (void)
2135 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2136 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2137 int modelindex, tag_index;
2139 if (ent == prog->edicts)
2141 VM_Warning("gettagindex: can't affect world entity\n");
2144 if (ent->priv.server->free)
2146 VM_Warning("gettagindex: can't affect free entity\n");
2150 modelindex = (int)ent->fields.client->modelindex;
2152 modelindex = -(modelindex+1);
2154 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2155 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2158 tag_index = CL_GetTagIndex(ent, tag_name);
2160 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2162 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2165 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2166 void VM_CL_gettaginfo (void)
2168 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2169 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2170 matrix4x4_t tag_matrix;
2173 returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2174 Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2179 VM_Warning("gettagindex: can't affect world entity\n");
2182 VM_Warning("gettagindex: can't affect free entity\n");
2185 Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2188 Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2191 Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2196 //=================================================
2197 //[515]: here goes test/unfinished/etc.
2199 //[515]: check if it is what it should be
2200 void VM_WasFreed (void)
2203 VM_SAFEPARMCOUNT(1, VM_WasFreed);
2205 e = PRVM_G_EDICT(OFS_PARM0);
2206 if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (*prog->time - e->priv.required->freetime) > 0.5 )))
2207 PRVM_G_FLOAT(OFS_RETURN) = false;
2209 PRVM_G_FLOAT(OFS_RETURN) = true;
2212 void VM_CL_select_cube (void)
2216 float *mins2, *maxs2;
2217 prvm_edict_t *ent, *chain;
2218 vec3_t mins1, maxs1;
2220 VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
2222 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2223 if(!prog->flag & PRVM_FE_CHAIN)
2224 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2226 chain_of = PRVM_ED_FindField("chain")->ofs;
2227 chain = prog->edicts;
2229 mins2 = PRVM_G_VECTOR(OFS_PARM0);
2230 maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2232 ent = PRVM_NEXT_EDICT(prog->edicts);
2233 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2235 if (ent->priv.required->free)
2237 VectorCopy(ent->fields.client->origin, mins1);
2238 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2239 VectorAdd(mins1, ent->fields.client->mins, mins1);
2240 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2242 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2244 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2248 VM_RETURN_EDICT(chain);
2251 void VM_CL_select_super (void)
2256 prvm_edict_t *ent, *chain;
2257 vec3_t mins1, maxs1;
2259 VM_SAFEPARMCOUNT(8, VM_findchain);
2261 v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
2263 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2264 if(!prog->flag & PRVM_FE_CHAIN)
2265 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2267 chain_of = PRVM_ED_FindField("chain")->ofs;
2268 chain = prog->edicts;
2270 mins2 = PRVM_G_VECTOR(OFS_PARM0);
2271 maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2273 ent = PRVM_NEXT_EDICT(prog->edicts);
2274 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2276 if (ent->priv.required->free)
2278 VectorCopy(ent->fields.client->origin, mins1);
2279 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2280 VectorAdd(mins1, ent->fields.client->mins, mins1);
2281 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2283 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2285 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2289 VM_RETURN_EDICT(chain);*/
2292 static int Is_Text_Color (char c, char t)
2295 char c2 = c - (c & 128);
2296 char t2 = t - (t & 128);
2298 if(c != '^' && c2 != '^') return 0;
2299 if(t >= '0' && t <= '9') a = 1;
2300 if(t2 >= '0' && t2 <= '9') a = 1;
2301 /* if(t >= 'A' && t <= 'Z') a = 2;
2302 if(t2 >= 'A' && t2 <= 'Z') a = 2;
2304 if(a == 1 && scr_colortext.integer > 0)
2306 if(a == 2 && scr_multifonts.integer > 0)
2312 void VM_uncolorstring (void) //#170
2318 VM_SAFEPARMCOUNT(1, VM_uncolorstring);
2319 in = PRVM_G_STRING(OFS_PARM0);
2321 PRVM_ERROR ("VM_uncolorstring: %s: NULL\n", PRVM_NAME);
2322 VM_CheckEmptyString (in);
2323 out = VM_GetTempString();
2328 if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
2339 void VM_CL_selecttraceline (void)
2342 int ent, ignore, csqcents;
2344 v1 = PRVM_G_VECTOR(OFS_PARM0);
2345 v2 = PRVM_G_VECTOR(OFS_PARM1);
2346 ignore = (int)PRVM_G_FLOAT(OFS_PARM2);
2347 csqcents = (int)PRVM_G_FLOAT(OFS_PARM3);
2350 if((csqcents && ignore > cl.num_csqcentities) || (!csqcents && ignore > cl.num_entities))
2352 VM_Warning("VM_CL_selecttraceline: out of entities\n");
2357 prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &prog->globals.client->trace_ent, &cl.csqcentities[ignore].render, csqcents);
2359 prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl.entities[ignore].render, csqcents);
2360 PRVM_G_FLOAT(OFS_RETURN) = ent;
2363 void VM_charindex (void)
2366 s = PRVM_G_STRING(OFS_PARM0);
2369 if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
2371 PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
2374 //#223 string(float c, ...) chr2str (FTE_STRINGS)
2375 void VM_chr2str (void)
2379 t = VM_GetTempString();
2380 for(i=0;i<prog->argc;i++)
2381 t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
2383 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
2386 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2387 void VM_strncmp (void)
2389 const char *s1, *s2;
2390 VM_SAFEPARMCOUNT(1, VM_strncmp);
2391 s1 = PRVM_G_STRING(OFS_PARM0);
2392 s2 = PRVM_G_STRING(OFS_PARM1);
2393 PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
2396 //============================================================================
2397 //============================================================================
2399 prvm_builtin_t vm_cl_builtins[] = {
2400 0, // to be consistent with the old vm
2401 VM_CL_makevectors, // #1 void(vector ang) makevectors
2402 VM_CL_setorigin, // #2 void(entity e, vector o) setorigin
2403 VM_CL_setmodel, // #3 void(entity e, string m) setmodel
2404 VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize
2406 VM_break, // #6 void() break
2407 VM_random, // #7 float() random
2408 VM_CL_sound, // #8 void(entity e, float chan, string samp) sound
2409 VM_normalize, // #9 vector(vector v) normalize
2410 VM_error, // #10 void(string e) error
2411 VM_objerror, // #11 void(string e) objerror
2412 VM_vlen, // #12 float(vector v) vlen
2413 VM_vectoyaw, // #13 float(vector v) vectoyaw
2414 VM_CL_spawn, // #14 entity() spawn
2415 VM_remove, // #15 void(entity e) remove
2416 VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2418 VM_find, // #18 entity(entity start, .string fld, string match) find
2419 VM_CL_precache_sound, // #19 void(string s) precache_sound
2420 VM_CL_precache_model, // #20 void(string s) precache_model
2422 VM_CL_findradius, // #22 entity(vector org, float rad) findradius
2425 VM_dprint, // #25 void(string s) dprint
2426 VM_ftos, // #26 void(string s) ftos
2427 VM_vtos, // #27 void(string s) vtos
2428 VM_coredump, // #28 void() coredump
2429 VM_traceon, // #29 void() traceon
2430 VM_traceoff, // #30 void() traceoff
2431 VM_eprint, // #31 void(entity e) eprint
2434 VM_CL_droptofloor, // #34 float() droptofloor
2435 VM_CL_lightstyle, // #35 void(float style, string value) lightstyle
2436 VM_rint, // #36 float(float v) rint
2437 VM_floor, // #37 float(float v) floor
2438 VM_ceil, // #38 float(float v) ceil
2440 VM_CL_checkbottom, // #40 float(entity e) checkbottom
2441 VM_CL_pointcontents, // #41 float(vector v) pointcontents
2443 VM_fabs, // #43 float(float f) fabs
2445 VM_cvar, // #45 float(string s) cvar
2446 VM_localcmd, // #46 void(string s) localcmd
2447 VM_nextent, // #47 entity(entity e) nextent
2448 VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle
2449 VM_CL_changeyaw, // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
2451 VM_vectoangles, // #51 vector(vector v) vectoangles
2452 0, // #52 void(float to, float f) WriteByte
2453 0, // #53 void(float to, float f) WriteChar
2454 0, // #54 void(float to, float f) WriteShort
2455 0, // #55 void(float to, float f) WriteLong
2456 0, // #56 void(float to, float f) WriteCoord
2457 0, // #57 void(float to, float f) WriteAngle
2458 0, // #58 void(float to, string s) WriteString
2460 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2461 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2462 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2463 VM_CL_changepitch, // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
2464 VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2465 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2472 VM_cvar_set, // #72 void(string var, string val) cvar_set
2474 VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2475 VM_CL_precache_model, // #75 string(string s) precache_model2
2476 VM_CL_precache_sound, // #76 string(string s) precache_sound2
2481 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2490 VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2491 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2492 VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2493 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2494 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2495 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2496 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2497 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2498 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2499 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2510 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2511 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2512 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2513 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2514 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2515 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2516 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2517 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2518 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2519 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2521 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2531 VM_bitshift, //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2535 VM_charindex, //#222 float(string str, float ofs) str2chr (FTE_STRINGS)
2536 VM_chr2str, //#223 string(float c, ...) chr2str (FTE_STRINGS)
2541 VM_strncmp, //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2543 e10, e10, e10, e10, e10, e10, e10, // #230-299
2545 //======CSQC start=======//
2546 //3d world (buffer/buffering) operations
2547 VM_R_ClearScene, //#300 void() clearscene (EXT_CSQC)
2548 VM_R_AddEntities, //#301 void(float mask) addentities (EXT_CSQC)
2549 VM_R_AddEntity, //#302 void(entity ent) addentity (EXT_CSQC)
2550 VM_R_SetView, //#303 float(float property, ...) setproperty (EXT_CSQC)
2551 VM_R_RenderScene, //#304 void() renderscene (EXT_CSQC)
2552 VM_R_AddDynamicLight, //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2553 VM_R_PolygonBegin, //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2554 VM_R_PolygonVertex, //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2555 VM_R_PolygonEnd, //#308 void() R_EndPolygon
2558 //maths stuff that uses the current view settings
2559 VM_CL_unproject, //#310 vector (vector v) cs_unproject (EXT_CSQC)
2560 VM_CL_project, //#311 vector (vector v) cs_project (EXT_CSQC)
2565 //2d (immediate) operations
2566 VM_drawline, //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2567 VM_iscachedpic, //#316 float(string name) iscachedpic (EXT_CSQC)
2568 VM_precache_pic, //#317 string(string name, float trywad) precache_pic (EXT_CSQC)
2569 VM_getimagesize, //#318 vector(string picname) draw_getimagesize (EXT_CSQC)
2570 VM_freepic, //#319 void(string name) freepic (EXT_CSQC)
2571 VM_drawcharacter, //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
2572 VM_drawstring, //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
2573 VM_drawpic, //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
2574 VM_drawfill, //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
2575 VM_drawsetcliparea, //#324 void(float x, float y, float width, float height) drawsetcliparea
2576 VM_drawresetcliparea, //#325 void(void) drawresetcliparea
2582 VM_CL_getstatf, //#330 float(float stnum) getstatf (EXT_CSQC)
2583 VM_CL_getstati, //#331 float(float stnum) getstati (EXT_CSQC)
2584 VM_CL_getstats, //#332 string(float firststnum) getstats (EXT_CSQC)
2585 VM_CL_setmodelindex, //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2586 VM_CL_modelnameforindex, //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2587 VM_CL_particleeffectnum, //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2588 VM_CL_trailparticles, //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2589 VM_CL_pointparticles, //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
2590 VM_CL_centerprint, //#338 void(string s) cprint (EXT_CSQC)
2591 VM_print, //#339 void(string s) print (EXT_CSQC)
2592 VM_keynumtostring, //#340 string(float keynum) keynumtostring (EXT_CSQC)
2593 VM_stringtokeynum, //#341 float(string keyname) stringtokeynum (EXT_CSQC)
2594 VM_CL_getkeybind, //#342 string(float keynum) getkeybind (EXT_CSQC)
2595 VM_CL_setcursormode, //#343 void(float usecursor) setcursormode (EXT_CSQC)
2596 VM_getmousepos, //#344 vector() getmousepos (EXT_CSQC)
2597 VM_CL_getinputstate, //#345 float(float framenum) getinputstate (EXT_CSQC)
2598 VM_CL_setsensitivityscale, //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
2599 VM_CL_runplayerphysics, //#347 void() runstandardplayerphysics (EXT_CSQC)
2600 VM_CL_getplayerkey, //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
2601 VM_CL_isdemo, //#349 float() isdemo (EXT_CSQC)
2602 VM_isserver, //#350 float() isserver (EXT_CSQC)
2603 VM_CL_setlistener, //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
2604 VM_CL_registercmd, //#352 void(string cmdname) registercommand (EXT_CSQC)
2605 VM_WasFreed, //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
2606 VM_CL_playernum, //#354 float() playernum
2607 VM_CL_onground, //#355 float() cl_onground (EXT_CSQC)
2608 VM_charindex, //#356 float(string s, float num) charindex
2609 VM_CL_selecttraceline, //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline
2612 VM_CL_ReadByte, //#360 float() readbyte (EXT_CSQC)
2613 VM_CL_ReadChar, //#361 float() readchar (EXT_CSQC)
2614 VM_CL_ReadShort, //#362 float() readshort (EXT_CSQC)
2615 VM_CL_ReadLong, //#363 float() readlong (EXT_CSQC)
2616 VM_CL_ReadCoord, //#364 float() readcoord (EXT_CSQC)
2617 VM_CL_ReadAngle, //#365 float() readangle (EXT_CSQC)
2618 VM_CL_ReadString, //#366 string() readstring (EXT_CSQC)
2619 VM_CL_ReadFloat, //#367 float() readfloat (EXT_CSQC)
2652 //=========CSQC end========//
2654 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2656 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2657 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2658 VM_CL_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2659 VM_CL_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2660 VM_CL_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2661 VM_CL_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2662 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)
2663 VM_CL_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2664 VM_CL_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2665 VM_CL_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2666 VM_CL_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2667 VM_CL_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2668 VM_CL_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2669 VM_CL_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2670 VM_CL_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2671 VM_CL_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2672 VM_CL_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2673 VM_CL_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2674 VM_CL_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2675 VM_CL_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2676 VM_CL_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2677 VM_CL_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2678 VM_CL_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2679 VM_CL_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2680 VM_CL_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2681 VM_CL_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2682 VM_CL_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2683 VM_CL_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2684 VM_CL_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2685 VM_CL_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2686 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2687 VM_CL_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2688 VM_CL_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2689 VM_CL_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2690 VM_CL_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2691 VM_CL_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2692 VM_CL_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2693 VM_CL_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2695 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2696 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2697 VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2698 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2699 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2700 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2701 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2702 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2703 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2704 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2705 VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2706 VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2714 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2715 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2716 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2717 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2718 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2719 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2720 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2721 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2722 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2723 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2724 e10, e10, e10 // #470-499 (LordHavoc)
2727 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2729 void VM_CL_Cmd_Init(void)
2733 void VM_CL_Cmd_Reset(void)