3 //============================================================================
8 char *vm_sv_extensions =
13 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
37 "DP_GFX_EXTERNALTEXTURES_PERMAP "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
51 "DP_QC_ASINACOSATANATAN2TAN "
57 "DP_QC_FINDCHAINFLAGS "
58 "DP_QC_FINDCHAINFLOAT "
66 "DP_QC_MULTIPLETEMPSTRINGS "
68 "DP_QC_SINCOSSQRTPOW "
70 "DP_QC_STRING_CASE_FUNCTIONS "
71 "DP_QC_STRINGBUFFERS "
72 "DP_QC_STRINGCOLORFUNCTIONS "
73 "DP_QC_TOKENIZEBYSEPARATOR "
76 "DP_QC_TRACE_MOVETYPE_HITMODEL "
77 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
78 "DP_QC_UNLIMITEDTEMPSTRINGS "
79 "DP_QC_VECTORVECTORS "
85 "DP_SND_DIRECTIONLESSATTNNONE "
94 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
95 "DP_SV_DRAWONLYTOCLIENT "
98 "DP_SV_ENTITYCONTENTSTRANSITION "
99 "DP_SV_MODELFLAGS_AS_EFFECTS "
101 "DP_SV_NODRAWTOCLIENT "
103 "DP_SV_PLAYERPHYSICS "
104 "DP_SV_PRECACHEANYTIME "
107 "DP_SV_ROTATINGBMODEL "
110 "DP_SV_WRITEUNTERMINATEDSTRING "
114 "DP_TE_EXPLOSIONRGB "
116 "DP_TE_PARTICLECUBE "
117 "DP_TE_PARTICLERAIN "
118 "DP_TE_PARTICLESNOW "
120 "DP_TE_QUADEFFECTS1 "
123 "DP_TE_STANDARDEFFECTBUILTINS "
124 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
127 //"EXT_CSQC " // not ready yet
129 "KRIMZON_SV_PARSECLIENTCOMMAND "
132 "NEXUIZ_PLAYERMODEL "
134 "PRYDON_CLIENTCURSOR "
135 "TENEBRAE_GFX_DLIGHTS "
145 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
147 setorigin (entity, origin)
150 static void VM_SV_setorigin (void)
155 VM_SAFEPARMCOUNT(2, VM_setorigin);
157 e = PRVM_G_EDICT(OFS_PARM0);
158 if (e == prog->edicts)
160 VM_Warning("setorigin: can not modify world entity\n");
163 if (e->priv.server->free)
165 VM_Warning("setorigin: can not modify free entity\n");
168 org = PRVM_G_VECTOR(OFS_PARM1);
169 VectorCopy (org, e->fields.server->origin);
170 SV_LinkEdict (e, false);
174 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
178 for (i=0 ; i<3 ; i++)
180 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
182 // set derived values
183 VectorCopy (min, e->fields.server->mins);
184 VectorCopy (max, e->fields.server->maxs);
185 VectorSubtract (max, min, e->fields.server->size);
187 SV_LinkEdict (e, false);
194 the size box is rotated by the current angle
195 LordHavoc: no it isn't...
197 setsize (entity, minvector, maxvector)
200 static void VM_SV_setsize (void)
205 VM_SAFEPARMCOUNT(3, VM_setsize);
207 e = PRVM_G_EDICT(OFS_PARM0);
208 if (e == prog->edicts)
210 VM_Warning("setsize: can not modify world entity\n");
213 if (e->priv.server->free)
215 VM_Warning("setsize: can not modify free entity\n");
218 min = PRVM_G_VECTOR(OFS_PARM1);
219 max = PRVM_G_VECTOR(OFS_PARM2);
220 SetMinMaxSize (e, min, max, false);
228 setmodel(entity, model)
231 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
232 static void VM_SV_setmodel (void)
238 VM_SAFEPARMCOUNT(2, VM_setmodel);
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning("setmodel: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning("setmodel: can not modify free entity\n");
251 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
252 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
253 e->fields.server->modelindex = i;
259 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
260 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
262 SetMinMaxSize (e, quakemins, quakemaxs, true);
265 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
272 single print to a specific client
274 sprint(clientent, value)
277 static void VM_SV_sprint (void)
281 char string[VM_STRINGTEMP_LENGTH];
283 VM_VarString(1, string, sizeof(string));
285 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
287 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
288 // LordHavoc: div0 requested that sprintto world operate like print
295 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
297 VM_Warning("tried to centerprint to a non-client\n");
301 client = svs.clients + entnum-1;
302 if (!client->netconnection)
305 MSG_WriteChar(&client->netconnection->message,svc_print);
306 MSG_WriteString(&client->netconnection->message, string);
314 single print to a specific client
316 centerprint(clientent, value)
319 static void VM_SV_centerprint (void)
323 char string[VM_STRINGTEMP_LENGTH];
325 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
327 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
329 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
331 VM_Warning("tried to centerprint to a non-client\n");
335 client = svs.clients + entnum-1;
336 if (!client->netconnection)
339 VM_VarString(1, string, sizeof(string));
340 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
341 MSG_WriteString(&client->netconnection->message, string);
348 particle(origin, color, count)
351 static void VM_SV_particle (void)
357 VM_SAFEPARMCOUNT(4, VM_SV_particle);
359 org = PRVM_G_VECTOR(OFS_PARM0);
360 dir = PRVM_G_VECTOR(OFS_PARM1);
361 color = PRVM_G_FLOAT(OFS_PARM2);
362 count = PRVM_G_FLOAT(OFS_PARM3);
363 SV_StartParticle (org, dir, (int)color, (int)count);
373 static void VM_SV_ambientsound (void)
377 float vol, attenuation;
380 VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
382 pos = PRVM_G_VECTOR (OFS_PARM0);
383 samp = PRVM_G_STRING(OFS_PARM1);
384 vol = PRVM_G_FLOAT(OFS_PARM2);
385 attenuation = PRVM_G_FLOAT(OFS_PARM3);
387 // check to see if samp was properly precached
388 soundnum = SV_SoundIndex(samp, 1);
396 // add an svc_spawnambient command to the level signon packet
399 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
401 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
403 MSG_WriteVector(&sv.signon, pos, sv.protocol);
406 MSG_WriteShort (&sv.signon, soundnum);
408 MSG_WriteByte (&sv.signon, soundnum);
410 MSG_WriteByte (&sv.signon, (int)(vol*255));
411 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
419 Each entity can have eight independant sound sources, like voice,
422 Channel 0 is an auto-allocate channel, the others override anything
423 already running on that entity/channel pair.
425 An attenuation of 0 will play full volume everywhere in the level.
426 Larger attenuations will drop off.
430 static void VM_SV_sound (void)
434 prvm_edict_t *entity;
438 VM_SAFEPARMCOUNT(5, VM_SV_sound);
440 entity = PRVM_G_EDICT(OFS_PARM0);
441 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
442 sample = PRVM_G_STRING(OFS_PARM2);
443 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
444 attenuation = PRVM_G_FLOAT(OFS_PARM4);
446 if (volume < 0 || volume > 255)
448 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
452 if (attenuation < 0 || attenuation > 4)
454 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
458 if (channel < 0 || channel > 7)
460 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
464 SV_StartSound (entity, channel, sample, volume, attenuation);
471 Used for use tracing and shot targeting
472 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
473 if the tryents flag is set.
475 traceline (vector1, vector2, movetype, ignore)
478 static void VM_SV_traceline (void)
485 VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
487 prog->xfunction->builtinsprofile += 30;
489 v1 = PRVM_G_VECTOR(OFS_PARM0);
490 v2 = PRVM_G_VECTOR(OFS_PARM1);
491 move = (int)PRVM_G_FLOAT(OFS_PARM2);
492 ent = PRVM_G_EDICT(OFS_PARM3);
494 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
495 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
497 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
499 VM_SetTraceGlobals(&trace);
507 Used for use tracing and shot targeting
508 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
509 if the tryents flag is set.
511 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
514 // LordHavoc: added this for my own use, VERY useful, similar to traceline
515 static void VM_SV_tracebox (void)
517 float *v1, *v2, *m1, *m2;
522 VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
524 prog->xfunction->builtinsprofile += 30;
526 v1 = PRVM_G_VECTOR(OFS_PARM0);
527 m1 = PRVM_G_VECTOR(OFS_PARM1);
528 m2 = PRVM_G_VECTOR(OFS_PARM2);
529 v2 = PRVM_G_VECTOR(OFS_PARM3);
530 move = (int)PRVM_G_FLOAT(OFS_PARM4);
531 ent = PRVM_G_EDICT(OFS_PARM5);
533 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
534 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
536 trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
538 VM_SetTraceGlobals(&trace);
541 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
546 vec3_t original_origin;
547 vec3_t original_velocity;
548 vec3_t original_angles;
549 vec3_t original_avelocity;
553 VectorCopy(tossent->fields.server->origin , original_origin );
554 VectorCopy(tossent->fields.server->velocity , original_velocity );
555 VectorCopy(tossent->fields.server->angles , original_angles );
556 VectorCopy(tossent->fields.server->avelocity, original_avelocity);
558 val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
559 if (val != NULL && val->_float != 0)
560 gravity = val->_float;
563 gravity *= sv_gravity.value * 0.05;
565 for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
567 SV_CheckVelocity (tossent);
568 tossent->fields.server->velocity[2] -= gravity;
569 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
570 VectorScale (tossent->fields.server->velocity, 0.05, move);
571 VectorAdd (tossent->fields.server->origin, move, end);
572 trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
573 VectorCopy (trace.endpos, tossent->fields.server->origin);
575 if (trace.fraction < 1)
579 VectorCopy(original_origin , tossent->fields.server->origin );
580 VectorCopy(original_velocity , tossent->fields.server->velocity );
581 VectorCopy(original_angles , tossent->fields.server->angles );
582 VectorCopy(original_avelocity, tossent->fields.server->avelocity);
587 static void VM_SV_tracetoss (void)
591 prvm_edict_t *ignore;
593 VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
595 prog->xfunction->builtinsprofile += 600;
597 ent = PRVM_G_EDICT(OFS_PARM0);
598 if (ent == prog->edicts)
600 VM_Warning("tracetoss: can not use world entity\n");
603 ignore = PRVM_G_EDICT(OFS_PARM1);
605 trace = SV_Trace_Toss (ent, ignore);
607 VM_SetTraceGlobals(&trace);
610 //============================================================================
612 static int checkpvsbytes;
613 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
615 static int VM_SV_newcheckclient (int check)
621 // cycle to the next one
623 check = bound(1, check, svs.maxclients);
624 if (check == svs.maxclients)
632 prog->xfunction->builtinsprofile++;
634 if (i == svs.maxclients+1)
636 // look up the client's edict
637 ent = PRVM_EDICT_NUM(i);
638 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
639 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
641 // found a valid client (possibly the same one again)
645 // get the PVS for the entity
646 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
648 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
649 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
658 Returns a client (or object that has a client enemy) that would be a
661 If there is more than one valid option, they are cycled each frame
663 If (self.origin + self.viewofs) is not in the PVS of the current target,
664 it is not returned at all.
669 int c_invis, c_notvis;
670 static void VM_SV_checkclient (void)
672 prvm_edict_t *ent, *self;
675 VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
677 // find a new check if on a new frame
678 if (sv.time - sv.lastchecktime >= 0.1)
680 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
681 sv.lastchecktime = sv.time;
684 // return check if it might be visible
685 ent = PRVM_EDICT_NUM(sv.lastcheck);
686 if (ent->priv.server->free || ent->fields.server->health <= 0)
688 VM_RETURN_EDICT(prog->edicts);
692 // if current entity can't possibly see the check entity, return 0
693 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
694 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
695 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
698 VM_RETURN_EDICT(prog->edicts);
702 // might be able to see it
704 VM_RETURN_EDICT(ent);
707 //============================================================================
714 Sends text over to the client's execution buffer
716 stuffcmd (clientent, value, ...)
719 static void VM_SV_stuffcmd (void)
723 char string[VM_STRINGTEMP_LENGTH];
725 VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
727 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
728 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
730 VM_Warning("Can't stuffcmd to a non-client\n");
734 VM_VarString(1, string, sizeof(string));
737 host_client = svs.clients + entnum-1;
738 Host_ClientCommands ("%s", string);
746 Returns a chain of entities that have origins within a spherical area
748 findradius (origin, radius)
751 static void VM_SV_findradius (void)
753 prvm_edict_t *ent, *chain;
754 vec_t radius, radius2;
755 vec3_t org, eorg, mins, maxs;
758 prvm_edict_t *touchedicts[MAX_EDICTS];
760 VM_SAFEPARMCOUNT(2, VM_SV_findradius);
762 chain = (prvm_edict_t *)prog->edicts;
764 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
765 radius = PRVM_G_FLOAT(OFS_PARM1);
766 radius2 = radius * radius;
768 mins[0] = org[0] - (radius + 1);
769 mins[1] = org[1] - (radius + 1);
770 mins[2] = org[2] - (radius + 1);
771 maxs[0] = org[0] + (radius + 1);
772 maxs[1] = org[1] + (radius + 1);
773 maxs[2] = org[2] + (radius + 1);
774 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
775 if (numtouchedicts > MAX_EDICTS)
777 // this never happens
778 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
779 numtouchedicts = MAX_EDICTS;
781 for (i = 0;i < numtouchedicts;i++)
783 ent = touchedicts[i];
784 prog->xfunction->builtinsprofile++;
785 // Quake did not return non-solid entities but darkplaces does
786 // (note: this is the reason you can't blow up fallen zombies)
787 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
789 // LordHavoc: compare against bounding box rather than center so it
790 // doesn't miss large objects, and use DotProduct instead of Length
791 // for a major speedup
792 VectorSubtract(org, ent->fields.server->origin, eorg);
793 if (sv_gameplayfix_findradiusdistancetobox.integer)
795 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
796 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
797 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
800 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
801 if (DotProduct(eorg, eorg) < radius2)
803 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
808 VM_RETURN_EDICT(chain);
811 static void VM_SV_precache_sound (void)
813 VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
814 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
815 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
818 static void VM_SV_precache_model (void)
820 VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
821 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
822 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
829 float(float yaw, float dist[, settrace]) walkmove
832 static void VM_SV_walkmove (void)
841 VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
843 // assume failure if it returns early
844 PRVM_G_FLOAT(OFS_RETURN) = 0;
846 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
847 if (ent == prog->edicts)
849 VM_Warning("walkmove: can not modify world entity\n");
852 if (ent->priv.server->free)
854 VM_Warning("walkmove: can not modify free entity\n");
857 yaw = PRVM_G_FLOAT(OFS_PARM0);
858 dist = PRVM_G_FLOAT(OFS_PARM1);
859 settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
861 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
864 yaw = yaw*M_PI*2 / 360;
866 move[0] = cos(yaw)*dist;
867 move[1] = sin(yaw)*dist;
870 // save program state, because SV_movestep may call other progs
871 oldf = prog->xfunction;
872 oldself = prog->globals.server->self;
874 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
877 // restore program state
878 prog->xfunction = oldf;
879 prog->globals.server->self = oldself;
889 static void VM_SV_droptofloor (void)
895 VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
897 // assume failure if it returns early
898 PRVM_G_FLOAT(OFS_RETURN) = 0;
900 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
901 if (ent == prog->edicts)
903 VM_Warning("droptofloor: can not modify world entity\n");
906 if (ent->priv.server->free)
908 VM_Warning("droptofloor: can not modify free entity\n");
912 VectorCopy (ent->fields.server->origin, end);
915 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
917 if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
919 if (trace.fraction < 1)
920 VectorCopy (trace.endpos, ent->fields.server->origin);
921 SV_LinkEdict (ent, false);
922 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
923 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
924 PRVM_G_FLOAT(OFS_RETURN) = 1;
925 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
926 ent->priv.server->suspendedinairflag = true;
934 void(float style, string value) lightstyle
937 static void VM_SV_lightstyle (void)
944 VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
946 style = (int)PRVM_G_FLOAT(OFS_PARM0);
947 val = PRVM_G_STRING(OFS_PARM1);
949 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
950 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
953 // change the string in sv
954 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
956 // send message to all clients on this server
957 if (sv.state != ss_active)
960 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
962 if (client->active && client->netconnection)
964 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
965 MSG_WriteChar (&client->netconnection->message,style);
966 MSG_WriteString (&client->netconnection->message, val);
976 static void VM_SV_checkbottom (void)
978 VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
979 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
987 static void VM_SV_pointcontents (void)
989 VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
990 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
997 Pick a vector for the player to shoot along
998 vector aim(entity, missilespeed)
1001 static void VM_SV_aim (void)
1003 prvm_edict_t *ent, *check, *bestent;
1004 vec3_t start, dir, end, bestdir;
1007 float dist, bestdist;
1010 VM_SAFEPARMCOUNT(2, VM_SV_aim);
1012 // assume failure if it returns early
1013 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1014 // if sv_aim is so high it can't possibly accept anything, skip out early
1015 if (sv_aim.value >= 1)
1018 ent = PRVM_G_EDICT(OFS_PARM0);
1019 if (ent == prog->edicts)
1021 VM_Warning("aim: can not use world entity\n");
1024 if (ent->priv.server->free)
1026 VM_Warning("aim: can not use free entity\n");
1029 speed = PRVM_G_FLOAT(OFS_PARM1);
1031 VectorCopy (ent->fields.server->origin, start);
1034 // try sending a trace straight
1035 VectorCopy (prog->globals.server->v_forward, dir);
1036 VectorMA (start, 2048, dir, end);
1037 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1038 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1039 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1041 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1046 // try all possible entities
1047 VectorCopy (dir, bestdir);
1048 bestdist = sv_aim.value;
1051 check = PRVM_NEXT_EDICT(prog->edicts);
1052 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1054 prog->xfunction->builtinsprofile++;
1055 if (check->fields.server->takedamage != DAMAGE_AIM)
1059 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1060 continue; // don't aim at teammate
1061 for (j=0 ; j<3 ; j++)
1062 end[j] = check->fields.server->origin[j]
1063 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1064 VectorSubtract (end, start, dir);
1065 VectorNormalize (dir);
1066 dist = DotProduct (dir, prog->globals.server->v_forward);
1067 if (dist < bestdist)
1068 continue; // to far to turn
1069 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1070 if (tr.ent == check)
1071 { // can shoot at this one
1079 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1080 dist = DotProduct (dir, prog->globals.server->v_forward);
1081 VectorScale (prog->globals.server->v_forward, dist, end);
1083 VectorNormalize (end);
1084 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1088 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1093 ===============================================================================
1097 ===============================================================================
1100 #define MSG_BROADCAST 0 // unreliable to all
1101 #define MSG_ONE 1 // reliable to one (msg_entity)
1102 #define MSG_ALL 2 // reliable to all
1103 #define MSG_INIT 3 // write to the init string
1104 #define MSG_ENTITY 5
1106 sizebuf_t *WriteDest (void)
1112 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1116 return &sv.datagram;
1119 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1120 entnum = PRVM_NUM_FOR_EDICT(ent);
1121 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1123 VM_Warning ("WriteDest: tried to write to non-client\n");
1124 return &sv.reliable_datagram;
1127 return &svs.clients[entnum-1].netconnection->message;
1130 VM_Warning ("WriteDest: bad destination\n");
1132 return &sv.reliable_datagram;
1138 return sv.writeentitiestoclient_msg;
1144 static void VM_SV_WriteByte (void)
1146 VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1147 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1150 static void VM_SV_WriteChar (void)
1152 VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1153 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1156 static void VM_SV_WriteShort (void)
1158 VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1159 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1162 static void VM_SV_WriteLong (void)
1164 VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1165 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1168 static void VM_SV_WriteAngle (void)
1170 VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1171 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1174 static void VM_SV_WriteCoord (void)
1176 VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1177 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1180 static void VM_SV_WriteString (void)
1182 VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1183 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1186 static void VM_SV_WriteUnterminatedString (void)
1188 VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1189 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1193 static void VM_SV_WriteEntity (void)
1195 VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1196 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1199 //////////////////////////////////////////////////////////
1201 static void VM_SV_makestatic (void)
1206 // allow 0 parameters due to an id1 qc bug in which this function is used
1207 // with no parameters (but directly after setmodel with self in OFS_PARM0)
1208 VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1210 if (prog->argc >= 1)
1211 ent = PRVM_G_EDICT(OFS_PARM0);
1213 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1214 if (ent == prog->edicts)
1216 VM_Warning("makestatic: can not modify world entity\n");
1219 if (ent->priv.server->free)
1221 VM_Warning("makestatic: can not modify free entity\n");
1226 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1231 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1232 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1233 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1237 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1238 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1239 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1242 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1243 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1244 for (i=0 ; i<3 ; i++)
1246 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1247 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1250 // throw the entity away now
1254 //=============================================================================
1261 static void VM_SV_setspawnparms (void)
1267 VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1269 ent = PRVM_G_EDICT(OFS_PARM0);
1270 i = PRVM_NUM_FOR_EDICT(ent);
1271 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1273 Con_Print("tried to setspawnparms on a non-client\n");
1277 // copy spawn parms out of the client_t
1278 client = svs.clients + i-1;
1279 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1280 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1287 Returns a color vector indicating the lighting at the requested point.
1289 (Internal Operation note: actually measures the light beneath the point, just like
1290 the model lighting on the client)
1295 static void VM_SV_getlight (void)
1297 vec3_t ambientcolor, diffusecolor, diffusenormal;
1299 VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1300 p = PRVM_G_VECTOR(OFS_PARM0);
1301 VectorClear(ambientcolor);
1302 VectorClear(diffusecolor);
1303 VectorClear(diffusenormal);
1304 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1305 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1306 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1311 unsigned char type; // 1/2/8 or other value if isn't used
1315 static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32
1316 static int vm_customstats_last;
1318 void VM_CustomStats_Clear (void)
1322 Z_Free(vm_customstats);
1323 vm_customstats = NULL;
1324 vm_customstats_last = -1;
1328 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1336 for(i=0; i<vm_customstats_last+1 ;i++)
1338 if(!vm_customstats[i].type)
1340 switch(vm_customstats[i].type)
1342 //string as 16 bytes
1345 strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1346 stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1347 stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1348 stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1349 stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1351 //float field sent as-is
1353 stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1355 //integer value of float field
1357 stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1365 // void(float index, float type, .void field) SV_AddStat = #232;
1366 // Set up an auto-sent player stat.
1367 // Client's get thier own fields sent to them. Index may not be less than 32.
1368 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1369 // 1: string (4 stats carrying a total of 16 charactures)
1370 // 2: float (one stat, float converted to an integer for transportation)
1371 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1372 static void VM_SV_AddStat (void)
1377 VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1381 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1384 VM_Warning("PF_SV_AddStat: not enough memory\n");
1388 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1389 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1390 off = PRVM_G_INT (OFS_PARM2);
1395 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1398 if(i >= (MAX_CL_STATS-32))
1400 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1403 if(i > (MAX_CL_STATS-32-4) && type == 1)
1405 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1408 vm_customstats[i].type = type;
1409 vm_customstats[i].fieldoffset = off;
1410 if(vm_customstats_last < i)
1411 vm_customstats_last = i;
1418 copies data from one entity to another
1420 copyentity(src, dst)
1423 static void VM_SV_copyentity (void)
1425 prvm_edict_t *in, *out;
1426 VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1427 in = PRVM_G_EDICT(OFS_PARM0);
1428 if (in == prog->edicts)
1430 VM_Warning("copyentity: can not read world entity\n");
1433 if (in->priv.server->free)
1435 VM_Warning("copyentity: can not read free entity\n");
1438 out = PRVM_G_EDICT(OFS_PARM1);
1439 if (out == prog->edicts)
1441 VM_Warning("copyentity: can not modify world entity\n");
1444 if (out->priv.server->free)
1446 VM_Warning("copyentity: can not modify free entity\n");
1449 memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1450 SV_LinkEdict(out, false);
1458 sets the color of a client and broadcasts the update to all connected clients
1460 setcolor(clientent, value)
1463 static void VM_SV_setcolor (void)
1469 VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1470 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1471 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1473 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1475 Con_Print("tried to setcolor a non-client\n");
1479 client = svs.clients + entnum-1;
1482 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1484 client->edict->fields.server->team = (i & 15) + 1;
1487 if (client->old_colors != client->colors)
1489 client->old_colors = client->colors;
1490 // send notification to all clients
1491 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1492 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1493 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1501 effect(origin, modelname, startframe, framecount, framerate)
1504 static void VM_SV_effect (void)
1508 VM_SAFEPARMCOUNT(5, VM_SV_effect);
1509 s = PRVM_G_STRING(OFS_PARM1);
1512 VM_Warning("effect: no model specified\n");
1516 i = SV_ModelIndex(s, 1);
1519 VM_Warning("effect: model not precached\n");
1523 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1525 VM_Warning("effect: framecount < 1\n");
1529 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1531 VM_Warning("effect: framerate < 1\n");
1535 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1538 static void VM_SV_te_blood (void)
1540 VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1541 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1543 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1544 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1548 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1550 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1551 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1552 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1554 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1555 SV_FlushBroadcastMessages();
1558 static void VM_SV_te_bloodshower (void)
1560 VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1561 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1563 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1564 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1570 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1571 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1572 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1574 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1576 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1577 SV_FlushBroadcastMessages();
1580 static void VM_SV_te_explosionrgb (void)
1582 VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1583 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1584 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1586 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1587 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1588 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1590 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1591 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1592 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1593 SV_FlushBroadcastMessages();
1596 static void VM_SV_te_particlecube (void)
1598 VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1599 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1601 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1602 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1604 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1605 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1606 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1608 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1609 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1610 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1612 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1613 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1614 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1616 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1618 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1619 // gravity true/false
1620 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1623 SV_FlushBroadcastMessages();
1626 static void VM_SV_te_particlerain (void)
1628 VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1629 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1631 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1632 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1634 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1635 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1636 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1638 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1639 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1640 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1644 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1646 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1648 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1649 SV_FlushBroadcastMessages();
1652 static void VM_SV_te_particlesnow (void)
1654 VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1655 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1657 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1658 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1660 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1664 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1672 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1674 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1675 SV_FlushBroadcastMessages();
1678 static void VM_SV_te_spark (void)
1680 VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1681 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1683 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1684 MSG_WriteByte(&sv.datagram, TE_SPARK);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1690 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1691 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1692 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1694 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1695 SV_FlushBroadcastMessages();
1698 static void VM_SV_te_gunshotquad (void)
1700 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1701 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1702 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1706 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1707 SV_FlushBroadcastMessages();
1710 static void VM_SV_te_spikequad (void)
1712 VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1713 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1714 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1719 SV_FlushBroadcastMessages();
1722 static void VM_SV_te_superspikequad (void)
1724 VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1725 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1726 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1731 SV_FlushBroadcastMessages();
1734 static void VM_SV_te_explosionquad (void)
1736 VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1737 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1738 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1743 SV_FlushBroadcastMessages();
1746 static void VM_SV_te_smallflash (void)
1748 VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
1749 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1750 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1755 SV_FlushBroadcastMessages();
1758 static void VM_SV_te_customflash (void)
1760 VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
1761 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1763 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1764 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1766 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1770 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1772 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1774 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1775 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1776 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1777 SV_FlushBroadcastMessages();
1780 static void VM_SV_te_gunshot (void)
1782 VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
1783 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1784 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1789 SV_FlushBroadcastMessages();
1792 static void VM_SV_te_spike (void)
1794 VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
1795 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1796 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1801 SV_FlushBroadcastMessages();
1804 static void VM_SV_te_superspike (void)
1806 VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
1807 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1808 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1813 SV_FlushBroadcastMessages();
1816 static void VM_SV_te_explosion (void)
1818 VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
1819 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1820 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1824 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1825 SV_FlushBroadcastMessages();
1828 static void VM_SV_te_tarexplosion (void)
1830 VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
1831 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1832 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1837 SV_FlushBroadcastMessages();
1840 static void VM_SV_te_wizspike (void)
1842 VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
1843 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1844 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1848 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1849 SV_FlushBroadcastMessages();
1852 static void VM_SV_te_knightspike (void)
1854 VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
1855 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1856 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1858 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1861 SV_FlushBroadcastMessages();
1864 static void VM_SV_te_lavasplash (void)
1866 VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
1867 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1868 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 SV_FlushBroadcastMessages();
1876 static void VM_SV_te_teleport (void)
1878 VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1885 SV_FlushBroadcastMessages();
1888 static void VM_SV_te_explosion2 (void)
1890 VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
1891 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1892 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1898 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1899 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1900 SV_FlushBroadcastMessages();
1903 static void VM_SV_te_lightning1 (void)
1905 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
1906 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1907 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1909 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1918 SV_FlushBroadcastMessages();
1921 static void VM_SV_te_lightning2 (void)
1923 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
1924 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1925 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1927 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1936 SV_FlushBroadcastMessages();
1939 static void VM_SV_te_lightning3 (void)
1941 VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
1942 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1943 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1945 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1954 SV_FlushBroadcastMessages();
1957 static void VM_SV_te_beam (void)
1959 VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
1960 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1961 MSG_WriteByte(&sv.datagram, TE_BEAM);
1963 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1965 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1972 SV_FlushBroadcastMessages();
1975 static void VM_SV_te_plasmaburn (void)
1977 VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 SV_FlushBroadcastMessages();
1986 static void VM_SV_te_flamejet (void)
1988 VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
1989 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1990 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1994 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2000 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2001 SV_FlushBroadcastMessages();
2004 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2007 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2009 bestdist = 1000000000;
2011 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2013 // clip original point to each triangle of the surface and find the
2014 // triangle that is closest
2015 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2016 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2017 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2018 TriangleNormal(v[0], v[1], v[2], facenormal);
2019 VectorNormalize(facenormal);
2020 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2021 VectorMA(p, offsetdist, facenormal, temp);
2022 for (j = 0, k = 2;j < 3;k = j, j++)
2024 VectorSubtract(v[k], v[j], edgenormal);
2025 CrossProduct(edgenormal, facenormal, sidenormal);
2026 VectorNormalize(sidenormal);
2027 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2029 VectorMA(temp, offsetdist, sidenormal, temp);
2031 dist = VectorDistance2(temp, p);
2032 if (bestdist > dist)
2035 VectorCopy(temp, out);
2040 static model_t *getmodel(prvm_edict_t *ed)
2043 if (!ed || ed->priv.server->free)
2045 modelindex = (int)ed->fields.server->modelindex;
2046 if (modelindex < 1 || modelindex >= MAX_MODELS)
2048 return sv.models[modelindex];
2051 static msurface_t *getsurface(model_t *model, int surfacenum)
2053 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2055 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2059 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2060 static void VM_SV_getsurfacenumpoints(void)
2063 msurface_t *surface;
2064 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints);
2065 // return 0 if no such surface
2066 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2068 PRVM_G_FLOAT(OFS_RETURN) = 0;
2072 // note: this (incorrectly) assumes it is a simple polygon
2073 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2075 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2076 static void VM_SV_getsurfacepoint(void)
2080 msurface_t *surface;
2082 VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint);
2083 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2084 ed = PRVM_G_EDICT(OFS_PARM0);
2085 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2087 // note: this (incorrectly) assumes it is a simple polygon
2088 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2089 if (pointnum < 0 || pointnum >= surface->num_vertices)
2091 // FIXME: implement rotation/scaling
2092 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2094 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2095 static void VM_SV_getsurfacenormal(void)
2098 msurface_t *surface;
2100 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal);
2101 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2102 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2104 // FIXME: implement rotation/scaling
2105 // note: this (incorrectly) assumes it is a simple polygon
2106 // note: this only returns the first triangle, so it doesn't work very
2107 // well for curved surfaces or arbitrary meshes
2108 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);
2109 VectorNormalize(normal);
2110 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2112 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2113 static void VM_SV_getsurfacetexture(void)
2116 msurface_t *surface;
2117 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture);
2118 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2119 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2121 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2123 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2124 static void VM_SV_getsurfacenearpoint(void)
2126 int surfacenum, best;
2128 vec_t dist, bestdist;
2131 msurface_t *surface;
2133 VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint);
2134 PRVM_G_FLOAT(OFS_RETURN) = -1;
2135 ed = PRVM_G_EDICT(OFS_PARM0);
2136 point = PRVM_G_VECTOR(OFS_PARM1);
2138 if (!ed || ed->priv.server->free)
2140 model = getmodel(ed);
2141 if (!model || !model->num_surfaces)
2144 // FIXME: implement rotation/scaling
2145 VectorSubtract(point, ed->fields.server->origin, p);
2147 bestdist = 1000000000;
2148 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2150 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2151 // first see if the nearest point on the surface's box is closer than the previous match
2152 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2153 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2154 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2155 dist = VectorLength2(clipped);
2156 if (dist < bestdist)
2158 // it is, check the nearest point on the actual geometry
2159 clippointtosurface(model, surface, p, clipped);
2160 VectorSubtract(clipped, p, clipped);
2161 dist += VectorLength2(clipped);
2162 if (dist < bestdist)
2164 // that's closer too, store it as the best match
2170 PRVM_G_FLOAT(OFS_RETURN) = best;
2172 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2173 static void VM_SV_getsurfaceclippedpoint(void)
2177 msurface_t *surface;
2179 VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint);
2180 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2181 ed = PRVM_G_EDICT(OFS_PARM0);
2182 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2184 // FIXME: implement rotation/scaling
2185 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2186 clippointtosurface(model, surface, p, out);
2187 // FIXME: implement rotation/scaling
2188 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2191 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2192 //this function originally written by KrimZon, made shorter by LordHavoc
2193 static void VM_SV_clientcommand (void)
2195 client_t *temp_client;
2197 VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2199 //find client for this entity
2200 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2201 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2203 Con_Print("PF_clientcommand: entity is not a client\n");
2207 temp_client = host_client;
2208 host_client = svs.clients + i;
2209 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2210 host_client = temp_client;
2213 //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
2214 static void VM_SV_setattachment (void)
2216 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2217 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2218 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2222 VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2224 if (e == prog->edicts)
2226 VM_Warning("setattachment: can not modify world entity\n");
2229 if (e->priv.server->free)
2231 VM_Warning("setattachment: can not modify free entity\n");
2235 if (tagentity == NULL)
2236 tagentity = prog->edicts;
2238 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2240 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2242 v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2245 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2247 modelindex = (int)tagentity->fields.server->modelindex;
2248 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2250 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2252 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);
2255 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));
2259 /////////////////////////////////////////
2260 // DP_MD3_TAGINFO extension coded by VorteX
2262 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2267 i = (int)e->fields.server->modelindex;
2268 if (i < 1 || i >= MAX_MODELS)
2270 model = sv.models[i];
2272 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2275 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2277 float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2281 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale);
2283 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * cl_viewmodel_scale.value);
2286 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2292 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2293 && (model = sv.models[(int)ent->fields.server->modelindex])
2294 && model->animscenes)
2296 // if model has wrong frame, engine automatically switches to model first frame
2297 frame = (int)ent->fields.server->frame;
2298 if (frame < 0 || frame >= model->numframes)
2300 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2302 *out = identitymatrix;
2306 // Warnings/errors code:
2307 // 0 - normal (everything all-right)
2310 // 3 - null or non-precached model
2311 // 4 - no tags with requested index
2312 // 5 - runaway loop at attachment chain
2313 extern cvar_t cl_bob;
2314 extern cvar_t cl_bobcycle;
2315 extern cvar_t cl_bobup;
2316 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2320 int modelindex, attachloop;
2321 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2324 *out = identitymatrix; // warnings and errors return identical matrix
2326 if (ent == prog->edicts)
2328 if (ent->priv.server->free)
2331 modelindex = (int)ent->fields.server->modelindex;
2332 if (modelindex <= 0 || modelindex > MAX_MODELS)
2335 model = sv.models[modelindex];
2337 tagmatrix = identitymatrix;
2338 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2342 if (attachloop >= 256) // prevent runaway looping
2344 // apply transformation by child's tagindex on parent entity and then
2345 // by parent entity itself
2346 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2347 if (ret && attachloop == 0)
2349 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2350 SV_GetEntityMatrix(ent, &entitymatrix, false);
2351 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2352 // next iteration we process the parent entity
2353 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2355 tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2356 ent = PRVM_EDICT_NUM(val->edict);
2363 // RENDER_VIEWMODEL magic
2364 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2366 Matrix4x4_Copy(&tagmatrix, out);
2367 ent = PRVM_EDICT_NUM(val->edict);
2369 SV_GetEntityMatrix(ent, &entitymatrix, true);
2370 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2373 // Cl_bob, ported from rendering code
2374 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2377 // LordHavoc: this code is *weird*, but not replacable (I think it
2378 // should be done in QC on the server, but oh well, quake is quake)
2379 // LordHavoc: figured out bobup: the time at which the sin is at 180
2380 // degrees (which allows lengthening or squishing the peak or valley)
2381 cycle = sv.time/cl_bobcycle.value;
2382 cycle -= (int)cycle;
2383 if (cycle < cl_bobup.value)
2384 cycle = sin(M_PI * cycle / cl_bobup.value);
2386 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2387 // bob is proportional to velocity in the xy plane
2388 // (don't count Z, or jumping messes it up)
2389 bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
2390 bob = bob*0.3 + bob*0.7*cycle;
2391 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2398 //float(entity ent, string tagname) gettagindex;
2400 static void VM_SV_gettagindex (void)
2403 const char *tag_name;
2404 int modelindex, tag_index;
2406 VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2408 ent = PRVM_G_EDICT(OFS_PARM0);
2409 tag_name = PRVM_G_STRING(OFS_PARM1);
2411 if (ent == prog->edicts)
2413 VM_Warning("gettagindex: can't affect world entity\n");
2416 if (ent->priv.server->free)
2418 VM_Warning("gettagindex: can't affect free entity\n");
2422 modelindex = (int)ent->fields.server->modelindex;
2424 if (modelindex <= 0 || modelindex > MAX_MODELS)
2425 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2428 tag_index = SV_GetTagIndex(ent, tag_name);
2430 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2432 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2435 //vector(entity ent, float tagindex) gettaginfo;
2436 static void VM_SV_gettaginfo (void)
2440 matrix4x4_t tag_matrix;
2443 VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2445 e = PRVM_G_EDICT(OFS_PARM0);
2446 tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2448 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2449 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2454 VM_Warning("gettagindex: can't affect world entity\n");
2457 VM_Warning("gettagindex: can't affect free entity\n");
2460 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2463 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2466 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2471 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2472 static void VM_SV_dropclient (void)
2475 client_t *oldhostclient;
2476 VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2477 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2478 if (clientnum < 0 || clientnum >= svs.maxclients)
2480 VM_Warning("dropclient: not a client\n");
2483 if (!svs.clients[clientnum].active)
2485 VM_Warning("dropclient: that client slot is not connected\n");
2488 oldhostclient = host_client;
2489 host_client = svs.clients + clientnum;
2490 SV_DropClient(false);
2491 host_client = oldhostclient;
2494 //entity() spawnclient (DP_SV_BOTCLIENT)
2495 static void VM_SV_spawnclient (void)
2499 VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2500 prog->xfunction->builtinsprofile += 2;
2502 for (i = 0;i < svs.maxclients;i++)
2504 if (!svs.clients[i].active)
2506 prog->xfunction->builtinsprofile += 100;
2507 SV_ConnectClient (i, NULL);
2508 // this has to be set or else ClientDisconnect won't be called
2509 // we assume the qc will call ClientConnect...
2510 svs.clients[i].clientconnectcalled = true;
2511 ed = PRVM_EDICT_NUM(i + 1);
2515 VM_RETURN_EDICT(ed);
2518 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2519 static void VM_SV_clienttype (void)
2522 VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2523 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2524 if (clientnum < 0 || clientnum >= svs.maxclients)
2525 PRVM_G_FLOAT(OFS_RETURN) = 3;
2526 else if (!svs.clients[clientnum].active)
2527 PRVM_G_FLOAT(OFS_RETURN) = 0;
2528 else if (svs.clients[clientnum].netconnection)
2529 PRVM_G_FLOAT(OFS_RETURN) = 1;
2531 PRVM_G_FLOAT(OFS_RETURN) = 2;
2538 string(string key) serverkey
2541 void VM_SV_serverkey(void)
2543 char string[VM_STRINGTEMP_LENGTH];
2544 VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2545 InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2546 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2549 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2550 static void VM_SV_setmodelindex (void)
2555 VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2557 e = PRVM_G_EDICT(OFS_PARM0);
2558 if (e == prog->edicts)
2560 VM_Warning("setmodelindex: can not modify world entity\n");
2563 if (e->priv.server->free)
2565 VM_Warning("setmodelindex: can not modify free entity\n");
2568 i = (int)PRVM_G_FLOAT(OFS_PARM1);
2569 if (i <= 0 || i > MAX_MODELS)
2571 VM_Warning("setmodelindex: invalid modelindex\n");
2574 if (!sv.model_precache[i][0])
2576 VM_Warning("setmodelindex: model not precached\n");
2580 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2581 e->fields.server->modelindex = i;
2587 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2588 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2590 SetMinMaxSize (e, quakemins, quakemaxs, true);
2593 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2596 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2597 static void VM_SV_modelnameforindex (void)
2600 VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2602 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2604 i = (int)PRVM_G_FLOAT(OFS_PARM0);
2605 if (i <= 0 || i > MAX_MODELS)
2607 VM_Warning("modelnameforindex: invalid modelindex\n");
2610 if (!sv.model_precache[i][0])
2612 VM_Warning("modelnameforindex: model not precached\n");
2616 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2619 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2620 static void VM_SV_particleeffectnum (void)
2623 VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2624 i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2627 PRVM_G_FLOAT(OFS_RETURN) = i;
2630 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2631 static void VM_SV_trailparticles (void)
2633 VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2635 MSG_WriteByte(&sv.datagram, svc_trailparticles);
2636 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2637 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2638 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2639 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2640 SV_FlushBroadcastMessages();
2643 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2644 static void VM_SV_pointparticles (void)
2646 VM_SAFEPARMCOUNT(4, VM_SV_pointparticles);
2648 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2649 MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM0));
2650 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1), sv.protocol);
2651 MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2652 MSG_WriteShort(&sv.datagram, bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535));
2653 SV_FlushBroadcastMessages();
2656 prvm_builtin_t vm_sv_builtins[] = {
2657 NULL, // #0 NULL function (not callable) (QUAKE)
2658 VM_makevectors, // #1 void(vector ang) makevectors (QUAKE)
2659 VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE)
2660 VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE)
2661 VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE)
2662 NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
2663 VM_break, // #6 void() break (QUAKE)
2664 VM_random, // #7 float() random (QUAKE)
2665 VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE)
2666 VM_normalize, // #9 vector(vector v) normalize (QUAKE)
2667 VM_error, // #10 void(string e) error (QUAKE)
2668 VM_objerror, // #11 void(string e) objerror (QUAKE)
2669 VM_vlen, // #12 float(vector v) vlen (QUAKE)
2670 VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE)
2671 VM_spawn, // #14 entity() spawn (QUAKE)
2672 VM_remove, // #15 void(entity e) remove (QUAKE)
2673 VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
2674 VM_SV_checkclient, // #17 entity() checkclient (QUAKE)
2675 VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE)
2676 VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE)
2677 VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE)
2678 VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
2679 VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE)
2680 VM_bprint, // #23 void(string s, ...) bprint (QUAKE)
2681 VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE)
2682 VM_dprint, // #25 void(string s, ...) dprint (QUAKE)
2683 VM_ftos, // #26 string(float f) ftos (QUAKE)
2684 VM_vtos, // #27 string(vector v) vtos (QUAKE)
2685 VM_coredump, // #28 void() coredump (QUAKE)
2686 VM_traceon, // #29 void() traceon (QUAKE)
2687 VM_traceoff, // #30 void() traceoff (QUAKE)
2688 VM_eprint, // #31 void(entity e) eprint (QUAKE)
2689 VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE)
2690 NULL, // #33 (QUAKE)
2691 VM_SV_droptofloor, // #34 float() droptofloor (QUAKE)
2692 VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE)
2693 VM_rint, // #36 float(float v) rint (QUAKE)
2694 VM_floor, // #37 float(float v) floor (QUAKE)
2695 VM_ceil, // #38 float(float v) ceil (QUAKE)
2696 NULL, // #39 (QUAKE)
2697 VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE)
2698 VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE)
2699 NULL, // #42 (QUAKE)
2700 VM_fabs, // #43 float(float f) fabs (QUAKE)
2701 VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
2702 VM_cvar, // #45 float(string s) cvar (QUAKE)
2703 VM_localcmd, // #46 void(string s) localcmd (QUAKE)
2704 VM_nextent, // #47 entity(entity e) nextent (QUAKE)
2705 VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
2706 VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
2707 NULL, // #50 (QUAKE)
2708 VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE)
2709 VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE)
2710 VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE)
2711 VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE)
2712 VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE)
2713 VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE)
2714 VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE)
2715 VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE)
2716 VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE)
2717 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
2718 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
2719 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
2720 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
2721 VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
2722 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
2723 NULL, // #66 (QUAKE)
2724 SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
2725 VM_precache_file, // #68 string(string s) precache_file (QUAKE)
2726 VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
2727 VM_changelevel, // #70 void(string s) changelevel (QUAKE)
2728 NULL, // #71 (QUAKE)
2729 VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE)
2730 VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE)
2731 VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
2732 VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE)
2733 VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE)
2734 VM_precache_file, // #77 string(string s) precache_file2 (QUAKE)
2735 VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE)
2736 NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
2737 NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
2738 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2739 NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD)
2740 NULL, // #83 (QUAKE)
2741 NULL, // #84 (QUAKE)
2742 NULL, // #85 (QUAKE)
2743 NULL, // #86 (QUAKE)
2744 NULL, // #87 (QUAKE)
2745 NULL, // #88 (QUAKE)
2746 NULL, // #89 (QUAKE)
2747 VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2748 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2749 VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2750 VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2751 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2752 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2753 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2754 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2755 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2756 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2757 // FrikaC and Telejano range #100-#199
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)
2858 // FTEQW range #200-#299
2877 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2881 VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
2882 VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS)
2887 VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
2891 VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2959 // CSQC range #300-#399
2960 NULL, // #300 void() clearscene (EXT_CSQC)
2961 NULL, // #301 void(float mask) addentities (EXT_CSQC)
2962 NULL, // #302 void(entity ent) addentity (EXT_CSQC)
2963 NULL, // #303 float(float property, ...) setproperty (EXT_CSQC)
2964 NULL, // #304 void() renderscene (EXT_CSQC)
2965 NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
2966 NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
2967 NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
2968 NULL, // #308 void() R_EndPolygon
2970 NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC)
2971 NULL, // #311 vector (vector v) cs_project (EXT_CSQC)
2975 NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
2976 NULL, // #316 float(string name) iscachedpic (EXT_CSQC)
2977 NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
2978 NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
2979 NULL, // #319 void(string name) freepic (EXT_CSQC)
2980 NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
2981 NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
2982 NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
2983 NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
2984 NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea
2985 NULL, // #325 void(void) drawresetcliparea
2990 NULL, // #330 float(float stnum) getstatf (EXT_CSQC)
2991 NULL, // #331 float(float stnum) getstati (EXT_CSQC)
2992 NULL, // #332 string(float firststnum) getstats (EXT_CSQC)
2993 VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2994 VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2995 VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
2996 VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2997 VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
2998 NULL, // #338 void(string s, ...) centerprint (EXT_CSQC)
2999 VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3000 NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC)
3001 NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3002 NULL, // #342 string(float keynum) getkeybind (EXT_CSQC)
3003 NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC)
3004 NULL, // #344 vector() getmousepos (EXT_CSQC)
3005 NULL, // #345 float(float framenum) getinputstate (EXT_CSQC)
3006 NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3007 NULL, // #347 void() runstandardplayerphysics (EXT_CSQC)
3008 NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3009 NULL, // #349 float() isdemo (EXT_CSQC)
3010 VM_isserver, // #350 float() isserver (EXT_CSQC)
3011 NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3012 NULL, // #352 void(string cmdname) registercommand (EXT_CSQC)
3013 VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3014 VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC)
3020 NULL, // #360 float() readbyte (EXT_CSQC)
3021 NULL, // #361 float() readchar (EXT_CSQC)
3022 NULL, // #362 float() readshort (EXT_CSQC)
3023 NULL, // #363 float() readlong (EXT_CSQC)
3024 NULL, // #364 float() readcoord (EXT_CSQC)
3025 NULL, // #365 float() readangle (EXT_CSQC)
3026 NULL, // #366 string() readstring (EXT_CSQC)
3027 NULL, // #367 float() readfloat (EXT_CSQC)
3060 // LordHavoc's range #400-#499
3061 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3062 VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3063 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3064 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3065 VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3066 VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3067 VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3068 VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3069 VM_SV_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3070 VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3071 VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3072 VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3073 VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3074 VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3075 VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3076 VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3077 VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3078 VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3079 VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3080 VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3081 VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3082 VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3083 VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3084 VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3085 VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3086 VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3087 VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3088 VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3089 VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3090 VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3091 VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3092 VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3093 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3094 VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3095 VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3096 VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3097 VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3098 VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3099 VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3100 VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3101 VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3102 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3103 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3104 VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3105 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
3106 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
3107 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
3108 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
3109 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3110 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3111 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3112 VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3113 VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3114 VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3115 VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3116 VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3117 VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3118 VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3120 VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3121 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3122 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3123 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3124 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3125 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3126 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3127 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3128 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3129 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3130 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3132 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3133 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3134 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3135 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3136 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3137 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3138 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3139 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3140 VM_tokenizebyseparator, // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3141 VM_strtolower, // #480 string(string s) VM_strtolower : DRESK - Return string as lowercase
3142 VM_strtoupper, // #481 string(string s) VM_strtoupper : DRESK - Return string as uppercase
3163 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3165 void VM_SV_Cmd_Init(void)
3170 void VM_SV_Cmd_Reset(void)