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 // change the string in sv
866 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
868 // send message to all clients on this server
869 if (sv.state != ss_active)
872 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
876 MSG_WriteChar (&client->message, svc_lightstyle);
877 MSG_WriteChar (&client->message,style);
878 MSG_WriteString (&client->message, val);
888 void PF_checkbottom (void)
890 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
898 void PF_pointcontents (void)
900 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
907 Pick a vector for the player to shoot along
908 vector aim(entity, missilespeed)
913 prvm_edict_t *ent, *check, *bestent;
914 vec3_t start, dir, end, bestdir;
917 float dist, bestdist;
920 // assume failure if it returns early
921 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
922 // if sv_aim is so high it can't possibly accept anything, skip out early
923 if (sv_aim.value >= 1)
926 ent = PRVM_G_EDICT(OFS_PARM0);
927 if (ent == prog->edicts)
928 PF_WARNING("aim: can not use world entity\n");
929 if (ent->priv.server->free)
930 PF_WARNING("aim: can not use free entity\n");
931 speed = PRVM_G_FLOAT(OFS_PARM1);
933 VectorCopy (ent->fields.server->origin, start);
936 // try sending a trace straight
937 VectorCopy (prog->globals.server->v_forward, dir);
938 VectorMA (start, 2048, dir, end);
939 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
940 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
941 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
943 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
948 // try all possible entities
949 VectorCopy (dir, bestdir);
950 bestdist = sv_aim.value;
953 check = PRVM_NEXT_EDICT(prog->edicts);
954 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
956 prog->xfunction->builtinsprofile++;
957 if (check->fields.server->takedamage != DAMAGE_AIM)
961 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
962 continue; // don't aim at teammate
963 for (j=0 ; j<3 ; j++)
964 end[j] = check->fields.server->origin[j]
965 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
966 VectorSubtract (end, start, dir);
967 VectorNormalize (dir);
968 dist = DotProduct (dir, prog->globals.server->v_forward);
970 continue; // to far to turn
971 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
973 { // can shoot at this one
981 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
982 dist = DotProduct (dir, prog->globals.server->v_forward);
983 VectorScale (prog->globals.server->v_forward, dist, end);
985 VectorNormalize (end);
986 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
990 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
998 This was a major timewaster in progs, so it was converted to C
1001 void PF_changeyaw (void)
1004 float ideal, current, move, speed;
1006 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1007 if (ent == prog->edicts)
1008 PF_WARNING("changeyaw: can not modify world entity\n");
1009 if (ent->priv.server->free)
1010 PF_WARNING("changeyaw: can not modify free entity\n");
1011 current = ANGLEMOD(ent->fields.server->angles[1]);
1012 ideal = ent->fields.server->ideal_yaw;
1013 speed = ent->fields.server->yaw_speed;
1015 if (current == ideal)
1017 move = ideal - current;
1018 if (ideal > current)
1039 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1047 void PF_changepitch (void)
1050 float ideal, current, move, speed;
1053 ent = PRVM_G_EDICT(OFS_PARM0);
1054 if (ent == prog->edicts)
1055 PF_WARNING("changepitch: can not modify world entity\n");
1056 if (ent->priv.server->free)
1057 PF_WARNING("changepitch: can not modify free entity\n");
1058 current = ANGLEMOD( ent->fields.server->angles[0] );
1059 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1060 ideal = val->_float;
1063 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1066 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1067 speed = val->_float;
1070 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1074 if (current == ideal)
1076 move = ideal - current;
1077 if (ideal > current)
1098 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1102 ===============================================================================
1106 ===============================================================================
1109 #define MSG_BROADCAST 0 // unreliable to all
1110 #define MSG_ONE 1 // reliable to one (msg_entity)
1111 #define MSG_ALL 2 // reliable to all
1112 #define MSG_INIT 3 // write to the init string
1114 sizebuf_t *WriteDest (void)
1120 dest = PRVM_G_FLOAT(OFS_PARM0);
1124 return &sv.datagram;
1127 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1128 entnum = PRVM_NUM_FOR_EDICT(ent);
1129 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1131 Con_Printf ("WriteDest: tried to write to non-client\n");
1132 return &sv.reliable_datagram;
1135 return &svs.clients[entnum-1].message;
1138 Con_Printf ("WriteDest: bad destination");
1140 return &sv.reliable_datagram;
1149 void PF_WriteByte (void)
1151 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1154 void PF_WriteChar (void)
1156 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1159 void PF_WriteShort (void)
1161 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1164 void PF_WriteLong (void)
1166 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1169 void PF_WriteAngle (void)
1171 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1174 void PF_WriteCoord (void)
1176 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1179 void PF_WriteString (void)
1181 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1185 void PF_WriteEntity (void)
1187 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1190 //////////////////////////////////////////////////////////
1192 void PF_makestatic (void)
1197 ent = PRVM_G_EDICT(OFS_PARM0);
1198 if (ent == prog->edicts)
1199 PF_WARNING("makestatic: can not modify world entity\n");
1200 if (ent->priv.server->free)
1201 PF_WARNING("makestatic: can not modify free entity\n");
1204 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1209 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1210 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1211 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1215 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1216 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1217 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1220 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1221 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1222 for (i=0 ; i<3 ; i++)
1224 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1225 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1228 // throw the entity away now
1232 //=============================================================================
1239 void PF_setspawnparms (void)
1245 ent = PRVM_G_EDICT(OFS_PARM0);
1246 i = PRVM_NUM_FOR_EDICT(ent);
1247 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1249 Con_Print("tried to setspawnparms on a non-client\n");
1253 // copy spawn parms out of the client_t
1254 client = svs.clients + i-1;
1255 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1256 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1263 Returns a color vector indicating the lighting at the requested point.
1265 (Internal Operation note: actually measures the light beneath the point, just like
1266 the model lighting on the client)
1271 void PF_getlight (void)
1273 vec3_t ambientcolor, diffusecolor, diffusenormal;
1275 p = PRVM_G_VECTOR(OFS_PARM0);
1276 VectorClear(ambientcolor);
1277 VectorClear(diffusecolor);
1278 VectorClear(diffusenormal);
1279 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1280 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1281 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1284 void PF_registercvar (void)
1286 const char *name, *value;
1287 name = PRVM_G_STRING(OFS_PARM0);
1288 value = PRVM_G_STRING(OFS_PARM1);
1289 PRVM_G_FLOAT(OFS_RETURN) = 0;
1291 // first check to see if it has already been defined
1292 if (Cvar_FindVar (name))
1295 // check for overlap with a command
1296 if (Cmd_Exists (name))
1298 Con_Printf("PF_registercvar: %s is a command\n", name);
1302 Cvar_Get(name, value, 0);
1304 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1311 copies data from one entity to another
1313 copyentity(src, dst)
1316 void PF_copyentity (void)
1318 prvm_edict_t *in, *out;
1319 in = PRVM_G_EDICT(OFS_PARM0);
1320 if (in == prog->edicts)
1321 PF_WARNING("copyentity: can not read world entity\n");
1322 if (in->priv.server->free)
1323 PF_WARNING("copyentity: can not read free entity\n");
1324 out = PRVM_G_EDICT(OFS_PARM1);
1325 if (out == prog->edicts)
1326 PF_WARNING("copyentity: can not modify world entity\n");
1327 if (out->priv.server->free)
1328 PF_WARNING("copyentity: can not modify free entity\n");
1329 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1337 sets the color of a client and broadcasts the update to all connected clients
1339 setcolor(clientent, value)
1342 void PF_setcolor (void)
1348 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1349 i = PRVM_G_FLOAT(OFS_PARM1);
1351 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1353 Con_Print("tried to setcolor a non-client\n");
1357 client = svs.clients + entnum-1;
1360 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1362 client->edict->fields.server->team = (i & 15) + 1;
1365 if (client->old_colors != client->colors)
1367 client->old_colors = client->colors;
1368 // send notification to all clients
1369 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1370 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1371 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1379 effect(origin, modelname, startframe, framecount, framerate)
1382 void PF_effect (void)
1386 s = PRVM_G_STRING(OFS_PARM1);
1388 PF_WARNING("effect: no model specified\n");
1390 i = SV_ModelIndex(s, 1);
1392 PF_WARNING("effect: model not precached\n");
1393 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1396 void PF_te_blood (void)
1398 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1400 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1401 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1403 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1404 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1405 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1407 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1408 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1409 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1411 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1414 void PF_te_bloodshower (void)
1416 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1418 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1419 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1421 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1422 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1423 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1425 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1426 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1427 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1429 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1431 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1434 void PF_te_explosionrgb (void)
1436 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1437 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1439 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1440 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1441 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1443 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1444 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1445 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1448 void PF_te_particlecube (void)
1450 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1452 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1453 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1455 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1456 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1457 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1459 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1460 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1461 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1463 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1464 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1465 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1467 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1469 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1470 // gravity true/false
1471 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1473 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1476 void PF_te_particlerain (void)
1478 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1480 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1481 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1483 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1484 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1485 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1487 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1488 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1489 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1491 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1493 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1495 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1497 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1500 void PF_te_particlesnow (void)
1502 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1504 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1505 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1507 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1508 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1509 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1511 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1513 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1515 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1516 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1517 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1519 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1521 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1524 void PF_te_spark (void)
1526 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1528 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1529 MSG_WriteByte(&sv.datagram, TE_SPARK);
1531 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1532 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1533 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1535 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1536 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1537 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1539 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1542 void PF_te_gunshotquad (void)
1544 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1545 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1548 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1549 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1552 void PF_te_spikequad (void)
1554 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1555 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1557 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1558 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1559 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1562 void PF_te_superspikequad (void)
1564 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1565 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1569 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1572 void PF_te_explosionquad (void)
1574 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1575 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1577 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1578 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1579 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1582 void PF_te_smallflash (void)
1584 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1585 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1587 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1588 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1589 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1592 void PF_te_customflash (void)
1594 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1596 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1597 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1599 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1600 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1601 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1603 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1605 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1607 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1608 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1609 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1612 void PF_te_gunshot (void)
1614 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1615 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1617 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1618 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1619 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1622 void PF_te_spike (void)
1624 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1625 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1627 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1628 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1632 void PF_te_superspike (void)
1634 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1635 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1637 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1638 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1639 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1642 void PF_te_explosion (void)
1644 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1645 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1648 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1652 void PF_te_tarexplosion (void)
1654 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1655 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1658 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1662 void PF_te_wizspike (void)
1664 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1665 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1672 void PF_te_knightspike (void)
1674 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1675 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1677 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1678 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1682 void PF_te_lavasplash (void)
1684 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1685 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1692 void PF_te_teleport (void)
1694 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1695 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1697 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1698 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1699 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1702 void PF_te_explosion2 (void)
1704 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1705 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1711 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1712 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1715 void PF_te_lightning1 (void)
1717 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1718 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1720 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1727 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1728 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1731 void PF_te_lightning2 (void)
1733 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1734 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1736 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1747 void PF_te_lightning3 (void)
1749 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1750 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1752 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1763 void PF_te_beam (void)
1765 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1766 MSG_WriteByte(&sv.datagram, TE_BEAM);
1768 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1771 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1779 void PF_te_plasmaburn (void)
1781 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1782 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1788 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1791 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1793 bestdist = 1000000000;
1795 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1797 // clip original point to each triangle of the surface and find the
1798 // triangle that is closest
1799 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1800 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1801 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1802 TriangleNormal(v[0], v[1], v[2], facenormal);
1803 VectorNormalize(facenormal);
1804 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1805 VectorMA(p, offsetdist, facenormal, temp);
1806 for (j = 0, k = 2;j < 3;k = j, j++)
1808 VectorSubtract(v[k], v[j], edgenormal);
1809 CrossProduct(edgenormal, facenormal, sidenormal);
1810 VectorNormalize(sidenormal);
1811 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1813 VectorMA(temp, offsetdist, sidenormal, temp);
1815 dist = VectorDistance2(temp, p);
1816 if (bestdist > dist)
1819 VectorCopy(temp, out);
1824 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1828 if (!ed || ed->priv.server->free)
1830 modelindex = ed->fields.server->modelindex;
1831 if (modelindex < 1 || modelindex >= MAX_MODELS)
1833 model = sv.models[modelindex];
1834 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1836 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1840 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1841 void PF_getsurfacenumpoints(void)
1843 msurface_t *surface;
1844 // return 0 if no such surface
1845 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1847 PRVM_G_FLOAT(OFS_RETURN) = 0;
1851 // note: this (incorrectly) assumes it is a simple polygon
1852 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1854 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1855 void PF_getsurfacepoint(void)
1858 msurface_t *surface;
1860 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1861 ed = PRVM_G_EDICT(OFS_PARM0);
1862 if (!ed || ed->priv.server->free)
1864 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1866 // note: this (incorrectly) assumes it is a simple polygon
1867 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1868 if (pointnum < 0 || pointnum >= surface->num_vertices)
1870 // FIXME: implement rotation/scaling
1871 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1873 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1874 void PF_getsurfacenormal(void)
1876 msurface_t *surface;
1878 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1879 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1881 // FIXME: implement rotation/scaling
1882 // note: this (incorrectly) assumes it is a simple polygon
1883 // note: this only returns the first triangle, so it doesn't work very
1884 // well for curved surfaces or arbitrary meshes
1885 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);
1886 VectorNormalize(normal);
1887 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1889 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1890 void PF_getsurfacetexture(void)
1892 msurface_t *surface;
1893 PRVM_G_INT(OFS_RETURN) = 0;
1894 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1896 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1898 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1899 void PF_getsurfacenearpoint(void)
1901 int surfacenum, best, modelindex;
1903 vec_t dist, bestdist;
1906 msurface_t *surface;
1908 PRVM_G_FLOAT(OFS_RETURN) = -1;
1909 ed = PRVM_G_EDICT(OFS_PARM0);
1910 point = PRVM_G_VECTOR(OFS_PARM1);
1912 if (!ed || ed->priv.server->free)
1914 modelindex = ed->fields.server->modelindex;
1915 if (modelindex < 1 || modelindex >= MAX_MODELS)
1917 model = sv.models[modelindex];
1918 if (!model->num_surfaces)
1921 // FIXME: implement rotation/scaling
1922 VectorSubtract(point, ed->fields.server->origin, p);
1924 bestdist = 1000000000;
1925 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1927 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1928 // first see if the nearest point on the surface's box is closer than the previous match
1929 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1930 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1931 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1932 dist = VectorLength2(clipped);
1933 if (dist < bestdist)
1935 // it is, check the nearest point on the actual geometry
1936 clippointtosurface(surface, p, clipped);
1937 VectorSubtract(clipped, p, clipped);
1938 dist += VectorLength2(clipped);
1939 if (dist < bestdist)
1941 // that's closer too, store it as the best match
1947 PRVM_G_FLOAT(OFS_RETURN) = best;
1949 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1950 void PF_getsurfaceclippedpoint(void)
1953 msurface_t *surface;
1955 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1956 ed = PRVM_G_EDICT(OFS_PARM0);
1957 if (!ed || ed->priv.server->free)
1959 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1961 // FIXME: implement rotation/scaling
1962 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1963 clippointtosurface(surface, p, out);
1964 // FIXME: implement rotation/scaling
1965 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1968 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1969 //this function originally written by KrimZon, made shorter by LordHavoc
1970 void PF_clientcommand (void)
1972 client_t *temp_client;
1975 //find client for this entity
1976 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
1977 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1979 Con_Print("PF_clientcommand: entity is not a client\n");
1983 temp_client = host_client;
1984 host_client = svs.clients + i;
1985 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1986 host_client = temp_client;
1989 //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)
1990 void PF_setattachment (void)
1992 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1993 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1994 const char *tagname = PRVM_G_STRING(OFS_PARM2);
1999 if (e == prog->edicts)
2000 PF_WARNING("setattachment: can not modify world entity\n");
2001 if (e->priv.server->free)
2002 PF_WARNING("setattachment: can not modify free entity\n");
2004 if (tagentity == NULL)
2005 tagentity = prog->edicts;
2007 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2009 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2011 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2014 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2016 modelindex = (int)tagentity->fields.server->modelindex;
2017 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2019 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2021 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);
2024 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));
2028 /////////////////////////////////////////
2029 // DP_MD3_TAGINFO extension coded by VorteX
2031 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2036 i = e->fields.server->modelindex;
2037 if (i < 1 || i >= MAX_MODELS)
2039 model = sv.models[i];
2041 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2044 // Warnings/errors code:
2045 // 0 - normal (everything all-right)
2048 // 3 - null or non-precached model
2049 // 4 - no tags with requested index
2050 // 5 - runaway loop at attachment chain
2051 extern cvar_t cl_bob;
2052 extern cvar_t cl_bobcycle;
2053 extern cvar_t cl_bobup;
2054 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2057 int modelindex, reqframe, attachloop;
2058 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2059 prvm_edict_t *attachent;
2062 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2064 if (ent == prog->edicts)
2066 if (ent->priv.server->free)
2069 modelindex = (int)ent->fields.server->modelindex;
2070 if (modelindex <= 0 || modelindex > MAX_MODELS)
2073 model = sv.models[modelindex];
2075 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2076 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2078 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2080 // get initial tag matrix
2083 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2088 Matrix4x4_CreateIdentity(&tagmatrix);
2090 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2091 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2095 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2096 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2097 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)
2098 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2100 Matrix4x4_CreateIdentity(&attachmatrix);
2102 // apply transformation by child entity matrix
2103 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2104 if (val->_float == 0)
2106 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);
2107 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2108 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]);
2109 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]);
2110 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]);
2111 Matrix4x4_Copy(&tagmatrix, out);
2113 // finally transformate by matrix of tag on parent entity
2114 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2115 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];
2116 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];
2117 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];
2118 Matrix4x4_Copy(&tagmatrix, out);
2122 if (attachloop > 255) // prevent runaway looping
2125 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2128 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2129 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2130 if (val->_float == 0)
2132 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2133 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);
2134 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2135 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]);
2136 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]);
2137 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]);
2139 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2140 {// RENDER_VIEWMODEL magic
2141 Matrix4x4_Copy(&tagmatrix, out);
2142 ent = PRVM_EDICT_NUM(val->edict);
2144 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2145 if (val->_float == 0)
2148 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);
2149 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2150 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]);
2151 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]);
2152 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]);
2155 // Cl_bob, ported from rendering code
2156 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2159 // LordHavoc: this code is *weird*, but not replacable (I think it
2160 // should be done in QC on the server, but oh well, quake is quake)
2161 // LordHavoc: figured out bobup: the time at which the sin is at 180
2162 // degrees (which allows lengthening or squishing the peak or valley)
2163 cycle = sv.time/cl_bobcycle.value;
2164 cycle -= (int)cycle;
2165 if (cycle < cl_bobup.value)
2166 cycle = sin(M_PI * cycle / cl_bobup.value);
2168 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2169 // bob is proportional to velocity in the xy plane
2170 // (don't count Z, or jumping messes it up)
2171 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;
2172 bob = bob*0.3 + bob*0.7*cycle;
2173 out->m[2][3] += bound(-7, bob, 4);
2180 //float(entity ent, string tagname) gettagindex;
2182 void PF_gettagindex (void)
2184 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2185 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2186 int modelindex, tag_index;
2188 if (ent == prog->edicts)
2189 PF_WARNING("gettagindex: can't affect world entity\n");
2190 if (ent->priv.server->free)
2191 PF_WARNING("gettagindex: can't affect free entity\n");
2193 modelindex = (int)ent->fields.server->modelindex;
2195 if (modelindex <= 0 || modelindex > MAX_MODELS)
2196 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2199 tag_index = SV_GetTagIndex(ent, tag_name);
2201 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2203 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2206 //vector(entity ent, float tagindex) gettaginfo;
2207 void PF_gettaginfo (void)
2209 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2210 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2211 matrix4x4_t tag_matrix;
2214 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2215 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2220 PF_WARNING("gettagindex: can't affect world entity\n");
2223 PF_WARNING("gettagindex: can't affect free entity\n");
2226 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2229 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2232 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2237 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2238 void PF_dropclient (void)
2241 client_t *oldhostclient;
2242 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2243 if (clientnum < 0 || clientnum >= svs.maxclients)
2244 PF_WARNING("dropclient: not a client\n");
2245 if (!svs.clients[clientnum].active)
2246 PF_WARNING("dropclient: that client slot is not connected\n");
2247 oldhostclient = host_client;
2248 host_client = svs.clients + clientnum;
2249 SV_DropClient(false);
2250 host_client = oldhostclient;
2253 //entity() spawnclient (DP_SV_BOTCLIENT)
2254 void PF_spawnclient (void)
2258 prog->xfunction->builtinsprofile += 2;
2260 for (i = 0;i < svs.maxclients;i++)
2262 if (!svs.clients[i].active)
2264 prog->xfunction->builtinsprofile += 100;
2265 SV_ConnectClient (i, NULL);
2266 ed = PRVM_EDICT_NUM(i + 1);
2270 VM_RETURN_EDICT(ed);
2273 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2274 void PF_clienttype (void)
2277 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2278 if (clientnum < 0 || clientnum >= svs.maxclients)
2279 PRVM_G_FLOAT(OFS_RETURN) = 3;
2280 else if (!svs.clients[clientnum].active)
2281 PRVM_G_FLOAT(OFS_RETURN) = 0;
2282 else if (svs.clients[clientnum].netconnection)
2283 PRVM_G_FLOAT(OFS_RETURN) = 1;
2285 PRVM_G_FLOAT(OFS_RETURN) = 2;
2288 prvm_builtin_t vm_sv_builtins[] = {
2290 PF_makevectors, // #1 void(entity e) makevectors
2291 PF_setorigin, // #2 void(entity e, vector o) setorigin
2292 PF_setmodel, // #3 void(entity e, string m) setmodel
2293 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2294 NULL, // #5 void(entity e, vector min, vector max) setabssize
2295 VM_break, // #6 void() break
2296 VM_random, // #7 float() random
2297 PF_sound, // #8 void(entity e, float chan, string samp) sound
2298 VM_normalize, // #9 vector(vector v) normalize
2299 VM_error, // #10 void(string e) error
2300 VM_objerror, // #11 void(string e) objerror
2301 VM_vlen, // #12 float(vector v) vlen
2302 VM_vectoyaw, // #13 float(vector v) vectoyaw
2303 VM_spawn, // #14 entity() spawn
2304 VM_remove, // #15 void(entity e) remove
2305 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2306 PF_checkclient, // #17 entity() clientlist
2307 VM_find, // #18 entity(entity start, .string fld, string match) find
2308 PF_precache_sound, // #19 void(string s) precache_sound
2309 PF_precache_model, // #20 void(string s) precache_model
2310 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2311 PF_findradius, // #22 entity(vector org, float rad) findradius
2312 VM_bprint, // #23 void(string s) bprint
2313 PF_sprint, // #24 void(entity client, string s) sprint
2314 VM_dprint, // #25 void(string s) dprint
2315 VM_ftos, // #26 void(string s) ftos
2316 VM_vtos, // #27 void(string s) vtos
2317 VM_coredump, // #28 void() coredump
2318 VM_traceon, // #29 void() traceon
2319 VM_traceoff, // #30 void() traceoff
2320 VM_eprint, // #31 void(entity e) eprint
2321 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2323 PF_droptofloor, // #34 float() droptofloor
2324 PF_lightstyle, // #35 void(float style, string value) lightstyle
2325 VM_rint, // #36 float(float v) rint
2326 VM_floor, // #37 float(float v) floor
2327 VM_ceil, // #38 float(float v) ceil
2329 PF_checkbottom, // #40 float(entity e) checkbottom
2330 PF_pointcontents, // #41 float(vector v) pointcontents
2332 VM_fabs, // #43 float(float f) fabs
2333 PF_aim, // #44 vector(entity e, float speed) aim
2334 VM_cvar, // #45 float(string s) cvar
2335 VM_localcmd, // #46 void(string s) localcmd
2336 VM_nextent, // #47 entity(entity e) nextent
2337 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2338 PF_changeyaw, // #49 void() ChangeYaw
2340 VM_vectoangles, // #51 vector(vector v) vectoangles
2341 PF_WriteByte, // #52 void(float to, float f) WriteByte
2342 PF_WriteChar, // #53 void(float to, float f) WriteChar
2343 PF_WriteShort, // #54 void(float to, float f) WriteShort
2344 PF_WriteLong, // #55 void(float to, float f) WriteLong
2345 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2346 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2347 PF_WriteString, // #58 void(float to, string s) WriteString
2348 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2349 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2350 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2351 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2352 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2353 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2354 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2356 SV_MoveToGoal, // #67 void(float step) movetogoal
2357 PF_precache_file, // #68 string(string s) precache_file
2358 PF_makestatic, // #69 void(entity e) makestatic
2359 VM_changelevel, // #70 void(string s) changelevel
2361 VM_cvar_set, // #72 void(string var, string val) cvar_set
2362 PF_centerprint, // #73 void(entity client, strings) centerprint
2363 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2364 PF_precache_model, // #75 string(string s) precache_model2
2365 PF_precache_sound, // #76 string(string s) precache_sound2
2366 PF_precache_file, // #77 string(string s) precache_file2
2367 PF_setspawnparms, // #78 void(entity e) setspawnparms
2370 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2379 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2380 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2381 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2382 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2383 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2384 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2385 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2386 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2387 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2388 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2399 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2400 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2401 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2402 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2403 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2404 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2405 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2406 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2407 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2408 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2409 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2410 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2411 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2412 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2413 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2414 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2415 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2416 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2417 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2418 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2419 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2420 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2421 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2422 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2423 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2424 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2425 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2426 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2427 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2428 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2429 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2430 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2431 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2432 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2433 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2434 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2435 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2436 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2437 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2438 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2439 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2440 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2441 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2442 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2443 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2444 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2445 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2446 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2447 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2448 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2449 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2450 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2451 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2452 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2453 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2454 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2455 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2456 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2457 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2458 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2459 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2460 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2461 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2462 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2463 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2464 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2465 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2466 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2467 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2472 e10, e10, e10, e10 // #460-499 (LordHavoc)
2475 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2477 void VM_SV_Cmd_Init(void)
2482 void VM_SV_Cmd_Reset(void)