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 =
12 "DP_CON_ALIASPARAMETERS "
31 "DP_ENT_CUSTOMCOLORMAP "
32 "DP_ENT_EXTERIORMODELTOCLIENT "
34 "DP_ENT_LOWPRECISION "
37 "DP_GFX_EXTERNALTEXTURES "
38 "DP_GFX_EXTERNALTEXTURES_PERMAP "
40 "DP_GFX_QUAKE3MODELTAGS "
44 "DP_HALFLIFE_MAP_CVAR "
50 "DP_MOVETYPEBOUNCEMISSILE "
52 "DP_QC_ASINACOSATANATAN2TAN "
58 "DP_QC_FINDCHAINFLAGS "
59 "DP_QC_FINDCHAINFLOAT "
62 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
67 "DP_QC_MULTIPLETEMPSTRINGS "
69 "DP_QC_SINCOSSQRTPOW "
71 "DP_QC_STRINGBUFFERS "
72 "DP_QC_STRINGCOLORFUNCTIONS "
73 "DP_QC_UNLIMITEDTEMPSTRINGS "
76 "DP_QC_TRACE_MOVETYPE_HITMODEL "
77 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
78 "DP_QC_VECTORVECTORS "
84 "DP_SND_DIRECTIONLESSATTNNONE "
93 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
94 "DP_SV_DRAWONLYTOCLIENT "
97 "DP_SV_ENTITYCONTENTSTRANSITION "
98 "DP_SV_NODRAWTOCLIENT "
100 "DP_SV_PLAYERPHYSICS "
101 "DP_SV_PRECACHEANYTIME "
104 "DP_SV_ROTATINGBMODEL "
107 "DP_SV_WRITEUNTERMINATEDSTRING "
111 "DP_TE_EXPLOSIONRGB "
113 "DP_TE_PARTICLECUBE "
114 "DP_TE_PARTICLERAIN "
115 "DP_TE_PARTICLESNOW "
117 "DP_TE_QUADEFFECTS1 "
120 "DP_TE_STANDARDEFFECTBUILTINS "
121 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
124 //"EXT_CSQC " // not ready yet
126 "KRIMZON_SV_PARSECLIENTCOMMAND "
130 "PRYDON_CLIENTCURSOR "
131 "TENEBRAE_GFX_DLIGHTS "
133 "NEXUIZ_PLAYERMODEL "
140 Writes new values for v_forward, v_up, and v_right based on angles
144 void PF_makevectors (void)
146 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
153 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.
155 setorigin (entity, origin)
158 void PF_setorigin (void)
163 e = PRVM_G_EDICT(OFS_PARM0);
164 if (e == prog->edicts)
166 VM_Warning("setorigin: can not modify world entity\n");
169 if (e->priv.server->free)
171 VM_Warning("setorigin: can not modify free entity\n");
174 org = PRVM_G_VECTOR(OFS_PARM1);
175 VectorCopy (org, e->fields.server->origin);
176 SV_LinkEdict (e, false);
180 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
184 for (i=0 ; i<3 ; i++)
186 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
188 // set derived values
189 VectorCopy (min, e->fields.server->mins);
190 VectorCopy (max, e->fields.server->maxs);
191 VectorSubtract (max, min, e->fields.server->size);
193 SV_LinkEdict (e, false);
200 the size box is rotated by the current angle
201 LordHavoc: no it isn't...
203 setsize (entity, minvector, maxvector)
206 void PF_setsize (void)
211 e = PRVM_G_EDICT(OFS_PARM0);
212 if (e == prog->edicts)
214 VM_Warning("setsize: can not modify world entity\n");
217 if (e->priv.server->free)
219 VM_Warning("setsize: can not modify free entity\n");
222 min = PRVM_G_VECTOR(OFS_PARM1);
223 max = PRVM_G_VECTOR(OFS_PARM2);
224 SetMinMaxSize (e, min, max, false);
232 setmodel(entity, model)
235 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
236 void PF_setmodel (void)
242 e = PRVM_G_EDICT(OFS_PARM0);
243 if (e == prog->edicts)
245 VM_Warning("setmodel: can not modify world entity\n");
248 if (e->priv.server->free)
250 VM_Warning("setmodel: can not modify free entity\n");
253 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
254 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
255 e->fields.server->modelindex = i;
261 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
262 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
264 SetMinMaxSize (e, quakemins, quakemaxs, true);
267 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
274 single print to a specific client
276 sprint(clientent, value)
279 void PF_sprint (void)
283 char string[VM_STRINGTEMP_LENGTH];
285 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
287 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
289 VM_Warning("tried to centerprint to a non-client\n");
293 client = svs.clients + entnum-1;
294 if (!client->netconnection)
297 VM_VarString(1, string, sizeof(string));
298 MSG_WriteChar(&client->netconnection->message,svc_print);
299 MSG_WriteString(&client->netconnection->message, string);
307 single print to a specific client
309 centerprint(clientent, value)
312 void PF_centerprint (void)
316 char string[VM_STRINGTEMP_LENGTH];
318 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
320 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
322 VM_Warning("tried to centerprint to a non-client\n");
326 client = svs.clients + entnum-1;
327 if (!client->netconnection)
330 VM_VarString(1, string, sizeof(string));
331 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
332 MSG_WriteString(&client->netconnection->message, string);
339 particle(origin, color, count)
342 void PF_particle (void)
348 org = PRVM_G_VECTOR(OFS_PARM0);
349 dir = PRVM_G_VECTOR(OFS_PARM1);
350 color = PRVM_G_FLOAT(OFS_PARM2);
351 count = PRVM_G_FLOAT(OFS_PARM3);
352 SV_StartParticle (org, dir, (int)color, (int)count);
362 void PF_ambientsound (void)
366 float vol, attenuation;
369 pos = PRVM_G_VECTOR (OFS_PARM0);
370 samp = PRVM_G_STRING(OFS_PARM1);
371 vol = PRVM_G_FLOAT(OFS_PARM2);
372 attenuation = PRVM_G_FLOAT(OFS_PARM3);
374 // check to see if samp was properly precached
375 soundnum = SV_SoundIndex(samp, 1);
383 // add an svc_spawnambient command to the level signon packet
386 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
388 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
390 MSG_WriteVector(&sv.signon, pos, sv.protocol);
393 MSG_WriteShort (&sv.signon, soundnum);
395 MSG_WriteByte (&sv.signon, soundnum);
397 MSG_WriteByte (&sv.signon, (int)(vol*255));
398 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
406 Each entity can have eight independant sound sources, like voice,
409 Channel 0 is an auto-allocate channel, the others override anything
410 already running on that entity/channel pair.
412 An attenuation of 0 will play full volume everywhere in the level.
413 Larger attenuations will drop off.
421 prvm_edict_t *entity;
425 entity = PRVM_G_EDICT(OFS_PARM0);
426 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
427 sample = PRVM_G_STRING(OFS_PARM2);
428 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
429 attenuation = PRVM_G_FLOAT(OFS_PARM4);
431 if (volume < 0 || volume > 255)
433 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
437 if (attenuation < 0 || attenuation > 4)
439 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
443 if (channel < 0 || channel > 7)
445 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
449 SV_StartSound (entity, channel, sample, volume, attenuation);
456 Used for use tracing and shot targeting
457 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
458 if the tryents flag is set.
460 traceline (vector1, vector2, tryents)
463 void PF_traceline (void)
471 prog->xfunction->builtinsprofile += 30;
473 v1 = PRVM_G_VECTOR(OFS_PARM0);
474 v2 = PRVM_G_VECTOR(OFS_PARM1);
475 move = (int)PRVM_G_FLOAT(OFS_PARM2);
476 ent = PRVM_G_EDICT(OFS_PARM3);
478 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]))
479 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));
481 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
483 prog->globals.server->trace_allsolid = trace.allsolid;
484 prog->globals.server->trace_startsolid = trace.startsolid;
485 prog->globals.server->trace_fraction = trace.fraction;
486 prog->globals.server->trace_inwater = trace.inwater;
487 prog->globals.server->trace_inopen = trace.inopen;
488 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
489 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
490 prog->globals.server->trace_plane_dist = trace.plane.dist;
492 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
494 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
495 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
496 val->_float = trace.startsupercontents;
497 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
498 val->_float = trace.hitsupercontents;
499 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
500 val->_float = trace.hitq3surfaceflags;
501 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
503 if (trace.hittexture)
504 val->string = PRVM_SetTempString(trace.hittexture->name);
515 Used for use tracing and shot targeting
516 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
517 if the tryents flag is set.
519 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
522 // LordHavoc: added this for my own use, VERY useful, similar to traceline
523 void PF_tracebox (void)
525 float *v1, *v2, *m1, *m2;
531 prog->xfunction->builtinsprofile += 30;
533 v1 = PRVM_G_VECTOR(OFS_PARM0);
534 m1 = PRVM_G_VECTOR(OFS_PARM1);
535 m2 = PRVM_G_VECTOR(OFS_PARM2);
536 v2 = PRVM_G_VECTOR(OFS_PARM3);
537 move = (int)PRVM_G_FLOAT(OFS_PARM4);
538 ent = PRVM_G_EDICT(OFS_PARM5);
540 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]))
541 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));
543 trace = SV_Move (v1, m1, m2, v2, move, ent);
545 prog->globals.server->trace_allsolid = trace.allsolid;
546 prog->globals.server->trace_startsolid = trace.startsolid;
547 prog->globals.server->trace_fraction = trace.fraction;
548 prog->globals.server->trace_inwater = trace.inwater;
549 prog->globals.server->trace_inopen = trace.inopen;
550 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
551 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
552 prog->globals.server->trace_plane_dist = trace.plane.dist;
554 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
556 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
557 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
558 val->_float = trace.startsupercontents;
559 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
560 val->_float = trace.hitsupercontents;
561 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
562 val->_float = trace.hitq3surfaceflags;
563 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
565 if (trace.hittexture)
566 val->string = PRVM_SetTempString(trace.hittexture->name);
572 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
573 void PF_tracetoss (void)
577 prvm_edict_t *ignore;
580 prog->xfunction->builtinsprofile += 600;
582 ent = PRVM_G_EDICT(OFS_PARM0);
583 if (ent == prog->edicts)
585 VM_Warning("tracetoss: can not use world entity\n");
588 ignore = PRVM_G_EDICT(OFS_PARM1);
590 trace = SV_Trace_Toss (ent, ignore);
592 prog->globals.server->trace_allsolid = trace.allsolid;
593 prog->globals.server->trace_startsolid = trace.startsolid;
594 prog->globals.server->trace_fraction = trace.fraction;
595 prog->globals.server->trace_inwater = trace.inwater;
596 prog->globals.server->trace_inopen = trace.inopen;
597 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
598 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
599 prog->globals.server->trace_plane_dist = trace.plane.dist;
601 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
603 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
604 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
605 val->_float = trace.startsupercontents;
606 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
607 val->_float = trace.hitsupercontents;
608 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
609 val->_float = trace.hitq3surfaceflags;
610 if ((val = PRVM_GETGLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
612 if (trace.hittexture)
613 val->string = PRVM_SetTempString(trace.hittexture->name);
624 Returns true if the given entity can move to the given position from it's
625 current position by walking or rolling.
627 scalar checkpos (entity, vector)
630 void PF_checkpos (void)
634 //============================================================================
637 unsigned char checkpvs[MAX_MAP_LEAFS/8];
639 int PF_newcheckclient (int check)
645 // cycle to the next one
647 check = bound(1, check, svs.maxclients);
648 if (check == svs.maxclients)
656 prog->xfunction->builtinsprofile++;
658 if (i == svs.maxclients+1)
660 // look up the client's edict
661 ent = PRVM_EDICT_NUM(i);
662 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
663 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
665 // found a valid client (possibly the same one again)
669 // get the PVS for the entity
670 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
672 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
673 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
682 Returns a client (or object that has a client enemy) that would be a
685 If there is more than one valid option, they are cycled each frame
687 If (self.origin + self.viewofs) is not in the PVS of the current target,
688 it is not returned at all.
693 int c_invis, c_notvis;
694 void PF_checkclient (void)
696 prvm_edict_t *ent, *self;
699 // find a new check if on a new frame
700 if (sv.time - sv.lastchecktime >= 0.1)
702 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
703 sv.lastchecktime = sv.time;
706 // return check if it might be visible
707 ent = PRVM_EDICT_NUM(sv.lastcheck);
708 if (ent->priv.server->free || ent->fields.server->health <= 0)
710 VM_RETURN_EDICT(prog->edicts);
714 // if current entity can't possibly see the check entity, return 0
715 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
716 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
717 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
720 VM_RETURN_EDICT(prog->edicts);
724 // might be able to see it
726 VM_RETURN_EDICT(ent);
729 //============================================================================
736 Sends text over to the client's execution buffer
738 stuffcmd (clientent, value, ...)
741 void PF_stuffcmd (void)
745 char string[VM_STRINGTEMP_LENGTH];
747 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
748 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
750 VM_Warning("Can't stuffcmd to a non-client\n");
754 VM_VarString(1, string, sizeof(string));
757 host_client = svs.clients + entnum-1;
758 Host_ClientCommands ("%s", string);
766 Returns a chain of entities that have origins within a spherical area
768 findradius (origin, radius)
771 void PF_findradius (void)
773 prvm_edict_t *ent, *chain;
774 vec_t radius, radius2;
775 vec3_t org, eorg, mins, maxs;
778 prvm_edict_t *touchedicts[MAX_EDICTS];
780 chain = (prvm_edict_t *)prog->edicts;
782 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
783 radius = PRVM_G_FLOAT(OFS_PARM1);
784 radius2 = radius * radius;
786 mins[0] = org[0] - (radius + 1);
787 mins[1] = org[1] - (radius + 1);
788 mins[2] = org[2] - (radius + 1);
789 maxs[0] = org[0] + (radius + 1);
790 maxs[1] = org[1] + (radius + 1);
791 maxs[2] = org[2] + (radius + 1);
792 numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
793 if (numtouchedicts > MAX_EDICTS)
795 // this never happens
796 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
797 numtouchedicts = MAX_EDICTS;
799 for (i = 0;i < numtouchedicts;i++)
801 ent = touchedicts[i];
802 prog->xfunction->builtinsprofile++;
803 // Quake did not return non-solid entities but darkplaces does
804 // (note: this is the reason you can't blow up fallen zombies)
805 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
807 // LordHavoc: compare against bounding box rather than center so it
808 // doesn't miss large objects, and use DotProduct instead of Length
809 // for a major speedup
810 VectorSubtract(org, ent->fields.server->origin, eorg);
811 if (sv_gameplayfix_findradiusdistancetobox.integer)
813 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
814 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
815 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
818 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
819 if (DotProduct(eorg, eorg) < radius2)
821 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
826 VM_RETURN_EDICT(chain);
829 void PF_precache_file (void)
830 { // precache_file is only used to copy files with qcc, it does nothing
831 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
835 void PF_precache_sound (void)
837 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
838 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
841 void PF_precache_model (void)
843 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
844 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
851 float(float yaw, float dist) walkmove
854 void PF_walkmove (void)
862 // assume failure if it returns early
863 PRVM_G_FLOAT(OFS_RETURN) = 0;
865 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
866 if (ent == prog->edicts)
868 VM_Warning("walkmove: can not modify world entity\n");
871 if (ent->priv.server->free)
873 VM_Warning("walkmove: can not modify free entity\n");
876 yaw = PRVM_G_FLOAT(OFS_PARM0);
877 dist = PRVM_G_FLOAT(OFS_PARM1);
879 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
882 yaw = yaw*M_PI*2 / 360;
884 move[0] = cos(yaw)*dist;
885 move[1] = sin(yaw)*dist;
888 // save program state, because SV_movestep may call other progs
889 oldf = prog->xfunction;
890 oldself = prog->globals.server->self;
892 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
895 // restore program state
896 prog->xfunction = oldf;
897 prog->globals.server->self = oldself;
907 void PF_droptofloor (void)
913 // assume failure if it returns early
914 PRVM_G_FLOAT(OFS_RETURN) = 0;
916 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
917 if (ent == prog->edicts)
919 VM_Warning("droptofloor: can not modify world entity\n");
922 if (ent->priv.server->free)
924 VM_Warning("droptofloor: can not modify free entity\n");
928 VectorCopy (ent->fields.server->origin, end);
931 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
933 if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
935 if (trace.fraction < 1)
936 VectorCopy (trace.endpos, ent->fields.server->origin);
937 SV_LinkEdict (ent, false);
938 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
939 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
940 PRVM_G_FLOAT(OFS_RETURN) = 1;
941 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
942 ent->priv.server->suspendedinairflag = true;
950 void(float style, string value) lightstyle
953 void PF_lightstyle (void)
960 style = (int)PRVM_G_FLOAT(OFS_PARM0);
961 val = PRVM_G_STRING(OFS_PARM1);
963 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
964 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
967 // change the string in sv
968 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
970 // send message to all clients on this server
971 if (sv.state != ss_active)
974 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
976 if (client->active && client->netconnection)
978 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
979 MSG_WriteChar (&client->netconnection->message,style);
980 MSG_WriteString (&client->netconnection->message, val);
990 void PF_checkbottom (void)
992 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1000 void PF_pointcontents (void)
1002 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1009 Pick a vector for the player to shoot along
1010 vector aim(entity, missilespeed)
1015 prvm_edict_t *ent, *check, *bestent;
1016 vec3_t start, dir, end, bestdir;
1019 float dist, bestdist;
1022 // assume failure if it returns early
1023 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1024 // if sv_aim is so high it can't possibly accept anything, skip out early
1025 if (sv_aim.value >= 1)
1028 ent = PRVM_G_EDICT(OFS_PARM0);
1029 if (ent == prog->edicts)
1031 VM_Warning("aim: can not use world entity\n");
1034 if (ent->priv.server->free)
1036 VM_Warning("aim: can not use free entity\n");
1039 speed = PRVM_G_FLOAT(OFS_PARM1);
1041 VectorCopy (ent->fields.server->origin, start);
1044 // try sending a trace straight
1045 VectorCopy (prog->globals.server->v_forward, dir);
1046 VectorMA (start, 2048, dir, end);
1047 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1048 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1049 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1051 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1056 // try all possible entities
1057 VectorCopy (dir, bestdir);
1058 bestdist = sv_aim.value;
1061 check = PRVM_NEXT_EDICT(prog->edicts);
1062 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1064 prog->xfunction->builtinsprofile++;
1065 if (check->fields.server->takedamage != DAMAGE_AIM)
1069 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1070 continue; // don't aim at teammate
1071 for (j=0 ; j<3 ; j++)
1072 end[j] = check->fields.server->origin[j]
1073 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1074 VectorSubtract (end, start, dir);
1075 VectorNormalize (dir);
1076 dist = DotProduct (dir, prog->globals.server->v_forward);
1077 if (dist < bestdist)
1078 continue; // to far to turn
1079 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1080 if (tr.ent == check)
1081 { // can shoot at this one
1089 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1090 dist = DotProduct (dir, prog->globals.server->v_forward);
1091 VectorScale (prog->globals.server->v_forward, dist, end);
1093 VectorNormalize (end);
1094 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1098 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1103 ===============================================================================
1107 ===============================================================================
1110 #define MSG_BROADCAST 0 // unreliable to all
1111 #define MSG_ONE 1 // reliable to one (msg_entity)
1112 #define MSG_ALL 2 // reliable to all
1113 #define MSG_INIT 3 // write to the init string
1114 #define MSG_ENTITY 5
1116 sizebuf_t *WriteDest (void)
1121 extern sizebuf_t *sv2csqcbuf;
1123 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1127 return &sv.datagram;
1130 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1131 entnum = PRVM_NUM_FOR_EDICT(ent);
1132 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1134 VM_Warning ("WriteDest: tried to write to non-client\n");
1135 return &sv.reliable_datagram;
1138 return &svs.clients[entnum-1].netconnection->message;
1141 VM_Warning ("WriteDest: bad destination\n");
1143 return &sv.reliable_datagram;
1155 void PF_WriteByte (void)
1157 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1160 void PF_WriteChar (void)
1162 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1165 void PF_WriteShort (void)
1167 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1170 void PF_WriteLong (void)
1172 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1175 void PF_WriteAngle (void)
1177 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1180 void PF_WriteCoord (void)
1182 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1185 void PF_WriteString (void)
1187 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1190 void PF_WriteUnterminatedString (void)
1192 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1196 void PF_WriteEntity (void)
1198 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1201 //////////////////////////////////////////////////////////
1203 void PF_makestatic (void)
1208 ent = PRVM_G_EDICT(OFS_PARM0);
1209 if (ent == prog->edicts)
1211 VM_Warning("makestatic: can not modify world entity\n");
1214 if (ent->priv.server->free)
1216 VM_Warning("makestatic: can not modify free entity\n");
1221 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1226 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1227 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1228 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1232 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1233 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1234 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1237 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1238 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1239 for (i=0 ; i<3 ; i++)
1241 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1242 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1245 // throw the entity away now
1249 //=============================================================================
1256 void PF_setspawnparms (void)
1262 ent = PRVM_G_EDICT(OFS_PARM0);
1263 i = PRVM_NUM_FOR_EDICT(ent);
1264 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1266 Con_Print("tried to setspawnparms on a non-client\n");
1270 // copy spawn parms out of the client_t
1271 client = svs.clients + i-1;
1272 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1273 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1280 Returns a color vector indicating the lighting at the requested point.
1282 (Internal Operation note: actually measures the light beneath the point, just like
1283 the model lighting on the client)
1288 void PF_getlight (void)
1290 vec3_t ambientcolor, diffusecolor, diffusenormal;
1292 p = PRVM_G_VECTOR(OFS_PARM0);
1293 VectorClear(ambientcolor);
1294 VectorClear(diffusecolor);
1295 VectorClear(diffusenormal);
1296 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1297 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1298 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1301 void PF_registercvar (void)
1303 const char *name, *value;
1304 name = PRVM_G_STRING(OFS_PARM0);
1305 value = PRVM_G_STRING(OFS_PARM1);
1306 PRVM_G_FLOAT(OFS_RETURN) = 0;
1308 // first check to see if it has already been defined
1309 if (Cvar_FindVar (name))
1312 // check for overlap with a command
1313 if (Cmd_Exists (name))
1315 VM_Warning("PF_registercvar: %s is a command\n", name);
1319 Cvar_Get(name, value, 0);
1321 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1326 unsigned char type; // 1/2/8 or other value if isn't used
1330 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1331 static int vm_autosentstats_last;
1333 void VM_AutoSentStats_Clear (void)
1335 if(vm_autosentstats)
1337 Z_Free(vm_autosentstats);
1338 vm_autosentstats = NULL;
1339 vm_autosentstats_last = -1;
1343 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1344 #define VM_SENDSTAT(a,b,c)\
1347 if((c)==(unsigned char)(c))\
1349 MSG_WriteByte((a), svc_updatestatubyte);\
1350 MSG_WriteByte((a), (b));\
1351 MSG_WriteByte((a), (c));\
1355 MSG_WriteByte((a), svc_updatestat);\
1356 MSG_WriteByte((a), (b));\
1357 MSG_WriteLong((a), (c));\
1361 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1373 if(!vm_autosentstats)
1376 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);
1378 for(i=0; i<vm_autosentstats_last+1 ;i++)
1380 if(!vm_autosentstats[i].type)
1382 switch(vm_autosentstats[i].type)
1386 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1394 stats[i+32] = si[0];
1395 stats[i+33] = si[1];
1396 stats[i+34] = si[2];
1397 stats[i+35] = si[3];
1401 VM_SENDSTAT(msg, i+32, si[0]);
1402 VM_SENDSTAT(msg, i+33, si[1]);
1403 VM_SENDSTAT(msg, i+34, si[2]);
1404 VM_SENDSTAT(msg, i+35, si[3]);
1410 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1411 k.i = LittleLong (k.i);
1415 VM_SENDSTAT(msg, i+32, k.i);
1419 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1423 VM_SENDSTAT(msg, i+32, v);
1431 // void(float index, float type, .void field) SV_AddStat = #470;
1432 // Set up an auto-sent player stat.
1433 // Client's get thier own fields sent to them. Index may not be less than 32.
1434 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1435 // 1: string (4 stats carrying a total of 16 charactures)
1436 // 2: float (one stat, float converted to an integer for transportation)
1437 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1438 void PF_SV_AddStat (void)
1443 if(!vm_autosentstats)
1445 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1446 if(!vm_autosentstats)
1448 VM_Warning("PF_SV_AddStat: not enough memory\n");
1452 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1453 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1454 off = PRVM_G_INT (OFS_PARM2);
1459 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1462 if(i >= (MAX_CL_STATS-32))
1464 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1467 if(i > (MAX_CL_STATS-32-4) && type == 1)
1469 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1472 vm_autosentstats[i].type = type;
1473 vm_autosentstats[i].fieldoffset = off;
1474 if(vm_autosentstats_last < i)
1475 vm_autosentstats_last = i;
1482 copies data from one entity to another
1484 copyentity(src, dst)
1487 void PF_copyentity (void)
1489 prvm_edict_t *in, *out;
1490 in = PRVM_G_EDICT(OFS_PARM0);
1491 if (in == prog->edicts)
1493 VM_Warning("copyentity: can not read world entity\n");
1496 if (in->priv.server->free)
1498 VM_Warning("copyentity: can not read free entity\n");
1501 out = PRVM_G_EDICT(OFS_PARM1);
1502 if (out == prog->edicts)
1504 VM_Warning("copyentity: can not modify world entity\n");
1507 if (out->priv.server->free)
1509 VM_Warning("copyentity: can not modify free entity\n");
1512 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1520 sets the color of a client and broadcasts the update to all connected clients
1522 setcolor(clientent, value)
1525 void PF_setcolor (void)
1531 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1532 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1534 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1536 Con_Print("tried to setcolor a non-client\n");
1540 client = svs.clients + entnum-1;
1543 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1545 client->edict->fields.server->team = (i & 15) + 1;
1548 if (client->old_colors != client->colors)
1550 client->old_colors = client->colors;
1551 // send notification to all clients
1552 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1553 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1554 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1562 effect(origin, modelname, startframe, framecount, framerate)
1565 void PF_effect (void)
1569 s = PRVM_G_STRING(OFS_PARM1);
1572 VM_Warning("effect: no model specified\n");
1576 i = SV_ModelIndex(s, 1);
1579 VM_Warning("effect: model not precached\n");
1583 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1585 VM_Warning("effect: framecount < 1\n");
1589 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1591 VM_Warning("effect: framerate < 1\n");
1595 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));
1598 void PF_te_blood (void)
1600 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1602 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1603 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1605 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1606 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1607 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1609 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1610 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1611 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1613 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1616 void PF_te_bloodshower (void)
1618 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1620 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1621 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1623 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1624 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1625 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1627 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1628 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1629 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1631 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1633 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1636 void PF_te_explosionrgb (void)
1638 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1639 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1641 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1642 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1643 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1645 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1646 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1647 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1650 void PF_te_particlecube (void)
1652 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1654 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1655 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1657 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1658 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1659 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1661 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1662 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1663 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1665 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1666 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1667 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1669 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1671 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1672 // gravity true/false
1673 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1675 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1678 void PF_te_particlerain (void)
1680 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1682 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1683 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1685 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1686 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1687 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1689 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1690 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1691 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1693 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1694 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1695 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1697 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1699 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1702 void PF_te_particlesnow (void)
1704 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1706 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1707 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1709 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1710 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1711 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1713 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1714 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1715 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1719 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1721 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1723 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1726 void PF_te_spark (void)
1728 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1730 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1731 MSG_WriteByte(&sv.datagram, TE_SPARK);
1733 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1737 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1738 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1739 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1741 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1744 void PF_te_gunshotquad (void)
1746 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1751 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1754 void PF_te_spikequad (void)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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);
1764 void PF_te_superspikequad (void)
1766 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1767 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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);
1774 void PF_te_explosionquad (void)
1776 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1777 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1784 void PF_te_smallflash (void)
1786 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1789 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1790 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1791 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1794 void PF_te_customflash (void)
1796 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1798 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1799 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1805 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1807 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1809 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1810 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1811 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1814 void PF_te_gunshot (void)
1816 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1817 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1819 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1824 void PF_te_spike (void)
1826 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1834 void PF_te_superspike (void)
1836 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1839 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1844 void PF_te_explosion (void)
1846 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1849 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1854 void PF_te_tarexplosion (void)
1856 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1859 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1864 void PF_te_wizspike (void)
1866 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1867 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1874 void PF_te_knightspike (void)
1876 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1877 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1884 void PF_te_lavasplash (void)
1886 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1887 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1894 void PF_te_teleport (void)
1896 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1897 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1904 void PF_te_explosion2 (void)
1906 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1907 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1911 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1913 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
1914 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
1917 void PF_te_lightning1 (void)
1919 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1920 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1922 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1924 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1925 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1926 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1928 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1929 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1933 void PF_te_lightning2 (void)
1935 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1936 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1938 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1944 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1945 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1949 void PF_te_lightning3 (void)
1951 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1952 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1954 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1965 void PF_te_beam (void)
1967 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1968 MSG_WriteByte(&sv.datagram, TE_BEAM);
1970 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1973 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1974 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1981 void PF_te_plasmaburn (void)
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1985 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1990 void PF_te_flamejet (void)
1992 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1993 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1995 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2003 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2006 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2009 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2011 bestdist = 1000000000;
2013 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2015 // clip original point to each triangle of the surface and find the
2016 // triangle that is closest
2017 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2018 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2019 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2020 TriangleNormal(v[0], v[1], v[2], facenormal);
2021 VectorNormalize(facenormal);
2022 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2023 VectorMA(p, offsetdist, facenormal, temp);
2024 for (j = 0, k = 2;j < 3;k = j, j++)
2026 VectorSubtract(v[k], v[j], edgenormal);
2027 CrossProduct(edgenormal, facenormal, sidenormal);
2028 VectorNormalize(sidenormal);
2029 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2031 VectorMA(temp, offsetdist, sidenormal, temp);
2033 dist = VectorDistance2(temp, p);
2034 if (bestdist > dist)
2037 VectorCopy(temp, out);
2042 static model_t *getmodel(prvm_edict_t *ed)
2045 if (!ed || ed->priv.server->free)
2047 modelindex = (int)ed->fields.server->modelindex;
2048 if (modelindex < 1 || modelindex >= MAX_MODELS)
2050 return sv.models[modelindex];
2053 static msurface_t *getsurface(model_t *model, int surfacenum)
2055 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2057 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2061 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2062 void PF_getsurfacenumpoints(void)
2065 msurface_t *surface;
2066 // return 0 if no such surface
2067 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2069 PRVM_G_FLOAT(OFS_RETURN) = 0;
2073 // note: this (incorrectly) assumes it is a simple polygon
2074 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2076 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2077 void PF_getsurfacepoint(void)
2081 msurface_t *surface;
2083 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2084 ed = PRVM_G_EDICT(OFS_PARM0);
2085 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2087 // note: this (incorrectly) assumes it is a simple polygon
2088 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2089 if (pointnum < 0 || pointnum >= surface->num_vertices)
2091 // FIXME: implement rotation/scaling
2092 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2094 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2095 void PF_getsurfacenormal(void)
2098 msurface_t *surface;
2100 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2101 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2103 // FIXME: implement rotation/scaling
2104 // note: this (incorrectly) assumes it is a simple polygon
2105 // note: this only returns the first triangle, so it doesn't work very
2106 // well for curved surfaces or arbitrary meshes
2107 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);
2108 VectorNormalize(normal);
2109 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2111 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2112 void PF_getsurfacetexture(void)
2115 msurface_t *surface;
2116 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2117 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2119 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2121 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2122 void PF_getsurfacenearpoint(void)
2124 int surfacenum, best;
2126 vec_t dist, bestdist;
2129 msurface_t *surface;
2131 PRVM_G_FLOAT(OFS_RETURN) = -1;
2132 ed = PRVM_G_EDICT(OFS_PARM0);
2133 point = PRVM_G_VECTOR(OFS_PARM1);
2135 if (!ed || ed->priv.server->free)
2137 model = getmodel(ed);
2138 if (!model || !model->num_surfaces)
2141 // FIXME: implement rotation/scaling
2142 VectorSubtract(point, ed->fields.server->origin, p);
2144 bestdist = 1000000000;
2145 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2147 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2148 // first see if the nearest point on the surface's box is closer than the previous match
2149 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2150 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2151 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2152 dist = VectorLength2(clipped);
2153 if (dist < bestdist)
2155 // it is, check the nearest point on the actual geometry
2156 clippointtosurface(model, surface, p, clipped);
2157 VectorSubtract(clipped, p, clipped);
2158 dist += VectorLength2(clipped);
2159 if (dist < bestdist)
2161 // that's closer too, store it as the best match
2167 PRVM_G_FLOAT(OFS_RETURN) = best;
2169 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2170 void PF_getsurfaceclippedpoint(void)
2174 msurface_t *surface;
2176 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2177 ed = PRVM_G_EDICT(OFS_PARM0);
2178 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2180 // FIXME: implement rotation/scaling
2181 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2182 clippointtosurface(model, surface, p, out);
2183 // FIXME: implement rotation/scaling
2184 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2187 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2188 //this function originally written by KrimZon, made shorter by LordHavoc
2189 void PF_clientcommand (void)
2191 client_t *temp_client;
2194 //find client for this entity
2195 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2196 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2198 Con_Print("PF_clientcommand: entity is not a client\n");
2202 temp_client = host_client;
2203 host_client = svs.clients + i;
2204 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2205 host_client = temp_client;
2208 //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)
2209 void PF_setattachment (void)
2211 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2212 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2213 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2218 if (e == prog->edicts)
2220 VM_Warning("setattachment: can not modify world entity\n");
2223 if (e->priv.server->free)
2225 VM_Warning("setattachment: can not modify free entity\n");
2229 if (tagentity == NULL)
2230 tagentity = prog->edicts;
2232 v = PRVM_GETEDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2234 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2236 v = PRVM_GETEDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2239 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2241 modelindex = (int)tagentity->fields.server->modelindex;
2242 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2244 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2246 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);
2249 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));
2253 /////////////////////////////////////////
2254 // DP_MD3_TAGINFO extension coded by VorteX
2256 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2261 i = (int)e->fields.server->modelindex;
2262 if (i < 1 || i >= MAX_MODELS)
2264 model = sv.models[i];
2266 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2269 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2271 float scale = PRVM_GETEDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
2275 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);
2277 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);
2280 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2286 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2287 && (model = sv.models[(int)ent->fields.server->modelindex])
2288 && model->animscenes)
2290 // if model has wrong frame, engine automatically switches to model first frame
2291 frame = (int)ent->fields.server->frame;
2292 if (frame < 0 || frame >= model->numframes)
2294 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2296 *out = identitymatrix;
2300 // Warnings/errors code:
2301 // 0 - normal (everything all-right)
2304 // 3 - null or non-precached model
2305 // 4 - no tags with requested index
2306 // 5 - runaway loop at attachment chain
2307 extern cvar_t cl_bob;
2308 extern cvar_t cl_bobcycle;
2309 extern cvar_t cl_bobup;
2310 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2314 int modelindex, attachloop;
2315 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2318 *out = identitymatrix; // warnings and errors return identical matrix
2320 if (ent == prog->edicts)
2322 if (ent->priv.server->free)
2325 modelindex = (int)ent->fields.server->modelindex;
2326 if (modelindex <= 0 || modelindex > MAX_MODELS)
2329 model = sv.models[modelindex];
2331 tagmatrix = identitymatrix;
2332 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2336 if (attachloop >= 256) // prevent runaway looping
2338 // apply transformation by child's tagindex on parent entity and then
2339 // by parent entity itself
2340 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2341 if (ret && attachloop == 0)
2343 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2344 SV_GetEntityMatrix(ent, &entitymatrix, false);
2345 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2346 // next iteration we process the parent entity
2347 if ((val = PRVM_GETEDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2349 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2350 ent = PRVM_EDICT_NUM(val->edict);
2357 // RENDER_VIEWMODEL magic
2358 if ((val = PRVM_GETEDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2360 Matrix4x4_Copy(&tagmatrix, out);
2361 ent = PRVM_EDICT_NUM(val->edict);
2363 SV_GetEntityMatrix(ent, &entitymatrix, true);
2364 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2367 // Cl_bob, ported from rendering code
2368 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2371 // LordHavoc: this code is *weird*, but not replacable (I think it
2372 // should be done in QC on the server, but oh well, quake is quake)
2373 // LordHavoc: figured out bobup: the time at which the sin is at 180
2374 // degrees (which allows lengthening or squishing the peak or valley)
2375 cycle = sv.time/cl_bobcycle.value;
2376 cycle -= (int)cycle;
2377 if (cycle < cl_bobup.value)
2378 cycle = sin(M_PI * cycle / cl_bobup.value);
2380 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2381 // bob is proportional to velocity in the xy plane
2382 // (don't count Z, or jumping messes it up)
2383 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;
2384 bob = bob*0.3 + bob*0.7*cycle;
2385 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2392 //float(entity ent, string tagname) gettagindex;
2394 void PF_gettagindex (void)
2396 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2397 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2398 int modelindex, tag_index;
2400 if (ent == prog->edicts)
2402 VM_Warning("gettagindex: can't affect world entity\n");
2405 if (ent->priv.server->free)
2407 VM_Warning("gettagindex: can't affect free entity\n");
2411 modelindex = (int)ent->fields.server->modelindex;
2413 if (modelindex <= 0 || modelindex > MAX_MODELS)
2414 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2417 tag_index = SV_GetTagIndex(ent, tag_name);
2419 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2421 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2424 //vector(entity ent, float tagindex) gettaginfo;
2425 void PF_gettaginfo (void)
2427 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2428 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2429 matrix4x4_t tag_matrix;
2432 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2433 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2438 VM_Warning("gettagindex: can't affect world entity\n");
2441 VM_Warning("gettagindex: can't affect free entity\n");
2444 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2447 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2450 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2455 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2456 void PF_dropclient (void)
2459 client_t *oldhostclient;
2460 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2461 if (clientnum < 0 || clientnum >= svs.maxclients)
2463 VM_Warning("dropclient: not a client\n");
2466 if (!svs.clients[clientnum].active)
2468 VM_Warning("dropclient: that client slot is not connected\n");
2471 oldhostclient = host_client;
2472 host_client = svs.clients + clientnum;
2473 SV_DropClient(false);
2474 host_client = oldhostclient;
2477 //entity() spawnclient (DP_SV_BOTCLIENT)
2478 void PF_spawnclient (void)
2482 prog->xfunction->builtinsprofile += 2;
2484 for (i = 0;i < svs.maxclients;i++)
2486 if (!svs.clients[i].active)
2488 prog->xfunction->builtinsprofile += 100;
2489 SV_ConnectClient (i, NULL);
2490 // this has to be set or else ClientDisconnect won't be called
2491 // we assume the qc will call ClientConnect...
2492 svs.clients[i].clientconnectcalled = true;
2493 ed = PRVM_EDICT_NUM(i + 1);
2497 VM_RETURN_EDICT(ed);
2500 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2501 void PF_clienttype (void)
2504 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2505 if (clientnum < 0 || clientnum >= svs.maxclients)
2506 PRVM_G_FLOAT(OFS_RETURN) = 3;
2507 else if (!svs.clients[clientnum].active)
2508 PRVM_G_FLOAT(OFS_RETURN) = 0;
2509 else if (svs.clients[clientnum].netconnection)
2510 PRVM_G_FLOAT(OFS_RETURN) = 1;
2512 PRVM_G_FLOAT(OFS_RETURN) = 2;
2515 void PF_edict_num (void)
2517 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2520 prvm_builtin_t vm_sv_builtins[] = {
2522 PF_makevectors, // #1 void(vector ang) makevectors
2523 PF_setorigin, // #2 void(entity e, vector o) setorigin
2524 PF_setmodel, // #3 void(entity e, string m) setmodel
2525 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2526 NULL, // #5 void(entity e, vector min, vector max) setabssize
2527 VM_break, // #6 void() break
2528 VM_random, // #7 float() random
2529 PF_sound, // #8 void(entity e, float chan, string samp) sound
2530 VM_normalize, // #9 vector(vector v) normalize
2531 VM_error, // #10 void(string e) error
2532 VM_objerror, // #11 void(string e) objerror
2533 VM_vlen, // #12 float(vector v) vlen
2534 VM_vectoyaw, // #13 float(vector v) vectoyaw
2535 VM_spawn, // #14 entity() spawn
2536 VM_remove, // #15 void(entity e) remove
2537 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2538 PF_checkclient, // #17 entity() clientlist
2539 VM_find, // #18 entity(entity start, .string fld, string match) find
2540 PF_precache_sound, // #19 void(string s) precache_sound
2541 PF_precache_model, // #20 void(string s) precache_model
2542 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2543 PF_findradius, // #22 entity(vector org, float rad) findradius
2544 VM_bprint, // #23 void(string s) bprint
2545 PF_sprint, // #24 void(entity client, string s) sprint
2546 VM_dprint, // #25 void(string s) dprint
2547 VM_ftos, // #26 void(string s) ftos
2548 VM_vtos, // #27 void(string s) vtos
2549 VM_coredump, // #28 void() coredump
2550 VM_traceon, // #29 void() traceon
2551 VM_traceoff, // #30 void() traceoff
2552 VM_eprint, // #31 void(entity e) eprint
2553 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2555 PF_droptofloor, // #34 float() droptofloor
2556 PF_lightstyle, // #35 void(float style, string value) lightstyle
2557 VM_rint, // #36 float(float v) rint
2558 VM_floor, // #37 float(float v) floor
2559 VM_ceil, // #38 float(float v) ceil
2561 PF_checkbottom, // #40 float(entity e) checkbottom
2562 PF_pointcontents, // #41 float(vector v) pointcontents
2564 VM_fabs, // #43 float(float f) fabs
2565 PF_aim, // #44 vector(entity e, float speed) aim
2566 VM_cvar, // #45 float(string s) cvar
2567 VM_localcmd, // #46 void(string s) localcmd
2568 VM_nextent, // #47 entity(entity e) nextent
2569 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2570 VM_changeyaw, // #49 void() ChangeYaw
2572 VM_vectoangles, // #51 vector(vector v) vectoangles
2573 PF_WriteByte, // #52 void(float to, float f) WriteByte
2574 PF_WriteChar, // #53 void(float to, float f) WriteChar
2575 PF_WriteShort, // #54 void(float to, float f) WriteShort
2576 PF_WriteLong, // #55 void(float to, float f) WriteLong
2577 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2578 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2579 PF_WriteString, // #58 void(float to, string s) WriteString
2580 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2581 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2582 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2583 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2584 VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2585 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2586 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2588 SV_MoveToGoal, // #67 void(float step) movetogoal
2589 PF_precache_file, // #68 string(string s) precache_file
2590 PF_makestatic, // #69 void(entity e) makestatic
2591 VM_changelevel, // #70 void(string s) changelevel
2593 VM_cvar_set, // #72 void(string var, string val) cvar_set
2594 PF_centerprint, // #73 void(entity client, strings) centerprint
2595 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2596 PF_precache_model, // #75 string(string s) precache_model2
2597 PF_precache_sound, // #76 string(string s) precache_sound2
2598 PF_precache_file, // #77 string(string s) precache_file2
2599 PF_setspawnparms, // #78 void(entity e) setspawnparms
2602 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2611 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2612 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2613 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2614 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2615 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2616 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2617 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2618 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2619 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2620 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2631 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2632 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2633 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2634 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2635 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2636 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2637 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2638 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2639 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2640 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2641 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2642 // FTEQW range #200-#299
2661 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2683 VM_print, // #339 void(string, ...) print (DP_SV_PRINT)
2690 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2691 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2692 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2693 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2694 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2695 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2696 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2697 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2698 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2699 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2700 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2701 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2702 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2703 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2704 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2705 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2706 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2707 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2708 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2709 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2710 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2711 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2712 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2713 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2714 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2715 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2716 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2717 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2718 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2719 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2720 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2721 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2722 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2723 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2724 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2725 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2726 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2727 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2728 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2729 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2730 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2731 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2732 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2733 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2734 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2735 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2736 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2737 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2738 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2739 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2740 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2741 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2742 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2743 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2744 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2745 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2746 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2747 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2749 PF_edict_num, // #459 entity(float num) (??)
2750 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2751 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2752 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2753 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2754 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2755 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2756 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2757 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2758 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2759 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2760 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2761 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2762 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2763 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2764 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2765 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2766 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2767 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2768 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
2771 e10, e10 // #480-499 (LordHavoc)
2774 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2776 void VM_SV_Cmd_Init(void)
2781 void VM_SV_Cmd_Reset(void)