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 "
114 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
117 //"EXT_CSQC " // not ready yet
119 "KRIMZON_SV_PARSECLIENTCOMMAND "
123 "PRYDON_CLIENTCURSOR "
124 "TENEBRAE_GFX_DLIGHTS "
126 "NEXUIZ_PLAYERMODEL "
133 Writes new values for v_forward, v_up, and v_right based on angles
137 void PF_makevectors (void)
139 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
146 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.
148 setorigin (entity, origin)
151 void PF_setorigin (void)
156 e = PRVM_G_EDICT(OFS_PARM0);
157 if (e == prog->edicts)
158 PF_WARNING("setorigin: can not modify world entity\n");
159 if (e->priv.server->free)
160 PF_WARNING("setorigin: can not modify free entity\n");
161 org = PRVM_G_VECTOR(OFS_PARM1);
162 VectorCopy (org, e->fields.server->origin);
163 SV_LinkEdict (e, false);
167 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
171 for (i=0 ; i<3 ; i++)
173 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
175 // set derived values
176 VectorCopy (min, e->fields.server->mins);
177 VectorCopy (max, e->fields.server->maxs);
178 VectorSubtract (max, min, e->fields.server->size);
180 SV_LinkEdict (e, false);
187 the size box is rotated by the current angle
188 LordHavoc: no it isn't...
190 setsize (entity, minvector, maxvector)
193 void PF_setsize (void)
198 e = PRVM_G_EDICT(OFS_PARM0);
199 if (e == prog->edicts)
200 PF_WARNING("setsize: can not modify world entity\n");
201 if (e->priv.server->free)
202 PF_WARNING("setsize: can not modify free entity\n");
203 min = PRVM_G_VECTOR(OFS_PARM1);
204 max = PRVM_G_VECTOR(OFS_PARM2);
205 SetMinMaxSize (e, min, max, false);
213 setmodel(entity, model)
216 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
217 void PF_setmodel (void)
223 e = PRVM_G_EDICT(OFS_PARM0);
224 if (e == prog->edicts)
225 PF_WARNING("setmodel: can not modify world entity\n");
226 if (e->priv.server->free)
227 PF_WARNING("setmodel: can not modify free entity\n");
228 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
229 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
230 e->fields.server->modelindex = i;
236 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
237 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
239 SetMinMaxSize (e, quakemins, quakemaxs, true);
242 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
249 single print to a specific client
251 sprint(clientent, value)
254 void PF_sprint (void)
258 char string[VM_STRINGTEMP_LENGTH];
260 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
262 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
264 Con_Print("tried to sprint to a non-client\n");
268 client = svs.clients + entnum-1;
269 if (!client->netconnection)
272 VM_VarString(1, string, sizeof(string));
273 MSG_WriteChar(&client->netconnection->message,svc_print);
274 MSG_WriteString(&client->netconnection->message, string);
282 single print to a specific client
284 centerprint(clientent, value)
287 void PF_centerprint (void)
291 char string[VM_STRINGTEMP_LENGTH];
293 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
295 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
297 Con_Print("tried to sprint to a non-client\n");
301 client = svs.clients + entnum-1;
302 if (!client->netconnection)
305 VM_VarString(1, string, sizeof(string));
306 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
307 MSG_WriteString(&client->netconnection->message, string);
314 particle(origin, color, count)
317 void PF_particle (void)
323 org = PRVM_G_VECTOR(OFS_PARM0);
324 dir = PRVM_G_VECTOR(OFS_PARM1);
325 color = PRVM_G_FLOAT(OFS_PARM2);
326 count = PRVM_G_FLOAT(OFS_PARM3);
327 SV_StartParticle (org, dir, color, count);
337 void PF_ambientsound (void)
341 float vol, attenuation;
344 pos = PRVM_G_VECTOR (OFS_PARM0);
345 samp = PRVM_G_STRING(OFS_PARM1);
346 vol = PRVM_G_FLOAT(OFS_PARM2);
347 attenuation = PRVM_G_FLOAT(OFS_PARM3);
349 // check to see if samp was properly precached
350 soundnum = SV_SoundIndex(samp, 1);
358 // add an svc_spawnambient command to the level signon packet
361 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
363 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
365 MSG_WriteVector(&sv.signon, pos, sv.protocol);
368 MSG_WriteShort (&sv.signon, soundnum);
370 MSG_WriteByte (&sv.signon, soundnum);
372 MSG_WriteByte (&sv.signon, vol*255);
373 MSG_WriteByte (&sv.signon, attenuation*64);
381 Each entity can have eight independant sound sources, like voice,
384 Channel 0 is an auto-allocate channel, the others override anything
385 already running on that entity/channel pair.
387 An attenuation of 0 will play full volume everywhere in the level.
388 Larger attenuations will drop off.
396 prvm_edict_t *entity;
400 entity = PRVM_G_EDICT(OFS_PARM0);
401 channel = PRVM_G_FLOAT(OFS_PARM1);
402 sample = PRVM_G_STRING(OFS_PARM2);
403 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
404 attenuation = PRVM_G_FLOAT(OFS_PARM4);
406 if (volume < 0 || volume > 255)
407 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
409 if (attenuation < 0 || attenuation > 4)
410 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
412 if (channel < 0 || channel > 7)
413 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
415 SV_StartSound (entity, channel, sample, volume, attenuation);
422 Used for use tracing and shot targeting
423 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
424 if the tryents flag is set.
426 traceline (vector1, vector2, tryents)
429 void PF_traceline (void)
437 prog->xfunction->builtinsprofile += 30;
439 v1 = PRVM_G_VECTOR(OFS_PARM0);
440 v2 = PRVM_G_VECTOR(OFS_PARM1);
441 move = PRVM_G_FLOAT(OFS_PARM2);
442 ent = PRVM_G_EDICT(OFS_PARM3);
444 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]))
445 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));
447 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
449 prog->globals.server->trace_allsolid = trace.allsolid;
450 prog->globals.server->trace_startsolid = trace.startsolid;
451 prog->globals.server->trace_fraction = trace.fraction;
452 prog->globals.server->trace_inwater = trace.inwater;
453 prog->globals.server->trace_inopen = trace.inopen;
454 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
455 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
456 prog->globals.server->trace_plane_dist = trace.plane.dist;
458 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
460 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
461 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
462 val->_float = trace.startsupercontents;
463 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
464 val->_float = trace.hitsupercontents;
465 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
466 val->_float = trace.hitq3surfaceflags;
467 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
469 if (trace.hittexture)
471 char *s = VM_GetTempString();
472 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
473 val->string = PRVM_SetEngineString(s);
485 Used for use tracing and shot targeting
486 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
487 if the tryents flag is set.
489 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
492 // LordHavoc: added this for my own use, VERY useful, similar to traceline
493 void PF_tracebox (void)
495 float *v1, *v2, *m1, *m2;
501 prog->xfunction->builtinsprofile += 30;
503 v1 = PRVM_G_VECTOR(OFS_PARM0);
504 m1 = PRVM_G_VECTOR(OFS_PARM1);
505 m2 = PRVM_G_VECTOR(OFS_PARM2);
506 v2 = PRVM_G_VECTOR(OFS_PARM3);
507 move = PRVM_G_FLOAT(OFS_PARM4);
508 ent = PRVM_G_EDICT(OFS_PARM5);
510 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]))
511 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));
513 trace = SV_Move (v1, m1, m2, v2, move, ent);
515 prog->globals.server->trace_allsolid = trace.allsolid;
516 prog->globals.server->trace_startsolid = trace.startsolid;
517 prog->globals.server->trace_fraction = trace.fraction;
518 prog->globals.server->trace_inwater = trace.inwater;
519 prog->globals.server->trace_inopen = trace.inopen;
520 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
521 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
522 prog->globals.server->trace_plane_dist = trace.plane.dist;
524 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
526 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
527 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
528 val->_float = trace.startsupercontents;
529 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
530 val->_float = trace.hitsupercontents;
531 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
532 val->_float = trace.hitq3surfaceflags;
533 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
535 if (trace.hittexture)
537 char *s = VM_GetTempString();
538 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
539 val->string = PRVM_SetEngineString(s);
546 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
547 void PF_tracetoss (void)
551 prvm_edict_t *ignore;
554 prog->xfunction->builtinsprofile += 600;
556 ent = PRVM_G_EDICT(OFS_PARM0);
557 if (ent == prog->edicts)
558 PF_WARNING("tracetoss: can not use world entity\n");
559 ignore = PRVM_G_EDICT(OFS_PARM1);
561 trace = SV_Trace_Toss (ent, ignore);
563 prog->globals.server->trace_allsolid = trace.allsolid;
564 prog->globals.server->trace_startsolid = trace.startsolid;
565 prog->globals.server->trace_fraction = trace.fraction;
566 prog->globals.server->trace_inwater = trace.inwater;
567 prog->globals.server->trace_inopen = trace.inopen;
568 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
569 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
570 prog->globals.server->trace_plane_dist = trace.plane.dist;
572 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
574 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
575 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
576 val->_float = trace.startsupercontents;
577 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
578 val->_float = trace.hitsupercontents;
579 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
580 val->_float = trace.hitq3surfaceflags;
581 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
583 if (trace.hittexture)
585 char *s = VM_GetTempString();
586 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
587 val->string = PRVM_SetEngineString(s);
599 Returns true if the given entity can move to the given position from it's
600 current position by walking or rolling.
602 scalar checkpos (entity, vector)
605 void PF_checkpos (void)
609 //============================================================================
612 unsigned char checkpvs[MAX_MAP_LEAFS/8];
614 int PF_newcheckclient (int check)
620 // cycle to the next one
622 check = bound(1, check, svs.maxclients);
623 if (check == svs.maxclients)
631 prog->xfunction->builtinsprofile++;
633 if (i == svs.maxclients+1)
635 // look up the client's edict
636 ent = PRVM_EDICT_NUM(i);
637 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
638 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
640 // found a valid client (possibly the same one again)
644 // get the PVS for the entity
645 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
647 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
648 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
657 Returns a client (or object that has a client enemy) that would be a
660 If there is more than one valid option, they are cycled each frame
662 If (self.origin + self.viewofs) is not in the PVS of the current target,
663 it is not returned at all.
668 int c_invis, c_notvis;
669 void PF_checkclient (void)
671 prvm_edict_t *ent, *self;
674 // find a new check if on a new frame
675 if (sv.time - sv.lastchecktime >= 0.1)
677 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
678 sv.lastchecktime = sv.time;
681 // return check if it might be visible
682 ent = PRVM_EDICT_NUM(sv.lastcheck);
683 if (ent->priv.server->free || ent->fields.server->health <= 0)
685 VM_RETURN_EDICT(prog->edicts);
689 // if current entity can't possibly see the check entity, return 0
690 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
691 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
692 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
695 VM_RETURN_EDICT(prog->edicts);
699 // might be able to see it
701 VM_RETURN_EDICT(ent);
704 //============================================================================
711 Sends text over to the client's execution buffer
713 stuffcmd (clientent, value, ...)
716 void PF_stuffcmd (void)
720 char string[VM_STRINGTEMP_LENGTH];
722 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
723 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
725 Con_Print("Can't stuffcmd to a non-client\n");
729 VM_VarString(1, string, sizeof(string));
732 host_client = svs.clients + entnum-1;
733 Host_ClientCommands ("%s", string);
741 Returns a chain of entities that have origins within a spherical area
743 findradius (origin, radius)
746 void PF_findradius (void)
748 prvm_edict_t *ent, *chain;
749 vec_t radius, radius2;
750 vec3_t org, eorg, mins, maxs;
753 prvm_edict_t *touchedicts[MAX_EDICTS];
755 chain = (prvm_edict_t *)prog->edicts;
757 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
758 radius = PRVM_G_FLOAT(OFS_PARM1);
759 radius2 = radius * radius;
761 mins[0] = org[0] - (radius + 1);
762 mins[1] = org[1] - (radius + 1);
763 mins[2] = org[2] - (radius + 1);
764 maxs[0] = org[0] + (radius + 1);
765 maxs[1] = org[1] + (radius + 1);
766 maxs[2] = org[2] + (radius + 1);
767 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
768 if (numtouchedicts > MAX_EDICTS)
770 // this never happens
771 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
772 numtouchedicts = MAX_EDICTS;
774 for (i = 0;i < numtouchedicts;i++)
776 ent = touchedicts[i];
777 prog->xfunction->builtinsprofile++;
778 // Quake did not return non-solid entities but darkplaces does
779 // (note: this is the reason you can't blow up fallen zombies)
780 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
782 // LordHavoc: compare against bounding box rather than center so it
783 // doesn't miss large objects, and use DotProduct instead of Length
784 // for a major speedup
785 VectorSubtract(org, ent->fields.server->origin, eorg);
786 if (sv_gameplayfix_findradiusdistancetobox.integer)
788 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
789 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
790 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
793 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
794 if (DotProduct(eorg, eorg) < radius2)
796 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
801 VM_RETURN_EDICT(chain);
804 void PF_precache_file (void)
805 { // precache_file is only used to copy files with qcc, it does nothing
806 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
810 void PF_precache_sound (void)
812 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
813 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
816 void PF_precache_model (void)
818 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
819 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
826 float(float yaw, float dist) walkmove
829 void PF_walkmove (void)
837 // assume failure if it returns early
838 PRVM_G_FLOAT(OFS_RETURN) = 0;
840 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
841 if (ent == prog->edicts)
842 PF_WARNING("walkmove: can not modify world entity\n");
843 if (ent->priv.server->free)
844 PF_WARNING("walkmove: can not modify free entity\n");
845 yaw = PRVM_G_FLOAT(OFS_PARM0);
846 dist = PRVM_G_FLOAT(OFS_PARM1);
848 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
851 yaw = yaw*M_PI*2 / 360;
853 move[0] = cos(yaw)*dist;
854 move[1] = sin(yaw)*dist;
857 // save program state, because SV_movestep may call other progs
858 oldf = prog->xfunction;
859 oldself = prog->globals.server->self;
861 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
864 // restore program state
865 prog->xfunction = oldf;
866 prog->globals.server->self = oldself;
876 void PF_droptofloor (void)
882 // assume failure if it returns early
883 PRVM_G_FLOAT(OFS_RETURN) = 0;
885 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
886 if (ent == prog->edicts)
887 PF_WARNING("droptofloor: can not modify world entity\n");
888 if (ent->priv.server->free)
889 PF_WARNING("droptofloor: can not modify free entity\n");
891 VectorCopy (ent->fields.server->origin, end);
894 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
896 if (trace.fraction != 1)
898 VectorCopy (trace.endpos, ent->fields.server->origin);
899 SV_LinkEdict (ent, false);
900 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
901 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
902 PRVM_G_FLOAT(OFS_RETURN) = 1;
903 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
904 ent->priv.server->suspendedinairflag = true;
912 void(float style, string value) lightstyle
915 void PF_lightstyle (void)
922 style = PRVM_G_FLOAT(OFS_PARM0);
923 val = PRVM_G_STRING(OFS_PARM1);
925 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
926 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
929 // change the string in sv
930 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
932 // send message to all clients on this server
933 if (sv.state != ss_active)
936 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
938 if (client->active && client->netconnection)
940 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
941 MSG_WriteChar (&client->netconnection->message,style);
942 MSG_WriteString (&client->netconnection->message, val);
952 void PF_checkbottom (void)
954 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
962 void PF_pointcontents (void)
964 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
971 Pick a vector for the player to shoot along
972 vector aim(entity, missilespeed)
977 prvm_edict_t *ent, *check, *bestent;
978 vec3_t start, dir, end, bestdir;
981 float dist, bestdist;
984 // assume failure if it returns early
985 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
986 // if sv_aim is so high it can't possibly accept anything, skip out early
987 if (sv_aim.value >= 1)
990 ent = PRVM_G_EDICT(OFS_PARM0);
991 if (ent == prog->edicts)
992 PF_WARNING("aim: can not use world entity\n");
993 if (ent->priv.server->free)
994 PF_WARNING("aim: can not use free entity\n");
995 speed = PRVM_G_FLOAT(OFS_PARM1);
997 VectorCopy (ent->fields.server->origin, start);
1000 // try sending a trace straight
1001 VectorCopy (prog->globals.server->v_forward, dir);
1002 VectorMA (start, 2048, dir, end);
1003 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1004 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1005 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1007 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1012 // try all possible entities
1013 VectorCopy (dir, bestdir);
1014 bestdist = sv_aim.value;
1017 check = PRVM_NEXT_EDICT(prog->edicts);
1018 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1020 prog->xfunction->builtinsprofile++;
1021 if (check->fields.server->takedamage != DAMAGE_AIM)
1025 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1026 continue; // don't aim at teammate
1027 for (j=0 ; j<3 ; j++)
1028 end[j] = check->fields.server->origin[j]
1029 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1030 VectorSubtract (end, start, dir);
1031 VectorNormalize (dir);
1032 dist = DotProduct (dir, prog->globals.server->v_forward);
1033 if (dist < bestdist)
1034 continue; // to far to turn
1035 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1036 if (tr.ent == check)
1037 { // can shoot at this one
1045 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1046 dist = DotProduct (dir, prog->globals.server->v_forward);
1047 VectorScale (prog->globals.server->v_forward, dist, end);
1049 VectorNormalize (end);
1050 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1054 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1062 This was a major timewaster in progs, so it was converted to C
1065 void PF_changeyaw (void)
1068 float ideal, current, move, speed;
1070 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1071 if (ent == prog->edicts)
1072 PF_WARNING("changeyaw: can not modify world entity\n");
1073 if (ent->priv.server->free)
1074 PF_WARNING("changeyaw: can not modify free entity\n");
1075 current = ANGLEMOD(ent->fields.server->angles[1]);
1076 ideal = ent->fields.server->ideal_yaw;
1077 speed = ent->fields.server->yaw_speed;
1079 if (current == ideal)
1081 move = ideal - current;
1082 if (ideal > current)
1103 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1111 void PF_changepitch (void)
1114 float ideal, current, move, speed;
1117 ent = PRVM_G_EDICT(OFS_PARM0);
1118 if (ent == prog->edicts)
1119 PF_WARNING("changepitch: can not modify world entity\n");
1120 if (ent->priv.server->free)
1121 PF_WARNING("changepitch: can not modify free entity\n");
1122 current = ANGLEMOD( ent->fields.server->angles[0] );
1123 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1124 ideal = val->_float;
1127 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1130 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1131 speed = val->_float;
1134 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1138 if (current == ideal)
1140 move = ideal - current;
1141 if (ideal > current)
1162 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1166 ===============================================================================
1170 ===============================================================================
1173 #define MSG_BROADCAST 0 // unreliable to all
1174 #define MSG_ONE 1 // reliable to one (msg_entity)
1175 #define MSG_ALL 2 // reliable to all
1176 #define MSG_INIT 3 // write to the init string
1177 #define MSG_ENTITY 5
1179 sizebuf_t *WriteDest (void)
1184 extern sizebuf_t *sv2csqcbuf;
1186 dest = PRVM_G_FLOAT(OFS_PARM0);
1190 return &sv.datagram;
1193 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1194 entnum = PRVM_NUM_FOR_EDICT(ent);
1195 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1197 Con_Printf ("WriteDest: tried to write to non-client\n");
1198 return &sv.reliable_datagram;
1201 return &svs.clients[entnum-1].netconnection->message;
1204 Con_Printf ("WriteDest: bad destination\n");
1206 return &sv.reliable_datagram;
1218 void PF_WriteByte (void)
1220 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1223 void PF_WriteChar (void)
1225 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1228 void PF_WriteShort (void)
1230 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1233 void PF_WriteLong (void)
1235 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1238 void PF_WriteAngle (void)
1240 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1243 void PF_WriteCoord (void)
1245 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1248 void PF_WriteString (void)
1250 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1253 void PF_WriteUnterminatedString (void)
1255 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1259 void PF_WriteEntity (void)
1261 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1264 //////////////////////////////////////////////////////////
1266 void PF_makestatic (void)
1271 ent = PRVM_G_EDICT(OFS_PARM0);
1272 if (ent == prog->edicts)
1273 PF_WARNING("makestatic: can not modify world entity\n");
1274 if (ent->priv.server->free)
1275 PF_WARNING("makestatic: can not modify free entity\n");
1278 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1283 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1284 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1285 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1289 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1290 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1291 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1294 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1295 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1296 for (i=0 ; i<3 ; i++)
1298 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1299 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1302 // throw the entity away now
1306 //=============================================================================
1313 void PF_setspawnparms (void)
1319 ent = PRVM_G_EDICT(OFS_PARM0);
1320 i = PRVM_NUM_FOR_EDICT(ent);
1321 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1323 Con_Print("tried to setspawnparms on a non-client\n");
1327 // copy spawn parms out of the client_t
1328 client = svs.clients + i-1;
1329 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1330 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1337 Returns a color vector indicating the lighting at the requested point.
1339 (Internal Operation note: actually measures the light beneath the point, just like
1340 the model lighting on the client)
1345 void PF_getlight (void)
1347 vec3_t ambientcolor, diffusecolor, diffusenormal;
1349 p = PRVM_G_VECTOR(OFS_PARM0);
1350 VectorClear(ambientcolor);
1351 VectorClear(diffusecolor);
1352 VectorClear(diffusenormal);
1353 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1354 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1355 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1358 void PF_registercvar (void)
1360 const char *name, *value;
1361 name = PRVM_G_STRING(OFS_PARM0);
1362 value = PRVM_G_STRING(OFS_PARM1);
1363 PRVM_G_FLOAT(OFS_RETURN) = 0;
1365 // first check to see if it has already been defined
1366 if (Cvar_FindVar (name))
1369 // check for overlap with a command
1370 if (Cmd_Exists (name))
1372 Con_Printf("PF_registercvar: %s is a command\n", name);
1376 Cvar_Get(name, value, 0);
1378 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1383 unsigned char type; // 1/2/8 or other value if isn't used
1387 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1388 static int vm_autosentstats_last;
1390 void VM_AutoSentStats_Clear (void)
1392 if(vm_autosentstats)
1394 free(vm_autosentstats);
1395 vm_autosentstats = NULL;
1396 vm_autosentstats_last = -1;
1400 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1401 #define VM_SENDSTAT(a,b,c)\
1404 if((c)==(unsigned char)(c))\
1406 MSG_WriteByte((a), svc_updatestatubyte);\
1407 MSG_WriteByte((a), (b));\
1408 MSG_WriteByte((a), (c));\
1412 MSG_WriteByte((a), svc_updatestat);\
1413 MSG_WriteByte((a), (b));\
1414 MSG_WriteLong((a), (c));\
1418 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1430 if(!vm_autosentstats)
1433 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);
1435 for(i=0; i<vm_autosentstats_last+1 ;i++)
1437 if(!vm_autosentstats[i].type)
1439 switch(vm_autosentstats[i].type)
1443 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1451 stats[i+32] = si[0];
1452 stats[i+33] = si[1];
1453 stats[i+34] = si[2];
1454 stats[i+35] = si[3];
1458 VM_SENDSTAT(msg, i+32, si[0]);
1459 VM_SENDSTAT(msg, i+33, si[1]);
1460 VM_SENDSTAT(msg, i+34, si[2]);
1461 VM_SENDSTAT(msg, i+35, si[3]);
1467 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1468 k.i = LittleLong (k.i);
1472 VM_SENDSTAT(msg, i+32, k.i);
1476 v = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1480 VM_SENDSTAT(msg, i+32, v);
1488 // void(float index, float type, .void field) SV_AddStat = #470;
1489 // Set up an auto-sent player stat.
1490 // Client's get thier own fields sent to them. Index may not be less than 32.
1491 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1492 // 1: string (4 stats carrying a total of 16 charactures)
1493 // 2: float (one stat, float converted to an integer for transportation)
1494 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1495 void PF_SV_AddStat (void)
1500 if(!vm_autosentstats)
1502 vm_autosentstats = malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1503 if(!vm_autosentstats)
1505 Con_Printf("PF_SV_AddStat: not enough memory\n");
1509 i = PRVM_G_FLOAT(OFS_PARM0);
1510 type = PRVM_G_FLOAT(OFS_PARM1);
1511 off = PRVM_G_INT (OFS_PARM2);
1516 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1519 if(i >= (MAX_CL_STATS-32))
1521 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1524 if(i > (MAX_CL_STATS-32-4) && type == 1)
1526 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1529 vm_autosentstats[i].type = type;
1530 vm_autosentstats[i].fieldoffset = off;
1531 if(vm_autosentstats_last < i)
1532 vm_autosentstats_last = i;
1539 copies data from one entity to another
1541 copyentity(src, dst)
1544 void PF_copyentity (void)
1546 prvm_edict_t *in, *out;
1547 in = PRVM_G_EDICT(OFS_PARM0);
1548 if (in == prog->edicts)
1549 PF_WARNING("copyentity: can not read world entity\n");
1550 if (in->priv.server->free)
1551 PF_WARNING("copyentity: can not read free entity\n");
1552 out = PRVM_G_EDICT(OFS_PARM1);
1553 if (out == prog->edicts)
1554 PF_WARNING("copyentity: can not modify world entity\n");
1555 if (out->priv.server->free)
1556 PF_WARNING("copyentity: can not modify free entity\n");
1557 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1565 sets the color of a client and broadcasts the update to all connected clients
1567 setcolor(clientent, value)
1570 void PF_setcolor (void)
1576 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1577 i = PRVM_G_FLOAT(OFS_PARM1);
1579 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1581 Con_Print("tried to setcolor a non-client\n");
1585 client = svs.clients + entnum-1;
1588 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1590 client->edict->fields.server->team = (i & 15) + 1;
1593 if (client->old_colors != client->colors)
1595 client->old_colors = client->colors;
1596 // send notification to all clients
1597 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1598 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1599 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1607 effect(origin, modelname, startframe, framecount, framerate)
1610 void PF_effect (void)
1614 s = PRVM_G_STRING(OFS_PARM1);
1616 PF_WARNING("effect: no model specified\n");
1618 i = SV_ModelIndex(s, 1);
1620 PF_WARNING("effect: model not precached\n");
1621 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1624 void PF_te_blood (void)
1626 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1628 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1629 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1632 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1633 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1635 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1636 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1637 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1639 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1642 void PF_te_bloodshower (void)
1644 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1646 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1647 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1649 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1650 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1651 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1653 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1654 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1655 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1659 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1662 void PF_te_explosionrgb (void)
1664 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1665 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1668 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1669 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1671 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1672 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1673 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1676 void PF_te_particlecube (void)
1678 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1680 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1681 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1683 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1684 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1688 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1692 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1695 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1697 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1698 // gravity true/false
1699 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1701 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1704 void PF_te_particlerain (void)
1706 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1708 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1709 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1712 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1715 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1720 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1721 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1723 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1725 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1728 void PF_te_particlesnow (void)
1730 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1732 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1733 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1737 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1747 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1749 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1752 void PF_te_spark (void)
1754 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_SPARK);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1763 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1764 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1765 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1767 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1770 void PF_te_gunshotquad (void)
1772 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1773 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1780 void PF_te_spikequad (void)
1782 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1783 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1790 void PF_te_superspikequad (void)
1792 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1793 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1795 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1800 void PF_te_explosionquad (void)
1802 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1803 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1810 void PF_te_smallflash (void)
1812 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1813 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1815 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1816 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1817 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1820 void PF_te_customflash (void)
1822 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1824 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1825 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1833 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1835 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1836 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1837 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1840 void PF_te_gunshot (void)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1847 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1850 void PF_te_spike (void)
1852 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1853 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1855 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1856 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1857 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1860 void PF_te_superspike (void)
1862 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1865 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1870 void PF_te_explosion (void)
1872 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1873 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1875 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1880 void PF_te_tarexplosion (void)
1882 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1885 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1890 void PF_te_wizspike (void)
1892 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1893 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1895 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1900 void PF_te_knightspike (void)
1902 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1905 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1910 void PF_te_lavasplash (void)
1912 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1913 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1916 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1917 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1920 void PF_te_teleport (void)
1922 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1923 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1927 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1930 void PF_te_explosion2 (void)
1932 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1933 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1935 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1939 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1940 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1943 void PF_te_lightning1 (void)
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1948 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1954 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1955 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1959 void PF_te_lightning2 (void)
1961 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1962 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1964 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1975 void PF_te_lightning3 (void)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1980 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1984 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1991 void PF_te_beam (void)
1993 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1994 MSG_WriteByte(&sv.datagram, TE_BEAM);
1996 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2004 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2007 void PF_te_plasmaburn (void)
2009 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2010 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2013 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2016 void PF_te_flamejet (void)
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2023 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2025 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2029 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
2032 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
2035 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2037 bestdist = 1000000000;
2039 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2041 // clip original point to each triangle of the surface and find the
2042 // triangle that is closest
2043 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
2044 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
2045 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
2046 TriangleNormal(v[0], v[1], v[2], facenormal);
2047 VectorNormalize(facenormal);
2048 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2049 VectorMA(p, offsetdist, facenormal, temp);
2050 for (j = 0, k = 2;j < 3;k = j, j++)
2052 VectorSubtract(v[k], v[j], edgenormal);
2053 CrossProduct(edgenormal, facenormal, sidenormal);
2054 VectorNormalize(sidenormal);
2055 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2057 VectorMA(temp, offsetdist, sidenormal, temp);
2059 dist = VectorDistance2(temp, p);
2060 if (bestdist > dist)
2063 VectorCopy(temp, out);
2068 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2072 if (!ed || ed->priv.server->free)
2074 modelindex = ed->fields.server->modelindex;
2075 if (modelindex < 1 || modelindex >= MAX_MODELS)
2077 model = sv.models[modelindex];
2078 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2080 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2084 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2085 void PF_getsurfacenumpoints(void)
2087 msurface_t *surface;
2088 // return 0 if no such surface
2089 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2091 PRVM_G_FLOAT(OFS_RETURN) = 0;
2095 // note: this (incorrectly) assumes it is a simple polygon
2096 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2098 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2099 void PF_getsurfacepoint(void)
2102 msurface_t *surface;
2104 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2105 ed = PRVM_G_EDICT(OFS_PARM0);
2106 if (!ed || ed->priv.server->free)
2108 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2110 // note: this (incorrectly) assumes it is a simple polygon
2111 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2112 if (pointnum < 0 || pointnum >= surface->num_vertices)
2114 // FIXME: implement rotation/scaling
2115 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2117 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2118 void PF_getsurfacenormal(void)
2120 msurface_t *surface;
2122 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2123 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2125 // FIXME: implement rotation/scaling
2126 // note: this (incorrectly) assumes it is a simple polygon
2127 // note: this only returns the first triangle, so it doesn't work very
2128 // well for curved surfaces or arbitrary meshes
2129 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);
2130 VectorNormalize(normal);
2131 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2133 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2134 void PF_getsurfacetexture(void)
2136 msurface_t *surface;
2137 PRVM_G_INT(OFS_RETURN) = 0;
2138 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2140 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2142 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2143 void PF_getsurfacenearpoint(void)
2145 int surfacenum, best, modelindex;
2147 vec_t dist, bestdist;
2150 msurface_t *surface;
2152 PRVM_G_FLOAT(OFS_RETURN) = -1;
2153 ed = PRVM_G_EDICT(OFS_PARM0);
2154 point = PRVM_G_VECTOR(OFS_PARM1);
2156 if (!ed || ed->priv.server->free)
2158 modelindex = ed->fields.server->modelindex;
2159 if (modelindex < 1 || modelindex >= MAX_MODELS)
2161 model = sv.models[modelindex];
2162 if (!model->num_surfaces)
2165 // FIXME: implement rotation/scaling
2166 VectorSubtract(point, ed->fields.server->origin, p);
2168 bestdist = 1000000000;
2169 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2171 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2172 // first see if the nearest point on the surface's box is closer than the previous match
2173 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2174 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2175 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2176 dist = VectorLength2(clipped);
2177 if (dist < bestdist)
2179 // it is, check the nearest point on the actual geometry
2180 clippointtosurface(surface, p, clipped);
2181 VectorSubtract(clipped, p, clipped);
2182 dist += VectorLength2(clipped);
2183 if (dist < bestdist)
2185 // that's closer too, store it as the best match
2191 PRVM_G_FLOAT(OFS_RETURN) = best;
2193 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2194 void PF_getsurfaceclippedpoint(void)
2197 msurface_t *surface;
2199 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2200 ed = PRVM_G_EDICT(OFS_PARM0);
2201 if (!ed || ed->priv.server->free)
2203 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2205 // FIXME: implement rotation/scaling
2206 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2207 clippointtosurface(surface, p, out);
2208 // FIXME: implement rotation/scaling
2209 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2212 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2213 //this function originally written by KrimZon, made shorter by LordHavoc
2214 void PF_clientcommand (void)
2216 client_t *temp_client;
2219 //find client for this entity
2220 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2221 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2223 Con_Print("PF_clientcommand: entity is not a client\n");
2227 temp_client = host_client;
2228 host_client = svs.clients + i;
2229 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2230 host_client = temp_client;
2233 //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)
2234 void PF_setattachment (void)
2236 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2237 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2238 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2243 if (e == prog->edicts)
2244 PF_WARNING("setattachment: can not modify world entity\n");
2245 if (e->priv.server->free)
2246 PF_WARNING("setattachment: can not modify free entity\n");
2248 if (tagentity == NULL)
2249 tagentity = prog->edicts;
2251 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2253 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2255 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2258 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2260 modelindex = (int)tagentity->fields.server->modelindex;
2261 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2263 v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2265 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);
2268 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));
2272 /////////////////////////////////////////
2273 // DP_MD3_TAGINFO extension coded by VorteX
2275 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2280 i = e->fields.server->modelindex;
2281 if (i < 1 || i >= MAX_MODELS)
2283 model = sv.models[i];
2285 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2288 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2290 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2294 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);
2296 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);
2299 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2305 && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2306 && (model = sv.models[(int)ent->fields.server->modelindex])
2307 && model->animscenes)
2309 // if model has wrong frame, engine automatically switches to model first frame
2310 frame = (int)ent->fields.server->frame;
2311 if (frame < 0 || frame >= model->numframes)
2313 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2315 *out = identitymatrix;
2319 // Warnings/errors code:
2320 // 0 - normal (everything all-right)
2323 // 3 - null or non-precached model
2324 // 4 - no tags with requested index
2325 // 5 - runaway loop at attachment chain
2326 extern cvar_t cl_bob;
2327 extern cvar_t cl_bobcycle;
2328 extern cvar_t cl_bobup;
2329 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2333 int modelindex, attachloop;
2334 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2337 *out = identitymatrix; // warnings and errors return identical matrix
2339 if (ent == prog->edicts)
2341 if (ent->priv.server->free)
2344 modelindex = (int)ent->fields.server->modelindex;
2345 if (modelindex <= 0 || modelindex > MAX_MODELS)
2348 model = sv.models[modelindex];
2350 tagmatrix = identitymatrix;
2351 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2355 if (attachloop >= 256) // prevent runaway looping
2357 // apply transformation by child's tagindex on parent entity and then
2358 // by parent entity itself
2359 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2360 if (ret && attachloop == 0)
2362 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2363 SV_GetEntityMatrix(ent, &entitymatrix, false);
2364 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2365 // next iteration we process the parent entity
2366 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2368 tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2369 ent = PRVM_EDICT_NUM(val->edict);
2376 // RENDER_VIEWMODEL magic
2377 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2379 Matrix4x4_Copy(&tagmatrix, out);
2380 ent = PRVM_EDICT_NUM(val->edict);
2382 SV_GetEntityMatrix(ent, &entitymatrix, true);
2383 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2386 // Cl_bob, ported from rendering code
2387 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2390 // LordHavoc: this code is *weird*, but not replacable (I think it
2391 // should be done in QC on the server, but oh well, quake is quake)
2392 // LordHavoc: figured out bobup: the time at which the sin is at 180
2393 // degrees (which allows lengthening or squishing the peak or valley)
2394 cycle = sv.time/cl_bobcycle.value;
2395 cycle -= (int)cycle;
2396 if (cycle < cl_bobup.value)
2397 cycle = sin(M_PI * cycle / cl_bobup.value);
2399 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2400 // bob is proportional to velocity in the xy plane
2401 // (don't count Z, or jumping messes it up)
2402 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;
2403 bob = bob*0.3 + bob*0.7*cycle;
2404 out->m[2][3] += bound(-7, bob, 4);
2411 //float(entity ent, string tagname) gettagindex;
2413 void PF_gettagindex (void)
2415 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2416 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2417 int modelindex, tag_index;
2419 if (ent == prog->edicts)
2420 PF_WARNING("gettagindex: can't affect world entity\n");
2421 if (ent->priv.server->free)
2422 PF_WARNING("gettagindex: can't affect free entity\n");
2424 modelindex = (int)ent->fields.server->modelindex;
2426 if (modelindex <= 0 || modelindex > MAX_MODELS)
2427 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2430 tag_index = SV_GetTagIndex(ent, tag_name);
2432 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2434 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2437 //vector(entity ent, float tagindex) gettaginfo;
2438 void PF_gettaginfo (void)
2440 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2441 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2442 matrix4x4_t tag_matrix;
2445 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2446 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2451 PF_WARNING("gettagindex: can't affect world entity\n");
2454 PF_WARNING("gettagindex: can't affect free entity\n");
2457 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2460 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2463 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2468 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2469 void PF_dropclient (void)
2472 client_t *oldhostclient;
2473 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2474 if (clientnum < 0 || clientnum >= svs.maxclients)
2475 PF_WARNING("dropclient: not a client\n");
2476 if (!svs.clients[clientnum].active)
2477 PF_WARNING("dropclient: that client slot is not connected\n");
2478 oldhostclient = host_client;
2479 host_client = svs.clients + clientnum;
2480 SV_DropClient(false);
2481 host_client = oldhostclient;
2484 //entity() spawnclient (DP_SV_BOTCLIENT)
2485 void PF_spawnclient (void)
2489 prog->xfunction->builtinsprofile += 2;
2491 for (i = 0;i < svs.maxclients;i++)
2493 if (!svs.clients[i].active)
2495 prog->xfunction->builtinsprofile += 100;
2496 SV_ConnectClient (i, NULL);
2497 // this has to be set or else ClientDisconnect won't be called
2498 // we assume the qc will call ClientConnect...
2499 svs.clients[i].clientconnectcalled = true;
2500 ed = PRVM_EDICT_NUM(i + 1);
2504 VM_RETURN_EDICT(ed);
2507 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2508 void PF_clienttype (void)
2511 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2512 if (clientnum < 0 || clientnum >= svs.maxclients)
2513 PRVM_G_FLOAT(OFS_RETURN) = 3;
2514 else if (!svs.clients[clientnum].active)
2515 PRVM_G_FLOAT(OFS_RETURN) = 0;
2516 else if (svs.clients[clientnum].netconnection)
2517 PRVM_G_FLOAT(OFS_RETURN) = 1;
2519 PRVM_G_FLOAT(OFS_RETURN) = 2;
2522 void PF_edict_num (void)
2524 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2527 prvm_builtin_t vm_sv_builtins[] = {
2529 PF_makevectors, // #1 void(vector ang) makevectors
2530 PF_setorigin, // #2 void(entity e, vector o) setorigin
2531 PF_setmodel, // #3 void(entity e, string m) setmodel
2532 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2533 NULL, // #5 void(entity e, vector min, vector max) setabssize
2534 VM_break, // #6 void() break
2535 VM_random, // #7 float() random
2536 PF_sound, // #8 void(entity e, float chan, string samp) sound
2537 VM_normalize, // #9 vector(vector v) normalize
2538 VM_error, // #10 void(string e) error
2539 VM_objerror, // #11 void(string e) objerror
2540 VM_vlen, // #12 float(vector v) vlen
2541 VM_vectoyaw, // #13 float(vector v) vectoyaw
2542 VM_spawn, // #14 entity() spawn
2543 VM_remove, // #15 void(entity e) remove
2544 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2545 PF_checkclient, // #17 entity() clientlist
2546 VM_find, // #18 entity(entity start, .string fld, string match) find
2547 PF_precache_sound, // #19 void(string s) precache_sound
2548 PF_precache_model, // #20 void(string s) precache_model
2549 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2550 PF_findradius, // #22 entity(vector org, float rad) findradius
2551 VM_bprint, // #23 void(string s) bprint
2552 PF_sprint, // #24 void(entity client, string s) sprint
2553 VM_dprint, // #25 void(string s) dprint
2554 VM_ftos, // #26 void(string s) ftos
2555 VM_vtos, // #27 void(string s) vtos
2556 VM_coredump, // #28 void() coredump
2557 VM_traceon, // #29 void() traceon
2558 VM_traceoff, // #30 void() traceoff
2559 VM_eprint, // #31 void(entity e) eprint
2560 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2562 PF_droptofloor, // #34 float() droptofloor
2563 PF_lightstyle, // #35 void(float style, string value) lightstyle
2564 VM_rint, // #36 float(float v) rint
2565 VM_floor, // #37 float(float v) floor
2566 VM_ceil, // #38 float(float v) ceil
2568 PF_checkbottom, // #40 float(entity e) checkbottom
2569 PF_pointcontents, // #41 float(vector v) pointcontents
2571 VM_fabs, // #43 float(float f) fabs
2572 PF_aim, // #44 vector(entity e, float speed) aim
2573 VM_cvar, // #45 float(string s) cvar
2574 VM_localcmd, // #46 void(string s) localcmd
2575 VM_nextent, // #47 entity(entity e) nextent
2576 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2577 PF_changeyaw, // #49 void() ChangeYaw
2579 VM_vectoangles, // #51 vector(vector v) vectoangles
2580 PF_WriteByte, // #52 void(float to, float f) WriteByte
2581 PF_WriteChar, // #53 void(float to, float f) WriteChar
2582 PF_WriteShort, // #54 void(float to, float f) WriteShort
2583 PF_WriteLong, // #55 void(float to, float f) WriteLong
2584 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2585 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2586 PF_WriteString, // #58 void(float to, string s) WriteString
2587 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2588 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2589 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2590 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2591 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2592 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2593 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2595 SV_MoveToGoal, // #67 void(float step) movetogoal
2596 PF_precache_file, // #68 string(string s) precache_file
2597 PF_makestatic, // #69 void(entity e) makestatic
2598 VM_changelevel, // #70 void(string s) changelevel
2600 VM_cvar_set, // #72 void(string var, string val) cvar_set
2601 PF_centerprint, // #73 void(entity client, strings) centerprint
2602 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2603 PF_precache_model, // #75 string(string s) precache_model2
2604 PF_precache_sound, // #76 string(string s) precache_sound2
2605 PF_precache_file, // #77 string(string s) precache_file2
2606 PF_setspawnparms, // #78 void(entity e) setspawnparms
2609 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2618 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2619 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2620 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2621 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2622 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2623 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2624 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2625 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2626 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2627 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2638 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2639 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2640 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2641 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2642 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2643 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2644 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2645 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2646 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2647 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2648 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2649 // FTEQW range #200-#299
2668 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2678 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2679 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2680 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2681 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2682 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2683 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2684 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2685 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2686 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2687 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2688 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2689 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2690 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2691 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2692 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2693 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2694 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2695 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2696 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2697 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2698 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2699 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2700 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2701 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2702 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2703 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2704 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2705 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2706 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2707 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2708 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2709 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2710 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2711 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2712 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2713 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2714 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2715 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2716 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2717 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2718 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2719 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2720 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2721 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2722 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2723 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2724 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2725 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2726 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2727 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2728 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2729 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2730 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2731 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2732 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2733 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2734 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2735 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2736 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2738 PF_edict_num, // #459 entity(float num) (??)
2739 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2740 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2741 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2742 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2743 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2744 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2745 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2746 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2747 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2748 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2749 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2759 e10, e10 // #480-499 (LordHavoc)
2762 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2764 void VM_SV_Cmd_Init(void)
2769 void VM_SV_Cmd_Reset(void)