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", "maximum cosine angle for quake's vertical autoaim, a value above 1 completely disables the autoaim, quake used 0.93"}; //"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 if (!client->netconnection)
271 VM_VarString(1, string, sizeof(string));
272 MSG_WriteChar(&client->netconnection->message,svc_print);
273 MSG_WriteString(&client->netconnection->message, string);
281 single print to a specific client
283 centerprint(clientent, value)
286 void PF_centerprint (void)
290 char string[VM_STRINGTEMP_LENGTH];
292 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
294 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
296 Con_Print("tried to sprint to a non-client\n");
300 client = svs.clients + entnum-1;
301 if (!client->netconnection)
304 VM_VarString(1, string, sizeof(string));
305 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
306 MSG_WriteString(&client->netconnection->message, string);
313 particle(origin, color, count)
316 void PF_particle (void)
322 org = PRVM_G_VECTOR(OFS_PARM0);
323 dir = PRVM_G_VECTOR(OFS_PARM1);
324 color = PRVM_G_FLOAT(OFS_PARM2);
325 count = PRVM_G_FLOAT(OFS_PARM3);
326 SV_StartParticle (org, dir, color, count);
336 void PF_ambientsound (void)
340 float vol, attenuation;
343 pos = PRVM_G_VECTOR (OFS_PARM0);
344 samp = PRVM_G_STRING(OFS_PARM1);
345 vol = PRVM_G_FLOAT(OFS_PARM2);
346 attenuation = PRVM_G_FLOAT(OFS_PARM3);
348 // check to see if samp was properly precached
349 soundnum = SV_SoundIndex(samp, 1);
357 // add an svc_spawnambient command to the level signon packet
360 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
362 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
364 MSG_WriteVector(&sv.signon, pos, sv.protocol);
367 MSG_WriteShort (&sv.signon, soundnum);
369 MSG_WriteByte (&sv.signon, soundnum);
371 MSG_WriteByte (&sv.signon, vol*255);
372 MSG_WriteByte (&sv.signon, attenuation*64);
380 Each entity can have eight independant sound sources, like voice,
383 Channel 0 is an auto-allocate channel, the others override anything
384 already running on that entity/channel pair.
386 An attenuation of 0 will play full volume everywhere in the level.
387 Larger attenuations will drop off.
395 prvm_edict_t *entity;
399 entity = PRVM_G_EDICT(OFS_PARM0);
400 channel = PRVM_G_FLOAT(OFS_PARM1);
401 sample = PRVM_G_STRING(OFS_PARM2);
402 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
403 attenuation = PRVM_G_FLOAT(OFS_PARM4);
405 if (volume < 0 || volume > 255)
406 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
408 if (attenuation < 0 || attenuation > 4)
409 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
411 if (channel < 0 || channel > 7)
412 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
414 SV_StartSound (entity, channel, sample, volume, attenuation);
421 Used for use tracing and shot targeting
422 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
423 if the tryents flag is set.
425 traceline (vector1, vector2, tryents)
428 void PF_traceline (void)
435 prog->xfunction->builtinsprofile += 30;
437 v1 = PRVM_G_VECTOR(OFS_PARM0);
438 v2 = PRVM_G_VECTOR(OFS_PARM1);
439 move = PRVM_G_FLOAT(OFS_PARM2);
440 ent = PRVM_G_EDICT(OFS_PARM3);
442 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
443 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
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 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
492 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
494 trace = SV_Move (v1, m1, m2, v2, move, ent);
496 prog->globals.server->trace_allsolid = trace.allsolid;
497 prog->globals.server->trace_startsolid = trace.startsolid;
498 prog->globals.server->trace_fraction = trace.fraction;
499 prog->globals.server->trace_inwater = trace.inwater;
500 prog->globals.server->trace_inopen = trace.inopen;
501 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
502 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
503 prog->globals.server->trace_plane_dist = trace.plane.dist;
505 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
507 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
510 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
511 void PF_tracetoss (void)
515 prvm_edict_t *ignore;
517 prog->xfunction->builtinsprofile += 600;
519 ent = PRVM_G_EDICT(OFS_PARM0);
520 if (ent == prog->edicts)
521 PF_WARNING("tracetoss: can not use world entity\n");
522 ignore = PRVM_G_EDICT(OFS_PARM1);
524 trace = SV_Trace_Toss (ent, ignore);
526 prog->globals.server->trace_allsolid = trace.allsolid;
527 prog->globals.server->trace_startsolid = trace.startsolid;
528 prog->globals.server->trace_fraction = trace.fraction;
529 prog->globals.server->trace_inwater = trace.inwater;
530 prog->globals.server->trace_inopen = trace.inopen;
531 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
532 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
533 prog->globals.server->trace_plane_dist = trace.plane.dist;
535 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
537 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
545 Returns true if the given entity can move to the given position from it's
546 current position by walking or rolling.
548 scalar checkpos (entity, vector)
551 void PF_checkpos (void)
555 //============================================================================
558 unsigned char checkpvs[MAX_MAP_LEAFS/8];
560 int PF_newcheckclient (int check)
566 // cycle to the next one
568 check = bound(1, check, svs.maxclients);
569 if (check == svs.maxclients)
577 prog->xfunction->builtinsprofile++;
579 if (i == svs.maxclients+1)
581 // look up the client's edict
582 ent = PRVM_EDICT_NUM(i);
583 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
584 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
586 // found a valid client (possibly the same one again)
590 // get the PVS for the entity
591 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
593 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
594 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
603 Returns a client (or object that has a client enemy) that would be a
606 If there is more than one valid option, they are cycled each frame
608 If (self.origin + self.viewofs) is not in the PVS of the current target,
609 it is not returned at all.
614 int c_invis, c_notvis;
615 void PF_checkclient (void)
617 prvm_edict_t *ent, *self;
620 // find a new check if on a new frame
621 if (sv.time - sv.lastchecktime >= 0.1)
623 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
624 sv.lastchecktime = sv.time;
627 // return check if it might be visible
628 ent = PRVM_EDICT_NUM(sv.lastcheck);
629 if (ent->priv.server->free || ent->fields.server->health <= 0)
631 VM_RETURN_EDICT(prog->edicts);
635 // if current entity can't possibly see the check entity, return 0
636 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
637 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
638 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
641 VM_RETURN_EDICT(prog->edicts);
645 // might be able to see it
647 VM_RETURN_EDICT(ent);
650 //============================================================================
657 Sends text over to the client's execution buffer
659 stuffcmd (clientent, value, ...)
662 void PF_stuffcmd (void)
666 char string[VM_STRINGTEMP_LENGTH];
668 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
669 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
671 Con_Print("Can't stuffcmd to a non-client\n");
675 VM_VarString(1, string, sizeof(string));
678 host_client = svs.clients + entnum-1;
679 Host_ClientCommands ("%s", string);
687 Returns a chain of entities that have origins within a spherical area
689 findradius (origin, radius)
692 void PF_findradius (void)
694 prvm_edict_t *ent, *chain;
695 vec_t radius, radius2;
696 vec3_t org, eorg, mins, maxs;
699 prvm_edict_t *touchedicts[MAX_EDICTS];
701 chain = (prvm_edict_t *)prog->edicts;
703 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
704 radius = PRVM_G_FLOAT(OFS_PARM1);
705 radius2 = radius * radius;
707 mins[0] = org[0] - (radius + 1);
708 mins[1] = org[1] - (radius + 1);
709 mins[2] = org[2] - (radius + 1);
710 maxs[0] = org[0] + (radius + 1);
711 maxs[1] = org[1] + (radius + 1);
712 maxs[2] = org[2] + (radius + 1);
713 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
714 if (numtouchedicts > MAX_EDICTS)
716 // this never happens
717 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
718 numtouchedicts = MAX_EDICTS;
720 for (i = 0;i < numtouchedicts;i++)
722 ent = touchedicts[i];
723 prog->xfunction->builtinsprofile++;
724 // Quake did not return non-solid entities but darkplaces does
725 // (note: this is the reason you can't blow up fallen zombies)
726 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
728 // LordHavoc: compare against bounding box rather than center so it
729 // doesn't miss large objects, and use DotProduct instead of Length
730 // for a major speedup
731 VectorSubtract(org, ent->fields.server->origin, eorg);
732 if (sv_gameplayfix_findradiusdistancetobox.integer)
734 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
735 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
736 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
739 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
740 if (DotProduct(eorg, eorg) < radius2)
742 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
747 VM_RETURN_EDICT(chain);
750 void PF_precache_file (void)
751 { // precache_file is only used to copy files with qcc, it does nothing
752 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
756 void PF_precache_sound (void)
758 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
759 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
762 void PF_precache_model (void)
764 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
765 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
772 float(float yaw, float dist) walkmove
775 void PF_walkmove (void)
783 // assume failure if it returns early
784 PRVM_G_FLOAT(OFS_RETURN) = 0;
786 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
787 if (ent == prog->edicts)
788 PF_WARNING("walkmove: can not modify world entity\n");
789 if (ent->priv.server->free)
790 PF_WARNING("walkmove: can not modify free entity\n");
791 yaw = PRVM_G_FLOAT(OFS_PARM0);
792 dist = PRVM_G_FLOAT(OFS_PARM1);
794 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
797 yaw = yaw*M_PI*2 / 360;
799 move[0] = cos(yaw)*dist;
800 move[1] = sin(yaw)*dist;
803 // save program state, because SV_movestep may call other progs
804 oldf = prog->xfunction;
805 oldself = prog->globals.server->self;
807 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
810 // restore program state
811 prog->xfunction = oldf;
812 prog->globals.server->self = oldself;
822 void PF_droptofloor (void)
828 // assume failure if it returns early
829 PRVM_G_FLOAT(OFS_RETURN) = 0;
831 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
832 if (ent == prog->edicts)
833 PF_WARNING("droptofloor: can not modify world entity\n");
834 if (ent->priv.server->free)
835 PF_WARNING("droptofloor: can not modify free entity\n");
837 VectorCopy (ent->fields.server->origin, end);
840 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
842 if (trace.fraction != 1)
844 VectorCopy (trace.endpos, ent->fields.server->origin);
845 SV_LinkEdict (ent, false);
846 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
847 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
848 PRVM_G_FLOAT(OFS_RETURN) = 1;
849 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
850 ent->priv.server->suspendedinairflag = true;
858 void(float style, string value) lightstyle
861 void PF_lightstyle (void)
868 style = PRVM_G_FLOAT(OFS_PARM0);
869 val = PRVM_G_STRING(OFS_PARM1);
871 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
872 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
875 // change the string in sv
876 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
878 // send message to all clients on this server
879 if (sv.state != ss_active)
882 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
884 if (client->active && client->netconnection)
886 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
887 MSG_WriteChar (&client->netconnection->message,style);
888 MSG_WriteString (&client->netconnection->message, val);
898 void PF_checkbottom (void)
900 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
908 void PF_pointcontents (void)
910 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
917 Pick a vector for the player to shoot along
918 vector aim(entity, missilespeed)
923 prvm_edict_t *ent, *check, *bestent;
924 vec3_t start, dir, end, bestdir;
927 float dist, bestdist;
930 // assume failure if it returns early
931 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
932 // if sv_aim is so high it can't possibly accept anything, skip out early
933 if (sv_aim.value >= 1)
936 ent = PRVM_G_EDICT(OFS_PARM0);
937 if (ent == prog->edicts)
938 PF_WARNING("aim: can not use world entity\n");
939 if (ent->priv.server->free)
940 PF_WARNING("aim: can not use free entity\n");
941 speed = PRVM_G_FLOAT(OFS_PARM1);
943 VectorCopy (ent->fields.server->origin, start);
946 // try sending a trace straight
947 VectorCopy (prog->globals.server->v_forward, dir);
948 VectorMA (start, 2048, dir, end);
949 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
950 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
951 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
953 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
958 // try all possible entities
959 VectorCopy (dir, bestdir);
960 bestdist = sv_aim.value;
963 check = PRVM_NEXT_EDICT(prog->edicts);
964 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
966 prog->xfunction->builtinsprofile++;
967 if (check->fields.server->takedamage != DAMAGE_AIM)
971 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
972 continue; // don't aim at teammate
973 for (j=0 ; j<3 ; j++)
974 end[j] = check->fields.server->origin[j]
975 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
976 VectorSubtract (end, start, dir);
977 VectorNormalize (dir);
978 dist = DotProduct (dir, prog->globals.server->v_forward);
980 continue; // to far to turn
981 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
983 { // can shoot at this one
991 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
992 dist = DotProduct (dir, prog->globals.server->v_forward);
993 VectorScale (prog->globals.server->v_forward, dist, end);
995 VectorNormalize (end);
996 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1000 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1008 This was a major timewaster in progs, so it was converted to C
1011 void PF_changeyaw (void)
1014 float ideal, current, move, speed;
1016 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1017 if (ent == prog->edicts)
1018 PF_WARNING("changeyaw: can not modify world entity\n");
1019 if (ent->priv.server->free)
1020 PF_WARNING("changeyaw: can not modify free entity\n");
1021 current = ANGLEMOD(ent->fields.server->angles[1]);
1022 ideal = ent->fields.server->ideal_yaw;
1023 speed = ent->fields.server->yaw_speed;
1025 if (current == ideal)
1027 move = ideal - current;
1028 if (ideal > current)
1049 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1057 void PF_changepitch (void)
1060 float ideal, current, move, speed;
1063 ent = PRVM_G_EDICT(OFS_PARM0);
1064 if (ent == prog->edicts)
1065 PF_WARNING("changepitch: can not modify world entity\n");
1066 if (ent->priv.server->free)
1067 PF_WARNING("changepitch: can not modify free entity\n");
1068 current = ANGLEMOD( ent->fields.server->angles[0] );
1069 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1070 ideal = val->_float;
1073 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1076 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1077 speed = val->_float;
1080 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1084 if (current == ideal)
1086 move = ideal - current;
1087 if (ideal > current)
1108 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1112 ===============================================================================
1116 ===============================================================================
1119 #define MSG_BROADCAST 0 // unreliable to all
1120 #define MSG_ONE 1 // reliable to one (msg_entity)
1121 #define MSG_ALL 2 // reliable to all
1122 #define MSG_INIT 3 // write to the init string
1123 #define MSG_ENTITY 5
1125 sizebuf_t *WriteDest (void)
1130 extern sizebuf_t *sv2csqcbuf;
1132 dest = PRVM_G_FLOAT(OFS_PARM0);
1136 return &sv.datagram;
1139 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1140 entnum = PRVM_NUM_FOR_EDICT(ent);
1141 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1143 Con_Printf ("WriteDest: tried to write to non-client\n");
1144 return &sv.reliable_datagram;
1147 return &svs.clients[entnum-1].netconnection->message;
1150 Con_Printf ("WriteDest: bad destination\n");
1152 return &sv.reliable_datagram;
1164 void PF_WriteByte (void)
1166 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1169 void PF_WriteChar (void)
1171 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1174 void PF_WriteShort (void)
1176 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1179 void PF_WriteLong (void)
1181 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1184 void PF_WriteAngle (void)
1186 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1189 void PF_WriteCoord (void)
1191 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1194 void PF_WriteString (void)
1196 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1199 void PF_WriteUnterminatedString (void)
1201 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1205 void PF_WriteEntity (void)
1207 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1210 //////////////////////////////////////////////////////////
1212 void PF_makestatic (void)
1217 ent = PRVM_G_EDICT(OFS_PARM0);
1218 if (ent == prog->edicts)
1219 PF_WARNING("makestatic: can not modify world entity\n");
1220 if (ent->priv.server->free)
1221 PF_WARNING("makestatic: can not modify free entity\n");
1224 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1229 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1230 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1231 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1235 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1236 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1237 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1240 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1241 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1242 for (i=0 ; i<3 ; i++)
1244 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1245 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1248 // throw the entity away now
1252 //=============================================================================
1259 void PF_setspawnparms (void)
1265 ent = PRVM_G_EDICT(OFS_PARM0);
1266 i = PRVM_NUM_FOR_EDICT(ent);
1267 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1269 Con_Print("tried to setspawnparms on a non-client\n");
1273 // copy spawn parms out of the client_t
1274 client = svs.clients + i-1;
1275 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1276 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1283 Returns a color vector indicating the lighting at the requested point.
1285 (Internal Operation note: actually measures the light beneath the point, just like
1286 the model lighting on the client)
1291 void PF_getlight (void)
1293 vec3_t ambientcolor, diffusecolor, diffusenormal;
1295 p = PRVM_G_VECTOR(OFS_PARM0);
1296 VectorClear(ambientcolor);
1297 VectorClear(diffusecolor);
1298 VectorClear(diffusenormal);
1299 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1300 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1301 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1304 void PF_registercvar (void)
1306 const char *name, *value;
1307 name = PRVM_G_STRING(OFS_PARM0);
1308 value = PRVM_G_STRING(OFS_PARM1);
1309 PRVM_G_FLOAT(OFS_RETURN) = 0;
1311 // first check to see if it has already been defined
1312 if (Cvar_FindVar (name))
1315 // check for overlap with a command
1316 if (Cmd_Exists (name))
1318 Con_Printf("PF_registercvar: %s is a command\n", name);
1322 Cvar_Get(name, value, 0);
1324 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1329 unsigned char type; // 1/2/8 or other value if isn't used
1333 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1334 static int vm_autosentstats_last;
1336 void VM_AutoSentStats_Clear (void)
1338 if(vm_autosentstats)
1340 free(vm_autosentstats);
1341 vm_autosentstats = NULL;
1342 vm_autosentstats_last = -1;
1346 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1347 #define VM_SENDSTAT(a,b,c)\
1350 if((c)==(unsigned char)(c))\
1352 MSG_WriteByte((a), svc_updatestatubyte);\
1353 MSG_WriteByte((a), (b));\
1354 MSG_WriteByte((a), (c));\
1358 MSG_WriteByte((a), svc_updatestat);\
1359 MSG_WriteByte((a), (b));\
1360 MSG_WriteLong((a), (c));\
1364 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1376 if(!vm_autosentstats)
1379 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);
1381 for(i=0; i<vm_autosentstats_last+1 ;i++)
1383 if(!vm_autosentstats[i].type)
1385 switch(vm_autosentstats[i].type)
1389 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1397 stats[i+32] = si[0];
1398 stats[i+33] = si[1];
1399 stats[i+34] = si[2];
1400 stats[i+35] = si[3];
1404 VM_SENDSTAT(msg, i+32, si[0]);
1405 VM_SENDSTAT(msg, i+33, si[1]);
1406 VM_SENDSTAT(msg, i+34, si[2]);
1407 VM_SENDSTAT(msg, i+35, si[3]);
1413 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1414 k.i = LittleLong (k.i);
1418 VM_SENDSTAT(msg, i+32, k.i);
1422 v = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1426 VM_SENDSTAT(msg, i+32, v);
1434 // void(float index, float type, .void field) SV_AddStat = #470;
1435 // Set up an auto-sent player stat.
1436 // Client's get thier own fields sent to them. Index may not be less than 32.
1437 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1438 // 1: string (4 stats carrying a total of 16 charactures)
1439 // 2: float (one stat, float converted to an integer for transportation)
1440 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1441 void PF_SV_AddStat (void)
1446 if(!vm_autosentstats)
1448 vm_autosentstats = malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1449 if(!vm_autosentstats)
1451 Con_Printf("PF_SV_AddStat: not enough memory\n");
1455 i = PRVM_G_FLOAT(OFS_PARM0);
1456 type = PRVM_G_FLOAT(OFS_PARM1);
1457 off = PRVM_G_INT (OFS_PARM2);
1462 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1465 if(i >= (MAX_CL_STATS-32))
1467 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1470 if(i > (MAX_CL_STATS-32-4) && type == 1)
1472 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1475 vm_autosentstats[i].type = type;
1476 vm_autosentstats[i].fieldoffset = off;
1477 if(vm_autosentstats_last < i)
1478 vm_autosentstats_last = i;
1485 copies data from one entity to another
1487 copyentity(src, dst)
1490 void PF_copyentity (void)
1492 prvm_edict_t *in, *out;
1493 in = PRVM_G_EDICT(OFS_PARM0);
1494 if (in == prog->edicts)
1495 PF_WARNING("copyentity: can not read world entity\n");
1496 if (in->priv.server->free)
1497 PF_WARNING("copyentity: can not read free entity\n");
1498 out = PRVM_G_EDICT(OFS_PARM1);
1499 if (out == prog->edicts)
1500 PF_WARNING("copyentity: can not modify world entity\n");
1501 if (out->priv.server->free)
1502 PF_WARNING("copyentity: can not modify free entity\n");
1503 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1511 sets the color of a client and broadcasts the update to all connected clients
1513 setcolor(clientent, value)
1516 void PF_setcolor (void)
1522 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1523 i = PRVM_G_FLOAT(OFS_PARM1);
1525 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1527 Con_Print("tried to setcolor a non-client\n");
1531 client = svs.clients + entnum-1;
1534 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1536 client->edict->fields.server->team = (i & 15) + 1;
1539 if (client->old_colors != client->colors)
1541 client->old_colors = client->colors;
1542 // send notification to all clients
1543 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1544 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1545 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1553 effect(origin, modelname, startframe, framecount, framerate)
1556 void PF_effect (void)
1560 s = PRVM_G_STRING(OFS_PARM1);
1562 PF_WARNING("effect: no model specified\n");
1564 i = SV_ModelIndex(s, 1);
1566 PF_WARNING("effect: model not precached\n");
1567 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1570 void PF_te_blood (void)
1572 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1574 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1575 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1577 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1578 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1579 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1581 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1582 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1583 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1585 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1588 void PF_te_bloodshower (void)
1590 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1592 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1593 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1595 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1596 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1597 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1599 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1600 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1601 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1603 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1605 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1608 void PF_te_explosionrgb (void)
1610 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1611 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1613 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1614 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1615 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1617 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1618 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1619 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1622 void PF_te_particlecube (void)
1624 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1626 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1627 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1630 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1634 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1635 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1637 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1638 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1639 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1641 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1643 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1644 // gravity true/false
1645 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1647 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1650 void PF_te_particlerain (void)
1652 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1654 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1655 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1658 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1663 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1669 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1671 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1674 void PF_te_particlesnow (void)
1676 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1678 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1679 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1681 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1682 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1693 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1695 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1698 void PF_te_spark (void)
1700 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1702 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1703 MSG_WriteByte(&sv.datagram, TE_SPARK);
1705 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1706 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1707 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1709 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1710 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1711 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1713 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1716 void PF_te_gunshotquad (void)
1718 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1719 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1726 void PF_te_spikequad (void)
1728 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1729 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1731 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1732 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1736 void PF_te_superspikequad (void)
1738 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1739 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1746 void PF_te_explosionquad (void)
1748 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1749 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1756 void PF_te_smallflash (void)
1758 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1759 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
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);
1766 void PF_te_customflash (void)
1768 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1770 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1771 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1777 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1779 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1781 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1782 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1783 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1786 void PF_te_gunshot (void)
1788 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1789 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1796 void PF_te_spike (void)
1798 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1799 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1806 void PF_te_superspike (void)
1808 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1809 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1816 void PF_te_explosion (void)
1818 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1819 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1823 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1826 void PF_te_tarexplosion (void)
1828 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1829 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1836 void PF_te_wizspike (void)
1838 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1839 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1842 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1843 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1846 void PF_te_knightspike (void)
1848 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1849 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1856 void PF_te_lavasplash (void)
1858 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1859 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1863 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1866 void PF_te_teleport (void)
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1873 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1876 void PF_te_explosion2 (void)
1878 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1879 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1883 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1885 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1886 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1889 void PF_te_lightning1 (void)
1891 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1892 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1894 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1905 void PF_te_lightning2 (void)
1907 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1908 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1910 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1921 void PF_te_lightning3 (void)
1923 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1924 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1926 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1934 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1937 void PF_te_beam (void)
1939 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1940 MSG_WriteByte(&sv.datagram, TE_BEAM);
1942 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1953 void PF_te_plasmaburn (void)
1955 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1956 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1962 void PF_te_flamejet (void)
1964 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1965 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1975 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1978 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1981 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1983 bestdist = 1000000000;
1985 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1987 // clip original point to each triangle of the surface and find the
1988 // triangle that is closest
1989 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1990 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1991 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1992 TriangleNormal(v[0], v[1], v[2], facenormal);
1993 VectorNormalize(facenormal);
1994 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1995 VectorMA(p, offsetdist, facenormal, temp);
1996 for (j = 0, k = 2;j < 3;k = j, j++)
1998 VectorSubtract(v[k], v[j], edgenormal);
1999 CrossProduct(edgenormal, facenormal, sidenormal);
2000 VectorNormalize(sidenormal);
2001 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2003 VectorMA(temp, offsetdist, sidenormal, temp);
2005 dist = VectorDistance2(temp, p);
2006 if (bestdist > dist)
2009 VectorCopy(temp, out);
2014 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2018 if (!ed || ed->priv.server->free)
2020 modelindex = ed->fields.server->modelindex;
2021 if (modelindex < 1 || modelindex >= MAX_MODELS)
2023 model = sv.models[modelindex];
2024 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2026 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2030 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2031 void PF_getsurfacenumpoints(void)
2033 msurface_t *surface;
2034 // return 0 if no such surface
2035 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2037 PRVM_G_FLOAT(OFS_RETURN) = 0;
2041 // note: this (incorrectly) assumes it is a simple polygon
2042 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2044 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2045 void PF_getsurfacepoint(void)
2048 msurface_t *surface;
2050 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2051 ed = PRVM_G_EDICT(OFS_PARM0);
2052 if (!ed || ed->priv.server->free)
2054 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2056 // note: this (incorrectly) assumes it is a simple polygon
2057 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2058 if (pointnum < 0 || pointnum >= surface->num_vertices)
2060 // FIXME: implement rotation/scaling
2061 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2063 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2064 void PF_getsurfacenormal(void)
2066 msurface_t *surface;
2068 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2069 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2071 // FIXME: implement rotation/scaling
2072 // note: this (incorrectly) assumes it is a simple polygon
2073 // note: this only returns the first triangle, so it doesn't work very
2074 // well for curved surfaces or arbitrary meshes
2075 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);
2076 VectorNormalize(normal);
2077 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2079 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2080 void PF_getsurfacetexture(void)
2082 msurface_t *surface;
2083 PRVM_G_INT(OFS_RETURN) = 0;
2084 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2086 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2088 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2089 void PF_getsurfacenearpoint(void)
2091 int surfacenum, best, modelindex;
2093 vec_t dist, bestdist;
2096 msurface_t *surface;
2098 PRVM_G_FLOAT(OFS_RETURN) = -1;
2099 ed = PRVM_G_EDICT(OFS_PARM0);
2100 point = PRVM_G_VECTOR(OFS_PARM1);
2102 if (!ed || ed->priv.server->free)
2104 modelindex = ed->fields.server->modelindex;
2105 if (modelindex < 1 || modelindex >= MAX_MODELS)
2107 model = sv.models[modelindex];
2108 if (!model->num_surfaces)
2111 // FIXME: implement rotation/scaling
2112 VectorSubtract(point, ed->fields.server->origin, p);
2114 bestdist = 1000000000;
2115 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2117 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2118 // first see if the nearest point on the surface's box is closer than the previous match
2119 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2120 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2121 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2122 dist = VectorLength2(clipped);
2123 if (dist < bestdist)
2125 // it is, check the nearest point on the actual geometry
2126 clippointtosurface(surface, p, clipped);
2127 VectorSubtract(clipped, p, clipped);
2128 dist += VectorLength2(clipped);
2129 if (dist < bestdist)
2131 // that's closer too, store it as the best match
2137 PRVM_G_FLOAT(OFS_RETURN) = best;
2139 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2140 void PF_getsurfaceclippedpoint(void)
2143 msurface_t *surface;
2145 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2146 ed = PRVM_G_EDICT(OFS_PARM0);
2147 if (!ed || ed->priv.server->free)
2149 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2151 // FIXME: implement rotation/scaling
2152 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2153 clippointtosurface(surface, p, out);
2154 // FIXME: implement rotation/scaling
2155 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2158 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2159 //this function originally written by KrimZon, made shorter by LordHavoc
2160 void PF_clientcommand (void)
2162 client_t *temp_client;
2165 //find client for this entity
2166 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2167 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2169 Con_Print("PF_clientcommand: entity is not a client\n");
2173 temp_client = host_client;
2174 host_client = svs.clients + i;
2175 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2176 host_client = temp_client;
2179 //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)
2180 void PF_setattachment (void)
2182 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2183 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2184 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2189 if (e == prog->edicts)
2190 PF_WARNING("setattachment: can not modify world entity\n");
2191 if (e->priv.server->free)
2192 PF_WARNING("setattachment: can not modify free entity\n");
2194 if (tagentity == NULL)
2195 tagentity = prog->edicts;
2197 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2199 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2201 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2204 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2206 modelindex = (int)tagentity->fields.server->modelindex;
2207 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2209 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2211 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);
2214 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));
2218 /////////////////////////////////////////
2219 // DP_MD3_TAGINFO extension coded by VorteX
2221 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2226 i = e->fields.server->modelindex;
2227 if (i < 1 || i >= MAX_MODELS)
2229 model = sv.models[i];
2231 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2234 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2236 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2240 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);
2242 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);
2245 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2251 && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2252 && (model = sv.models[(int)ent->fields.server->modelindex])
2253 && model->animscenes)
2255 // if model has wrong frame, engine automatically switches to model first frame
2256 frame = (int)ent->fields.server->frame;
2257 if (frame < 0 || frame >= model->numframes)
2259 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2261 *out = identitymatrix;
2265 // Warnings/errors code:
2266 // 0 - normal (everything all-right)
2269 // 3 - null or non-precached model
2270 // 4 - no tags with requested index
2271 // 5 - runaway loop at attachment chain
2272 extern cvar_t cl_bob;
2273 extern cvar_t cl_bobcycle;
2274 extern cvar_t cl_bobup;
2275 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2279 int modelindex, attachloop;
2280 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2283 *out = identitymatrix; // warnings and errors return identical matrix
2285 if (ent == prog->edicts)
2287 if (ent->priv.server->free)
2290 modelindex = (int)ent->fields.server->modelindex;
2291 if (modelindex <= 0 || modelindex > MAX_MODELS)
2294 model = sv.models[modelindex];
2296 tagmatrix = identitymatrix;
2297 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2301 if (attachloop >= 256) // prevent runaway looping
2303 // apply transformation by child's tagindex on parent entity and then
2304 // by parent entity itself
2305 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2306 if (ret && attachloop == 0)
2308 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2309 SV_GetEntityMatrix(ent, &entitymatrix, false);
2310 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2311 // next iteration we process the parent entity
2312 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2314 tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2315 ent = PRVM_EDICT_NUM(val->edict);
2322 // RENDER_VIEWMODEL magic
2323 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2325 Matrix4x4_Copy(&tagmatrix, out);
2326 ent = PRVM_EDICT_NUM(val->edict);
2328 SV_GetEntityMatrix(ent, &entitymatrix, true);
2329 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2332 // Cl_bob, ported from rendering code
2333 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2336 // LordHavoc: this code is *weird*, but not replacable (I think it
2337 // should be done in QC on the server, but oh well, quake is quake)
2338 // LordHavoc: figured out bobup: the time at which the sin is at 180
2339 // degrees (which allows lengthening or squishing the peak or valley)
2340 cycle = sv.time/cl_bobcycle.value;
2341 cycle -= (int)cycle;
2342 if (cycle < cl_bobup.value)
2343 cycle = sin(M_PI * cycle / cl_bobup.value);
2345 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2346 // bob is proportional to velocity in the xy plane
2347 // (don't count Z, or jumping messes it up)
2348 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;
2349 bob = bob*0.3 + bob*0.7*cycle;
2350 out->m[2][3] += bound(-7, bob, 4);
2357 //float(entity ent, string tagname) gettagindex;
2359 void PF_gettagindex (void)
2361 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2362 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2363 int modelindex, tag_index;
2365 if (ent == prog->edicts)
2366 PF_WARNING("gettagindex: can't affect world entity\n");
2367 if (ent->priv.server->free)
2368 PF_WARNING("gettagindex: can't affect free entity\n");
2370 modelindex = (int)ent->fields.server->modelindex;
2372 if (modelindex <= 0 || modelindex > MAX_MODELS)
2373 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2376 tag_index = SV_GetTagIndex(ent, tag_name);
2378 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2380 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2383 //vector(entity ent, float tagindex) gettaginfo;
2384 void PF_gettaginfo (void)
2386 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2387 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2388 matrix4x4_t tag_matrix;
2391 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2392 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2397 PF_WARNING("gettagindex: can't affect world entity\n");
2400 PF_WARNING("gettagindex: can't affect free entity\n");
2403 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2406 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2409 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2414 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2415 void PF_dropclient (void)
2418 client_t *oldhostclient;
2419 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2420 if (clientnum < 0 || clientnum >= svs.maxclients)
2421 PF_WARNING("dropclient: not a client\n");
2422 if (!svs.clients[clientnum].active)
2423 PF_WARNING("dropclient: that client slot is not connected\n");
2424 oldhostclient = host_client;
2425 host_client = svs.clients + clientnum;
2426 SV_DropClient(false);
2427 host_client = oldhostclient;
2430 //entity() spawnclient (DP_SV_BOTCLIENT)
2431 void PF_spawnclient (void)
2435 prog->xfunction->builtinsprofile += 2;
2437 for (i = 0;i < svs.maxclients;i++)
2439 if (!svs.clients[i].active)
2441 prog->xfunction->builtinsprofile += 100;
2442 SV_ConnectClient (i, NULL);
2443 ed = PRVM_EDICT_NUM(i + 1);
2447 VM_RETURN_EDICT(ed);
2450 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2451 void PF_clienttype (void)
2454 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2455 if (clientnum < 0 || clientnum >= svs.maxclients)
2456 PRVM_G_FLOAT(OFS_RETURN) = 3;
2457 else if (!svs.clients[clientnum].active)
2458 PRVM_G_FLOAT(OFS_RETURN) = 0;
2459 else if (svs.clients[clientnum].netconnection)
2460 PRVM_G_FLOAT(OFS_RETURN) = 1;
2462 PRVM_G_FLOAT(OFS_RETURN) = 2;
2465 void PF_edict_num (void)
2467 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2470 prvm_builtin_t vm_sv_builtins[] = {
2472 PF_makevectors, // #1 void(vector ang) makevectors
2473 PF_setorigin, // #2 void(entity e, vector o) setorigin
2474 PF_setmodel, // #3 void(entity e, string m) setmodel
2475 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2476 NULL, // #5 void(entity e, vector min, vector max) setabssize
2477 VM_break, // #6 void() break
2478 VM_random, // #7 float() random
2479 PF_sound, // #8 void(entity e, float chan, string samp) sound
2480 VM_normalize, // #9 vector(vector v) normalize
2481 VM_error, // #10 void(string e) error
2482 VM_objerror, // #11 void(string e) objerror
2483 VM_vlen, // #12 float(vector v) vlen
2484 VM_vectoyaw, // #13 float(vector v) vectoyaw
2485 VM_spawn, // #14 entity() spawn
2486 VM_remove, // #15 void(entity e) remove
2487 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2488 PF_checkclient, // #17 entity() clientlist
2489 VM_find, // #18 entity(entity start, .string fld, string match) find
2490 PF_precache_sound, // #19 void(string s) precache_sound
2491 PF_precache_model, // #20 void(string s) precache_model
2492 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2493 PF_findradius, // #22 entity(vector org, float rad) findradius
2494 VM_bprint, // #23 void(string s) bprint
2495 PF_sprint, // #24 void(entity client, string s) sprint
2496 VM_dprint, // #25 void(string s) dprint
2497 VM_ftos, // #26 void(string s) ftos
2498 VM_vtos, // #27 void(string s) vtos
2499 VM_coredump, // #28 void() coredump
2500 VM_traceon, // #29 void() traceon
2501 VM_traceoff, // #30 void() traceoff
2502 VM_eprint, // #31 void(entity e) eprint
2503 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2505 PF_droptofloor, // #34 float() droptofloor
2506 PF_lightstyle, // #35 void(float style, string value) lightstyle
2507 VM_rint, // #36 float(float v) rint
2508 VM_floor, // #37 float(float v) floor
2509 VM_ceil, // #38 float(float v) ceil
2511 PF_checkbottom, // #40 float(entity e) checkbottom
2512 PF_pointcontents, // #41 float(vector v) pointcontents
2514 VM_fabs, // #43 float(float f) fabs
2515 PF_aim, // #44 vector(entity e, float speed) aim
2516 VM_cvar, // #45 float(string s) cvar
2517 VM_localcmd, // #46 void(string s) localcmd
2518 VM_nextent, // #47 entity(entity e) nextent
2519 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2520 PF_changeyaw, // #49 void() ChangeYaw
2522 VM_vectoangles, // #51 vector(vector v) vectoangles
2523 PF_WriteByte, // #52 void(float to, float f) WriteByte
2524 PF_WriteChar, // #53 void(float to, float f) WriteChar
2525 PF_WriteShort, // #54 void(float to, float f) WriteShort
2526 PF_WriteLong, // #55 void(float to, float f) WriteLong
2527 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2528 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2529 PF_WriteString, // #58 void(float to, string s) WriteString
2530 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2531 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2532 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2533 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2534 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2535 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2536 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2538 SV_MoveToGoal, // #67 void(float step) movetogoal
2539 PF_precache_file, // #68 string(string s) precache_file
2540 PF_makestatic, // #69 void(entity e) makestatic
2541 VM_changelevel, // #70 void(string s) changelevel
2543 VM_cvar_set, // #72 void(string var, string val) cvar_set
2544 PF_centerprint, // #73 void(entity client, strings) centerprint
2545 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2546 PF_precache_model, // #75 string(string s) precache_model2
2547 PF_precache_sound, // #76 string(string s) precache_sound2
2548 PF_precache_file, // #77 string(string s) precache_file2
2549 PF_setspawnparms, // #78 void(entity e) setspawnparms
2552 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2561 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2562 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2563 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2564 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2565 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2566 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2567 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2568 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2569 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2570 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2581 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2582 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2583 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2584 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2585 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2586 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2587 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2588 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2589 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2590 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2591 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2592 // FTEQW range #200-#299
2611 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2621 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2622 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2623 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2624 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2625 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2626 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2627 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2628 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2629 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2630 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2631 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2632 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2633 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2634 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2635 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2636 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2637 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2638 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2639 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2640 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2641 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2642 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2643 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2644 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2645 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2646 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2647 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2648 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2649 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2650 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2651 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2652 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2653 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2654 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2655 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2656 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2657 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2658 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2659 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2660 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2661 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2662 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2663 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2664 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2665 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2666 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2667 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2668 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2669 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2670 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2671 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2672 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2673 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2674 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2675 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2676 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2677 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2678 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2679 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2681 PF_edict_num, // #459 entity(float num) (??)
2682 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2683 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2684 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2685 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2686 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2687 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2688 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2689 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2690 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2691 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2692 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2702 e10, e10 // #480-499 (LordHavoc)
2705 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2707 void VM_SV_Cmd_Init(void)
2712 void VM_SV_Cmd_Reset(void)