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 "
31 "DP_ENT_CUSTOMCOLORMAP "
32 "DP_ENT_EXTERIORMODELTOCLIENT "
34 "DP_ENT_LOWPRECISION "
37 "DP_GFX_EXTERNALTEXTURES "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
56 "DP_QC_FINDCHAINFLAGS "
57 "DP_QC_FINDCHAINFLOAT "
60 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
65 "DP_QC_MULTIPLETEMPSTRINGS "
67 "DP_QC_SINCOSSQRTPOW "
68 "DP_QC_STRINGBUFFERS "
71 "DP_QC_TRACE_MOVETYPE_HITMODEL "
72 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
73 "DP_QC_VECTORVECTORS "
79 "DP_SND_DIRECTIONLESSATTNNONE "
88 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
89 "DP_SV_DRAWONLYTOCLIENT "
92 "DP_SV_NODRAWTOCLIENT "
94 "DP_SV_PLAYERPHYSICS "
95 "DP_SV_PRECACHEANYTIME "
97 "DP_SV_ROTATINGBMODEL "
100 "DP_SV_WRITEUNTERMINATEDSTRING "
104 "DP_TE_EXPLOSIONRGB "
106 "DP_TE_PARTICLECUBE "
107 "DP_TE_PARTICLERAIN "
108 "DP_TE_PARTICLESNOW "
110 "DP_TE_QUADEFFECTS1 "
113 "DP_TE_STANDARDEFFECTBUILTINS "
116 //"EXT_CSQC " // not ready yet
118 "KRIMZON_SV_PARSECLIENTCOMMAND "
122 "PRYDON_CLIENTCURSOR "
123 "TENEBRAE_GFX_DLIGHTS "
125 "NEXUIZ_PLAYERMODEL "
132 Writes new values for v_forward, v_up, and v_right based on angles
136 void PF_makevectors (void)
138 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
145 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.
147 setorigin (entity, origin)
150 void PF_setorigin (void)
155 e = PRVM_G_EDICT(OFS_PARM0);
156 if (e == prog->edicts)
157 PF_WARNING("setorigin: can not modify world entity\n");
158 if (e->priv.server->free)
159 PF_WARNING("setorigin: can not modify free entity\n");
160 org = PRVM_G_VECTOR(OFS_PARM1);
161 VectorCopy (org, e->fields.server->origin);
162 SV_LinkEdict (e, false);
166 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
170 for (i=0 ; i<3 ; i++)
172 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
174 // set derived values
175 VectorCopy (min, e->fields.server->mins);
176 VectorCopy (max, e->fields.server->maxs);
177 VectorSubtract (max, min, e->fields.server->size);
179 SV_LinkEdict (e, false);
186 the size box is rotated by the current angle
187 LordHavoc: no it isn't...
189 setsize (entity, minvector, maxvector)
192 void PF_setsize (void)
197 e = PRVM_G_EDICT(OFS_PARM0);
198 if (e == prog->edicts)
199 PF_WARNING("setsize: can not modify world entity\n");
200 if (e->priv.server->free)
201 PF_WARNING("setsize: can not modify free entity\n");
202 min = PRVM_G_VECTOR(OFS_PARM1);
203 max = PRVM_G_VECTOR(OFS_PARM2);
204 SetMinMaxSize (e, min, max, false);
212 setmodel(entity, model)
215 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
216 void PF_setmodel (void)
222 e = PRVM_G_EDICT(OFS_PARM0);
223 if (e == prog->edicts)
224 PF_WARNING("setmodel: can not modify world entity\n");
225 if (e->priv.server->free)
226 PF_WARNING("setmodel: can not modify free entity\n");
227 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
228 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
229 e->fields.server->modelindex = i;
235 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
236 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
238 SetMinMaxSize (e, quakemins, quakemaxs, true);
241 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
248 single print to a specific client
250 sprint(clientent, value)
253 void PF_sprint (void)
257 char string[VM_STRINGTEMP_LENGTH];
259 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
261 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
263 Con_Print("tried to sprint to a non-client\n");
267 client = svs.clients + entnum-1;
268 VM_VarString(1, string, sizeof(string));
269 MSG_WriteChar(&client->message,svc_print);
270 MSG_WriteString(&client->message, string);
278 single print to a specific client
280 centerprint(clientent, value)
283 void PF_centerprint (void)
287 char string[VM_STRINGTEMP_LENGTH];
289 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
291 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
293 Con_Print("tried to sprint to a non-client\n");
297 client = svs.clients + entnum-1;
298 VM_VarString(1, string, sizeof(string));
299 MSG_WriteChar(&client->message,svc_centerprint);
300 MSG_WriteString(&client->message, string);
307 particle(origin, color, count)
310 void PF_particle (void)
316 org = PRVM_G_VECTOR(OFS_PARM0);
317 dir = PRVM_G_VECTOR(OFS_PARM1);
318 color = PRVM_G_FLOAT(OFS_PARM2);
319 count = PRVM_G_FLOAT(OFS_PARM3);
320 SV_StartParticle (org, dir, color, count);
330 void PF_ambientsound (void)
334 float vol, attenuation;
337 pos = PRVM_G_VECTOR (OFS_PARM0);
338 samp = PRVM_G_STRING(OFS_PARM1);
339 vol = PRVM_G_FLOAT(OFS_PARM2);
340 attenuation = PRVM_G_FLOAT(OFS_PARM3);
342 // check to see if samp was properly precached
343 soundnum = SV_SoundIndex(samp, 1);
351 // add an svc_spawnambient command to the level signon packet
354 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
356 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
358 MSG_WriteVector(&sv.signon, pos, sv.protocol);
361 MSG_WriteShort (&sv.signon, soundnum);
363 MSG_WriteByte (&sv.signon, soundnum);
365 MSG_WriteByte (&sv.signon, vol*255);
366 MSG_WriteByte (&sv.signon, attenuation*64);
374 Each entity can have eight independant sound sources, like voice,
377 Channel 0 is an auto-allocate channel, the others override anything
378 already running on that entity/channel pair.
380 An attenuation of 0 will play full volume everywhere in the level.
381 Larger attenuations will drop off.
389 prvm_edict_t *entity;
393 entity = PRVM_G_EDICT(OFS_PARM0);
394 channel = PRVM_G_FLOAT(OFS_PARM1);
395 sample = PRVM_G_STRING(OFS_PARM2);
396 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
397 attenuation = PRVM_G_FLOAT(OFS_PARM4);
399 if (volume < 0 || volume > 255)
400 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
402 if (attenuation < 0 || attenuation > 4)
403 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
405 if (channel < 0 || channel > 7)
406 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
408 SV_StartSound (entity, channel, sample, volume, attenuation);
415 Used for use tracing and shot targeting
416 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
417 if the tryents flag is set.
419 traceline (vector1, vector2, tryents)
422 void PF_traceline (void)
429 prog->xfunction->builtinsprofile += 30;
431 v1 = PRVM_G_VECTOR(OFS_PARM0);
432 v2 = PRVM_G_VECTOR(OFS_PARM1);
433 move = PRVM_G_FLOAT(OFS_PARM2);
434 ent = PRVM_G_EDICT(OFS_PARM3);
436 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
438 prog->globals.server->trace_allsolid = trace.allsolid;
439 prog->globals.server->trace_startsolid = trace.startsolid;
440 prog->globals.server->trace_fraction = trace.fraction;
441 prog->globals.server->trace_inwater = trace.inwater;
442 prog->globals.server->trace_inopen = trace.inopen;
443 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
444 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
445 prog->globals.server->trace_plane_dist = trace.plane.dist;
447 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
449 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
450 // FIXME: add trace_endcontents
458 Used for use tracing and shot targeting
459 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
460 if the tryents flag is set.
462 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
465 // LordHavoc: added this for my own use, VERY useful, similar to traceline
466 void PF_tracebox (void)
468 float *v1, *v2, *m1, *m2;
473 prog->xfunction->builtinsprofile += 30;
475 v1 = PRVM_G_VECTOR(OFS_PARM0);
476 m1 = PRVM_G_VECTOR(OFS_PARM1);
477 m2 = PRVM_G_VECTOR(OFS_PARM2);
478 v2 = PRVM_G_VECTOR(OFS_PARM3);
479 move = PRVM_G_FLOAT(OFS_PARM4);
480 ent = PRVM_G_EDICT(OFS_PARM5);
482 trace = SV_Move (v1, m1, m2, v2, move, ent);
484 prog->globals.server->trace_allsolid = trace.allsolid;
485 prog->globals.server->trace_startsolid = trace.startsolid;
486 prog->globals.server->trace_fraction = trace.fraction;
487 prog->globals.server->trace_inwater = trace.inwater;
488 prog->globals.server->trace_inopen = trace.inopen;
489 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
490 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
491 prog->globals.server->trace_plane_dist = trace.plane.dist;
493 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
495 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
498 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
499 void PF_tracetoss (void)
503 prvm_edict_t *ignore;
505 prog->xfunction->builtinsprofile += 600;
507 ent = PRVM_G_EDICT(OFS_PARM0);
508 if (ent == prog->edicts)
509 PF_WARNING("tracetoss: can not use world entity\n");
510 ignore = PRVM_G_EDICT(OFS_PARM1);
512 trace = SV_Trace_Toss (ent, ignore);
514 prog->globals.server->trace_allsolid = trace.allsolid;
515 prog->globals.server->trace_startsolid = trace.startsolid;
516 prog->globals.server->trace_fraction = trace.fraction;
517 prog->globals.server->trace_inwater = trace.inwater;
518 prog->globals.server->trace_inopen = trace.inopen;
519 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
520 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
521 prog->globals.server->trace_plane_dist = trace.plane.dist;
523 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
525 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
533 Returns true if the given entity can move to the given position from it's
534 current position by walking or rolling.
536 scalar checkpos (entity, vector)
539 void PF_checkpos (void)
543 //============================================================================
546 unsigned char checkpvs[MAX_MAP_LEAFS/8];
548 int PF_newcheckclient (int check)
554 // cycle to the next one
556 check = bound(1, check, svs.maxclients);
557 if (check == svs.maxclients)
565 prog->xfunction->builtinsprofile++;
567 if (i == svs.maxclients+1)
569 // look up the client's edict
570 ent = PRVM_EDICT_NUM(i);
571 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
572 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
574 // found a valid client (possibly the same one again)
578 // get the PVS for the entity
579 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
581 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
582 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
591 Returns a client (or object that has a client enemy) that would be a
594 If there is more than one valid option, they are cycled each frame
596 If (self.origin + self.viewofs) is not in the PVS of the current target,
597 it is not returned at all.
602 int c_invis, c_notvis;
603 void PF_checkclient (void)
605 prvm_edict_t *ent, *self;
608 // find a new check if on a new frame
609 if (sv.time - sv.lastchecktime >= 0.1)
611 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
612 sv.lastchecktime = sv.time;
615 // return check if it might be visible
616 ent = PRVM_EDICT_NUM(sv.lastcheck);
617 if (ent->priv.server->free || ent->fields.server->health <= 0)
619 VM_RETURN_EDICT(prog->edicts);
623 // if current entity can't possibly see the check entity, return 0
624 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
625 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
626 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
629 VM_RETURN_EDICT(prog->edicts);
633 // might be able to see it
635 VM_RETURN_EDICT(ent);
638 //============================================================================
645 Sends text over to the client's execution buffer
647 stuffcmd (clientent, value, ...)
650 void PF_stuffcmd (void)
654 char string[VM_STRINGTEMP_LENGTH];
656 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
657 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
659 Con_Print("Can't stuffcmd to a non-client\n");
663 VM_VarString(1, string, sizeof(string));
666 host_client = svs.clients + entnum-1;
667 Host_ClientCommands ("%s", string);
675 Returns a chain of entities that have origins within a spherical area
677 findradius (origin, radius)
680 void PF_findradius (void)
682 prvm_edict_t *ent, *chain;
683 vec_t radius, radius2;
684 vec3_t org, eorg, mins, maxs;
687 prvm_edict_t *touchedicts[MAX_EDICTS];
689 chain = (prvm_edict_t *)prog->edicts;
691 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
692 radius = PRVM_G_FLOAT(OFS_PARM1);
693 radius2 = radius * radius;
695 mins[0] = org[0] - (radius + 1);
696 mins[1] = org[1] - (radius + 1);
697 mins[2] = org[2] - (radius + 1);
698 maxs[0] = org[0] + (radius + 1);
699 maxs[1] = org[1] + (radius + 1);
700 maxs[2] = org[2] + (radius + 1);
701 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
702 if (numtouchedicts > MAX_EDICTS)
704 // this never happens
705 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
706 numtouchedicts = MAX_EDICTS;
708 for (i = 0;i < numtouchedicts;i++)
710 ent = touchedicts[i];
711 prog->xfunction->builtinsprofile++;
712 // Quake did not return non-solid entities but darkplaces does
713 // (note: this is the reason you can't blow up fallen zombies)
714 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
716 // LordHavoc: compare against bounding box rather than center so it
717 // doesn't miss large objects, and use DotProduct instead of Length
718 // for a major speedup
719 VectorSubtract(org, ent->fields.server->origin, eorg);
720 if (sv_gameplayfix_findradiusdistancetobox.integer)
722 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
723 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
724 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
727 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
728 if (DotProduct(eorg, eorg) < radius2)
730 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
735 VM_RETURN_EDICT(chain);
738 void PF_precache_file (void)
739 { // precache_file is only used to copy files with qcc, it does nothing
740 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
744 void PF_precache_sound (void)
746 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
747 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
750 void PF_precache_model (void)
752 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
753 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
760 float(float yaw, float dist) walkmove
763 void PF_walkmove (void)
771 // assume failure if it returns early
772 PRVM_G_FLOAT(OFS_RETURN) = 0;
774 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
775 if (ent == prog->edicts)
776 PF_WARNING("walkmove: can not modify world entity\n");
777 if (ent->priv.server->free)
778 PF_WARNING("walkmove: can not modify free entity\n");
779 yaw = PRVM_G_FLOAT(OFS_PARM0);
780 dist = PRVM_G_FLOAT(OFS_PARM1);
782 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
785 yaw = yaw*M_PI*2 / 360;
787 move[0] = cos(yaw)*dist;
788 move[1] = sin(yaw)*dist;
791 // save program state, because SV_movestep may call other progs
792 oldf = prog->xfunction;
793 oldself = prog->globals.server->self;
795 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
798 // restore program state
799 prog->xfunction = oldf;
800 prog->globals.server->self = oldself;
810 void PF_droptofloor (void)
816 // assume failure if it returns early
817 PRVM_G_FLOAT(OFS_RETURN) = 0;
819 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
820 if (ent == prog->edicts)
821 PF_WARNING("droptofloor: can not modify world entity\n");
822 if (ent->priv.server->free)
823 PF_WARNING("droptofloor: can not modify free entity\n");
825 VectorCopy (ent->fields.server->origin, end);
828 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
830 if (trace.fraction != 1)
832 VectorCopy (trace.endpos, ent->fields.server->origin);
833 SV_LinkEdict (ent, false);
834 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
835 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
836 PRVM_G_FLOAT(OFS_RETURN) = 1;
837 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
838 ent->priv.server->suspendedinairflag = true;
846 void(float style, string value) lightstyle
849 void PF_lightstyle (void)
856 style = PRVM_G_FLOAT(OFS_PARM0);
857 val = PRVM_G_STRING(OFS_PARM1);
859 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
860 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
863 // change the string in sv
864 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
866 // send message to all clients on this server
867 if (sv.state != ss_active)
870 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
874 MSG_WriteChar (&client->message, svc_lightstyle);
875 MSG_WriteChar (&client->message,style);
876 MSG_WriteString (&client->message, val);
886 void PF_checkbottom (void)
888 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
896 void PF_pointcontents (void)
898 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
905 Pick a vector for the player to shoot along
906 vector aim(entity, missilespeed)
911 prvm_edict_t *ent, *check, *bestent;
912 vec3_t start, dir, end, bestdir;
915 float dist, bestdist;
918 // assume failure if it returns early
919 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
920 // if sv_aim is so high it can't possibly accept anything, skip out early
921 if (sv_aim.value >= 1)
924 ent = PRVM_G_EDICT(OFS_PARM0);
925 if (ent == prog->edicts)
926 PF_WARNING("aim: can not use world entity\n");
927 if (ent->priv.server->free)
928 PF_WARNING("aim: can not use free entity\n");
929 speed = PRVM_G_FLOAT(OFS_PARM1);
931 VectorCopy (ent->fields.server->origin, start);
934 // try sending a trace straight
935 VectorCopy (prog->globals.server->v_forward, dir);
936 VectorMA (start, 2048, dir, end);
937 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
938 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
939 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
941 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
946 // try all possible entities
947 VectorCopy (dir, bestdir);
948 bestdist = sv_aim.value;
951 check = PRVM_NEXT_EDICT(prog->edicts);
952 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
954 prog->xfunction->builtinsprofile++;
955 if (check->fields.server->takedamage != DAMAGE_AIM)
959 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
960 continue; // don't aim at teammate
961 for (j=0 ; j<3 ; j++)
962 end[j] = check->fields.server->origin[j]
963 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
964 VectorSubtract (end, start, dir);
965 VectorNormalize (dir);
966 dist = DotProduct (dir, prog->globals.server->v_forward);
968 continue; // to far to turn
969 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
971 { // can shoot at this one
979 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
980 dist = DotProduct (dir, prog->globals.server->v_forward);
981 VectorScale (prog->globals.server->v_forward, dist, end);
983 VectorNormalize (end);
984 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
988 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
996 This was a major timewaster in progs, so it was converted to C
999 void PF_changeyaw (void)
1002 float ideal, current, move, speed;
1004 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1005 if (ent == prog->edicts)
1006 PF_WARNING("changeyaw: can not modify world entity\n");
1007 if (ent->priv.server->free)
1008 PF_WARNING("changeyaw: can not modify free entity\n");
1009 current = ANGLEMOD(ent->fields.server->angles[1]);
1010 ideal = ent->fields.server->ideal_yaw;
1011 speed = ent->fields.server->yaw_speed;
1013 if (current == ideal)
1015 move = ideal - current;
1016 if (ideal > current)
1037 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1045 void PF_changepitch (void)
1048 float ideal, current, move, speed;
1051 ent = PRVM_G_EDICT(OFS_PARM0);
1052 if (ent == prog->edicts)
1053 PF_WARNING("changepitch: can not modify world entity\n");
1054 if (ent->priv.server->free)
1055 PF_WARNING("changepitch: can not modify free entity\n");
1056 current = ANGLEMOD( ent->fields.server->angles[0] );
1057 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1058 ideal = val->_float;
1061 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1064 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1065 speed = val->_float;
1068 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1072 if (current == ideal)
1074 move = ideal - current;
1075 if (ideal > current)
1096 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1100 ===============================================================================
1104 ===============================================================================
1107 #define MSG_BROADCAST 0 // unreliable to all
1108 #define MSG_ONE 1 // reliable to one (msg_entity)
1109 #define MSG_ALL 2 // reliable to all
1110 #define MSG_INIT 3 // write to the init string
1111 #define MSG_ENTITY 5
1113 sizebuf_t *WriteDest (void)
1118 extern sizebuf_t *sv2csqcbuf;
1120 dest = PRVM_G_FLOAT(OFS_PARM0);
1124 return &sv.datagram;
1127 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1128 entnum = PRVM_NUM_FOR_EDICT(ent);
1129 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1131 Con_Printf ("WriteDest: tried to write to non-client\n");
1132 return &sv.reliable_datagram;
1135 return &svs.clients[entnum-1].message;
1138 Con_Printf ("WriteDest: bad destination\n");
1140 return &sv.reliable_datagram;
1152 void PF_WriteByte (void)
1154 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1157 void PF_WriteChar (void)
1159 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1162 void PF_WriteShort (void)
1164 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1167 void PF_WriteLong (void)
1169 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1172 void PF_WriteAngle (void)
1174 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1177 void PF_WriteCoord (void)
1179 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1182 void PF_WriteString (void)
1184 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1187 void PF_WriteUnterminatedString (void)
1189 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1193 void PF_WriteEntity (void)
1195 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1198 //////////////////////////////////////////////////////////
1200 void PF_makestatic (void)
1205 ent = PRVM_G_EDICT(OFS_PARM0);
1206 if (ent == prog->edicts)
1207 PF_WARNING("makestatic: can not modify world entity\n");
1208 if (ent->priv.server->free)
1209 PF_WARNING("makestatic: can not modify free entity\n");
1212 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1217 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1218 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1219 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1223 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1224 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1225 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1228 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1229 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1230 for (i=0 ; i<3 ; i++)
1232 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1233 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1236 // throw the entity away now
1240 //=============================================================================
1247 void PF_setspawnparms (void)
1253 ent = PRVM_G_EDICT(OFS_PARM0);
1254 i = PRVM_NUM_FOR_EDICT(ent);
1255 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1257 Con_Print("tried to setspawnparms on a non-client\n");
1261 // copy spawn parms out of the client_t
1262 client = svs.clients + i-1;
1263 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1264 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1271 Returns a color vector indicating the lighting at the requested point.
1273 (Internal Operation note: actually measures the light beneath the point, just like
1274 the model lighting on the client)
1279 void PF_getlight (void)
1281 vec3_t ambientcolor, diffusecolor, diffusenormal;
1283 p = PRVM_G_VECTOR(OFS_PARM0);
1284 VectorClear(ambientcolor);
1285 VectorClear(diffusecolor);
1286 VectorClear(diffusenormal);
1287 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1288 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1289 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1292 void PF_registercvar (void)
1294 const char *name, *value;
1295 name = PRVM_G_STRING(OFS_PARM0);
1296 value = PRVM_G_STRING(OFS_PARM1);
1297 PRVM_G_FLOAT(OFS_RETURN) = 0;
1299 // first check to see if it has already been defined
1300 if (Cvar_FindVar (name))
1303 // check for overlap with a command
1304 if (Cmd_Exists (name))
1306 Con_Printf("PF_registercvar: %s is a command\n", name);
1310 Cvar_Get(name, value, 0);
1312 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1317 unsigned char type; // 1/2/8 or other value if isn't used
1321 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1322 static int vm_autosentstats_last;
1324 void VM_AutoSentStats_Clear (void)
1326 if(vm_autosentstats)
1328 free(vm_autosentstats);
1329 vm_autosentstats = NULL;
1330 vm_autosentstats_last = -1;
1334 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1335 #define VM_SENDSTAT(a,b,c)\
1338 if((c)==(unsigned char)(c))\
1340 MSG_WriteByte((a), svc_updatestatubyte);\
1341 MSG_WriteByte((a), (b));\
1342 MSG_WriteByte((a), (c));\
1346 MSG_WriteByte((a), svc_updatestat);\
1347 MSG_WriteByte((a), (b));\
1348 MSG_WriteLong((a), (c));\
1352 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1364 if(!vm_autosentstats)
1367 send = (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5);
1369 for(i=0; i<vm_autosentstats_last+1 ;i++)
1371 if(!vm_autosentstats[i].type)
1373 switch(vm_autosentstats[i].type)
1377 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1385 stats[i+32] = si[0];
1386 stats[i+33] = si[1];
1387 stats[i+34] = si[2];
1388 stats[i+35] = si[3];
1392 VM_SENDSTAT(msg, i+32, si[0]);
1393 VM_SENDSTAT(msg, i+33, si[1]);
1394 VM_SENDSTAT(msg, i+34, si[2]);
1395 VM_SENDSTAT(msg, i+35, si[3]);
1401 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1402 k.i = LittleLong (k.i);
1406 VM_SENDSTAT(msg, i+32, k.i);
1410 v = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1414 VM_SENDSTAT(msg, i+32, v);
1422 // void(float index, float type, .void field) SV_AddStat = #470;
1423 // Set up an auto-sent player stat.
1424 // Client's get thier own fields sent to them. Index may not be less than 32.
1425 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1426 // 1: string (4 stats carrying a total of 16 charactures)
1427 // 2: float (one stat, float converted to an integer for transportation)
1428 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1429 void PF_SV_AddStat (void)
1434 if(!vm_autosentstats)
1436 vm_autosentstats = malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1437 if(!vm_autosentstats)
1439 Con_Printf("PF_SV_AddStat: not enough memory\n");
1443 i = PRVM_G_FLOAT(OFS_PARM0);
1444 type = PRVM_G_FLOAT(OFS_PARM1);
1445 off = PRVM_G_INT (OFS_PARM2);
1450 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1453 if(i >= (MAX_CL_STATS-32))
1455 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1458 if(i > (MAX_CL_STATS-32-4) && type == 1)
1460 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1463 vm_autosentstats[i].type = type;
1464 vm_autosentstats[i].fieldoffset = off;
1465 if(vm_autosentstats_last < i)
1466 vm_autosentstats_last = i;
1473 copies data from one entity to another
1475 copyentity(src, dst)
1478 void PF_copyentity (void)
1480 prvm_edict_t *in, *out;
1481 in = PRVM_G_EDICT(OFS_PARM0);
1482 if (in == prog->edicts)
1483 PF_WARNING("copyentity: can not read world entity\n");
1484 if (in->priv.server->free)
1485 PF_WARNING("copyentity: can not read free entity\n");
1486 out = PRVM_G_EDICT(OFS_PARM1);
1487 if (out == prog->edicts)
1488 PF_WARNING("copyentity: can not modify world entity\n");
1489 if (out->priv.server->free)
1490 PF_WARNING("copyentity: can not modify free entity\n");
1491 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1499 sets the color of a client and broadcasts the update to all connected clients
1501 setcolor(clientent, value)
1504 void PF_setcolor (void)
1510 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1511 i = PRVM_G_FLOAT(OFS_PARM1);
1513 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1515 Con_Print("tried to setcolor a non-client\n");
1519 client = svs.clients + entnum-1;
1522 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1524 client->edict->fields.server->team = (i & 15) + 1;
1527 if (client->old_colors != client->colors)
1529 client->old_colors = client->colors;
1530 // send notification to all clients
1531 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1532 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1533 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1541 effect(origin, modelname, startframe, framecount, framerate)
1544 void PF_effect (void)
1548 s = PRVM_G_STRING(OFS_PARM1);
1550 PF_WARNING("effect: no model specified\n");
1552 i = SV_ModelIndex(s, 1);
1554 PF_WARNING("effect: model not precached\n");
1555 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1558 void PF_te_blood (void)
1560 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1562 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1563 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1565 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1569 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1570 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1571 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1573 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1576 void PF_te_bloodshower (void)
1578 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1580 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1581 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1583 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1584 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1585 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1587 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1588 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1589 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1591 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1593 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1596 void PF_te_explosionrgb (void)
1598 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1599 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1601 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1602 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1603 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1605 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1606 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1607 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1610 void PF_te_particlecube (void)
1612 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1614 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1615 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1617 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1618 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1619 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1621 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1622 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1625 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1626 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1627 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1629 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1631 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1632 // gravity true/false
1633 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1635 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1638 void PF_te_particlerain (void)
1640 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1642 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1643 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1645 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1646 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1657 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1659 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1662 void PF_te_particlesnow (void)
1664 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1666 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1667 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1670 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1671 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1673 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1674 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1677 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1678 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1679 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1681 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1683 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1686 void PF_te_spark (void)
1688 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1690 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1691 MSG_WriteByte(&sv.datagram, TE_SPARK);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1694 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1695 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1697 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1698 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1699 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1701 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1704 void PF_te_gunshotquad (void)
1706 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1707 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1714 void PF_te_spikequad (void)
1716 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1717 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1724 void PF_te_superspikequad (void)
1726 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1727 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1729 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1730 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1734 void PF_te_explosionquad (void)
1736 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1737 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1744 void PF_te_smallflash (void)
1746 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1754 void PF_te_customflash (void)
1756 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1758 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1759 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1763 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1765 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1767 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1769 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1770 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1771 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1774 void PF_te_gunshot (void)
1776 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1777 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1784 void PF_te_spike (void)
1786 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1794 void PF_te_superspike (void)
1796 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1797 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1804 void PF_te_explosion (void)
1806 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1807 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1814 void PF_te_tarexplosion (void)
1816 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1817 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1824 void PF_te_wizspike (void)
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1834 void PF_te_knightspike (void)
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1844 void PF_te_lavasplash (void)
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1854 void PF_te_teleport (void)
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1864 void PF_te_explosion2 (void)
1866 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1867 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1874 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1877 void PF_te_lightning1 (void)
1879 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1882 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1884 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1893 void PF_te_lightning2 (void)
1895 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1896 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1898 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1904 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1909 void PF_te_lightning3 (void)
1911 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1912 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1914 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1925 void PF_te_beam (void)
1927 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928 MSG_WriteByte(&sv.datagram, TE_BEAM);
1930 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1941 void PF_te_plasmaburn (void)
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1950 void PF_te_flamejet (void)
1952 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1963 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1966 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1969 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1971 bestdist = 1000000000;
1973 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1975 // clip original point to each triangle of the surface and find the
1976 // triangle that is closest
1977 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1978 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1979 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1980 TriangleNormal(v[0], v[1], v[2], facenormal);
1981 VectorNormalize(facenormal);
1982 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1983 VectorMA(p, offsetdist, facenormal, temp);
1984 for (j = 0, k = 2;j < 3;k = j, j++)
1986 VectorSubtract(v[k], v[j], edgenormal);
1987 CrossProduct(edgenormal, facenormal, sidenormal);
1988 VectorNormalize(sidenormal);
1989 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1991 VectorMA(temp, offsetdist, sidenormal, temp);
1993 dist = VectorDistance2(temp, p);
1994 if (bestdist > dist)
1997 VectorCopy(temp, out);
2002 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2006 if (!ed || ed->priv.server->free)
2008 modelindex = ed->fields.server->modelindex;
2009 if (modelindex < 1 || modelindex >= MAX_MODELS)
2011 model = sv.models[modelindex];
2012 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2014 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2018 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2019 void PF_getsurfacenumpoints(void)
2021 msurface_t *surface;
2022 // return 0 if no such surface
2023 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2025 PRVM_G_FLOAT(OFS_RETURN) = 0;
2029 // note: this (incorrectly) assumes it is a simple polygon
2030 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2032 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2033 void PF_getsurfacepoint(void)
2036 msurface_t *surface;
2038 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2039 ed = PRVM_G_EDICT(OFS_PARM0);
2040 if (!ed || ed->priv.server->free)
2042 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2044 // note: this (incorrectly) assumes it is a simple polygon
2045 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2046 if (pointnum < 0 || pointnum >= surface->num_vertices)
2048 // FIXME: implement rotation/scaling
2049 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2051 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2052 void PF_getsurfacenormal(void)
2054 msurface_t *surface;
2056 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2057 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2059 // FIXME: implement rotation/scaling
2060 // note: this (incorrectly) assumes it is a simple polygon
2061 // note: this only returns the first triangle, so it doesn't work very
2062 // well for curved surfaces or arbitrary meshes
2063 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);
2064 VectorNormalize(normal);
2065 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2067 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2068 void PF_getsurfacetexture(void)
2070 msurface_t *surface;
2071 PRVM_G_INT(OFS_RETURN) = 0;
2072 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2074 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2076 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2077 void PF_getsurfacenearpoint(void)
2079 int surfacenum, best, modelindex;
2081 vec_t dist, bestdist;
2084 msurface_t *surface;
2086 PRVM_G_FLOAT(OFS_RETURN) = -1;
2087 ed = PRVM_G_EDICT(OFS_PARM0);
2088 point = PRVM_G_VECTOR(OFS_PARM1);
2090 if (!ed || ed->priv.server->free)
2092 modelindex = ed->fields.server->modelindex;
2093 if (modelindex < 1 || modelindex >= MAX_MODELS)
2095 model = sv.models[modelindex];
2096 if (!model->num_surfaces)
2099 // FIXME: implement rotation/scaling
2100 VectorSubtract(point, ed->fields.server->origin, p);
2102 bestdist = 1000000000;
2103 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2105 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2106 // first see if the nearest point on the surface's box is closer than the previous match
2107 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2108 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2109 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2110 dist = VectorLength2(clipped);
2111 if (dist < bestdist)
2113 // it is, check the nearest point on the actual geometry
2114 clippointtosurface(surface, p, clipped);
2115 VectorSubtract(clipped, p, clipped);
2116 dist += VectorLength2(clipped);
2117 if (dist < bestdist)
2119 // that's closer too, store it as the best match
2125 PRVM_G_FLOAT(OFS_RETURN) = best;
2127 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2128 void PF_getsurfaceclippedpoint(void)
2131 msurface_t *surface;
2133 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2134 ed = PRVM_G_EDICT(OFS_PARM0);
2135 if (!ed || ed->priv.server->free)
2137 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2139 // FIXME: implement rotation/scaling
2140 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2141 clippointtosurface(surface, p, out);
2142 // FIXME: implement rotation/scaling
2143 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2146 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2147 //this function originally written by KrimZon, made shorter by LordHavoc
2148 void PF_clientcommand (void)
2150 client_t *temp_client;
2153 //find client for this entity
2154 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2155 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2157 Con_Print("PF_clientcommand: entity is not a client\n");
2161 temp_client = host_client;
2162 host_client = svs.clients + i;
2163 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2164 host_client = temp_client;
2167 //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)
2168 void PF_setattachment (void)
2170 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2171 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2172 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2177 if (e == prog->edicts)
2178 PF_WARNING("setattachment: can not modify world entity\n");
2179 if (e->priv.server->free)
2180 PF_WARNING("setattachment: can not modify free entity\n");
2182 if (tagentity == NULL)
2183 tagentity = prog->edicts;
2185 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2187 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2189 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2192 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2194 modelindex = (int)tagentity->fields.server->modelindex;
2195 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2197 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2199 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);
2202 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));
2206 /////////////////////////////////////////
2207 // DP_MD3_TAGINFO extension coded by VorteX
2209 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2214 i = e->fields.server->modelindex;
2215 if (i < 1 || i >= MAX_MODELS)
2217 model = sv.models[i];
2219 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2222 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2224 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2228 Matrix4x4_CreateFromQuakeEntity(out, 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], scale);
2230 Matrix4x4_CreateFromQuakeEntity(out, 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], scale * 0.333);
2233 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2239 && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2240 && (model = sv.models[(int)ent->fields.server->modelindex])
2241 && model->animscenes)
2243 // if model has wrong frame, engine automatically switches to model first frame
2244 frame = (int)ent->fields.server->frame;
2245 if (frame < 0 || frame >= model->numframes)
2247 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2249 Matrix4x4_CreateIdentity(out);
2253 // Warnings/errors code:
2254 // 0 - normal (everything all-right)
2257 // 3 - null or non-precached model
2258 // 4 - no tags with requested index
2259 // 5 - runaway loop at attachment chain
2260 extern cvar_t cl_bob;
2261 extern cvar_t cl_bobcycle;
2262 extern cvar_t cl_bobup;
2263 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2267 int modelindex, attachloop;
2268 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2271 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2273 if (ent == prog->edicts)
2275 if (ent->priv.server->free)
2278 modelindex = (int)ent->fields.server->modelindex;
2279 if (modelindex <= 0 || modelindex > MAX_MODELS)
2282 model = sv.models[modelindex];
2284 Matrix4x4_CreateIdentity(&tagmatrix);
2285 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2289 if (attachloop >= 256) // prevent runaway looping
2291 // apply transformation by child's tagindex on parent entity and then
2292 // by parent entity itself
2293 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2294 if (ret && attachloop == 0)
2296 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2297 SV_GetEntityMatrix(ent, &entitymatrix, false);
2298 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2299 // next iteration we process the parent entity
2300 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2302 tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2303 ent = PRVM_EDICT_NUM(val->edict);
2310 // RENDER_VIEWMODEL magic
2311 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2313 Matrix4x4_Copy(&tagmatrix, out);
2314 ent = PRVM_EDICT_NUM(val->edict);
2316 SV_GetEntityMatrix(ent, &entitymatrix, true);
2317 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2320 // Cl_bob, ported from rendering code
2321 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2324 // LordHavoc: this code is *weird*, but not replacable (I think it
2325 // should be done in QC on the server, but oh well, quake is quake)
2326 // LordHavoc: figured out bobup: the time at which the sin is at 180
2327 // degrees (which allows lengthening or squishing the peak or valley)
2328 cycle = sv.time/cl_bobcycle.value;
2329 cycle -= (int)cycle;
2330 if (cycle < cl_bobup.value)
2331 cycle = sin(M_PI * cycle / cl_bobup.value);
2333 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2334 // bob is proportional to velocity in the xy plane
2335 // (don't count Z, or jumping messes it up)
2336 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;
2337 bob = bob*0.3 + bob*0.7*cycle;
2338 out->m[2][3] += bound(-7, bob, 4);
2345 //float(entity ent, string tagname) gettagindex;
2347 void PF_gettagindex (void)
2349 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2350 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2351 int modelindex, tag_index;
2353 if (ent == prog->edicts)
2354 PF_WARNING("gettagindex: can't affect world entity\n");
2355 if (ent->priv.server->free)
2356 PF_WARNING("gettagindex: can't affect free entity\n");
2358 modelindex = (int)ent->fields.server->modelindex;
2360 if (modelindex <= 0 || modelindex > MAX_MODELS)
2361 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2364 tag_index = SV_GetTagIndex(ent, tag_name);
2366 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2368 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2371 //vector(entity ent, float tagindex) gettaginfo;
2372 void PF_gettaginfo (void)
2374 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2375 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2376 matrix4x4_t tag_matrix;
2379 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2380 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2385 PF_WARNING("gettagindex: can't affect world entity\n");
2388 PF_WARNING("gettagindex: can't affect free entity\n");
2391 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2394 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2397 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2402 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2403 void PF_dropclient (void)
2406 client_t *oldhostclient;
2407 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2408 if (clientnum < 0 || clientnum >= svs.maxclients)
2409 PF_WARNING("dropclient: not a client\n");
2410 if (!svs.clients[clientnum].active)
2411 PF_WARNING("dropclient: that client slot is not connected\n");
2412 oldhostclient = host_client;
2413 host_client = svs.clients + clientnum;
2414 SV_DropClient(false);
2415 host_client = oldhostclient;
2418 //entity() spawnclient (DP_SV_BOTCLIENT)
2419 void PF_spawnclient (void)
2423 prog->xfunction->builtinsprofile += 2;
2425 for (i = 0;i < svs.maxclients;i++)
2427 if (!svs.clients[i].active)
2429 prog->xfunction->builtinsprofile += 100;
2430 SV_ConnectClient (i, NULL);
2431 ed = PRVM_EDICT_NUM(i + 1);
2435 VM_RETURN_EDICT(ed);
2438 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2439 void PF_clienttype (void)
2442 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2443 if (clientnum < 0 || clientnum >= svs.maxclients)
2444 PRVM_G_FLOAT(OFS_RETURN) = 3;
2445 else if (!svs.clients[clientnum].active)
2446 PRVM_G_FLOAT(OFS_RETURN) = 0;
2447 else if (svs.clients[clientnum].netconnection)
2448 PRVM_G_FLOAT(OFS_RETURN) = 1;
2450 PRVM_G_FLOAT(OFS_RETURN) = 2;
2453 void PF_edict_num (void)
2455 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2458 prvm_builtin_t vm_sv_builtins[] = {
2460 PF_makevectors, // #1 void(vector ang) makevectors
2461 PF_setorigin, // #2 void(entity e, vector o) setorigin
2462 PF_setmodel, // #3 void(entity e, string m) setmodel
2463 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2464 NULL, // #5 void(entity e, vector min, vector max) setabssize
2465 VM_break, // #6 void() break
2466 VM_random, // #7 float() random
2467 PF_sound, // #8 void(entity e, float chan, string samp) sound
2468 VM_normalize, // #9 vector(vector v) normalize
2469 VM_error, // #10 void(string e) error
2470 VM_objerror, // #11 void(string e) objerror
2471 VM_vlen, // #12 float(vector v) vlen
2472 VM_vectoyaw, // #13 float(vector v) vectoyaw
2473 VM_spawn, // #14 entity() spawn
2474 VM_remove, // #15 void(entity e) remove
2475 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2476 PF_checkclient, // #17 entity() clientlist
2477 VM_find, // #18 entity(entity start, .string fld, string match) find
2478 PF_precache_sound, // #19 void(string s) precache_sound
2479 PF_precache_model, // #20 void(string s) precache_model
2480 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2481 PF_findradius, // #22 entity(vector org, float rad) findradius
2482 VM_bprint, // #23 void(string s) bprint
2483 PF_sprint, // #24 void(entity client, string s) sprint
2484 VM_dprint, // #25 void(string s) dprint
2485 VM_ftos, // #26 void(string s) ftos
2486 VM_vtos, // #27 void(string s) vtos
2487 VM_coredump, // #28 void() coredump
2488 VM_traceon, // #29 void() traceon
2489 VM_traceoff, // #30 void() traceoff
2490 VM_eprint, // #31 void(entity e) eprint
2491 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2493 PF_droptofloor, // #34 float() droptofloor
2494 PF_lightstyle, // #35 void(float style, string value) lightstyle
2495 VM_rint, // #36 float(float v) rint
2496 VM_floor, // #37 float(float v) floor
2497 VM_ceil, // #38 float(float v) ceil
2499 PF_checkbottom, // #40 float(entity e) checkbottom
2500 PF_pointcontents, // #41 float(vector v) pointcontents
2502 VM_fabs, // #43 float(float f) fabs
2503 PF_aim, // #44 vector(entity e, float speed) aim
2504 VM_cvar, // #45 float(string s) cvar
2505 VM_localcmd, // #46 void(string s) localcmd
2506 VM_nextent, // #47 entity(entity e) nextent
2507 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2508 PF_changeyaw, // #49 void() ChangeYaw
2510 VM_vectoangles, // #51 vector(vector v) vectoangles
2511 PF_WriteByte, // #52 void(float to, float f) WriteByte
2512 PF_WriteChar, // #53 void(float to, float f) WriteChar
2513 PF_WriteShort, // #54 void(float to, float f) WriteShort
2514 PF_WriteLong, // #55 void(float to, float f) WriteLong
2515 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2516 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2517 PF_WriteString, // #58 void(float to, string s) WriteString
2518 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2519 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2520 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2521 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2522 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2523 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2524 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2526 SV_MoveToGoal, // #67 void(float step) movetogoal
2527 PF_precache_file, // #68 string(string s) precache_file
2528 PF_makestatic, // #69 void(entity e) makestatic
2529 VM_changelevel, // #70 void(string s) changelevel
2531 VM_cvar_set, // #72 void(string var, string val) cvar_set
2532 PF_centerprint, // #73 void(entity client, strings) centerprint
2533 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2534 PF_precache_model, // #75 string(string s) precache_model2
2535 PF_precache_sound, // #76 string(string s) precache_sound2
2536 PF_precache_file, // #77 string(string s) precache_file2
2537 PF_setspawnparms, // #78 void(entity e) setspawnparms
2540 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2549 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2550 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2551 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2552 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2553 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2554 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2555 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2556 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2557 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2558 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2569 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2570 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2571 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2572 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2573 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2574 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2575 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2576 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2577 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2578 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2579 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2580 // FTEQW range #200-#299
2599 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2609 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2610 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2611 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2612 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2613 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2614 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2615 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2616 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2617 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2618 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2619 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2620 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2621 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2622 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2623 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2624 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2625 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2626 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2627 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2628 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2629 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2630 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2631 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2632 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2633 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2634 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2635 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2636 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2637 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2638 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2639 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2640 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2641 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2642 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2643 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2644 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2645 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2646 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2647 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2648 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2649 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2650 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2651 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2652 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2653 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2654 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2655 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2656 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2657 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2658 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2659 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2660 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2661 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2662 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2663 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2664 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2665 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2666 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2667 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2669 PF_edict_num, // #459 entity(float num) (??)
2670 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2671 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2672 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2673 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2674 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2675 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2676 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2677 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2678 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2679 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2680 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2690 e10, e10 // #471-499 (LordHavoc)
2693 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2695 void VM_SV_Cmd_Init(void)
2700 void VM_SV_Cmd_Reset(void)