3 //============================================================================
6 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
7 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
10 char *vm_sv_extensions =
12 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
38 "DP_GFX_QUAKE3MODELTAGS "
42 "DP_HALFLIFE_MAP_CVAR "
48 "DP_MOVETYPEBOUNCEMISSILE "
55 "DP_QC_FINDCHAINFLAGS "
56 "DP_QC_FINDCHAINFLOAT "
59 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
64 "DP_QC_MULTIPLETEMPSTRINGS "
66 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_TRACE_MOVETYPE_HITMODEL "
70 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
71 "DP_QC_VECTORVECTORS "
77 "DP_SND_DIRECTIONLESSATTNNONE "
86 "DP_SV_DRAWONLYTOCLIENT "
89 "DP_SV_NODRAWTOCLIENT "
91 "DP_SV_PLAYERPHYSICS "
92 "DP_SV_PRECACHEANYTIME "
94 "DP_SV_ROTATINGBMODEL "
97 "DP_SV_WRITEUNTERMINATEDSTRING "
101 "DP_TE_EXPLOSIONRGB "
103 "DP_TE_PARTICLECUBE "
104 "DP_TE_PARTICLERAIN "
105 "DP_TE_PARTICLESNOW "
107 "DP_TE_QUADEFFECTS1 "
110 "DP_TE_STANDARDEFFECTBUILTINS "
113 "KRIMZON_SV_PARSECLIENTCOMMAND "
117 "PRYDON_CLIENTCURSOR "
118 "TENEBRAE_GFX_DLIGHTS "
120 "NEXUIZ_PLAYERMODEL "
127 Writes new values for v_forward, v_up, and v_right based on angles
131 void PF_makevectors (void)
133 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
140 Writes new values for v_forward, v_up, and v_right based on the given forward vector
141 vectorvectors(vector, vector)
144 void PF_vectorvectors (void)
146 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
147 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
154 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.
156 setorigin (entity, origin)
159 void PF_setorigin (void)
164 e = PRVM_G_EDICT(OFS_PARM0);
165 if (e == prog->edicts)
166 PF_WARNING("setorigin: can not modify world entity\n");
167 if (e->priv.server->free)
168 PF_WARNING("setorigin: can not modify free entity\n");
169 org = PRVM_G_VECTOR(OFS_PARM1);
170 VectorCopy (org, e->fields.server->origin);
171 SV_LinkEdict (e, false);
175 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
179 for (i=0 ; i<3 ; i++)
181 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs\n");
183 // set derived values
184 VectorCopy (min, e->fields.server->mins);
185 VectorCopy (max, e->fields.server->maxs);
186 VectorSubtract (max, min, e->fields.server->size);
188 SV_LinkEdict (e, false);
195 the size box is rotated by the current angle
196 LordHavoc: no it isn't...
198 setsize (entity, minvector, maxvector)
201 void PF_setsize (void)
206 e = PRVM_G_EDICT(OFS_PARM0);
207 if (e == prog->edicts)
208 PF_WARNING("setsize: can not modify world entity\n");
209 if (e->priv.server->free)
210 PF_WARNING("setsize: can not modify free entity\n");
211 min = PRVM_G_VECTOR(OFS_PARM1);
212 max = PRVM_G_VECTOR(OFS_PARM2);
213 SetMinMaxSize (e, min, max, false);
221 setmodel(entity, model)
224 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
225 void PF_setmodel (void)
231 e = PRVM_G_EDICT(OFS_PARM0);
232 if (e == prog->edicts)
233 PF_WARNING("setmodel: can not modify world entity\n");
234 if (e->priv.server->free)
235 PF_WARNING("setmodel: can not modify free entity\n");
236 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
237 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
238 e->fields.server->modelindex = i;
244 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
245 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
247 SetMinMaxSize (e, quakemins, quakemaxs, true);
250 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
257 single print to a specific client
259 sprint(clientent, value)
262 void PF_sprint (void)
266 char string[VM_STRINGTEMP_LENGTH];
268 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
270 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
272 Con_Print("tried to sprint to a non-client\n");
276 client = svs.clients + entnum-1;
277 VM_VarString(1, string, sizeof(string));
278 MSG_WriteChar(&client->message,svc_print);
279 MSG_WriteString(&client->message, string);
287 single print to a specific client
289 centerprint(clientent, value)
292 void PF_centerprint (void)
296 char string[VM_STRINGTEMP_LENGTH];
298 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
300 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
302 Con_Print("tried to sprint to a non-client\n");
306 client = svs.clients + entnum-1;
307 VM_VarString(1, string, sizeof(string));
308 MSG_WriteChar(&client->message,svc_centerprint);
309 MSG_WriteString(&client->message, string);
316 particle(origin, color, count)
319 void PF_particle (void)
325 org = PRVM_G_VECTOR(OFS_PARM0);
326 dir = PRVM_G_VECTOR(OFS_PARM1);
327 color = PRVM_G_FLOAT(OFS_PARM2);
328 count = PRVM_G_FLOAT(OFS_PARM3);
329 SV_StartParticle (org, dir, color, count);
339 void PF_ambientsound (void)
343 float vol, attenuation;
346 pos = PRVM_G_VECTOR (OFS_PARM0);
347 samp = PRVM_G_STRING(OFS_PARM1);
348 vol = PRVM_G_FLOAT(OFS_PARM2);
349 attenuation = PRVM_G_FLOAT(OFS_PARM3);
351 // check to see if samp was properly precached
352 soundnum = SV_SoundIndex(samp, 1);
360 // add an svc_spawnambient command to the level signon packet
363 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
365 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
367 MSG_WriteVector(&sv.signon, pos, sv.protocol);
370 MSG_WriteShort (&sv.signon, soundnum);
372 MSG_WriteByte (&sv.signon, soundnum);
374 MSG_WriteByte (&sv.signon, vol*255);
375 MSG_WriteByte (&sv.signon, attenuation*64);
383 Each entity can have eight independant sound sources, like voice,
386 Channel 0 is an auto-allocate channel, the others override anything
387 already running on that entity/channel pair.
389 An attenuation of 0 will play full volume everywhere in the level.
390 Larger attenuations will drop off.
398 prvm_edict_t *entity;
402 entity = PRVM_G_EDICT(OFS_PARM0);
403 channel = PRVM_G_FLOAT(OFS_PARM1);
404 sample = PRVM_G_STRING(OFS_PARM2);
405 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
406 attenuation = PRVM_G_FLOAT(OFS_PARM4);
408 if (volume < 0 || volume > 255)
409 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
411 if (attenuation < 0 || attenuation > 4)
412 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
414 if (channel < 0 || channel > 7)
415 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
417 SV_StartSound (entity, channel, sample, volume, attenuation);
424 Used for use tracing and shot targeting
425 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
426 if the tryents flag is set.
428 traceline (vector1, vector2, tryents)
431 void PF_traceline (void)
438 prog->xfunction->builtinsprofile += 30;
440 v1 = PRVM_G_VECTOR(OFS_PARM0);
441 v2 = PRVM_G_VECTOR(OFS_PARM1);
442 move = PRVM_G_FLOAT(OFS_PARM2);
443 ent = PRVM_G_EDICT(OFS_PARM3);
445 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
447 prog->globals.server->trace_allsolid = trace.allsolid;
448 prog->globals.server->trace_startsolid = trace.startsolid;
449 prog->globals.server->trace_fraction = trace.fraction;
450 prog->globals.server->trace_inwater = trace.inwater;
451 prog->globals.server->trace_inopen = trace.inopen;
452 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
453 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
454 prog->globals.server->trace_plane_dist = trace.plane.dist;
456 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
458 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
459 // FIXME: add trace_endcontents
467 Used for use tracing and shot targeting
468 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
469 if the tryents flag is set.
471 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
474 // LordHavoc: added this for my own use, VERY useful, similar to traceline
475 void PF_tracebox (void)
477 float *v1, *v2, *m1, *m2;
482 prog->xfunction->builtinsprofile += 30;
484 v1 = PRVM_G_VECTOR(OFS_PARM0);
485 m1 = PRVM_G_VECTOR(OFS_PARM1);
486 m2 = PRVM_G_VECTOR(OFS_PARM2);
487 v2 = PRVM_G_VECTOR(OFS_PARM3);
488 move = PRVM_G_FLOAT(OFS_PARM4);
489 ent = PRVM_G_EDICT(OFS_PARM5);
491 trace = SV_Move (v1, m1, m2, v2, move, ent);
493 prog->globals.server->trace_allsolid = trace.allsolid;
494 prog->globals.server->trace_startsolid = trace.startsolid;
495 prog->globals.server->trace_fraction = trace.fraction;
496 prog->globals.server->trace_inwater = trace.inwater;
497 prog->globals.server->trace_inopen = trace.inopen;
498 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
499 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
500 prog->globals.server->trace_plane_dist = trace.plane.dist;
502 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
504 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
507 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
508 void PF_tracetoss (void)
512 prvm_edict_t *ignore;
514 prog->xfunction->builtinsprofile += 600;
516 ent = PRVM_G_EDICT(OFS_PARM0);
517 if (ent == prog->edicts)
518 PF_WARNING("tracetoss: can not use world entity\n");
519 ignore = PRVM_G_EDICT(OFS_PARM1);
521 trace = SV_Trace_Toss (ent, ignore);
523 prog->globals.server->trace_allsolid = trace.allsolid;
524 prog->globals.server->trace_startsolid = trace.startsolid;
525 prog->globals.server->trace_fraction = trace.fraction;
526 prog->globals.server->trace_inwater = trace.inwater;
527 prog->globals.server->trace_inopen = trace.inopen;
528 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
529 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
530 prog->globals.server->trace_plane_dist = trace.plane.dist;
532 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
534 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
542 Returns true if the given entity can move to the given position from it's
543 current position by walking or rolling.
545 scalar checkpos (entity, vector)
548 void PF_checkpos (void)
552 //============================================================================
555 qbyte checkpvs[MAX_MAP_LEAFS/8];
557 int PF_newcheckclient (int check)
563 // cycle to the next one
565 check = bound(1, check, svs.maxclients);
566 if (check == svs.maxclients)
574 prog->xfunction->builtinsprofile++;
576 if (i == svs.maxclients+1)
578 // look up the client's edict
579 ent = PRVM_EDICT_NUM(i);
580 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
581 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
583 // found a valid client (possibly the same one again)
587 // get the PVS for the entity
588 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
590 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
591 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
600 Returns a client (or object that has a client enemy) that would be a
603 If there is more than one valid option, they are cycled each frame
605 If (self.origin + self.viewofs) is not in the PVS of the current target,
606 it is not returned at all.
611 int c_invis, c_notvis;
612 void PF_checkclient (void)
614 prvm_edict_t *ent, *self;
617 // find a new check if on a new frame
618 if (sv.time - sv.lastchecktime >= 0.1)
620 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
621 sv.lastchecktime = sv.time;
624 // return check if it might be visible
625 ent = PRVM_EDICT_NUM(sv.lastcheck);
626 if (ent->priv.server->free || ent->fields.server->health <= 0)
628 VM_RETURN_EDICT(prog->edicts);
632 // if current entity can't possibly see the check entity, return 0
633 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
634 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
635 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
638 VM_RETURN_EDICT(prog->edicts);
642 // might be able to see it
644 VM_RETURN_EDICT(ent);
647 //============================================================================
654 Sends text over to the client's execution buffer
656 stuffcmd (clientent, value)
659 void PF_stuffcmd (void)
665 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
666 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
668 Con_Print("Can't stuffcmd to a non-client\n");
671 str = PRVM_G_STRING(OFS_PARM1);
674 host_client = svs.clients + entnum-1;
675 Host_ClientCommands ("%s", str);
683 Returns a chain of entities that have origins within a spherical area
685 findradius (origin, radius)
688 void PF_findradius (void)
690 prvm_edict_t *ent, *chain;
691 vec_t radius, radius2;
692 vec3_t org, eorg, mins, maxs;
695 prvm_edict_t *touchedicts[MAX_EDICTS];
697 chain = (prvm_edict_t *)prog->edicts;
699 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
700 radius = PRVM_G_FLOAT(OFS_PARM1);
701 radius2 = radius * radius;
703 mins[0] = org[0] - (radius + 1);
704 mins[1] = org[1] - (radius + 1);
705 mins[2] = org[2] - (radius + 1);
706 maxs[0] = org[0] + (radius + 1);
707 maxs[1] = org[1] + (radius + 1);
708 maxs[2] = org[2] + (radius + 1);
709 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
710 if (numtouchedicts > MAX_EDICTS)
712 // this never happens
713 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
714 numtouchedicts = MAX_EDICTS;
716 for (i = 0;i < numtouchedicts;i++)
718 ent = touchedicts[i];
719 prog->xfunction->builtinsprofile++;
720 // Quake did not return non-solid entities but darkplaces does
721 // (note: this is the reason you can't blow up fallen zombies)
722 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
724 // LordHavoc: compare against bounding box rather than center so it
725 // doesn't miss large objects, and use DotProduct instead of Length
726 // for a major speedup
727 VectorSubtract(org, ent->fields.server->origin, eorg);
728 if (sv_gameplayfix_findradiusdistancetobox.integer)
730 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
731 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
732 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
735 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
736 if (DotProduct(eorg, eorg) < radius2)
738 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
743 VM_RETURN_EDICT(chain);
746 void PF_precache_file (void)
747 { // precache_file is only used to copy files with qcc, it does nothing
748 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
752 void PF_precache_sound (void)
754 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
755 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
758 void PF_precache_model (void)
760 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
761 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
768 float(float yaw, float dist) walkmove
771 void PF_walkmove (void)
779 // assume failure if it returns early
780 PRVM_G_FLOAT(OFS_RETURN) = 0;
782 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
783 if (ent == prog->edicts)
784 PF_WARNING("walkmove: can not modify world entity\n");
785 if (ent->priv.server->free)
786 PF_WARNING("walkmove: can not modify free entity\n");
787 yaw = PRVM_G_FLOAT(OFS_PARM0);
788 dist = PRVM_G_FLOAT(OFS_PARM1);
790 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
793 yaw = yaw*M_PI*2 / 360;
795 move[0] = cos(yaw)*dist;
796 move[1] = sin(yaw)*dist;
799 // save program state, because SV_movestep may call other progs
800 oldf = prog->xfunction;
801 oldself = prog->globals.server->self;
803 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
806 // restore program state
807 prog->xfunction = oldf;
808 prog->globals.server->self = oldself;
818 void PF_droptofloor (void)
824 // assume failure if it returns early
825 PRVM_G_FLOAT(OFS_RETURN) = 0;
827 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
828 if (ent == prog->edicts)
829 PF_WARNING("droptofloor: can not modify world entity\n");
830 if (ent->priv.server->free)
831 PF_WARNING("droptofloor: can not modify free entity\n");
833 VectorCopy (ent->fields.server->origin, end);
836 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
838 if (trace.fraction != 1)
840 VectorCopy (trace.endpos, ent->fields.server->origin);
841 SV_LinkEdict (ent, false);
842 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
843 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
844 PRVM_G_FLOAT(OFS_RETURN) = 1;
845 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
846 ent->priv.server->suspendedinairflag = true;
854 void(float style, string value) lightstyle
857 void PF_lightstyle (void)
864 style = PRVM_G_FLOAT(OFS_PARM0);
865 val = PRVM_G_STRING(OFS_PARM1);
867 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
868 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
871 // change the string in sv
872 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
874 // send message to all clients on this server
875 if (sv.state != ss_active)
878 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
882 MSG_WriteChar (&client->message, svc_lightstyle);
883 MSG_WriteChar (&client->message,style);
884 MSG_WriteString (&client->message, val);
894 void PF_checkbottom (void)
896 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
904 void PF_pointcontents (void)
906 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
913 Pick a vector for the player to shoot along
914 vector aim(entity, missilespeed)
919 prvm_edict_t *ent, *check, *bestent;
920 vec3_t start, dir, end, bestdir;
923 float dist, bestdist;
926 // assume failure if it returns early
927 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
928 // if sv_aim is so high it can't possibly accept anything, skip out early
929 if (sv_aim.value >= 1)
932 ent = PRVM_G_EDICT(OFS_PARM0);
933 if (ent == prog->edicts)
934 PF_WARNING("aim: can not use world entity\n");
935 if (ent->priv.server->free)
936 PF_WARNING("aim: can not use free entity\n");
937 speed = PRVM_G_FLOAT(OFS_PARM1);
939 VectorCopy (ent->fields.server->origin, start);
942 // try sending a trace straight
943 VectorCopy (prog->globals.server->v_forward, dir);
944 VectorMA (start, 2048, dir, end);
945 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
946 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
947 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
949 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
954 // try all possible entities
955 VectorCopy (dir, bestdir);
956 bestdist = sv_aim.value;
959 check = PRVM_NEXT_EDICT(prog->edicts);
960 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
962 prog->xfunction->builtinsprofile++;
963 if (check->fields.server->takedamage != DAMAGE_AIM)
967 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
968 continue; // don't aim at teammate
969 for (j=0 ; j<3 ; j++)
970 end[j] = check->fields.server->origin[j]
971 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
972 VectorSubtract (end, start, dir);
973 VectorNormalize (dir);
974 dist = DotProduct (dir, prog->globals.server->v_forward);
976 continue; // to far to turn
977 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
979 { // can shoot at this one
987 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
988 dist = DotProduct (dir, prog->globals.server->v_forward);
989 VectorScale (prog->globals.server->v_forward, dist, end);
991 VectorNormalize (end);
992 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
996 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1004 This was a major timewaster in progs, so it was converted to C
1007 void PF_changeyaw (void)
1010 float ideal, current, move, speed;
1012 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1013 if (ent == prog->edicts)
1014 PF_WARNING("changeyaw: can not modify world entity\n");
1015 if (ent->priv.server->free)
1016 PF_WARNING("changeyaw: can not modify free entity\n");
1017 current = ANGLEMOD(ent->fields.server->angles[1]);
1018 ideal = ent->fields.server->ideal_yaw;
1019 speed = ent->fields.server->yaw_speed;
1021 if (current == ideal)
1023 move = ideal - current;
1024 if (ideal > current)
1045 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1053 void PF_changepitch (void)
1056 float ideal, current, move, speed;
1059 ent = PRVM_G_EDICT(OFS_PARM0);
1060 if (ent == prog->edicts)
1061 PF_WARNING("changepitch: can not modify world entity\n");
1062 if (ent->priv.server->free)
1063 PF_WARNING("changepitch: can not modify free entity\n");
1064 current = ANGLEMOD( ent->fields.server->angles[0] );
1065 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1066 ideal = val->_float;
1069 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1072 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1073 speed = val->_float;
1076 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1080 if (current == ideal)
1082 move = ideal - current;
1083 if (ideal > current)
1104 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1108 ===============================================================================
1112 ===============================================================================
1115 #define MSG_BROADCAST 0 // unreliable to all
1116 #define MSG_ONE 1 // reliable to one (msg_entity)
1117 #define MSG_ALL 2 // reliable to all
1118 #define MSG_INIT 3 // write to the init string
1120 sizebuf_t *WriteDest (void)
1126 dest = PRVM_G_FLOAT(OFS_PARM0);
1130 return &sv.datagram;
1133 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1134 entnum = PRVM_NUM_FOR_EDICT(ent);
1135 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1137 Con_Printf ("WriteDest: tried to write to non-client\n");
1138 return &sv.reliable_datagram;
1141 return &svs.clients[entnum-1].message;
1144 Con_Printf ("WriteDest: bad destination");
1146 return &sv.reliable_datagram;
1155 void PF_WriteByte (void)
1157 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1160 void PF_WriteChar (void)
1162 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1165 void PF_WriteShort (void)
1167 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1170 void PF_WriteLong (void)
1172 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1175 void PF_WriteAngle (void)
1177 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1180 void PF_WriteCoord (void)
1182 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1185 void PF_WriteString (void)
1187 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1190 void PF_WriteUnterminatedString (void)
1192 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1196 void PF_WriteEntity (void)
1198 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1201 //////////////////////////////////////////////////////////
1203 void PF_makestatic (void)
1208 ent = PRVM_G_EDICT(OFS_PARM0);
1209 if (ent == prog->edicts)
1210 PF_WARNING("makestatic: can not modify world entity\n");
1211 if (ent->priv.server->free)
1212 PF_WARNING("makestatic: can not modify free entity\n");
1215 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1220 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1221 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1222 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1226 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1227 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1228 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1231 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1232 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1233 for (i=0 ; i<3 ; i++)
1235 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1236 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1239 // throw the entity away now
1243 //=============================================================================
1250 void PF_setspawnparms (void)
1256 ent = PRVM_G_EDICT(OFS_PARM0);
1257 i = PRVM_NUM_FOR_EDICT(ent);
1258 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1260 Con_Print("tried to setspawnparms on a non-client\n");
1264 // copy spawn parms out of the client_t
1265 client = svs.clients + i-1;
1266 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1267 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1274 Returns a color vector indicating the lighting at the requested point.
1276 (Internal Operation note: actually measures the light beneath the point, just like
1277 the model lighting on the client)
1282 void PF_getlight (void)
1284 vec3_t ambientcolor, diffusecolor, diffusenormal;
1286 p = PRVM_G_VECTOR(OFS_PARM0);
1287 VectorClear(ambientcolor);
1288 VectorClear(diffusecolor);
1289 VectorClear(diffusenormal);
1290 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1291 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1292 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1295 void PF_registercvar (void)
1297 const char *name, *value;
1298 name = PRVM_G_STRING(OFS_PARM0);
1299 value = PRVM_G_STRING(OFS_PARM1);
1300 PRVM_G_FLOAT(OFS_RETURN) = 0;
1302 // first check to see if it has already been defined
1303 if (Cvar_FindVar (name))
1306 // check for overlap with a command
1307 if (Cmd_Exists (name))
1309 Con_Printf("PF_registercvar: %s is a command\n", name);
1313 Cvar_Get(name, value, 0);
1315 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1322 copies data from one entity to another
1324 copyentity(src, dst)
1327 void PF_copyentity (void)
1329 prvm_edict_t *in, *out;
1330 in = PRVM_G_EDICT(OFS_PARM0);
1331 if (in == prog->edicts)
1332 PF_WARNING("copyentity: can not read world entity\n");
1333 if (in->priv.server->free)
1334 PF_WARNING("copyentity: can not read free entity\n");
1335 out = PRVM_G_EDICT(OFS_PARM1);
1336 if (out == prog->edicts)
1337 PF_WARNING("copyentity: can not modify world entity\n");
1338 if (out->priv.server->free)
1339 PF_WARNING("copyentity: can not modify free entity\n");
1340 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1348 sets the color of a client and broadcasts the update to all connected clients
1350 setcolor(clientent, value)
1353 void PF_setcolor (void)
1359 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1360 i = PRVM_G_FLOAT(OFS_PARM1);
1362 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1364 Con_Print("tried to setcolor a non-client\n");
1368 client = svs.clients + entnum-1;
1371 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1373 client->edict->fields.server->team = (i & 15) + 1;
1376 if (client->old_colors != client->colors)
1378 client->old_colors = client->colors;
1379 // send notification to all clients
1380 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1381 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1382 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1390 effect(origin, modelname, startframe, framecount, framerate)
1393 void PF_effect (void)
1397 s = PRVM_G_STRING(OFS_PARM1);
1399 PF_WARNING("effect: no model specified\n");
1401 i = SV_ModelIndex(s, 1);
1403 PF_WARNING("effect: model not precached\n");
1404 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1407 void PF_te_blood (void)
1409 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1411 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1412 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1414 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1415 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1416 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1418 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1419 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1420 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1422 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1425 void PF_te_bloodshower (void)
1427 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1430 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1432 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1433 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1434 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1436 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1437 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1438 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1440 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1442 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1445 void PF_te_explosionrgb (void)
1447 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1448 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1450 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1451 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1452 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1454 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1455 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1456 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1459 void PF_te_particlecube (void)
1461 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1463 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1464 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1466 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1467 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1468 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1470 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1471 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1472 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1474 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1475 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1476 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1478 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1480 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1481 // gravity true/false
1482 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1484 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1487 void PF_te_particlerain (void)
1489 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1491 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1492 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
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_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1499 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1500 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1502 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1503 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1504 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1506 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1508 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1511 void PF_te_particlesnow (void)
1513 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1515 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1516 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1518 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1519 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1522 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1523 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1524 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1526 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1527 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1528 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1530 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1532 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1535 void PF_te_spark (void)
1537 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1540 MSG_WriteByte(&sv.datagram, TE_SPARK);
1542 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1543 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1546 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1547 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1548 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1550 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1553 void PF_te_gunshotquad (void)
1555 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1556 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1558 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1559 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1560 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1563 void PF_te_spikequad (void)
1565 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1566 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1568 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1569 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1570 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1573 void PF_te_superspikequad (void)
1575 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1576 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1578 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1579 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1580 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1583 void PF_te_explosionquad (void)
1585 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1586 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1588 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1589 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1590 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1593 void PF_te_smallflash (void)
1595 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1596 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1598 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1599 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1600 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1603 void PF_te_customflash (void)
1605 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1607 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1608 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
1614 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1616 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1618 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1619 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1620 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1623 void PF_te_gunshot (void)
1625 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1626 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1628 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1630 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1633 void PF_te_spike (void)
1635 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1636 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1638 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1639 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1640 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1643 void PF_te_superspike (void)
1645 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1646 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1648 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1653 void PF_te_explosion (void)
1655 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1656 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1658 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1660 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1663 void PF_te_tarexplosion (void)
1665 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1666 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1673 void PF_te_wizspike (void)
1675 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1676 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1678 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1680 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1683 void PF_te_knightspike (void)
1685 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1686 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1693 void PF_te_lavasplash (void)
1695 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1696 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1698 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1699 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1700 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1703 void PF_te_teleport (void)
1705 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1706 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1708 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1713 void PF_te_explosion2 (void)
1715 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1716 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1722 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1723 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1726 void PF_te_lightning1 (void)
1728 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1729 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1731 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1742 void PF_te_lightning2 (void)
1744 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1745 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1747 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1758 void PF_te_lightning3 (void)
1760 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1761 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1763 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1765 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1766 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1767 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1771 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1774 void PF_te_beam (void)
1776 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1777 MSG_WriteByte(&sv.datagram, TE_BEAM);
1779 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1790 void PF_te_plasmaburn (void)
1792 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1793 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1799 void PF_te_flamejet (void)
1801 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1802 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1812 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1815 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1818 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1820 bestdist = 1000000000;
1822 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1824 // clip original point to each triangle of the surface and find the
1825 // triangle that is closest
1826 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1827 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1828 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1829 TriangleNormal(v[0], v[1], v[2], facenormal);
1830 VectorNormalize(facenormal);
1831 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1832 VectorMA(p, offsetdist, facenormal, temp);
1833 for (j = 0, k = 2;j < 3;k = j, j++)
1835 VectorSubtract(v[k], v[j], edgenormal);
1836 CrossProduct(edgenormal, facenormal, sidenormal);
1837 VectorNormalize(sidenormal);
1838 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1840 VectorMA(temp, offsetdist, sidenormal, temp);
1842 dist = VectorDistance2(temp, p);
1843 if (bestdist > dist)
1846 VectorCopy(temp, out);
1851 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1855 if (!ed || ed->priv.server->free)
1857 modelindex = ed->fields.server->modelindex;
1858 if (modelindex < 1 || modelindex >= MAX_MODELS)
1860 model = sv.models[modelindex];
1861 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1863 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1867 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1868 void PF_getsurfacenumpoints(void)
1870 msurface_t *surface;
1871 // return 0 if no such surface
1872 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1874 PRVM_G_FLOAT(OFS_RETURN) = 0;
1878 // note: this (incorrectly) assumes it is a simple polygon
1879 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1881 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1882 void PF_getsurfacepoint(void)
1885 msurface_t *surface;
1887 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1888 ed = PRVM_G_EDICT(OFS_PARM0);
1889 if (!ed || ed->priv.server->free)
1891 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1893 // note: this (incorrectly) assumes it is a simple polygon
1894 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1895 if (pointnum < 0 || pointnum >= surface->num_vertices)
1897 // FIXME: implement rotation/scaling
1898 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1900 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1901 void PF_getsurfacenormal(void)
1903 msurface_t *surface;
1905 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1906 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1908 // FIXME: implement rotation/scaling
1909 // note: this (incorrectly) assumes it is a simple polygon
1910 // note: this only returns the first triangle, so it doesn't work very
1911 // well for curved surfaces or arbitrary meshes
1912 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);
1913 VectorNormalize(normal);
1914 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1916 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1917 void PF_getsurfacetexture(void)
1919 msurface_t *surface;
1920 PRVM_G_INT(OFS_RETURN) = 0;
1921 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1923 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1925 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1926 void PF_getsurfacenearpoint(void)
1928 int surfacenum, best, modelindex;
1930 vec_t dist, bestdist;
1933 msurface_t *surface;
1935 PRVM_G_FLOAT(OFS_RETURN) = -1;
1936 ed = PRVM_G_EDICT(OFS_PARM0);
1937 point = PRVM_G_VECTOR(OFS_PARM1);
1939 if (!ed || ed->priv.server->free)
1941 modelindex = ed->fields.server->modelindex;
1942 if (modelindex < 1 || modelindex >= MAX_MODELS)
1944 model = sv.models[modelindex];
1945 if (!model->num_surfaces)
1948 // FIXME: implement rotation/scaling
1949 VectorSubtract(point, ed->fields.server->origin, p);
1951 bestdist = 1000000000;
1952 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1954 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1955 // first see if the nearest point on the surface's box is closer than the previous match
1956 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1957 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1958 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1959 dist = VectorLength2(clipped);
1960 if (dist < bestdist)
1962 // it is, check the nearest point on the actual geometry
1963 clippointtosurface(surface, p, clipped);
1964 VectorSubtract(clipped, p, clipped);
1965 dist += VectorLength2(clipped);
1966 if (dist < bestdist)
1968 // that's closer too, store it as the best match
1974 PRVM_G_FLOAT(OFS_RETURN) = best;
1976 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1977 void PF_getsurfaceclippedpoint(void)
1980 msurface_t *surface;
1982 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1983 ed = PRVM_G_EDICT(OFS_PARM0);
1984 if (!ed || ed->priv.server->free)
1986 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1988 // FIXME: implement rotation/scaling
1989 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1990 clippointtosurface(surface, p, out);
1991 // FIXME: implement rotation/scaling
1992 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1995 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1996 //this function originally written by KrimZon, made shorter by LordHavoc
1997 void PF_clientcommand (void)
1999 client_t *temp_client;
2002 //find client for this entity
2003 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2004 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2006 Con_Print("PF_clientcommand: entity is not a client\n");
2010 temp_client = host_client;
2011 host_client = svs.clients + i;
2012 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2013 host_client = temp_client;
2016 //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)
2017 void PF_setattachment (void)
2019 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2020 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2021 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2026 if (e == prog->edicts)
2027 PF_WARNING("setattachment: can not modify world entity\n");
2028 if (e->priv.server->free)
2029 PF_WARNING("setattachment: can not modify free entity\n");
2031 if (tagentity == NULL)
2032 tagentity = prog->edicts;
2034 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2036 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2038 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2041 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2043 modelindex = (int)tagentity->fields.server->modelindex;
2044 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2046 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2048 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);
2051 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));
2055 /////////////////////////////////////////
2056 // DP_MD3_TAGINFO extension coded by VorteX
2058 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2063 i = e->fields.server->modelindex;
2064 if (i < 1 || i >= MAX_MODELS)
2066 model = sv.models[i];
2068 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2071 // Warnings/errors code:
2072 // 0 - normal (everything all-right)
2075 // 3 - null or non-precached model
2076 // 4 - no tags with requested index
2077 // 5 - runaway loop at attachment chain
2078 extern cvar_t cl_bob;
2079 extern cvar_t cl_bobcycle;
2080 extern cvar_t cl_bobup;
2081 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2084 int modelindex, reqframe, attachloop;
2085 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2086 prvm_edict_t *attachent;
2089 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2091 if (ent == prog->edicts)
2093 if (ent->priv.server->free)
2096 modelindex = (int)ent->fields.server->modelindex;
2097 if (modelindex <= 0 || modelindex > MAX_MODELS)
2100 model = sv.models[modelindex];
2102 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2103 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2105 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2107 // get initial tag matrix
2110 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2115 Matrix4x4_CreateIdentity(&tagmatrix);
2117 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2118 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2122 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2123 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2124 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)
2125 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2127 Matrix4x4_CreateIdentity(&attachmatrix);
2129 // apply transformation by child entity matrix
2130 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2131 if (val->_float == 0)
2133 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], val->_float);
2134 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2135 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2136 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2137 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2138 Matrix4x4_Copy(&tagmatrix, out);
2140 // finally transformate by matrix of tag on parent entity
2141 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2142 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];
2143 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];
2144 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];
2145 Matrix4x4_Copy(&tagmatrix, out);
2149 if (attachloop > 255) // prevent runaway looping
2152 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2155 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2156 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2157 if (val->_float == 0)
2159 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2160 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);
2161 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2162 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]);
2163 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]);
2164 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 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2167 {// RENDER_VIEWMODEL magic
2168 Matrix4x4_Copy(&tagmatrix, out);
2169 ent = PRVM_EDICT_NUM(val->edict);
2171 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2172 if (val->_float == 0)
2175 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);
2176 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2177 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]);
2178 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]);
2179 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]);
2182 // Cl_bob, ported from rendering code
2183 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2186 // LordHavoc: this code is *weird*, but not replacable (I think it
2187 // should be done in QC on the server, but oh well, quake is quake)
2188 // LordHavoc: figured out bobup: the time at which the sin is at 180
2189 // degrees (which allows lengthening or squishing the peak or valley)
2190 cycle = sv.time/cl_bobcycle.value;
2191 cycle -= (int)cycle;
2192 if (cycle < cl_bobup.value)
2193 cycle = sin(M_PI * cycle / cl_bobup.value);
2195 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2196 // bob is proportional to velocity in the xy plane
2197 // (don't count Z, or jumping messes it up)
2198 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;
2199 bob = bob*0.3 + bob*0.7*cycle;
2200 out->m[2][3] += bound(-7, bob, 4);
2207 //float(entity ent, string tagname) gettagindex;
2209 void PF_gettagindex (void)
2211 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2212 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2213 int modelindex, tag_index;
2215 if (ent == prog->edicts)
2216 PF_WARNING("gettagindex: can't affect world entity\n");
2217 if (ent->priv.server->free)
2218 PF_WARNING("gettagindex: can't affect free entity\n");
2220 modelindex = (int)ent->fields.server->modelindex;
2222 if (modelindex <= 0 || modelindex > MAX_MODELS)
2223 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2226 tag_index = SV_GetTagIndex(ent, tag_name);
2228 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2230 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2233 //vector(entity ent, float tagindex) gettaginfo;
2234 void PF_gettaginfo (void)
2236 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2237 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2238 matrix4x4_t tag_matrix;
2241 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2242 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2247 PF_WARNING("gettagindex: can't affect world entity\n");
2250 PF_WARNING("gettagindex: can't affect free entity\n");
2253 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2256 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2259 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2264 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2265 void PF_dropclient (void)
2268 client_t *oldhostclient;
2269 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2270 if (clientnum < 0 || clientnum >= svs.maxclients)
2271 PF_WARNING("dropclient: not a client\n");
2272 if (!svs.clients[clientnum].active)
2273 PF_WARNING("dropclient: that client slot is not connected\n");
2274 oldhostclient = host_client;
2275 host_client = svs.clients + clientnum;
2276 SV_DropClient(false);
2277 host_client = oldhostclient;
2280 //entity() spawnclient (DP_SV_BOTCLIENT)
2281 void PF_spawnclient (void)
2285 prog->xfunction->builtinsprofile += 2;
2287 for (i = 0;i < svs.maxclients;i++)
2289 if (!svs.clients[i].active)
2291 prog->xfunction->builtinsprofile += 100;
2292 SV_ConnectClient (i, NULL);
2293 ed = PRVM_EDICT_NUM(i + 1);
2297 VM_RETURN_EDICT(ed);
2300 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2301 void PF_clienttype (void)
2304 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2305 if (clientnum < 0 || clientnum >= svs.maxclients)
2306 PRVM_G_FLOAT(OFS_RETURN) = 3;
2307 else if (!svs.clients[clientnum].active)
2308 PRVM_G_FLOAT(OFS_RETURN) = 0;
2309 else if (svs.clients[clientnum].netconnection)
2310 PRVM_G_FLOAT(OFS_RETURN) = 1;
2312 PRVM_G_FLOAT(OFS_RETURN) = 2;
2315 prvm_builtin_t vm_sv_builtins[] = {
2317 PF_makevectors, // #1 void(entity e) makevectors
2318 PF_setorigin, // #2 void(entity e, vector o) setorigin
2319 PF_setmodel, // #3 void(entity e, string m) setmodel
2320 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2321 NULL, // #5 void(entity e, vector min, vector max) setabssize
2322 VM_break, // #6 void() break
2323 VM_random, // #7 float() random
2324 PF_sound, // #8 void(entity e, float chan, string samp) sound
2325 VM_normalize, // #9 vector(vector v) normalize
2326 VM_error, // #10 void(string e) error
2327 VM_objerror, // #11 void(string e) objerror
2328 VM_vlen, // #12 float(vector v) vlen
2329 VM_vectoyaw, // #13 float(vector v) vectoyaw
2330 VM_spawn, // #14 entity() spawn
2331 VM_remove, // #15 void(entity e) remove
2332 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2333 PF_checkclient, // #17 entity() clientlist
2334 VM_find, // #18 entity(entity start, .string fld, string match) find
2335 PF_precache_sound, // #19 void(string s) precache_sound
2336 PF_precache_model, // #20 void(string s) precache_model
2337 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2338 PF_findradius, // #22 entity(vector org, float rad) findradius
2339 VM_bprint, // #23 void(string s) bprint
2340 PF_sprint, // #24 void(entity client, string s) sprint
2341 VM_dprint, // #25 void(string s) dprint
2342 VM_ftos, // #26 void(string s) ftos
2343 VM_vtos, // #27 void(string s) vtos
2344 VM_coredump, // #28 void() coredump
2345 VM_traceon, // #29 void() traceon
2346 VM_traceoff, // #30 void() traceoff
2347 VM_eprint, // #31 void(entity e) eprint
2348 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2350 PF_droptofloor, // #34 float() droptofloor
2351 PF_lightstyle, // #35 void(float style, string value) lightstyle
2352 VM_rint, // #36 float(float v) rint
2353 VM_floor, // #37 float(float v) floor
2354 VM_ceil, // #38 float(float v) ceil
2356 PF_checkbottom, // #40 float(entity e) checkbottom
2357 PF_pointcontents, // #41 float(vector v) pointcontents
2359 VM_fabs, // #43 float(float f) fabs
2360 PF_aim, // #44 vector(entity e, float speed) aim
2361 VM_cvar, // #45 float(string s) cvar
2362 VM_localcmd, // #46 void(string s) localcmd
2363 VM_nextent, // #47 entity(entity e) nextent
2364 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2365 PF_changeyaw, // #49 void() ChangeYaw
2367 VM_vectoangles, // #51 vector(vector v) vectoangles
2368 PF_WriteByte, // #52 void(float to, float f) WriteByte
2369 PF_WriteChar, // #53 void(float to, float f) WriteChar
2370 PF_WriteShort, // #54 void(float to, float f) WriteShort
2371 PF_WriteLong, // #55 void(float to, float f) WriteLong
2372 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2373 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2374 PF_WriteString, // #58 void(float to, string s) WriteString
2375 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2376 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2377 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2378 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2379 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2380 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2381 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2383 SV_MoveToGoal, // #67 void(float step) movetogoal
2384 PF_precache_file, // #68 string(string s) precache_file
2385 PF_makestatic, // #69 void(entity e) makestatic
2386 VM_changelevel, // #70 void(string s) changelevel
2388 VM_cvar_set, // #72 void(string var, string val) cvar_set
2389 PF_centerprint, // #73 void(entity client, strings) centerprint
2390 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2391 PF_precache_model, // #75 string(string s) precache_model2
2392 PF_precache_sound, // #76 string(string s) precache_sound2
2393 PF_precache_file, // #77 string(string s) precache_file2
2394 PF_setspawnparms, // #78 void(entity e) setspawnparms
2397 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2406 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2407 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2408 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2409 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2410 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2411 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2412 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2413 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2414 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2415 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2426 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2427 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2428 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2429 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2430 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2431 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2432 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2433 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2434 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2435 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2436 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2437 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2438 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2439 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2440 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2441 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2442 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2443 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2444 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2445 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2446 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2447 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2448 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2449 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2450 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2451 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2452 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2453 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2454 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2455 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2456 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2457 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2458 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2459 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2460 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2461 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2462 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2463 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2464 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2465 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2466 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2467 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2468 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2469 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2470 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2471 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2472 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2473 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2474 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2475 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2476 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2477 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2478 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2479 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2480 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2481 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2482 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2483 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2484 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2485 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2486 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2487 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2488 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2489 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2490 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2491 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2492 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2493 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2494 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2495 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2496 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2499 e10, e10, e10, e10 // #460-499 (LordHavoc)
2502 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2504 void VM_SV_Cmd_Init(void)
2509 void VM_SV_Cmd_Reset(void)