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 =
27 "DP_ENT_CUSTOMCOLORMAP "
28 "DP_ENT_EXTERIORMODELTOCLIENT "
30 "DP_ENT_LOWPRECISION "
33 "DP_GFX_EXTERNALTEXTURES "
35 "DP_GFX_QUAKE3MODELTAGS "
39 "DP_HALFLIFE_MAP_CVAR "
45 "DP_MOVETYPEBOUNCEMISSILE "
52 "DP_QC_FINDCHAINFLAGS "
53 "DP_QC_FINDCHAINFLOAT "
56 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
61 "DP_QC_MULTIPLETEMPSTRINGS "
63 "DP_QC_SINCOSSQRTPOW "
66 "DP_QC_TRACE_MOVETYPE_HITMODEL "
67 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
68 "DP_QC_VECTORVECTORS "
74 "DP_SND_DIRECTIONLESSATTNNONE "
83 "DP_SV_DRAWONLYTOCLIENT "
86 "DP_SV_NODRAWTOCLIENT "
88 "DP_SV_PLAYERPHYSICS "
90 "DP_SV_ROTATINGBMODEL "
100 "DP_TE_PARTICLESNOW "
102 "DP_TE_QUADEFFECTS1 "
105 "DP_TE_STANDARDEFFECTBUILTINS "
108 "KRIMZON_SV_PARSECLIENTCOMMAND "
112 "PRYDON_CLIENTCURSOR "
113 "TENEBRAE_GFX_DLIGHTS "
115 "NEXUIZ_PLAYERMODEL "
123 Writes new values for v_forward, v_up, and v_right based on angles
127 void PF_makevectors (void)
129 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
136 Writes new values for v_forward, v_up, and v_right based on the given forward vector
137 vectorvectors(vector, vector)
140 void PF_vectorvectors (void)
142 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
143 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
150 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.
152 setorigin (entity, origin)
155 void PF_setorigin (void)
160 e = PRVM_G_EDICT(OFS_PARM0);
161 if (e == prog->edicts)
162 PF_WARNING("setorigin: can not modify world entity\n");
163 if (e->priv.server->free)
164 PF_WARNING("setorigin: can not modify free entity\n");
165 org = PRVM_G_VECTOR(OFS_PARM1);
166 VectorCopy (org, e->fields.server->origin);
167 SV_LinkEdict (e, false);
171 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
175 for (i=0 ; i<3 ; i++)
177 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs\n");
179 // set derived values
180 VectorCopy (min, e->fields.server->mins);
181 VectorCopy (max, e->fields.server->maxs);
182 VectorSubtract (max, min, e->fields.server->size);
184 SV_LinkEdict (e, false);
191 the size box is rotated by the current angle
192 LordHavoc: no it isn't...
194 setsize (entity, minvector, maxvector)
197 void PF_setsize (void)
202 e = PRVM_G_EDICT(OFS_PARM0);
203 if (e == prog->edicts)
204 PF_WARNING("setsize: can not modify world entity\n");
205 if (e->priv.server->free)
206 PF_WARNING("setsize: can not modify free entity\n");
207 min = PRVM_G_VECTOR(OFS_PARM1);
208 max = PRVM_G_VECTOR(OFS_PARM2);
209 SetMinMaxSize (e, min, max, false);
217 setmodel(entity, model)
220 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
221 void PF_setmodel (void)
227 e = PRVM_G_EDICT(OFS_PARM0);
228 if (e == prog->edicts)
229 PF_WARNING("setmodel: can not modify world entity\n");
230 if (e->priv.server->free)
231 PF_WARNING("setmodel: can not modify free entity\n");
232 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
233 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
234 e->fields.server->modelindex = i;
240 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
241 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
243 SetMinMaxSize (e, quakemins, quakemaxs, true);
246 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
253 single print to a specific client
255 sprint(clientent, value)
258 void PF_sprint (void)
262 char string[VM_STRINGTEMP_LENGTH];
264 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
266 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
268 Con_Print("tried to sprint to a non-client\n");
272 client = svs.clients + entnum-1;
273 VM_VarString(1, string, sizeof(string));
274 MSG_WriteChar(&client->message,svc_print);
275 MSG_WriteString(&client->message, string);
283 single print to a specific client
285 centerprint(clientent, value)
288 void PF_centerprint (void)
292 char string[VM_STRINGTEMP_LENGTH];
294 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
296 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
298 Con_Print("tried to sprint to a non-client\n");
302 client = svs.clients + entnum-1;
303 VM_VarString(1, string, sizeof(string));
304 MSG_WriteChar(&client->message,svc_centerprint);
305 MSG_WriteString(&client->message, string);
312 particle(origin, color, count)
315 void PF_particle (void)
321 org = PRVM_G_VECTOR(OFS_PARM0);
322 dir = PRVM_G_VECTOR(OFS_PARM1);
323 color = PRVM_G_FLOAT(OFS_PARM2);
324 count = PRVM_G_FLOAT(OFS_PARM3);
325 SV_StartParticle (org, dir, color, count);
335 void PF_ambientsound (void)
339 float vol, attenuation;
342 pos = PRVM_G_VECTOR (OFS_PARM0);
343 samp = PRVM_G_STRING(OFS_PARM1);
344 vol = PRVM_G_FLOAT(OFS_PARM2);
345 attenuation = PRVM_G_FLOAT(OFS_PARM3);
347 // check to see if samp was properly precached
348 soundnum = SV_SoundIndex(samp, 1);
356 // add an svc_spawnambient command to the level signon packet
359 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
361 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
363 MSG_WriteVector(&sv.signon, pos, sv.protocol);
366 MSG_WriteShort (&sv.signon, soundnum);
368 MSG_WriteByte (&sv.signon, soundnum);
370 MSG_WriteByte (&sv.signon, vol*255);
371 MSG_WriteByte (&sv.signon, attenuation*64);
379 Each entity can have eight independant sound sources, like voice,
382 Channel 0 is an auto-allocate channel, the others override anything
383 already running on that entity/channel pair.
385 An attenuation of 0 will play full volume everywhere in the level.
386 Larger attenuations will drop off.
394 prvm_edict_t *entity;
398 entity = PRVM_G_EDICT(OFS_PARM0);
399 channel = PRVM_G_FLOAT(OFS_PARM1);
400 sample = PRVM_G_STRING(OFS_PARM2);
401 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
402 attenuation = PRVM_G_FLOAT(OFS_PARM4);
404 if (volume < 0 || volume > 255)
405 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
407 if (attenuation < 0 || attenuation > 4)
408 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
410 if (channel < 0 || channel > 7)
411 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
413 SV_StartSound (entity, channel, sample, volume, attenuation);
420 Used for use tracing and shot targeting
421 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
422 if the tryents flag is set.
424 traceline (vector1, vector2, tryents)
427 void PF_traceline (void)
434 prog->xfunction->builtinsprofile += 30;
436 v1 = PRVM_G_VECTOR(OFS_PARM0);
437 v2 = PRVM_G_VECTOR(OFS_PARM1);
438 move = PRVM_G_FLOAT(OFS_PARM2);
439 ent = PRVM_G_EDICT(OFS_PARM3);
441 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
443 prog->globals.server->trace_allsolid = trace.allsolid;
444 prog->globals.server->trace_startsolid = trace.startsolid;
445 prog->globals.server->trace_fraction = trace.fraction;
446 prog->globals.server->trace_inwater = trace.inwater;
447 prog->globals.server->trace_inopen = trace.inopen;
448 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
449 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
450 prog->globals.server->trace_plane_dist = trace.plane.dist;
452 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
454 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
455 // FIXME: add trace_endcontents
463 Used for use tracing and shot targeting
464 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
465 if the tryents flag is set.
467 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
470 // LordHavoc: added this for my own use, VERY useful, similar to traceline
471 void PF_tracebox (void)
473 float *v1, *v2, *m1, *m2;
478 prog->xfunction->builtinsprofile += 30;
480 v1 = PRVM_G_VECTOR(OFS_PARM0);
481 m1 = PRVM_G_VECTOR(OFS_PARM1);
482 m2 = PRVM_G_VECTOR(OFS_PARM2);
483 v2 = PRVM_G_VECTOR(OFS_PARM3);
484 move = PRVM_G_FLOAT(OFS_PARM4);
485 ent = PRVM_G_EDICT(OFS_PARM5);
487 trace = SV_Move (v1, m1, m2, v2, move, ent);
489 prog->globals.server->trace_allsolid = trace.allsolid;
490 prog->globals.server->trace_startsolid = trace.startsolid;
491 prog->globals.server->trace_fraction = trace.fraction;
492 prog->globals.server->trace_inwater = trace.inwater;
493 prog->globals.server->trace_inopen = trace.inopen;
494 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
495 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
496 prog->globals.server->trace_plane_dist = trace.plane.dist;
498 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
500 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
503 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
504 void PF_tracetoss (void)
508 prvm_edict_t *ignore;
510 prog->xfunction->builtinsprofile += 600;
512 ent = PRVM_G_EDICT(OFS_PARM0);
513 if (ent == prog->edicts)
514 PF_WARNING("tracetoss: can not use world entity\n");
515 ignore = PRVM_G_EDICT(OFS_PARM1);
517 trace = SV_Trace_Toss (ent, ignore);
519 prog->globals.server->trace_allsolid = trace.allsolid;
520 prog->globals.server->trace_startsolid = trace.startsolid;
521 prog->globals.server->trace_fraction = trace.fraction;
522 prog->globals.server->trace_inwater = trace.inwater;
523 prog->globals.server->trace_inopen = trace.inopen;
524 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
525 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
526 prog->globals.server->trace_plane_dist = trace.plane.dist;
528 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
530 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
538 Returns true if the given entity can move to the given position from it's
539 current position by walking or rolling.
541 scalar checkpos (entity, vector)
544 void PF_checkpos (void)
548 //============================================================================
551 qbyte checkpvs[MAX_MAP_LEAFS/8];
553 int PF_newcheckclient (int check)
559 // cycle to the next one
561 check = bound(1, check, svs.maxclients);
562 if (check == svs.maxclients)
570 prog->xfunction->builtinsprofile++;
572 if (i == svs.maxclients+1)
574 // look up the client's edict
575 ent = PRVM_EDICT_NUM(i);
576 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
577 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
579 // found a valid client (possibly the same one again)
583 // get the PVS for the entity
584 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
586 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
587 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
596 Returns a client (or object that has a client enemy) that would be a
599 If there is more than one valid option, they are cycled each frame
601 If (self.origin + self.viewofs) is not in the PVS of the current target,
602 it is not returned at all.
607 int c_invis, c_notvis;
608 void PF_checkclient (void)
610 prvm_edict_t *ent, *self;
613 // find a new check if on a new frame
614 if (sv.time - sv.lastchecktime >= 0.1)
616 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
617 sv.lastchecktime = sv.time;
620 // return check if it might be visible
621 ent = PRVM_EDICT_NUM(sv.lastcheck);
622 if (ent->priv.server->free || ent->fields.server->health <= 0)
624 VM_RETURN_EDICT(prog->edicts);
628 // if current entity can't possibly see the check entity, return 0
629 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
630 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
631 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
634 VM_RETURN_EDICT(prog->edicts);
638 // might be able to see it
640 VM_RETURN_EDICT(ent);
643 //============================================================================
650 Sends text over to the client's execution buffer
652 stuffcmd (clientent, value)
655 void PF_stuffcmd (void)
661 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
662 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
664 Con_Print("Can't stuffcmd to a non-client\n");
667 str = PRVM_G_STRING(OFS_PARM1);
670 host_client = svs.clients + entnum-1;
671 Host_ClientCommands ("%s", str);
679 Returns a chain of entities that have origins within a spherical area
681 findradius (origin, radius)
684 void PF_findradius (void)
686 prvm_edict_t *ent, *chain;
687 vec_t radius, radius2;
688 vec3_t org, eorg, mins, maxs;
691 prvm_edict_t *touchedicts[MAX_EDICTS];
693 chain = (prvm_edict_t *)prog->edicts;
695 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
696 radius = PRVM_G_FLOAT(OFS_PARM1);
697 radius2 = radius * radius;
699 mins[0] = org[0] - (radius + 1);
700 mins[1] = org[1] - (radius + 1);
701 mins[2] = org[2] - (radius + 1);
702 maxs[0] = org[0] + (radius + 1);
703 maxs[1] = org[1] + (radius + 1);
704 maxs[2] = org[2] + (radius + 1);
705 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
706 if (numtouchedicts > MAX_EDICTS)
708 // this never happens
709 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
710 numtouchedicts = MAX_EDICTS;
712 for (i = 0;i < numtouchedicts;i++)
714 ent = touchedicts[i];
715 prog->xfunction->builtinsprofile++;
716 // Quake did not return non-solid entities but darkplaces does
717 // (note: this is the reason you can't blow up fallen zombies)
718 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
720 // LordHavoc: compare against bounding box rather than center so it
721 // doesn't miss large objects, and use DotProduct instead of Length
722 // for a major speedup
723 VectorSubtract(org, ent->fields.server->origin, eorg);
724 if (sv_gameplayfix_findradiusdistancetobox.integer)
726 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
727 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
728 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
731 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
732 if (DotProduct(eorg, eorg) < radius2)
734 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
739 VM_RETURN_EDICT(chain);
742 void PF_precache_file (void)
743 { // precache_file is only used to copy files with qcc, it does nothing
744 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
748 void PF_precache_sound (void)
750 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
751 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
754 void PF_precache_model (void)
756 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
757 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
764 float(float yaw, float dist) walkmove
767 void PF_walkmove (void)
775 // assume failure if it returns early
776 PRVM_G_FLOAT(OFS_RETURN) = 0;
778 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
779 if (ent == prog->edicts)
780 PF_WARNING("walkmove: can not modify world entity\n");
781 if (ent->priv.server->free)
782 PF_WARNING("walkmove: can not modify free entity\n");
783 yaw = PRVM_G_FLOAT(OFS_PARM0);
784 dist = PRVM_G_FLOAT(OFS_PARM1);
786 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
789 yaw = yaw*M_PI*2 / 360;
791 move[0] = cos(yaw)*dist;
792 move[1] = sin(yaw)*dist;
795 // save program state, because SV_movestep may call other progs
796 oldf = prog->xfunction;
797 oldself = prog->globals.server->self;
799 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
802 // restore program state
803 prog->xfunction = oldf;
804 prog->globals.server->self = oldself;
814 void PF_droptofloor (void)
820 // assume failure if it returns early
821 PRVM_G_FLOAT(OFS_RETURN) = 0;
823 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
824 if (ent == prog->edicts)
825 PF_WARNING("droptofloor: can not modify world entity\n");
826 if (ent->priv.server->free)
827 PF_WARNING("droptofloor: can not modify free entity\n");
829 VectorCopy (ent->fields.server->origin, end);
832 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
834 if (trace.fraction != 1)
836 VectorCopy (trace.endpos, ent->fields.server->origin);
837 SV_LinkEdict (ent, false);
838 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
839 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
840 PRVM_G_FLOAT(OFS_RETURN) = 1;
841 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
842 ent->priv.server->suspendedinairflag = true;
850 void(float style, string value) lightstyle
853 void PF_lightstyle (void)
860 style = PRVM_G_FLOAT(OFS_PARM0);
861 val = PRVM_G_STRING(OFS_PARM1);
863 // change the string in sv
864 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
866 // send message to all clients on this server
867 if (sv.state != ss_active)
870 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
874 MSG_WriteChar (&client->message, svc_lightstyle);
875 MSG_WriteChar (&client->message,style);
876 MSG_WriteString (&client->message, val);
886 void PF_checkbottom (void)
888 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
896 void PF_pointcontents (void)
898 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
905 Pick a vector for the player to shoot along
906 vector aim(entity, missilespeed)
911 prvm_edict_t *ent, *check, *bestent;
912 vec3_t start, dir, end, bestdir;
915 float dist, bestdist;
918 // assume failure if it returns early
919 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
920 // if sv_aim is so high it can't possibly accept anything, skip out early
921 if (sv_aim.value >= 1)
924 ent = PRVM_G_EDICT(OFS_PARM0);
925 if (ent == prog->edicts)
926 PF_WARNING("aim: can not use world entity\n");
927 if (ent->priv.server->free)
928 PF_WARNING("aim: can not use free entity\n");
929 speed = PRVM_G_FLOAT(OFS_PARM1);
931 VectorCopy (ent->fields.server->origin, start);
934 // try sending a trace straight
935 VectorCopy (prog->globals.server->v_forward, dir);
936 VectorMA (start, 2048, dir, end);
937 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
938 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
939 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
941 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
946 // try all possible entities
947 VectorCopy (dir, bestdir);
948 bestdist = sv_aim.value;
951 check = PRVM_NEXT_EDICT(prog->edicts);
952 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
954 prog->xfunction->builtinsprofile++;
955 if (check->fields.server->takedamage != DAMAGE_AIM)
959 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
960 continue; // don't aim at teammate
961 for (j=0 ; j<3 ; j++)
962 end[j] = check->fields.server->origin[j]
963 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
964 VectorSubtract (end, start, dir);
965 VectorNormalize (dir);
966 dist = DotProduct (dir, prog->globals.server->v_forward);
968 continue; // to far to turn
969 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
971 { // can shoot at this one
979 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
980 dist = DotProduct (dir, prog->globals.server->v_forward);
981 VectorScale (prog->globals.server->v_forward, dist, end);
983 VectorNormalize (end);
984 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
988 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
996 This was a major timewaster in progs, so it was converted to C
999 void PF_changeyaw (void)
1002 float ideal, current, move, speed;
1004 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1005 if (ent == prog->edicts)
1006 PF_WARNING("changeyaw: can not modify world entity\n");
1007 if (ent->priv.server->free)
1008 PF_WARNING("changeyaw: can not modify free entity\n");
1009 current = ANGLEMOD(ent->fields.server->angles[1]);
1010 ideal = ent->fields.server->ideal_yaw;
1011 speed = ent->fields.server->yaw_speed;
1013 if (current == ideal)
1015 move = ideal - current;
1016 if (ideal > current)
1037 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1045 void PF_changepitch (void)
1048 float ideal, current, move, speed;
1051 ent = PRVM_G_EDICT(OFS_PARM0);
1052 if (ent == prog->edicts)
1053 PF_WARNING("changepitch: can not modify world entity\n");
1054 if (ent->priv.server->free)
1055 PF_WARNING("changepitch: can not modify free entity\n");
1056 current = ANGLEMOD( ent->fields.server->angles[0] );
1057 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1058 ideal = val->_float;
1061 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1064 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1065 speed = val->_float;
1068 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1072 if (current == ideal)
1074 move = ideal - current;
1075 if (ideal > current)
1096 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1100 ===============================================================================
1104 ===============================================================================
1107 #define MSG_BROADCAST 0 // unreliable to all
1108 #define MSG_ONE 1 // reliable to one (msg_entity)
1109 #define MSG_ALL 2 // reliable to all
1110 #define MSG_INIT 3 // write to the init string
1112 sizebuf_t *WriteDest (void)
1118 dest = PRVM_G_FLOAT(OFS_PARM0);
1122 return &sv.datagram;
1125 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1126 entnum = PRVM_NUM_FOR_EDICT(ent);
1127 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1129 Con_Printf ("WriteDest: tried to write to non-client\n");
1130 return &sv.reliable_datagram;
1133 return &svs.clients[entnum-1].message;
1136 Con_Printf ("WriteDest: bad destination");
1138 return &sv.reliable_datagram;
1147 void PF_WriteByte (void)
1149 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1152 void PF_WriteChar (void)
1154 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1157 void PF_WriteShort (void)
1159 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1162 void PF_WriteLong (void)
1164 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1167 void PF_WriteAngle (void)
1169 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1172 void PF_WriteCoord (void)
1174 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1177 void PF_WriteString (void)
1179 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1183 void PF_WriteEntity (void)
1185 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1188 //////////////////////////////////////////////////////////
1190 void PF_makestatic (void)
1195 ent = PRVM_G_EDICT(OFS_PARM0);
1196 if (ent == prog->edicts)
1197 PF_WARNING("makestatic: can not modify world entity\n");
1198 if (ent->priv.server->free)
1199 PF_WARNING("makestatic: can not modify free entity\n");
1202 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1207 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1208 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1209 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1213 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1214 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1215 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1218 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1219 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1220 for (i=0 ; i<3 ; i++)
1222 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1223 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1226 // throw the entity away now
1230 //=============================================================================
1237 void PF_setspawnparms (void)
1243 ent = PRVM_G_EDICT(OFS_PARM0);
1244 i = PRVM_NUM_FOR_EDICT(ent);
1245 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1247 Con_Print("tried to setspawnparms on a non-client\n");
1251 // copy spawn parms out of the client_t
1252 client = svs.clients + i-1;
1253 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1254 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1261 Returns a color vector indicating the lighting at the requested point.
1263 (Internal Operation note: actually measures the light beneath the point, just like
1264 the model lighting on the client)
1269 void PF_getlight (void)
1271 vec3_t ambientcolor, diffusecolor, diffusenormal;
1273 p = PRVM_G_VECTOR(OFS_PARM0);
1274 VectorClear(ambientcolor);
1275 VectorClear(diffusecolor);
1276 VectorClear(diffusenormal);
1277 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1278 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1279 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1282 void PF_registercvar (void)
1284 const char *name, *value;
1285 name = PRVM_G_STRING(OFS_PARM0);
1286 value = PRVM_G_STRING(OFS_PARM1);
1287 PRVM_G_FLOAT(OFS_RETURN) = 0;
1289 // first check to see if it has already been defined
1290 if (Cvar_FindVar (name))
1293 // check for overlap with a command
1294 if (Cmd_Exists (name))
1296 Con_Printf("PF_registercvar: %s is a command\n", name);
1300 Cvar_Get(name, value, 0);
1302 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1309 copies data from one entity to another
1311 copyentity(src, dst)
1314 void PF_copyentity (void)
1316 prvm_edict_t *in, *out;
1317 in = PRVM_G_EDICT(OFS_PARM0);
1318 if (in == prog->edicts)
1319 PF_WARNING("copyentity: can not read world entity\n");
1320 if (in->priv.server->free)
1321 PF_WARNING("copyentity: can not read free entity\n");
1322 out = PRVM_G_EDICT(OFS_PARM1);
1323 if (out == prog->edicts)
1324 PF_WARNING("copyentity: can not modify world entity\n");
1325 if (out->priv.server->free)
1326 PF_WARNING("copyentity: can not modify free entity\n");
1327 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1335 sets the color of a client and broadcasts the update to all connected clients
1337 setcolor(clientent, value)
1340 void PF_setcolor (void)
1346 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1347 i = PRVM_G_FLOAT(OFS_PARM1);
1349 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1351 Con_Print("tried to setcolor a non-client\n");
1355 client = svs.clients + entnum-1;
1358 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1360 client->edict->fields.server->team = (i & 15) + 1;
1363 if (client->old_colors != client->colors)
1365 client->old_colors = client->colors;
1366 // send notification to all clients
1367 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1368 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1369 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1377 effect(origin, modelname, startframe, framecount, framerate)
1380 void PF_effect (void)
1384 s = PRVM_G_STRING(OFS_PARM1);
1386 PF_WARNING("effect: no model specified\n");
1388 i = SV_ModelIndex(s, 1);
1390 PF_WARNING("effect: model not precached\n");
1391 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1394 void PF_te_blood (void)
1396 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1398 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1399 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1401 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1402 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1403 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1405 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1406 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1407 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1409 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1412 void PF_te_bloodshower (void)
1414 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1416 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1417 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1419 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1420 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1421 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1423 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1424 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1425 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1427 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1429 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1432 void PF_te_explosionrgb (void)
1434 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1435 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1437 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1438 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1439 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1441 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1442 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1443 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1446 void PF_te_particlecube (void)
1448 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1450 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1451 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1453 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1454 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1455 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1457 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1458 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1459 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1461 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1462 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1463 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1465 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1467 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1468 // gravity true/false
1469 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1471 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1474 void PF_te_particlerain (void)
1476 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1478 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1479 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1481 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1482 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1483 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1485 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1486 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1487 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1489 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1490 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1491 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1493 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1495 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1498 void PF_te_particlesnow (void)
1500 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1502 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1503 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1505 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1506 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1507 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1509 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1510 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1511 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1513 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1514 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1515 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1517 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1519 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1522 void PF_te_spark (void)
1524 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1526 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1527 MSG_WriteByte(&sv.datagram, TE_SPARK);
1529 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1530 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1531 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1533 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1534 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1535 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1537 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1540 void PF_te_gunshotquad (void)
1542 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1543 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1545 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1550 void PF_te_spikequad (void)
1552 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1553 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1555 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1556 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1557 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1560 void PF_te_superspikequad (void)
1562 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1563 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1565 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1570 void PF_te_explosionquad (void)
1572 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1573 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1575 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1576 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1577 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1580 void PF_te_smallflash (void)
1582 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1583 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1585 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1586 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1587 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1590 void PF_te_customflash (void)
1592 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1594 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1595 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1597 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1598 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1599 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1601 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1603 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1605 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1606 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1607 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1610 void PF_te_gunshot (void)
1612 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1613 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1615 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1616 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1617 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1620 void PF_te_spike (void)
1622 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1623 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1625 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1626 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1627 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1630 void PF_te_superspike (void)
1632 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1633 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1635 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1636 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1637 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1640 void PF_te_explosion (void)
1642 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1643 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1645 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1650 void PF_te_tarexplosion (void)
1652 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1653 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1656 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1660 void PF_te_wizspike (void)
1662 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1663 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1670 void PF_te_knightspike (void)
1672 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1673 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1676 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1677 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1680 void PF_te_lavasplash (void)
1682 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1683 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1690 void PF_te_teleport (void)
1692 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1693 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1695 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1696 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1697 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1700 void PF_te_explosion2 (void)
1702 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1703 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1706 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1709 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1710 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1713 void PF_te_lightning1 (void)
1715 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1716 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1718 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1725 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1729 void PF_te_lightning2 (void)
1731 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1732 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1734 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1745 void PF_te_lightning3 (void)
1747 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1748 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1750 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1756 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1757 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1761 void PF_te_beam (void)
1763 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1764 MSG_WriteByte(&sv.datagram, TE_BEAM);
1766 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1777 void PF_te_plasmaburn (void)
1779 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1780 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1786 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1789 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1791 bestdist = 1000000000;
1793 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1795 // clip original point to each triangle of the surface and find the
1796 // triangle that is closest
1797 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1798 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1799 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1800 TriangleNormal(v[0], v[1], v[2], facenormal);
1801 VectorNormalize(facenormal);
1802 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1803 VectorMA(p, offsetdist, facenormal, temp);
1804 for (j = 0, k = 2;j < 3;k = j, j++)
1806 VectorSubtract(v[k], v[j], edgenormal);
1807 CrossProduct(edgenormal, facenormal, sidenormal);
1808 VectorNormalize(sidenormal);
1809 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1811 VectorMA(temp, offsetdist, sidenormal, temp);
1813 dist = VectorDistance2(temp, p);
1814 if (bestdist > dist)
1817 VectorCopy(temp, out);
1822 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1826 if (!ed || ed->priv.server->free)
1828 modelindex = ed->fields.server->modelindex;
1829 if (modelindex < 1 || modelindex >= MAX_MODELS)
1831 model = sv.models[modelindex];
1832 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1834 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1838 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1839 void PF_getsurfacenumpoints(void)
1841 msurface_t *surface;
1842 // return 0 if no such surface
1843 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1845 PRVM_G_FLOAT(OFS_RETURN) = 0;
1849 // note: this (incorrectly) assumes it is a simple polygon
1850 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1852 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1853 void PF_getsurfacepoint(void)
1856 msurface_t *surface;
1858 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1859 ed = PRVM_G_EDICT(OFS_PARM0);
1860 if (!ed || ed->priv.server->free)
1862 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1864 // note: this (incorrectly) assumes it is a simple polygon
1865 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1866 if (pointnum < 0 || pointnum >= surface->num_vertices)
1868 // FIXME: implement rotation/scaling
1869 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1871 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1872 void PF_getsurfacenormal(void)
1874 msurface_t *surface;
1876 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1877 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1879 // FIXME: implement rotation/scaling
1880 // note: this (incorrectly) assumes it is a simple polygon
1881 // note: this only returns the first triangle, so it doesn't work very
1882 // well for curved surfaces or arbitrary meshes
1883 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);
1884 VectorNormalize(normal);
1885 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1887 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1888 void PF_getsurfacetexture(void)
1890 msurface_t *surface;
1891 PRVM_G_INT(OFS_RETURN) = 0;
1892 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1894 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1896 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1897 void PF_getsurfacenearpoint(void)
1899 int surfacenum, best, modelindex;
1901 vec_t dist, bestdist;
1904 msurface_t *surface;
1906 PRVM_G_FLOAT(OFS_RETURN) = -1;
1907 ed = PRVM_G_EDICT(OFS_PARM0);
1908 point = PRVM_G_VECTOR(OFS_PARM1);
1910 if (!ed || ed->priv.server->free)
1912 modelindex = ed->fields.server->modelindex;
1913 if (modelindex < 1 || modelindex >= MAX_MODELS)
1915 model = sv.models[modelindex];
1916 if (!model->num_surfaces)
1919 // FIXME: implement rotation/scaling
1920 VectorSubtract(point, ed->fields.server->origin, p);
1922 bestdist = 1000000000;
1923 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1925 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1926 // first see if the nearest point on the surface's box is closer than the previous match
1927 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1928 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1929 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1930 dist = VectorLength2(clipped);
1931 if (dist < bestdist)
1933 // it is, check the nearest point on the actual geometry
1934 clippointtosurface(surface, p, clipped);
1935 VectorSubtract(clipped, p, clipped);
1936 dist += VectorLength2(clipped);
1937 if (dist < bestdist)
1939 // that's closer too, store it as the best match
1945 PRVM_G_FLOAT(OFS_RETURN) = best;
1947 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1948 void PF_getsurfaceclippedpoint(void)
1951 msurface_t *surface;
1953 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1954 ed = PRVM_G_EDICT(OFS_PARM0);
1955 if (!ed || ed->priv.server->free)
1957 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1959 // FIXME: implement rotation/scaling
1960 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1961 clippointtosurface(surface, p, out);
1962 // FIXME: implement rotation/scaling
1963 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1966 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1967 //this function originally written by KrimZon, made shorter by LordHavoc
1968 void PF_clientcommand (void)
1970 client_t *temp_client;
1973 //find client for this entity
1974 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
1975 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1977 Con_Print("PF_clientcommand: entity is not a client\n");
1981 temp_client = host_client;
1982 host_client = svs.clients + i;
1983 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1984 host_client = temp_client;
1987 //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)
1988 void PF_setattachment (void)
1990 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
1991 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
1992 const char *tagname = PRVM_G_STRING(OFS_PARM2);
1997 if (e == prog->edicts)
1998 PF_WARNING("setattachment: can not modify world entity\n");
1999 if (e->priv.server->free)
2000 PF_WARNING("setattachment: can not modify free entity\n");
2002 if (tagentity == NULL)
2003 tagentity = prog->edicts;
2005 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2007 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2009 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2012 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2014 modelindex = (int)tagentity->fields.server->modelindex;
2015 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2017 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2019 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);
2022 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));
2026 /////////////////////////////////////////
2027 // DP_MD3_TAGINFO extension coded by VorteX
2029 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2034 i = e->fields.server->modelindex;
2035 if (i < 1 || i >= MAX_MODELS)
2037 model = sv.models[i];
2039 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2042 // Warnings/errors code:
2043 // 0 - normal (everything all-right)
2046 // 3 - null or non-precached model
2047 // 4 - no tags with requested index
2048 // 5 - runaway loop at attachment chain
2049 extern cvar_t cl_bob;
2050 extern cvar_t cl_bobcycle;
2051 extern cvar_t cl_bobup;
2052 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2055 int modelindex, reqframe, attachloop;
2056 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2057 prvm_edict_t *attachent;
2060 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2062 if (ent == prog->edicts)
2064 if (ent->priv.server->free)
2067 modelindex = (int)ent->fields.server->modelindex;
2068 if (modelindex <= 0 || modelindex > MAX_MODELS)
2071 model = sv.models[modelindex];
2073 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2074 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2076 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2078 // get initial tag matrix
2081 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2086 Matrix4x4_CreateIdentity(&tagmatrix);
2088 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2089 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2093 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2094 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2095 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)
2096 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2098 Matrix4x4_CreateIdentity(&attachmatrix);
2100 // apply transformation by child entity matrix
2101 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2102 if (val->_float == 0)
2104 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);
2105 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2106 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]);
2107 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]);
2108 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]);
2109 Matrix4x4_Copy(&tagmatrix, out);
2111 // finally transformate by matrix of tag on parent entity
2112 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2113 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];
2114 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];
2115 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];
2116 Matrix4x4_Copy(&tagmatrix, out);
2120 if (attachloop > 255) // prevent runaway looping
2123 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2126 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2127 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2128 if (val->_float == 0)
2130 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2131 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);
2132 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2133 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]);
2134 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]);
2135 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]);
2137 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2138 {// RENDER_VIEWMODEL magic
2139 Matrix4x4_Copy(&tagmatrix, out);
2140 ent = PRVM_EDICT_NUM(val->edict);
2142 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2143 if (val->_float == 0)
2146 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);
2147 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2148 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]);
2149 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]);
2150 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]);
2153 // Cl_bob, ported from rendering code
2154 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2157 // LordHavoc: this code is *weird*, but not replacable (I think it
2158 // should be done in QC on the server, but oh well, quake is quake)
2159 // LordHavoc: figured out bobup: the time at which the sin is at 180
2160 // degrees (which allows lengthening or squishing the peak or valley)
2161 cycle = sv.time/cl_bobcycle.value;
2162 cycle -= (int)cycle;
2163 if (cycle < cl_bobup.value)
2164 cycle = sin(M_PI * cycle / cl_bobup.value);
2166 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2167 // bob is proportional to velocity in the xy plane
2168 // (don't count Z, or jumping messes it up)
2169 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;
2170 bob = bob*0.3 + bob*0.7*cycle;
2171 out->m[2][3] += bound(-7, bob, 4);
2178 //float(entity ent, string tagname) gettagindex;
2180 void PF_gettagindex (void)
2182 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2183 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2184 int modelindex, tag_index;
2186 if (ent == prog->edicts)
2187 PF_WARNING("gettagindex: can't affect world entity\n");
2188 if (ent->priv.server->free)
2189 PF_WARNING("gettagindex: can't affect free entity\n");
2191 modelindex = (int)ent->fields.server->modelindex;
2193 if (modelindex <= 0 || modelindex > MAX_MODELS)
2194 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2197 tag_index = SV_GetTagIndex(ent, tag_name);
2199 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2201 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2204 //vector(entity ent, float tagindex) gettaginfo;
2205 void PF_gettaginfo (void)
2207 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2208 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2209 matrix4x4_t tag_matrix;
2212 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2213 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2218 PF_WARNING("gettagindex: can't affect world entity\n");
2221 PF_WARNING("gettagindex: can't affect free entity\n");
2224 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2227 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2230 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2235 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2236 void PF_dropclient (void)
2239 client_t *oldhostclient;
2240 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2241 if (clientnum < 0 || clientnum >= svs.maxclients)
2242 PF_WARNING("dropclient: not a client\n");
2243 if (!svs.clients[clientnum].active)
2244 PF_WARNING("dropclient: that client slot is not connected\n");
2245 oldhostclient = host_client;
2246 host_client = svs.clients + clientnum;
2247 SV_DropClient(false);
2248 host_client = oldhostclient;
2251 //entity() spawnclient (DP_SV_BOTCLIENT)
2252 void PF_spawnclient (void)
2256 prog->xfunction->builtinsprofile += 2;
2258 for (i = 0;i < svs.maxclients;i++)
2260 if (!svs.clients[i].active)
2262 prog->xfunction->builtinsprofile += 100;
2263 SV_ConnectClient (i, NULL);
2264 ed = PRVM_EDICT_NUM(i + 1);
2268 VM_RETURN_EDICT(ed);
2271 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2272 void PF_clienttype (void)
2275 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2276 if (clientnum < 0 || clientnum >= svs.maxclients)
2277 PRVM_G_FLOAT(OFS_RETURN) = 3;
2278 else if (!svs.clients[clientnum].active)
2279 PRVM_G_FLOAT(OFS_RETURN) = 0;
2280 else if (svs.clients[clientnum].netconnection)
2281 PRVM_G_FLOAT(OFS_RETURN) = 1;
2283 PRVM_G_FLOAT(OFS_RETURN) = 2;
2286 prvm_builtin_t vm_sv_builtins[] = {
2288 PF_makevectors, // #1 void(entity e) makevectors
2289 PF_setorigin, // #2 void(entity e, vector o) setorigin
2290 PF_setmodel, // #3 void(entity e, string m) setmodel
2291 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2292 NULL, // #5 void(entity e, vector min, vector max) setabssize
2293 VM_break, // #6 void() break
2294 VM_random, // #7 float() random
2295 PF_sound, // #8 void(entity e, float chan, string samp) sound
2296 VM_normalize, // #9 vector(vector v) normalize
2297 VM_error, // #10 void(string e) error
2298 VM_objerror, // #11 void(string e) objerror
2299 VM_vlen, // #12 float(vector v) vlen
2300 VM_vectoyaw, // #13 float(vector v) vectoyaw
2301 VM_spawn, // #14 entity() spawn
2302 VM_remove, // #15 void(entity e) remove
2303 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2304 PF_checkclient, // #17 entity() clientlist
2305 VM_find, // #18 entity(entity start, .string fld, string match) find
2306 PF_precache_sound, // #19 void(string s) precache_sound
2307 PF_precache_model, // #20 void(string s) precache_model
2308 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2309 PF_findradius, // #22 entity(vector org, float rad) findradius
2310 VM_bprint, // #23 void(string s) bprint
2311 PF_sprint, // #24 void(entity client, string s) sprint
2312 VM_dprint, // #25 void(string s) dprint
2313 VM_ftos, // #26 void(string s) ftos
2314 VM_vtos, // #27 void(string s) vtos
2315 VM_coredump, // #28 void() coredump
2316 VM_traceon, // #29 void() traceon
2317 VM_traceoff, // #30 void() traceoff
2318 VM_eprint, // #31 void(entity e) eprint
2319 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2321 PF_droptofloor, // #34 float() droptofloor
2322 PF_lightstyle, // #35 void(float style, string value) lightstyle
2323 VM_rint, // #36 float(float v) rint
2324 VM_floor, // #37 float(float v) floor
2325 VM_ceil, // #38 float(float v) ceil
2327 PF_checkbottom, // #40 float(entity e) checkbottom
2328 PF_pointcontents, // #41 float(vector v) pointcontents
2330 VM_fabs, // #43 float(float f) fabs
2331 PF_aim, // #44 vector(entity e, float speed) aim
2332 VM_cvar, // #45 float(string s) cvar
2333 VM_localcmd, // #46 void(string s) localcmd
2334 VM_nextent, // #47 entity(entity e) nextent
2335 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2336 PF_changeyaw, // #49 void() ChangeYaw
2338 VM_vectoangles, // #51 vector(vector v) vectoangles
2339 PF_WriteByte, // #52 void(float to, float f) WriteByte
2340 PF_WriteChar, // #53 void(float to, float f) WriteChar
2341 PF_WriteShort, // #54 void(float to, float f) WriteShort
2342 PF_WriteLong, // #55 void(float to, float f) WriteLong
2343 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2344 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2345 PF_WriteString, // #58 void(float to, string s) WriteString
2346 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2347 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2348 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2349 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2350 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2351 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2352 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2354 SV_MoveToGoal, // #67 void(float step) movetogoal
2355 PF_precache_file, // #68 string(string s) precache_file
2356 PF_makestatic, // #69 void(entity e) makestatic
2357 VM_changelevel, // #70 void(string s) changelevel
2359 VM_cvar_set, // #72 void(string var, string val) cvar_set
2360 PF_centerprint, // #73 void(entity client, strings) centerprint
2361 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2362 PF_precache_model, // #75 string(string s) precache_model2
2363 PF_precache_sound, // #76 string(string s) precache_sound2
2364 PF_precache_file, // #77 string(string s) precache_file2
2365 PF_setspawnparms, // #78 void(entity e) setspawnparms
2368 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2377 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2378 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2379 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2380 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2381 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2382 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2383 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2384 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2385 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2386 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2397 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2398 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2399 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2400 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2401 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2402 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2403 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2404 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2405 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2406 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2407 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2408 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2409 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2410 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2411 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2412 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2413 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2414 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2415 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2416 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2417 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2418 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2419 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2420 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2421 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2422 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2423 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2424 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2425 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2426 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2427 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2428 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2429 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2430 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2431 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2432 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2433 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2434 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2435 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2436 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2437 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2438 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2439 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2440 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2441 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2442 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2443 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2444 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2445 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2446 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2447 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2448 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2449 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2450 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2451 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2452 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2453 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2454 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2455 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2456 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2457 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2458 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2459 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2460 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2461 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2462 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2463 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2464 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2465 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2470 e10, e10, e10, e10 // #460-499 (LordHavoc)
2473 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2475 void VM_SV_Cmd_Init(void)
2480 void VM_SV_Cmd_Reset(void)