3 //============================================================================
6 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
9 char *vm_sv_extensions =
11 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
37 "DP_GFX_EXTERNALTEXTURES_PERMAP "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
51 "DP_QC_ASINACOSATANATAN2TAN "
57 "DP_QC_FINDCHAINFLAGS "
58 "DP_QC_FINDCHAINFLOAT "
61 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
66 "DP_QC_MULTIPLETEMPSTRINGS "
68 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_STRINGBUFFERS "
70 "DP_QC_STRINGCOLORFUNCTIONS "
73 "DP_QC_TRACE_MOVETYPE_HITMODEL "
74 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
75 "DP_QC_VECTORVECTORS "
81 "DP_SND_DIRECTIONLESSATTNNONE "
90 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
91 "DP_SV_DRAWONLYTOCLIENT "
94 "DP_SV_NODRAWTOCLIENT "
96 "DP_SV_PLAYERPHYSICS "
97 "DP_SV_PRECACHEANYTIME "
99 "DP_SV_ROTATINGBMODEL "
102 "DP_SV_WRITEUNTERMINATEDSTRING "
106 "DP_TE_EXPLOSIONRGB "
108 "DP_TE_PARTICLECUBE "
109 "DP_TE_PARTICLERAIN "
110 "DP_TE_PARTICLESNOW "
112 "DP_TE_QUADEFFECTS1 "
115 "DP_TE_STANDARDEFFECTBUILTINS "
116 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
119 //"EXT_CSQC " // not ready yet
121 "KRIMZON_SV_PARSECLIENTCOMMAND "
125 "PRYDON_CLIENTCURSOR "
126 "TENEBRAE_GFX_DLIGHTS "
128 "NEXUIZ_PLAYERMODEL "
135 Writes new values for v_forward, v_up, and v_right based on angles
139 void PF_makevectors (void)
141 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
148 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.
150 setorigin (entity, origin)
153 void PF_setorigin (void)
158 e = PRVM_G_EDICT(OFS_PARM0);
159 if (e == prog->edicts)
161 VM_Warning("setorigin: can not modify world entity\n");
164 if (e->priv.server->free)
166 VM_Warning("setorigin: can not modify free entity\n");
169 org = PRVM_G_VECTOR(OFS_PARM1);
170 VectorCopy (org, e->fields.server->origin);
171 SV_LinkEdict (e, false);
175 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
179 for (i=0 ; i<3 ; i++)
181 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
183 // set derived values
184 VectorCopy (min, e->fields.server->mins);
185 VectorCopy (max, e->fields.server->maxs);
186 VectorSubtract (max, min, e->fields.server->size);
188 SV_LinkEdict (e, false);
195 the size box is rotated by the current angle
196 LordHavoc: no it isn't...
198 setsize (entity, minvector, maxvector)
201 void PF_setsize (void)
206 e = PRVM_G_EDICT(OFS_PARM0);
207 if (e == prog->edicts)
209 VM_Warning("setsize: can not modify world entity\n");
212 if (e->priv.server->free)
214 VM_Warning("setsize: can not modify free entity\n");
217 min = PRVM_G_VECTOR(OFS_PARM1);
218 max = PRVM_G_VECTOR(OFS_PARM2);
219 SetMinMaxSize (e, min, max, false);
227 setmodel(entity, model)
230 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
231 void PF_setmodel (void)
237 e = PRVM_G_EDICT(OFS_PARM0);
238 if (e == prog->edicts)
240 VM_Warning("setmodel: can not modify world entity\n");
243 if (e->priv.server->free)
245 VM_Warning("setmodel: can not modify free entity\n");
248 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
249 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
250 e->fields.server->modelindex = i;
256 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
257 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
259 SetMinMaxSize (e, quakemins, quakemaxs, true);
262 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
269 single print to a specific client
271 sprint(clientent, value)
274 void PF_sprint (void)
278 char string[VM_STRINGTEMP_LENGTH];
280 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
282 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
284 VM_Warning("tried to centerprint to a non-client\n");
288 client = svs.clients + entnum-1;
289 if (!client->netconnection)
292 VM_VarString(1, string, sizeof(string));
293 MSG_WriteChar(&client->netconnection->message,svc_print);
294 MSG_WriteString(&client->netconnection->message, string);
302 single print to a specific client
304 centerprint(clientent, value)
307 void PF_centerprint (void)
311 char string[VM_STRINGTEMP_LENGTH];
313 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
315 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
317 VM_Warning("tried to centerprint to a non-client\n");
321 client = svs.clients + entnum-1;
322 if (!client->netconnection)
325 VM_VarString(1, string, sizeof(string));
326 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
327 MSG_WriteString(&client->netconnection->message, string);
334 particle(origin, color, count)
337 void PF_particle (void)
343 org = PRVM_G_VECTOR(OFS_PARM0);
344 dir = PRVM_G_VECTOR(OFS_PARM1);
345 color = PRVM_G_FLOAT(OFS_PARM2);
346 count = PRVM_G_FLOAT(OFS_PARM3);
347 SV_StartParticle (org, dir, (int)color, (int)count);
357 void PF_ambientsound (void)
361 float vol, attenuation;
364 pos = PRVM_G_VECTOR (OFS_PARM0);
365 samp = PRVM_G_STRING(OFS_PARM1);
366 vol = PRVM_G_FLOAT(OFS_PARM2);
367 attenuation = PRVM_G_FLOAT(OFS_PARM3);
369 // check to see if samp was properly precached
370 soundnum = SV_SoundIndex(samp, 1);
378 // add an svc_spawnambient command to the level signon packet
381 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
383 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
385 MSG_WriteVector(&sv.signon, pos, sv.protocol);
388 MSG_WriteShort (&sv.signon, soundnum);
390 MSG_WriteByte (&sv.signon, soundnum);
392 MSG_WriteByte (&sv.signon, (int)(vol*255));
393 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
401 Each entity can have eight independant sound sources, like voice,
404 Channel 0 is an auto-allocate channel, the others override anything
405 already running on that entity/channel pair.
407 An attenuation of 0 will play full volume everywhere in the level.
408 Larger attenuations will drop off.
416 prvm_edict_t *entity;
420 entity = PRVM_G_EDICT(OFS_PARM0);
421 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
422 sample = PRVM_G_STRING(OFS_PARM2);
423 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
424 attenuation = PRVM_G_FLOAT(OFS_PARM4);
426 if (volume < 0 || volume > 255)
428 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
432 if (attenuation < 0 || attenuation > 4)
434 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
438 if (channel < 0 || channel > 7)
440 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
444 SV_StartSound (entity, channel, sample, volume, attenuation);
451 Used for use tracing and shot targeting
452 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
453 if the tryents flag is set.
455 traceline (vector1, vector2, tryents)
458 void PF_traceline (void)
466 prog->xfunction->builtinsprofile += 30;
468 v1 = PRVM_G_VECTOR(OFS_PARM0);
469 v2 = PRVM_G_VECTOR(OFS_PARM1);
470 move = (int)PRVM_G_FLOAT(OFS_PARM2);
471 ent = PRVM_G_EDICT(OFS_PARM3);
473 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]))
474 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));
476 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
478 prog->globals.server->trace_allsolid = trace.allsolid;
479 prog->globals.server->trace_startsolid = trace.startsolid;
480 prog->globals.server->trace_fraction = trace.fraction;
481 prog->globals.server->trace_inwater = trace.inwater;
482 prog->globals.server->trace_inopen = trace.inopen;
483 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
484 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
485 prog->globals.server->trace_plane_dist = trace.plane.dist;
487 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
489 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
490 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
491 val->_float = trace.startsupercontents;
492 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
493 val->_float = trace.hitsupercontents;
494 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
495 val->_float = trace.hitq3surfaceflags;
496 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
498 if (trace.hittexture)
500 char *s = VM_GetTempString();
501 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
502 val->string = PRVM_SetEngineString(s);
514 Used for use tracing and shot targeting
515 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
516 if the tryents flag is set.
518 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
521 // LordHavoc: added this for my own use, VERY useful, similar to traceline
522 void PF_tracebox (void)
524 float *v1, *v2, *m1, *m2;
530 prog->xfunction->builtinsprofile += 30;
532 v1 = PRVM_G_VECTOR(OFS_PARM0);
533 m1 = PRVM_G_VECTOR(OFS_PARM1);
534 m2 = PRVM_G_VECTOR(OFS_PARM2);
535 v2 = PRVM_G_VECTOR(OFS_PARM3);
536 move = (int)PRVM_G_FLOAT(OFS_PARM4);
537 ent = PRVM_G_EDICT(OFS_PARM5);
539 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]))
540 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));
542 trace = SV_Move (v1, m1, m2, v2, move, ent);
544 prog->globals.server->trace_allsolid = trace.allsolid;
545 prog->globals.server->trace_startsolid = trace.startsolid;
546 prog->globals.server->trace_fraction = trace.fraction;
547 prog->globals.server->trace_inwater = trace.inwater;
548 prog->globals.server->trace_inopen = trace.inopen;
549 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
550 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
551 prog->globals.server->trace_plane_dist = trace.plane.dist;
553 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
555 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
556 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
557 val->_float = trace.startsupercontents;
558 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
559 val->_float = trace.hitsupercontents;
560 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
561 val->_float = trace.hitq3surfaceflags;
562 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
564 if (trace.hittexture)
566 char *s = VM_GetTempString();
567 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
568 val->string = PRVM_SetEngineString(s);
575 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
576 void PF_tracetoss (void)
580 prvm_edict_t *ignore;
583 prog->xfunction->builtinsprofile += 600;
585 ent = PRVM_G_EDICT(OFS_PARM0);
586 if (ent == prog->edicts)
588 VM_Warning("tracetoss: can not use world entity\n");
591 ignore = PRVM_G_EDICT(OFS_PARM1);
593 trace = SV_Trace_Toss (ent, ignore);
595 prog->globals.server->trace_allsolid = trace.allsolid;
596 prog->globals.server->trace_startsolid = trace.startsolid;
597 prog->globals.server->trace_fraction = trace.fraction;
598 prog->globals.server->trace_inwater = trace.inwater;
599 prog->globals.server->trace_inopen = trace.inopen;
600 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
601 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
602 prog->globals.server->trace_plane_dist = trace.plane.dist;
604 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
606 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
607 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
608 val->_float = trace.startsupercontents;
609 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
610 val->_float = trace.hitsupercontents;
611 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
612 val->_float = trace.hitq3surfaceflags;
613 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
615 if (trace.hittexture)
617 char *s = VM_GetTempString();
618 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
619 val->string = PRVM_SetEngineString(s);
631 Returns true if the given entity can move to the given position from it's
632 current position by walking or rolling.
634 scalar checkpos (entity, vector)
637 void PF_checkpos (void)
641 //============================================================================
644 unsigned char checkpvs[MAX_MAP_LEAFS/8];
646 int PF_newcheckclient (int check)
652 // cycle to the next one
654 check = bound(1, check, svs.maxclients);
655 if (check == svs.maxclients)
663 prog->xfunction->builtinsprofile++;
665 if (i == svs.maxclients+1)
667 // look up the client's edict
668 ent = PRVM_EDICT_NUM(i);
669 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
670 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
672 // found a valid client (possibly the same one again)
676 // get the PVS for the entity
677 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
679 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
680 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
689 Returns a client (or object that has a client enemy) that would be a
692 If there is more than one valid option, they are cycled each frame
694 If (self.origin + self.viewofs) is not in the PVS of the current target,
695 it is not returned at all.
700 int c_invis, c_notvis;
701 void PF_checkclient (void)
703 prvm_edict_t *ent, *self;
706 // find a new check if on a new frame
707 if (sv.time - sv.lastchecktime >= 0.1)
709 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
710 sv.lastchecktime = sv.time;
713 // return check if it might be visible
714 ent = PRVM_EDICT_NUM(sv.lastcheck);
715 if (ent->priv.server->free || ent->fields.server->health <= 0)
717 VM_RETURN_EDICT(prog->edicts);
721 // if current entity can't possibly see the check entity, return 0
722 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
723 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
724 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
727 VM_RETURN_EDICT(prog->edicts);
731 // might be able to see it
733 VM_RETURN_EDICT(ent);
736 //============================================================================
743 Sends text over to the client's execution buffer
745 stuffcmd (clientent, value, ...)
748 void PF_stuffcmd (void)
752 char string[VM_STRINGTEMP_LENGTH];
754 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
755 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
757 VM_Warning("Can't stuffcmd to a non-client\n");
761 VM_VarString(1, string, sizeof(string));
764 host_client = svs.clients + entnum-1;
765 Host_ClientCommands ("%s", string);
773 Returns a chain of entities that have origins within a spherical area
775 findradius (origin, radius)
778 void PF_findradius (void)
780 prvm_edict_t *ent, *chain;
781 vec_t radius, radius2;
782 vec3_t org, eorg, mins, maxs;
785 prvm_edict_t *touchedicts[MAX_EDICTS];
787 chain = (prvm_edict_t *)prog->edicts;
789 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
790 radius = PRVM_G_FLOAT(OFS_PARM1);
791 radius2 = radius * radius;
793 mins[0] = org[0] - (radius + 1);
794 mins[1] = org[1] - (radius + 1);
795 mins[2] = org[2] - (radius + 1);
796 maxs[0] = org[0] + (radius + 1);
797 maxs[1] = org[1] + (radius + 1);
798 maxs[2] = org[2] + (radius + 1);
799 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
800 if (numtouchedicts > MAX_EDICTS)
802 // this never happens
803 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
804 numtouchedicts = MAX_EDICTS;
806 for (i = 0;i < numtouchedicts;i++)
808 ent = touchedicts[i];
809 prog->xfunction->builtinsprofile++;
810 // Quake did not return non-solid entities but darkplaces does
811 // (note: this is the reason you can't blow up fallen zombies)
812 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
814 // LordHavoc: compare against bounding box rather than center so it
815 // doesn't miss large objects, and use DotProduct instead of Length
816 // for a major speedup
817 VectorSubtract(org, ent->fields.server->origin, eorg);
818 if (sv_gameplayfix_findradiusdistancetobox.integer)
820 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
821 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
822 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
825 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
826 if (DotProduct(eorg, eorg) < radius2)
828 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
833 VM_RETURN_EDICT(chain);
836 void PF_precache_file (void)
837 { // precache_file is only used to copy files with qcc, it does nothing
838 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
842 void PF_precache_sound (void)
844 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
845 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
848 void PF_precache_model (void)
850 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
851 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
858 float(float yaw, float dist) walkmove
861 void PF_walkmove (void)
869 // assume failure if it returns early
870 PRVM_G_FLOAT(OFS_RETURN) = 0;
872 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
873 if (ent == prog->edicts)
875 VM_Warning("walkmove: can not modify world entity\n");
878 if (ent->priv.server->free)
880 VM_Warning("walkmove: can not modify free entity\n");
883 yaw = PRVM_G_FLOAT(OFS_PARM0);
884 dist = PRVM_G_FLOAT(OFS_PARM1);
886 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
889 yaw = yaw*M_PI*2 / 360;
891 move[0] = cos(yaw)*dist;
892 move[1] = sin(yaw)*dist;
895 // save program state, because SV_movestep may call other progs
896 oldf = prog->xfunction;
897 oldself = prog->globals.server->self;
899 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
902 // restore program state
903 prog->xfunction = oldf;
904 prog->globals.server->self = oldself;
914 void PF_droptofloor (void)
920 // assume failure if it returns early
921 PRVM_G_FLOAT(OFS_RETURN) = 0;
923 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
924 if (ent == prog->edicts)
926 VM_Warning("droptofloor: can not modify world entity\n");
929 if (ent->priv.server->free)
931 VM_Warning("droptofloor: can not modify free entity\n");
935 VectorCopy (ent->fields.server->origin, end);
938 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
940 if (trace.fraction != 1)
942 VectorCopy (trace.endpos, ent->fields.server->origin);
943 SV_LinkEdict (ent, false);
944 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
945 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
946 PRVM_G_FLOAT(OFS_RETURN) = 1;
947 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
948 ent->priv.server->suspendedinairflag = true;
956 void(float style, string value) lightstyle
959 void PF_lightstyle (void)
966 style = (int)PRVM_G_FLOAT(OFS_PARM0);
967 val = PRVM_G_STRING(OFS_PARM1);
969 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
970 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
973 // change the string in sv
974 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
976 // send message to all clients on this server
977 if (sv.state != ss_active)
980 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
982 if (client->active && client->netconnection)
984 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
985 MSG_WriteChar (&client->netconnection->message,style);
986 MSG_WriteString (&client->netconnection->message, val);
996 void PF_checkbottom (void)
998 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1006 void PF_pointcontents (void)
1008 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1015 Pick a vector for the player to shoot along
1016 vector aim(entity, missilespeed)
1021 prvm_edict_t *ent, *check, *bestent;
1022 vec3_t start, dir, end, bestdir;
1025 float dist, bestdist;
1028 // assume failure if it returns early
1029 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1030 // if sv_aim is so high it can't possibly accept anything, skip out early
1031 if (sv_aim.value >= 1)
1034 ent = PRVM_G_EDICT(OFS_PARM0);
1035 if (ent == prog->edicts)
1037 VM_Warning("aim: can not use world entity\n");
1040 if (ent->priv.server->free)
1042 VM_Warning("aim: can not use free entity\n");
1045 speed = PRVM_G_FLOAT(OFS_PARM1);
1047 VectorCopy (ent->fields.server->origin, start);
1050 // try sending a trace straight
1051 VectorCopy (prog->globals.server->v_forward, dir);
1052 VectorMA (start, 2048, dir, end);
1053 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1054 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1055 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1057 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1062 // try all possible entities
1063 VectorCopy (dir, bestdir);
1064 bestdist = sv_aim.value;
1067 check = PRVM_NEXT_EDICT(prog->edicts);
1068 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1070 prog->xfunction->builtinsprofile++;
1071 if (check->fields.server->takedamage != DAMAGE_AIM)
1075 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1076 continue; // don't aim at teammate
1077 for (j=0 ; j<3 ; j++)
1078 end[j] = check->fields.server->origin[j]
1079 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1080 VectorSubtract (end, start, dir);
1081 VectorNormalize (dir);
1082 dist = DotProduct (dir, prog->globals.server->v_forward);
1083 if (dist < bestdist)
1084 continue; // to far to turn
1085 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1086 if (tr.ent == check)
1087 { // can shoot at this one
1095 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1096 dist = DotProduct (dir, prog->globals.server->v_forward);
1097 VectorScale (prog->globals.server->v_forward, dist, end);
1099 VectorNormalize (end);
1100 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1104 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1112 This was a major timewaster in progs, so it was converted to C
1115 void PF_changeyaw (void)
1118 float ideal, current, move, speed;
1120 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1121 if (ent == prog->edicts)
1123 VM_Warning("changeyaw: can not modify world entity\n");
1126 if (ent->priv.server->free)
1128 VM_Warning("changeyaw: can not modify free entity\n");
1131 current = ANGLEMOD(ent->fields.server->angles[1]);
1132 ideal = ent->fields.server->ideal_yaw;
1133 speed = ent->fields.server->yaw_speed;
1135 if (current == ideal)
1137 move = ideal - current;
1138 if (ideal > current)
1159 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1167 void PF_changepitch (void)
1170 float ideal, current, move, speed;
1173 ent = PRVM_G_EDICT(OFS_PARM0);
1174 if (ent == prog->edicts)
1176 VM_Warning("changepitch: can not modify world entity\n");
1179 if (ent->priv.server->free)
1181 VM_Warning("changepitch: can not modify free entity\n");
1184 current = ANGLEMOD( ent->fields.server->angles[0] );
1185 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1186 ideal = val->_float;
1189 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1192 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1193 speed = val->_float;
1196 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1200 if (current == ideal)
1202 move = ideal - current;
1203 if (ideal > current)
1224 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1228 ===============================================================================
1232 ===============================================================================
1235 #define MSG_BROADCAST 0 // unreliable to all
1236 #define MSG_ONE 1 // reliable to one (msg_entity)
1237 #define MSG_ALL 2 // reliable to all
1238 #define MSG_INIT 3 // write to the init string
1239 #define MSG_ENTITY 5
1241 sizebuf_t *WriteDest (void)
1246 extern sizebuf_t *sv2csqcbuf;
1248 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1252 return &sv.datagram;
1255 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1256 entnum = PRVM_NUM_FOR_EDICT(ent);
1257 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1259 VM_Warning ("WriteDest: tried to write to non-client\n");
1260 return &sv.reliable_datagram;
1263 return &svs.clients[entnum-1].netconnection->message;
1266 VM_Warning ("WriteDest: bad destination\n");
1268 return &sv.reliable_datagram;
1280 void PF_WriteByte (void)
1282 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1285 void PF_WriteChar (void)
1287 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1290 void PF_WriteShort (void)
1292 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1295 void PF_WriteLong (void)
1297 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1300 void PF_WriteAngle (void)
1302 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1305 void PF_WriteCoord (void)
1307 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1310 void PF_WriteString (void)
1312 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1315 void PF_WriteUnterminatedString (void)
1317 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1321 void PF_WriteEntity (void)
1323 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1326 //////////////////////////////////////////////////////////
1328 void PF_makestatic (void)
1333 ent = PRVM_G_EDICT(OFS_PARM0);
1334 if (ent == prog->edicts)
1336 VM_Warning("makestatic: can not modify world entity\n");
1339 if (ent->priv.server->free)
1341 VM_Warning("makestatic: can not modify free entity\n");
1346 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1351 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1352 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1353 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1357 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1358 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1359 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1362 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1363 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1364 for (i=0 ; i<3 ; i++)
1366 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1367 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1370 // throw the entity away now
1374 //=============================================================================
1381 void PF_setspawnparms (void)
1387 ent = PRVM_G_EDICT(OFS_PARM0);
1388 i = PRVM_NUM_FOR_EDICT(ent);
1389 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1391 Con_Print("tried to setspawnparms on a non-client\n");
1395 // copy spawn parms out of the client_t
1396 client = svs.clients + i-1;
1397 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1398 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1405 Returns a color vector indicating the lighting at the requested point.
1407 (Internal Operation note: actually measures the light beneath the point, just like
1408 the model lighting on the client)
1413 void PF_getlight (void)
1415 vec3_t ambientcolor, diffusecolor, diffusenormal;
1417 p = PRVM_G_VECTOR(OFS_PARM0);
1418 VectorClear(ambientcolor);
1419 VectorClear(diffusecolor);
1420 VectorClear(diffusenormal);
1421 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1422 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1423 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1426 void PF_registercvar (void)
1428 const char *name, *value;
1429 name = PRVM_G_STRING(OFS_PARM0);
1430 value = PRVM_G_STRING(OFS_PARM1);
1431 PRVM_G_FLOAT(OFS_RETURN) = 0;
1433 // first check to see if it has already been defined
1434 if (Cvar_FindVar (name))
1437 // check for overlap with a command
1438 if (Cmd_Exists (name))
1440 VM_Warning("PF_registercvar: %s is a command\n", name);
1444 Cvar_Get(name, value, 0);
1446 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1451 unsigned char type; // 1/2/8 or other value if isn't used
1455 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1456 static int vm_autosentstats_last;
1458 void VM_AutoSentStats_Clear (void)
1460 if(vm_autosentstats)
1462 Z_Free(vm_autosentstats);
1463 vm_autosentstats = NULL;
1464 vm_autosentstats_last = -1;
1468 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1469 #define VM_SENDSTAT(a,b,c)\
1472 if((c)==(unsigned char)(c))\
1474 MSG_WriteByte((a), svc_updatestatubyte);\
1475 MSG_WriteByte((a), (b));\
1476 MSG_WriteByte((a), (c));\
1480 MSG_WriteByte((a), svc_updatestat);\
1481 MSG_WriteByte((a), (b));\
1482 MSG_WriteLong((a), (c));\
1486 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1498 if(!vm_autosentstats)
1501 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);
1503 for(i=0; i<vm_autosentstats_last+1 ;i++)
1505 if(!vm_autosentstats[i].type)
1507 switch(vm_autosentstats[i].type)
1511 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1519 stats[i+32] = si[0];
1520 stats[i+33] = si[1];
1521 stats[i+34] = si[2];
1522 stats[i+35] = si[3];
1526 VM_SENDSTAT(msg, i+32, si[0]);
1527 VM_SENDSTAT(msg, i+33, si[1]);
1528 VM_SENDSTAT(msg, i+34, si[2]);
1529 VM_SENDSTAT(msg, i+35, si[3]);
1535 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1536 k.i = LittleLong (k.i);
1540 VM_SENDSTAT(msg, i+32, k.i);
1544 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1548 VM_SENDSTAT(msg, i+32, v);
1556 // void(float index, float type, .void field) SV_AddStat = #470;
1557 // Set up an auto-sent player stat.
1558 // Client's get thier own fields sent to them. Index may not be less than 32.
1559 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1560 // 1: string (4 stats carrying a total of 16 charactures)
1561 // 2: float (one stat, float converted to an integer for transportation)
1562 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1563 void PF_SV_AddStat (void)
1568 if(!vm_autosentstats)
1570 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1571 if(!vm_autosentstats)
1573 VM_Warning("PF_SV_AddStat: not enough memory\n");
1577 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1578 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1579 off = PRVM_G_INT (OFS_PARM2);
1584 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1587 if(i >= (MAX_CL_STATS-32))
1589 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1592 if(i > (MAX_CL_STATS-32-4) && type == 1)
1594 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1597 vm_autosentstats[i].type = type;
1598 vm_autosentstats[i].fieldoffset = off;
1599 if(vm_autosentstats_last < i)
1600 vm_autosentstats_last = i;
1607 copies data from one entity to another
1609 copyentity(src, dst)
1612 void PF_copyentity (void)
1614 prvm_edict_t *in, *out;
1615 in = PRVM_G_EDICT(OFS_PARM0);
1616 if (in == prog->edicts)
1618 VM_Warning("copyentity: can not read world entity\n");
1621 if (in->priv.server->free)
1623 VM_Warning("copyentity: can not read free entity\n");
1626 out = PRVM_G_EDICT(OFS_PARM1);
1627 if (out == prog->edicts)
1629 VM_Warning("copyentity: can not modify world entity\n");
1632 if (out->priv.server->free)
1634 VM_Warning("copyentity: can not modify free entity\n");
1637 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1645 sets the color of a client and broadcasts the update to all connected clients
1647 setcolor(clientent, value)
1650 void PF_setcolor (void)
1656 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1657 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1659 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1661 Con_Print("tried to setcolor a non-client\n");
1665 client = svs.clients + entnum-1;
1668 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1670 client->edict->fields.server->team = (i & 15) + 1;
1673 if (client->old_colors != client->colors)
1675 client->old_colors = client->colors;
1676 // send notification to all clients
1677 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1678 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1679 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1687 effect(origin, modelname, startframe, framecount, framerate)
1690 void PF_effect (void)
1694 s = PRVM_G_STRING(OFS_PARM1);
1697 VM_Warning("effect: no model specified\n");
1701 i = SV_ModelIndex(s, 1);
1704 VM_Warning("effect: model not precached\n");
1707 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1710 void PF_te_blood (void)
1712 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1714 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1715 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1721 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1722 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1723 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1725 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1728 void PF_te_bloodshower (void)
1730 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1732 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1733 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
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_FLOAT(OFS_PARM2), sv.protocol);
1745 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1748 void PF_te_explosionrgb (void)
1750 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1751 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1755 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1757 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1758 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1759 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1762 void PF_te_particlecube (void)
1764 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1766 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1767 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1771 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1781 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1783 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1784 // gravity true/false
1785 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1787 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1790 void PF_te_particlerain (void)
1792 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1794 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1795 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1799 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1809 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1811 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1814 void PF_te_particlesnow (void)
1816 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1818 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1819 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
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);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1833 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1835 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1838 void PF_te_spark (void)
1840 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1842 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1843 MSG_WriteByte(&sv.datagram, TE_SPARK);
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);
1849 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1850 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1851 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1853 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1856 void PF_te_gunshotquad (void)
1858 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1859 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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_spikequad (void)
1868 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1869 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
1878 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1879 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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);
1886 void PF_te_explosionquad (void)
1888 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1889 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1893 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1896 void PF_te_smallflash (void)
1898 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1899 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1903 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1906 void PF_te_customflash (void)
1908 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1910 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1911 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1915 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1917 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1919 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1921 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1922 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1923 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1926 void PF_te_gunshot (void)
1928 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1929 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1933 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1936 void PF_te_spike (void)
1938 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1939 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1943 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1946 void PF_te_superspike (void)
1948 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1949 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1953 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1956 void PF_te_explosion (void)
1958 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1966 void PF_te_tarexplosion (void)
1968 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1969 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1976 void PF_te_wizspike (void)
1978 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1986 void PF_te_knightspike (void)
1988 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1989 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1993 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1996 void PF_te_lavasplash (void)
1998 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2006 void PF_te_teleport (void)
2008 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2009 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
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_explosion2 (void)
2018 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2019 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
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_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2026 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2029 void PF_te_lightning1 (void)
2031 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2032 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2034 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2038 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2045 void PF_te_lightning2 (void)
2047 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2048 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2050 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2054 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2061 void PF_te_lightning3 (void)
2063 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2064 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2066 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2070 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2077 void PF_te_beam (void)
2079 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2080 MSG_WriteByte(&sv.datagram, TE_BEAM);
2082 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2086 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2093 void PF_te_plasmaburn (void)
2095 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2096 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2099 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2102 void PF_te_flamejet (void)
2104 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2105 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2109 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2115 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2118 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2121 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2123 bestdist = 1000000000;
2125 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2127 // clip original point to each triangle of the surface and find the
2128 // triangle that is closest
2129 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2130 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2131 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2132 TriangleNormal(v[0], v[1], v[2], facenormal);
2133 VectorNormalize(facenormal);
2134 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2135 VectorMA(p, offsetdist, facenormal, temp);
2136 for (j = 0, k = 2;j < 3;k = j, j++)
2138 VectorSubtract(v[k], v[j], edgenormal);
2139 CrossProduct(edgenormal, facenormal, sidenormal);
2140 VectorNormalize(sidenormal);
2141 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2143 VectorMA(temp, offsetdist, sidenormal, temp);
2145 dist = VectorDistance2(temp, p);
2146 if (bestdist > dist)
2149 VectorCopy(temp, out);
2154 static model_t *getmodel(prvm_edict_t *ed)
2157 if (!ed || ed->priv.server->free)
2159 modelindex = (int)ed->fields.server->modelindex;
2160 if (modelindex < 1 || modelindex >= MAX_MODELS)
2162 return sv.models[modelindex];
2165 static msurface_t *getsurface(model_t *model, int surfacenum)
2167 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2169 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2173 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2174 void PF_getsurfacenumpoints(void)
2177 msurface_t *surface;
2178 // return 0 if no such surface
2179 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2181 PRVM_G_FLOAT(OFS_RETURN) = 0;
2185 // note: this (incorrectly) assumes it is a simple polygon
2186 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2188 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2189 void PF_getsurfacepoint(void)
2193 msurface_t *surface;
2195 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2196 ed = PRVM_G_EDICT(OFS_PARM0);
2197 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2199 // note: this (incorrectly) assumes it is a simple polygon
2200 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2201 if (pointnum < 0 || pointnum >= surface->num_vertices)
2203 // FIXME: implement rotation/scaling
2204 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2206 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2207 void PF_getsurfacenormal(void)
2210 msurface_t *surface;
2212 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2213 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2215 // FIXME: implement rotation/scaling
2216 // note: this (incorrectly) assumes it is a simple polygon
2217 // note: this only returns the first triangle, so it doesn't work very
2218 // well for curved surfaces or arbitrary meshes
2219 TriangleNormal((model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 3, (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2220 VectorNormalize(normal);
2221 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2223 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2224 void PF_getsurfacetexture(void)
2227 msurface_t *surface;
2228 PRVM_G_INT(OFS_RETURN) = 0;
2229 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2231 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2233 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2234 void PF_getsurfacenearpoint(void)
2236 int surfacenum, best;
2238 vec_t dist, bestdist;
2241 msurface_t *surface;
2243 PRVM_G_FLOAT(OFS_RETURN) = -1;
2244 ed = PRVM_G_EDICT(OFS_PARM0);
2245 point = PRVM_G_VECTOR(OFS_PARM1);
2247 if (!ed || ed->priv.server->free)
2249 model = getmodel(ed);
2250 if (!model || !model->num_surfaces)
2253 // FIXME: implement rotation/scaling
2254 VectorSubtract(point, ed->fields.server->origin, p);
2256 bestdist = 1000000000;
2257 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2259 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2260 // first see if the nearest point on the surface's box is closer than the previous match
2261 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2262 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2263 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2264 dist = VectorLength2(clipped);
2265 if (dist < bestdist)
2267 // it is, check the nearest point on the actual geometry
2268 clippointtosurface(model, surface, p, clipped);
2269 VectorSubtract(clipped, p, clipped);
2270 dist += VectorLength2(clipped);
2271 if (dist < bestdist)
2273 // that's closer too, store it as the best match
2279 PRVM_G_FLOAT(OFS_RETURN) = best;
2281 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2282 void PF_getsurfaceclippedpoint(void)
2286 msurface_t *surface;
2288 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2289 ed = PRVM_G_EDICT(OFS_PARM0);
2290 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2292 // FIXME: implement rotation/scaling
2293 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2294 clippointtosurface(model, surface, p, out);
2295 // FIXME: implement rotation/scaling
2296 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2299 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2300 //this function originally written by KrimZon, made shorter by LordHavoc
2301 void PF_clientcommand (void)
2303 client_t *temp_client;
2306 //find client for this entity
2307 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2308 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2310 Con_Print("PF_clientcommand: entity is not a client\n");
2314 temp_client = host_client;
2315 host_client = svs.clients + i;
2316 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2317 host_client = temp_client;
2320 //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)
2321 void PF_setattachment (void)
2323 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2324 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2325 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2330 if (e == prog->edicts)
2332 VM_Warning("setattachment: can not modify world entity\n");
2335 if (e->priv.server->free)
2337 VM_Warning("setattachment: can not modify free entity\n");
2341 if (tagentity == NULL)
2342 tagentity = prog->edicts;
2344 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2346 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2348 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2351 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2353 modelindex = (int)tagentity->fields.server->modelindex;
2354 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2356 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2358 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);
2361 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));
2365 /////////////////////////////////////////
2366 // DP_MD3_TAGINFO extension coded by VorteX
2368 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2373 i = (int)e->fields.server->modelindex;
2374 if (i < 1 || i >= MAX_MODELS)
2376 model = sv.models[i];
2378 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2381 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2383 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2387 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);
2389 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 * cl_viewmodel_scale.value);
2392 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2398 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2399 && (model = sv.models[(int)ent->fields.server->modelindex])
2400 && model->animscenes)
2402 // if model has wrong frame, engine automatically switches to model first frame
2403 frame = (int)ent->fields.server->frame;
2404 if (frame < 0 || frame >= model->numframes)
2406 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2408 *out = identitymatrix;
2412 // Warnings/errors code:
2413 // 0 - normal (everything all-right)
2416 // 3 - null or non-precached model
2417 // 4 - no tags with requested index
2418 // 5 - runaway loop at attachment chain
2419 extern cvar_t cl_bob;
2420 extern cvar_t cl_bobcycle;
2421 extern cvar_t cl_bobup;
2422 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2426 int modelindex, attachloop;
2427 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2430 *out = identitymatrix; // warnings and errors return identical matrix
2432 if (ent == prog->edicts)
2434 if (ent->priv.server->free)
2437 modelindex = (int)ent->fields.server->modelindex;
2438 if (modelindex <= 0 || modelindex > MAX_MODELS)
2441 model = sv.models[modelindex];
2443 tagmatrix = identitymatrix;
2444 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2448 if (attachloop >= 256) // prevent runaway looping
2450 // apply transformation by child's tagindex on parent entity and then
2451 // by parent entity itself
2452 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2453 if (ret && attachloop == 0)
2455 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2456 SV_GetEntityMatrix(ent, &entitymatrix, false);
2457 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2458 // next iteration we process the parent entity
2459 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2461 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2462 ent = PRVM_EDICT_NUM(val->edict);
2469 // RENDER_VIEWMODEL magic
2470 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2472 Matrix4x4_Copy(&tagmatrix, out);
2473 ent = PRVM_EDICT_NUM(val->edict);
2475 SV_GetEntityMatrix(ent, &entitymatrix, true);
2476 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2479 // Cl_bob, ported from rendering code
2480 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2483 // LordHavoc: this code is *weird*, but not replacable (I think it
2484 // should be done in QC on the server, but oh well, quake is quake)
2485 // LordHavoc: figured out bobup: the time at which the sin is at 180
2486 // degrees (which allows lengthening or squishing the peak or valley)
2487 cycle = sv.time/cl_bobcycle.value;
2488 cycle -= (int)cycle;
2489 if (cycle < cl_bobup.value)
2490 cycle = sin(M_PI * cycle / cl_bobup.value);
2492 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2493 // bob is proportional to velocity in the xy plane
2494 // (don't count Z, or jumping messes it up)
2495 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;
2496 bob = bob*0.3 + bob*0.7*cycle;
2497 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2504 //float(entity ent, string tagname) gettagindex;
2506 void PF_gettagindex (void)
2508 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2509 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2510 int modelindex, tag_index;
2512 if (ent == prog->edicts)
2514 VM_Warning("gettagindex: can't affect world entity\n");
2517 if (ent->priv.server->free)
2519 VM_Warning("gettagindex: can't affect free entity\n");
2523 modelindex = (int)ent->fields.server->modelindex;
2525 if (modelindex <= 0 || modelindex > MAX_MODELS)
2526 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2529 tag_index = SV_GetTagIndex(ent, tag_name);
2531 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2533 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2536 //vector(entity ent, float tagindex) gettaginfo;
2537 void PF_gettaginfo (void)
2539 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2540 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2541 matrix4x4_t tag_matrix;
2544 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2545 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2550 VM_Warning("gettagindex: can't affect world entity\n");
2553 VM_Warning("gettagindex: can't affect free entity\n");
2556 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2559 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2562 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2567 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2568 void PF_dropclient (void)
2571 client_t *oldhostclient;
2572 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2573 if (clientnum < 0 || clientnum >= svs.maxclients)
2575 VM_Warning("dropclient: not a client\n");
2578 if (!svs.clients[clientnum].active)
2580 VM_Warning("dropclient: that client slot is not connected\n");
2583 oldhostclient = host_client;
2584 host_client = svs.clients + clientnum;
2585 SV_DropClient(false);
2586 host_client = oldhostclient;
2589 //entity() spawnclient (DP_SV_BOTCLIENT)
2590 void PF_spawnclient (void)
2594 prog->xfunction->builtinsprofile += 2;
2596 for (i = 0;i < svs.maxclients;i++)
2598 if (!svs.clients[i].active)
2600 prog->xfunction->builtinsprofile += 100;
2601 SV_ConnectClient (i, NULL);
2602 // this has to be set or else ClientDisconnect won't be called
2603 // we assume the qc will call ClientConnect...
2604 svs.clients[i].clientconnectcalled = true;
2605 ed = PRVM_EDICT_NUM(i + 1);
2609 VM_RETURN_EDICT(ed);
2612 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2613 void PF_clienttype (void)
2616 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2617 if (clientnum < 0 || clientnum >= svs.maxclients)
2618 PRVM_G_FLOAT(OFS_RETURN) = 3;
2619 else if (!svs.clients[clientnum].active)
2620 PRVM_G_FLOAT(OFS_RETURN) = 0;
2621 else if (svs.clients[clientnum].netconnection)
2622 PRVM_G_FLOAT(OFS_RETURN) = 1;
2624 PRVM_G_FLOAT(OFS_RETURN) = 2;
2627 void PF_edict_num (void)
2629 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2632 prvm_builtin_t vm_sv_builtins[] = {
2634 PF_makevectors, // #1 void(vector ang) makevectors
2635 PF_setorigin, // #2 void(entity e, vector o) setorigin
2636 PF_setmodel, // #3 void(entity e, string m) setmodel
2637 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2638 NULL, // #5 void(entity e, vector min, vector max) setabssize
2639 VM_break, // #6 void() break
2640 VM_random, // #7 float() random
2641 PF_sound, // #8 void(entity e, float chan, string samp) sound
2642 VM_normalize, // #9 vector(vector v) normalize
2643 VM_error, // #10 void(string e) error
2644 VM_objerror, // #11 void(string e) objerror
2645 VM_vlen, // #12 float(vector v) vlen
2646 VM_vectoyaw, // #13 float(vector v) vectoyaw
2647 VM_spawn, // #14 entity() spawn
2648 VM_remove, // #15 void(entity e) remove
2649 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2650 PF_checkclient, // #17 entity() clientlist
2651 VM_find, // #18 entity(entity start, .string fld, string match) find
2652 PF_precache_sound, // #19 void(string s) precache_sound
2653 PF_precache_model, // #20 void(string s) precache_model
2654 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2655 PF_findradius, // #22 entity(vector org, float rad) findradius
2656 VM_bprint, // #23 void(string s) bprint
2657 PF_sprint, // #24 void(entity client, string s) sprint
2658 VM_dprint, // #25 void(string s) dprint
2659 VM_ftos, // #26 void(string s) ftos
2660 VM_vtos, // #27 void(string s) vtos
2661 VM_coredump, // #28 void() coredump
2662 VM_traceon, // #29 void() traceon
2663 VM_traceoff, // #30 void() traceoff
2664 VM_eprint, // #31 void(entity e) eprint
2665 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2667 PF_droptofloor, // #34 float() droptofloor
2668 PF_lightstyle, // #35 void(float style, string value) lightstyle
2669 VM_rint, // #36 float(float v) rint
2670 VM_floor, // #37 float(float v) floor
2671 VM_ceil, // #38 float(float v) ceil
2673 PF_checkbottom, // #40 float(entity e) checkbottom
2674 PF_pointcontents, // #41 float(vector v) pointcontents
2676 VM_fabs, // #43 float(float f) fabs
2677 PF_aim, // #44 vector(entity e, float speed) aim
2678 VM_cvar, // #45 float(string s) cvar
2679 VM_localcmd, // #46 void(string s) localcmd
2680 VM_nextent, // #47 entity(entity e) nextent
2681 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2682 PF_changeyaw, // #49 void() ChangeYaw
2684 VM_vectoangles, // #51 vector(vector v) vectoangles
2685 PF_WriteByte, // #52 void(float to, float f) WriteByte
2686 PF_WriteChar, // #53 void(float to, float f) WriteChar
2687 PF_WriteShort, // #54 void(float to, float f) WriteShort
2688 PF_WriteLong, // #55 void(float to, float f) WriteLong
2689 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2690 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2691 PF_WriteString, // #58 void(float to, string s) WriteString
2692 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2693 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2694 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2695 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2696 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2697 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2698 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2700 SV_MoveToGoal, // #67 void(float step) movetogoal
2701 PF_precache_file, // #68 string(string s) precache_file
2702 PF_makestatic, // #69 void(entity e) makestatic
2703 VM_changelevel, // #70 void(string s) changelevel
2705 VM_cvar_set, // #72 void(string var, string val) cvar_set
2706 PF_centerprint, // #73 void(entity client, strings) centerprint
2707 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2708 PF_precache_model, // #75 string(string s) precache_model2
2709 PF_precache_sound, // #76 string(string s) precache_sound2
2710 PF_precache_file, // #77 string(string s) precache_file2
2711 PF_setspawnparms, // #78 void(entity e) setspawnparms
2714 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2723 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2724 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2725 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2726 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2727 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2728 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2729 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2730 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2731 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2732 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2743 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2744 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2745 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2746 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2747 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2748 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2749 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2750 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2751 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2752 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2753 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2754 // FTEQW range #200-#299
2773 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2783 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2784 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2785 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2786 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2787 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2788 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2789 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2790 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2791 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2792 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2793 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2794 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2795 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2796 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2797 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2798 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2799 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2800 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2801 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2802 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2803 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2804 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2805 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2806 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2807 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2808 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2809 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2810 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2811 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2812 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2813 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2814 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2815 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2816 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2817 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2818 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2819 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2820 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2821 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2822 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2823 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2824 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2825 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2826 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2827 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2828 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2829 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2830 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2831 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2832 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2833 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2834 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2835 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2836 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2837 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2838 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2839 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2840 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2841 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2843 PF_edict_num, // #459 entity(float num) (??)
2844 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2845 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2846 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2847 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2848 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2849 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2850 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2851 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2852 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2853 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2854 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2855 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2856 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2857 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2858 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2859 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2860 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2861 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS)
2864 e10, e10 // #480-499 (LordHavoc)
2867 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2869 void VM_SV_Cmd_Init(void)
2874 void VM_SV_Cmd_Reset(void)