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 "
93 "DP_SV_ROTATINGBMODEL "
101 "DP_TE_PARTICLECUBE "
102 "DP_TE_PARTICLERAIN "
103 "DP_TE_PARTICLESNOW "
105 "DP_TE_QUADEFFECTS1 "
108 "DP_TE_STANDARDEFFECTBUILTINS "
111 "KRIMZON_SV_PARSECLIENTCOMMAND "
115 "PRYDON_CLIENTCURSOR "
116 "TENEBRAE_GFX_DLIGHTS "
118 "NEXUIZ_PLAYERMODEL "
125 Writes new values for v_forward, v_up, and v_right based on angles
129 void PF_makevectors (void)
131 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
138 Writes new values for v_forward, v_up, and v_right based on the given forward vector
139 vectorvectors(vector, vector)
142 void PF_vectorvectors (void)
144 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
145 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
152 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.
154 setorigin (entity, origin)
157 void PF_setorigin (void)
162 e = PRVM_G_EDICT(OFS_PARM0);
163 if (e == prog->edicts)
164 PF_WARNING("setorigin: can not modify world entity\n");
165 if (e->priv.server->free)
166 PF_WARNING("setorigin: can not modify free entity\n");
167 org = PRVM_G_VECTOR(OFS_PARM1);
168 VectorCopy (org, e->fields.server->origin);
169 SV_LinkEdict (e, false);
173 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
177 for (i=0 ; i<3 ; i++)
179 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs\n");
181 // set derived values
182 VectorCopy (min, e->fields.server->mins);
183 VectorCopy (max, e->fields.server->maxs);
184 VectorSubtract (max, min, e->fields.server->size);
186 SV_LinkEdict (e, false);
193 the size box is rotated by the current angle
194 LordHavoc: no it isn't...
196 setsize (entity, minvector, maxvector)
199 void PF_setsize (void)
204 e = PRVM_G_EDICT(OFS_PARM0);
205 if (e == prog->edicts)
206 PF_WARNING("setsize: can not modify world entity\n");
207 if (e->priv.server->free)
208 PF_WARNING("setsize: can not modify free entity\n");
209 min = PRVM_G_VECTOR(OFS_PARM1);
210 max = PRVM_G_VECTOR(OFS_PARM2);
211 SetMinMaxSize (e, min, max, false);
219 setmodel(entity, model)
222 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
223 void PF_setmodel (void)
229 e = PRVM_G_EDICT(OFS_PARM0);
230 if (e == prog->edicts)
231 PF_WARNING("setmodel: can not modify world entity\n");
232 if (e->priv.server->free)
233 PF_WARNING("setmodel: can not modify free entity\n");
234 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
235 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
236 e->fields.server->modelindex = i;
242 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
243 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
245 SetMinMaxSize (e, quakemins, quakemaxs, true);
248 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
255 single print to a specific client
257 sprint(clientent, value)
260 void PF_sprint (void)
264 char string[VM_STRINGTEMP_LENGTH];
266 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
268 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
270 Con_Print("tried to sprint to a non-client\n");
274 client = svs.clients + entnum-1;
275 VM_VarString(1, string, sizeof(string));
276 MSG_WriteChar(&client->message,svc_print);
277 MSG_WriteString(&client->message, string);
285 single print to a specific client
287 centerprint(clientent, value)
290 void PF_centerprint (void)
294 char string[VM_STRINGTEMP_LENGTH];
296 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
298 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
300 Con_Print("tried to sprint to a non-client\n");
304 client = svs.clients + entnum-1;
305 VM_VarString(1, string, sizeof(string));
306 MSG_WriteChar(&client->message,svc_centerprint);
307 MSG_WriteString(&client->message, string);
314 particle(origin, color, count)
317 void PF_particle (void)
323 org = PRVM_G_VECTOR(OFS_PARM0);
324 dir = PRVM_G_VECTOR(OFS_PARM1);
325 color = PRVM_G_FLOAT(OFS_PARM2);
326 count = PRVM_G_FLOAT(OFS_PARM3);
327 SV_StartParticle (org, dir, color, count);
337 void PF_ambientsound (void)
341 float vol, attenuation;
344 pos = PRVM_G_VECTOR (OFS_PARM0);
345 samp = PRVM_G_STRING(OFS_PARM1);
346 vol = PRVM_G_FLOAT(OFS_PARM2);
347 attenuation = PRVM_G_FLOAT(OFS_PARM3);
349 // check to see if samp was properly precached
350 soundnum = SV_SoundIndex(samp, 1);
358 // add an svc_spawnambient command to the level signon packet
361 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
363 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
365 MSG_WriteVector(&sv.signon, pos, sv.protocol);
368 MSG_WriteShort (&sv.signon, soundnum);
370 MSG_WriteByte (&sv.signon, soundnum);
372 MSG_WriteByte (&sv.signon, vol*255);
373 MSG_WriteByte (&sv.signon, attenuation*64);
381 Each entity can have eight independant sound sources, like voice,
384 Channel 0 is an auto-allocate channel, the others override anything
385 already running on that entity/channel pair.
387 An attenuation of 0 will play full volume everywhere in the level.
388 Larger attenuations will drop off.
396 prvm_edict_t *entity;
400 entity = PRVM_G_EDICT(OFS_PARM0);
401 channel = PRVM_G_FLOAT(OFS_PARM1);
402 sample = PRVM_G_STRING(OFS_PARM2);
403 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
404 attenuation = PRVM_G_FLOAT(OFS_PARM4);
406 if (volume < 0 || volume > 255)
407 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
409 if (attenuation < 0 || attenuation > 4)
410 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
412 if (channel < 0 || channel > 7)
413 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
415 SV_StartSound (entity, channel, sample, volume, attenuation);
422 Used for use tracing and shot targeting
423 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
424 if the tryents flag is set.
426 traceline (vector1, vector2, tryents)
429 void PF_traceline (void)
436 prog->xfunction->builtinsprofile += 30;
438 v1 = PRVM_G_VECTOR(OFS_PARM0);
439 v2 = PRVM_G_VECTOR(OFS_PARM1);
440 move = PRVM_G_FLOAT(OFS_PARM2);
441 ent = PRVM_G_EDICT(OFS_PARM3);
443 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
445 prog->globals.server->trace_allsolid = trace.allsolid;
446 prog->globals.server->trace_startsolid = trace.startsolid;
447 prog->globals.server->trace_fraction = trace.fraction;
448 prog->globals.server->trace_inwater = trace.inwater;
449 prog->globals.server->trace_inopen = trace.inopen;
450 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
451 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
452 prog->globals.server->trace_plane_dist = trace.plane.dist;
454 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
456 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
457 // FIXME: add trace_endcontents
465 Used for use tracing and shot targeting
466 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
467 if the tryents flag is set.
469 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
472 // LordHavoc: added this for my own use, VERY useful, similar to traceline
473 void PF_tracebox (void)
475 float *v1, *v2, *m1, *m2;
480 prog->xfunction->builtinsprofile += 30;
482 v1 = PRVM_G_VECTOR(OFS_PARM0);
483 m1 = PRVM_G_VECTOR(OFS_PARM1);
484 m2 = PRVM_G_VECTOR(OFS_PARM2);
485 v2 = PRVM_G_VECTOR(OFS_PARM3);
486 move = PRVM_G_FLOAT(OFS_PARM4);
487 ent = PRVM_G_EDICT(OFS_PARM5);
489 trace = SV_Move (v1, m1, m2, v2, move, ent);
491 prog->globals.server->trace_allsolid = trace.allsolid;
492 prog->globals.server->trace_startsolid = trace.startsolid;
493 prog->globals.server->trace_fraction = trace.fraction;
494 prog->globals.server->trace_inwater = trace.inwater;
495 prog->globals.server->trace_inopen = trace.inopen;
496 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
497 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
498 prog->globals.server->trace_plane_dist = trace.plane.dist;
500 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
502 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
505 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
506 void PF_tracetoss (void)
510 prvm_edict_t *ignore;
512 prog->xfunction->builtinsprofile += 600;
514 ent = PRVM_G_EDICT(OFS_PARM0);
515 if (ent == prog->edicts)
516 PF_WARNING("tracetoss: can not use world entity\n");
517 ignore = PRVM_G_EDICT(OFS_PARM1);
519 trace = SV_Trace_Toss (ent, ignore);
521 prog->globals.server->trace_allsolid = trace.allsolid;
522 prog->globals.server->trace_startsolid = trace.startsolid;
523 prog->globals.server->trace_fraction = trace.fraction;
524 prog->globals.server->trace_inwater = trace.inwater;
525 prog->globals.server->trace_inopen = trace.inopen;
526 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
527 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
528 prog->globals.server->trace_plane_dist = trace.plane.dist;
530 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
532 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
540 Returns true if the given entity can move to the given position from it's
541 current position by walking or rolling.
543 scalar checkpos (entity, vector)
546 void PF_checkpos (void)
550 //============================================================================
553 qbyte checkpvs[MAX_MAP_LEAFS/8];
555 int PF_newcheckclient (int check)
561 // cycle to the next one
563 check = bound(1, check, svs.maxclients);
564 if (check == svs.maxclients)
572 prog->xfunction->builtinsprofile++;
574 if (i == svs.maxclients+1)
576 // look up the client's edict
577 ent = PRVM_EDICT_NUM(i);
578 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
579 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
581 // found a valid client (possibly the same one again)
585 // get the PVS for the entity
586 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
588 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
589 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
598 Returns a client (or object that has a client enemy) that would be a
601 If there is more than one valid option, they are cycled each frame
603 If (self.origin + self.viewofs) is not in the PVS of the current target,
604 it is not returned at all.
609 int c_invis, c_notvis;
610 void PF_checkclient (void)
612 prvm_edict_t *ent, *self;
615 // find a new check if on a new frame
616 if (sv.time - sv.lastchecktime >= 0.1)
618 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
619 sv.lastchecktime = sv.time;
622 // return check if it might be visible
623 ent = PRVM_EDICT_NUM(sv.lastcheck);
624 if (ent->priv.server->free || ent->fields.server->health <= 0)
626 VM_RETURN_EDICT(prog->edicts);
630 // if current entity can't possibly see the check entity, return 0
631 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
632 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
633 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
636 VM_RETURN_EDICT(prog->edicts);
640 // might be able to see it
642 VM_RETURN_EDICT(ent);
645 //============================================================================
652 Sends text over to the client's execution buffer
654 stuffcmd (clientent, value)
657 void PF_stuffcmd (void)
663 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
664 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
666 Con_Print("Can't stuffcmd to a non-client\n");
669 str = PRVM_G_STRING(OFS_PARM1);
672 host_client = svs.clients + entnum-1;
673 Host_ClientCommands ("%s", str);
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++)
880 MSG_WriteChar (&client->message, svc_lightstyle);
881 MSG_WriteChar (&client->message,style);
882 MSG_WriteString (&client->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) = SV_PointQ1Contents(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
1118 sizebuf_t *WriteDest (void)
1124 dest = PRVM_G_FLOAT(OFS_PARM0);
1128 return &sv.datagram;
1131 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1132 entnum = PRVM_NUM_FOR_EDICT(ent);
1133 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1135 Con_Printf ("WriteDest: tried to write to non-client\n");
1136 return &sv.reliable_datagram;
1139 return &svs.clients[entnum-1].message;
1142 Con_Printf ("WriteDest: bad destination");
1144 return &sv.reliable_datagram;
1153 void PF_WriteByte (void)
1155 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1158 void PF_WriteChar (void)
1160 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1163 void PF_WriteShort (void)
1165 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1168 void PF_WriteLong (void)
1170 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1173 void PF_WriteAngle (void)
1175 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1178 void PF_WriteCoord (void)
1180 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1183 void PF_WriteString (void)
1185 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1189 void PF_WriteEntity (void)
1191 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1194 //////////////////////////////////////////////////////////
1196 void PF_makestatic (void)
1201 ent = PRVM_G_EDICT(OFS_PARM0);
1202 if (ent == prog->edicts)
1203 PF_WARNING("makestatic: can not modify world entity\n");
1204 if (ent->priv.server->free)
1205 PF_WARNING("makestatic: can not modify free entity\n");
1208 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1213 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1214 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1215 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1219 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1220 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1221 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1224 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1225 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1226 for (i=0 ; i<3 ; i++)
1228 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1229 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1232 // throw the entity away now
1236 //=============================================================================
1243 void PF_setspawnparms (void)
1249 ent = PRVM_G_EDICT(OFS_PARM0);
1250 i = PRVM_NUM_FOR_EDICT(ent);
1251 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1253 Con_Print("tried to setspawnparms on a non-client\n");
1257 // copy spawn parms out of the client_t
1258 client = svs.clients + i-1;
1259 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1260 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1267 Returns a color vector indicating the lighting at the requested point.
1269 (Internal Operation note: actually measures the light beneath the point, just like
1270 the model lighting on the client)
1275 void PF_getlight (void)
1277 vec3_t ambientcolor, diffusecolor, diffusenormal;
1279 p = PRVM_G_VECTOR(OFS_PARM0);
1280 VectorClear(ambientcolor);
1281 VectorClear(diffusecolor);
1282 VectorClear(diffusenormal);
1283 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1284 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1285 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1288 void PF_registercvar (void)
1290 const char *name, *value;
1291 name = PRVM_G_STRING(OFS_PARM0);
1292 value = PRVM_G_STRING(OFS_PARM1);
1293 PRVM_G_FLOAT(OFS_RETURN) = 0;
1295 // first check to see if it has already been defined
1296 if (Cvar_FindVar (name))
1299 // check for overlap with a command
1300 if (Cmd_Exists (name))
1302 Con_Printf("PF_registercvar: %s is a command\n", name);
1306 Cvar_Get(name, value, 0);
1308 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1315 copies data from one entity to another
1317 copyentity(src, dst)
1320 void PF_copyentity (void)
1322 prvm_edict_t *in, *out;
1323 in = PRVM_G_EDICT(OFS_PARM0);
1324 if (in == prog->edicts)
1325 PF_WARNING("copyentity: can not read world entity\n");
1326 if (in->priv.server->free)
1327 PF_WARNING("copyentity: can not read free entity\n");
1328 out = PRVM_G_EDICT(OFS_PARM1);
1329 if (out == prog->edicts)
1330 PF_WARNING("copyentity: can not modify world entity\n");
1331 if (out->priv.server->free)
1332 PF_WARNING("copyentity: can not modify free entity\n");
1333 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1341 sets the color of a client and broadcasts the update to all connected clients
1343 setcolor(clientent, value)
1346 void PF_setcolor (void)
1352 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1353 i = PRVM_G_FLOAT(OFS_PARM1);
1355 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1357 Con_Print("tried to setcolor a non-client\n");
1361 client = svs.clients + entnum-1;
1364 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1366 client->edict->fields.server->team = (i & 15) + 1;
1369 if (client->old_colors != client->colors)
1371 client->old_colors = client->colors;
1372 // send notification to all clients
1373 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1374 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1375 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1383 effect(origin, modelname, startframe, framecount, framerate)
1386 void PF_effect (void)
1390 s = PRVM_G_STRING(OFS_PARM1);
1392 PF_WARNING("effect: no model specified\n");
1394 i = SV_ModelIndex(s, 1);
1396 PF_WARNING("effect: model not precached\n");
1397 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1400 void PF_te_blood (void)
1402 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1404 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1405 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1407 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1408 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1409 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1411 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1412 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1413 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1415 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1418 void PF_te_bloodshower (void)
1420 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1422 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1423 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1425 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1426 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1427 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1429 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1430 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1431 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1433 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1435 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1438 void PF_te_explosionrgb (void)
1440 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1441 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1443 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1444 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1445 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1447 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1448 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1449 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1452 void PF_te_particlecube (void)
1454 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1456 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1457 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1459 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1460 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1461 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1463 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1464 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1465 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1467 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1468 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1469 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1471 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1473 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1474 // gravity true/false
1475 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1477 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1480 void PF_te_particlerain (void)
1482 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1484 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1485 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1487 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1488 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1489 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1491 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1493 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1495 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1496 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1497 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1499 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1501 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1504 void PF_te_particlesnow (void)
1506 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1508 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1509 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1511 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1513 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1515 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1516 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1517 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1519 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1521 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1523 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1525 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1528 void PF_te_spark (void)
1530 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1532 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1533 MSG_WriteByte(&sv.datagram, TE_SPARK);
1535 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1536 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1537 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1539 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1540 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1541 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1543 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1546 void PF_te_gunshotquad (void)
1548 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1549 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1551 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1552 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1553 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1556 void PF_te_spikequad (void)
1558 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1559 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1561 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1566 void PF_te_superspikequad (void)
1568 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1569 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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);
1576 void PF_te_explosionquad (void)
1578 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1579 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1581 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1582 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1583 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1586 void PF_te_smallflash (void)
1588 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1589 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1591 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1592 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1593 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1596 void PF_te_customflash (void)
1598 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1600 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1601 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1603 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1604 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1605 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1607 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1609 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1611 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1612 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1613 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1616 void PF_te_gunshot (void)
1618 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1619 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1621 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1626 void PF_te_spike (void)
1628 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1629 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1636 void PF_te_superspike (void)
1638 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1639 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1646 void PF_te_explosion (void)
1648 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1649 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
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);
1656 void PF_te_tarexplosion (void)
1658 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1659 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1663 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1666 void PF_te_wizspike (void)
1668 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1669 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1673 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1676 void PF_te_knightspike (void)
1678 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1679 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1686 void PF_te_lavasplash (void)
1688 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1689 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1696 void PF_te_teleport (void)
1698 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1699 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1706 void PF_te_explosion2 (void)
1708 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1709 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1715 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1716 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1719 void PF_te_lightning1 (void)
1721 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1722 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1724 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1727 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1735 void PF_te_lightning2 (void)
1737 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1738 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1740 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1751 void PF_te_lightning3 (void)
1753 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1754 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1756 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1767 void PF_te_beam (void)
1769 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1770 MSG_WriteByte(&sv.datagram, TE_BEAM);
1772 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1783 void PF_te_plasmaburn (void)
1785 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1786 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1788 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1792 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1795 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1797 bestdist = 1000000000;
1799 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1801 // clip original point to each triangle of the surface and find the
1802 // triangle that is closest
1803 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1804 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1805 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1806 TriangleNormal(v[0], v[1], v[2], facenormal);
1807 VectorNormalize(facenormal);
1808 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1809 VectorMA(p, offsetdist, facenormal, temp);
1810 for (j = 0, k = 2;j < 3;k = j, j++)
1812 VectorSubtract(v[k], v[j], edgenormal);
1813 CrossProduct(edgenormal, facenormal, sidenormal);
1814 VectorNormalize(sidenormal);
1815 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1817 VectorMA(temp, offsetdist, sidenormal, temp);
1819 dist = VectorDistance2(temp, p);
1820 if (bestdist > dist)
1823 VectorCopy(temp, out);
1828 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1832 if (!ed || ed->priv.server->free)
1834 modelindex = ed->fields.server->modelindex;
1835 if (modelindex < 1 || modelindex >= MAX_MODELS)
1837 model = sv.models[modelindex];
1838 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1840 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1844 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1845 void PF_getsurfacenumpoints(void)
1847 msurface_t *surface;
1848 // return 0 if no such surface
1849 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1851 PRVM_G_FLOAT(OFS_RETURN) = 0;
1855 // note: this (incorrectly) assumes it is a simple polygon
1856 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1858 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1859 void PF_getsurfacepoint(void)
1862 msurface_t *surface;
1864 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1865 ed = PRVM_G_EDICT(OFS_PARM0);
1866 if (!ed || ed->priv.server->free)
1868 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1870 // note: this (incorrectly) assumes it is a simple polygon
1871 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1872 if (pointnum < 0 || pointnum >= surface->num_vertices)
1874 // FIXME: implement rotation/scaling
1875 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1877 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1878 void PF_getsurfacenormal(void)
1880 msurface_t *surface;
1882 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1883 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1885 // FIXME: implement rotation/scaling
1886 // note: this (incorrectly) assumes it is a simple polygon
1887 // note: this only returns the first triangle, so it doesn't work very
1888 // well for curved surfaces or arbitrary meshes
1889 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);
1890 VectorNormalize(normal);
1891 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1893 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1894 void PF_getsurfacetexture(void)
1896 msurface_t *surface;
1897 PRVM_G_INT(OFS_RETURN) = 0;
1898 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1900 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1902 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1903 void PF_getsurfacenearpoint(void)
1905 int surfacenum, best, modelindex;
1907 vec_t dist, bestdist;
1910 msurface_t *surface;
1912 PRVM_G_FLOAT(OFS_RETURN) = -1;
1913 ed = PRVM_G_EDICT(OFS_PARM0);
1914 point = PRVM_G_VECTOR(OFS_PARM1);
1916 if (!ed || ed->priv.server->free)
1918 modelindex = ed->fields.server->modelindex;
1919 if (modelindex < 1 || modelindex >= MAX_MODELS)
1921 model = sv.models[modelindex];
1922 if (!model->num_surfaces)
1925 // FIXME: implement rotation/scaling
1926 VectorSubtract(point, ed->fields.server->origin, p);
1928 bestdist = 1000000000;
1929 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1931 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1932 // first see if the nearest point on the surface's box is closer than the previous match
1933 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1934 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1935 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1936 dist = VectorLength2(clipped);
1937 if (dist < bestdist)
1939 // it is, check the nearest point on the actual geometry
1940 clippointtosurface(surface, p, clipped);
1941 VectorSubtract(clipped, p, clipped);
1942 dist += VectorLength2(clipped);
1943 if (dist < bestdist)
1945 // that's closer too, store it as the best match
1951 PRVM_G_FLOAT(OFS_RETURN) = best;
1953 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1954 void PF_getsurfaceclippedpoint(void)
1957 msurface_t *surface;
1959 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1960 ed = PRVM_G_EDICT(OFS_PARM0);
1961 if (!ed || ed->priv.server->free)
1963 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1965 // FIXME: implement rotation/scaling
1966 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1967 clippointtosurface(surface, p, out);
1968 // FIXME: implement rotation/scaling
1969 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1972 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1973 //this function originally written by KrimZon, made shorter by LordHavoc
1974 void PF_clientcommand (void)
1976 client_t *temp_client;
1979 //find client for this entity
1980 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
1981 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1983 Con_Print("PF_clientcommand: entity is not a client\n");
1987 temp_client = host_client;
1988 host_client = svs.clients + i;
1989 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1990 host_client = temp_client;
1993 //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)
1994 void PF_setattachment (void)
1996 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1997 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1998 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2003 if (e == prog->edicts)
2004 PF_WARNING("setattachment: can not modify world entity\n");
2005 if (e->priv.server->free)
2006 PF_WARNING("setattachment: can not modify free entity\n");
2008 if (tagentity == NULL)
2009 tagentity = prog->edicts;
2011 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2013 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2015 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2018 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2020 modelindex = (int)tagentity->fields.server->modelindex;
2021 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2023 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2025 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);
2028 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));
2032 /////////////////////////////////////////
2033 // DP_MD3_TAGINFO extension coded by VorteX
2035 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2040 i = e->fields.server->modelindex;
2041 if (i < 1 || i >= MAX_MODELS)
2043 model = sv.models[i];
2045 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2048 // Warnings/errors code:
2049 // 0 - normal (everything all-right)
2052 // 3 - null or non-precached model
2053 // 4 - no tags with requested index
2054 // 5 - runaway loop at attachment chain
2055 extern cvar_t cl_bob;
2056 extern cvar_t cl_bobcycle;
2057 extern cvar_t cl_bobup;
2058 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2061 int modelindex, reqframe, attachloop;
2062 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2063 prvm_edict_t *attachent;
2066 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2068 if (ent == prog->edicts)
2070 if (ent->priv.server->free)
2073 modelindex = (int)ent->fields.server->modelindex;
2074 if (modelindex <= 0 || modelindex > MAX_MODELS)
2077 model = sv.models[modelindex];
2079 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2080 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2082 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2084 // get initial tag matrix
2087 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2092 Matrix4x4_CreateIdentity(&tagmatrix);
2094 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2095 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2099 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2100 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2101 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)
2102 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2104 Matrix4x4_CreateIdentity(&attachmatrix);
2106 // apply transformation by child entity matrix
2107 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2108 if (val->_float == 0)
2110 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);
2111 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2112 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]);
2113 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]);
2114 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]);
2115 Matrix4x4_Copy(&tagmatrix, out);
2117 // finally transformate by matrix of tag on parent entity
2118 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2119 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];
2120 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];
2121 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];
2122 Matrix4x4_Copy(&tagmatrix, out);
2126 if (attachloop > 255) // prevent runaway looping
2129 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2132 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2133 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2134 if (val->_float == 0)
2136 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2137 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);
2138 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2139 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]);
2140 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]);
2141 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]);
2143 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2144 {// RENDER_VIEWMODEL magic
2145 Matrix4x4_Copy(&tagmatrix, out);
2146 ent = PRVM_EDICT_NUM(val->edict);
2148 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2149 if (val->_float == 0)
2152 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);
2153 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2154 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]);
2155 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]);
2156 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]);
2159 // Cl_bob, ported from rendering code
2160 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2163 // LordHavoc: this code is *weird*, but not replacable (I think it
2164 // should be done in QC on the server, but oh well, quake is quake)
2165 // LordHavoc: figured out bobup: the time at which the sin is at 180
2166 // degrees (which allows lengthening or squishing the peak or valley)
2167 cycle = sv.time/cl_bobcycle.value;
2168 cycle -= (int)cycle;
2169 if (cycle < cl_bobup.value)
2170 cycle = sin(M_PI * cycle / cl_bobup.value);
2172 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2173 // bob is proportional to velocity in the xy plane
2174 // (don't count Z, or jumping messes it up)
2175 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;
2176 bob = bob*0.3 + bob*0.7*cycle;
2177 out->m[2][3] += bound(-7, bob, 4);
2184 //float(entity ent, string tagname) gettagindex;
2186 void PF_gettagindex (void)
2188 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2189 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2190 int modelindex, tag_index;
2192 if (ent == prog->edicts)
2193 PF_WARNING("gettagindex: can't affect world entity\n");
2194 if (ent->priv.server->free)
2195 PF_WARNING("gettagindex: can't affect free entity\n");
2197 modelindex = (int)ent->fields.server->modelindex;
2199 if (modelindex <= 0 || modelindex > MAX_MODELS)
2200 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2203 tag_index = SV_GetTagIndex(ent, tag_name);
2205 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2207 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2210 //vector(entity ent, float tagindex) gettaginfo;
2211 void PF_gettaginfo (void)
2213 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2214 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2215 matrix4x4_t tag_matrix;
2218 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2219 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2224 PF_WARNING("gettagindex: can't affect world entity\n");
2227 PF_WARNING("gettagindex: can't affect free entity\n");
2230 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2233 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2236 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2241 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2242 void PF_dropclient (void)
2245 client_t *oldhostclient;
2246 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2247 if (clientnum < 0 || clientnum >= svs.maxclients)
2248 PF_WARNING("dropclient: not a client\n");
2249 if (!svs.clients[clientnum].active)
2250 PF_WARNING("dropclient: that client slot is not connected\n");
2251 oldhostclient = host_client;
2252 host_client = svs.clients + clientnum;
2253 SV_DropClient(false);
2254 host_client = oldhostclient;
2257 //entity() spawnclient (DP_SV_BOTCLIENT)
2258 void PF_spawnclient (void)
2262 prog->xfunction->builtinsprofile += 2;
2264 for (i = 0;i < svs.maxclients;i++)
2266 if (!svs.clients[i].active)
2268 prog->xfunction->builtinsprofile += 100;
2269 SV_ConnectClient (i, NULL);
2270 ed = PRVM_EDICT_NUM(i + 1);
2274 VM_RETURN_EDICT(ed);
2277 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2278 void PF_clienttype (void)
2281 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2282 if (clientnum < 0 || clientnum >= svs.maxclients)
2283 PRVM_G_FLOAT(OFS_RETURN) = 3;
2284 else if (!svs.clients[clientnum].active)
2285 PRVM_G_FLOAT(OFS_RETURN) = 0;
2286 else if (svs.clients[clientnum].netconnection)
2287 PRVM_G_FLOAT(OFS_RETURN) = 1;
2289 PRVM_G_FLOAT(OFS_RETURN) = 2;
2292 prvm_builtin_t vm_sv_builtins[] = {
2294 PF_makevectors, // #1 void(entity e) makevectors
2295 PF_setorigin, // #2 void(entity e, vector o) setorigin
2296 PF_setmodel, // #3 void(entity e, string m) setmodel
2297 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2298 NULL, // #5 void(entity e, vector min, vector max) setabssize
2299 VM_break, // #6 void() break
2300 VM_random, // #7 float() random
2301 PF_sound, // #8 void(entity e, float chan, string samp) sound
2302 VM_normalize, // #9 vector(vector v) normalize
2303 VM_error, // #10 void(string e) error
2304 VM_objerror, // #11 void(string e) objerror
2305 VM_vlen, // #12 float(vector v) vlen
2306 VM_vectoyaw, // #13 float(vector v) vectoyaw
2307 VM_spawn, // #14 entity() spawn
2308 VM_remove, // #15 void(entity e) remove
2309 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2310 PF_checkclient, // #17 entity() clientlist
2311 VM_find, // #18 entity(entity start, .string fld, string match) find
2312 PF_precache_sound, // #19 void(string s) precache_sound
2313 PF_precache_model, // #20 void(string s) precache_model
2314 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2315 PF_findradius, // #22 entity(vector org, float rad) findradius
2316 VM_bprint, // #23 void(string s) bprint
2317 PF_sprint, // #24 void(entity client, string s) sprint
2318 VM_dprint, // #25 void(string s) dprint
2319 VM_ftos, // #26 void(string s) ftos
2320 VM_vtos, // #27 void(string s) vtos
2321 VM_coredump, // #28 void() coredump
2322 VM_traceon, // #29 void() traceon
2323 VM_traceoff, // #30 void() traceoff
2324 VM_eprint, // #31 void(entity e) eprint
2325 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2327 PF_droptofloor, // #34 float() droptofloor
2328 PF_lightstyle, // #35 void(float style, string value) lightstyle
2329 VM_rint, // #36 float(float v) rint
2330 VM_floor, // #37 float(float v) floor
2331 VM_ceil, // #38 float(float v) ceil
2333 PF_checkbottom, // #40 float(entity e) checkbottom
2334 PF_pointcontents, // #41 float(vector v) pointcontents
2336 VM_fabs, // #43 float(float f) fabs
2337 PF_aim, // #44 vector(entity e, float speed) aim
2338 VM_cvar, // #45 float(string s) cvar
2339 VM_localcmd, // #46 void(string s) localcmd
2340 VM_nextent, // #47 entity(entity e) nextent
2341 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2342 PF_changeyaw, // #49 void() ChangeYaw
2344 VM_vectoangles, // #51 vector(vector v) vectoangles
2345 PF_WriteByte, // #52 void(float to, float f) WriteByte
2346 PF_WriteChar, // #53 void(float to, float f) WriteChar
2347 PF_WriteShort, // #54 void(float to, float f) WriteShort
2348 PF_WriteLong, // #55 void(float to, float f) WriteLong
2349 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2350 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2351 PF_WriteString, // #58 void(float to, string s) WriteString
2352 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2353 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2354 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2355 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2356 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2357 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2358 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2360 SV_MoveToGoal, // #67 void(float step) movetogoal
2361 PF_precache_file, // #68 string(string s) precache_file
2362 PF_makestatic, // #69 void(entity e) makestatic
2363 VM_changelevel, // #70 void(string s) changelevel
2365 VM_cvar_set, // #72 void(string var, string val) cvar_set
2366 PF_centerprint, // #73 void(entity client, strings) centerprint
2367 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2368 PF_precache_model, // #75 string(string s) precache_model2
2369 PF_precache_sound, // #76 string(string s) precache_sound2
2370 PF_precache_file, // #77 string(string s) precache_file2
2371 PF_setspawnparms, // #78 void(entity e) setspawnparms
2374 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2383 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2384 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2385 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2386 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2387 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2388 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2389 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2390 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2391 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2392 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2403 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2404 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2405 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2406 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2407 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2408 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2409 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2410 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2411 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2412 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2413 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2414 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2415 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2416 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2417 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2418 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2419 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2420 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2421 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2422 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2423 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2424 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2425 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2426 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2427 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2428 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2429 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2430 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2431 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2432 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2433 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2434 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2435 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2436 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2437 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2438 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2439 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2440 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2441 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2442 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2443 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2444 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2445 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2446 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2447 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2448 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2449 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2450 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2451 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2452 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2453 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2454 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2455 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2456 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2457 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2458 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2459 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2460 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2461 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2462 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2463 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2464 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2465 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2466 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2467 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2468 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2469 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2470 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2471 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2476 e10, e10, e10, e10 // #460-499 (LordHavoc)
2479 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2481 void VM_SV_Cmd_Init(void)
2486 void VM_SV_Cmd_Reset(void)