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) = SV_PointQ1Contents(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 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1802 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1804 bestdist = 1000000000;
1806 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1808 // clip original point to each triangle of the surface and find the
1809 // triangle that is closest
1810 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1811 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1812 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1813 TriangleNormal(v[0], v[1], v[2], facenormal);
1814 VectorNormalize(facenormal);
1815 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1816 VectorMA(p, offsetdist, facenormal, temp);
1817 for (j = 0, k = 2;j < 3;k = j, j++)
1819 VectorSubtract(v[k], v[j], edgenormal);
1820 CrossProduct(edgenormal, facenormal, sidenormal);
1821 VectorNormalize(sidenormal);
1822 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1824 VectorMA(temp, offsetdist, sidenormal, temp);
1826 dist = VectorDistance2(temp, p);
1827 if (bestdist > dist)
1830 VectorCopy(temp, out);
1835 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
1839 if (!ed || ed->priv.server->free)
1841 modelindex = ed->fields.server->modelindex;
1842 if (modelindex < 1 || modelindex >= MAX_MODELS)
1844 model = sv.models[modelindex];
1845 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
1847 return model->data_surfaces + surfacenum + model->firstmodelsurface;
1851 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
1852 void PF_getsurfacenumpoints(void)
1854 msurface_t *surface;
1855 // return 0 if no such surface
1856 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1858 PRVM_G_FLOAT(OFS_RETURN) = 0;
1862 // note: this (incorrectly) assumes it is a simple polygon
1863 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
1865 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
1866 void PF_getsurfacepoint(void)
1869 msurface_t *surface;
1871 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1872 ed = PRVM_G_EDICT(OFS_PARM0);
1873 if (!ed || ed->priv.server->free)
1875 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1877 // note: this (incorrectly) assumes it is a simple polygon
1878 pointnum = PRVM_G_FLOAT(OFS_PARM2);
1879 if (pointnum < 0 || pointnum >= surface->num_vertices)
1881 // FIXME: implement rotation/scaling
1882 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1884 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
1885 void PF_getsurfacenormal(void)
1887 msurface_t *surface;
1889 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1890 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1892 // FIXME: implement rotation/scaling
1893 // note: this (incorrectly) assumes it is a simple polygon
1894 // note: this only returns the first triangle, so it doesn't work very
1895 // well for curved surfaces or arbitrary meshes
1896 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);
1897 VectorNormalize(normal);
1898 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
1900 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
1901 void PF_getsurfacetexture(void)
1903 msurface_t *surface;
1904 PRVM_G_INT(OFS_RETURN) = 0;
1905 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
1907 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
1909 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
1910 void PF_getsurfacenearpoint(void)
1912 int surfacenum, best, modelindex;
1914 vec_t dist, bestdist;
1917 msurface_t *surface;
1919 PRVM_G_FLOAT(OFS_RETURN) = -1;
1920 ed = PRVM_G_EDICT(OFS_PARM0);
1921 point = PRVM_G_VECTOR(OFS_PARM1);
1923 if (!ed || ed->priv.server->free)
1925 modelindex = ed->fields.server->modelindex;
1926 if (modelindex < 1 || modelindex >= MAX_MODELS)
1928 model = sv.models[modelindex];
1929 if (!model->num_surfaces)
1932 // FIXME: implement rotation/scaling
1933 VectorSubtract(point, ed->fields.server->origin, p);
1935 bestdist = 1000000000;
1936 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
1938 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
1939 // first see if the nearest point on the surface's box is closer than the previous match
1940 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
1941 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
1942 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
1943 dist = VectorLength2(clipped);
1944 if (dist < bestdist)
1946 // it is, check the nearest point on the actual geometry
1947 clippointtosurface(surface, p, clipped);
1948 VectorSubtract(clipped, p, clipped);
1949 dist += VectorLength2(clipped);
1950 if (dist < bestdist)
1952 // that's closer too, store it as the best match
1958 PRVM_G_FLOAT(OFS_RETURN) = best;
1960 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
1961 void PF_getsurfaceclippedpoint(void)
1964 msurface_t *surface;
1966 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
1967 ed = PRVM_G_EDICT(OFS_PARM0);
1968 if (!ed || ed->priv.server->free)
1970 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
1972 // FIXME: implement rotation/scaling
1973 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
1974 clippointtosurface(surface, p, out);
1975 // FIXME: implement rotation/scaling
1976 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
1979 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
1980 //this function originally written by KrimZon, made shorter by LordHavoc
1981 void PF_clientcommand (void)
1983 client_t *temp_client;
1986 //find client for this entity
1987 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
1988 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
1990 Con_Print("PF_clientcommand: entity is not a client\n");
1994 temp_client = host_client;
1995 host_client = svs.clients + i;
1996 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
1997 host_client = temp_client;
2000 //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)
2001 void PF_setattachment (void)
2003 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2004 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2005 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2010 if (e == prog->edicts)
2011 PF_WARNING("setattachment: can not modify world entity\n");
2012 if (e->priv.server->free)
2013 PF_WARNING("setattachment: can not modify free entity\n");
2015 if (tagentity == NULL)
2016 tagentity = prog->edicts;
2018 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2020 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2022 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2025 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2027 modelindex = (int)tagentity->fields.server->modelindex;
2028 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2030 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2032 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);
2035 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));
2039 /////////////////////////////////////////
2040 // DP_MD3_TAGINFO extension coded by VorteX
2042 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2047 i = e->fields.server->modelindex;
2048 if (i < 1 || i >= MAX_MODELS)
2050 model = sv.models[i];
2052 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2055 // Warnings/errors code:
2056 // 0 - normal (everything all-right)
2059 // 3 - null or non-precached model
2060 // 4 - no tags with requested index
2061 // 5 - runaway loop at attachment chain
2062 extern cvar_t cl_bob;
2063 extern cvar_t cl_bobcycle;
2064 extern cvar_t cl_bobup;
2065 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2068 int modelindex, reqframe, attachloop;
2069 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2070 prvm_edict_t *attachent;
2073 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2075 if (ent == prog->edicts)
2077 if (ent->priv.server->free)
2080 modelindex = (int)ent->fields.server->modelindex;
2081 if (modelindex <= 0 || modelindex > MAX_MODELS)
2084 model = sv.models[modelindex];
2086 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
2087 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
2089 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
2091 // get initial tag matrix
2094 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
2099 Matrix4x4_CreateIdentity(&tagmatrix);
2101 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2102 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2106 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
2107 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
2108 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)
2109 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
2111 Matrix4x4_CreateIdentity(&attachmatrix);
2113 // apply transformation by child entity matrix
2114 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2115 if (val->_float == 0)
2117 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);
2118 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2119 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]);
2120 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]);
2121 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]);
2122 Matrix4x4_Copy(&tagmatrix, out);
2124 // finally transformate by matrix of tag on parent entity
2125 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2126 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];
2127 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];
2128 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];
2129 Matrix4x4_Copy(&tagmatrix, out);
2133 if (attachloop > 255) // prevent runaway looping
2136 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
2139 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
2140 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2141 if (val->_float == 0)
2143 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
2144 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);
2145 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2146 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]);
2147 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]);
2148 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]);
2150 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2151 {// RENDER_VIEWMODEL magic
2152 Matrix4x4_Copy(&tagmatrix, out);
2153 ent = PRVM_EDICT_NUM(val->edict);
2155 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
2156 if (val->_float == 0)
2159 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], val->_float);
2160 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2161 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
2162 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
2163 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
2166 // Cl_bob, ported from rendering code
2167 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2170 // LordHavoc: this code is *weird*, but not replacable (I think it
2171 // should be done in QC on the server, but oh well, quake is quake)
2172 // LordHavoc: figured out bobup: the time at which the sin is at 180
2173 // degrees (which allows lengthening or squishing the peak or valley)
2174 cycle = sv.time/cl_bobcycle.value;
2175 cycle -= (int)cycle;
2176 if (cycle < cl_bobup.value)
2177 cycle = sin(M_PI * cycle / cl_bobup.value);
2179 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2180 // bob is proportional to velocity in the xy plane
2181 // (don't count Z, or jumping messes it up)
2182 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;
2183 bob = bob*0.3 + bob*0.7*cycle;
2184 out->m[2][3] += bound(-7, bob, 4);
2191 //float(entity ent, string tagname) gettagindex;
2193 void PF_gettagindex (void)
2195 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2196 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2197 int modelindex, tag_index;
2199 if (ent == prog->edicts)
2200 PF_WARNING("gettagindex: can't affect world entity\n");
2201 if (ent->priv.server->free)
2202 PF_WARNING("gettagindex: can't affect free entity\n");
2204 modelindex = (int)ent->fields.server->modelindex;
2206 if (modelindex <= 0 || modelindex > MAX_MODELS)
2207 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2210 tag_index = SV_GetTagIndex(ent, tag_name);
2212 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2214 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2217 //vector(entity ent, float tagindex) gettaginfo;
2218 void PF_gettaginfo (void)
2220 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2221 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2222 matrix4x4_t tag_matrix;
2225 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2226 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2231 PF_WARNING("gettagindex: can't affect world entity\n");
2234 PF_WARNING("gettagindex: can't affect free entity\n");
2237 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2240 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2243 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2248 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2249 void PF_dropclient (void)
2252 client_t *oldhostclient;
2253 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2254 if (clientnum < 0 || clientnum >= svs.maxclients)
2255 PF_WARNING("dropclient: not a client\n");
2256 if (!svs.clients[clientnum].active)
2257 PF_WARNING("dropclient: that client slot is not connected\n");
2258 oldhostclient = host_client;
2259 host_client = svs.clients + clientnum;
2260 SV_DropClient(false);
2261 host_client = oldhostclient;
2264 //entity() spawnclient (DP_SV_BOTCLIENT)
2265 void PF_spawnclient (void)
2269 prog->xfunction->builtinsprofile += 2;
2271 for (i = 0;i < svs.maxclients;i++)
2273 if (!svs.clients[i].active)
2275 prog->xfunction->builtinsprofile += 100;
2276 SV_ConnectClient (i, NULL);
2277 ed = PRVM_EDICT_NUM(i + 1);
2281 VM_RETURN_EDICT(ed);
2284 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2285 void PF_clienttype (void)
2288 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2289 if (clientnum < 0 || clientnum >= svs.maxclients)
2290 PRVM_G_FLOAT(OFS_RETURN) = 3;
2291 else if (!svs.clients[clientnum].active)
2292 PRVM_G_FLOAT(OFS_RETURN) = 0;
2293 else if (svs.clients[clientnum].netconnection)
2294 PRVM_G_FLOAT(OFS_RETURN) = 1;
2296 PRVM_G_FLOAT(OFS_RETURN) = 2;
2299 prvm_builtin_t vm_sv_builtins[] = {
2301 PF_makevectors, // #1 void(entity e) makevectors
2302 PF_setorigin, // #2 void(entity e, vector o) setorigin
2303 PF_setmodel, // #3 void(entity e, string m) setmodel
2304 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2305 NULL, // #5 void(entity e, vector min, vector max) setabssize
2306 VM_break, // #6 void() break
2307 VM_random, // #7 float() random
2308 PF_sound, // #8 void(entity e, float chan, string samp) sound
2309 VM_normalize, // #9 vector(vector v) normalize
2310 VM_error, // #10 void(string e) error
2311 VM_objerror, // #11 void(string e) objerror
2312 VM_vlen, // #12 float(vector v) vlen
2313 VM_vectoyaw, // #13 float(vector v) vectoyaw
2314 VM_spawn, // #14 entity() spawn
2315 VM_remove, // #15 void(entity e) remove
2316 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2317 PF_checkclient, // #17 entity() clientlist
2318 VM_find, // #18 entity(entity start, .string fld, string match) find
2319 PF_precache_sound, // #19 void(string s) precache_sound
2320 PF_precache_model, // #20 void(string s) precache_model
2321 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2322 PF_findradius, // #22 entity(vector org, float rad) findradius
2323 VM_bprint, // #23 void(string s) bprint
2324 PF_sprint, // #24 void(entity client, string s) sprint
2325 VM_dprint, // #25 void(string s) dprint
2326 VM_ftos, // #26 void(string s) ftos
2327 VM_vtos, // #27 void(string s) vtos
2328 VM_coredump, // #28 void() coredump
2329 VM_traceon, // #29 void() traceon
2330 VM_traceoff, // #30 void() traceoff
2331 VM_eprint, // #31 void(entity e) eprint
2332 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2334 PF_droptofloor, // #34 float() droptofloor
2335 PF_lightstyle, // #35 void(float style, string value) lightstyle
2336 VM_rint, // #36 float(float v) rint
2337 VM_floor, // #37 float(float v) floor
2338 VM_ceil, // #38 float(float v) ceil
2340 PF_checkbottom, // #40 float(entity e) checkbottom
2341 PF_pointcontents, // #41 float(vector v) pointcontents
2343 VM_fabs, // #43 float(float f) fabs
2344 PF_aim, // #44 vector(entity e, float speed) aim
2345 VM_cvar, // #45 float(string s) cvar
2346 VM_localcmd, // #46 void(string s) localcmd
2347 VM_nextent, // #47 entity(entity e) nextent
2348 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2349 PF_changeyaw, // #49 void() ChangeYaw
2351 VM_vectoangles, // #51 vector(vector v) vectoangles
2352 PF_WriteByte, // #52 void(float to, float f) WriteByte
2353 PF_WriteChar, // #53 void(float to, float f) WriteChar
2354 PF_WriteShort, // #54 void(float to, float f) WriteShort
2355 PF_WriteLong, // #55 void(float to, float f) WriteLong
2356 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2357 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2358 PF_WriteString, // #58 void(float to, string s) WriteString
2359 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2360 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2361 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2362 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2363 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2364 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2365 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2367 SV_MoveToGoal, // #67 void(float step) movetogoal
2368 PF_precache_file, // #68 string(string s) precache_file
2369 PF_makestatic, // #69 void(entity e) makestatic
2370 VM_changelevel, // #70 void(string s) changelevel
2372 VM_cvar_set, // #72 void(string var, string val) cvar_set
2373 PF_centerprint, // #73 void(entity client, strings) centerprint
2374 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2375 PF_precache_model, // #75 string(string s) precache_model2
2376 PF_precache_sound, // #76 string(string s) precache_sound2
2377 PF_precache_file, // #77 string(string s) precache_file2
2378 PF_setspawnparms, // #78 void(entity e) setspawnparms
2381 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2390 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2391 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2392 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2393 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2394 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2395 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2396 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2397 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2398 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2399 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2410 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2411 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2412 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2413 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2414 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2415 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2416 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2417 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2418 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2419 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2420 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2421 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299
2422 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2423 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2424 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2425 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2426 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2427 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2428 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2429 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2430 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2431 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2432 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2433 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2434 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2435 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2436 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2437 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2438 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2439 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2440 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2441 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2442 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2443 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2444 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2445 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2446 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2447 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2448 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2449 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2450 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2451 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2452 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2453 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2454 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2455 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2456 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2457 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2458 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2459 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2460 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2461 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2462 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2463 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2464 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2465 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2466 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2467 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2468 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2469 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2470 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2471 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2472 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2473 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2474 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2475 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2476 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2477 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2478 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2479 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2483 e10, e10, e10, e10 // #460-499 (LordHavoc)
2486 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2488 void VM_SV_Cmd_Init(void)
2493 void VM_SV_Cmd_Reset(void)