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 "
73 "DP_SND_DIRECTIONLESSATTNNONE "
82 "DP_SV_DRAWONLYTOCLIENT "
85 "DP_SV_NODRAWTOCLIENT "
87 "DP_SV_PLAYERPHYSICS "
89 "DP_SV_ROTATINGBMODEL "
101 "DP_TE_QUADEFFECTS1 "
104 "DP_TE_STANDARDEFFECTBUILTINS "
107 "KRIMZON_SV_PARSECLIENTCOMMAND "
111 "PRYDON_CLIENTCURSOR "
112 "TENEBRAE_GFX_DLIGHTS "
114 "NEXUIZ_PLAYERMODEL "
122 Writes new values for v_forward, v_up, and v_right based on angles
126 void PF_makevectors (void)
128 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
135 Writes new values for v_forward, v_up, and v_right based on the given forward vector
136 vectorvectors(vector, vector)
139 void PF_vectorvectors (void)
141 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
142 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
149 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.
151 setorigin (entity, origin)
154 void PF_setorigin (void)
159 e = PRVM_G_EDICT(OFS_PARM0);
160 if (e == prog->edicts)
161 PF_WARNING("setorigin: can not modify world entity\n");
162 if (e->priv.server->free)
163 PF_WARNING("setorigin: can not modify free entity\n");
164 org = PRVM_G_VECTOR(OFS_PARM1);
165 VectorCopy (org, e->fields.server->origin);
166 SV_LinkEdict (e, false);
170 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
174 for (i=0 ; i<3 ; i++)
176 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs\n");
178 // set derived values
179 VectorCopy (min, e->fields.server->mins);
180 VectorCopy (max, e->fields.server->maxs);
181 VectorSubtract (max, min, e->fields.server->size);
183 SV_LinkEdict (e, false);
190 the size box is rotated by the current angle
191 LordHavoc: no it isn't...
193 setsize (entity, minvector, maxvector)
196 void PF_setsize (void)
201 e = PRVM_G_EDICT(OFS_PARM0);
202 if (e == prog->edicts)
203 PF_WARNING("setsize: can not modify world entity\n");
204 if (e->priv.server->free)
205 PF_WARNING("setsize: can not modify free entity\n");
206 min = PRVM_G_VECTOR(OFS_PARM1);
207 max = PRVM_G_VECTOR(OFS_PARM2);
208 SetMinMaxSize (e, min, max, false);
216 setmodel(entity, model)
219 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
220 void PF_setmodel (void)
226 e = PRVM_G_EDICT(OFS_PARM0);
227 if (e == prog->edicts)
228 PF_WARNING("setmodel: can not modify world entity\n");
229 if (e->priv.server->free)
230 PF_WARNING("setmodel: can not modify free entity\n");
231 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
232 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
233 e->fields.server->modelindex = i;
239 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
240 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
242 SetMinMaxSize (e, quakemins, quakemaxs, true);
245 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
252 single print to a specific client
254 sprint(clientent, value)
257 void PF_sprint (void)
261 char string[VM_STRINGTEMP_LENGTH];
263 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
265 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
267 Con_Print("tried to sprint to a non-client\n");
271 client = svs.clients + entnum-1;
272 VM_VarString(1, string, sizeof(string));
273 MSG_WriteChar(&client->message,svc_print);
274 MSG_WriteString(&client->message, string);
282 single print to a specific client
284 centerprint(clientent, value)
287 void PF_centerprint (void)
291 char string[VM_STRINGTEMP_LENGTH];
293 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
295 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
297 Con_Print("tried to sprint to a non-client\n");
301 client = svs.clients + entnum-1;
302 VM_VarString(1, string, sizeof(string));
303 MSG_WriteChar(&client->message,svc_centerprint);
304 MSG_WriteString(&client->message, string);
311 particle(origin, color, count)
314 void PF_particle (void)
320 org = PRVM_G_VECTOR(OFS_PARM0);
321 dir = PRVM_G_VECTOR(OFS_PARM1);
322 color = PRVM_G_FLOAT(OFS_PARM2);
323 count = PRVM_G_FLOAT(OFS_PARM3);
324 SV_StartParticle (org, dir, color, count);
334 void PF_ambientsound (void)
338 float vol, attenuation;
341 pos = PRVM_G_VECTOR (OFS_PARM0);
342 samp = PRVM_G_STRING(OFS_PARM1);
343 vol = PRVM_G_FLOAT(OFS_PARM2);
344 attenuation = PRVM_G_FLOAT(OFS_PARM3);
346 // check to see if samp was properly precached
347 soundnum = SV_SoundIndex(samp, 1);
355 // add an svc_spawnambient command to the level signon packet
358 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
360 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
362 MSG_WriteVector(&sv.signon, pos, sv.protocol);
365 MSG_WriteShort (&sv.signon, soundnum);
367 MSG_WriteByte (&sv.signon, soundnum);
369 MSG_WriteByte (&sv.signon, vol*255);
370 MSG_WriteByte (&sv.signon, attenuation*64);
378 Each entity can have eight independant sound sources, like voice,
381 Channel 0 is an auto-allocate channel, the others override anything
382 already running on that entity/channel pair.
384 An attenuation of 0 will play full volume everywhere in the level.
385 Larger attenuations will drop off.
393 prvm_edict_t *entity;
397 entity = PRVM_G_EDICT(OFS_PARM0);
398 channel = PRVM_G_FLOAT(OFS_PARM1);
399 sample = PRVM_G_STRING(OFS_PARM2);
400 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
401 attenuation = PRVM_G_FLOAT(OFS_PARM4);
403 if (volume < 0 || volume > 255)
404 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
406 if (attenuation < 0 || attenuation > 4)
407 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
409 if (channel < 0 || channel > 7)
410 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
412 SV_StartSound (entity, channel, sample, volume, attenuation);
419 Used for use tracing and shot targeting
420 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
421 if the tryents flag is set.
423 traceline (vector1, vector2, tryents)
426 void PF_traceline (void)
433 prog->xfunction->builtinsprofile += 30;
435 v1 = PRVM_G_VECTOR(OFS_PARM0);
436 v2 = PRVM_G_VECTOR(OFS_PARM1);
437 move = PRVM_G_FLOAT(OFS_PARM2);
438 ent = PRVM_G_EDICT(OFS_PARM3);
440 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
442 prog->globals.server->trace_allsolid = trace.allsolid;
443 prog->globals.server->trace_startsolid = trace.startsolid;
444 prog->globals.server->trace_fraction = trace.fraction;
445 prog->globals.server->trace_inwater = trace.inwater;
446 prog->globals.server->trace_inopen = trace.inopen;
447 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
448 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
449 prog->globals.server->trace_plane_dist = trace.plane.dist;
451 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
453 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
454 // FIXME: add trace_endcontents
462 Used for use tracing and shot targeting
463 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
464 if the tryents flag is set.
466 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
469 // LordHavoc: added this for my own use, VERY useful, similar to traceline
470 void PF_tracebox (void)
472 float *v1, *v2, *m1, *m2;
477 prog->xfunction->builtinsprofile += 30;
479 v1 = PRVM_G_VECTOR(OFS_PARM0);
480 m1 = PRVM_G_VECTOR(OFS_PARM1);
481 m2 = PRVM_G_VECTOR(OFS_PARM2);
482 v2 = PRVM_G_VECTOR(OFS_PARM3);
483 move = PRVM_G_FLOAT(OFS_PARM4);
484 ent = PRVM_G_EDICT(OFS_PARM5);
486 trace = SV_Move (v1, m1, m2, v2, move, ent);
488 prog->globals.server->trace_allsolid = trace.allsolid;
489 prog->globals.server->trace_startsolid = trace.startsolid;
490 prog->globals.server->trace_fraction = trace.fraction;
491 prog->globals.server->trace_inwater = trace.inwater;
492 prog->globals.server->trace_inopen = trace.inopen;
493 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
494 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
495 prog->globals.server->trace_plane_dist = trace.plane.dist;
497 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
499 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
502 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
503 void PF_tracetoss (void)
507 prvm_edict_t *ignore;
509 prog->xfunction->builtinsprofile += 600;
511 ent = PRVM_G_EDICT(OFS_PARM0);
512 if (ent == prog->edicts)
513 PF_WARNING("tracetoss: can not use world entity\n");
514 ignore = PRVM_G_EDICT(OFS_PARM1);
516 trace = SV_Trace_Toss (ent, ignore);
518 prog->globals.server->trace_allsolid = trace.allsolid;
519 prog->globals.server->trace_startsolid = trace.startsolid;
520 prog->globals.server->trace_fraction = trace.fraction;
521 prog->globals.server->trace_inwater = trace.inwater;
522 prog->globals.server->trace_inopen = trace.inopen;
523 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
524 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
525 prog->globals.server->trace_plane_dist = trace.plane.dist;
527 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
529 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
537 Returns true if the given entity can move to the given position from it's
538 current position by walking or rolling.
540 scalar checkpos (entity, vector)
543 void PF_checkpos (void)
547 //============================================================================
550 qbyte checkpvs[MAX_MAP_LEAFS/8];
552 int PF_newcheckclient (int check)
558 // cycle to the next one
560 check = bound(1, check, svs.maxclients);
561 if (check == svs.maxclients)
569 prog->xfunction->builtinsprofile++;
571 if (i == svs.maxclients+1)
573 // look up the client's edict
574 ent = PRVM_EDICT_NUM(i);
575 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
576 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
578 // found a valid client (possibly the same one again)
582 // get the PVS for the entity
583 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
585 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
586 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
595 Returns a client (or object that has a client enemy) that would be a
598 If there is more than one valid option, they are cycled each frame
600 If (self.origin + self.viewofs) is not in the PVS of the current target,
601 it is not returned at all.
606 int c_invis, c_notvis;
607 void PF_checkclient (void)
609 prvm_edict_t *ent, *self;
612 // find a new check if on a new frame
613 if (sv.time - sv.lastchecktime >= 0.1)
615 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
616 sv.lastchecktime = sv.time;
619 // return check if it might be visible
620 ent = PRVM_EDICT_NUM(sv.lastcheck);
621 if (ent->priv.server->free || ent->fields.server->health <= 0)
623 VM_RETURN_EDICT(prog->edicts);
627 // if current entity can't possibly see the check entity, return 0
628 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
629 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
630 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
633 VM_RETURN_EDICT(prog->edicts);
637 // might be able to see it
639 VM_RETURN_EDICT(ent);
642 //============================================================================
649 Sends text over to the client's execution buffer
651 stuffcmd (clientent, value)
654 void PF_stuffcmd (void)
660 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
661 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
663 Con_Print("Can't stuffcmd to a non-client\n");
666 str = PRVM_G_STRING(OFS_PARM1);
669 host_client = svs.clients + entnum-1;
670 Host_ClientCommands ("%s", str);
678 Returns a chain of entities that have origins within a spherical area
680 findradius (origin, radius)
683 void PF_findradius (void)
685 prvm_edict_t *ent, *chain;
686 vec_t radius, radius2;
687 vec3_t org, eorg, mins, maxs;
690 prvm_edict_t *touchedicts[MAX_EDICTS];
692 chain = (prvm_edict_t *)prog->edicts;
694 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
695 radius = PRVM_G_FLOAT(OFS_PARM1);
696 radius2 = radius * radius;
698 mins[0] = org[0] - (radius + 1);
699 mins[1] = org[1] - (radius + 1);
700 mins[2] = org[2] - (radius + 1);
701 maxs[0] = org[0] + (radius + 1);
702 maxs[1] = org[1] + (radius + 1);
703 maxs[2] = org[2] + (radius + 1);
704 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
705 if (numtouchedicts > MAX_EDICTS)
707 // this never happens
708 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
709 numtouchedicts = MAX_EDICTS;
711 for (i = 0;i < numtouchedicts;i++)
713 ent = touchedicts[i];
714 prog->xfunction->builtinsprofile++;
715 // Quake did not return non-solid entities but darkplaces does
716 // (note: this is the reason you can't blow up fallen zombies)
717 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
719 // LordHavoc: compare against bounding box rather than center so it
720 // doesn't miss large objects, and use DotProduct instead of Length
721 // for a major speedup
722 VectorSubtract(org, ent->fields.server->origin, eorg);
723 if (sv_gameplayfix_findradiusdistancetobox.integer)
725 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
726 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
727 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
730 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
731 if (DotProduct(eorg, eorg) < radius2)
733 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
738 VM_RETURN_EDICT(chain);
741 // LordHavoc: search for flags in float fields
742 void PF_findflags (void)
749 e = PRVM_G_EDICTNUM(OFS_PARM0);
750 f = PRVM_G_INT(OFS_PARM1);
751 s = (int)PRVM_G_FLOAT(OFS_PARM2);
753 for (e++ ; e < prog->num_edicts ; e++)
755 prog->xfunction->builtinsprofile++;
756 ed = PRVM_EDICT_NUM(e);
757 if (ed->priv.server->free)
759 if ((int)PRVM_E_FLOAT(ed,f) & s)
766 VM_RETURN_EDICT(prog->edicts);
769 // LordHavoc: chained search for flags in float fields
770 void PF_findchainflags (void)
775 prvm_edict_t *ent, *chain;
777 chain = (prvm_edict_t *)prog->edicts;
779 f = PRVM_G_INT(OFS_PARM0);
780 s = (int)PRVM_G_FLOAT(OFS_PARM1);
782 ent = PRVM_NEXT_EDICT(prog->edicts);
783 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
785 prog->xfunction->builtinsprofile++;
786 if (ent->priv.server->free)
788 if (!((int)PRVM_E_FLOAT(ent,f) & s))
791 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
795 VM_RETURN_EDICT(chain);
798 void PF_precache_file (void)
799 { // precache_file is only used to copy files with qcc, it does nothing
800 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
804 void PF_precache_sound (void)
806 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
807 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
810 void PF_precache_model (void)
812 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
813 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
820 float(float yaw, float dist) walkmove
823 void PF_walkmove (void)
831 // assume failure if it returns early
832 PRVM_G_FLOAT(OFS_RETURN) = 0;
834 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
835 if (ent == prog->edicts)
836 PF_WARNING("walkmove: can not modify world entity\n");
837 if (ent->priv.server->free)
838 PF_WARNING("walkmove: can not modify free entity\n");
839 yaw = PRVM_G_FLOAT(OFS_PARM0);
840 dist = PRVM_G_FLOAT(OFS_PARM1);
842 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
845 yaw = yaw*M_PI*2 / 360;
847 move[0] = cos(yaw)*dist;
848 move[1] = sin(yaw)*dist;
851 // save program state, because SV_movestep may call other progs
852 oldf = prog->xfunction;
853 oldself = prog->globals.server->self;
855 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
858 // restore program state
859 prog->xfunction = oldf;
860 prog->globals.server->self = oldself;
870 void PF_droptofloor (void)
876 // assume failure if it returns early
877 PRVM_G_FLOAT(OFS_RETURN) = 0;
879 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
880 if (ent == prog->edicts)
881 PF_WARNING("droptofloor: can not modify world entity\n");
882 if (ent->priv.server->free)
883 PF_WARNING("droptofloor: can not modify free entity\n");
885 VectorCopy (ent->fields.server->origin, end);
888 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
890 if (trace.fraction != 1)
892 VectorCopy (trace.endpos, ent->fields.server->origin);
893 SV_LinkEdict (ent, false);
894 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
895 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
896 PRVM_G_FLOAT(OFS_RETURN) = 1;
897 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
898 ent->priv.server->suspendedinairflag = true;
906 void(float style, string value) lightstyle
909 void PF_lightstyle (void)
916 style = PRVM_G_FLOAT(OFS_PARM0);
917 val = PRVM_G_STRING(OFS_PARM1);
919 // change the string in sv
920 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
922 // send message to all clients on this server
923 if (sv.state != ss_active)
926 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
930 MSG_WriteChar (&client->message, svc_lightstyle);
931 MSG_WriteChar (&client->message,style);
932 MSG_WriteString (&client->message, val);
942 void PF_checkbottom (void)
944 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
952 void PF_pointcontents (void)
954 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
961 Pick a vector for the player to shoot along
962 vector aim(entity, missilespeed)
967 prvm_edict_t *ent, *check, *bestent;
968 vec3_t start, dir, end, bestdir;
971 float dist, bestdist;
974 // assume failure if it returns early
975 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
976 // if sv_aim is so high it can't possibly accept anything, skip out early
977 if (sv_aim.value >= 1)
980 ent = PRVM_G_EDICT(OFS_PARM0);
981 if (ent == prog->edicts)
982 PF_WARNING("aim: can not use world entity\n");
983 if (ent->priv.server->free)
984 PF_WARNING("aim: can not use free entity\n");
985 speed = PRVM_G_FLOAT(OFS_PARM1);
987 VectorCopy (ent->fields.server->origin, start);
990 // try sending a trace straight
991 VectorCopy (prog->globals.server->v_forward, dir);
992 VectorMA (start, 2048, dir, end);
993 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
994 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
995 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
997 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1002 // try all possible entities
1003 VectorCopy (dir, bestdir);
1004 bestdist = sv_aim.value;
1007 check = PRVM_NEXT_EDICT(prog->edicts);
1008 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1010 prog->xfunction->builtinsprofile++;
1011 if (check->fields.server->takedamage != DAMAGE_AIM)
1015 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1016 continue; // don't aim at teammate
1017 for (j=0 ; j<3 ; j++)
1018 end[j] = check->fields.server->origin[j]
1019 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1020 VectorSubtract (end, start, dir);
1021 VectorNormalize (dir);
1022 dist = DotProduct (dir, prog->globals.server->v_forward);
1023 if (dist < bestdist)
1024 continue; // to far to turn
1025 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1026 if (tr.ent == check)
1027 { // can shoot at this one
1035 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1036 dist = DotProduct (dir, prog->globals.server->v_forward);
1037 VectorScale (prog->globals.server->v_forward, dist, end);
1039 VectorNormalize (end);
1040 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1044 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1052 This was a major timewaster in progs, so it was converted to C
1055 void PF_changeyaw (void)
1058 float ideal, current, move, speed;
1060 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1061 if (ent == prog->edicts)
1062 PF_WARNING("changeyaw: can not modify world entity\n");
1063 if (ent->priv.server->free)
1064 PF_WARNING("changeyaw: can not modify free entity\n");
1065 current = ANGLEMOD(ent->fields.server->angles[1]);
1066 ideal = ent->fields.server->ideal_yaw;
1067 speed = ent->fields.server->yaw_speed;
1069 if (current == ideal)
1071 move = ideal - current;
1072 if (ideal > current)
1093 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1101 void PF_changepitch (void)
1104 float ideal, current, move, speed;
1107 ent = PRVM_G_EDICT(OFS_PARM0);
1108 if (ent == prog->edicts)
1109 PF_WARNING("changepitch: can not modify world entity\n");
1110 if (ent->priv.server->free)
1111 PF_WARNING("changepitch: can not modify free entity\n");
1112 current = ANGLEMOD( ent->fields.server->angles[0] );
1113 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1114 ideal = val->_float;
1117 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1120 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1121 speed = val->_float;
1124 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1128 if (current == ideal)
1130 move = ideal - current;
1131 if (ideal > current)
1152 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1156 ===============================================================================
1160 ===============================================================================
1163 #define MSG_BROADCAST 0 // unreliable to all
1164 #define MSG_ONE 1 // reliable to one (msg_entity)
1165 #define MSG_ALL 2 // reliable to all
1166 #define MSG_INIT 3 // write to the init string
1168 sizebuf_t *WriteDest (void)
1174 dest = PRVM_G_FLOAT(OFS_PARM0);
1178 return &sv.datagram;
1181 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1182 entnum = PRVM_NUM_FOR_EDICT(ent);
1183 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1184 Host_Error("WriteDest: tried to write to non-client\n");
1185 return &svs.clients[entnum-1].message;
1188 return &sv.reliable_datagram;
1194 Host_Error("WriteDest: bad destination");
1201 void PF_WriteByte (void)
1203 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1206 void PF_WriteChar (void)
1208 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1211 void PF_WriteShort (void)
1213 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1216 void PF_WriteLong (void)
1218 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1221 void PF_WriteAngle (void)
1223 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1226 void PF_WriteCoord (void)
1228 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1231 void PF_WriteString (void)
1233 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1237 void PF_WriteEntity (void)
1239 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1242 //////////////////////////////////////////////////////////
1244 void PF_makestatic (void)
1249 ent = PRVM_G_EDICT(OFS_PARM0);
1250 if (ent == prog->edicts)
1251 PF_WARNING("makestatic: can not modify world entity\n");
1252 if (ent->priv.server->free)
1253 PF_WARNING("makestatic: can not modify free entity\n");
1256 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1261 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1262 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1263 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1267 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1268 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1269 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1272 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1273 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1274 for (i=0 ; i<3 ; i++)
1276 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1277 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1280 // throw the entity away now
1284 //=============================================================================
1291 void PF_setspawnparms (void)
1297 ent = PRVM_G_EDICT(OFS_PARM0);
1298 i = PRVM_NUM_FOR_EDICT(ent);
1299 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1301 Con_Print("tried to setspawnparms on a non-client\n");
1305 // copy spawn parms out of the client_t
1306 client = svs.clients + i-1;
1307 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1308 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1315 Returns a color vector indicating the lighting at the requested point.
1317 (Internal Operation note: actually measures the light beneath the point, just like
1318 the model lighting on the client)
1323 void PF_getlight (void)
1325 vec3_t ambientcolor, diffusecolor, diffusenormal;
1327 p = PRVM_G_VECTOR(OFS_PARM0);
1328 VectorClear(ambientcolor);
1329 VectorClear(diffusecolor);
1330 VectorClear(diffusenormal);
1331 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1332 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1333 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1336 void PF_registercvar (void)
1338 const char *name, *value;
1339 name = PRVM_G_STRING(OFS_PARM0);
1340 value = PRVM_G_STRING(OFS_PARM1);
1341 PRVM_G_FLOAT(OFS_RETURN) = 0;
1343 // first check to see if it has already been defined
1344 if (Cvar_FindVar (name))
1347 // check for overlap with a command
1348 if (Cmd_Exists (name))
1350 Con_Printf("PF_registercvar: %s is a command\n", name);
1354 Cvar_Get(name, value, 0);
1356 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1363 copies data from one entity to another
1365 copyentity(src, dst)
1368 void PF_copyentity (void)
1370 prvm_edict_t *in, *out;
1371 in = PRVM_G_EDICT(OFS_PARM0);
1372 if (in == prog->edicts)
1373 PF_WARNING("copyentity: can not read world entity\n");
1374 if (in->priv.server->free)
1375 PF_WARNING("copyentity: can not read free entity\n");
1376 out = PRVM_G_EDICT(OFS_PARM1);
1377 if (out == prog->edicts)
1378 PF_WARNING("copyentity: can not modify world entity\n");
1379 if (out->priv.server->free)
1380 PF_WARNING("copyentity: can not modify free entity\n");
1381 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1389 sets the color of a client and broadcasts the update to all connected clients
1391 setcolor(clientent, value)
1394 void PF_setcolor (void)
1400 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1401 i = PRVM_G_FLOAT(OFS_PARM1);
1403 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1405 Con_Print("tried to setcolor a non-client\n");
1409 client = svs.clients + entnum-1;
1412 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1414 client->edict->fields.server->team = (i & 15) + 1;
1417 if (client->old_colors != client->colors)
1419 client->old_colors = client->colors;
1420 // send notification to all clients
1421 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1422 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1423 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1431 effect(origin, modelname, startframe, framecount, framerate)
1434 void PF_effect (void)
1438 s = PRVM_G_STRING(OFS_PARM1);
1440 PF_WARNING("effect: no model specified\n");
1442 i = SV_ModelIndex(s, 1);
1444 PF_WARNING("effect: model not precached\n");
1445 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1448 void PF_te_blood (void)
1450 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1452 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1453 MSG_WriteByte(&sv.datagram, TE_BLOOD);
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_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1460 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1461 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1463 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1466 void PF_te_bloodshower (void)
1468 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1470 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1471 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1473 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1474 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1475 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1477 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1478 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1479 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1481 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1483 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1486 void PF_te_explosionrgb (void)
1488 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1489 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1491 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1493 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1495 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1496 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1497 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1500 void PF_te_particlecube (void)
1502 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1504 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1505 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
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));
1522 // gravity true/false
1523 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1525 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1528 void PF_te_particlerain (void)
1530 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1532 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1533 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1535 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1536 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1537 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1539 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1540 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1541 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1543 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1545 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1547 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1549 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1552 void PF_te_particlesnow (void)
1554 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1556 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1557 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1559 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1560 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1561 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1564 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1565 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1569 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1571 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1573 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1576 void PF_te_spark (void)
1578 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1580 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1581 MSG_WriteByte(&sv.datagram, TE_SPARK);
1583 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1584 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1585 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1587 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1588 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1589 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1591 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1594 void PF_te_gunshotquad (void)
1596 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1597 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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);
1604 void PF_te_spikequad (void)
1606 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1607 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1609 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1610 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1611 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1614 void PF_te_superspikequad (void)
1616 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1617 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1619 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1620 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1621 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1624 void PF_te_explosionquad (void)
1626 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1627 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1630 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1634 void PF_te_smallflash (void)
1636 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1637 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1639 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1640 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1644 void PF_te_customflash (void)
1646 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1648 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1649 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1655 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1657 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1659 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1660 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1661 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1664 void PF_te_gunshot (void)
1666 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1667 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1674 void PF_te_spike (void)
1676 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1677 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1684 void PF_te_superspike (void)
1686 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1687 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1694 void PF_te_explosion (void)
1696 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1697 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1699 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1700 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1704 void PF_te_tarexplosion (void)
1706 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1707 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1714 void PF_te_wizspike (void)
1716 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1717 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1724 void PF_te_knightspike (void)
1726 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1727 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1734 void PF_te_lavasplash (void)
1736 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1737 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1744 void PF_te_teleport (void)
1746 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1754 void PF_te_explosion2 (void)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1763 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1764 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1767 void PF_te_lightning1 (void)
1769 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1770 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1772 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1783 void PF_te_lightning2 (void)
1785 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1786 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1788 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1799 void PF_te_lightning3 (void)
1801 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1802 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1804 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1815 void PF_te_beam (void)
1817 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1818 MSG_WriteByte(&sv.datagram, TE_BEAM);
1820 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1824 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1831 void PF_te_plasmaburn (void)
1833 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1834 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1840 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1843 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1845 bestdist = 1000000000;
1847 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1849 // clip original point to each triangle of the surface and find the
1850 // triangle that is closest
1851 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1852 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1853 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1854 TriangleNormal(v[0], v[1], v[2], facenormal);
1855 VectorNormalize(facenormal);
1856 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1857 VectorMA(p, offsetdist, facenormal, temp);
1858 for (j = 0, k = 2;j < 3;k = j, j++)
1860 VectorSubtract(v[k], v[j], edgenormal);
1861 CrossProduct(edgenormal, facenormal, sidenormal);
1862 VectorNormalize(sidenormal);
1863 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1865 VectorMA(temp, offsetdist, sidenormal, temp);
1867 dist = VectorDistance2(temp, p);
1868 if (bestdist > dist)
1871 VectorCopy(temp, out);
1876 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1880 if (!ed || ed->priv.server->free)
1882 modelindex = ed->fields.server->modelindex;
1883 if (modelindex < 1 || modelindex >= MAX_MODELS)
1885 model = sv.models[modelindex];
1886 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1888 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1892 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1893 void PF_getsurfacenumpoints(void)
1895 msurface_t *surface;
1896 // return 0 if no such surface
1897 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1899 PRVM_G_FLOAT(OFS_RETURN) = 0;
1903 // note: this (incorrectly) assumes it is a simple polygon
1904 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1906 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1907 void PF_getsurfacepoint(void)
1910 msurface_t *surface;
1912 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1913 ed = PRVM_G_EDICT(OFS_PARM0);
1914 if (!ed || ed->priv.server->free)
1916 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1918 // note: this (incorrectly) assumes it is a simple polygon
1919 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1920 if (pointnum < 0 || pointnum >= surface->num_vertices)
1922 // FIXME: implement rotation/scaling
1923 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1925 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1926 void PF_getsurfacenormal(void)
1928 msurface_t *surface;
1930 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1931 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1933 // FIXME: implement rotation/scaling
1934 // note: this (incorrectly) assumes it is a simple polygon
1935 // note: this only returns the first triangle, so it doesn't work very
1936 // well for curved surfaces or arbitrary meshes
1937 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);
1938 VectorNormalize(normal);
1939 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1941 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1942 void PF_getsurfacetexture(void)
1944 msurface_t *surface;
1945 PRVM_G_INT(OFS_RETURN) = 0;
1946 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1948 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1950 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1951 void PF_getsurfacenearpoint(void)
1953 int surfacenum, best, modelindex;
1955 vec_t dist, bestdist;
1958 msurface_t *surface;
1960 PRVM_G_FLOAT(OFS_RETURN) = -1;
1961 ed = PRVM_G_EDICT(OFS_PARM0);
1962 point = PRVM_G_VECTOR(OFS_PARM1);
1964 if (!ed || ed->priv.server->free)
1966 modelindex = ed->fields.server->modelindex;
1967 if (modelindex < 1 || modelindex >= MAX_MODELS)
1969 model = sv.models[modelindex];
1970 if (!model->num_surfaces)
1973 // FIXME: implement rotation/scaling
1974 VectorSubtract(point, ed->fields.server->origin, p);
1976 bestdist = 1000000000;
1977 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1979 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1980 // first see if the nearest point on the surface's box is closer than the previous match
1981 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1982 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1983 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1984 dist = VectorLength2(clipped);
1985 if (dist < bestdist)
1987 // it is, check the nearest point on the actual geometry
1988 clippointtosurface(surface, p, clipped);
1989 VectorSubtract(clipped, p, clipped);
1990 dist += VectorLength2(clipped);
1991 if (dist < bestdist)
1993 // that's closer too, store it as the best match
1999 PRVM_G_FLOAT(OFS_RETURN) = best;
2001 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2002 void PF_getsurfaceclippedpoint(void)
2005 msurface_t *surface;
2007 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2008 ed = PRVM_G_EDICT(OFS_PARM0);
2009 if (!ed || ed->priv.server->free)
2011 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2013 // FIXME: implement rotation/scaling
2014 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2015 clippointtosurface(surface, p, out);
2016 // FIXME: implement rotation/scaling
2017 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2020 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2021 //this function originally written by KrimZon, made shorter by LordHavoc
2022 void PF_clientcommand (void)
2024 client_t *temp_client;
2027 //find client for this entity
2028 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2029 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2031 Con_Print("PF_clientcommand: entity is not a client\n");
2035 temp_client = host_client;
2036 host_client = svs.clients + i;
2037 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2038 host_client = temp_client;
2041 //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)
2042 void PF_setattachment (void)
2044 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2045 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2046 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2051 if (e == prog->edicts)
2052 PF_WARNING("setattachment: can not modify world entity\n");
2053 if (e->priv.server->free)
2054 PF_WARNING("setattachment: can not modify free entity\n");
2056 if (tagentity == NULL)
2057 tagentity = prog->edicts;
2059 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2061 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2063 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2066 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2068 modelindex = (int)tagentity->fields.server->modelindex;
2069 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2071 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2073 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);
2076 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));
2080 /////////////////////////////////////////
2081 // DP_MD3_TAGINFO extension coded by VorteX
2083 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2088 i = e->fields.server->modelindex;
2089 if (i < 1 || i >= MAX_MODELS)
2091 model = sv.models[i];
2093 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2096 // Warnings/errors code:
2097 // 0 - normal (everything all-right)
2100 // 3 - null or non-precached model
2101 // 4 - no tags with requested index
2102 // 5 - runaway loop at attachment chain
2103 extern cvar_t cl_bob;
2104 extern cvar_t cl_bobcycle;
2105 extern cvar_t cl_bobup;
2106 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2109 int modelindex, reqframe, attachloop;
2110 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2111 prvm_edict_t *attachent;
2114 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2116 if (ent == prog->edicts)
2118 if (ent->priv.server->free)
2121 modelindex = (int)ent->fields.server->modelindex;
2122 if (modelindex <= 0 || modelindex > MAX_MODELS)
2125 model = sv.models[modelindex];
2127 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2128 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2130 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2132 // get initial tag matrix
2135 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2140 Matrix4x4_CreateIdentity(&tagmatrix);
2142 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2143 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2147 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2148 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2149 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)
2150 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2152 Matrix4x4_CreateIdentity(&attachmatrix);
2154 // apply transformation by child entity matrix
2155 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2156 if (val->_float == 0)
2158 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);
2159 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2160 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]);
2161 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]);
2162 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]);
2163 Matrix4x4_Copy(&tagmatrix, out);
2165 // finally transformate by matrix of tag on parent entity
2166 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2167 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];
2168 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];
2169 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];
2170 Matrix4x4_Copy(&tagmatrix, out);
2174 if (attachloop > 255) // prevent runaway looping
2177 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2180 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2181 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2182 if (val->_float == 0)
2184 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2185 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);
2186 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2187 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]);
2188 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]);
2189 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]);
2191 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2192 {// RENDER_VIEWMODEL magic
2193 Matrix4x4_Copy(&tagmatrix, out);
2194 ent = PRVM_EDICT_NUM(val->edict);
2196 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2197 if (val->_float == 0)
2200 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);
2201 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2202 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]);
2203 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]);
2204 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]);
2207 // Cl_bob, ported from rendering code
2208 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2211 // LordHavoc: this code is *weird*, but not replacable (I think it
2212 // should be done in QC on the server, but oh well, quake is quake)
2213 // LordHavoc: figured out bobup: the time at which the sin is at 180
2214 // degrees (which allows lengthening or squishing the peak or valley)
2215 cycle = sv.time/cl_bobcycle.value;
2216 cycle -= (int)cycle;
2217 if (cycle < cl_bobup.value)
2218 cycle = sin(M_PI * cycle / cl_bobup.value);
2220 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2221 // bob is proportional to velocity in the xy plane
2222 // (don't count Z, or jumping messes it up)
2223 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;
2224 bob = bob*0.3 + bob*0.7*cycle;
2225 out->m[2][3] += bound(-7, bob, 4);
2232 //float(entity ent, string tagname) gettagindex;
2234 void PF_gettagindex (void)
2236 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2237 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2238 int modelindex, tag_index;
2240 if (ent == prog->edicts)
2241 PF_WARNING("gettagindex: can't affect world entity\n");
2242 if (ent->priv.server->free)
2243 PF_WARNING("gettagindex: can't affect free entity\n");
2245 modelindex = (int)ent->fields.server->modelindex;
2247 if (modelindex <= 0 || modelindex > MAX_MODELS)
2248 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2251 tag_index = SV_GetTagIndex(ent, tag_name);
2253 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2255 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2258 //vector(entity ent, float tagindex) gettaginfo;
2259 void PF_gettaginfo (void)
2261 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2262 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2263 matrix4x4_t tag_matrix;
2266 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2267 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2272 PF_WARNING("gettagindex: can't affect world entity\n");
2275 PF_WARNING("gettagindex: can't affect free entity\n");
2278 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2281 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2284 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2289 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2290 void PF_dropclient (void)
2293 client_t *oldhostclient;
2294 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2295 if (clientnum < 0 || clientnum >= svs.maxclients)
2296 PF_WARNING("dropclient: not a client\n");
2297 if (!svs.clients[clientnum].active)
2298 PF_WARNING("dropclient: that client slot is not connected\n");
2299 oldhostclient = host_client;
2300 host_client = svs.clients + clientnum;
2301 SV_DropClient(false);
2302 host_client = oldhostclient;
2305 //entity() spawnclient (DP_SV_BOTCLIENT)
2306 void PF_spawnclient (void)
2310 prog->xfunction->builtinsprofile += 2;
2312 for (i = 0;i < svs.maxclients;i++)
2314 if (!svs.clients[i].active)
2316 prog->xfunction->builtinsprofile += 100;
2317 SV_ConnectClient (i, NULL);
2318 ed = PRVM_EDICT_NUM(i + 1);
2322 VM_RETURN_EDICT(ed);
2325 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2326 void PF_clienttype (void)
2329 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2330 if (clientnum < 0 || clientnum >= svs.maxclients)
2331 PRVM_G_FLOAT(OFS_RETURN) = 3;
2332 else if (!svs.clients[clientnum].active)
2333 PRVM_G_FLOAT(OFS_RETURN) = 0;
2334 else if (svs.clients[clientnum].netconnection)
2335 PRVM_G_FLOAT(OFS_RETURN) = 1;
2337 PRVM_G_FLOAT(OFS_RETURN) = 2;
2340 prvm_builtin_t vm_sv_builtins[] = {
2342 PF_makevectors, // #1 void(entity e) makevectors
2343 PF_setorigin, // #2 void(entity e, vector o) setorigin
2344 PF_setmodel, // #3 void(entity e, string m) setmodel
2345 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2346 NULL, // #5 void(entity e, vector min, vector max) setabssize
2347 VM_break, // #6 void() break
2348 VM_random, // #7 float() random
2349 PF_sound, // #8 void(entity e, float chan, string samp) sound
2350 VM_normalize, // #9 vector(vector v) normalize
2351 VM_error, // #10 void(string e) error
2352 VM_objerror, // #11 void(string e) objerror
2353 VM_vlen, // #12 float(vector v) vlen
2354 VM_vectoyaw, // #13 float(vector v) vectoyaw
2355 VM_spawn, // #14 entity() spawn
2356 VM_remove, // #15 void(entity e) remove
2357 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2358 PF_checkclient, // #17 entity() clientlist
2359 VM_find, // #18 entity(entity start, .string fld, string match) find
2360 PF_precache_sound, // #19 void(string s) precache_sound
2361 PF_precache_model, // #20 void(string s) precache_model
2362 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2363 PF_findradius, // #22 entity(vector org, float rad) findradius
2364 VM_bprint, // #23 void(string s) bprint
2365 PF_sprint, // #24 void(entity client, string s) sprint
2366 VM_dprint, // #25 void(string s) dprint
2367 VM_ftos, // #26 void(string s) ftos
2368 VM_vtos, // #27 void(string s) vtos
2369 VM_coredump, // #28 void() coredump
2370 VM_traceon, // #29 void() traceon
2371 VM_traceoff, // #30 void() traceoff
2372 VM_eprint, // #31 void(entity e) eprint
2373 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2375 PF_droptofloor, // #34 float() droptofloor
2376 PF_lightstyle, // #35 void(float style, string value) lightstyle
2377 VM_rint, // #36 float(float v) rint
2378 VM_floor, // #37 float(float v) floor
2379 VM_ceil, // #38 float(float v) ceil
2381 PF_checkbottom, // #40 float(entity e) checkbottom
2382 PF_pointcontents, // #41 float(vector v) pointcontents
2384 VM_fabs, // #43 float(float f) fabs
2385 PF_aim, // #44 vector(entity e, float speed) aim
2386 VM_cvar, // #45 float(string s) cvar
2387 VM_localcmd, // #46 void(string s) localcmd
2388 VM_nextent, // #47 entity(entity e) nextent
2389 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2390 PF_changeyaw, // #49 void() ChangeYaw
2392 VM_vectoangles, // #51 vector(vector v) vectoangles
2393 PF_WriteByte, // #52 void(float to, float f) WriteByte
2394 PF_WriteChar, // #53 void(float to, float f) WriteChar
2395 PF_WriteShort, // #54 void(float to, float f) WriteShort
2396 PF_WriteLong, // #55 void(float to, float f) WriteLong
2397 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2398 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2399 PF_WriteString, // #58 void(float to, string s) WriteString
2400 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2401 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2402 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2403 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2404 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2405 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2406 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2408 SV_MoveToGoal, // #67 void(float step) movetogoal
2409 PF_precache_file, // #68 string(string s) precache_file
2410 PF_makestatic, // #69 void(entity e) makestatic
2411 VM_changelevel, // #70 void(string s) changelevel
2413 VM_cvar_set, // #72 void(string var, string val) cvar_set
2414 PF_centerprint, // #73 void(entity client, strings) centerprint
2415 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2416 PF_precache_model, // #75 string(string s) precache_model2
2417 PF_precache_sound, // #76 string(string s) precache_sound2
2418 PF_precache_file, // #77 string(string s) precache_file2
2419 PF_setspawnparms, // #78 void(entity e) setspawnparms
2422 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2431 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2432 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2433 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2434 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2435 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2436 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2437 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2438 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2439 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2440 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2451 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2452 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2453 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2454 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2455 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2456 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2457 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2458 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2459 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2460 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2461 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2462 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2463 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2464 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2465 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2466 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2467 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2468 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2469 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2470 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2471 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2472 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2473 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2474 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2475 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2476 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2477 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2478 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2479 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2480 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2481 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2482 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2483 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2484 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2485 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2486 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2487 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2488 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2489 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2490 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2491 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2492 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2493 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2494 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2495 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2496 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2497 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2498 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2499 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2500 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2501 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2502 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2503 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2504 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2505 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2506 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2507 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2508 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2509 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2510 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2511 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2512 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2513 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2514 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2515 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2516 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2517 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2518 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2519 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2524 e10, e10, e10, e10 // #460-499 (LordHavoc)
2527 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2529 void VM_SV_Cmd_Init(void)
2534 void VM_SV_Cmd_Reset(void)