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
20 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
23 //[515]: really need new list ?
24 char *vm_cl_extensions =
38 "DP_ENT_CUSTOMCOLORMAP "
41 "DP_GFX_EXTERNALTEXTURES "
43 "DP_GFX_QUAKE3MODELTAGS "
47 "DP_HALFLIFE_MAP_CVAR "
53 "DP_MOVETYPEBOUNCEMISSILE "
60 "DP_QC_FINDCHAINFLAGS "
61 "DP_QC_FINDCHAINFLOAT "
64 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
69 "DP_QC_MULTIPLETEMPSTRINGS "
71 "DP_QC_SINCOSSQRTPOW "
72 //"DP_QC_STRINGBUFFERS " //[515]: not needed ?
75 "DP_QC_TRACE_MOVETYPE_HITMODEL "
76 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
77 "DP_QC_VECTORVECTORS "
83 "DP_SND_DIRECTIONLESSATTNNONE "
90 "DP_SV_ROTATINGBMODEL "
101 "DP_TE_QUADEFFECTS1 "
104 "DP_TE_STANDARDEFFECTBUILTINS "
108 "KRIMZON_SV_PARSECLIENTCOMMAND "
111 "PRYDON_CLIENTCURSOR "
112 "TENEBRAE_GFX_DLIGHTS "
114 "NEXUIZ_PLAYERMODEL "
118 sfx_t *S_FindName(const char *name);
119 int CL_PointQ1Contents(const vec3_t p);
120 void PF_registercvar (void);
121 int Sbar_GetPlayer (int index);
122 void Sbar_SortFrags (void);
123 void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
124 void CL_ExpandCSQCEntities(int num);
125 void CSQC_RelinkAllEntities (int drawmask);
126 void CSQC_RelinkCSQCEntities (void);
127 char *Key_GetBind (int key);
133 // #1 void(vector ang) makevectors
134 void VM_CL_makevectors (void)
136 VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
137 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up);
140 // #2 void(entity e, vector o) setorigin
141 void VM_CL_setorigin (void)
146 e = PRVM_G_EDICT(OFS_PARM0);
147 if (e == prog->edicts)
148 PF_WARNING("setorigin: can not modify world entity\n");
149 if (e->priv.required->free)
150 PF_WARNING("setorigin: can not modify free entity\n");
151 org = PRVM_G_VECTOR(OFS_PARM1);
152 VectorCopy (org, e->fields.client->origin);
155 // #3 void(entity e, string m) setmodel
156 void VM_CL_setmodel (void)
163 VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
165 e = PRVM_G_EDICT(OFS_PARM0);
166 m = PRVM_G_STRING(OFS_PARM1);
167 for(i=0;i<MAX_MODELS;i++)
168 if(!cl.csqc_model_precache[i])
171 if(!strcmp(cl.csqc_model_precache[i]->name, m))
173 e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
174 e->fields.client->modelindex = -(i+1);
178 for (i=0, mod = cl.model_precache[0] ; i < MAX_MODELS ; i++, mod = cl.model_precache[i])
180 if(!strcmp(mod->name, m))
182 e->fields.client->model = PRVM_SetEngineString(mod->name);
183 e->fields.client->modelindex = i;
186 e->fields.client->modelindex = 0;
187 e->fields.client->model = 0;
190 // #4 void(entity e, vector min, vector max) setsize
191 void VM_CL_setsize (void)
195 VM_SAFEPARMCOUNT(3, VM_CL_setsize);
197 e = PRVM_G_EDICT(OFS_PARM0);
198 if (e == prog->edicts)
199 PF_WARNING("setsize: can not modify world entity\n");
200 if (e->priv.server->free)
201 PF_WARNING("setsize: can not modify free entity\n");
202 min = PRVM_G_VECTOR(OFS_PARM1);
203 max = PRVM_G_VECTOR(OFS_PARM2);
205 VectorCopy (min, e->fields.client->mins);
206 VectorCopy (max, e->fields.client->maxs);
207 VectorSubtract (max, min, e->fields.client->size);
210 // #8 void(entity e, float chan, string samp) sound
211 void VM_CL_sound (void)
215 prvm_edict_t *entity;
219 VM_SAFEPARMCOUNT(5, VM_CL_sound);
221 entity = PRVM_G_EDICT(OFS_PARM0);
222 channel = PRVM_G_FLOAT(OFS_PARM1);
223 sample = PRVM_G_STRING(OFS_PARM2);
224 volume = PRVM_G_FLOAT(OFS_PARM3)*255;
225 attenuation = PRVM_G_FLOAT(OFS_PARM4);
227 if (volume < 0 || volume > 255)
228 PF_WARNING("VM_CL_sound: volume must be in range 0-1\n");
230 if (attenuation < 0 || attenuation > 4)
231 PF_WARNING("VM_CL_sound: attenuation must be in range 0-4\n");
233 if (channel < 0 || channel > 7)
234 PF_WARNING("VM_CL_sound: channel must be in range 0-7\n");
236 S_StartSound(32768 + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), entity->fields.client->origin, volume, attenuation);
239 // #14 entity() spawn
240 void VM_CL_spawn (void)
243 ed = PRVM_ED_Alloc();
244 ed->fields.client->entnum = PRVM_NUM_FOR_EDICT(ed); //[515]: not needed any more ?
248 // #16 float(vector v1, vector v2, float tryents) traceline
249 void VM_CL_traceline (void)
255 v1 = PRVM_G_VECTOR(OFS_PARM0);
256 v2 = PRVM_G_VECTOR(OFS_PARM1);
258 trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false);
260 prog->globals.client->trace_allsolid = trace.allsolid;
261 prog->globals.client->trace_startsolid = trace.startsolid;
262 prog->globals.client->trace_fraction = trace.fraction;
263 prog->globals.client->trace_inwater = trace.inwater;
264 prog->globals.client->trace_inopen = trace.inopen;
265 VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
266 VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
267 prog->globals.client->trace_plane_dist = trace.plane.dist;
269 prog->globals.client->trace_ent = ent;
271 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
274 // #19 void(string s) precache_sound
275 void VM_CL_precache_sound (void)
278 VM_SAFEPARMCOUNT(1, VM_CL_precache_sound);
279 n = PRVM_G_STRING(OFS_PARM0);
280 S_PrecacheSound(n, true, false);
283 // #20 void(string s) precache_model
284 void VM_CL_precache_model (void)
290 VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
292 name = PRVM_G_STRING(OFS_PARM0);
293 for(i=1;i<MAX_MODELS;i++)
294 if(!cl.csqc_model_precache[i])
300 if(!strcmp(cl.csqc_model_precache[i]->name, name))
307 PRVM_G_FLOAT(OFS_RETURN) = i;
310 PRVM_G_FLOAT(OFS_RETURN) = 0;
311 m = Mod_ForName(name, false, false, false);
314 for(i=1;i<MAX_MODELS;i++)
315 if(!cl.csqc_model_precache[i])
318 PF_WARNING("VM_CL_precache_model: no free models\n");
319 cl.csqc_model_precache[i] = (model_t*)m;
320 PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
323 Con_Printf("VM_CL_precache_model: model \"%s\" not found\n", name);
326 int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
331 ent = PRVM_NEXT_EDICT(prog->edicts);
332 for(k=0,i=1; i<prog->num_edicts ;i++, ent = PRVM_NEXT_EDICT(ent))
334 if (ent->priv.required->free)
336 // VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin);
337 // VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax);
338 if(BoxesOverlap(mins, maxs, ent->fields.client->absmin, ent->fields.client->absmax))
344 // #22 entity(vector org, float rad) findradius
345 void VM_CL_findradius (void)
347 prvm_edict_t *ent, *chain;
348 vec_t radius, radius2;
349 vec3_t org, eorg, mins, maxs;
350 int i, numtouchedicts;
351 prvm_edict_t *touchedicts[MAX_EDICTS];
353 chain = (prvm_edict_t *)prog->edicts;
355 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
356 radius = PRVM_G_FLOAT(OFS_PARM1);
357 radius2 = radius * radius;
359 mins[0] = org[0] - (radius + 1);
360 mins[1] = org[1] - (radius + 1);
361 mins[2] = org[2] - (radius + 1);
362 maxs[0] = org[0] + (radius + 1);
363 maxs[1] = org[1] + (radius + 1);
364 maxs[2] = org[2] + (radius + 1);
365 numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
366 if (numtouchedicts > MAX_EDICTS)
368 // this never happens //[515]: for what then ?
369 Con_Printf("CSQC_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
370 numtouchedicts = MAX_EDICTS;
372 for (i = 0;i < numtouchedicts;i++)
374 ent = touchedicts[i];
375 // Quake did not return non-solid entities but darkplaces does
376 // (note: this is the reason you can't blow up fallen zombies)
377 if (ent->fields.client->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
379 // LordHavoc: compare against bounding box rather than center so it
380 // doesn't miss large objects, and use DotProduct instead of Length
381 // for a major speedup
382 VectorSubtract(org, ent->fields.client->origin, eorg);
383 if (sv_gameplayfix_findradiusdistancetobox.integer)
385 eorg[0] -= bound(ent->fields.client->mins[0], eorg[0], ent->fields.client->maxs[0]);
386 eorg[1] -= bound(ent->fields.client->mins[1], eorg[1], ent->fields.client->maxs[1]);
387 eorg[2] -= bound(ent->fields.client->mins[2], eorg[2], ent->fields.client->maxs[2]);
390 VectorMAMAM(1, eorg, 0.5f, ent->fields.client->mins, 0.5f, ent->fields.client->maxs, eorg);
391 if (DotProduct(eorg, eorg) < radius2)
393 ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
398 VM_RETURN_EDICT(chain);
401 // #34 float() droptofloor
402 void VM_CL_droptofloor (void)
409 // assume failure if it returns early
410 PRVM_G_FLOAT(OFS_RETURN) = 0;
412 ent = PRVM_PROG_TO_EDICT(prog->globals.client->self);
413 if (ent == prog->edicts)
414 PF_WARNING("droptofloor: can not modify world entity\n");
415 if (ent->priv.server->free)
416 PF_WARNING("droptofloor: can not modify free entity\n");
418 VectorCopy (ent->fields.client->origin, end);
421 trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false);
423 if (trace.fraction != 1)
425 VectorCopy (trace.endpos, ent->fields.client->origin);
426 ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND;
427 // ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
428 PRVM_G_FLOAT(OFS_RETURN) = 1;
429 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
430 // ent->priv.server->suspendedinairflag = true;
434 // #35 void(float style, string value) lightstyle
435 void VM_CL_lightstyle (void)
440 VM_SAFEPARMCOUNT(2, VM_CL_lightstyle);
442 i = PRVM_G_FLOAT(OFS_PARM0);
443 c = PRVM_G_STRING(OFS_PARM1);
444 if (i >= MAX_LIGHTSTYLES)
445 PF_WARNING("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
446 strlcpy (cl_lightstyle[i].map, MSG_ReadString(), sizeof (cl_lightstyle[i].map));
447 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
448 cl_lightstyle[i].length = (int)strlen(cl_lightstyle[i].map);
451 // #40 float(entity e) checkbottom
452 void VM_CL_checkbottom (void)
454 static int cs_yes, cs_no;
456 vec3_t mins, maxs, start, stop;
461 VM_SAFEPARMCOUNT(1, VM_CL_checkbottom);
462 ent = PRVM_G_EDICT(OFS_PARM0);
463 PRVM_G_FLOAT(OFS_RETURN) = 0;
465 VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins);
466 VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs);
468 // if all of the points under the corners are solid world, don't bother
469 // with the tougher checks
470 // the corners must be within 16 of the midpoint
471 start[2] = mins[2] - 1;
472 for (x=0 ; x<=1 ; x++)
473 for (y=0 ; y<=1 ; y++)
475 start[0] = x ? maxs[0] : mins[0];
476 start[1] = y ? maxs[1] : mins[1];
477 if (!(CL_PointSuperContents(start) & SUPERCONTENTS_SOLID))
482 PRVM_G_FLOAT(OFS_RETURN) = true;
483 return; // we got out easy
488 // check it for real...
492 // the midpoint must be within 16 of the bottom
493 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
494 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
495 stop[2] = start[2] - 2*sv_stepheight.value;
496 trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
498 if (trace.fraction == 1.0)
501 mid = bottom = trace.endpos[2];
503 // the corners must be within 16 of the midpoint
504 for (x=0 ; x<=1 ; x++)
505 for (y=0 ; y<=1 ; y++)
507 start[0] = stop[0] = x ? maxs[0] : mins[0];
508 start[1] = stop[1] = y ? maxs[1] : mins[1];
510 trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true);
512 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
513 bottom = trace.endpos[2];
514 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
519 PRVM_G_FLOAT(OFS_RETURN) = true;
522 // #41 float(vector v) pointcontents
523 void VM_CL_pointcontents (void)
525 VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
526 PRVM_G_FLOAT(OFS_RETURN) = CL_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
529 // #48 void(vector o, vector d, float color, float count) particle
530 void VM_CL_particle (void)
535 VM_SAFEPARMCOUNT(4, VM_CL_particle);
537 org = PRVM_G_VECTOR(OFS_PARM0);
538 dir = PRVM_G_VECTOR(OFS_PARM1);
539 color = PRVM_G_FLOAT(OFS_PARM2);
540 count = PRVM_G_FLOAT(OFS_PARM3);
541 if (cl_particles_blood_bloodhack.integer)
546 CL_BloodPuff(org, dir, count / 2);
552 CL_BloodPuff(org, dir, count / 2);
556 CL_RunParticleEffect (org, dir, color, count);
559 // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
560 void VM_CL_changeyaw (void)
563 float ideal, current, move, speed;
564 VM_SAFEPARMCOUNT(3, VM_CL_changeyaw);
566 ent = PRVM_G_EDICT(OFS_PARM0);
567 if (ent == prog->edicts)
568 PF_WARNING("changeyaw: can not modify world entity\n");
569 if (ent->priv.server->free)
570 PF_WARNING("changeyaw: can not modify free entity\n");
571 current = ANGLEMOD(ent->fields.client->angles[1]);
572 ideal = PRVM_G_FLOAT(OFS_PARM1);
573 speed = PRVM_G_FLOAT(OFS_PARM2);
575 if (current == ideal)
577 move = ideal - current;
599 ent->fields.client->angles[1] = ANGLEMOD (current + move);
602 // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
603 void VM_CL_changepitch (void)
606 float ideal, current, move, speed;
607 VM_SAFEPARMCOUNT(3, VM_CL_changepitch);
609 ent = PRVM_G_EDICT(OFS_PARM0);
610 if (ent == prog->edicts)
611 PF_WARNING("changepitch: can not modify world entity\n");
612 if (ent->priv.server->free)
613 PF_WARNING("changepitch: can not modify free entity\n");
614 current = ANGLEMOD( ent->fields.client->angles[0] );
615 ideal = PRVM_G_FLOAT(OFS_PARM1);
616 speed = PRVM_G_FLOAT(OFS_PARM2);
618 if (current == ideal)
620 move = ideal - current;
642 ent->fields.client->angles[0] = ANGLEMOD (current + move);
645 // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
646 void VM_CL_tracetoss (void)
650 prvm_edict_t *ignore;
652 ent = PRVM_G_EDICT(OFS_PARM0);
653 if (ent == prog->edicts)
654 PF_WARNING("tracetoss: can not use world entity\n");
655 ignore = PRVM_G_EDICT(OFS_PARM1);
658 trace = SV_Trace_Toss (ent, ignore);
660 prog->globals.server->trace_allsolid = trace.allsolid;
661 prog->globals.server->trace_startsolid = trace.startsolid;
662 prog->globals.server->trace_fraction = trace.fraction;
663 prog->globals.server->trace_inwater = trace.inwater;
664 prog->globals.server->trace_inopen = trace.inopen;
665 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
666 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
667 prog->globals.server->trace_plane_dist = trace.plane.dist;
669 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
671 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
675 // #74 void(vector pos, string samp, float vol, float atten) ambientsound
676 void VM_CL_ambientsound (void)
680 VM_SAFEPARMCOUNT(4, VM_CL_ambientsound);
681 s = S_FindName(PRVM_G_STRING(OFS_PARM0));
682 f = PRVM_G_VECTOR(OFS_PARM1);
683 S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64);
686 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
687 void VM_CL_tracebox (void)
689 float *v1, *v2, *m1, *m2;
693 v1 = PRVM_G_VECTOR(OFS_PARM0);
694 m1 = PRVM_G_VECTOR(OFS_PARM1);
695 m2 = PRVM_G_VECTOR(OFS_PARM2);
696 v2 = PRVM_G_VECTOR(OFS_PARM3);
698 trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false);
700 prog->globals.client->trace_allsolid = trace.allsolid;
701 prog->globals.client->trace_startsolid = trace.startsolid;
702 prog->globals.client->trace_fraction = trace.fraction;
703 prog->globals.client->trace_inwater = trace.inwater;
704 prog->globals.client->trace_inopen = trace.inopen;
705 VectorCopy (trace.endpos, prog->globals.client->trace_endpos);
706 VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal);
707 prog->globals.client->trace_plane_dist = trace.plane.dist;
709 prog->globals.client->trace_ent = ent;
711 prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
714 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
715 void VM_CL_getlight (void)
717 vec3_t ambientcolor, diffusecolor, diffusenormal;
720 VM_SAFEPARMCOUNT(1, VM_CL_getlight);
722 p = PRVM_G_VECTOR(OFS_PARM0);
723 VectorClear(ambientcolor);
724 VectorClear(diffusecolor);
725 VectorClear(diffusenormal);
726 if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
727 cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
728 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
732 //============================================================================
733 //[515]: SCENE MANAGER builtins
734 void V_CalcRefdef (void);//view.c
735 void CSQC_R_ClearScreen (void);//gl_rmain.c
736 void CSQC_R_RenderScene (void);//gl_rmain.c
737 void CSQC_AddEntity (int n);//csprogs.c
738 void CSQC_ClearCSQCEntities (void);
740 matrix4x4_t csqc_listenermatrix;
741 qboolean csqc_usecsqclistener = false, csqc_frame = false;//[515]: per-frame
742 qboolean csqc_onground;
744 static char *particleeffect_names[] =
751 "TE_LIGHTNING1",//trail
752 "TE_LIGHTNING2",//trail
755 "TE_LIGHTNING3",//trail
761 "",//TE_LIGHTNING4NEH
780 "TE_TEI_BIGEXPLOSION",
784 //trail effects (as modelflags)
797 #define CSQC_TRAILSTART 36
798 static const int particleeffects_num = sizeof(particleeffect_names)/sizeof(char*);
800 static void CSQC_R_RecalcView (void)
802 extern matrix4x4_t viewmodelmatrix;
803 Matrix4x4_CreateIdentity(&viewmodelmatrix);
804 Matrix4x4_CreateIdentity(&r_refdef.viewentitymatrix);
805 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 1);
806 Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], 0.3);
809 //#300 void() clearscene (EXT_CSQC)
810 void VM_R_ClearScene (void)
812 VM_SAFEPARMCOUNT(0, VM_R_ClearScene);
813 // CSQC_R_RecalcView();
815 CSQC_ClearCSQCEntities();
816 CSQC_R_ClearScreen();
819 //#301 void(float mask) addentities (EXT_CSQC)
820 void VM_R_AddEntities (void)
822 VM_SAFEPARMCOUNT(1, VM_R_AddEntities);
823 csqc_drawmask = PRVM_G_FLOAT(OFS_PARM0);
826 //#302 void(entity ent) addentity (EXT_CSQC)
827 void VM_R_AddEntity (void)
829 VM_SAFEPARMCOUNT(1, VM_R_AddEntity);
830 CSQC_AddEntity(PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)));
833 //#303 float(float property, ...) setproperty (EXT_CSQC)
834 void VM_R_SetView (void)
841 VM_SAFEPARMCOUNT(2, VM_R_SetView);
843 c = PRVM_G_FLOAT(OFS_PARM0);
844 f = PRVM_G_VECTOR(OFS_PARM1);
845 k = PRVM_G_FLOAT(OFS_PARM1);
849 case VF_MIN: r_refdef.x = f[0];
852 case VF_MIN_X: r_refdef.x = k;
854 case VF_MIN_Y: r_refdef.y = k;
856 case VF_SIZE: r_refdef.width = f[0];
857 r_refdef.height = f[1];
859 case VF_SIZE_Y: r_refdef.width = k;
861 case VF_SIZE_X: r_refdef.height = k;
863 case VF_VIEWPORT: r_refdef.x = f[0];
865 f = PRVM_G_VECTOR(OFS_PARM2);
866 r_refdef.width = f[0];
867 r_refdef.height = f[1];
869 case VF_FOV: //r_refdef.fov_x = f[0]; // FIXME!
870 //r_refdef.fov_y = f[1]; // FIXME!
872 case VF_FOVX: //r_refdef.fov_x = k; // FIXME!
874 case VF_FOVY: //r_refdef.fov_y = k; // FIXME!
876 case VF_ORIGIN: VectorCopy(f, csqc_origin);
879 case VF_ORIGIN_X: csqc_origin[0] = k;
882 case VF_ORIGIN_Y: csqc_origin[1] = k;
885 case VF_ORIGIN_Z: csqc_origin[2] = k;
888 case VF_ANGLES: VectorCopy(f, csqc_angles);
891 case VF_ANGLES_X: csqc_angles[0] = k;
894 case VF_ANGLES_Y: csqc_angles[1] = k;
897 case VF_ANGLES_Z: csqc_angles[2] = k;
900 case VF_DRAWWORLD: cl.csqc_vidvars.drawworld = k;
902 case VF_DRAWENGINESBAR: cl.csqc_vidvars.drawenginesbar = k;
904 case VF_DRAWCROSSHAIR: cl.csqc_vidvars.drawcrosshair = k;
907 case VF_CL_VIEWANGLES: VectorCopy(f, cl.viewangles);
909 case VF_CL_VIEWANGLES_X:cl.viewangles[0] = k;
911 case VF_CL_VIEWANGLES_Y:cl.viewangles[1] = k;
913 case VF_CL_VIEWANGLES_Z:cl.viewangles[2] = k;
916 default: Con_Printf("VM_R_SetView : unknown parm %i\n", c);
917 PRVM_G_FLOAT(OFS_RETURN) = 0;
920 PRVM_G_FLOAT(OFS_RETURN) = 1;
923 //#304 void() renderscene (EXT_CSQC)
924 void VM_R_RenderScene (void) //#134
926 VM_SAFEPARMCOUNT(0, VM_R_RenderScene);
930 CSQC_RelinkCSQCEntities();
931 CSQC_RelinkAllEntities(csqc_drawmask);
934 CSQC_R_RenderScene();
937 //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
938 void VM_R_AddDynamicLight (void)
941 matrix4x4_t tempmatrix;
942 VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight);
944 pos = PRVM_G_VECTOR(OFS_PARM0);
945 col = PRVM_G_VECTOR(OFS_PARM2);
946 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
947 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);
948 //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);
951 //============================================================================
953 //#310 vector (vector v) cs_unproject (EXT_CSQC)
954 void VM_CL_unproject (void)
959 VM_SAFEPARMCOUNT(1, VM_CL_unproject);
960 f = PRVM_G_VECTOR(OFS_PARM0);
961 VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.frustum_x * 2.0 / r_refdef.width, f[1] * f[2] * -r_refdef.frustum_y * 2.0 / r_refdef.height);
962 Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, PRVM_G_VECTOR(OFS_RETURN));
965 //#311 vector (vector v) cs_project (EXT_CSQC)
966 void VM_CL_project (void)
972 VM_SAFEPARMCOUNT(1, VM_CL_project);
973 f = PRVM_G_VECTOR(OFS_PARM0);
974 Matrix4x4_Invert_Simple(&m, &r_refdef.viewentitymatrix);
975 Matrix4x4_Transform(&m, f, v);
976 VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.frustum_x*0.5*r_refdef.width, v[2]/v[0]/-r_refdef.frustum_y*r_refdef.height*0.5, v[0]);
979 //#330 float(float stnum) getstatf (EXT_CSQC)
980 void VM_CL_getstatf (void)
988 VM_SAFEPARMCOUNT(1, VM_CL_getstatf);
989 i = PRVM_G_FLOAT(OFS_PARM0);
990 if(i < 0 || i >= MAX_CL_STATS)
992 Con_Printf("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
996 PRVM_G_FLOAT(OFS_RETURN) = dat.f;
999 //#331 float(float stnum) getstati (EXT_CSQC)
1000 void VM_CL_getstati (void)
1003 VM_SAFEPARMCOUNT(1, VM_CL_getstati);
1004 index = PRVM_G_FLOAT(OFS_PARM0);
1006 if(index < 0 || index >= MAX_CL_STATS)
1008 Con_Printf("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
1011 i = cl.stats[index];
1012 PRVM_G_FLOAT(OFS_RETURN) = i;
1015 //#332 string(float firststnum) getstats (EXT_CSQC)
1016 void VM_CL_getstats (void)
1020 VM_SAFEPARMCOUNT(1, VM_CL_getstats);
1021 i = PRVM_G_FLOAT(OFS_PARM0);
1022 if(i < 0 || i > MAX_CL_STATS-4)
1024 Con_Printf("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
1027 t = VM_GetTempString();
1028 strlcpy(t, (char*)&cl.stats[i], 16);
1029 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1032 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
1033 void VM_CL_setmodelindex (void)
1039 VM_SAFEPARMCOUNT(2, VM_CL_setmodelindex);
1041 t = PRVM_G_EDICT(OFS_PARM0);
1042 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1044 t->fields.client->model = 0;
1045 t->fields.client->modelindex = 0;
1053 PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
1054 m = cl.csqc_model_precache[i];
1058 PF_WARNING("VM_CL_setmodelindex >= MAX_MODELS\n");
1060 m = cl.model_precache[i];
1062 PF_WARNING("VM_CL_setmodelindex: null model\n");
1063 t->fields.client->model = PRVM_SetEngineString(m->name);
1064 t->fields.client->modelindex = i;
1067 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
1068 void VM_CL_modelnameforindex (void)
1072 VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
1074 PRVM_G_INT(OFS_RETURN) = 0;
1075 i = PRVM_G_FLOAT(OFS_PARM0);
1080 PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
1081 if(cl.csqc_model_precache[i])
1082 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.csqc_model_precache[i]->name);
1086 PF_WARNING("VM_CL_modelnameforindex >= MAX_MODELS\n");
1087 if(cl.model_precache[i])
1088 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl.model_precache[i]->name);
1091 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
1092 void VM_CL_particleeffectnum (void)
1096 VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
1097 n = PRVM_G_STRING(OFS_PARM0);
1098 for(i=0;i<particleeffects_num;i++)
1099 if(!strcasecmp(particleeffect_names[i], n))
1101 PRVM_G_FLOAT(OFS_RETURN) = i;
1104 PRVM_G_FLOAT(OFS_RETURN) = -1;
1107 void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
1112 // override any beam with the same entity
1113 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1115 if (b->entity == ent && ent)
1118 b->lightning = lightning;
1119 b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1121 b->endtime = cl.time + 0.2;
1122 VectorCopy (start, b->start);
1123 VectorCopy (end, b->end);
1129 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1131 if (!b->model || b->endtime < cl.time)
1134 b->lightning = lightning;
1135 b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1137 b->endtime = cl.time + 0.2;
1138 VectorCopy (start, b->start);
1139 VectorCopy (end, b->end);
1143 Con_Print("beam list overflow!\n");
1146 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
1147 void VM_CL_trailparticles (void)
1152 VM_SAFEPARMCOUNT(4, VM_CL_trailparticles);
1154 entnum = PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
1155 i = PRVM_G_FLOAT(OFS_PARM1);
1156 start = PRVM_G_VECTOR(OFS_PARM2);
1157 end = PRVM_G_VECTOR(OFS_PARM3);
1159 if(i >= particleeffects_num)
1161 if (entnum >= MAX_EDICTS)
1163 Con_Printf("CSQC_ParseBeam: invalid entity number %i\n", entnum);
1166 if (entnum >= cl_max_csqcentities)
1167 CL_ExpandCSQCEntities(entnum);
1169 ent = &cl_csqcentities[entnum];
1172 col = PRVM_G_FLOAT(OFS_PARM4);
1174 col = ent->state_current.glowcolor;
1179 CSQC_ParseBeam(entnum, start, end, cl.model_bolt, true);
1182 CSQC_ParseBeam(entnum, start, end, cl.model_bolt2, true);
1185 CSQC_ParseBeam(entnum, start, end, cl.model_bolt3, false);
1188 CSQC_ParseBeam(entnum, start, end, cl.model_beam, false);
1191 CL_RocketTrail(start, end, i-CSQC_TRAILSTART, col, ent);
1196 //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
1197 void VM_CL_pointparticles (void)
1202 VM_SAFEPARMCOUNT(2, VM_CL_pointparticles);
1203 i = PRVM_G_FLOAT(OFS_PARM0);
1204 f = PRVM_G_VECTOR(OFS_PARM1);
1207 v = PRVM_G_VECTOR(OFS_PARM2);
1208 n = PRVM_G_FLOAT(OFS_PARM3);
1216 if(i >= particleeffects_num)
1224 case TE_GUNSHOTQUAD:
1225 CL_SparkShower(f, v, 15, 1);
1227 if (cl_particles_bulletimpacts.integer)
1231 case TE_SUPERSPIKEQUAD:
1232 CL_SparkShower(f, v, 30, 1);
1234 if (cl_particles_bulletimpacts.integer)
1238 case TE_EXPLOSIONQUAD:
1239 case TE_TEI_BIGEXPLOSION:
1240 CL_ParticleExplosion(f);
1242 case TE_TAREXPLOSION:
1243 CL_BlobExplosion(f);
1246 CL_RunParticleEffect(f, v, 20, 30);
1248 case TE_KNIGHTSPIKE:
1249 CL_RunParticleEffect(f, v, 226, 20);
1255 CL_TeleportSplash(f);
1259 case TE_EXPLOSIONRGB:
1260 CL_ParticleExplosion2(f, v[0], v[1]);
1263 CL_BloodPuff(f, v, n);
1266 CL_SparkShower(f, v, n, 1);
1275 CL_BeamParticle(f, v, 8, 1, 1, 1, 1, 1);
1278 CL_Tei_Smoke(f, v, n);
1280 case TE_TEI_PLASMAHIT:
1281 CL_Tei_PlasmaHit(f, v, n);
1287 //#338 void(string s) cprint (EXT_CSQC)
1288 void VM_CL_centerprint (void)
1290 char s[VM_STRINGTEMP_LENGTH];
1292 VM_SAFEPARMCOUNT(1, VM_CL_centerprint);
1293 VM_VarString(0, s, sizeof(s));
1297 //#342 string(float keynum) getkeybind (EXT_CSQC)
1298 void VM_CL_getkeybind (void)
1302 VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
1303 i = PRVM_G_FLOAT(OFS_PARM0);
1304 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(Key_GetBind(i));
1307 //#343 void(float usecursor) setcursormode (EXT_CSQC)
1308 void VM_CL_setcursormode (void)
1310 VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
1311 cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0);
1312 cl_ignoremousemove = true;
1315 //#345 float(float framenum) getinputstate (EXT_CSQC)
1316 void VM_CL_getinputstate (void)
1319 VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
1320 frame = PRVM_G_FLOAT(OFS_PARM0);
1321 for (i = 0;i < cl.movement_numqueue;i++)
1322 if (cl.movement_queue[i].sequence == frame)
1324 VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
1325 //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
1326 VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
1327 prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
1328 if(cl.movement_queue[i].crouch)
1330 VectorCopy(cl_playercrouchmins, prog->globals.client->pmove_mins);
1331 VectorCopy(cl_playercrouchmaxs, prog->globals.client->pmove_maxs);
1335 VectorCopy(cl_playerstandmins, prog->globals.client->pmove_mins);
1336 VectorCopy(cl_playerstandmaxs, prog->globals.client->pmove_maxs);
1341 //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
1342 void VM_CL_setsensitivityscale (void)
1344 VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
1345 cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
1348 //#347 void() runstandardplayerphysics (EXT_CSQC)
1349 void VM_CL_runplayerphysics (void)
1353 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
1354 void VM_CL_getplayerkey (void)
1361 VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
1363 i = PRVM_G_FLOAT(OFS_PARM0);
1364 c = PRVM_G_STRING(OFS_PARM1);
1365 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
1368 i = Sbar_GetPlayer(i);
1374 if(!strcasecmp(c, "name"))
1375 strcpy(t, cl.scores[i].name);
1377 if(!strcasecmp(c, "frags"))
1378 sprintf(t, "%i", cl.scores[i].frags);
1380 // if(!strcasecmp(c, "ping"))
1381 // sprintf(t, "%i", cl.scores[i].ping);
1383 // if(!strcasecmp(c, "entertime"))
1384 // sprintf(t, "%f", cl.scores[i].entertime);
1386 if(!strcasecmp(c, "colors"))
1387 sprintf(t, "%i", cl.scores[i].colors);
1389 if(!strcasecmp(c, "topcolor"))
1390 sprintf(t, "%i", cl.scores[i].colors & 0xf0);
1392 if(!strcasecmp(c, "bottomcolor"))
1393 sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
1395 if(!strcasecmp(c, "viewentity"))
1396 sprintf(t, "%i", i+1);
1399 temp = VM_GetTempString();
1401 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(temp);
1404 //#349 float() isdemo (EXT_CSQC)
1405 void VM_CL_isdemo (void)
1407 PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
1410 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
1411 void VM_CL_setlistener (void)
1413 VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
1414 Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
1415 csqc_usecsqclistener = true; //use csqc listener at this frame
1418 //#352 void(string cmdname) registercommand (EXT_CSQC)
1419 void VM_CL_registercmd (void)
1422 VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
1423 if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
1425 t = Z_Malloc(strlen(PRVM_G_STRING(OFS_PARM0))+1);
1426 strcpy(t, PRVM_G_STRING(OFS_PARM0));
1427 Cmd_AddCommand(t, NULL);
1430 Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL);
1434 //#354 float() playernum (EXT_CSQC)
1435 void VM_CL_playernum (void)
1439 VM_SAFEPARMCOUNT(0, VM_CL_playernum);
1441 for(i=k=0 ; i<cl.maxclients ; i++)
1442 if(cl.scores[i].name[0])
1444 PRVM_G_FLOAT(OFS_RETURN) = k;
1447 //#355 float() cl_onground (EXT_CSQC)
1448 void VM_CL_onground (void)
1450 PRVM_G_FLOAT(OFS_RETURN) = csqc_onground;
1453 //#360 float() readbyte (EXT_CSQC)
1454 void VM_CL_ReadByte (void)
1456 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
1459 //#361 float() readchar (EXT_CSQC)
1460 void VM_CL_ReadChar (void)
1462 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
1465 //#362 float() readshort (EXT_CSQC)
1466 void VM_CL_ReadShort (void)
1468 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
1471 //#363 float() readlong (EXT_CSQC)
1472 void VM_CL_ReadLong (void)
1474 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
1477 //#364 float() readcoord (EXT_CSQC)
1478 void VM_CL_ReadCoord (void)
1480 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cl.protocol);
1483 //#365 float() readangle (EXT_CSQC)
1484 void VM_CL_ReadAngle (void)
1486 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cl.protocol);
1489 //#366 string() readstring (EXT_CSQC)
1490 void VM_CL_ReadString (void)
1493 t = VM_GetTempString();
1494 s = MSG_ReadString();
1495 PRVM_G_INT(OFS_RETURN) = 0;
1499 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
1503 //#367 float() readfloat (EXT_CSQC)
1504 void VM_CL_ReadFloat (void)
1506 PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
1509 //=================================================================//
1511 // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
1512 void VM_CL_effect (void)
1514 VM_SAFEPARMCOUNT(5, VM_CL_effect);
1515 CL_Effect(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1518 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
1519 void VM_CL_te_blood (void)
1523 VM_SAFEPARMCOUNT(3, VM_CL_te_blood);
1524 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1526 pos = PRVM_G_VECTOR(OFS_PARM0);
1527 CL_FindNonSolidLocation(pos, pos2, 4);
1528 CL_BloodPuff(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
1531 // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
1532 void VM_CL_te_bloodshower (void)
1534 VM_SAFEPARMCOUNT(4, VM_CL_te_bloodshower);
1535 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1537 CL_BloodShower(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3));
1540 // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
1541 void VM_CL_te_explosionrgb (void)
1545 matrix4x4_t tempmatrix;
1546 VM_SAFEPARMCOUNT(2, VM_CL_te_explosionrgb);
1547 pos = PRVM_G_VECTOR(OFS_PARM0);
1548 CL_FindNonSolidLocation(pos, pos2, 10);
1549 CL_ParticleExplosion(pos2);
1550 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1551 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);
1554 // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
1555 void VM_CL_te_particlecube (void)
1557 VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
1558 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1560 CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
1563 // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
1564 void VM_CL_te_particlerain (void)
1566 VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
1567 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1569 CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 0);
1572 // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
1573 void VM_CL_te_particlesnow (void)
1575 VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
1576 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1578 CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4), 1);
1581 // #411 void(vector org, vector vel, float howmany) te_spark
1582 void VM_CL_te_spark (void)
1586 VM_SAFEPARMCOUNT(3, VM_CL_te_spark);
1588 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1590 pos = PRVM_G_VECTOR(OFS_PARM0);
1591 CL_FindNonSolidLocation(pos, pos2, 4);
1592 CL_SparkShower(pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2), 1);
1595 // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
1596 void VM_CL_te_gunshotquad (void)
1600 matrix4x4_t tempmatrix;
1601 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshotquad);
1603 pos = PRVM_G_VECTOR(OFS_PARM0);
1604 CL_FindNonSolidLocation(pos, pos2, 4);
1605 CL_SparkShower(pos2, vec3_origin, 15, 1);
1606 CL_Smoke(pos2, vec3_origin, 15);
1607 CL_BulletMark(pos2);
1608 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1609 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1612 // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
1613 void VM_CL_te_spikequad (void)
1617 matrix4x4_t tempmatrix;
1619 VM_SAFEPARMCOUNT(1, VM_CL_te_spikequad);
1621 pos = PRVM_G_VECTOR(OFS_PARM0);
1622 CL_FindNonSolidLocation(pos, pos2, 4);
1623 if (cl_particles_bulletimpacts.integer)
1625 CL_SparkShower(pos2, vec3_origin, 15, 1);
1626 CL_Smoke(pos2, vec3_origin, 15);
1627 CL_BulletMark(pos2);
1629 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1630 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1631 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1635 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1636 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1637 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1641 // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
1642 void VM_CL_te_superspikequad (void)
1646 matrix4x4_t tempmatrix;
1648 VM_SAFEPARMCOUNT(1, VM_CL_te_superspikequad);
1650 pos = PRVM_G_VECTOR(OFS_PARM0);
1651 CL_FindNonSolidLocation(pos, pos2, 4);
1652 if (cl_particles_bulletimpacts.integer)
1654 CL_SparkShower(pos2, vec3_origin, 30, 1);
1655 CL_Smoke(pos2, vec3_origin, 30);
1656 CL_BulletMark(pos2);
1658 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1659 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1660 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos, 1, 1);
1664 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1665 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1666 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1670 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
1671 void VM_CL_te_explosionquad (void)
1675 matrix4x4_t tempmatrix;
1676 VM_SAFEPARMCOUNT(1, VM_CL_te_explosionquad);
1678 pos = PRVM_G_VECTOR(OFS_PARM0);
1679 CL_FindNonSolidLocation(pos, pos2, 10);
1680 CL_ParticleExplosion(pos2);
1681 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1682 CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1683 if (gamemode != GAME_NEXUIZ)
1684 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1687 // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
1688 void VM_CL_te_smallflash (void)
1692 matrix4x4_t tempmatrix;
1693 VM_SAFEPARMCOUNT(1, VM_CL_te_smallflash);
1695 pos = PRVM_G_VECTOR(OFS_PARM0);
1696 CL_FindNonSolidLocation(pos, pos2, 10);
1697 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1698 CL_AllocDlight(NULL, &tempmatrix, 200, 2, 2, 2, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1701 // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
1702 void VM_CL_te_customflash (void)
1706 matrix4x4_t tempmatrix;
1707 VM_SAFEPARMCOUNT(4, VM_CL_te_customflash);
1709 pos = PRVM_G_VECTOR(OFS_PARM0);
1710 CL_FindNonSolidLocation(pos, pos2, 4);
1711 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1712 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);
1715 // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
1716 void VM_CL_te_gunshot (void)
1720 VM_SAFEPARMCOUNT(1, VM_CL_te_gunshot);
1722 pos = PRVM_G_VECTOR(OFS_PARM0);
1723 CL_FindNonSolidLocation(pos, pos2, 4);
1724 CL_SparkShower(pos2, vec3_origin, 15, 1);
1725 CL_Smoke(pos2, vec3_origin, 15);
1726 CL_BulletMark(pos2);
1729 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
1730 void VM_CL_te_spike (void)
1735 VM_SAFEPARMCOUNT(1, VM_CL_te_spike);
1737 pos = PRVM_G_VECTOR(OFS_PARM0);
1738 CL_FindNonSolidLocation(pos, pos2, 4);
1739 if (cl_particles_bulletimpacts.integer)
1741 CL_SparkShower(pos2, vec3_origin, 15, 1);
1742 CL_Smoke(pos2, vec3_origin, 15);
1743 CL_BulletMark(pos2);
1745 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1749 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1750 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1751 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1755 // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
1756 void VM_CL_te_superspike (void)
1761 VM_SAFEPARMCOUNT(1, VM_CL_te_superspike);
1763 pos = PRVM_G_VECTOR(OFS_PARM0);
1764 CL_FindNonSolidLocation(pos, pos2, 4);
1765 if (cl_particles_bulletimpacts.integer)
1767 CL_SparkShower(pos2, vec3_origin, 30, 1);
1768 CL_Smoke(pos2, vec3_origin, 30);
1769 CL_BulletMark(pos2);
1771 if (rand() % 5) S_StartSound(-1, 0, cl.sfx_tink1, pos2, 1, 1);
1775 if (rnd == 1) S_StartSound(-1, 0, cl.sfx_ric1, pos2, 1, 1);
1776 else if (rnd == 2) S_StartSound(-1, 0, cl.sfx_ric2, pos2, 1, 1);
1777 else S_StartSound(-1, 0, cl.sfx_ric3, pos2, 1, 1);
1781 // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
1782 void VM_CL_te_explosion (void)
1786 matrix4x4_t tempmatrix;
1787 VM_SAFEPARMCOUNT(1, VM_CL_te_explosion);
1789 pos = PRVM_G_VECTOR(OFS_PARM0);
1790 CL_FindNonSolidLocation(pos, pos2, 10);
1791 CL_ParticleExplosion(pos2);
1792 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1793 CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1794 if (gamemode != GAME_NEXUIZ)
1795 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1798 // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
1799 void VM_CL_te_tarexplosion (void)
1803 matrix4x4_t tempmatrix;
1804 VM_SAFEPARMCOUNT(1, VM_CL_te_tarexplosion);
1806 pos = PRVM_G_VECTOR(OFS_PARM0);
1807 CL_FindNonSolidLocation(pos, pos2, 10);
1808 CL_BlobExplosion(pos2);
1809 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1810 CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1811 if (gamemode != GAME_NEXUIZ)
1812 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1815 // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
1816 void VM_CL_te_wizspike (void)
1820 matrix4x4_t tempmatrix;
1821 VM_SAFEPARMCOUNT(1, VM_CL_te_wizspike);
1823 pos = PRVM_G_VECTOR(OFS_PARM0);
1824 CL_FindNonSolidLocation(pos, pos2, 4);
1825 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1826 CL_AllocDlight(NULL, &tempmatrix, 100, 0.12f, 0.50f, 0.12f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1827 CL_RunParticleEffect(pos2, vec3_origin, 20, 30);
1828 S_StartSound(-1, 0, cl.sfx_wizhit, pos2, 1, 1);
1831 // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
1832 void VM_CL_te_knightspike (void)
1836 matrix4x4_t tempmatrix;
1837 VM_SAFEPARMCOUNT(1, VM_CL_te_knightspike);
1839 pos = PRVM_G_VECTOR(OFS_PARM0);
1840 CL_FindNonSolidLocation(pos, pos2, 4);
1841 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1842 CL_AllocDlight(NULL, &tempmatrix, 100, 0.50f, 0.30f, 0.10f, 500, 0.2, 0, -1, false, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1843 CL_RunParticleEffect(pos2, vec3_origin, 226, 20);
1844 S_StartSound(-1, 0, cl.sfx_knighthit, pos2, 1, 1);
1847 // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
1848 void VM_CL_te_lavasplash (void)
1850 VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
1851 CL_LavaSplash(PRVM_G_VECTOR(OFS_PARM0));
1854 // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
1855 void VM_CL_te_teleport (void)
1858 matrix4x4_t tempmatrix;
1859 VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
1861 pos = PRVM_G_VECTOR(OFS_PARM0);
1862 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1863 CL_AllocDlight(NULL, &tempmatrix, 200, 1.0f, 1.0f, 1.0f, 600, 99.0f, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1864 CL_TeleportSplash(pos);
1867 // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
1868 void VM_CL_te_explosion2 (void)
1872 matrix4x4_t tempmatrix;
1873 int colorStart, colorLength;
1874 unsigned char *tempcolor;
1875 VM_SAFEPARMCOUNT(3, VM_CL_te_explosion2);
1877 pos = PRVM_G_VECTOR(OFS_PARM0);
1878 colorStart = PRVM_G_FLOAT(OFS_PARM1);
1879 colorLength = PRVM_G_FLOAT(OFS_PARM2);
1880 CL_FindNonSolidLocation(pos, pos2, 10);
1881 CL_ParticleExplosion2(pos2, colorStart, colorLength);
1882 tempcolor = (unsigned char *)&palette_complete[(rand()%colorLength) + colorStart];
1883 color[0] = tempcolor[0] * (2.0f / 255.0f);
1884 color[1] = tempcolor[1] * (2.0f / 255.0f);
1885 color[2] = tempcolor[2] * (2.0f / 255.0f);
1886 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1887 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);
1888 if (gamemode != GAME_NEXUIZ)
1889 S_StartSound(-1, 0, cl.sfx_r_exp3, pos2, 1, 1);
1893 static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning)
1897 extern entity_t *cl_csqcentities;
1898 extern int cl_max_csqcentities;
1900 if (ent >= cl_max_csqcentities)
1901 CL_ExpandCSQCEntities(ent);
1903 // override any beam with the same entity
1904 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1906 if (b->entity == ent && ent)
1909 b->lightning = lightning;
1910 b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1912 b->endtime = cl.time + 0.2;
1913 VectorCopy (start, b->start);
1914 VectorCopy (end, b->end);
1920 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1922 if (!b->model || b->endtime < cl.time)
1925 b->lightning = lightning;
1926 b->relativestartvalid = (ent && cl_csqcentities[ent].state_current.active) ? 2 : 0;
1928 b->endtime = cl.time + 0.2;
1929 VectorCopy (start, b->start);
1930 VectorCopy (end, b->end);
1934 Con_Print("beam list overflow!\n");
1937 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
1938 void VM_CL_te_lightning1 (void)
1940 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
1941 VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
1944 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
1945 void VM_CL_te_lightning2 (void)
1947 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
1948 VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
1951 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
1952 void VM_CL_te_lightning3 (void)
1954 VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
1955 VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
1958 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
1959 void VM_CL_te_beam (void)
1961 VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
1962 VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
1965 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
1966 void VM_CL_te_plasmaburn (void)
1970 matrix4x4_t tempmatrix;
1971 VM_SAFEPARMCOUNT(1, VM_CL_te_plasmaburn);
1973 pos = PRVM_G_VECTOR(OFS_PARM0);
1974 CL_FindNonSolidLocation(pos, pos2, 4);
1975 Matrix4x4_CreateTranslate(&tempmatrix, pos2[0], pos2[1], pos2[2]);
1976 CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
1977 CL_PlasmaBurn(pos2);
1981 //====================================================================
1984 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out);
1985 static msurface_t *cl_getsurface(prvm_edict_t *ed, int surfacenum)
1988 model_t *model = NULL;
1989 if (!ed || ed->priv.server->free)
1991 modelindex = ed->fields.client->modelindex;
1996 modelindex = -(modelindex+1);
1997 if(modelindex < MAX_MODELS)
1998 model = cl.csqc_model_precache[modelindex];
2002 if(modelindex < MAX_MODELS)
2003 model = cl.model_precache[modelindex];
2007 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2009 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2012 // #434 float(entity e, float s) getsurfacenumpoints
2013 void VM_CL_getsurfacenumpoints(void)
2015 msurface_t *surface;
2016 // return 0 if no such surface
2017 if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2019 PRVM_G_FLOAT(OFS_RETURN) = 0;
2023 // note: this (incorrectly) assumes it is a simple polygon
2024 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2027 // #435 vector(entity e, float s, float n) getsurfacepoint
2028 void VM_CL_getsurfacepoint(void)
2031 msurface_t *surface;
2033 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2034 ed = PRVM_G_EDICT(OFS_PARM0);
2035 if (!ed || ed->priv.server->free)
2037 if (!(surface = cl_getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2039 // note: this (incorrectly) assumes it is a simple polygon
2040 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2041 if (pointnum < 0 || pointnum >= surface->num_vertices)
2043 // FIXME: implement rotation/scaling
2044 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2047 // #436 vector(entity e, float s) getsurfacenormal
2048 void VM_CL_getsurfacenormal(void)
2050 msurface_t *surface;
2052 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2053 if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2055 // FIXME: implement rotation/scaling
2056 // note: this (incorrectly) assumes it is a simple polygon
2057 // note: this only returns the first triangle, so it doesn't work very
2058 // well for curved surfaces or arbitrary meshes
2059 TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2060 VectorNormalize(normal);
2061 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2064 // #437 string(entity e, float s) getsurfacetexture
2065 void VM_CL_getsurfacetexture(void)
2067 msurface_t *surface;
2068 PRVM_G_INT(OFS_RETURN) = 0;
2069 if (!(surface = cl_getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2071 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2074 // #438 float(entity e, vector p) getsurfacenearpoint
2075 void VM_CL_getsurfacenearpoint(void)
2077 int surfacenum, best, modelindex;
2079 vec_t dist, bestdist;
2081 model_t *model = NULL;
2082 msurface_t *surface;
2084 PRVM_G_FLOAT(OFS_RETURN) = -1;
2085 ed = PRVM_G_EDICT(OFS_PARM0);
2086 point = PRVM_G_VECTOR(OFS_PARM1);
2088 if (!ed || ed->priv.server->free)
2090 modelindex = ed->fields.client->modelindex;
2095 modelindex = -(modelindex+1);
2096 if(modelindex < MAX_MODELS)
2097 model = cl.csqc_model_precache[modelindex];
2100 if(modelindex < MAX_MODELS)
2101 model = cl.model_precache[modelindex];
2104 if (!model->num_surfaces)
2107 // FIXME: implement rotation/scaling
2108 VectorSubtract(point, ed->fields.client->origin, p);
2110 bestdist = 1000000000;
2111 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2113 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2114 // first see if the nearest point on the surface's box is closer than the previous match
2115 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2116 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2117 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2118 dist = VectorLength2(clipped);
2119 if (dist < bestdist)
2121 // it is, check the nearest point on the actual geometry
2122 clippointtosurface(surface, p, clipped);
2123 VectorSubtract(clipped, p, clipped);
2124 dist += VectorLength2(clipped);
2125 if (dist < bestdist)
2127 // that's closer too, store it as the best match
2133 PRVM_G_FLOAT(OFS_RETURN) = best;
2136 // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint
2137 void VM_CL_getsurfaceclippedpoint(void)
2140 msurface_t *surface;
2142 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2143 ed = PRVM_G_EDICT(OFS_PARM0);
2144 if (!ed || ed->priv.server->free)
2146 if (!(surface = cl_getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2148 // FIXME: implement rotation/scaling
2149 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p);
2150 clippointtosurface(surface, p, out);
2151 // FIXME: implement rotation/scaling
2152 VectorAdd(out, ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
2155 // #443 void(entity e, entity tagentity, string tagname) setattachment
2156 void VM_CL_setattachment (void)
2158 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2159 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2160 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2165 if (e == prog->edicts)
2166 PF_WARNING("setattachment: can not modify world entity\n");
2167 if (e->priv.server->free)
2168 PF_WARNING("setattachment: can not modify free entity\n");
2170 if (tagentity == NULL)
2171 tagentity = prog->edicts;
2173 v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_entity);
2175 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2177 v = PRVM_GETEDICTFIELDVALUE(e, csqc_fieldoff_tag_index);
2180 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2182 modelindex = (int)tagentity->fields.client->modelindex;
2189 modelindex = -(modelindex+1);
2190 if(modelindex < MAX_MODELS)
2191 model = cl.csqc_model_precache[modelindex];
2194 if(modelindex < MAX_MODELS)
2195 model = cl.model_precache[modelindex];
2200 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.client->skin, tagname);
2202 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);
2205 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));
2209 /////////////////////////////////////////
2210 // DP_MD3_TAGINFO extension coded by VorteX
2212 int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
2217 i = e->fields.client->modelindex;
2226 m = cl.csqc_model_precache[i];
2232 m = cl.model_precache[i];
2234 return Mod_Alias_GetTagIndexForName(m, e->fields.client->skin, tagname);
2237 // Warnings/errors code:
2238 // 0 - normal (everything all-right)
2241 // 3 - null or non-precached model
2242 // 4 - no tags with requested index
2243 // 5 - runaway loop at attachment chain
2244 extern cvar_t cl_bob;
2245 extern cvar_t cl_bobcycle;
2246 extern cvar_t cl_bobup;
2247 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2250 int modelindex, reqframe, attachloop, i;
2251 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2252 prvm_edict_t *attachent;
2255 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2257 if (ent == prog->edicts)
2259 if (ent->priv.server->free)
2262 modelindex = (int)ent->fields.client->modelindex;
2268 modelindex = -(modelindex+1);
2269 if(modelindex >= MAX_MODELS)
2271 model = cl.csqc_model_precache[modelindex];
2274 if(modelindex >= MAX_MODELS)
2277 model = cl.model_precache[modelindex];
2279 if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
2280 reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
2282 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2284 // get initial tag matrix
2287 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2292 Matrix4x4_CreateIdentity(&tagmatrix);
2294 if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict)
2295 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2299 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2300 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_index);
2303 i = attachent->fields.client->modelindex;
2308 model = cl.csqc_model_precache[i];
2312 model = cl.model_precache[i];
2314 if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
2315 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, val->_float - 1, &attachmatrix);
2317 Matrix4x4_CreateIdentity(&attachmatrix);
2319 // apply transformation by child entity matrix
2320 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2321 if (val->_float == 0)
2323 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);
2324 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2325 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]);
2326 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]);
2327 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]);
2328 Matrix4x4_Copy(&tagmatrix, out);
2330 // finally transformate by matrix of tag on parent entity
2331 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2332 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];
2333 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];
2334 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];
2335 Matrix4x4_Copy(&tagmatrix, out);
2339 if (attachloop > 255) // prevent runaway looping
2342 while ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_tag_entity)) && val->edict);
2345 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2346 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2347 if (val->_float == 0)
2349 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2350 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);
2351 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2352 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]);
2353 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]);
2354 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]);
2356 if ((val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_renderflags)) && (RF_VIEWMODEL & (int)val->_float))
2357 {// RENDER_VIEWMODEL magic
2358 Matrix4x4_Copy(&tagmatrix, out);
2360 val = PRVM_GETEDICTFIELDVALUE(ent, csqc_fieldoff_scale);
2361 if (val->_float == 0)
2364 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, csqc_origin[0], csqc_origin[1], csqc_origin[2], csqc_angles[0], csqc_angles[1], csqc_angles[2], val->_float);
2365 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2366 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]);
2367 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]);
2368 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]);
2371 // Cl_bob, ported from rendering code
2372 if (ent->fields.client->health > 0 && cl_bob.value && cl_bobcycle.value)
2375 // LordHavoc: this code is *weird*, but not replacable (I think it
2376 // should be done in QC on the server, but oh well, quake is quake)
2377 // LordHavoc: figured out bobup: the time at which the sin is at 180
2378 // degrees (which allows lengthening or squishing the peak or valley)
2379 cycle = sv.time/cl_bobcycle.value;
2380 cycle -= (int)cycle;
2381 if (cycle < cl_bobup.value)
2382 cycle = sin(M_PI * cycle / cl_bobup.value);
2384 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2385 // bob is proportional to velocity in the xy plane
2386 // (don't count Z, or jumping messes it up)
2387 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;
2388 bob = bob*0.3 + bob*0.7*cycle;
2389 out->m[2][3] += bound(-7, bob, 4);
2396 // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2397 void VM_CL_gettagindex (void)
2399 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2400 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2401 int modelindex, tag_index;
2403 if (ent == prog->edicts)
2404 PF_WARNING("gettagindex: can't affect world entity\n");
2405 if (ent->priv.server->free)
2406 PF_WARNING("gettagindex: can't affect free entity\n");
2408 modelindex = (int)ent->fields.client->modelindex;
2410 modelindex = -(modelindex+1);
2412 if (modelindex <= 0 || modelindex >= MAX_MODELS)
2413 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2416 tag_index = CL_GetTagIndex(ent, tag_name);
2418 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2420 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2423 // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2424 void VM_CL_gettaginfo (void)
2426 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2427 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2428 matrix4x4_t tag_matrix;
2431 returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
2432 Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
2437 PF_WARNING("gettagindex: can't affect world entity\n");
2440 PF_WARNING("gettagindex: can't affect free entity\n");
2443 Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2446 Con_DPrintf("CL_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2449 Con_DPrintf("CL_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2454 //=================================================
2455 //[515]: here goes test/unfinished/etc.
2457 //[515]: check if it is what it should be
2458 void VM_WasFreed (void)
2461 VM_SAFEPARMCOUNT(1, VM_WasFreed);
2463 e = PRVM_G_EDICT(OFS_PARM0);
2464 if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (*prog->time - e->priv.required->freetime) > 0.5 )))
2465 PRVM_G_FLOAT(OFS_RETURN) = false;
2467 PRVM_G_FLOAT(OFS_RETURN) = true;
2470 void VM_CL_select_cube (void)
2474 float *mins2, *maxs2;
2475 prvm_edict_t *ent, *chain;
2476 vec3_t mins1, maxs1;
2478 VM_SAFEPARMCOUNT(2, VM_CL_select_cube);
2480 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2481 if(!prog->flag & PRVM_FE_CHAIN)
2482 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2484 chain_of = PRVM_ED_FindField("chain")->ofs;
2485 chain = prog->edicts;
2487 mins2 = PRVM_G_VECTOR(OFS_PARM0);
2488 maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2490 ent = PRVM_NEXT_EDICT(prog->edicts);
2491 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2493 if (ent->priv.required->free)
2495 VectorCopy(ent->fields.client->origin, mins1);
2496 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2497 VectorAdd(mins1, ent->fields.client->mins, mins1);
2498 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2500 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2502 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2506 VM_RETURN_EDICT(chain);
2509 void VM_CL_select_super (void)
2514 prvm_edict_t *ent, *chain;
2515 vec3_t mins1, maxs1;
2517 VM_SAFEPARMCOUNT(8, VM_findchain);
2519 v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3);
2521 // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another
2522 if(!prog->flag & PRVM_FE_CHAIN)
2523 PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME);
2525 chain_of = PRVM_ED_FindField("chain")->ofs;
2526 chain = prog->edicts;
2528 mins2 = PRVM_G_VECTOR(OFS_PARM0);
2529 maxs2 = PRVM_G_VECTOR(OFS_PARM1);
2531 ent = PRVM_NEXT_EDICT(prog->edicts);
2532 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
2534 if (ent->priv.required->free)
2536 VectorCopy(ent->fields.client->origin, mins1);
2537 VectorAdd(mins1, ent->fields.client->maxs, maxs1);
2538 VectorAdd(mins1, ent->fields.client->mins, mins1);
2539 if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2])
2541 if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2])
2543 PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
2547 VM_RETURN_EDICT(chain);*/
2550 static int Is_Text_Color (char c, char t)
2553 char c2 = c - (c & 128);
2554 char t2 = t - (t & 128);
2556 if(c != '^' && c2 != '^') return 0;
2557 if(t >= '0' && t <= '9') a = 1;
2558 if(t2 >= '0' && t2 <= '9') a = 1;
2559 /* if(t >= 'A' && t <= 'Z') a = 2;
2560 if(t2 >= 'A' && t2 <= 'Z') a = 2;
2562 if(a == 1 && scr_colortext.integer > 0)
2564 if(a == 2 && scr_multifonts.integer > 0)
2570 void VM_uncolorstring (void) //#170
2576 VM_SAFEPARMCOUNT(1, VM_uncolorstring);
2577 in = PRVM_G_STRING(OFS_PARM0);
2579 PRVM_ERROR ("VM_uncolorstring: %s: NULL\n", PRVM_NAME);
2580 VM_CheckEmptyString (in);
2581 out = VM_GetTempString();
2586 if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
2597 void VM_CL_selecttraceline (void)
2600 int ent, ignore, csqcents;
2602 v1 = PRVM_G_VECTOR(OFS_PARM0);
2603 v2 = PRVM_G_VECTOR(OFS_PARM1);
2604 ignore = PRVM_G_FLOAT(OFS_PARM2);
2605 csqcents = PRVM_G_FLOAT(OFS_PARM3);
2608 if((csqcents && ignore > cl_num_csqcentities) || (!csqcents && ignore > cl_num_entities))
2610 Con_Printf("VM_CL_selecttraceline: out of entities\n");
2615 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);
2617 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);
2618 PRVM_G_FLOAT(OFS_RETURN) = ent;
2621 void VM_charindex (void)
2624 s = PRVM_G_STRING(OFS_PARM0);
2627 if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s))
2629 PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)];
2632 //#223 string(float c, ...) chr2str (FTE_STRINGS)
2633 void VM_chr2str (void)
2637 t = VM_GetTempString();
2638 for(i=0;i<prog->argc;i++)
2639 t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
2641 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(t);
2644 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2645 void VM_strncmp (void)
2647 const char *s1, *s2;
2648 VM_SAFEPARMCOUNT(1, VM_strncmp);
2649 s1 = PRVM_G_STRING(OFS_PARM0);
2650 s2 = PRVM_G_STRING(OFS_PARM1);
2651 PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
2654 //============================================================================
2655 //============================================================================
2657 prvm_builtin_t vm_cl_builtins[] = {
2658 0, // to be consistent with the old vm
2659 VM_CL_makevectors, // #1 void(vector ang) makevectors
2660 VM_CL_setorigin, // #2 void(entity e, vector o) setorigin
2661 VM_CL_setmodel, // #3 void(entity e, string m) setmodel
2662 VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize
2664 VM_break, // #6 void() break
2665 VM_random, // #7 float() random
2666 VM_CL_sound, // #8 void(entity e, float chan, string samp) sound
2667 VM_normalize, // #9 vector(vector v) normalize
2668 VM_error, // #10 void(string e) error
2669 VM_objerror, // #11 void(string e) objerror
2670 VM_vlen, // #12 float(vector v) vlen
2671 VM_vectoyaw, // #13 float(vector v) vectoyaw
2672 VM_CL_spawn, // #14 entity() spawn
2673 VM_remove, // #15 void(entity e) remove
2674 VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2676 VM_find, // #18 entity(entity start, .string fld, string match) find
2677 VM_CL_precache_sound, // #19 void(string s) precache_sound
2678 VM_CL_precache_model, // #20 void(string s) precache_model
2680 VM_CL_findradius, // #22 entity(vector org, float rad) findradius
2683 VM_dprint, // #25 void(string s) dprint
2684 VM_ftos, // #26 void(string s) ftos
2685 VM_vtos, // #27 void(string s) vtos
2686 VM_coredump, // #28 void() coredump
2687 VM_traceon, // #29 void() traceon
2688 VM_traceoff, // #30 void() traceoff
2689 VM_eprint, // #31 void(entity e) eprint
2692 VM_CL_droptofloor, // #34 float() droptofloor
2693 VM_CL_lightstyle, // #35 void(float style, string value) lightstyle
2694 VM_rint, // #36 float(float v) rint
2695 VM_floor, // #37 float(float v) floor
2696 VM_ceil, // #38 float(float v) ceil
2698 VM_CL_checkbottom, // #40 float(entity e) checkbottom
2699 VM_CL_pointcontents, // #41 float(vector v) pointcontents
2701 VM_fabs, // #43 float(float f) fabs
2703 VM_cvar, // #45 float(string s) cvar
2704 VM_localcmd, // #46 void(string s) localcmd
2705 VM_nextent, // #47 entity(entity e) nextent
2706 VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle
2707 VM_CL_changeyaw, // #49 void(entity ent, float ideal_yaw, float speed_yaw) ChangeYaw
2709 VM_vectoangles, // #51 vector(vector v) vectoangles
2710 0, // #52 void(float to, float f) WriteByte
2711 0, // #53 void(float to, float f) WriteChar
2712 0, // #54 void(float to, float f) WriteShort
2713 0, // #55 void(float to, float f) WriteLong
2714 0, // #56 void(float to, float f) WriteCoord
2715 0, // #57 void(float to, float f) WriteAngle
2716 0, // #58 void(float to, string s) WriteString
2718 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2719 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2720 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2721 VM_CL_changepitch, // #63 void(entity ent, float ideal_pitch, float speed_pitch) changepitch (DP_QC_CHANGEPITCH)
2722 VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2723 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2730 VM_cvar_set, // #72 void(string var, string val) cvar_set
2732 VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2733 VM_CL_precache_model, // #75 string(string s) precache_model2
2734 VM_CL_precache_sound, // #76 string(string s) precache_sound2
2739 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2748 VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2749 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2750 VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2751 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2752 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2753 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2754 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2755 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2756 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2757 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2768 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2769 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2770 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2771 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2772 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2773 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2774 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2775 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2776 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2777 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2779 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2789 VM_bitshift, //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2793 VM_charindex, //#222 float(string str, float ofs) str2chr (FTE_STRINGS)
2794 VM_chr2str, //#223 string(float c, ...) chr2str (FTE_STRINGS)
2799 VM_strncmp, //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2801 e10, e10, e10, e10, e10, e10, e10, // #230-299
2803 //======CSQC start=======//
2804 //3d world (buffer/buffering) operations
2805 VM_R_ClearScene, //#300 void() clearscene (EXT_CSQC)
2806 VM_R_AddEntities, //#301 void(float mask) addentities (EXT_CSQC)
2807 VM_R_AddEntity, //#302 void(entity ent) addentity (EXT_CSQC)
2808 VM_R_SetView, //#303 float(float property, ...) setproperty (EXT_CSQC)
2809 VM_R_RenderScene, //#304 void() renderscene (EXT_CSQC)
2810 VM_R_AddDynamicLight, //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2811 VM_R_PolygonBegin, //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2812 VM_R_PolygonVertex, //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2813 VM_R_PolygonEnd, //#308 void() R_EndPolygon
2816 //maths stuff that uses the current view settings
2817 VM_CL_unproject, //#310 vector (vector v) cs_unproject (EXT_CSQC)
2818 VM_CL_project, //#311 vector (vector v) cs_project (EXT_CSQC)
2823 //2d (immediate) operations
2824 VM_drawline, //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2825 VM_iscachedpic, //#316 float(string name) iscachedpic (EXT_CSQC)
2826 VM_precache_pic, //#317 string(string name, float trywad) precache_pic (EXT_CSQC)
2827 VM_getimagesize, //#318 vector(string picname) draw_getimagesize (EXT_CSQC)
2828 VM_freepic, //#319 void(string name) freepic (EXT_CSQC)
2829 VM_drawcharacter, //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
2830 VM_drawstring, //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
2831 VM_drawpic, //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
2832 VM_drawfill, //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
2833 VM_drawsetcliparea, //#324 void(float x, float y, float width, float height) drawsetcliparea
2834 VM_drawresetcliparea, //#325 void(void) drawresetcliparea
2840 VM_CL_getstatf, //#330 float(float stnum) getstatf (EXT_CSQC)
2841 VM_CL_getstati, //#331 float(float stnum) getstati (EXT_CSQC)
2842 VM_CL_getstats, //#332 string(float firststnum) getstats (EXT_CSQC)
2843 VM_CL_setmodelindex, //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2844 VM_CL_modelnameforindex, //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2845 VM_CL_particleeffectnum, //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2846 VM_CL_trailparticles, //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2847 VM_CL_pointparticles, //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
2848 VM_CL_centerprint, //#338 void(string s) cprint (EXT_CSQC)
2849 VM_print, //#339 void(string s) print (EXT_CSQC)
2850 VM_keynumtostring, //#340 string(float keynum) keynumtostring (EXT_CSQC)
2851 VM_stringtokeynum, //#341 float(string keyname) stringtokeynum (EXT_CSQC)
2852 VM_CL_getkeybind, //#342 string(float keynum) getkeybind (EXT_CSQC)
2853 VM_CL_setcursormode, //#343 void(float usecursor) setcursormode (EXT_CSQC)
2854 VM_getmousepos, //#344 vector() getmousepos (EXT_CSQC)
2855 VM_CL_getinputstate, //#345 float(float framenum) getinputstate (EXT_CSQC)
2856 VM_CL_setsensitivityscale, //#346 void(float sens) setsensitivityscaler (EXT_CSQC)
2857 VM_CL_runplayerphysics, //#347 void() runstandardplayerphysics (EXT_CSQC)
2858 VM_CL_getplayerkey, //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
2859 VM_CL_isdemo, //#349 float() isdemo (EXT_CSQC)
2860 VM_isserver, //#350 float() isserver (EXT_CSQC)
2861 VM_CL_setlistener, //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
2862 VM_CL_registercmd, //#352 void(string cmdname) registercommand (EXT_CSQC)
2863 VM_WasFreed, //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
2864 VM_CL_playernum, //#354 float() playernum
2865 VM_CL_onground, //#355 float() cl_onground (EXT_CSQC)
2866 VM_charindex, //#356 float(string s, float num) charindex
2867 VM_CL_selecttraceline, //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline
2870 VM_CL_ReadByte, //#360 float() readbyte (EXT_CSQC)
2871 VM_CL_ReadChar, //#361 float() readchar (EXT_CSQC)
2872 VM_CL_ReadShort, //#362 float() readshort (EXT_CSQC)
2873 VM_CL_ReadLong, //#363 float() readlong (EXT_CSQC)
2874 VM_CL_ReadCoord, //#364 float() readcoord (EXT_CSQC)
2875 VM_CL_ReadAngle, //#365 float() readangle (EXT_CSQC)
2876 VM_CL_ReadString, //#366 string() readstring (EXT_CSQC)
2877 VM_CL_ReadFloat, //#367 float() readfloat (EXT_CSQC)
2910 //=========CSQC end========//
2912 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2914 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2915 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2916 VM_CL_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2917 VM_CL_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2918 VM_CL_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2919 VM_CL_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2920 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)
2921 VM_CL_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2922 VM_CL_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2923 VM_CL_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2924 VM_CL_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2925 VM_CL_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2926 VM_CL_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2927 VM_CL_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2928 VM_CL_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2929 VM_CL_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2930 VM_CL_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2931 VM_CL_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2932 VM_CL_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2933 VM_CL_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2934 VM_CL_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2935 VM_CL_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2936 VM_CL_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2937 VM_CL_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2938 VM_CL_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2939 VM_CL_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2940 VM_CL_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2941 VM_CL_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2942 VM_CL_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2943 VM_CL_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2944 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2945 VM_CL_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2946 VM_CL_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2947 VM_CL_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2948 VM_CL_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2949 VM_CL_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2950 VM_CL_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2951 VM_CL_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2953 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2954 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2955 VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2956 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2957 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2958 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2959 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2960 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2961 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2962 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2963 VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2964 VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2972 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2973 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2974 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2975 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2976 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2977 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2978 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2979 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2980 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2981 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2982 e10, e10, e10 // #470-499 (LordHavoc)
2985 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
2987 void VM_CL_Cmd_Init(void)
2991 void VM_CL_Cmd_Reset(void)