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)
1186 Con_Printf ("WriteDest: tried to write to non-client\n");
1187 return &sv.reliable_datagram;
1190 return &svs.clients[entnum-1].message;
1193 Con_Printf ("WriteDest: bad destination");
1195 return &sv.reliable_datagram;
1204 void PF_WriteByte (void)
1206 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1209 void PF_WriteChar (void)
1211 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1214 void PF_WriteShort (void)
1216 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1219 void PF_WriteLong (void)
1221 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1224 void PF_WriteAngle (void)
1226 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1229 void PF_WriteCoord (void)
1231 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1234 void PF_WriteString (void)
1236 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1240 void PF_WriteEntity (void)
1242 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1245 //////////////////////////////////////////////////////////
1247 void PF_makestatic (void)
1252 ent = PRVM_G_EDICT(OFS_PARM0);
1253 if (ent == prog->edicts)
1254 PF_WARNING("makestatic: can not modify world entity\n");
1255 if (ent->priv.server->free)
1256 PF_WARNING("makestatic: can not modify free entity\n");
1259 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1264 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1265 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1266 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1270 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1271 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1272 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1275 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1276 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1277 for (i=0 ; i<3 ; i++)
1279 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1280 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1283 // throw the entity away now
1287 //=============================================================================
1294 void PF_setspawnparms (void)
1300 ent = PRVM_G_EDICT(OFS_PARM0);
1301 i = PRVM_NUM_FOR_EDICT(ent);
1302 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1304 Con_Print("tried to setspawnparms on a non-client\n");
1308 // copy spawn parms out of the client_t
1309 client = svs.clients + i-1;
1310 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1311 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1318 Returns a color vector indicating the lighting at the requested point.
1320 (Internal Operation note: actually measures the light beneath the point, just like
1321 the model lighting on the client)
1326 void PF_getlight (void)
1328 vec3_t ambientcolor, diffusecolor, diffusenormal;
1330 p = PRVM_G_VECTOR(OFS_PARM0);
1331 VectorClear(ambientcolor);
1332 VectorClear(diffusecolor);
1333 VectorClear(diffusenormal);
1334 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1335 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1336 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1339 void PF_registercvar (void)
1341 const char *name, *value;
1342 name = PRVM_G_STRING(OFS_PARM0);
1343 value = PRVM_G_STRING(OFS_PARM1);
1344 PRVM_G_FLOAT(OFS_RETURN) = 0;
1346 // first check to see if it has already been defined
1347 if (Cvar_FindVar (name))
1350 // check for overlap with a command
1351 if (Cmd_Exists (name))
1353 Con_Printf("PF_registercvar: %s is a command\n", name);
1357 Cvar_Get(name, value, 0);
1359 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1366 copies data from one entity to another
1368 copyentity(src, dst)
1371 void PF_copyentity (void)
1373 prvm_edict_t *in, *out;
1374 in = PRVM_G_EDICT(OFS_PARM0);
1375 if (in == prog->edicts)
1376 PF_WARNING("copyentity: can not read world entity\n");
1377 if (in->priv.server->free)
1378 PF_WARNING("copyentity: can not read free entity\n");
1379 out = PRVM_G_EDICT(OFS_PARM1);
1380 if (out == prog->edicts)
1381 PF_WARNING("copyentity: can not modify world entity\n");
1382 if (out->priv.server->free)
1383 PF_WARNING("copyentity: can not modify free entity\n");
1384 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1392 sets the color of a client and broadcasts the update to all connected clients
1394 setcolor(clientent, value)
1397 void PF_setcolor (void)
1403 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1404 i = PRVM_G_FLOAT(OFS_PARM1);
1406 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1408 Con_Print("tried to setcolor a non-client\n");
1412 client = svs.clients + entnum-1;
1415 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1417 client->edict->fields.server->team = (i & 15) + 1;
1420 if (client->old_colors != client->colors)
1422 client->old_colors = client->colors;
1423 // send notification to all clients
1424 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1425 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1426 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1434 effect(origin, modelname, startframe, framecount, framerate)
1437 void PF_effect (void)
1441 s = PRVM_G_STRING(OFS_PARM1);
1443 PF_WARNING("effect: no model specified\n");
1445 i = SV_ModelIndex(s, 1);
1447 PF_WARNING("effect: model not precached\n");
1448 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1451 void PF_te_blood (void)
1453 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1455 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1456 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1458 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1459 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1460 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1462 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1463 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1464 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1466 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1469 void PF_te_bloodshower (void)
1471 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1473 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1474 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1476 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1477 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1478 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1480 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1481 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1482 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1484 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1486 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1489 void PF_te_explosionrgb (void)
1491 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1492 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1494 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1495 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1496 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1498 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1499 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1500 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1503 void PF_te_particlecube (void)
1505 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1507 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1508 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1510 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1511 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1514 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1515 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1516 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1518 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1519 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1522 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1524 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1525 // gravity true/false
1526 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1528 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1531 void PF_te_particlerain (void)
1533 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1535 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1536 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1538 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1539 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1540 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1542 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1543 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1548 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1550 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1552 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1555 void PF_te_particlesnow (void)
1557 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1560 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1564 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1570 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1571 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1572 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1574 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1576 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1579 void PF_te_spark (void)
1581 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1583 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1584 MSG_WriteByte(&sv.datagram, TE_SPARK);
1586 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1587 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1588 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1590 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1591 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1592 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1594 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1597 void PF_te_gunshotquad (void)
1599 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1600 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1602 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1603 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1604 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1607 void PF_te_spikequad (void)
1609 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1610 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1612 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1613 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1614 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1617 void PF_te_superspikequad (void)
1619 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1620 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1624 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1627 void PF_te_explosionquad (void)
1629 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1630 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1634 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1637 void PF_te_smallflash (void)
1639 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1640 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1644 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1647 void PF_te_customflash (void)
1649 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1651 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1652 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1656 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1658 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1660 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1662 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1663 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1664 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1667 void PF_te_gunshot (void)
1669 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1670 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1672 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1673 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1674 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1677 void PF_te_spike (void)
1679 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1680 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1687 void PF_te_superspike (void)
1689 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1690 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1694 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1697 void PF_te_explosion (void)
1699 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1700 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1702 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1703 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1704 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1707 void PF_te_tarexplosion (void)
1709 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1710 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1717 void PF_te_wizspike (void)
1719 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1720 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1727 void PF_te_knightspike (void)
1729 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1730 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1737 void PF_te_lavasplash (void)
1739 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1740 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1747 void PF_te_teleport (void)
1749 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1750 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1757 void PF_te_explosion2 (void)
1759 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1760 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1764 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1766 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1767 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1770 void PF_te_lightning1 (void)
1772 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1773 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1775 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1786 void PF_te_lightning2 (void)
1788 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1789 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1791 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1802 void PF_te_lightning3 (void)
1804 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1805 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1807 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1818 void PF_te_beam (void)
1820 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1821 MSG_WriteByte(&sv.datagram, TE_BEAM);
1823 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1834 void PF_te_plasmaburn (void)
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1843 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1846 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1848 bestdist = 1000000000;
1850 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1852 // clip original point to each triangle of the surface and find the
1853 // triangle that is closest
1854 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1855 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1856 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1857 TriangleNormal(v[0], v[1], v[2], facenormal);
1858 VectorNormalize(facenormal);
1859 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1860 VectorMA(p, offsetdist, facenormal, temp);
1861 for (j = 0, k = 2;j < 3;k = j, j++)
1863 VectorSubtract(v[k], v[j], edgenormal);
1864 CrossProduct(edgenormal, facenormal, sidenormal);
1865 VectorNormalize(sidenormal);
1866 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1868 VectorMA(temp, offsetdist, sidenormal, temp);
1870 dist = VectorDistance2(temp, p);
1871 if (bestdist > dist)
1874 VectorCopy(temp, out);
1879 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1883 if (!ed || ed->priv.server->free)
1885 modelindex = ed->fields.server->modelindex;
1886 if (modelindex < 1 || modelindex >= MAX_MODELS)
1888 model = sv.models[modelindex];
1889 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1891 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1895 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1896 void PF_getsurfacenumpoints(void)
1898 msurface_t *surface;
1899 // return 0 if no such surface
1900 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1902 PRVM_G_FLOAT(OFS_RETURN) = 0;
1906 // note: this (incorrectly) assumes it is a simple polygon
1907 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1909 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1910 void PF_getsurfacepoint(void)
1913 msurface_t *surface;
1915 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1916 ed = PRVM_G_EDICT(OFS_PARM0);
1917 if (!ed || ed->priv.server->free)
1919 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1921 // note: this (incorrectly) assumes it is a simple polygon
1922 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1923 if (pointnum < 0 || pointnum >= surface->num_vertices)
1925 // FIXME: implement rotation/scaling
1926 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1928 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1929 void PF_getsurfacenormal(void)
1931 msurface_t *surface;
1933 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1934 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1936 // FIXME: implement rotation/scaling
1937 // note: this (incorrectly) assumes it is a simple polygon
1938 // note: this only returns the first triangle, so it doesn't work very
1939 // well for curved surfaces or arbitrary meshes
1940 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);
1941 VectorNormalize(normal);
1942 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1944 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1945 void PF_getsurfacetexture(void)
1947 msurface_t *surface;
1948 PRVM_G_INT(OFS_RETURN) = 0;
1949 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1951 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1953 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1954 void PF_getsurfacenearpoint(void)
1956 int surfacenum, best, modelindex;
1958 vec_t dist, bestdist;
1961 msurface_t *surface;
1963 PRVM_G_FLOAT(OFS_RETURN) = -1;
1964 ed = PRVM_G_EDICT(OFS_PARM0);
1965 point = PRVM_G_VECTOR(OFS_PARM1);
1967 if (!ed || ed->priv.server->free)
1969 modelindex = ed->fields.server->modelindex;
1970 if (modelindex < 1 || modelindex >= MAX_MODELS)
1972 model = sv.models[modelindex];
1973 if (!model->num_surfaces)
1976 // FIXME: implement rotation/scaling
1977 VectorSubtract(point, ed->fields.server->origin, p);
1979 bestdist = 1000000000;
1980 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1982 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1983 // first see if the nearest point on the surface's box is closer than the previous match
1984 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1985 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1986 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1987 dist = VectorLength2(clipped);
1988 if (dist < bestdist)
1990 // it is, check the nearest point on the actual geometry
1991 clippointtosurface(surface, p, clipped);
1992 VectorSubtract(clipped, p, clipped);
1993 dist += VectorLength2(clipped);
1994 if (dist < bestdist)
1996 // that's closer too, store it as the best match
2002 PRVM_G_FLOAT(OFS_RETURN) = best;
2004 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2005 void PF_getsurfaceclippedpoint(void)
2008 msurface_t *surface;
2010 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2011 ed = PRVM_G_EDICT(OFS_PARM0);
2012 if (!ed || ed->priv.server->free)
2014 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2016 // FIXME: implement rotation/scaling
2017 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2018 clippointtosurface(surface, p, out);
2019 // FIXME: implement rotation/scaling
2020 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2023 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2024 //this function originally written by KrimZon, made shorter by LordHavoc
2025 void PF_clientcommand (void)
2027 client_t *temp_client;
2030 //find client for this entity
2031 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2032 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2034 Con_Print("PF_clientcommand: entity is not a client\n");
2038 temp_client = host_client;
2039 host_client = svs.clients + i;
2040 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2041 host_client = temp_client;
2044 //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)
2045 void PF_setattachment (void)
2047 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2048 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2049 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2054 if (e == prog->edicts)
2055 PF_WARNING("setattachment: can not modify world entity\n");
2056 if (e->priv.server->free)
2057 PF_WARNING("setattachment: can not modify free entity\n");
2059 if (tagentity == NULL)
2060 tagentity = prog->edicts;
2062 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2064 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2066 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2069 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2071 modelindex = (int)tagentity->fields.server->modelindex;
2072 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2074 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2076 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);
2079 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));
2083 /////////////////////////////////////////
2084 // DP_MD3_TAGINFO extension coded by VorteX
2086 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2091 i = e->fields.server->modelindex;
2092 if (i < 1 || i >= MAX_MODELS)
2094 model = sv.models[i];
2096 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2099 // Warnings/errors code:
2100 // 0 - normal (everything all-right)
2103 // 3 - null or non-precached model
2104 // 4 - no tags with requested index
2105 // 5 - runaway loop at attachment chain
2106 extern cvar_t cl_bob;
2107 extern cvar_t cl_bobcycle;
2108 extern cvar_t cl_bobup;
2109 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2112 int modelindex, reqframe, attachloop;
2113 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2114 prvm_edict_t *attachent;
2117 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2119 if (ent == prog->edicts)
2121 if (ent->priv.server->free)
2124 modelindex = (int)ent->fields.server->modelindex;
2125 if (modelindex <= 0 || modelindex > MAX_MODELS)
2128 model = sv.models[modelindex];
2130 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2131 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2133 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2135 // get initial tag matrix
2138 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2143 Matrix4x4_CreateIdentity(&tagmatrix);
2145 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2146 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2150 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2151 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2152 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)
2153 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2155 Matrix4x4_CreateIdentity(&attachmatrix);
2157 // apply transformation by child entity matrix
2158 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2159 if (val->_float == 0)
2161 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);
2162 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2163 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]);
2164 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]);
2165 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]);
2166 Matrix4x4_Copy(&tagmatrix, out);
2168 // finally transformate by matrix of tag on parent entity
2169 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2170 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];
2171 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];
2172 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];
2173 Matrix4x4_Copy(&tagmatrix, out);
2177 if (attachloop > 255) // prevent runaway looping
2180 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2183 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2184 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2185 if (val->_float == 0)
2187 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2188 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);
2189 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2190 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]);
2191 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]);
2192 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]);
2194 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2195 {// RENDER_VIEWMODEL magic
2196 Matrix4x4_Copy(&tagmatrix, out);
2197 ent = PRVM_EDICT_NUM(val->edict);
2199 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2200 if (val->_float == 0)
2203 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);
2204 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2205 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]);
2206 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]);
2207 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]);
2210 // Cl_bob, ported from rendering code
2211 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2214 // LordHavoc: this code is *weird*, but not replacable (I think it
2215 // should be done in QC on the server, but oh well, quake is quake)
2216 // LordHavoc: figured out bobup: the time at which the sin is at 180
2217 // degrees (which allows lengthening or squishing the peak or valley)
2218 cycle = sv.time/cl_bobcycle.value;
2219 cycle -= (int)cycle;
2220 if (cycle < cl_bobup.value)
2221 cycle = sin(M_PI * cycle / cl_bobup.value);
2223 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2224 // bob is proportional to velocity in the xy plane
2225 // (don't count Z, or jumping messes it up)
2226 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;
2227 bob = bob*0.3 + bob*0.7*cycle;
2228 out->m[2][3] += bound(-7, bob, 4);
2235 //float(entity ent, string tagname) gettagindex;
2237 void PF_gettagindex (void)
2239 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2240 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2241 int modelindex, tag_index;
2243 if (ent == prog->edicts)
2244 PF_WARNING("gettagindex: can't affect world entity\n");
2245 if (ent->priv.server->free)
2246 PF_WARNING("gettagindex: can't affect free entity\n");
2248 modelindex = (int)ent->fields.server->modelindex;
2250 if (modelindex <= 0 || modelindex > MAX_MODELS)
2251 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2254 tag_index = SV_GetTagIndex(ent, tag_name);
2256 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2258 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2261 //vector(entity ent, float tagindex) gettaginfo;
2262 void PF_gettaginfo (void)
2264 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2265 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2266 matrix4x4_t tag_matrix;
2269 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2270 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2275 PF_WARNING("gettagindex: can't affect world entity\n");
2278 PF_WARNING("gettagindex: can't affect free entity\n");
2281 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2284 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2287 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2292 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2293 void PF_dropclient (void)
2296 client_t *oldhostclient;
2297 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2298 if (clientnum < 0 || clientnum >= svs.maxclients)
2299 PF_WARNING("dropclient: not a client\n");
2300 if (!svs.clients[clientnum].active)
2301 PF_WARNING("dropclient: that client slot is not connected\n");
2302 oldhostclient = host_client;
2303 host_client = svs.clients + clientnum;
2304 SV_DropClient(false);
2305 host_client = oldhostclient;
2308 //entity() spawnclient (DP_SV_BOTCLIENT)
2309 void PF_spawnclient (void)
2313 prog->xfunction->builtinsprofile += 2;
2315 for (i = 0;i < svs.maxclients;i++)
2317 if (!svs.clients[i].active)
2319 prog->xfunction->builtinsprofile += 100;
2320 SV_ConnectClient (i, NULL);
2321 ed = PRVM_EDICT_NUM(i + 1);
2325 VM_RETURN_EDICT(ed);
2328 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2329 void PF_clienttype (void)
2332 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2333 if (clientnum < 0 || clientnum >= svs.maxclients)
2334 PRVM_G_FLOAT(OFS_RETURN) = 3;
2335 else if (!svs.clients[clientnum].active)
2336 PRVM_G_FLOAT(OFS_RETURN) = 0;
2337 else if (svs.clients[clientnum].netconnection)
2338 PRVM_G_FLOAT(OFS_RETURN) = 1;
2340 PRVM_G_FLOAT(OFS_RETURN) = 2;
2343 prvm_builtin_t vm_sv_builtins[] = {
2345 PF_makevectors, // #1 void(entity e) makevectors
2346 PF_setorigin, // #2 void(entity e, vector o) setorigin
2347 PF_setmodel, // #3 void(entity e, string m) setmodel
2348 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2349 NULL, // #5 void(entity e, vector min, vector max) setabssize
2350 VM_break, // #6 void() break
2351 VM_random, // #7 float() random
2352 PF_sound, // #8 void(entity e, float chan, string samp) sound
2353 VM_normalize, // #9 vector(vector v) normalize
2354 VM_error, // #10 void(string e) error
2355 VM_objerror, // #11 void(string e) objerror
2356 VM_vlen, // #12 float(vector v) vlen
2357 VM_vectoyaw, // #13 float(vector v) vectoyaw
2358 VM_spawn, // #14 entity() spawn
2359 VM_remove, // #15 void(entity e) remove
2360 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2361 PF_checkclient, // #17 entity() clientlist
2362 VM_find, // #18 entity(entity start, .string fld, string match) find
2363 PF_precache_sound, // #19 void(string s) precache_sound
2364 PF_precache_model, // #20 void(string s) precache_model
2365 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2366 PF_findradius, // #22 entity(vector org, float rad) findradius
2367 VM_bprint, // #23 void(string s) bprint
2368 PF_sprint, // #24 void(entity client, string s) sprint
2369 VM_dprint, // #25 void(string s) dprint
2370 VM_ftos, // #26 void(string s) ftos
2371 VM_vtos, // #27 void(string s) vtos
2372 VM_coredump, // #28 void() coredump
2373 VM_traceon, // #29 void() traceon
2374 VM_traceoff, // #30 void() traceoff
2375 VM_eprint, // #31 void(entity e) eprint
2376 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2378 PF_droptofloor, // #34 float() droptofloor
2379 PF_lightstyle, // #35 void(float style, string value) lightstyle
2380 VM_rint, // #36 float(float v) rint
2381 VM_floor, // #37 float(float v) floor
2382 VM_ceil, // #38 float(float v) ceil
2384 PF_checkbottom, // #40 float(entity e) checkbottom
2385 PF_pointcontents, // #41 float(vector v) pointcontents
2387 VM_fabs, // #43 float(float f) fabs
2388 PF_aim, // #44 vector(entity e, float speed) aim
2389 VM_cvar, // #45 float(string s) cvar
2390 VM_localcmd, // #46 void(string s) localcmd
2391 VM_nextent, // #47 entity(entity e) nextent
2392 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2393 PF_changeyaw, // #49 void() ChangeYaw
2395 VM_vectoangles, // #51 vector(vector v) vectoangles
2396 PF_WriteByte, // #52 void(float to, float f) WriteByte
2397 PF_WriteChar, // #53 void(float to, float f) WriteChar
2398 PF_WriteShort, // #54 void(float to, float f) WriteShort
2399 PF_WriteLong, // #55 void(float to, float f) WriteLong
2400 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2401 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2402 PF_WriteString, // #58 void(float to, string s) WriteString
2403 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2404 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2405 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2406 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2407 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2408 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2409 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2411 SV_MoveToGoal, // #67 void(float step) movetogoal
2412 PF_precache_file, // #68 string(string s) precache_file
2413 PF_makestatic, // #69 void(entity e) makestatic
2414 VM_changelevel, // #70 void(string s) changelevel
2416 VM_cvar_set, // #72 void(string var, string val) cvar_set
2417 PF_centerprint, // #73 void(entity client, strings) centerprint
2418 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2419 PF_precache_model, // #75 string(string s) precache_model2
2420 PF_precache_sound, // #76 string(string s) precache_sound2
2421 PF_precache_file, // #77 string(string s) precache_file2
2422 PF_setspawnparms, // #78 void(entity e) setspawnparms
2425 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2434 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2435 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2436 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2437 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2438 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2439 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2440 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2441 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2442 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2443 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2454 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2455 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2456 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2457 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2458 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2459 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2460 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2461 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2462 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2463 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2464 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2465 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2466 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2467 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2468 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2469 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2470 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2471 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2472 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2473 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2474 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2475 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2476 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2477 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2478 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2479 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2480 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2481 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2482 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2483 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2484 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2485 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2486 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2487 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2488 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2489 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2490 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2491 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2492 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2493 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2494 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2495 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2496 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2497 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2498 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2499 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2500 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2501 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2502 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2503 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2504 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2505 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2506 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2507 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2508 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2509 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2510 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2511 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2512 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2513 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2514 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2515 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2516 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2517 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2518 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2519 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2520 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2521 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2522 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2527 e10, e10, e10, e10 // #460-499 (LordHavoc)
2530 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2532 void VM_SV_Cmd_Init(void)
2537 void VM_SV_Cmd_Reset(void)