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"}; //"0.93"}; // LordHavoc: disabled autoaim by default
10 char *vm_sv_extensions =
12 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
38 "DP_GFX_QUAKE3MODELTAGS "
42 "DP_HALFLIFE_MAP_CVAR "
48 "DP_MOVETYPEBOUNCEMISSILE "
55 "DP_QC_FINDCHAINFLAGS "
56 "DP_QC_FINDCHAINFLOAT "
59 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
64 "DP_QC_MULTIPLETEMPSTRINGS "
66 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_TRACE_MOVETYPE_HITMODEL "
70 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
71 "DP_QC_VECTORVECTORS "
77 "DP_SND_DIRECTIONLESSATTNNONE "
86 "DP_SV_DRAWONLYTOCLIENT "
89 "DP_SV_NODRAWTOCLIENT "
91 "DP_SV_PLAYERPHYSICS "
92 "DP_SV_PRECACHEANYTIME "
94 "DP_SV_ROTATINGBMODEL "
100 "DP_TE_EXPLOSIONRGB "
102 "DP_TE_PARTICLECUBE "
103 "DP_TE_PARTICLERAIN "
104 "DP_TE_PARTICLESNOW "
106 "DP_TE_QUADEFFECTS1 "
109 "DP_TE_STANDARDEFFECTBUILTINS "
112 "KRIMZON_SV_PARSECLIENTCOMMAND "
116 "PRYDON_CLIENTCURSOR "
117 "TENEBRAE_GFX_DLIGHTS "
119 "NEXUIZ_PLAYERMODEL "
126 Writes new values for v_forward, v_up, and v_right based on angles
130 void PF_makevectors (void)
132 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
139 Writes new values for v_forward, v_up, and v_right based on the given forward vector
140 vectorvectors(vector, vector)
143 void PF_vectorvectors (void)
145 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
146 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
153 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.
155 setorigin (entity, origin)
158 void PF_setorigin (void)
163 e = PRVM_G_EDICT(OFS_PARM0);
164 if (e == prog->edicts)
165 PF_WARNING("setorigin: can not modify world entity\n");
166 if (e->priv.server->free)
167 PF_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\n");
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 void PF_setsize (void)
205 e = PRVM_G_EDICT(OFS_PARM0);
206 if (e == prog->edicts)
207 PF_WARNING("setsize: can not modify world entity\n");
208 if (e->priv.server->free)
209 PF_WARNING("setsize: can not modify free entity\n");
210 min = PRVM_G_VECTOR(OFS_PARM1);
211 max = PRVM_G_VECTOR(OFS_PARM2);
212 SetMinMaxSize (e, min, max, false);
220 setmodel(entity, model)
223 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
224 void PF_setmodel (void)
230 e = PRVM_G_EDICT(OFS_PARM0);
231 if (e == prog->edicts)
232 PF_WARNING("setmodel: can not modify world entity\n");
233 if (e->priv.server->free)
234 PF_WARNING("setmodel: can not modify free entity\n");
235 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
236 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
237 e->fields.server->modelindex = i;
243 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
244 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
246 SetMinMaxSize (e, quakemins, quakemaxs, true);
249 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
256 single print to a specific client
258 sprint(clientent, value)
261 void PF_sprint (void)
265 char string[VM_STRINGTEMP_LENGTH];
267 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
269 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
271 Con_Print("tried to sprint to a non-client\n");
275 client = svs.clients + entnum-1;
276 VM_VarString(1, string, sizeof(string));
277 MSG_WriteChar(&client->message,svc_print);
278 MSG_WriteString(&client->message, string);
286 single print to a specific client
288 centerprint(clientent, value)
291 void PF_centerprint (void)
295 char string[VM_STRINGTEMP_LENGTH];
297 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
299 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
301 Con_Print("tried to sprint to a non-client\n");
305 client = svs.clients + entnum-1;
306 VM_VarString(1, string, sizeof(string));
307 MSG_WriteChar(&client->message,svc_centerprint);
308 MSG_WriteString(&client->message, string);
315 particle(origin, color, count)
318 void PF_particle (void)
324 org = PRVM_G_VECTOR(OFS_PARM0);
325 dir = PRVM_G_VECTOR(OFS_PARM1);
326 color = PRVM_G_FLOAT(OFS_PARM2);
327 count = PRVM_G_FLOAT(OFS_PARM3);
328 SV_StartParticle (org, dir, color, count);
338 void PF_ambientsound (void)
342 float vol, attenuation;
345 pos = PRVM_G_VECTOR (OFS_PARM0);
346 samp = PRVM_G_STRING(OFS_PARM1);
347 vol = PRVM_G_FLOAT(OFS_PARM2);
348 attenuation = PRVM_G_FLOAT(OFS_PARM3);
350 // check to see if samp was properly precached
351 soundnum = SV_SoundIndex(samp, 1);
359 // add an svc_spawnambient command to the level signon packet
362 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
364 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
366 MSG_WriteVector(&sv.signon, pos, sv.protocol);
369 MSG_WriteShort (&sv.signon, soundnum);
371 MSG_WriteByte (&sv.signon, soundnum);
373 MSG_WriteByte (&sv.signon, vol*255);
374 MSG_WriteByte (&sv.signon, attenuation*64);
382 Each entity can have eight independant sound sources, like voice,
385 Channel 0 is an auto-allocate channel, the others override anything
386 already running on that entity/channel pair.
388 An attenuation of 0 will play full volume everywhere in the level.
389 Larger attenuations will drop off.
397 prvm_edict_t *entity;
401 entity = PRVM_G_EDICT(OFS_PARM0);
402 channel = PRVM_G_FLOAT(OFS_PARM1);
403 sample = PRVM_G_STRING(OFS_PARM2);
404 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
405 attenuation = PRVM_G_FLOAT(OFS_PARM4);
407 if (volume < 0 || volume > 255)
408 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
410 if (attenuation < 0 || attenuation > 4)
411 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
413 if (channel < 0 || channel > 7)
414 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
416 SV_StartSound (entity, channel, sample, volume, attenuation);
423 Used for use tracing and shot targeting
424 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
425 if the tryents flag is set.
427 traceline (vector1, vector2, tryents)
430 void PF_traceline (void)
437 prog->xfunction->builtinsprofile += 30;
439 v1 = PRVM_G_VECTOR(OFS_PARM0);
440 v2 = PRVM_G_VECTOR(OFS_PARM1);
441 move = PRVM_G_FLOAT(OFS_PARM2);
442 ent = PRVM_G_EDICT(OFS_PARM3);
444 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
446 prog->globals.server->trace_allsolid = trace.allsolid;
447 prog->globals.server->trace_startsolid = trace.startsolid;
448 prog->globals.server->trace_fraction = trace.fraction;
449 prog->globals.server->trace_inwater = trace.inwater;
450 prog->globals.server->trace_inopen = trace.inopen;
451 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
452 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
453 prog->globals.server->trace_plane_dist = trace.plane.dist;
455 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
457 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
458 // FIXME: add trace_endcontents
466 Used for use tracing and shot targeting
467 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
468 if the tryents flag is set.
470 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
473 // LordHavoc: added this for my own use, VERY useful, similar to traceline
474 void PF_tracebox (void)
476 float *v1, *v2, *m1, *m2;
481 prog->xfunction->builtinsprofile += 30;
483 v1 = PRVM_G_VECTOR(OFS_PARM0);
484 m1 = PRVM_G_VECTOR(OFS_PARM1);
485 m2 = PRVM_G_VECTOR(OFS_PARM2);
486 v2 = PRVM_G_VECTOR(OFS_PARM3);
487 move = PRVM_G_FLOAT(OFS_PARM4);
488 ent = PRVM_G_EDICT(OFS_PARM5);
490 trace = SV_Move (v1, m1, m2, v2, move, ent);
492 prog->globals.server->trace_allsolid = trace.allsolid;
493 prog->globals.server->trace_startsolid = trace.startsolid;
494 prog->globals.server->trace_fraction = trace.fraction;
495 prog->globals.server->trace_inwater = trace.inwater;
496 prog->globals.server->trace_inopen = trace.inopen;
497 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
498 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
499 prog->globals.server->trace_plane_dist = trace.plane.dist;
501 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
503 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
506 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
507 void PF_tracetoss (void)
511 prvm_edict_t *ignore;
513 prog->xfunction->builtinsprofile += 600;
515 ent = PRVM_G_EDICT(OFS_PARM0);
516 if (ent == prog->edicts)
517 PF_WARNING("tracetoss: can not use world entity\n");
518 ignore = PRVM_G_EDICT(OFS_PARM1);
520 trace = SV_Trace_Toss (ent, ignore);
522 prog->globals.server->trace_allsolid = trace.allsolid;
523 prog->globals.server->trace_startsolid = trace.startsolid;
524 prog->globals.server->trace_fraction = trace.fraction;
525 prog->globals.server->trace_inwater = trace.inwater;
526 prog->globals.server->trace_inopen = trace.inopen;
527 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
528 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
529 prog->globals.server->trace_plane_dist = trace.plane.dist;
531 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
533 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
541 Returns true if the given entity can move to the given position from it's
542 current position by walking or rolling.
544 scalar checkpos (entity, vector)
547 void PF_checkpos (void)
551 //============================================================================
554 qbyte checkpvs[MAX_MAP_LEAFS/8];
556 int PF_newcheckclient (int check)
562 // cycle to the next one
564 check = bound(1, check, svs.maxclients);
565 if (check == svs.maxclients)
573 prog->xfunction->builtinsprofile++;
575 if (i == svs.maxclients+1)
577 // look up the client's edict
578 ent = PRVM_EDICT_NUM(i);
579 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
580 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
582 // found a valid client (possibly the same one again)
586 // get the PVS for the entity
587 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
589 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
590 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
599 Returns a client (or object that has a client enemy) that would be a
602 If there is more than one valid option, they are cycled each frame
604 If (self.origin + self.viewofs) is not in the PVS of the current target,
605 it is not returned at all.
610 int c_invis, c_notvis;
611 void PF_checkclient (void)
613 prvm_edict_t *ent, *self;
616 // find a new check if on a new frame
617 if (sv.time - sv.lastchecktime >= 0.1)
619 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
620 sv.lastchecktime = sv.time;
623 // return check if it might be visible
624 ent = PRVM_EDICT_NUM(sv.lastcheck);
625 if (ent->priv.server->free || ent->fields.server->health <= 0)
627 VM_RETURN_EDICT(prog->edicts);
631 // if current entity can't possibly see the check entity, return 0
632 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
633 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
634 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
637 VM_RETURN_EDICT(prog->edicts);
641 // might be able to see it
643 VM_RETURN_EDICT(ent);
646 //============================================================================
653 Sends text over to the client's execution buffer
655 stuffcmd (clientent, value)
658 void PF_stuffcmd (void)
664 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
665 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
667 Con_Print("Can't stuffcmd to a non-client\n");
670 str = PRVM_G_STRING(OFS_PARM1);
673 host_client = svs.clients + entnum-1;
674 Host_ClientCommands ("%s", str);
682 Returns a chain of entities that have origins within a spherical area
684 findradius (origin, radius)
687 void PF_findradius (void)
689 prvm_edict_t *ent, *chain;
690 vec_t radius, radius2;
691 vec3_t org, eorg, mins, maxs;
694 prvm_edict_t *touchedicts[MAX_EDICTS];
696 chain = (prvm_edict_t *)prog->edicts;
698 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
699 radius = PRVM_G_FLOAT(OFS_PARM1);
700 radius2 = radius * radius;
702 mins[0] = org[0] - (radius + 1);
703 mins[1] = org[1] - (radius + 1);
704 mins[2] = org[2] - (radius + 1);
705 maxs[0] = org[0] + (radius + 1);
706 maxs[1] = org[1] + (radius + 1);
707 maxs[2] = org[2] + (radius + 1);
708 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
709 if (numtouchedicts > MAX_EDICTS)
711 // this never happens
712 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
713 numtouchedicts = MAX_EDICTS;
715 for (i = 0;i < numtouchedicts;i++)
717 ent = touchedicts[i];
718 prog->xfunction->builtinsprofile++;
719 // Quake did not return non-solid entities but darkplaces does
720 // (note: this is the reason you can't blow up fallen zombies)
721 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
723 // LordHavoc: compare against bounding box rather than center so it
724 // doesn't miss large objects, and use DotProduct instead of Length
725 // for a major speedup
726 VectorSubtract(org, ent->fields.server->origin, eorg);
727 if (sv_gameplayfix_findradiusdistancetobox.integer)
729 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
730 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
731 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
734 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
735 if (DotProduct(eorg, eorg) < radius2)
737 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
742 VM_RETURN_EDICT(chain);
745 void PF_precache_file (void)
746 { // precache_file is only used to copy files with qcc, it does nothing
747 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
751 void PF_precache_sound (void)
753 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
754 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
757 void PF_precache_model (void)
759 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
760 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
767 float(float yaw, float dist) walkmove
770 void PF_walkmove (void)
778 // assume failure if it returns early
779 PRVM_G_FLOAT(OFS_RETURN) = 0;
781 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
782 if (ent == prog->edicts)
783 PF_WARNING("walkmove: can not modify world entity\n");
784 if (ent->priv.server->free)
785 PF_WARNING("walkmove: can not modify free entity\n");
786 yaw = PRVM_G_FLOAT(OFS_PARM0);
787 dist = PRVM_G_FLOAT(OFS_PARM1);
789 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
792 yaw = yaw*M_PI*2 / 360;
794 move[0] = cos(yaw)*dist;
795 move[1] = sin(yaw)*dist;
798 // save program state, because SV_movestep may call other progs
799 oldf = prog->xfunction;
800 oldself = prog->globals.server->self;
802 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
805 // restore program state
806 prog->xfunction = oldf;
807 prog->globals.server->self = oldself;
817 void PF_droptofloor (void)
823 // assume failure if it returns early
824 PRVM_G_FLOAT(OFS_RETURN) = 0;
826 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
827 if (ent == prog->edicts)
828 PF_WARNING("droptofloor: can not modify world entity\n");
829 if (ent->priv.server->free)
830 PF_WARNING("droptofloor: can not modify free entity\n");
832 VectorCopy (ent->fields.server->origin, end);
835 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
837 if (trace.fraction != 1)
839 VectorCopy (trace.endpos, ent->fields.server->origin);
840 SV_LinkEdict (ent, false);
841 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
842 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
843 PRVM_G_FLOAT(OFS_RETURN) = 1;
844 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
845 ent->priv.server->suspendedinairflag = true;
853 void(float style, string value) lightstyle
856 void PF_lightstyle (void)
863 style = PRVM_G_FLOAT(OFS_PARM0);
864 val = PRVM_G_STRING(OFS_PARM1);
866 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
867 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
870 // change the string in sv
871 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
873 // send message to all clients on this server
874 if (sv.state != ss_active)
877 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
881 MSG_WriteChar (&client->message, svc_lightstyle);
882 MSG_WriteChar (&client->message,style);
883 MSG_WriteString (&client->message, val);
893 void PF_checkbottom (void)
895 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
903 void PF_pointcontents (void)
905 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
912 Pick a vector for the player to shoot along
913 vector aim(entity, missilespeed)
918 prvm_edict_t *ent, *check, *bestent;
919 vec3_t start, dir, end, bestdir;
922 float dist, bestdist;
925 // assume failure if it returns early
926 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
927 // if sv_aim is so high it can't possibly accept anything, skip out early
928 if (sv_aim.value >= 1)
931 ent = PRVM_G_EDICT(OFS_PARM0);
932 if (ent == prog->edicts)
933 PF_WARNING("aim: can not use world entity\n");
934 if (ent->priv.server->free)
935 PF_WARNING("aim: can not use free entity\n");
936 speed = PRVM_G_FLOAT(OFS_PARM1);
938 VectorCopy (ent->fields.server->origin, start);
941 // try sending a trace straight
942 VectorCopy (prog->globals.server->v_forward, dir);
943 VectorMA (start, 2048, dir, end);
944 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
945 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
946 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
948 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
953 // try all possible entities
954 VectorCopy (dir, bestdir);
955 bestdist = sv_aim.value;
958 check = PRVM_NEXT_EDICT(prog->edicts);
959 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
961 prog->xfunction->builtinsprofile++;
962 if (check->fields.server->takedamage != DAMAGE_AIM)
966 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
967 continue; // don't aim at teammate
968 for (j=0 ; j<3 ; j++)
969 end[j] = check->fields.server->origin[j]
970 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
971 VectorSubtract (end, start, dir);
972 VectorNormalize (dir);
973 dist = DotProduct (dir, prog->globals.server->v_forward);
975 continue; // to far to turn
976 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
978 { // can shoot at this one
986 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
987 dist = DotProduct (dir, prog->globals.server->v_forward);
988 VectorScale (prog->globals.server->v_forward, dist, end);
990 VectorNormalize (end);
991 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
995 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1003 This was a major timewaster in progs, so it was converted to C
1006 void PF_changeyaw (void)
1009 float ideal, current, move, speed;
1011 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1012 if (ent == prog->edicts)
1013 PF_WARNING("changeyaw: can not modify world entity\n");
1014 if (ent->priv.server->free)
1015 PF_WARNING("changeyaw: can not modify free entity\n");
1016 current = ANGLEMOD(ent->fields.server->angles[1]);
1017 ideal = ent->fields.server->ideal_yaw;
1018 speed = ent->fields.server->yaw_speed;
1020 if (current == ideal)
1022 move = ideal - current;
1023 if (ideal > current)
1044 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1052 void PF_changepitch (void)
1055 float ideal, current, move, speed;
1058 ent = PRVM_G_EDICT(OFS_PARM0);
1059 if (ent == prog->edicts)
1060 PF_WARNING("changepitch: can not modify world entity\n");
1061 if (ent->priv.server->free)
1062 PF_WARNING("changepitch: can not modify free entity\n");
1063 current = ANGLEMOD( ent->fields.server->angles[0] );
1064 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1065 ideal = val->_float;
1068 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1071 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1072 speed = val->_float;
1075 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1079 if (current == ideal)
1081 move = ideal - current;
1082 if (ideal > current)
1103 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1107 ===============================================================================
1111 ===============================================================================
1114 #define MSG_BROADCAST 0 // unreliable to all
1115 #define MSG_ONE 1 // reliable to one (msg_entity)
1116 #define MSG_ALL 2 // reliable to all
1117 #define MSG_INIT 3 // write to the init string
1119 sizebuf_t *WriteDest (void)
1125 dest = PRVM_G_FLOAT(OFS_PARM0);
1129 return &sv.datagram;
1132 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1133 entnum = PRVM_NUM_FOR_EDICT(ent);
1134 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1136 Con_Printf ("WriteDest: tried to write to non-client\n");
1137 return &sv.reliable_datagram;
1140 return &svs.clients[entnum-1].message;
1143 Con_Printf ("WriteDest: bad destination");
1145 return &sv.reliable_datagram;
1154 void PF_WriteByte (void)
1156 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1159 void PF_WriteChar (void)
1161 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1164 void PF_WriteShort (void)
1166 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1169 void PF_WriteLong (void)
1171 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1174 void PF_WriteAngle (void)
1176 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1179 void PF_WriteCoord (void)
1181 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1184 void PF_WriteString (void)
1186 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1190 void PF_WriteEntity (void)
1192 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1195 //////////////////////////////////////////////////////////
1197 void PF_makestatic (void)
1202 ent = PRVM_G_EDICT(OFS_PARM0);
1203 if (ent == prog->edicts)
1204 PF_WARNING("makestatic: can not modify world entity\n");
1205 if (ent->priv.server->free)
1206 PF_WARNING("makestatic: can not modify free entity\n");
1209 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1214 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1215 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1216 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1220 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1221 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1222 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1225 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1226 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1227 for (i=0 ; i<3 ; i++)
1229 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1230 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1233 // throw the entity away now
1237 //=============================================================================
1244 void PF_setspawnparms (void)
1250 ent = PRVM_G_EDICT(OFS_PARM0);
1251 i = PRVM_NUM_FOR_EDICT(ent);
1252 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1254 Con_Print("tried to setspawnparms on a non-client\n");
1258 // copy spawn parms out of the client_t
1259 client = svs.clients + i-1;
1260 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1261 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1268 Returns a color vector indicating the lighting at the requested point.
1270 (Internal Operation note: actually measures the light beneath the point, just like
1271 the model lighting on the client)
1276 void PF_getlight (void)
1278 vec3_t ambientcolor, diffusecolor, diffusenormal;
1280 p = PRVM_G_VECTOR(OFS_PARM0);
1281 VectorClear(ambientcolor);
1282 VectorClear(diffusecolor);
1283 VectorClear(diffusenormal);
1284 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1285 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1286 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1289 void PF_registercvar (void)
1291 const char *name, *value;
1292 name = PRVM_G_STRING(OFS_PARM0);
1293 value = PRVM_G_STRING(OFS_PARM1);
1294 PRVM_G_FLOAT(OFS_RETURN) = 0;
1296 // first check to see if it has already been defined
1297 if (Cvar_FindVar (name))
1300 // check for overlap with a command
1301 if (Cmd_Exists (name))
1303 Con_Printf("PF_registercvar: %s is a command\n", name);
1307 Cvar_Get(name, value, 0);
1309 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1316 copies data from one entity to another
1318 copyentity(src, dst)
1321 void PF_copyentity (void)
1323 prvm_edict_t *in, *out;
1324 in = PRVM_G_EDICT(OFS_PARM0);
1325 if (in == prog->edicts)
1326 PF_WARNING("copyentity: can not read world entity\n");
1327 if (in->priv.server->free)
1328 PF_WARNING("copyentity: can not read free entity\n");
1329 out = PRVM_G_EDICT(OFS_PARM1);
1330 if (out == prog->edicts)
1331 PF_WARNING("copyentity: can not modify world entity\n");
1332 if (out->priv.server->free)
1333 PF_WARNING("copyentity: can not modify free entity\n");
1334 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1342 sets the color of a client and broadcasts the update to all connected clients
1344 setcolor(clientent, value)
1347 void PF_setcolor (void)
1353 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1354 i = PRVM_G_FLOAT(OFS_PARM1);
1356 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1358 Con_Print("tried to setcolor a non-client\n");
1362 client = svs.clients + entnum-1;
1365 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1367 client->edict->fields.server->team = (i & 15) + 1;
1370 if (client->old_colors != client->colors)
1372 client->old_colors = client->colors;
1373 // send notification to all clients
1374 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1375 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1376 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1384 effect(origin, modelname, startframe, framecount, framerate)
1387 void PF_effect (void)
1391 s = PRVM_G_STRING(OFS_PARM1);
1393 PF_WARNING("effect: no model specified\n");
1395 i = SV_ModelIndex(s, 1);
1397 PF_WARNING("effect: model not precached\n");
1398 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1401 void PF_te_blood (void)
1403 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1405 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1406 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1408 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1409 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1410 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1412 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1413 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1414 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1416 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1419 void PF_te_bloodshower (void)
1421 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1423 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1424 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1426 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1427 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1428 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1430 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1431 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1432 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1434 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1436 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1439 void PF_te_explosionrgb (void)
1441 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1442 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1444 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1445 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1446 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1448 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1449 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1450 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1453 void PF_te_particlecube (void)
1455 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1457 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1458 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1460 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1461 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1462 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1464 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1465 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1466 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1468 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1469 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1470 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1472 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1474 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1475 // gravity true/false
1476 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1478 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1481 void PF_te_particlerain (void)
1483 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1485 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1486 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1488 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1489 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1490 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1493 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1494 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1496 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1497 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1498 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1500 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1502 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1505 void PF_te_particlesnow (void)
1507 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1509 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1510 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1513 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1514 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1516 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1517 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1518 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1521 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1522 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1524 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1526 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1529 void PF_te_spark (void)
1531 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1533 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1534 MSG_WriteByte(&sv.datagram, TE_SPARK);
1536 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1537 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1538 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1540 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1541 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1542 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1544 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1547 void PF_te_gunshotquad (void)
1549 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1550 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1552 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1553 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1554 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1557 void PF_te_spikequad (void)
1559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1560 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1564 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1567 void PF_te_superspikequad (void)
1569 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1570 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1572 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1573 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1574 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1577 void PF_te_explosionquad (void)
1579 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1580 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1582 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1583 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1584 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1587 void PF_te_smallflash (void)
1589 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1590 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1592 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1593 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1594 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1597 void PF_te_customflash (void)
1599 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1601 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1602 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1610 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1612 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1613 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1614 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1617 void PF_te_gunshot (void)
1619 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1620 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1624 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1627 void PF_te_spike (void)
1629 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1630 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1634 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1637 void PF_te_superspike (void)
1639 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1640 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1644 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1647 void PF_te_explosion (void)
1649 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1650 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1657 void PF_te_tarexplosion (void)
1659 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1660 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1663 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1664 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1667 void PF_te_wizspike (void)
1669 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1670 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1673 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1674 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1677 void PF_te_knightspike (void)
1679 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1680 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1687 void PF_te_lavasplash (void)
1689 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1690 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1694 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1697 void PF_te_teleport (void)
1699 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1700 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1707 void PF_te_explosion2 (void)
1709 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1710 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1716 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1717 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1720 void PF_te_lightning1 (void)
1722 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1723 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1725 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1727 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1736 void PF_te_lightning2 (void)
1738 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1739 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1741 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1752 void PF_te_lightning3 (void)
1754 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1755 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1757 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1768 void PF_te_beam (void)
1770 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1771 MSG_WriteByte(&sv.datagram, TE_BEAM);
1773 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1784 void PF_te_plasmaburn (void)
1786 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1793 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1796 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1798 bestdist = 1000000000;
1800 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1802 // clip original point to each triangle of the surface and find the
1803 // triangle that is closest
1804 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1805 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1806 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1807 TriangleNormal(v[0], v[1], v[2], facenormal);
1808 VectorNormalize(facenormal);
1809 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1810 VectorMA(p, offsetdist, facenormal, temp);
1811 for (j = 0, k = 2;j < 3;k = j, j++)
1813 VectorSubtract(v[k], v[j], edgenormal);
1814 CrossProduct(edgenormal, facenormal, sidenormal);
1815 VectorNormalize(sidenormal);
1816 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1818 VectorMA(temp, offsetdist, sidenormal, temp);
1820 dist = VectorDistance2(temp, p);
1821 if (bestdist > dist)
1824 VectorCopy(temp, out);
1829 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1833 if (!ed || ed->priv.server->free)
1835 modelindex = ed->fields.server->modelindex;
1836 if (modelindex < 1 || modelindex >= MAX_MODELS)
1838 model = sv.models[modelindex];
1839 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1841 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1845 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1846 void PF_getsurfacenumpoints(void)
1848 msurface_t *surface;
1849 // return 0 if no such surface
1850 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1852 PRVM_G_FLOAT(OFS_RETURN) = 0;
1856 // note: this (incorrectly) assumes it is a simple polygon
1857 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1859 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1860 void PF_getsurfacepoint(void)
1863 msurface_t *surface;
1865 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1866 ed = PRVM_G_EDICT(OFS_PARM0);
1867 if (!ed || ed->priv.server->free)
1869 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1871 // note: this (incorrectly) assumes it is a simple polygon
1872 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1873 if (pointnum < 0 || pointnum >= surface->num_vertices)
1875 // FIXME: implement rotation/scaling
1876 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1878 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1879 void PF_getsurfacenormal(void)
1881 msurface_t *surface;
1883 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1884 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1886 // FIXME: implement rotation/scaling
1887 // note: this (incorrectly) assumes it is a simple polygon
1888 // note: this only returns the first triangle, so it doesn't work very
1889 // well for curved surfaces or arbitrary meshes
1890 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);
1891 VectorNormalize(normal);
1892 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1894 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1895 void PF_getsurfacetexture(void)
1897 msurface_t *surface;
1898 PRVM_G_INT(OFS_RETURN) = 0;
1899 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1901 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1903 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1904 void PF_getsurfacenearpoint(void)
1906 int surfacenum, best, modelindex;
1908 vec_t dist, bestdist;
1911 msurface_t *surface;
1913 PRVM_G_FLOAT(OFS_RETURN) = -1;
1914 ed = PRVM_G_EDICT(OFS_PARM0);
1915 point = PRVM_G_VECTOR(OFS_PARM1);
1917 if (!ed || ed->priv.server->free)
1919 modelindex = ed->fields.server->modelindex;
1920 if (modelindex < 1 || modelindex >= MAX_MODELS)
1922 model = sv.models[modelindex];
1923 if (!model->num_surfaces)
1926 // FIXME: implement rotation/scaling
1927 VectorSubtract(point, ed->fields.server->origin, p);
1929 bestdist = 1000000000;
1930 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1932 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1933 // first see if the nearest point on the surface's box is closer than the previous match
1934 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1935 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1936 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1937 dist = VectorLength2(clipped);
1938 if (dist < bestdist)
1940 // it is, check the nearest point on the actual geometry
1941 clippointtosurface(surface, p, clipped);
1942 VectorSubtract(clipped, p, clipped);
1943 dist += VectorLength2(clipped);
1944 if (dist < bestdist)
1946 // that's closer too, store it as the best match
1952 PRVM_G_FLOAT(OFS_RETURN) = best;
1954 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1955 void PF_getsurfaceclippedpoint(void)
1958 msurface_t *surface;
1960 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1961 ed = PRVM_G_EDICT(OFS_PARM0);
1962 if (!ed || ed->priv.server->free)
1964 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1966 // FIXME: implement rotation/scaling
1967 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1968 clippointtosurface(surface, p, out);
1969 // FIXME: implement rotation/scaling
1970 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1973 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1974 //this function originally written by KrimZon, made shorter by LordHavoc
1975 void PF_clientcommand (void)
1977 client_t *temp_client;
1980 //find client for this entity
1981 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
1982 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1984 Con_Print("PF_clientcommand: entity is not a client\n");
1988 temp_client = host_client;
1989 host_client = svs.clients + i;
1990 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1991 host_client = temp_client;
1994 //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)
1995 void PF_setattachment (void)
1997 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1998 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1999 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2004 if (e == prog->edicts)
2005 PF_WARNING("setattachment: can not modify world entity\n");
2006 if (e->priv.server->free)
2007 PF_WARNING("setattachment: can not modify free entity\n");
2009 if (tagentity == NULL)
2010 tagentity = prog->edicts;
2012 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2014 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2016 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2019 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2021 modelindex = (int)tagentity->fields.server->modelindex;
2022 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2024 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2026 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);
2029 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));
2033 /////////////////////////////////////////
2034 // DP_MD3_TAGINFO extension coded by VorteX
2036 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2041 i = e->fields.server->modelindex;
2042 if (i < 1 || i >= MAX_MODELS)
2044 model = sv.models[i];
2046 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2049 // Warnings/errors code:
2050 // 0 - normal (everything all-right)
2053 // 3 - null or non-precached model
2054 // 4 - no tags with requested index
2055 // 5 - runaway loop at attachment chain
2056 extern cvar_t cl_bob;
2057 extern cvar_t cl_bobcycle;
2058 extern cvar_t cl_bobup;
2059 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2062 int modelindex, reqframe, attachloop;
2063 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2064 prvm_edict_t *attachent;
2067 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2069 if (ent == prog->edicts)
2071 if (ent->priv.server->free)
2074 modelindex = (int)ent->fields.server->modelindex;
2075 if (modelindex <= 0 || modelindex > MAX_MODELS)
2078 model = sv.models[modelindex];
2080 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2081 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2083 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2085 // get initial tag matrix
2088 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2093 Matrix4x4_CreateIdentity(&tagmatrix);
2095 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2096 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2100 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2101 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2102 if (val->_float >= 1 && attachent->fields.server->modelindex >= 1 && attachent->fields.server->modelindex < MAX_MODELS && (model = sv.models[(int)attachent->fields.server->modelindex]) && model->animscenes && attachent->fields.server->frame >= 0 && attachent->fields.server->frame < model->numframes)
2103 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2105 Matrix4x4_CreateIdentity(&attachmatrix);
2107 // apply transformation by child entity matrix
2108 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2109 if (val->_float == 0)
2111 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], val->_float);
2112 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2113 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2114 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2115 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2116 Matrix4x4_Copy(&tagmatrix, out);
2118 // finally transformate by matrix of tag on parent entity
2119 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2120 out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
2121 out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
2122 out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
2123 Matrix4x4_Copy(&tagmatrix, out);
2127 if (attachloop > 255) // prevent runaway looping
2130 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2133 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2134 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2135 if (val->_float == 0)
2137 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2138 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], val->_float);
2139 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2140 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2141 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2142 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2144 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2145 {// RENDER_VIEWMODEL magic
2146 Matrix4x4_Copy(&tagmatrix, out);
2147 ent = PRVM_EDICT_NUM(val->edict);
2149 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2150 if (val->_float == 0)
2153 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, 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], val->_float);
2154 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2155 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2156 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2157 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2160 // Cl_bob, ported from rendering code
2161 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2164 // LordHavoc: this code is *weird*, but not replacable (I think it
2165 // should be done in QC on the server, but oh well, quake is quake)
2166 // LordHavoc: figured out bobup: the time at which the sin is at 180
2167 // degrees (which allows lengthening or squishing the peak or valley)
2168 cycle = sv.time/cl_bobcycle.value;
2169 cycle -= (int)cycle;
2170 if (cycle < cl_bobup.value)
2171 cycle = sin(M_PI * cycle / cl_bobup.value);
2173 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2174 // bob is proportional to velocity in the xy plane
2175 // (don't count Z, or jumping messes it up)
2176 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;
2177 bob = bob*0.3 + bob*0.7*cycle;
2178 out->m[2][3] += bound(-7, bob, 4);
2185 //float(entity ent, string tagname) gettagindex;
2187 void PF_gettagindex (void)
2189 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2190 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2191 int modelindex, tag_index;
2193 if (ent == prog->edicts)
2194 PF_WARNING("gettagindex: can't affect world entity\n");
2195 if (ent->priv.server->free)
2196 PF_WARNING("gettagindex: can't affect free entity\n");
2198 modelindex = (int)ent->fields.server->modelindex;
2200 if (modelindex <= 0 || modelindex > MAX_MODELS)
2201 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2204 tag_index = SV_GetTagIndex(ent, tag_name);
2206 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2208 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2211 //vector(entity ent, float tagindex) gettaginfo;
2212 void PF_gettaginfo (void)
2214 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2215 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2216 matrix4x4_t tag_matrix;
2219 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2220 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2225 PF_WARNING("gettagindex: can't affect world entity\n");
2228 PF_WARNING("gettagindex: can't affect free entity\n");
2231 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2234 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2237 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2242 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2243 void PF_dropclient (void)
2246 client_t *oldhostclient;
2247 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2248 if (clientnum < 0 || clientnum >= svs.maxclients)
2249 PF_WARNING("dropclient: not a client\n");
2250 if (!svs.clients[clientnum].active)
2251 PF_WARNING("dropclient: that client slot is not connected\n");
2252 oldhostclient = host_client;
2253 host_client = svs.clients + clientnum;
2254 SV_DropClient(false);
2255 host_client = oldhostclient;
2258 //entity() spawnclient (DP_SV_BOTCLIENT)
2259 void PF_spawnclient (void)
2263 prog->xfunction->builtinsprofile += 2;
2265 for (i = 0;i < svs.maxclients;i++)
2267 if (!svs.clients[i].active)
2269 prog->xfunction->builtinsprofile += 100;
2270 SV_ConnectClient (i, NULL);
2271 ed = PRVM_EDICT_NUM(i + 1);
2275 VM_RETURN_EDICT(ed);
2278 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2279 void PF_clienttype (void)
2282 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2283 if (clientnum < 0 || clientnum >= svs.maxclients)
2284 PRVM_G_FLOAT(OFS_RETURN) = 3;
2285 else if (!svs.clients[clientnum].active)
2286 PRVM_G_FLOAT(OFS_RETURN) = 0;
2287 else if (svs.clients[clientnum].netconnection)
2288 PRVM_G_FLOAT(OFS_RETURN) = 1;
2290 PRVM_G_FLOAT(OFS_RETURN) = 2;
2293 prvm_builtin_t vm_sv_builtins[] = {
2295 PF_makevectors, // #1 void(entity e) makevectors
2296 PF_setorigin, // #2 void(entity e, vector o) setorigin
2297 PF_setmodel, // #3 void(entity e, string m) setmodel
2298 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2299 NULL, // #5 void(entity e, vector min, vector max) setabssize
2300 VM_break, // #6 void() break
2301 VM_random, // #7 float() random
2302 PF_sound, // #8 void(entity e, float chan, string samp) sound
2303 VM_normalize, // #9 vector(vector v) normalize
2304 VM_error, // #10 void(string e) error
2305 VM_objerror, // #11 void(string e) objerror
2306 VM_vlen, // #12 float(vector v) vlen
2307 VM_vectoyaw, // #13 float(vector v) vectoyaw
2308 VM_spawn, // #14 entity() spawn
2309 VM_remove, // #15 void(entity e) remove
2310 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2311 PF_checkclient, // #17 entity() clientlist
2312 VM_find, // #18 entity(entity start, .string fld, string match) find
2313 PF_precache_sound, // #19 void(string s) precache_sound
2314 PF_precache_model, // #20 void(string s) precache_model
2315 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2316 PF_findradius, // #22 entity(vector org, float rad) findradius
2317 VM_bprint, // #23 void(string s) bprint
2318 PF_sprint, // #24 void(entity client, string s) sprint
2319 VM_dprint, // #25 void(string s) dprint
2320 VM_ftos, // #26 void(string s) ftos
2321 VM_vtos, // #27 void(string s) vtos
2322 VM_coredump, // #28 void() coredump
2323 VM_traceon, // #29 void() traceon
2324 VM_traceoff, // #30 void() traceoff
2325 VM_eprint, // #31 void(entity e) eprint
2326 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2328 PF_droptofloor, // #34 float() droptofloor
2329 PF_lightstyle, // #35 void(float style, string value) lightstyle
2330 VM_rint, // #36 float(float v) rint
2331 VM_floor, // #37 float(float v) floor
2332 VM_ceil, // #38 float(float v) ceil
2334 PF_checkbottom, // #40 float(entity e) checkbottom
2335 PF_pointcontents, // #41 float(vector v) pointcontents
2337 VM_fabs, // #43 float(float f) fabs
2338 PF_aim, // #44 vector(entity e, float speed) aim
2339 VM_cvar, // #45 float(string s) cvar
2340 VM_localcmd, // #46 void(string s) localcmd
2341 VM_nextent, // #47 entity(entity e) nextent
2342 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2343 PF_changeyaw, // #49 void() ChangeYaw
2345 VM_vectoangles, // #51 vector(vector v) vectoangles
2346 PF_WriteByte, // #52 void(float to, float f) WriteByte
2347 PF_WriteChar, // #53 void(float to, float f) WriteChar
2348 PF_WriteShort, // #54 void(float to, float f) WriteShort
2349 PF_WriteLong, // #55 void(float to, float f) WriteLong
2350 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2351 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2352 PF_WriteString, // #58 void(float to, string s) WriteString
2353 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2354 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2355 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2356 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2357 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2358 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2359 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2361 SV_MoveToGoal, // #67 void(float step) movetogoal
2362 PF_precache_file, // #68 string(string s) precache_file
2363 PF_makestatic, // #69 void(entity e) makestatic
2364 VM_changelevel, // #70 void(string s) changelevel
2366 VM_cvar_set, // #72 void(string var, string val) cvar_set
2367 PF_centerprint, // #73 void(entity client, strings) centerprint
2368 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2369 PF_precache_model, // #75 string(string s) precache_model2
2370 PF_precache_sound, // #76 string(string s) precache_sound2
2371 PF_precache_file, // #77 string(string s) precache_file2
2372 PF_setspawnparms, // #78 void(entity e) setspawnparms
2375 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2384 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2385 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2386 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2387 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2388 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2389 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2390 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2391 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2392 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2393 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2404 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2405 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2406 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2407 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2408 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2409 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2410 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2411 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2412 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2413 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2414 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2415 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2416 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2417 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2418 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2419 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2420 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2421 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2422 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2423 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2424 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2425 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2426 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2427 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2428 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2429 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2430 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2431 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2432 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2433 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2434 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2435 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2436 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2437 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2438 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2439 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2440 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2441 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2442 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2443 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2444 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2445 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2446 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2447 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2448 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2449 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2450 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2451 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2452 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2453 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2454 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2455 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2456 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2457 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2458 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2459 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2460 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2461 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2462 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2463 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2464 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2465 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2466 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2467 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2468 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2469 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2470 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2471 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2472 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2477 e10, e10, e10, e10 // #460-499 (LordHavoc)
2480 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2482 void VM_SV_Cmd_Init(void)
2487 void VM_SV_Cmd_Reset(void)