3 //============================================================================
6 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
7 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2", "maximum cosine angle for quake's vertical autoaim, a value above 1 completely disables the autoaim, quake used 0.93"}; //"0.93"}; // LordHavoc: disabled autoaim by default
10 char *vm_sv_extensions =
12 "DP_CON_ALIASPARAMETERS "
31 "DP_ENT_CUSTOMCOLORMAP "
32 "DP_ENT_EXTERIORMODELTOCLIENT "
34 "DP_ENT_LOWPRECISION "
37 "DP_GFX_EXTERNALTEXTURES "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
56 "DP_QC_FINDCHAINFLAGS "
57 "DP_QC_FINDCHAINFLOAT "
60 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
65 "DP_QC_MULTIPLETEMPSTRINGS "
67 "DP_QC_SINCOSSQRTPOW "
68 "DP_QC_STRINGBUFFERS "
71 "DP_QC_TRACE_MOVETYPE_HITMODEL "
72 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
73 "DP_QC_VECTORVECTORS "
79 "DP_SND_DIRECTIONLESSATTNNONE "
88 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
89 "DP_SV_DRAWONLYTOCLIENT "
92 "DP_SV_NODRAWTOCLIENT "
94 "DP_SV_PLAYERPHYSICS "
95 "DP_SV_PRECACHEANYTIME "
97 "DP_SV_ROTATINGBMODEL "
100 "DP_SV_WRITEUNTERMINATEDSTRING "
104 "DP_TE_EXPLOSIONRGB "
106 "DP_TE_PARTICLECUBE "
107 "DP_TE_PARTICLERAIN "
108 "DP_TE_PARTICLESNOW "
110 "DP_TE_QUADEFFECTS1 "
113 "DP_TE_STANDARDEFFECTBUILTINS "
116 //"EXT_CSQC " // not ready yet
118 "KRIMZON_SV_PARSECLIENTCOMMAND "
122 "PRYDON_CLIENTCURSOR "
123 "TENEBRAE_GFX_DLIGHTS "
125 "NEXUIZ_PLAYERMODEL "
132 Writes new values for v_forward, v_up, and v_right based on angles
136 void PF_makevectors (void)
138 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
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 void PF_setorigin (void)
155 e = PRVM_G_EDICT(OFS_PARM0);
156 if (e == prog->edicts)
157 PF_WARNING("setorigin: can not modify world entity\n");
158 if (e->priv.server->free)
159 PF_WARNING("setorigin: can not modify free entity\n");
160 org = PRVM_G_VECTOR(OFS_PARM1);
161 VectorCopy (org, e->fields.server->origin);
162 SV_LinkEdict (e, false);
166 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
170 for (i=0 ; i<3 ; i++)
172 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
174 // set derived values
175 VectorCopy (min, e->fields.server->mins);
176 VectorCopy (max, e->fields.server->maxs);
177 VectorSubtract (max, min, e->fields.server->size);
179 SV_LinkEdict (e, false);
186 the size box is rotated by the current angle
187 LordHavoc: no it isn't...
189 setsize (entity, minvector, maxvector)
192 void PF_setsize (void)
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);
204 SetMinMaxSize (e, min, max, false);
212 setmodel(entity, model)
215 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
216 void PF_setmodel (void)
222 e = PRVM_G_EDICT(OFS_PARM0);
223 if (e == prog->edicts)
224 PF_WARNING("setmodel: can not modify world entity\n");
225 if (e->priv.server->free)
226 PF_WARNING("setmodel: can not modify free entity\n");
227 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
228 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
229 e->fields.server->modelindex = i;
235 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
236 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
238 SetMinMaxSize (e, quakemins, quakemaxs, true);
241 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
248 single print to a specific client
250 sprint(clientent, value)
253 void PF_sprint (void)
257 char string[VM_STRINGTEMP_LENGTH];
259 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
261 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
263 Con_Print("tried to sprint to a non-client\n");
267 client = svs.clients + entnum-1;
268 if (!client->netconnection)
271 VM_VarString(1, string, sizeof(string));
272 MSG_WriteChar(&client->netconnection->message,svc_print);
273 MSG_WriteString(&client->netconnection->message, string);
281 single print to a specific client
283 centerprint(clientent, value)
286 void PF_centerprint (void)
290 char string[VM_STRINGTEMP_LENGTH];
292 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
294 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
296 Con_Print("tried to sprint to a non-client\n");
300 client = svs.clients + entnum-1;
301 if (!client->netconnection)
304 VM_VarString(1, string, sizeof(string));
305 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
306 MSG_WriteString(&client->netconnection->message, string);
313 particle(origin, color, count)
316 void PF_particle (void)
322 org = PRVM_G_VECTOR(OFS_PARM0);
323 dir = PRVM_G_VECTOR(OFS_PARM1);
324 color = PRVM_G_FLOAT(OFS_PARM2);
325 count = PRVM_G_FLOAT(OFS_PARM3);
326 SV_StartParticle (org, dir, color, count);
336 void PF_ambientsound (void)
340 float vol, attenuation;
343 pos = PRVM_G_VECTOR (OFS_PARM0);
344 samp = PRVM_G_STRING(OFS_PARM1);
345 vol = PRVM_G_FLOAT(OFS_PARM2);
346 attenuation = PRVM_G_FLOAT(OFS_PARM3);
348 // check to see if samp was properly precached
349 soundnum = SV_SoundIndex(samp, 1);
357 // add an svc_spawnambient command to the level signon packet
360 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
362 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
364 MSG_WriteVector(&sv.signon, pos, sv.protocol);
367 MSG_WriteShort (&sv.signon, soundnum);
369 MSG_WriteByte (&sv.signon, soundnum);
371 MSG_WriteByte (&sv.signon, vol*255);
372 MSG_WriteByte (&sv.signon, attenuation*64);
380 Each entity can have eight independant sound sources, like voice,
383 Channel 0 is an auto-allocate channel, the others override anything
384 already running on that entity/channel pair.
386 An attenuation of 0 will play full volume everywhere in the level.
387 Larger attenuations will drop off.
395 prvm_edict_t *entity;
399 entity = PRVM_G_EDICT(OFS_PARM0);
400 channel = PRVM_G_FLOAT(OFS_PARM1);
401 sample = PRVM_G_STRING(OFS_PARM2);
402 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
403 attenuation = PRVM_G_FLOAT(OFS_PARM4);
405 if (volume < 0 || volume > 255)
406 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
408 if (attenuation < 0 || attenuation > 4)
409 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
411 if (channel < 0 || channel > 7)
412 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
414 SV_StartSound (entity, channel, sample, volume, attenuation);
421 Used for use tracing and shot targeting
422 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
423 if the tryents flag is set.
425 traceline (vector1, vector2, tryents)
428 void PF_traceline (void)
435 prog->xfunction->builtinsprofile += 30;
437 v1 = PRVM_G_VECTOR(OFS_PARM0);
438 v2 = PRVM_G_VECTOR(OFS_PARM1);
439 move = PRVM_G_FLOAT(OFS_PARM2);
440 ent = PRVM_G_EDICT(OFS_PARM3);
442 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
444 prog->globals.server->trace_allsolid = trace.allsolid;
445 prog->globals.server->trace_startsolid = trace.startsolid;
446 prog->globals.server->trace_fraction = trace.fraction;
447 prog->globals.server->trace_inwater = trace.inwater;
448 prog->globals.server->trace_inopen = trace.inopen;
449 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
450 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
451 prog->globals.server->trace_plane_dist = trace.plane.dist;
453 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
455 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
456 // FIXME: add trace_endcontents
464 Used for use tracing and shot targeting
465 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
466 if the tryents flag is set.
468 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
471 // LordHavoc: added this for my own use, VERY useful, similar to traceline
472 void PF_tracebox (void)
474 float *v1, *v2, *m1, *m2;
479 prog->xfunction->builtinsprofile += 30;
481 v1 = PRVM_G_VECTOR(OFS_PARM0);
482 m1 = PRVM_G_VECTOR(OFS_PARM1);
483 m2 = PRVM_G_VECTOR(OFS_PARM2);
484 v2 = PRVM_G_VECTOR(OFS_PARM3);
485 move = PRVM_G_FLOAT(OFS_PARM4);
486 ent = PRVM_G_EDICT(OFS_PARM5);
488 trace = SV_Move (v1, m1, m2, v2, move, ent);
490 prog->globals.server->trace_allsolid = trace.allsolid;
491 prog->globals.server->trace_startsolid = trace.startsolid;
492 prog->globals.server->trace_fraction = trace.fraction;
493 prog->globals.server->trace_inwater = trace.inwater;
494 prog->globals.server->trace_inopen = trace.inopen;
495 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
496 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
497 prog->globals.server->trace_plane_dist = trace.plane.dist;
499 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
501 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
504 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
505 void PF_tracetoss (void)
509 prvm_edict_t *ignore;
511 prog->xfunction->builtinsprofile += 600;
513 ent = PRVM_G_EDICT(OFS_PARM0);
514 if (ent == prog->edicts)
515 PF_WARNING("tracetoss: can not use world entity\n");
516 ignore = PRVM_G_EDICT(OFS_PARM1);
518 trace = SV_Trace_Toss (ent, ignore);
520 prog->globals.server->trace_allsolid = trace.allsolid;
521 prog->globals.server->trace_startsolid = trace.startsolid;
522 prog->globals.server->trace_fraction = trace.fraction;
523 prog->globals.server->trace_inwater = trace.inwater;
524 prog->globals.server->trace_inopen = trace.inopen;
525 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
526 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
527 prog->globals.server->trace_plane_dist = trace.plane.dist;
529 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
531 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
539 Returns true if the given entity can move to the given position from it's
540 current position by walking or rolling.
542 scalar checkpos (entity, vector)
545 void PF_checkpos (void)
549 //============================================================================
552 unsigned char checkpvs[MAX_MAP_LEAFS/8];
554 int PF_newcheckclient (int check)
560 // cycle to the next one
562 check = bound(1, check, svs.maxclients);
563 if (check == svs.maxclients)
571 prog->xfunction->builtinsprofile++;
573 if (i == svs.maxclients+1)
575 // look up the client's edict
576 ent = PRVM_EDICT_NUM(i);
577 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
578 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
580 // found a valid client (possibly the same one again)
584 // get the PVS for the entity
585 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
587 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
588 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
597 Returns a client (or object that has a client enemy) that would be a
600 If there is more than one valid option, they are cycled each frame
602 If (self.origin + self.viewofs) is not in the PVS of the current target,
603 it is not returned at all.
608 int c_invis, c_notvis;
609 void PF_checkclient (void)
611 prvm_edict_t *ent, *self;
614 // find a new check if on a new frame
615 if (sv.time - sv.lastchecktime >= 0.1)
617 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
618 sv.lastchecktime = sv.time;
621 // return check if it might be visible
622 ent = PRVM_EDICT_NUM(sv.lastcheck);
623 if (ent->priv.server->free || ent->fields.server->health <= 0)
625 VM_RETURN_EDICT(prog->edicts);
629 // if current entity can't possibly see the check entity, return 0
630 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
631 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
632 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
635 VM_RETURN_EDICT(prog->edicts);
639 // might be able to see it
641 VM_RETURN_EDICT(ent);
644 //============================================================================
651 Sends text over to the client's execution buffer
653 stuffcmd (clientent, value, ...)
656 void PF_stuffcmd (void)
660 char string[VM_STRINGTEMP_LENGTH];
662 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
663 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
665 Con_Print("Can't stuffcmd to a non-client\n");
669 VM_VarString(1, string, sizeof(string));
672 host_client = svs.clients + entnum-1;
673 Host_ClientCommands ("%s", string);
681 Returns a chain of entities that have origins within a spherical area
683 findradius (origin, radius)
686 void PF_findradius (void)
688 prvm_edict_t *ent, *chain;
689 vec_t radius, radius2;
690 vec3_t org, eorg, mins, maxs;
693 prvm_edict_t *touchedicts[MAX_EDICTS];
695 chain = (prvm_edict_t *)prog->edicts;
697 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
698 radius = PRVM_G_FLOAT(OFS_PARM1);
699 radius2 = radius * radius;
701 mins[0] = org[0] - (radius + 1);
702 mins[1] = org[1] - (radius + 1);
703 mins[2] = org[2] - (radius + 1);
704 maxs[0] = org[0] + (radius + 1);
705 maxs[1] = org[1] + (radius + 1);
706 maxs[2] = org[2] + (radius + 1);
707 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
708 if (numtouchedicts > MAX_EDICTS)
710 // this never happens
711 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
712 numtouchedicts = MAX_EDICTS;
714 for (i = 0;i < numtouchedicts;i++)
716 ent = touchedicts[i];
717 prog->xfunction->builtinsprofile++;
718 // Quake did not return non-solid entities but darkplaces does
719 // (note: this is the reason you can't blow up fallen zombies)
720 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
722 // LordHavoc: compare against bounding box rather than center so it
723 // doesn't miss large objects, and use DotProduct instead of Length
724 // for a major speedup
725 VectorSubtract(org, ent->fields.server->origin, eorg);
726 if (sv_gameplayfix_findradiusdistancetobox.integer)
728 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
729 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
730 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
733 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
734 if (DotProduct(eorg, eorg) < radius2)
736 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
741 VM_RETURN_EDICT(chain);
744 void PF_precache_file (void)
745 { // precache_file is only used to copy files with qcc, it does nothing
746 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
750 void PF_precache_sound (void)
752 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
753 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
756 void PF_precache_model (void)
758 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
759 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
766 float(float yaw, float dist) walkmove
769 void PF_walkmove (void)
777 // assume failure if it returns early
778 PRVM_G_FLOAT(OFS_RETURN) = 0;
780 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
781 if (ent == prog->edicts)
782 PF_WARNING("walkmove: can not modify world entity\n");
783 if (ent->priv.server->free)
784 PF_WARNING("walkmove: can not modify free entity\n");
785 yaw = PRVM_G_FLOAT(OFS_PARM0);
786 dist = PRVM_G_FLOAT(OFS_PARM1);
788 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
791 yaw = yaw*M_PI*2 / 360;
793 move[0] = cos(yaw)*dist;
794 move[1] = sin(yaw)*dist;
797 // save program state, because SV_movestep may call other progs
798 oldf = prog->xfunction;
799 oldself = prog->globals.server->self;
801 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
804 // restore program state
805 prog->xfunction = oldf;
806 prog->globals.server->self = oldself;
816 void PF_droptofloor (void)
822 // assume failure if it returns early
823 PRVM_G_FLOAT(OFS_RETURN) = 0;
825 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
826 if (ent == prog->edicts)
827 PF_WARNING("droptofloor: can not modify world entity\n");
828 if (ent->priv.server->free)
829 PF_WARNING("droptofloor: can not modify free entity\n");
831 VectorCopy (ent->fields.server->origin, end);
834 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
836 if (trace.fraction != 1)
838 VectorCopy (trace.endpos, ent->fields.server->origin);
839 SV_LinkEdict (ent, false);
840 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
841 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
842 PRVM_G_FLOAT(OFS_RETURN) = 1;
843 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
844 ent->priv.server->suspendedinairflag = true;
852 void(float style, string value) lightstyle
855 void PF_lightstyle (void)
862 style = PRVM_G_FLOAT(OFS_PARM0);
863 val = PRVM_G_STRING(OFS_PARM1);
865 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
866 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
869 // change the string in sv
870 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
872 // send message to all clients on this server
873 if (sv.state != ss_active)
876 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
878 if (client->active && client->netconnection)
880 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
881 MSG_WriteChar (&client->netconnection->message,style);
882 MSG_WriteString (&client->netconnection->message, val);
892 void PF_checkbottom (void)
894 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
902 void PF_pointcontents (void)
904 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
911 Pick a vector for the player to shoot along
912 vector aim(entity, missilespeed)
917 prvm_edict_t *ent, *check, *bestent;
918 vec3_t start, dir, end, bestdir;
921 float dist, bestdist;
924 // assume failure if it returns early
925 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
926 // if sv_aim is so high it can't possibly accept anything, skip out early
927 if (sv_aim.value >= 1)
930 ent = PRVM_G_EDICT(OFS_PARM0);
931 if (ent == prog->edicts)
932 PF_WARNING("aim: can not use world entity\n");
933 if (ent->priv.server->free)
934 PF_WARNING("aim: can not use free entity\n");
935 speed = PRVM_G_FLOAT(OFS_PARM1);
937 VectorCopy (ent->fields.server->origin, start);
940 // try sending a trace straight
941 VectorCopy (prog->globals.server->v_forward, dir);
942 VectorMA (start, 2048, dir, end);
943 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
944 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
945 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
947 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
952 // try all possible entities
953 VectorCopy (dir, bestdir);
954 bestdist = sv_aim.value;
957 check = PRVM_NEXT_EDICT(prog->edicts);
958 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
960 prog->xfunction->builtinsprofile++;
961 if (check->fields.server->takedamage != DAMAGE_AIM)
965 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
966 continue; // don't aim at teammate
967 for (j=0 ; j<3 ; j++)
968 end[j] = check->fields.server->origin[j]
969 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
970 VectorSubtract (end, start, dir);
971 VectorNormalize (dir);
972 dist = DotProduct (dir, prog->globals.server->v_forward);
974 continue; // to far to turn
975 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
977 { // can shoot at this one
985 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
986 dist = DotProduct (dir, prog->globals.server->v_forward);
987 VectorScale (prog->globals.server->v_forward, dist, end);
989 VectorNormalize (end);
990 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
994 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1002 This was a major timewaster in progs, so it was converted to C
1005 void PF_changeyaw (void)
1008 float ideal, current, move, speed;
1010 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1011 if (ent == prog->edicts)
1012 PF_WARNING("changeyaw: can not modify world entity\n");
1013 if (ent->priv.server->free)
1014 PF_WARNING("changeyaw: can not modify free entity\n");
1015 current = ANGLEMOD(ent->fields.server->angles[1]);
1016 ideal = ent->fields.server->ideal_yaw;
1017 speed = ent->fields.server->yaw_speed;
1019 if (current == ideal)
1021 move = ideal - current;
1022 if (ideal > current)
1043 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1051 void PF_changepitch (void)
1054 float ideal, current, move, speed;
1057 ent = PRVM_G_EDICT(OFS_PARM0);
1058 if (ent == prog->edicts)
1059 PF_WARNING("changepitch: can not modify world entity\n");
1060 if (ent->priv.server->free)
1061 PF_WARNING("changepitch: can not modify free entity\n");
1062 current = ANGLEMOD( ent->fields.server->angles[0] );
1063 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1064 ideal = val->_float;
1067 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1070 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1071 speed = val->_float;
1074 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1078 if (current == ideal)
1080 move = ideal - current;
1081 if (ideal > current)
1102 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1106 ===============================================================================
1110 ===============================================================================
1113 #define MSG_BROADCAST 0 // unreliable to all
1114 #define MSG_ONE 1 // reliable to one (msg_entity)
1115 #define MSG_ALL 2 // reliable to all
1116 #define MSG_INIT 3 // write to the init string
1117 #define MSG_ENTITY 5
1119 sizebuf_t *WriteDest (void)
1124 extern sizebuf_t *sv2csqcbuf;
1126 dest = PRVM_G_FLOAT(OFS_PARM0);
1130 return &sv.datagram;
1133 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1134 entnum = PRVM_NUM_FOR_EDICT(ent);
1135 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1137 Con_Printf ("WriteDest: tried to write to non-client\n");
1138 return &sv.reliable_datagram;
1141 return &svs.clients[entnum-1].netconnection->message;
1144 Con_Printf ("WriteDest: bad destination\n");
1146 return &sv.reliable_datagram;
1158 void PF_WriteByte (void)
1160 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1163 void PF_WriteChar (void)
1165 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1168 void PF_WriteShort (void)
1170 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1173 void PF_WriteLong (void)
1175 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1178 void PF_WriteAngle (void)
1180 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1183 void PF_WriteCoord (void)
1185 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1188 void PF_WriteString (void)
1190 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1193 void PF_WriteUnterminatedString (void)
1195 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1199 void PF_WriteEntity (void)
1201 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1204 //////////////////////////////////////////////////////////
1206 void PF_makestatic (void)
1211 ent = PRVM_G_EDICT(OFS_PARM0);
1212 if (ent == prog->edicts)
1213 PF_WARNING("makestatic: can not modify world entity\n");
1214 if (ent->priv.server->free)
1215 PF_WARNING("makestatic: can not modify free entity\n");
1218 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1223 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1224 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1225 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1229 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1230 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1231 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1234 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1235 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1236 for (i=0 ; i<3 ; i++)
1238 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1239 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1242 // throw the entity away now
1246 //=============================================================================
1253 void PF_setspawnparms (void)
1259 ent = PRVM_G_EDICT(OFS_PARM0);
1260 i = PRVM_NUM_FOR_EDICT(ent);
1261 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1263 Con_Print("tried to setspawnparms on a non-client\n");
1267 // copy spawn parms out of the client_t
1268 client = svs.clients + i-1;
1269 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1270 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1277 Returns a color vector indicating the lighting at the requested point.
1279 (Internal Operation note: actually measures the light beneath the point, just like
1280 the model lighting on the client)
1285 void PF_getlight (void)
1287 vec3_t ambientcolor, diffusecolor, diffusenormal;
1289 p = PRVM_G_VECTOR(OFS_PARM0);
1290 VectorClear(ambientcolor);
1291 VectorClear(diffusecolor);
1292 VectorClear(diffusenormal);
1293 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1294 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1295 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1298 void PF_registercvar (void)
1300 const char *name, *value;
1301 name = PRVM_G_STRING(OFS_PARM0);
1302 value = PRVM_G_STRING(OFS_PARM1);
1303 PRVM_G_FLOAT(OFS_RETURN) = 0;
1305 // first check to see if it has already been defined
1306 if (Cvar_FindVar (name))
1309 // check for overlap with a command
1310 if (Cmd_Exists (name))
1312 Con_Printf("PF_registercvar: %s is a command\n", name);
1316 Cvar_Get(name, value, 0);
1318 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1323 unsigned char type; // 1/2/8 or other value if isn't used
1327 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1328 static int vm_autosentstats_last;
1330 void VM_AutoSentStats_Clear (void)
1332 if(vm_autosentstats)
1334 free(vm_autosentstats);
1335 vm_autosentstats = NULL;
1336 vm_autosentstats_last = -1;
1340 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1341 #define VM_SENDSTAT(a,b,c)\
1344 if((c)==(unsigned char)(c))\
1346 MSG_WriteByte((a), svc_updatestatubyte);\
1347 MSG_WriteByte((a), (b));\
1348 MSG_WriteByte((a), (c));\
1352 MSG_WriteByte((a), svc_updatestat);\
1353 MSG_WriteByte((a), (b));\
1354 MSG_WriteLong((a), (c));\
1358 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1370 if(!vm_autosentstats)
1373 send = (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5);
1375 for(i=0; i<vm_autosentstats_last+1 ;i++)
1377 if(!vm_autosentstats[i].type)
1379 switch(vm_autosentstats[i].type)
1383 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1391 stats[i+32] = si[0];
1392 stats[i+33] = si[1];
1393 stats[i+34] = si[2];
1394 stats[i+35] = si[3];
1398 VM_SENDSTAT(msg, i+32, si[0]);
1399 VM_SENDSTAT(msg, i+33, si[1]);
1400 VM_SENDSTAT(msg, i+34, si[2]);
1401 VM_SENDSTAT(msg, i+35, si[3]);
1407 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1408 k.i = LittleLong (k.i);
1412 VM_SENDSTAT(msg, i+32, k.i);
1416 v = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1420 VM_SENDSTAT(msg, i+32, v);
1428 // void(float index, float type, .void field) SV_AddStat = #470;
1429 // Set up an auto-sent player stat.
1430 // Client's get thier own fields sent to them. Index may not be less than 32.
1431 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1432 // 1: string (4 stats carrying a total of 16 charactures)
1433 // 2: float (one stat, float converted to an integer for transportation)
1434 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1435 void PF_SV_AddStat (void)
1440 if(!vm_autosentstats)
1442 vm_autosentstats = malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1443 if(!vm_autosentstats)
1445 Con_Printf("PF_SV_AddStat: not enough memory\n");
1449 i = PRVM_G_FLOAT(OFS_PARM0);
1450 type = PRVM_G_FLOAT(OFS_PARM1);
1451 off = PRVM_G_INT (OFS_PARM2);
1456 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1459 if(i >= (MAX_CL_STATS-32))
1461 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1464 if(i > (MAX_CL_STATS-32-4) && type == 1)
1466 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1469 vm_autosentstats[i].type = type;
1470 vm_autosentstats[i].fieldoffset = off;
1471 if(vm_autosentstats_last < i)
1472 vm_autosentstats_last = i;
1479 copies data from one entity to another
1481 copyentity(src, dst)
1484 void PF_copyentity (void)
1486 prvm_edict_t *in, *out;
1487 in = PRVM_G_EDICT(OFS_PARM0);
1488 if (in == prog->edicts)
1489 PF_WARNING("copyentity: can not read world entity\n");
1490 if (in->priv.server->free)
1491 PF_WARNING("copyentity: can not read free entity\n");
1492 out = PRVM_G_EDICT(OFS_PARM1);
1493 if (out == prog->edicts)
1494 PF_WARNING("copyentity: can not modify world entity\n");
1495 if (out->priv.server->free)
1496 PF_WARNING("copyentity: can not modify free entity\n");
1497 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1505 sets the color of a client and broadcasts the update to all connected clients
1507 setcolor(clientent, value)
1510 void PF_setcolor (void)
1516 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1517 i = PRVM_G_FLOAT(OFS_PARM1);
1519 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1521 Con_Print("tried to setcolor a non-client\n");
1525 client = svs.clients + entnum-1;
1528 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1530 client->edict->fields.server->team = (i & 15) + 1;
1533 if (client->old_colors != client->colors)
1535 client->old_colors = client->colors;
1536 // send notification to all clients
1537 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1538 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1539 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1547 effect(origin, modelname, startframe, framecount, framerate)
1550 void PF_effect (void)
1554 s = PRVM_G_STRING(OFS_PARM1);
1556 PF_WARNING("effect: no model specified\n");
1558 i = SV_ModelIndex(s, 1);
1560 PF_WARNING("effect: model not precached\n");
1561 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1564 void PF_te_blood (void)
1566 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1568 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1569 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1571 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1572 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1573 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1575 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1576 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1577 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1579 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1582 void PF_te_bloodshower (void)
1584 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1586 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1587 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1589 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1590 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1591 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1593 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1594 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1595 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1597 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1599 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1602 void PF_te_explosionrgb (void)
1604 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1605 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1607 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1608 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1609 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1611 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1612 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1613 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1616 void PF_te_particlecube (void)
1618 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1620 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1621 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1624 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1625 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1627 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1628 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1635 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1637 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1638 // gravity true/false
1639 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1644 void PF_te_particlerain (void)
1646 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1648 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1649 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1656 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1660 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1663 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1665 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1668 void PF_te_particlesnow (void)
1670 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1672 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1673 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1676 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1677 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1687 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1689 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1692 void PF_te_spark (void)
1694 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1696 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1697 MSG_WriteByte(&sv.datagram, TE_SPARK);
1699 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1700 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1703 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1704 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1705 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1707 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1710 void PF_te_gunshotquad (void)
1712 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1713 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1715 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1720 void PF_te_spikequad (void)
1722 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1723 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1725 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1727 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1730 void PF_te_superspikequad (void)
1732 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1733 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1740 void PF_te_explosionquad (void)
1742 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1743 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1750 void PF_te_smallflash (void)
1752 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1753 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1760 void PF_te_customflash (void)
1762 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1764 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1765 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1771 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1773 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1775 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1776 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1777 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1780 void PF_te_gunshot (void)
1782 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1783 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1790 void PF_te_spike (void)
1792 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1793 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1800 void PF_te_superspike (void)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1810 void PF_te_explosion (void)
1812 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1813 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1820 void PF_te_tarexplosion (void)
1822 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1823 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1830 void PF_te_wizspike (void)
1832 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1833 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1840 void PF_te_knightspike (void)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 void PF_te_lavasplash (void)
1852 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1853 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1860 void PF_te_teleport (void)
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 void PF_te_explosion2 (void)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1879 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1880 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1883 void PF_te_lightning1 (void)
1885 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1886 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1888 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1894 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1899 void PF_te_lightning2 (void)
1901 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1902 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1904 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1915 void PF_te_lightning3 (void)
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1920 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1923 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1931 void PF_te_beam (void)
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_BEAM);
1936 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1947 void PF_te_plasmaburn (void)
1949 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1950 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1956 void PF_te_flamejet (void)
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1972 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1975 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1977 bestdist = 1000000000;
1979 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1981 // clip original point to each triangle of the surface and find the
1982 // triangle that is closest
1983 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1984 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1985 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1986 TriangleNormal(v[0], v[1], v[2], facenormal);
1987 VectorNormalize(facenormal);
1988 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1989 VectorMA(p, offsetdist, facenormal, temp);
1990 for (j = 0, k = 2;j < 3;k = j, j++)
1992 VectorSubtract(v[k], v[j], edgenormal);
1993 CrossProduct(edgenormal, facenormal, sidenormal);
1994 VectorNormalize(sidenormal);
1995 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1997 VectorMA(temp, offsetdist, sidenormal, temp);
1999 dist = VectorDistance2(temp, p);
2000 if (bestdist > dist)
2003 VectorCopy(temp, out);
2008 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2012 if (!ed || ed->priv.server->free)
2014 modelindex = ed->fields.server->modelindex;
2015 if (modelindex < 1 || modelindex >= MAX_MODELS)
2017 model = sv.models[modelindex];
2018 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2020 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2024 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2025 void PF_getsurfacenumpoints(void)
2027 msurface_t *surface;
2028 // return 0 if no such surface
2029 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2031 PRVM_G_FLOAT(OFS_RETURN) = 0;
2035 // note: this (incorrectly) assumes it is a simple polygon
2036 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2038 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2039 void PF_getsurfacepoint(void)
2042 msurface_t *surface;
2044 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2045 ed = PRVM_G_EDICT(OFS_PARM0);
2046 if (!ed || ed->priv.server->free)
2048 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2050 // note: this (incorrectly) assumes it is a simple polygon
2051 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2052 if (pointnum < 0 || pointnum >= surface->num_vertices)
2054 // FIXME: implement rotation/scaling
2055 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2057 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2058 void PF_getsurfacenormal(void)
2060 msurface_t *surface;
2062 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2063 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2065 // FIXME: implement rotation/scaling
2066 // note: this (incorrectly) assumes it is a simple polygon
2067 // note: this only returns the first triangle, so it doesn't work very
2068 // well for curved surfaces or arbitrary meshes
2069 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);
2070 VectorNormalize(normal);
2071 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2073 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2074 void PF_getsurfacetexture(void)
2076 msurface_t *surface;
2077 PRVM_G_INT(OFS_RETURN) = 0;
2078 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2080 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2082 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2083 void PF_getsurfacenearpoint(void)
2085 int surfacenum, best, modelindex;
2087 vec_t dist, bestdist;
2090 msurface_t *surface;
2092 PRVM_G_FLOAT(OFS_RETURN) = -1;
2093 ed = PRVM_G_EDICT(OFS_PARM0);
2094 point = PRVM_G_VECTOR(OFS_PARM1);
2096 if (!ed || ed->priv.server->free)
2098 modelindex = ed->fields.server->modelindex;
2099 if (modelindex < 1 || modelindex >= MAX_MODELS)
2101 model = sv.models[modelindex];
2102 if (!model->num_surfaces)
2105 // FIXME: implement rotation/scaling
2106 VectorSubtract(point, ed->fields.server->origin, p);
2108 bestdist = 1000000000;
2109 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2111 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2112 // first see if the nearest point on the surface's box is closer than the previous match
2113 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2114 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2115 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2116 dist = VectorLength2(clipped);
2117 if (dist < bestdist)
2119 // it is, check the nearest point on the actual geometry
2120 clippointtosurface(surface, p, clipped);
2121 VectorSubtract(clipped, p, clipped);
2122 dist += VectorLength2(clipped);
2123 if (dist < bestdist)
2125 // that's closer too, store it as the best match
2131 PRVM_G_FLOAT(OFS_RETURN) = best;
2133 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2134 void PF_getsurfaceclippedpoint(void)
2137 msurface_t *surface;
2139 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2140 ed = PRVM_G_EDICT(OFS_PARM0);
2141 if (!ed || ed->priv.server->free)
2143 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2145 // FIXME: implement rotation/scaling
2146 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2147 clippointtosurface(surface, p, out);
2148 // FIXME: implement rotation/scaling
2149 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2152 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2153 //this function originally written by KrimZon, made shorter by LordHavoc
2154 void PF_clientcommand (void)
2156 client_t *temp_client;
2159 //find client for this entity
2160 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2161 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2163 Con_Print("PF_clientcommand: entity is not a client\n");
2167 temp_client = host_client;
2168 host_client = svs.clients + i;
2169 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2170 host_client = temp_client;
2173 //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)
2174 void PF_setattachment (void)
2176 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2177 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2178 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2183 if (e == prog->edicts)
2184 PF_WARNING("setattachment: can not modify world entity\n");
2185 if (e->priv.server->free)
2186 PF_WARNING("setattachment: can not modify free entity\n");
2188 if (tagentity == NULL)
2189 tagentity = prog->edicts;
2191 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2193 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2195 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2198 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2200 modelindex = (int)tagentity->fields.server->modelindex;
2201 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2203 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2205 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);
2208 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));
2212 /////////////////////////////////////////
2213 // DP_MD3_TAGINFO extension coded by VorteX
2215 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2220 i = e->fields.server->modelindex;
2221 if (i < 1 || i >= MAX_MODELS)
2223 model = sv.models[i];
2225 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2228 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2230 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2234 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);
2236 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 * 0.333);
2239 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2245 && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2246 && (model = sv.models[(int)ent->fields.server->modelindex])
2247 && model->animscenes)
2249 // if model has wrong frame, engine automatically switches to model first frame
2250 frame = (int)ent->fields.server->frame;
2251 if (frame < 0 || frame >= model->numframes)
2253 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2255 Matrix4x4_CreateIdentity(out);
2259 // Warnings/errors code:
2260 // 0 - normal (everything all-right)
2263 // 3 - null or non-precached model
2264 // 4 - no tags with requested index
2265 // 5 - runaway loop at attachment chain
2266 extern cvar_t cl_bob;
2267 extern cvar_t cl_bobcycle;
2268 extern cvar_t cl_bobup;
2269 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2273 int modelindex, attachloop;
2274 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2277 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2279 if (ent == prog->edicts)
2281 if (ent->priv.server->free)
2284 modelindex = (int)ent->fields.server->modelindex;
2285 if (modelindex <= 0 || modelindex > MAX_MODELS)
2288 model = sv.models[modelindex];
2290 Matrix4x4_CreateIdentity(&tagmatrix);
2291 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2295 if (attachloop >= 256) // prevent runaway looping
2297 // apply transformation by child's tagindex on parent entity and then
2298 // by parent entity itself
2299 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2300 if (ret && attachloop == 0)
2302 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2303 SV_GetEntityMatrix(ent, &entitymatrix, false);
2304 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2305 // next iteration we process the parent entity
2306 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2308 tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2309 ent = PRVM_EDICT_NUM(val->edict);
2316 // RENDER_VIEWMODEL magic
2317 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2319 Matrix4x4_Copy(&tagmatrix, out);
2320 ent = PRVM_EDICT_NUM(val->edict);
2322 SV_GetEntityMatrix(ent, &entitymatrix, true);
2323 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2326 // Cl_bob, ported from rendering code
2327 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2330 // LordHavoc: this code is *weird*, but not replacable (I think it
2331 // should be done in QC on the server, but oh well, quake is quake)
2332 // LordHavoc: figured out bobup: the time at which the sin is at 180
2333 // degrees (which allows lengthening or squishing the peak or valley)
2334 cycle = sv.time/cl_bobcycle.value;
2335 cycle -= (int)cycle;
2336 if (cycle < cl_bobup.value)
2337 cycle = sin(M_PI * cycle / cl_bobup.value);
2339 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2340 // bob is proportional to velocity in the xy plane
2341 // (don't count Z, or jumping messes it up)
2342 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;
2343 bob = bob*0.3 + bob*0.7*cycle;
2344 out->m[2][3] += bound(-7, bob, 4);
2351 //float(entity ent, string tagname) gettagindex;
2353 void PF_gettagindex (void)
2355 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2356 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2357 int modelindex, tag_index;
2359 if (ent == prog->edicts)
2360 PF_WARNING("gettagindex: can't affect world entity\n");
2361 if (ent->priv.server->free)
2362 PF_WARNING("gettagindex: can't affect free entity\n");
2364 modelindex = (int)ent->fields.server->modelindex;
2366 if (modelindex <= 0 || modelindex > MAX_MODELS)
2367 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2370 tag_index = SV_GetTagIndex(ent, tag_name);
2372 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2374 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2377 //vector(entity ent, float tagindex) gettaginfo;
2378 void PF_gettaginfo (void)
2380 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2381 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2382 matrix4x4_t tag_matrix;
2385 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2386 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2391 PF_WARNING("gettagindex: can't affect world entity\n");
2394 PF_WARNING("gettagindex: can't affect free entity\n");
2397 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2400 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2403 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2408 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2409 void PF_dropclient (void)
2412 client_t *oldhostclient;
2413 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2414 if (clientnum < 0 || clientnum >= svs.maxclients)
2415 PF_WARNING("dropclient: not a client\n");
2416 if (!svs.clients[clientnum].active)
2417 PF_WARNING("dropclient: that client slot is not connected\n");
2418 oldhostclient = host_client;
2419 host_client = svs.clients + clientnum;
2420 SV_DropClient(false);
2421 host_client = oldhostclient;
2424 //entity() spawnclient (DP_SV_BOTCLIENT)
2425 void PF_spawnclient (void)
2429 prog->xfunction->builtinsprofile += 2;
2431 for (i = 0;i < svs.maxclients;i++)
2433 if (!svs.clients[i].active)
2435 prog->xfunction->builtinsprofile += 100;
2436 SV_ConnectClient (i, NULL);
2437 ed = PRVM_EDICT_NUM(i + 1);
2441 VM_RETURN_EDICT(ed);
2444 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2445 void PF_clienttype (void)
2448 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2449 if (clientnum < 0 || clientnum >= svs.maxclients)
2450 PRVM_G_FLOAT(OFS_RETURN) = 3;
2451 else if (!svs.clients[clientnum].active)
2452 PRVM_G_FLOAT(OFS_RETURN) = 0;
2453 else if (svs.clients[clientnum].netconnection)
2454 PRVM_G_FLOAT(OFS_RETURN) = 1;
2456 PRVM_G_FLOAT(OFS_RETURN) = 2;
2459 void PF_edict_num (void)
2461 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2464 prvm_builtin_t vm_sv_builtins[] = {
2466 PF_makevectors, // #1 void(vector ang) makevectors
2467 PF_setorigin, // #2 void(entity e, vector o) setorigin
2468 PF_setmodel, // #3 void(entity e, string m) setmodel
2469 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2470 NULL, // #5 void(entity e, vector min, vector max) setabssize
2471 VM_break, // #6 void() break
2472 VM_random, // #7 float() random
2473 PF_sound, // #8 void(entity e, float chan, string samp) sound
2474 VM_normalize, // #9 vector(vector v) normalize
2475 VM_error, // #10 void(string e) error
2476 VM_objerror, // #11 void(string e) objerror
2477 VM_vlen, // #12 float(vector v) vlen
2478 VM_vectoyaw, // #13 float(vector v) vectoyaw
2479 VM_spawn, // #14 entity() spawn
2480 VM_remove, // #15 void(entity e) remove
2481 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2482 PF_checkclient, // #17 entity() clientlist
2483 VM_find, // #18 entity(entity start, .string fld, string match) find
2484 PF_precache_sound, // #19 void(string s) precache_sound
2485 PF_precache_model, // #20 void(string s) precache_model
2486 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2487 PF_findradius, // #22 entity(vector org, float rad) findradius
2488 VM_bprint, // #23 void(string s) bprint
2489 PF_sprint, // #24 void(entity client, string s) sprint
2490 VM_dprint, // #25 void(string s) dprint
2491 VM_ftos, // #26 void(string s) ftos
2492 VM_vtos, // #27 void(string s) vtos
2493 VM_coredump, // #28 void() coredump
2494 VM_traceon, // #29 void() traceon
2495 VM_traceoff, // #30 void() traceoff
2496 VM_eprint, // #31 void(entity e) eprint
2497 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2499 PF_droptofloor, // #34 float() droptofloor
2500 PF_lightstyle, // #35 void(float style, string value) lightstyle
2501 VM_rint, // #36 float(float v) rint
2502 VM_floor, // #37 float(float v) floor
2503 VM_ceil, // #38 float(float v) ceil
2505 PF_checkbottom, // #40 float(entity e) checkbottom
2506 PF_pointcontents, // #41 float(vector v) pointcontents
2508 VM_fabs, // #43 float(float f) fabs
2509 PF_aim, // #44 vector(entity e, float speed) aim
2510 VM_cvar, // #45 float(string s) cvar
2511 VM_localcmd, // #46 void(string s) localcmd
2512 VM_nextent, // #47 entity(entity e) nextent
2513 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2514 PF_changeyaw, // #49 void() ChangeYaw
2516 VM_vectoangles, // #51 vector(vector v) vectoangles
2517 PF_WriteByte, // #52 void(float to, float f) WriteByte
2518 PF_WriteChar, // #53 void(float to, float f) WriteChar
2519 PF_WriteShort, // #54 void(float to, float f) WriteShort
2520 PF_WriteLong, // #55 void(float to, float f) WriteLong
2521 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2522 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2523 PF_WriteString, // #58 void(float to, string s) WriteString
2524 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2525 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2526 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2527 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2528 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2529 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2530 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2532 SV_MoveToGoal, // #67 void(float step) movetogoal
2533 PF_precache_file, // #68 string(string s) precache_file
2534 PF_makestatic, // #69 void(entity e) makestatic
2535 VM_changelevel, // #70 void(string s) changelevel
2537 VM_cvar_set, // #72 void(string var, string val) cvar_set
2538 PF_centerprint, // #73 void(entity client, strings) centerprint
2539 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2540 PF_precache_model, // #75 string(string s) precache_model2
2541 PF_precache_sound, // #76 string(string s) precache_sound2
2542 PF_precache_file, // #77 string(string s) precache_file2
2543 PF_setspawnparms, // #78 void(entity e) setspawnparms
2546 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2555 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2556 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2557 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2558 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2559 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2560 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2561 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2562 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2563 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2564 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2575 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2576 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2577 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2578 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2579 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2580 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2581 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2582 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2583 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2584 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2585 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2586 // FTEQW range #200-#299
2605 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2615 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2616 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2617 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2618 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2619 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2620 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2621 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2622 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2623 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2624 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2625 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2626 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2627 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2628 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2629 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2630 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2631 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2632 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2633 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2634 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2635 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2636 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2637 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2638 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2639 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2640 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2641 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2642 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2643 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2644 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2645 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2646 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2647 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2648 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2649 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2650 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2651 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2652 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2653 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2654 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2655 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2656 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2657 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2658 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2659 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2660 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2661 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2662 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2663 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2664 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2665 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2666 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2667 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2668 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2669 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2670 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2671 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2672 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2673 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2675 PF_edict_num, // #459 entity(float num) (??)
2676 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2677 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2678 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2679 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2680 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2681 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2682 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2683 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2684 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2685 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2686 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2696 e10, e10 // #471-499 (LordHavoc)
2699 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2701 void VM_SV_Cmd_Init(void)
2706 void VM_SV_Cmd_Reset(void)