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(gval_trace_dpstartcontents)))
496 val->_float = trace.startsupercontents;
497 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
498 val->_float = trace.hitsupercontents;
499 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
500 val->_float = trace.hitq3surfaceflags;
501 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_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(gval_trace_dpstartcontents)))
558 val->_float = trace.startsupercontents;
559 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
560 val->_float = trace.hitsupercontents;
561 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
562 val->_float = trace.hitq3surfaceflags;
563 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_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(gval_trace_dpstartcontents)))
605 val->_float = trace.startsupercontents;
606 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
607 val->_float = trace.hitsupercontents;
608 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
609 val->_float = trace.hitq3surfaceflags;
610 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_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 = SV_EntitiesInBox(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));
1106 This was a major timewaster in progs, so it was converted to C
1109 void PF_changeyaw (void)
1112 float ideal, current, move, speed;
1114 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1115 if (ent == prog->edicts)
1117 VM_Warning("changeyaw: can not modify world entity\n");
1120 if (ent->priv.server->free)
1122 VM_Warning("changeyaw: can not modify free entity\n");
1125 current = ANGLEMOD(ent->fields.server->angles[1]);
1126 ideal = ent->fields.server->ideal_yaw;
1127 speed = ent->fields.server->yaw_speed;
1129 if (current == ideal)
1131 move = ideal - current;
1132 if (ideal > current)
1153 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1161 void PF_changepitch (void)
1164 float ideal, current, move, speed;
1167 ent = PRVM_G_EDICT(OFS_PARM0);
1168 if (ent == prog->edicts)
1170 VM_Warning("changepitch: can not modify world entity\n");
1173 if (ent->priv.server->free)
1175 VM_Warning("changepitch: can not modify free entity\n");
1178 current = ANGLEMOD( ent->fields.server->angles[0] );
1179 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1180 ideal = val->_float;
1183 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1186 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1187 speed = val->_float;
1190 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1194 if (current == ideal)
1196 move = ideal - current;
1197 if (ideal > current)
1218 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1222 ===============================================================================
1226 ===============================================================================
1229 #define MSG_BROADCAST 0 // unreliable to all
1230 #define MSG_ONE 1 // reliable to one (msg_entity)
1231 #define MSG_ALL 2 // reliable to all
1232 #define MSG_INIT 3 // write to the init string
1233 #define MSG_ENTITY 5
1235 sizebuf_t *WriteDest (void)
1240 extern sizebuf_t *sv2csqcbuf;
1242 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1246 return &sv.datagram;
1249 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1250 entnum = PRVM_NUM_FOR_EDICT(ent);
1251 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1253 VM_Warning ("WriteDest: tried to write to non-client\n");
1254 return &sv.reliable_datagram;
1257 return &svs.clients[entnum-1].netconnection->message;
1260 VM_Warning ("WriteDest: bad destination\n");
1262 return &sv.reliable_datagram;
1274 void PF_WriteByte (void)
1276 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1279 void PF_WriteChar (void)
1281 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1284 void PF_WriteShort (void)
1286 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1289 void PF_WriteLong (void)
1291 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1294 void PF_WriteAngle (void)
1296 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1299 void PF_WriteCoord (void)
1301 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1304 void PF_WriteString (void)
1306 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1309 void PF_WriteUnterminatedString (void)
1311 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1315 void PF_WriteEntity (void)
1317 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1320 //////////////////////////////////////////////////////////
1322 void PF_makestatic (void)
1327 ent = PRVM_G_EDICT(OFS_PARM0);
1328 if (ent == prog->edicts)
1330 VM_Warning("makestatic: can not modify world entity\n");
1333 if (ent->priv.server->free)
1335 VM_Warning("makestatic: can not modify free entity\n");
1340 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1345 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1346 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1347 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1351 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1352 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1353 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1356 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1357 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1358 for (i=0 ; i<3 ; i++)
1360 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1361 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1364 // throw the entity away now
1368 //=============================================================================
1375 void PF_setspawnparms (void)
1381 ent = PRVM_G_EDICT(OFS_PARM0);
1382 i = PRVM_NUM_FOR_EDICT(ent);
1383 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1385 Con_Print("tried to setspawnparms on a non-client\n");
1389 // copy spawn parms out of the client_t
1390 client = svs.clients + i-1;
1391 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1392 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1399 Returns a color vector indicating the lighting at the requested point.
1401 (Internal Operation note: actually measures the light beneath the point, just like
1402 the model lighting on the client)
1407 void PF_getlight (void)
1409 vec3_t ambientcolor, diffusecolor, diffusenormal;
1411 p = PRVM_G_VECTOR(OFS_PARM0);
1412 VectorClear(ambientcolor);
1413 VectorClear(diffusecolor);
1414 VectorClear(diffusenormal);
1415 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1416 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1417 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1420 void PF_registercvar (void)
1422 const char *name, *value;
1423 name = PRVM_G_STRING(OFS_PARM0);
1424 value = PRVM_G_STRING(OFS_PARM1);
1425 PRVM_G_FLOAT(OFS_RETURN) = 0;
1427 // first check to see if it has already been defined
1428 if (Cvar_FindVar (name))
1431 // check for overlap with a command
1432 if (Cmd_Exists (name))
1434 VM_Warning("PF_registercvar: %s is a command\n", name);
1438 Cvar_Get(name, value, 0);
1440 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1445 unsigned char type; // 1/2/8 or other value if isn't used
1449 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1450 static int vm_autosentstats_last;
1452 void VM_AutoSentStats_Clear (void)
1454 if(vm_autosentstats)
1456 Z_Free(vm_autosentstats);
1457 vm_autosentstats = NULL;
1458 vm_autosentstats_last = -1;
1462 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1463 #define VM_SENDSTAT(a,b,c)\
1466 if((c)==(unsigned char)(c))\
1468 MSG_WriteByte((a), svc_updatestatubyte);\
1469 MSG_WriteByte((a), (b));\
1470 MSG_WriteByte((a), (c));\
1474 MSG_WriteByte((a), svc_updatestat);\
1475 MSG_WriteByte((a), (b));\
1476 MSG_WriteLong((a), (c));\
1480 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1492 if(!vm_autosentstats)
1495 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);
1497 for(i=0; i<vm_autosentstats_last+1 ;i++)
1499 if(!vm_autosentstats[i].type)
1501 switch(vm_autosentstats[i].type)
1505 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1513 stats[i+32] = si[0];
1514 stats[i+33] = si[1];
1515 stats[i+34] = si[2];
1516 stats[i+35] = si[3];
1520 VM_SENDSTAT(msg, i+32, si[0]);
1521 VM_SENDSTAT(msg, i+33, si[1]);
1522 VM_SENDSTAT(msg, i+34, si[2]);
1523 VM_SENDSTAT(msg, i+35, si[3]);
1529 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1530 k.i = LittleLong (k.i);
1534 VM_SENDSTAT(msg, i+32, k.i);
1538 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1542 VM_SENDSTAT(msg, i+32, v);
1550 // void(float index, float type, .void field) SV_AddStat = #470;
1551 // Set up an auto-sent player stat.
1552 // Client's get thier own fields sent to them. Index may not be less than 32.
1553 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1554 // 1: string (4 stats carrying a total of 16 charactures)
1555 // 2: float (one stat, float converted to an integer for transportation)
1556 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1557 void PF_SV_AddStat (void)
1562 if(!vm_autosentstats)
1564 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1565 if(!vm_autosentstats)
1567 VM_Warning("PF_SV_AddStat: not enough memory\n");
1571 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1572 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1573 off = PRVM_G_INT (OFS_PARM2);
1578 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1581 if(i >= (MAX_CL_STATS-32))
1583 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1586 if(i > (MAX_CL_STATS-32-4) && type == 1)
1588 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1591 vm_autosentstats[i].type = type;
1592 vm_autosentstats[i].fieldoffset = off;
1593 if(vm_autosentstats_last < i)
1594 vm_autosentstats_last = i;
1601 copies data from one entity to another
1603 copyentity(src, dst)
1606 void PF_copyentity (void)
1608 prvm_edict_t *in, *out;
1609 in = PRVM_G_EDICT(OFS_PARM0);
1610 if (in == prog->edicts)
1612 VM_Warning("copyentity: can not read world entity\n");
1615 if (in->priv.server->free)
1617 VM_Warning("copyentity: can not read free entity\n");
1620 out = PRVM_G_EDICT(OFS_PARM1);
1621 if (out == prog->edicts)
1623 VM_Warning("copyentity: can not modify world entity\n");
1626 if (out->priv.server->free)
1628 VM_Warning("copyentity: can not modify free entity\n");
1631 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1639 sets the color of a client and broadcasts the update to all connected clients
1641 setcolor(clientent, value)
1644 void PF_setcolor (void)
1650 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1651 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1653 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1655 Con_Print("tried to setcolor a non-client\n");
1659 client = svs.clients + entnum-1;
1662 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1664 client->edict->fields.server->team = (i & 15) + 1;
1667 if (client->old_colors != client->colors)
1669 client->old_colors = client->colors;
1670 // send notification to all clients
1671 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1672 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1673 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1681 effect(origin, modelname, startframe, framecount, framerate)
1684 void PF_effect (void)
1688 s = PRVM_G_STRING(OFS_PARM1);
1691 VM_Warning("effect: no model specified\n");
1695 i = SV_ModelIndex(s, 1);
1698 VM_Warning("effect: model not precached\n");
1702 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1704 VM_Warning("effect: framecount < 1\n");
1708 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1710 VM_Warning("effect: framerate < 1\n");
1714 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));
1717 void PF_te_blood (void)
1719 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1721 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1722 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1725 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1726 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1728 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1729 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1730 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1732 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1735 void PF_te_bloodshower (void)
1737 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1739 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1740 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1750 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1752 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1755 void PF_te_explosionrgb (void)
1757 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1758 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1762 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1764 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1765 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1766 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1769 void PF_te_particlecube (void)
1771 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1773 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1774 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1788 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1790 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1791 // gravity true/false
1792 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1794 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1797 void PF_te_particlerain (void)
1799 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1801 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1802 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1814 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1816 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1818 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1821 void PF_te_particlesnow (void)
1823 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1825 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1838 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1840 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1842 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1845 void PF_te_spark (void)
1847 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1849 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1850 MSG_WriteByte(&sv.datagram, TE_SPARK);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1854 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1856 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1857 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1858 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1860 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1863 void PF_te_gunshotquad (void)
1865 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1866 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1873 void PF_te_spikequad (void)
1875 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1876 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1883 void PF_te_superspikequad (void)
1885 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1886 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1893 void PF_te_explosionquad (void)
1895 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1896 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1903 void PF_te_smallflash (void)
1905 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1906 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1910 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1913 void PF_te_customflash (void)
1915 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1917 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1918 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1922 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1924 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1926 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1928 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1929 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1930 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1933 void PF_te_gunshot (void)
1935 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1936 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1943 void PF_te_spike (void)
1945 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1953 void PF_te_superspike (void)
1955 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1956 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1963 void PF_te_explosion (void)
1965 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1966 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1973 void PF_te_tarexplosion (void)
1975 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983 void PF_te_wizspike (void)
1985 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1986 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1993 void PF_te_knightspike (void)
1995 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1996 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2003 void PF_te_lavasplash (void)
2005 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2006 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2013 void PF_te_teleport (void)
2015 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2016 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2023 void PF_te_explosion2 (void)
2025 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2026 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2030 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2032 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2033 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2036 void PF_te_lightning1 (void)
2038 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2039 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2041 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2049 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2052 void PF_te_lightning2 (void)
2054 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2055 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2057 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2065 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2068 void PF_te_lightning3 (void)
2070 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2071 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2073 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2081 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2084 void PF_te_beam (void)
2086 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2087 MSG_WriteByte(&sv.datagram, TE_BEAM);
2089 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2100 void PF_te_plasmaburn (void)
2102 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2109 void PF_te_flamejet (void)
2111 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2112 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2120 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2122 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2125 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2128 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2130 bestdist = 1000000000;
2132 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2134 // clip original point to each triangle of the surface and find the
2135 // triangle that is closest
2136 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2137 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2138 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2139 TriangleNormal(v[0], v[1], v[2], facenormal);
2140 VectorNormalize(facenormal);
2141 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2142 VectorMA(p, offsetdist, facenormal, temp);
2143 for (j = 0, k = 2;j < 3;k = j, j++)
2145 VectorSubtract(v[k], v[j], edgenormal);
2146 CrossProduct(edgenormal, facenormal, sidenormal);
2147 VectorNormalize(sidenormal);
2148 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2150 VectorMA(temp, offsetdist, sidenormal, temp);
2152 dist = VectorDistance2(temp, p);
2153 if (bestdist > dist)
2156 VectorCopy(temp, out);
2161 static model_t *getmodel(prvm_edict_t *ed)
2164 if (!ed || ed->priv.server->free)
2166 modelindex = (int)ed->fields.server->modelindex;
2167 if (modelindex < 1 || modelindex >= MAX_MODELS)
2169 return sv.models[modelindex];
2172 static msurface_t *getsurface(model_t *model, int surfacenum)
2174 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2176 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2180 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2181 void PF_getsurfacenumpoints(void)
2184 msurface_t *surface;
2185 // return 0 if no such surface
2186 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2188 PRVM_G_FLOAT(OFS_RETURN) = 0;
2192 // note: this (incorrectly) assumes it is a simple polygon
2193 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2195 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2196 void PF_getsurfacepoint(void)
2200 msurface_t *surface;
2202 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2203 ed = PRVM_G_EDICT(OFS_PARM0);
2204 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2206 // note: this (incorrectly) assumes it is a simple polygon
2207 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2208 if (pointnum < 0 || pointnum >= surface->num_vertices)
2210 // FIXME: implement rotation/scaling
2211 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2213 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2214 void PF_getsurfacenormal(void)
2217 msurface_t *surface;
2219 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2220 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2222 // FIXME: implement rotation/scaling
2223 // note: this (incorrectly) assumes it is a simple polygon
2224 // note: this only returns the first triangle, so it doesn't work very
2225 // well for curved surfaces or arbitrary meshes
2226 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);
2227 VectorNormalize(normal);
2228 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2230 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2231 void PF_getsurfacetexture(void)
2234 msurface_t *surface;
2235 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2236 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2238 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2240 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2241 void PF_getsurfacenearpoint(void)
2243 int surfacenum, best;
2245 vec_t dist, bestdist;
2248 msurface_t *surface;
2250 PRVM_G_FLOAT(OFS_RETURN) = -1;
2251 ed = PRVM_G_EDICT(OFS_PARM0);
2252 point = PRVM_G_VECTOR(OFS_PARM1);
2254 if (!ed || ed->priv.server->free)
2256 model = getmodel(ed);
2257 if (!model || !model->num_surfaces)
2260 // FIXME: implement rotation/scaling
2261 VectorSubtract(point, ed->fields.server->origin, p);
2263 bestdist = 1000000000;
2264 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2266 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2267 // first see if the nearest point on the surface's box is closer than the previous match
2268 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2269 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2270 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2271 dist = VectorLength2(clipped);
2272 if (dist < bestdist)
2274 // it is, check the nearest point on the actual geometry
2275 clippointtosurface(model, surface, p, clipped);
2276 VectorSubtract(clipped, p, clipped);
2277 dist += VectorLength2(clipped);
2278 if (dist < bestdist)
2280 // that's closer too, store it as the best match
2286 PRVM_G_FLOAT(OFS_RETURN) = best;
2288 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2289 void PF_getsurfaceclippedpoint(void)
2293 msurface_t *surface;
2295 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2296 ed = PRVM_G_EDICT(OFS_PARM0);
2297 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2299 // FIXME: implement rotation/scaling
2300 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2301 clippointtosurface(model, surface, p, out);
2302 // FIXME: implement rotation/scaling
2303 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2306 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2307 //this function originally written by KrimZon, made shorter by LordHavoc
2308 void PF_clientcommand (void)
2310 client_t *temp_client;
2313 //find client for this entity
2314 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2315 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2317 Con_Print("PF_clientcommand: entity is not a client\n");
2321 temp_client = host_client;
2322 host_client = svs.clients + i;
2323 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2324 host_client = temp_client;
2327 //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)
2328 void PF_setattachment (void)
2330 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2331 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2332 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2337 if (e == prog->edicts)
2339 VM_Warning("setattachment: can not modify world entity\n");
2342 if (e->priv.server->free)
2344 VM_Warning("setattachment: can not modify free entity\n");
2348 if (tagentity == NULL)
2349 tagentity = prog->edicts;
2351 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2353 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2355 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2358 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2360 modelindex = (int)tagentity->fields.server->modelindex;
2361 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2363 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2365 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);
2368 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));
2372 /////////////////////////////////////////
2373 // DP_MD3_TAGINFO extension coded by VorteX
2375 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2380 i = (int)e->fields.server->modelindex;
2381 if (i < 1 || i >= MAX_MODELS)
2383 model = sv.models[i];
2385 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2388 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2390 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2394 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);
2396 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);
2399 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2405 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2406 && (model = sv.models[(int)ent->fields.server->modelindex])
2407 && model->animscenes)
2409 // if model has wrong frame, engine automatically switches to model first frame
2410 frame = (int)ent->fields.server->frame;
2411 if (frame < 0 || frame >= model->numframes)
2413 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2415 *out = identitymatrix;
2419 // Warnings/errors code:
2420 // 0 - normal (everything all-right)
2423 // 3 - null or non-precached model
2424 // 4 - no tags with requested index
2425 // 5 - runaway loop at attachment chain
2426 extern cvar_t cl_bob;
2427 extern cvar_t cl_bobcycle;
2428 extern cvar_t cl_bobup;
2429 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2433 int modelindex, attachloop;
2434 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2437 *out = identitymatrix; // warnings and errors return identical matrix
2439 if (ent == prog->edicts)
2441 if (ent->priv.server->free)
2444 modelindex = (int)ent->fields.server->modelindex;
2445 if (modelindex <= 0 || modelindex > MAX_MODELS)
2448 model = sv.models[modelindex];
2450 tagmatrix = identitymatrix;
2451 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2455 if (attachloop >= 256) // prevent runaway looping
2457 // apply transformation by child's tagindex on parent entity and then
2458 // by parent entity itself
2459 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2460 if (ret && attachloop == 0)
2462 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2463 SV_GetEntityMatrix(ent, &entitymatrix, false);
2464 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2465 // next iteration we process the parent entity
2466 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2468 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2469 ent = PRVM_EDICT_NUM(val->edict);
2476 // RENDER_VIEWMODEL magic
2477 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2479 Matrix4x4_Copy(&tagmatrix, out);
2480 ent = PRVM_EDICT_NUM(val->edict);
2482 SV_GetEntityMatrix(ent, &entitymatrix, true);
2483 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2486 // Cl_bob, ported from rendering code
2487 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2490 // LordHavoc: this code is *weird*, but not replacable (I think it
2491 // should be done in QC on the server, but oh well, quake is quake)
2492 // LordHavoc: figured out bobup: the time at which the sin is at 180
2493 // degrees (which allows lengthening or squishing the peak or valley)
2494 cycle = sv.time/cl_bobcycle.value;
2495 cycle -= (int)cycle;
2496 if (cycle < cl_bobup.value)
2497 cycle = sin(M_PI * cycle / cl_bobup.value);
2499 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2500 // bob is proportional to velocity in the xy plane
2501 // (don't count Z, or jumping messes it up)
2502 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;
2503 bob = bob*0.3 + bob*0.7*cycle;
2504 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2511 //float(entity ent, string tagname) gettagindex;
2513 void PF_gettagindex (void)
2515 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2516 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2517 int modelindex, tag_index;
2519 if (ent == prog->edicts)
2521 VM_Warning("gettagindex: can't affect world entity\n");
2524 if (ent->priv.server->free)
2526 VM_Warning("gettagindex: can't affect free entity\n");
2530 modelindex = (int)ent->fields.server->modelindex;
2532 if (modelindex <= 0 || modelindex > MAX_MODELS)
2533 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2536 tag_index = SV_GetTagIndex(ent, tag_name);
2538 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2540 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2543 //vector(entity ent, float tagindex) gettaginfo;
2544 void PF_gettaginfo (void)
2546 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2547 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2548 matrix4x4_t tag_matrix;
2551 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2552 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2557 VM_Warning("gettagindex: can't affect world entity\n");
2560 VM_Warning("gettagindex: can't affect free entity\n");
2563 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2566 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2569 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2574 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2575 void PF_dropclient (void)
2578 client_t *oldhostclient;
2579 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2580 if (clientnum < 0 || clientnum >= svs.maxclients)
2582 VM_Warning("dropclient: not a client\n");
2585 if (!svs.clients[clientnum].active)
2587 VM_Warning("dropclient: that client slot is not connected\n");
2590 oldhostclient = host_client;
2591 host_client = svs.clients + clientnum;
2592 SV_DropClient(false);
2593 host_client = oldhostclient;
2596 //entity() spawnclient (DP_SV_BOTCLIENT)
2597 void PF_spawnclient (void)
2601 prog->xfunction->builtinsprofile += 2;
2603 for (i = 0;i < svs.maxclients;i++)
2605 if (!svs.clients[i].active)
2607 prog->xfunction->builtinsprofile += 100;
2608 SV_ConnectClient (i, NULL);
2609 // this has to be set or else ClientDisconnect won't be called
2610 // we assume the qc will call ClientConnect...
2611 svs.clients[i].clientconnectcalled = true;
2612 ed = PRVM_EDICT_NUM(i + 1);
2616 VM_RETURN_EDICT(ed);
2619 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2620 void PF_clienttype (void)
2623 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2624 if (clientnum < 0 || clientnum >= svs.maxclients)
2625 PRVM_G_FLOAT(OFS_RETURN) = 3;
2626 else if (!svs.clients[clientnum].active)
2627 PRVM_G_FLOAT(OFS_RETURN) = 0;
2628 else if (svs.clients[clientnum].netconnection)
2629 PRVM_G_FLOAT(OFS_RETURN) = 1;
2631 PRVM_G_FLOAT(OFS_RETURN) = 2;
2634 void PF_edict_num (void)
2636 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2639 prvm_builtin_t vm_sv_builtins[] = {
2641 PF_makevectors, // #1 void(vector ang) makevectors
2642 PF_setorigin, // #2 void(entity e, vector o) setorigin
2643 PF_setmodel, // #3 void(entity e, string m) setmodel
2644 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2645 NULL, // #5 void(entity e, vector min, vector max) setabssize
2646 VM_break, // #6 void() break
2647 VM_random, // #7 float() random
2648 PF_sound, // #8 void(entity e, float chan, string samp) sound
2649 VM_normalize, // #9 vector(vector v) normalize
2650 VM_error, // #10 void(string e) error
2651 VM_objerror, // #11 void(string e) objerror
2652 VM_vlen, // #12 float(vector v) vlen
2653 VM_vectoyaw, // #13 float(vector v) vectoyaw
2654 VM_spawn, // #14 entity() spawn
2655 VM_remove, // #15 void(entity e) remove
2656 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2657 PF_checkclient, // #17 entity() clientlist
2658 VM_find, // #18 entity(entity start, .string fld, string match) find
2659 PF_precache_sound, // #19 void(string s) precache_sound
2660 PF_precache_model, // #20 void(string s) precache_model
2661 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2662 PF_findradius, // #22 entity(vector org, float rad) findradius
2663 VM_bprint, // #23 void(string s) bprint
2664 PF_sprint, // #24 void(entity client, string s) sprint
2665 VM_dprint, // #25 void(string s) dprint
2666 VM_ftos, // #26 void(string s) ftos
2667 VM_vtos, // #27 void(string s) vtos
2668 VM_coredump, // #28 void() coredump
2669 VM_traceon, // #29 void() traceon
2670 VM_traceoff, // #30 void() traceoff
2671 VM_eprint, // #31 void(entity e) eprint
2672 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2674 PF_droptofloor, // #34 float() droptofloor
2675 PF_lightstyle, // #35 void(float style, string value) lightstyle
2676 VM_rint, // #36 float(float v) rint
2677 VM_floor, // #37 float(float v) floor
2678 VM_ceil, // #38 float(float v) ceil
2680 PF_checkbottom, // #40 float(entity e) checkbottom
2681 PF_pointcontents, // #41 float(vector v) pointcontents
2683 VM_fabs, // #43 float(float f) fabs
2684 PF_aim, // #44 vector(entity e, float speed) aim
2685 VM_cvar, // #45 float(string s) cvar
2686 VM_localcmd, // #46 void(string s) localcmd
2687 VM_nextent, // #47 entity(entity e) nextent
2688 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2689 PF_changeyaw, // #49 void() ChangeYaw
2691 VM_vectoangles, // #51 vector(vector v) vectoangles
2692 PF_WriteByte, // #52 void(float to, float f) WriteByte
2693 PF_WriteChar, // #53 void(float to, float f) WriteChar
2694 PF_WriteShort, // #54 void(float to, float f) WriteShort
2695 PF_WriteLong, // #55 void(float to, float f) WriteLong
2696 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2697 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2698 PF_WriteString, // #58 void(float to, string s) WriteString
2699 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2700 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2701 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2702 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2703 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2704 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2705 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2707 SV_MoveToGoal, // #67 void(float step) movetogoal
2708 PF_precache_file, // #68 string(string s) precache_file
2709 PF_makestatic, // #69 void(entity e) makestatic
2710 VM_changelevel, // #70 void(string s) changelevel
2712 VM_cvar_set, // #72 void(string var, string val) cvar_set
2713 PF_centerprint, // #73 void(entity client, strings) centerprint
2714 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2715 PF_precache_model, // #75 string(string s) precache_model2
2716 PF_precache_sound, // #76 string(string s) precache_sound2
2717 PF_precache_file, // #77 string(string s) precache_file2
2718 PF_setspawnparms, // #78 void(entity e) setspawnparms
2721 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2730 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2731 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2732 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2733 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2734 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2735 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2736 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2737 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2738 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2739 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2750 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2751 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2752 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2753 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2754 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2755 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2756 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2757 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2758 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2759 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2760 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2761 // FTEQW range #200-#299
2780 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2802 VM_print, // #339 void(string, ...) print (DP_SV_PRINT)
2809 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2810 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2811 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2812 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2813 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2814 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2815 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2816 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2817 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2818 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2819 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2820 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2821 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2822 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2823 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2824 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2825 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2826 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2827 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2828 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2829 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2830 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2831 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2832 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2833 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2834 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2835 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2836 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2837 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2838 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2839 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2840 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2841 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2842 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2843 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2844 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2845 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2846 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2847 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2848 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2849 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2850 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2851 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2852 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2853 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2854 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2855 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2856 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2857 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2858 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2859 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2860 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2861 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2862 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2863 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2864 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2865 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2866 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2868 PF_edict_num, // #459 entity(float num) (??)
2869 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2870 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2871 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2872 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2873 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2874 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2875 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2876 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2877 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2878 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2879 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2880 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2881 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2882 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2883 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2884 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2885 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2886 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2887 VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
2890 e10, e10 // #480-499 (LordHavoc)
2893 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2895 void VM_SV_Cmd_Init(void)
2900 void VM_SV_Cmd_Reset(void)