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 // LordHavoc: search for flags in float fields
743 void PF_findflags (void)
750 e = PRVM_G_EDICTNUM(OFS_PARM0);
751 f = PRVM_G_INT(OFS_PARM1);
752 s = (int)PRVM_G_FLOAT(OFS_PARM2);
754 for (e++ ; e < prog->num_edicts ; e++)
756 prog->xfunction->builtinsprofile++;
757 ed = PRVM_EDICT_NUM(e);
758 if (ed->priv.server->free)
760 if ((int)PRVM_E_FLOAT(ed,f) & s)
767 VM_RETURN_EDICT(prog->edicts);
770 // LordHavoc: chained search for flags in float fields
771 void PF_findchainflags (void)
776 prvm_edict_t *ent, *chain;
778 chain = (prvm_edict_t *)prog->edicts;
780 f = PRVM_G_INT(OFS_PARM0);
781 s = (int)PRVM_G_FLOAT(OFS_PARM1);
783 ent = PRVM_NEXT_EDICT(prog->edicts);
784 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
786 prog->xfunction->builtinsprofile++;
787 if (ent->priv.server->free)
789 if (!((int)PRVM_E_FLOAT(ent,f) & s))
792 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
796 VM_RETURN_EDICT(chain);
799 void PF_precache_file (void)
800 { // precache_file is only used to copy files with qcc, it does nothing
801 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
805 void PF_precache_sound (void)
807 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
808 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
811 void PF_precache_model (void)
813 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
814 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
821 float(float yaw, float dist) walkmove
824 void PF_walkmove (void)
832 // assume failure if it returns early
833 PRVM_G_FLOAT(OFS_RETURN) = 0;
835 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
836 if (ent == prog->edicts)
837 PF_WARNING("walkmove: can not modify world entity\n");
838 if (ent->priv.server->free)
839 PF_WARNING("walkmove: can not modify free entity\n");
840 yaw = PRVM_G_FLOAT(OFS_PARM0);
841 dist = PRVM_G_FLOAT(OFS_PARM1);
843 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
846 yaw = yaw*M_PI*2 / 360;
848 move[0] = cos(yaw)*dist;
849 move[1] = sin(yaw)*dist;
852 // save program state, because SV_movestep may call other progs
853 oldf = prog->xfunction;
854 oldself = prog->globals.server->self;
856 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
859 // restore program state
860 prog->xfunction = oldf;
861 prog->globals.server->self = oldself;
871 void PF_droptofloor (void)
877 // assume failure if it returns early
878 PRVM_G_FLOAT(OFS_RETURN) = 0;
880 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
881 if (ent == prog->edicts)
882 PF_WARNING("droptofloor: can not modify world entity\n");
883 if (ent->priv.server->free)
884 PF_WARNING("droptofloor: can not modify free entity\n");
886 VectorCopy (ent->fields.server->origin, end);
889 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
891 if (trace.fraction != 1)
893 VectorCopy (trace.endpos, ent->fields.server->origin);
894 SV_LinkEdict (ent, false);
895 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
896 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
897 PRVM_G_FLOAT(OFS_RETURN) = 1;
898 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
899 ent->priv.server->suspendedinairflag = true;
907 void(float style, string value) lightstyle
910 void PF_lightstyle (void)
917 style = PRVM_G_FLOAT(OFS_PARM0);
918 val = PRVM_G_STRING(OFS_PARM1);
920 // change the string in sv
921 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
923 // send message to all clients on this server
924 if (sv.state != ss_active)
927 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
931 MSG_WriteChar (&client->message, svc_lightstyle);
932 MSG_WriteChar (&client->message,style);
933 MSG_WriteString (&client->message, val);
943 void PF_checkbottom (void)
945 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
953 void PF_pointcontents (void)
955 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
962 Pick a vector for the player to shoot along
963 vector aim(entity, missilespeed)
968 prvm_edict_t *ent, *check, *bestent;
969 vec3_t start, dir, end, bestdir;
972 float dist, bestdist;
975 // assume failure if it returns early
976 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
977 // if sv_aim is so high it can't possibly accept anything, skip out early
978 if (sv_aim.value >= 1)
981 ent = PRVM_G_EDICT(OFS_PARM0);
982 if (ent == prog->edicts)
983 PF_WARNING("aim: can not use world entity\n");
984 if (ent->priv.server->free)
985 PF_WARNING("aim: can not use free entity\n");
986 speed = PRVM_G_FLOAT(OFS_PARM1);
988 VectorCopy (ent->fields.server->origin, start);
991 // try sending a trace straight
992 VectorCopy (prog->globals.server->v_forward, dir);
993 VectorMA (start, 2048, dir, end);
994 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
995 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
996 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
998 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1003 // try all possible entities
1004 VectorCopy (dir, bestdir);
1005 bestdist = sv_aim.value;
1008 check = PRVM_NEXT_EDICT(prog->edicts);
1009 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1011 prog->xfunction->builtinsprofile++;
1012 if (check->fields.server->takedamage != DAMAGE_AIM)
1016 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1017 continue; // don't aim at teammate
1018 for (j=0 ; j<3 ; j++)
1019 end[j] = check->fields.server->origin[j]
1020 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1021 VectorSubtract (end, start, dir);
1022 VectorNormalize (dir);
1023 dist = DotProduct (dir, prog->globals.server->v_forward);
1024 if (dist < bestdist)
1025 continue; // to far to turn
1026 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1027 if (tr.ent == check)
1028 { // can shoot at this one
1036 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1037 dist = DotProduct (dir, prog->globals.server->v_forward);
1038 VectorScale (prog->globals.server->v_forward, dist, end);
1040 VectorNormalize (end);
1041 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1045 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1053 This was a major timewaster in progs, so it was converted to C
1056 void PF_changeyaw (void)
1059 float ideal, current, move, speed;
1061 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1062 if (ent == prog->edicts)
1063 PF_WARNING("changeyaw: can not modify world entity\n");
1064 if (ent->priv.server->free)
1065 PF_WARNING("changeyaw: can not modify free entity\n");
1066 current = ANGLEMOD(ent->fields.server->angles[1]);
1067 ideal = ent->fields.server->ideal_yaw;
1068 speed = ent->fields.server->yaw_speed;
1070 if (current == ideal)
1072 move = ideal - current;
1073 if (ideal > current)
1094 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1102 void PF_changepitch (void)
1105 float ideal, current, move, speed;
1108 ent = PRVM_G_EDICT(OFS_PARM0);
1109 if (ent == prog->edicts)
1110 PF_WARNING("changepitch: can not modify world entity\n");
1111 if (ent->priv.server->free)
1112 PF_WARNING("changepitch: can not modify free entity\n");
1113 current = ANGLEMOD( ent->fields.server->angles[0] );
1114 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1115 ideal = val->_float;
1118 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1121 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1122 speed = val->_float;
1125 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1129 if (current == ideal)
1131 move = ideal - current;
1132 if (ideal > current)
1153 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1157 ===============================================================================
1161 ===============================================================================
1164 #define MSG_BROADCAST 0 // unreliable to all
1165 #define MSG_ONE 1 // reliable to one (msg_entity)
1166 #define MSG_ALL 2 // reliable to all
1167 #define MSG_INIT 3 // write to the init string
1169 sizebuf_t *WriteDest (void)
1175 dest = PRVM_G_FLOAT(OFS_PARM0);
1179 return &sv.datagram;
1182 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1183 entnum = PRVM_NUM_FOR_EDICT(ent);
1184 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1185 Host_Error("WriteDest: tried to write to non-client\n");
1186 return &svs.clients[entnum-1].message;
1189 return &sv.reliable_datagram;
1195 Host_Error("WriteDest: bad destination");
1202 void PF_WriteByte (void)
1204 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1207 void PF_WriteChar (void)
1209 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1212 void PF_WriteShort (void)
1214 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1217 void PF_WriteLong (void)
1219 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1222 void PF_WriteAngle (void)
1224 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1227 void PF_WriteCoord (void)
1229 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1232 void PF_WriteString (void)
1234 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1238 void PF_WriteEntity (void)
1240 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1243 //////////////////////////////////////////////////////////
1245 void PF_makestatic (void)
1250 ent = PRVM_G_EDICT(OFS_PARM0);
1251 if (ent == prog->edicts)
1252 PF_WARNING("makestatic: can not modify world entity\n");
1253 if (ent->priv.server->free)
1254 PF_WARNING("makestatic: can not modify free entity\n");
1257 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1262 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1263 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1264 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1268 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1269 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1270 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1273 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1274 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1275 for (i=0 ; i<3 ; i++)
1277 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1278 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1281 // throw the entity away now
1285 //=============================================================================
1292 void PF_setspawnparms (void)
1298 ent = PRVM_G_EDICT(OFS_PARM0);
1299 i = PRVM_NUM_FOR_EDICT(ent);
1300 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1302 Con_Print("tried to setspawnparms on a non-client\n");
1306 // copy spawn parms out of the client_t
1307 client = svs.clients + i-1;
1308 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1309 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1316 Returns a color vector indicating the lighting at the requested point.
1318 (Internal Operation note: actually measures the light beneath the point, just like
1319 the model lighting on the client)
1324 void PF_getlight (void)
1326 vec3_t ambientcolor, diffusecolor, diffusenormal;
1328 p = PRVM_G_VECTOR(OFS_PARM0);
1329 VectorClear(ambientcolor);
1330 VectorClear(diffusecolor);
1331 VectorClear(diffusenormal);
1332 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1333 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1334 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1337 void PF_registercvar (void)
1339 const char *name, *value;
1340 name = PRVM_G_STRING(OFS_PARM0);
1341 value = PRVM_G_STRING(OFS_PARM1);
1342 PRVM_G_FLOAT(OFS_RETURN) = 0;
1344 // first check to see if it has already been defined
1345 if (Cvar_FindVar (name))
1348 // check for overlap with a command
1349 if (Cmd_Exists (name))
1351 Con_Printf("PF_registercvar: %s is a command\n", name);
1355 Cvar_Get(name, value, 0);
1357 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1364 copies data from one entity to another
1366 copyentity(src, dst)
1369 void PF_copyentity (void)
1371 prvm_edict_t *in, *out;
1372 in = PRVM_G_EDICT(OFS_PARM0);
1373 if (in == prog->edicts)
1374 PF_WARNING("copyentity: can not read world entity\n");
1375 if (in->priv.server->free)
1376 PF_WARNING("copyentity: can not read free entity\n");
1377 out = PRVM_G_EDICT(OFS_PARM1);
1378 if (out == prog->edicts)
1379 PF_WARNING("copyentity: can not modify world entity\n");
1380 if (out->priv.server->free)
1381 PF_WARNING("copyentity: can not modify free entity\n");
1382 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1390 sets the color of a client and broadcasts the update to all connected clients
1392 setcolor(clientent, value)
1395 void PF_setcolor (void)
1401 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1402 i = PRVM_G_FLOAT(OFS_PARM1);
1404 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1406 Con_Print("tried to setcolor a non-client\n");
1410 client = svs.clients + entnum-1;
1413 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1415 client->edict->fields.server->team = (i & 15) + 1;
1418 if (client->old_colors != client->colors)
1420 client->old_colors = client->colors;
1421 // send notification to all clients
1422 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1423 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1424 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1432 effect(origin, modelname, startframe, framecount, framerate)
1435 void PF_effect (void)
1439 s = PRVM_G_STRING(OFS_PARM1);
1441 PF_WARNING("effect: no model specified\n");
1443 i = SV_ModelIndex(s, 1);
1445 PF_WARNING("effect: model not precached\n");
1446 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1449 void PF_te_blood (void)
1451 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1453 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1454 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1456 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1457 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1458 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1460 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1461 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1462 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1464 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1467 void PF_te_bloodshower (void)
1469 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1471 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1472 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1474 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1475 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1476 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1478 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1479 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1480 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1482 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1484 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1487 void PF_te_explosionrgb (void)
1489 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1490 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1493 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1494 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1496 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1497 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1498 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1501 void PF_te_particlecube (void)
1503 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1505 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1506 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1508 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1509 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1510 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1513 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1514 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1516 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1517 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1518 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1520 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1522 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1523 // gravity true/false
1524 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1526 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1529 void PF_te_particlerain (void)
1531 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1533 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1534 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1536 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1537 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1538 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1540 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1541 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1542 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1545 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1548 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1550 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1553 void PF_te_particlesnow (void)
1555 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1557 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1558 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1560 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1561 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1564 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1565 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1569 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1570 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1572 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1574 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1577 void PF_te_spark (void)
1579 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1581 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1582 MSG_WriteByte(&sv.datagram, TE_SPARK);
1584 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1585 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1586 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1588 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1589 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1590 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1592 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1595 void PF_te_gunshotquad (void)
1597 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1598 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1600 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1601 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1602 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1605 void PF_te_spikequad (void)
1607 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1608 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1610 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1611 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1612 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1615 void PF_te_superspikequad (void)
1617 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1618 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1620 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1621 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1625 void PF_te_explosionquad (void)
1627 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1628 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1630 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1635 void PF_te_smallflash (void)
1637 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1638 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1640 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1645 void PF_te_customflash (void)
1647 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1649 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1650 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1652 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1656 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1658 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1660 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1661 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1662 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1665 void PF_te_gunshot (void)
1667 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1668 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1675 void PF_te_spike (void)
1677 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1678 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1685 void PF_te_superspike (void)
1687 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1688 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1695 void PF_te_explosion (void)
1697 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1698 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1700 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1705 void PF_te_tarexplosion (void)
1707 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1708 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1715 void PF_te_wizspike (void)
1717 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1718 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1725 void PF_te_knightspike (void)
1727 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1728 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1735 void PF_te_lavasplash (void)
1737 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1738 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1745 void PF_te_teleport (void)
1747 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1748 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1755 void PF_te_explosion2 (void)
1757 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1758 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1764 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1765 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1768 void PF_te_lightning1 (void)
1770 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1771 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1773 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1784 void PF_te_lightning2 (void)
1786 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1789 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1800 void PF_te_lightning3 (void)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1805 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1816 void PF_te_beam (void)
1818 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1819 MSG_WriteByte(&sv.datagram, TE_BEAM);
1821 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1824 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1832 void PF_te_plasmaburn (void)
1834 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1835 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1841 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1844 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1846 bestdist = 1000000000;
1848 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1850 // clip original point to each triangle of the surface and find the
1851 // triangle that is closest
1852 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1853 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1854 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1855 TriangleNormal(v[0], v[1], v[2], facenormal);
1856 VectorNormalize(facenormal);
1857 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1858 VectorMA(p, offsetdist, facenormal, temp);
1859 for (j = 0, k = 2;j < 3;k = j, j++)
1861 VectorSubtract(v[k], v[j], edgenormal);
1862 CrossProduct(edgenormal, facenormal, sidenormal);
1863 VectorNormalize(sidenormal);
1864 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1866 VectorMA(temp, offsetdist, sidenormal, temp);
1868 dist = VectorDistance2(temp, p);
1869 if (bestdist > dist)
1872 VectorCopy(temp, out);
1877 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1881 if (!ed || ed->priv.server->free)
1883 modelindex = ed->fields.server->modelindex;
1884 if (modelindex < 1 || modelindex >= MAX_MODELS)
1886 model = sv.models[modelindex];
1887 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1889 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1893 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1894 void PF_getsurfacenumpoints(void)
1896 msurface_t *surface;
1897 // return 0 if no such surface
1898 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1900 PRVM_G_FLOAT(OFS_RETURN) = 0;
1904 // note: this (incorrectly) assumes it is a simple polygon
1905 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1907 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1908 void PF_getsurfacepoint(void)
1911 msurface_t *surface;
1913 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1914 ed = PRVM_G_EDICT(OFS_PARM0);
1915 if (!ed || ed->priv.server->free)
1917 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1919 // note: this (incorrectly) assumes it is a simple polygon
1920 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1921 if (pointnum < 0 || pointnum >= surface->num_vertices)
1923 // FIXME: implement rotation/scaling
1924 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1926 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1927 void PF_getsurfacenormal(void)
1929 msurface_t *surface;
1931 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1932 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1934 // FIXME: implement rotation/scaling
1935 // note: this (incorrectly) assumes it is a simple polygon
1936 // note: this only returns the first triangle, so it doesn't work very
1937 // well for curved surfaces or arbitrary meshes
1938 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);
1939 VectorNormalize(normal);
1940 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1942 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1943 void PF_getsurfacetexture(void)
1945 msurface_t *surface;
1946 PRVM_G_INT(OFS_RETURN) = 0;
1947 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1949 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1951 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1952 void PF_getsurfacenearpoint(void)
1954 int surfacenum, best, modelindex;
1956 vec_t dist, bestdist;
1959 msurface_t *surface;
1961 PRVM_G_FLOAT(OFS_RETURN) = -1;
1962 ed = PRVM_G_EDICT(OFS_PARM0);
1963 point = PRVM_G_VECTOR(OFS_PARM1);
1965 if (!ed || ed->priv.server->free)
1967 modelindex = ed->fields.server->modelindex;
1968 if (modelindex < 1 || modelindex >= MAX_MODELS)
1970 model = sv.models[modelindex];
1971 if (!model->num_surfaces)
1974 // FIXME: implement rotation/scaling
1975 VectorSubtract(point, ed->fields.server->origin, p);
1977 bestdist = 1000000000;
1978 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1980 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1981 // first see if the nearest point on the surface's box is closer than the previous match
1982 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1983 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1984 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1985 dist = VectorLength2(clipped);
1986 if (dist < bestdist)
1988 // it is, check the nearest point on the actual geometry
1989 clippointtosurface(surface, p, clipped);
1990 VectorSubtract(clipped, p, clipped);
1991 dist += VectorLength2(clipped);
1992 if (dist < bestdist)
1994 // that's closer too, store it as the best match
2000 PRVM_G_FLOAT(OFS_RETURN) = best;
2002 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2003 void PF_getsurfaceclippedpoint(void)
2006 msurface_t *surface;
2008 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2009 ed = PRVM_G_EDICT(OFS_PARM0);
2010 if (!ed || ed->priv.server->free)
2012 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2014 // FIXME: implement rotation/scaling
2015 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2016 clippointtosurface(surface, p, out);
2017 // FIXME: implement rotation/scaling
2018 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2021 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2022 //this function originally written by KrimZon, made shorter by LordHavoc
2023 void PF_clientcommand (void)
2025 client_t *temp_client;
2028 //find client for this entity
2029 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2030 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2032 Con_Print("PF_clientcommand: entity is not a client\n");
2036 temp_client = host_client;
2037 host_client = svs.clients + i;
2038 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2039 host_client = temp_client;
2042 //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)
2043 void PF_setattachment (void)
2045 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2046 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2047 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2052 if (e == prog->edicts)
2053 PF_WARNING("setattachment: can not modify world entity\n");
2054 if (e->priv.server->free)
2055 PF_WARNING("setattachment: can not modify free entity\n");
2057 if (tagentity == NULL)
2058 tagentity = prog->edicts;
2060 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2062 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2064 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2067 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2069 modelindex = (int)tagentity->fields.server->modelindex;
2070 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2072 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2074 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);
2077 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));
2081 /////////////////////////////////////////
2082 // DP_MD3_TAGINFO extension coded by VorteX
2084 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2089 i = e->fields.server->modelindex;
2090 if (i < 1 || i >= MAX_MODELS)
2092 model = sv.models[i];
2094 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2097 // Warnings/errors code:
2098 // 0 - normal (everything all-right)
2101 // 3 - null or non-precached model
2102 // 4 - no tags with requested index
2103 // 5 - runaway loop at attachment chain
2104 extern cvar_t cl_bob;
2105 extern cvar_t cl_bobcycle;
2106 extern cvar_t cl_bobup;
2107 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2110 int modelindex, reqframe, attachloop;
2111 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2112 prvm_edict_t *attachent;
2115 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2117 if (ent == prog->edicts)
2119 if (ent->priv.server->free)
2122 modelindex = (int)ent->fields.server->modelindex;
2123 if (modelindex <= 0 || modelindex > MAX_MODELS)
2126 model = sv.models[modelindex];
2128 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2129 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2131 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2133 // get initial tag matrix
2136 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2141 Matrix4x4_CreateIdentity(&tagmatrix);
2143 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2144 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2148 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2149 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2150 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)
2151 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2153 Matrix4x4_CreateIdentity(&attachmatrix);
2155 // apply transformation by child entity matrix
2156 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2157 if (val->_float == 0)
2159 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);
2160 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2161 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]);
2162 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]);
2163 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]);
2164 Matrix4x4_Copy(&tagmatrix, out);
2166 // finally transformate by matrix of tag on parent entity
2167 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2168 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];
2169 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];
2170 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];
2171 Matrix4x4_Copy(&tagmatrix, out);
2175 if (attachloop > 255) // prevent runaway looping
2178 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2181 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2182 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2183 if (val->_float == 0)
2185 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2186 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);
2187 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2188 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]);
2189 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]);
2190 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]);
2192 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2193 {// RENDER_VIEWMODEL magic
2194 Matrix4x4_Copy(&tagmatrix, out);
2195 ent = PRVM_EDICT_NUM(val->edict);
2197 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2198 if (val->_float == 0)
2201 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);
2202 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2203 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]);
2204 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]);
2205 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]);
2208 // Cl_bob, ported from rendering code
2209 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2212 // LordHavoc: this code is *weird*, but not replacable (I think it
2213 // should be done in QC on the server, but oh well, quake is quake)
2214 // LordHavoc: figured out bobup: the time at which the sin is at 180
2215 // degrees (which allows lengthening or squishing the peak or valley)
2216 cycle = sv.time/cl_bobcycle.value;
2217 cycle -= (int)cycle;
2218 if (cycle < cl_bobup.value)
2219 cycle = sin(M_PI * cycle / cl_bobup.value);
2221 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2222 // bob is proportional to velocity in the xy plane
2223 // (don't count Z, or jumping messes it up)
2224 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;
2225 bob = bob*0.3 + bob*0.7*cycle;
2226 out->m[2][3] += bound(-7, bob, 4);
2233 //float(entity ent, string tagname) gettagindex;
2235 void PF_gettagindex (void)
2237 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2238 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2239 int modelindex, tag_index;
2241 if (ent == prog->edicts)
2242 PF_WARNING("gettagindex: can't affect world entity\n");
2243 if (ent->priv.server->free)
2244 PF_WARNING("gettagindex: can't affect free entity\n");
2246 modelindex = (int)ent->fields.server->modelindex;
2248 if (modelindex <= 0 || modelindex > MAX_MODELS)
2249 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2252 tag_index = SV_GetTagIndex(ent, tag_name);
2254 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2256 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2259 //vector(entity ent, float tagindex) gettaginfo;
2260 void PF_gettaginfo (void)
2262 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2263 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2264 matrix4x4_t tag_matrix;
2267 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2268 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2273 PF_WARNING("gettagindex: can't affect world entity\n");
2276 PF_WARNING("gettagindex: can't affect free entity\n");
2279 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2282 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2285 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2290 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2291 void PF_dropclient (void)
2294 client_t *oldhostclient;
2295 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2296 if (clientnum < 0 || clientnum >= svs.maxclients)
2297 PF_WARNING("dropclient: not a client\n");
2298 if (!svs.clients[clientnum].active)
2299 PF_WARNING("dropclient: that client slot is not connected\n");
2300 oldhostclient = host_client;
2301 host_client = svs.clients + clientnum;
2302 SV_DropClient(false);
2303 host_client = oldhostclient;
2306 //entity() spawnclient (DP_SV_BOTCLIENT)
2307 void PF_spawnclient (void)
2311 prog->xfunction->builtinsprofile += 2;
2313 for (i = 0;i < svs.maxclients;i++)
2315 if (!svs.clients[i].active)
2317 prog->xfunction->builtinsprofile += 100;
2318 SV_ConnectClient (i, NULL);
2319 ed = PRVM_EDICT_NUM(i + 1);
2323 VM_RETURN_EDICT(ed);
2326 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2327 void PF_clienttype (void)
2330 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2331 if (clientnum < 0 || clientnum >= svs.maxclients)
2332 PRVM_G_FLOAT(OFS_RETURN) = 3;
2333 else if (!svs.clients[clientnum].active)
2334 PRVM_G_FLOAT(OFS_RETURN) = 0;
2335 else if (svs.clients[clientnum].netconnection)
2336 PRVM_G_FLOAT(OFS_RETURN) = 1;
2338 PRVM_G_FLOAT(OFS_RETURN) = 2;
2341 prvm_builtin_t vm_sv_builtins[] = {
2343 PF_makevectors, // #1 void(entity e) makevectors
2344 PF_setorigin, // #2 void(entity e, vector o) setorigin
2345 PF_setmodel, // #3 void(entity e, string m) setmodel
2346 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2347 NULL, // #5 void(entity e, vector min, vector max) setabssize
2348 VM_break, // #6 void() break
2349 VM_random, // #7 float() random
2350 PF_sound, // #8 void(entity e, float chan, string samp) sound
2351 VM_normalize, // #9 vector(vector v) normalize
2352 VM_error, // #10 void(string e) error
2353 VM_objerror, // #11 void(string e) objerror
2354 VM_vlen, // #12 float(vector v) vlen
2355 VM_vectoyaw, // #13 float(vector v) vectoyaw
2356 VM_spawn, // #14 entity() spawn
2357 VM_remove, // #15 void(entity e) remove
2358 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2359 PF_checkclient, // #17 entity() clientlist
2360 VM_find, // #18 entity(entity start, .string fld, string match) find
2361 PF_precache_sound, // #19 void(string s) precache_sound
2362 PF_precache_model, // #20 void(string s) precache_model
2363 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2364 PF_findradius, // #22 entity(vector org, float rad) findradius
2365 VM_bprint, // #23 void(string s) bprint
2366 PF_sprint, // #24 void(entity client, string s) sprint
2367 VM_dprint, // #25 void(string s) dprint
2368 VM_ftos, // #26 void(string s) ftos
2369 VM_vtos, // #27 void(string s) vtos
2370 VM_coredump, // #28 void() coredump
2371 VM_traceon, // #29 void() traceon
2372 VM_traceoff, // #30 void() traceoff
2373 VM_eprint, // #31 void(entity e) eprint
2374 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2376 PF_droptofloor, // #34 float() droptofloor
2377 PF_lightstyle, // #35 void(float style, string value) lightstyle
2378 VM_rint, // #36 float(float v) rint
2379 VM_floor, // #37 float(float v) floor
2380 VM_ceil, // #38 float(float v) ceil
2382 PF_checkbottom, // #40 float(entity e) checkbottom
2383 PF_pointcontents, // #41 float(vector v) pointcontents
2385 VM_fabs, // #43 float(float f) fabs
2386 PF_aim, // #44 vector(entity e, float speed) aim
2387 VM_cvar, // #45 float(string s) cvar
2388 VM_localcmd, // #46 void(string s) localcmd
2389 VM_nextent, // #47 entity(entity e) nextent
2390 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2391 PF_changeyaw, // #49 void() ChangeYaw
2393 VM_vectoangles, // #51 vector(vector v) vectoangles
2394 PF_WriteByte, // #52 void(float to, float f) WriteByte
2395 PF_WriteChar, // #53 void(float to, float f) WriteChar
2396 PF_WriteShort, // #54 void(float to, float f) WriteShort
2397 PF_WriteLong, // #55 void(float to, float f) WriteLong
2398 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2399 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2400 PF_WriteString, // #58 void(float to, string s) WriteString
2401 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2402 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2403 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2404 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2405 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2406 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2407 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2409 SV_MoveToGoal, // #67 void(float step) movetogoal
2410 PF_precache_file, // #68 string(string s) precache_file
2411 PF_makestatic, // #69 void(entity e) makestatic
2412 VM_changelevel, // #70 void(string s) changelevel
2414 VM_cvar_set, // #72 void(string var, string val) cvar_set
2415 PF_centerprint, // #73 void(entity client, strings) centerprint
2416 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2417 PF_precache_model, // #75 string(string s) precache_model2
2418 PF_precache_sound, // #76 string(string s) precache_sound2
2419 PF_precache_file, // #77 string(string s) precache_file2
2420 PF_setspawnparms, // #78 void(entity e) setspawnparms
2423 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2432 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2433 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2434 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2435 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2436 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2437 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2438 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2439 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2440 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2441 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2452 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2453 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2454 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2455 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2456 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2457 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2458 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2459 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2460 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2461 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2462 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2463 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2464 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2465 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2466 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2467 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2468 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2469 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2470 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2471 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2472 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2473 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2474 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2475 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2476 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2477 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2478 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2479 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2480 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2481 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2482 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2483 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2484 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2485 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2486 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2487 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2488 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2489 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2490 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2491 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2492 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2493 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2494 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2495 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2496 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2497 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2498 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2499 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2500 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2501 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2502 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2503 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2504 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2505 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2506 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2507 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2508 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2509 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2510 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2511 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2512 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2513 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2514 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2515 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2516 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2517 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2518 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2519 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2520 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2525 e10, e10, e10, e10 // #460-499 (LordHavoc)
2528 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2530 void VM_SV_Cmd_Init(void)
2535 void VM_SV_Cmd_Reset(void)