3 //============================================================================
6 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2", "maximum cosine angle for quake's vertical autoaim, a value above 1 completely disables the autoaim, quake used 0.93"}; //"0.93"}; // LordHavoc: disabled autoaim by default
9 char *vm_sv_extensions =
11 "DP_CON_ALIASPARAMETERS "
30 "DP_ENT_CUSTOMCOLORMAP "
31 "DP_ENT_EXTERIORMODELTOCLIENT "
33 "DP_ENT_LOWPRECISION "
36 "DP_GFX_EXTERNALTEXTURES "
37 "DP_GFX_EXTERNALTEXTURES_PERMAP "
39 "DP_GFX_QUAKE3MODELTAGS "
43 "DP_HALFLIFE_MAP_CVAR "
49 "DP_MOVETYPEBOUNCEMISSILE "
51 "DP_QC_ASINACOSATANATAN2TAN "
57 "DP_QC_FINDCHAINFLAGS "
58 "DP_QC_FINDCHAINFLOAT "
61 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
66 "DP_QC_MULTIPLETEMPSTRINGS "
68 "DP_QC_SINCOSSQRTPOW "
69 "DP_QC_STRINGBUFFERS "
72 "DP_QC_TRACE_MOVETYPE_HITMODEL "
73 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
74 "DP_QC_VECTORVECTORS "
80 "DP_SND_DIRECTIONLESSATTNNONE "
89 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
90 "DP_SV_DRAWONLYTOCLIENT "
93 "DP_SV_NODRAWTOCLIENT "
95 "DP_SV_PLAYERPHYSICS "
96 "DP_SV_PRECACHEANYTIME "
98 "DP_SV_ROTATINGBMODEL "
101 "DP_SV_WRITEUNTERMINATEDSTRING "
105 "DP_TE_EXPLOSIONRGB "
107 "DP_TE_PARTICLECUBE "
108 "DP_TE_PARTICLERAIN "
109 "DP_TE_PARTICLESNOW "
111 "DP_TE_QUADEFFECTS1 "
114 "DP_TE_STANDARDEFFECTBUILTINS "
115 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
118 //"EXT_CSQC " // not ready yet
120 "KRIMZON_SV_PARSECLIENTCOMMAND "
124 "PRYDON_CLIENTCURSOR "
125 "TENEBRAE_GFX_DLIGHTS "
127 "NEXUIZ_PLAYERMODEL "
134 Writes new values for v_forward, v_up, and v_right based on angles
138 void PF_makevectors (void)
140 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
147 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.
149 setorigin (entity, origin)
152 void PF_setorigin (void)
157 e = PRVM_G_EDICT(OFS_PARM0);
158 if (e == prog->edicts)
160 VM_Warning("setorigin: can not modify world entity\n");
163 if (e->priv.server->free)
165 VM_Warning("setorigin: can not modify free entity\n");
168 org = PRVM_G_VECTOR(OFS_PARM1);
169 VectorCopy (org, e->fields.server->origin);
170 SV_LinkEdict (e, false);
174 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
178 for (i=0 ; i<3 ; i++)
180 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
182 // set derived values
183 VectorCopy (min, e->fields.server->mins);
184 VectorCopy (max, e->fields.server->maxs);
185 VectorSubtract (max, min, e->fields.server->size);
187 SV_LinkEdict (e, false);
194 the size box is rotated by the current angle
195 LordHavoc: no it isn't...
197 setsize (entity, minvector, maxvector)
200 void PF_setsize (void)
205 e = PRVM_G_EDICT(OFS_PARM0);
206 if (e == prog->edicts)
208 VM_Warning("setsize: can not modify world entity\n");
211 if (e->priv.server->free)
213 VM_Warning("setsize: can not modify free entity\n");
216 min = PRVM_G_VECTOR(OFS_PARM1);
217 max = PRVM_G_VECTOR(OFS_PARM2);
218 SetMinMaxSize (e, min, max, false);
226 setmodel(entity, model)
229 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
230 void PF_setmodel (void)
236 e = PRVM_G_EDICT(OFS_PARM0);
237 if (e == prog->edicts)
239 VM_Warning("setmodel: can not modify world entity\n");
242 if (e->priv.server->free)
244 VM_Warning("setmodel: can not modify free entity\n");
247 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
248 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
249 e->fields.server->modelindex = i;
255 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
256 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
258 SetMinMaxSize (e, quakemins, quakemaxs, true);
261 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
268 single print to a specific client
270 sprint(clientent, value)
273 void PF_sprint (void)
277 char string[VM_STRINGTEMP_LENGTH];
279 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
281 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
283 VM_Warning("tried to centerprint to a non-client\n");
287 client = svs.clients + entnum-1;
288 if (!client->netconnection)
291 VM_VarString(1, string, sizeof(string));
292 MSG_WriteChar(&client->netconnection->message,svc_print);
293 MSG_WriteString(&client->netconnection->message, string);
301 single print to a specific client
303 centerprint(clientent, value)
306 void PF_centerprint (void)
310 char string[VM_STRINGTEMP_LENGTH];
312 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
314 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
316 VM_Warning("tried to centerprint to a non-client\n");
320 client = svs.clients + entnum-1;
321 if (!client->netconnection)
324 VM_VarString(1, string, sizeof(string));
325 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
326 MSG_WriteString(&client->netconnection->message, string);
333 particle(origin, color, count)
336 void PF_particle (void)
342 org = PRVM_G_VECTOR(OFS_PARM0);
343 dir = PRVM_G_VECTOR(OFS_PARM1);
344 color = PRVM_G_FLOAT(OFS_PARM2);
345 count = PRVM_G_FLOAT(OFS_PARM3);
346 SV_StartParticle (org, dir, (int)color, (int)count);
356 void PF_ambientsound (void)
360 float vol, attenuation;
363 pos = PRVM_G_VECTOR (OFS_PARM0);
364 samp = PRVM_G_STRING(OFS_PARM1);
365 vol = PRVM_G_FLOAT(OFS_PARM2);
366 attenuation = PRVM_G_FLOAT(OFS_PARM3);
368 // check to see if samp was properly precached
369 soundnum = SV_SoundIndex(samp, 1);
377 // add an svc_spawnambient command to the level signon packet
380 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
382 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
384 MSG_WriteVector(&sv.signon, pos, sv.protocol);
387 MSG_WriteShort (&sv.signon, soundnum);
389 MSG_WriteByte (&sv.signon, soundnum);
391 MSG_WriteByte (&sv.signon, (int)(vol*255));
392 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
400 Each entity can have eight independant sound sources, like voice,
403 Channel 0 is an auto-allocate channel, the others override anything
404 already running on that entity/channel pair.
406 An attenuation of 0 will play full volume everywhere in the level.
407 Larger attenuations will drop off.
415 prvm_edict_t *entity;
419 entity = PRVM_G_EDICT(OFS_PARM0);
420 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
421 sample = PRVM_G_STRING(OFS_PARM2);
422 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
423 attenuation = PRVM_G_FLOAT(OFS_PARM4);
425 if (volume < 0 || volume > 255)
427 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
431 if (attenuation < 0 || attenuation > 4)
433 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
437 if (channel < 0 || channel > 7)
439 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
443 SV_StartSound (entity, channel, sample, volume, attenuation);
450 Used for use tracing and shot targeting
451 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
452 if the tryents flag is set.
454 traceline (vector1, vector2, tryents)
457 void PF_traceline (void)
465 prog->xfunction->builtinsprofile += 30;
467 v1 = PRVM_G_VECTOR(OFS_PARM0);
468 v2 = PRVM_G_VECTOR(OFS_PARM1);
469 move = (int)PRVM_G_FLOAT(OFS_PARM2);
470 ent = PRVM_G_EDICT(OFS_PARM3);
472 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]))
473 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));
475 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
477 prog->globals.server->trace_allsolid = trace.allsolid;
478 prog->globals.server->trace_startsolid = trace.startsolid;
479 prog->globals.server->trace_fraction = trace.fraction;
480 prog->globals.server->trace_inwater = trace.inwater;
481 prog->globals.server->trace_inopen = trace.inopen;
482 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
483 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
484 prog->globals.server->trace_plane_dist = trace.plane.dist;
486 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
488 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
489 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
490 val->_float = trace.startsupercontents;
491 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
492 val->_float = trace.hitsupercontents;
493 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
494 val->_float = trace.hitq3surfaceflags;
495 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
497 if (trace.hittexture)
499 char *s = VM_GetTempString();
500 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
501 val->string = PRVM_SetEngineString(s);
513 Used for use tracing and shot targeting
514 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
515 if the tryents flag is set.
517 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
520 // LordHavoc: added this for my own use, VERY useful, similar to traceline
521 void PF_tracebox (void)
523 float *v1, *v2, *m1, *m2;
529 prog->xfunction->builtinsprofile += 30;
531 v1 = PRVM_G_VECTOR(OFS_PARM0);
532 m1 = PRVM_G_VECTOR(OFS_PARM1);
533 m2 = PRVM_G_VECTOR(OFS_PARM2);
534 v2 = PRVM_G_VECTOR(OFS_PARM3);
535 move = (int)PRVM_G_FLOAT(OFS_PARM4);
536 ent = PRVM_G_EDICT(OFS_PARM5);
538 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]))
539 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));
541 trace = SV_Move (v1, m1, m2, v2, move, ent);
543 prog->globals.server->trace_allsolid = trace.allsolid;
544 prog->globals.server->trace_startsolid = trace.startsolid;
545 prog->globals.server->trace_fraction = trace.fraction;
546 prog->globals.server->trace_inwater = trace.inwater;
547 prog->globals.server->trace_inopen = trace.inopen;
548 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
549 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
550 prog->globals.server->trace_plane_dist = trace.plane.dist;
552 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
554 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
555 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
556 val->_float = trace.startsupercontents;
557 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
558 val->_float = trace.hitsupercontents;
559 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
560 val->_float = trace.hitq3surfaceflags;
561 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
563 if (trace.hittexture)
565 char *s = VM_GetTempString();
566 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
567 val->string = PRVM_SetEngineString(s);
574 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
575 void PF_tracetoss (void)
579 prvm_edict_t *ignore;
582 prog->xfunction->builtinsprofile += 600;
584 ent = PRVM_G_EDICT(OFS_PARM0);
585 if (ent == prog->edicts)
587 VM_Warning("tracetoss: can not use world entity\n");
590 ignore = PRVM_G_EDICT(OFS_PARM1);
592 trace = SV_Trace_Toss (ent, ignore);
594 prog->globals.server->trace_allsolid = trace.allsolid;
595 prog->globals.server->trace_startsolid = trace.startsolid;
596 prog->globals.server->trace_fraction = trace.fraction;
597 prog->globals.server->trace_inwater = trace.inwater;
598 prog->globals.server->trace_inopen = trace.inopen;
599 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
600 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
601 prog->globals.server->trace_plane_dist = trace.plane.dist;
603 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
605 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
606 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
607 val->_float = trace.startsupercontents;
608 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
609 val->_float = trace.hitsupercontents;
610 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
611 val->_float = trace.hitq3surfaceflags;
612 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
614 if (trace.hittexture)
616 char *s = VM_GetTempString();
617 strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH);
618 val->string = PRVM_SetEngineString(s);
630 Returns true if the given entity can move to the given position from it's
631 current position by walking or rolling.
633 scalar checkpos (entity, vector)
636 void PF_checkpos (void)
640 //============================================================================
643 unsigned char checkpvs[MAX_MAP_LEAFS/8];
645 int PF_newcheckclient (int check)
651 // cycle to the next one
653 check = bound(1, check, svs.maxclients);
654 if (check == svs.maxclients)
662 prog->xfunction->builtinsprofile++;
664 if (i == svs.maxclients+1)
666 // look up the client's edict
667 ent = PRVM_EDICT_NUM(i);
668 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
669 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
671 // found a valid client (possibly the same one again)
675 // get the PVS for the entity
676 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
678 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
679 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
688 Returns a client (or object that has a client enemy) that would be a
691 If there is more than one valid option, they are cycled each frame
693 If (self.origin + self.viewofs) is not in the PVS of the current target,
694 it is not returned at all.
699 int c_invis, c_notvis;
700 void PF_checkclient (void)
702 prvm_edict_t *ent, *self;
705 // find a new check if on a new frame
706 if (sv.time - sv.lastchecktime >= 0.1)
708 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
709 sv.lastchecktime = sv.time;
712 // return check if it might be visible
713 ent = PRVM_EDICT_NUM(sv.lastcheck);
714 if (ent->priv.server->free || ent->fields.server->health <= 0)
716 VM_RETURN_EDICT(prog->edicts);
720 // if current entity can't possibly see the check entity, return 0
721 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
722 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
723 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
726 VM_RETURN_EDICT(prog->edicts);
730 // might be able to see it
732 VM_RETURN_EDICT(ent);
735 //============================================================================
742 Sends text over to the client's execution buffer
744 stuffcmd (clientent, value, ...)
747 void PF_stuffcmd (void)
751 char string[VM_STRINGTEMP_LENGTH];
753 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
754 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
756 VM_Warning("Can't stuffcmd to a non-client\n");
760 VM_VarString(1, string, sizeof(string));
763 host_client = svs.clients + entnum-1;
764 Host_ClientCommands ("%s", string);
772 Returns a chain of entities that have origins within a spherical area
774 findradius (origin, radius)
777 void PF_findradius (void)
779 prvm_edict_t *ent, *chain;
780 vec_t radius, radius2;
781 vec3_t org, eorg, mins, maxs;
784 prvm_edict_t *touchedicts[MAX_EDICTS];
786 chain = (prvm_edict_t *)prog->edicts;
788 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
789 radius = PRVM_G_FLOAT(OFS_PARM1);
790 radius2 = radius * radius;
792 mins[0] = org[0] - (radius + 1);
793 mins[1] = org[1] - (radius + 1);
794 mins[2] = org[2] - (radius + 1);
795 maxs[0] = org[0] + (radius + 1);
796 maxs[1] = org[1] + (radius + 1);
797 maxs[2] = org[2] + (radius + 1);
798 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
799 if (numtouchedicts > MAX_EDICTS)
801 // this never happens
802 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
803 numtouchedicts = MAX_EDICTS;
805 for (i = 0;i < numtouchedicts;i++)
807 ent = touchedicts[i];
808 prog->xfunction->builtinsprofile++;
809 // Quake did not return non-solid entities but darkplaces does
810 // (note: this is the reason you can't blow up fallen zombies)
811 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
813 // LordHavoc: compare against bounding box rather than center so it
814 // doesn't miss large objects, and use DotProduct instead of Length
815 // for a major speedup
816 VectorSubtract(org, ent->fields.server->origin, eorg);
817 if (sv_gameplayfix_findradiusdistancetobox.integer)
819 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
820 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
821 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
824 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
825 if (DotProduct(eorg, eorg) < radius2)
827 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
832 VM_RETURN_EDICT(chain);
835 void PF_precache_file (void)
836 { // precache_file is only used to copy files with qcc, it does nothing
837 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
841 void PF_precache_sound (void)
843 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
844 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
847 void PF_precache_model (void)
849 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
850 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
857 float(float yaw, float dist) walkmove
860 void PF_walkmove (void)
868 // assume failure if it returns early
869 PRVM_G_FLOAT(OFS_RETURN) = 0;
871 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
872 if (ent == prog->edicts)
874 VM_Warning("walkmove: can not modify world entity\n");
877 if (ent->priv.server->free)
879 VM_Warning("walkmove: can not modify free entity\n");
882 yaw = PRVM_G_FLOAT(OFS_PARM0);
883 dist = PRVM_G_FLOAT(OFS_PARM1);
885 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
888 yaw = yaw*M_PI*2 / 360;
890 move[0] = cos(yaw)*dist;
891 move[1] = sin(yaw)*dist;
894 // save program state, because SV_movestep may call other progs
895 oldf = prog->xfunction;
896 oldself = prog->globals.server->self;
898 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
901 // restore program state
902 prog->xfunction = oldf;
903 prog->globals.server->self = oldself;
913 void PF_droptofloor (void)
919 // assume failure if it returns early
920 PRVM_G_FLOAT(OFS_RETURN) = 0;
922 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
923 if (ent == prog->edicts)
925 VM_Warning("droptofloor: can not modify world entity\n");
928 if (ent->priv.server->free)
930 VM_Warning("droptofloor: can not modify free entity\n");
934 VectorCopy (ent->fields.server->origin, end);
937 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
939 if (trace.fraction != 1)
941 VectorCopy (trace.endpos, ent->fields.server->origin);
942 SV_LinkEdict (ent, false);
943 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
944 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
945 PRVM_G_FLOAT(OFS_RETURN) = 1;
946 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
947 ent->priv.server->suspendedinairflag = true;
955 void(float style, string value) lightstyle
958 void PF_lightstyle (void)
965 style = (int)PRVM_G_FLOAT(OFS_PARM0);
966 val = PRVM_G_STRING(OFS_PARM1);
968 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
969 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
972 // change the string in sv
973 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
975 // send message to all clients on this server
976 if (sv.state != ss_active)
979 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
981 if (client->active && client->netconnection)
983 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
984 MSG_WriteChar (&client->netconnection->message,style);
985 MSG_WriteString (&client->netconnection->message, val);
995 void PF_checkbottom (void)
997 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1005 void PF_pointcontents (void)
1007 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1014 Pick a vector for the player to shoot along
1015 vector aim(entity, missilespeed)
1020 prvm_edict_t *ent, *check, *bestent;
1021 vec3_t start, dir, end, bestdir;
1024 float dist, bestdist;
1027 // assume failure if it returns early
1028 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1029 // if sv_aim is so high it can't possibly accept anything, skip out early
1030 if (sv_aim.value >= 1)
1033 ent = PRVM_G_EDICT(OFS_PARM0);
1034 if (ent == prog->edicts)
1036 VM_Warning("aim: can not use world entity\n");
1039 if (ent->priv.server->free)
1041 VM_Warning("aim: can not use free entity\n");
1044 speed = PRVM_G_FLOAT(OFS_PARM1);
1046 VectorCopy (ent->fields.server->origin, start);
1049 // try sending a trace straight
1050 VectorCopy (prog->globals.server->v_forward, dir);
1051 VectorMA (start, 2048, dir, end);
1052 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1053 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1054 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1056 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1061 // try all possible entities
1062 VectorCopy (dir, bestdir);
1063 bestdist = sv_aim.value;
1066 check = PRVM_NEXT_EDICT(prog->edicts);
1067 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1069 prog->xfunction->builtinsprofile++;
1070 if (check->fields.server->takedamage != DAMAGE_AIM)
1074 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1075 continue; // don't aim at teammate
1076 for (j=0 ; j<3 ; j++)
1077 end[j] = check->fields.server->origin[j]
1078 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1079 VectorSubtract (end, start, dir);
1080 VectorNormalize (dir);
1081 dist = DotProduct (dir, prog->globals.server->v_forward);
1082 if (dist < bestdist)
1083 continue; // to far to turn
1084 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1085 if (tr.ent == check)
1086 { // can shoot at this one
1094 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1095 dist = DotProduct (dir, prog->globals.server->v_forward);
1096 VectorScale (prog->globals.server->v_forward, dist, end);
1098 VectorNormalize (end);
1099 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1103 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1111 This was a major timewaster in progs, so it was converted to C
1114 void PF_changeyaw (void)
1117 float ideal, current, move, speed;
1119 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1120 if (ent == prog->edicts)
1122 VM_Warning("changeyaw: can not modify world entity\n");
1125 if (ent->priv.server->free)
1127 VM_Warning("changeyaw: can not modify free entity\n");
1130 current = ANGLEMOD(ent->fields.server->angles[1]);
1131 ideal = ent->fields.server->ideal_yaw;
1132 speed = ent->fields.server->yaw_speed;
1134 if (current == ideal)
1136 move = ideal - current;
1137 if (ideal > current)
1158 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1166 void PF_changepitch (void)
1169 float ideal, current, move, speed;
1172 ent = PRVM_G_EDICT(OFS_PARM0);
1173 if (ent == prog->edicts)
1175 VM_Warning("changepitch: can not modify world entity\n");
1178 if (ent->priv.server->free)
1180 VM_Warning("changepitch: can not modify free entity\n");
1183 current = ANGLEMOD( ent->fields.server->angles[0] );
1184 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1185 ideal = val->_float;
1188 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1191 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1192 speed = val->_float;
1195 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1199 if (current == ideal)
1201 move = ideal - current;
1202 if (ideal > current)
1223 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1227 ===============================================================================
1231 ===============================================================================
1234 #define MSG_BROADCAST 0 // unreliable to all
1235 #define MSG_ONE 1 // reliable to one (msg_entity)
1236 #define MSG_ALL 2 // reliable to all
1237 #define MSG_INIT 3 // write to the init string
1238 #define MSG_ENTITY 5
1240 sizebuf_t *WriteDest (void)
1245 extern sizebuf_t *sv2csqcbuf;
1247 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1251 return &sv.datagram;
1254 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1255 entnum = PRVM_NUM_FOR_EDICT(ent);
1256 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1258 VM_Warning ("WriteDest: tried to write to non-client\n");
1259 return &sv.reliable_datagram;
1262 return &svs.clients[entnum-1].netconnection->message;
1265 VM_Warning ("WriteDest: bad destination\n");
1267 return &sv.reliable_datagram;
1279 void PF_WriteByte (void)
1281 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1284 void PF_WriteChar (void)
1286 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1289 void PF_WriteShort (void)
1291 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1294 void PF_WriteLong (void)
1296 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1299 void PF_WriteAngle (void)
1301 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1304 void PF_WriteCoord (void)
1306 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1309 void PF_WriteString (void)
1311 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1314 void PF_WriteUnterminatedString (void)
1316 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1320 void PF_WriteEntity (void)
1322 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1325 //////////////////////////////////////////////////////////
1327 void PF_makestatic (void)
1332 ent = PRVM_G_EDICT(OFS_PARM0);
1333 if (ent == prog->edicts)
1335 VM_Warning("makestatic: can not modify world entity\n");
1338 if (ent->priv.server->free)
1340 VM_Warning("makestatic: can not modify free entity\n");
1345 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1350 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1351 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1352 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1356 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1357 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1358 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1361 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1362 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1363 for (i=0 ; i<3 ; i++)
1365 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1366 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1369 // throw the entity away now
1373 //=============================================================================
1380 void PF_setspawnparms (void)
1386 ent = PRVM_G_EDICT(OFS_PARM0);
1387 i = PRVM_NUM_FOR_EDICT(ent);
1388 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1390 Con_Print("tried to setspawnparms on a non-client\n");
1394 // copy spawn parms out of the client_t
1395 client = svs.clients + i-1;
1396 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1397 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1404 Returns a color vector indicating the lighting at the requested point.
1406 (Internal Operation note: actually measures the light beneath the point, just like
1407 the model lighting on the client)
1412 void PF_getlight (void)
1414 vec3_t ambientcolor, diffusecolor, diffusenormal;
1416 p = PRVM_G_VECTOR(OFS_PARM0);
1417 VectorClear(ambientcolor);
1418 VectorClear(diffusecolor);
1419 VectorClear(diffusenormal);
1420 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1421 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1422 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1425 void PF_registercvar (void)
1427 const char *name, *value;
1428 name = PRVM_G_STRING(OFS_PARM0);
1429 value = PRVM_G_STRING(OFS_PARM1);
1430 PRVM_G_FLOAT(OFS_RETURN) = 0;
1432 // first check to see if it has already been defined
1433 if (Cvar_FindVar (name))
1436 // check for overlap with a command
1437 if (Cmd_Exists (name))
1439 VM_Warning("PF_registercvar: %s is a command\n", name);
1443 Cvar_Get(name, value, 0);
1445 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1450 unsigned char type; // 1/2/8 or other value if isn't used
1454 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1455 static int vm_autosentstats_last;
1457 void VM_AutoSentStats_Clear (void)
1459 if(vm_autosentstats)
1461 Z_Free(vm_autosentstats);
1462 vm_autosentstats = NULL;
1463 vm_autosentstats_last = -1;
1467 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1468 #define VM_SENDSTAT(a,b,c)\
1471 if((c)==(unsigned char)(c))\
1473 MSG_WriteByte((a), svc_updatestatubyte);\
1474 MSG_WriteByte((a), (b));\
1475 MSG_WriteByte((a), (c));\
1479 MSG_WriteByte((a), svc_updatestat);\
1480 MSG_WriteByte((a), (b));\
1481 MSG_WriteLong((a), (c));\
1485 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1497 if(!vm_autosentstats)
1500 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);
1502 for(i=0; i<vm_autosentstats_last+1 ;i++)
1504 if(!vm_autosentstats[i].type)
1506 switch(vm_autosentstats[i].type)
1510 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1518 stats[i+32] = si[0];
1519 stats[i+33] = si[1];
1520 stats[i+34] = si[2];
1521 stats[i+35] = si[3];
1525 VM_SENDSTAT(msg, i+32, si[0]);
1526 VM_SENDSTAT(msg, i+33, si[1]);
1527 VM_SENDSTAT(msg, i+34, si[2]);
1528 VM_SENDSTAT(msg, i+35, si[3]);
1534 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1535 k.i = LittleLong (k.i);
1539 VM_SENDSTAT(msg, i+32, k.i);
1543 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1547 VM_SENDSTAT(msg, i+32, v);
1555 // void(float index, float type, .void field) SV_AddStat = #470;
1556 // Set up an auto-sent player stat.
1557 // Client's get thier own fields sent to them. Index may not be less than 32.
1558 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1559 // 1: string (4 stats carrying a total of 16 charactures)
1560 // 2: float (one stat, float converted to an integer for transportation)
1561 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1562 void PF_SV_AddStat (void)
1567 if(!vm_autosentstats)
1569 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1570 if(!vm_autosentstats)
1572 VM_Warning("PF_SV_AddStat: not enough memory\n");
1576 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1577 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1578 off = PRVM_G_INT (OFS_PARM2);
1583 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1586 if(i >= (MAX_CL_STATS-32))
1588 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1591 if(i > (MAX_CL_STATS-32-4) && type == 1)
1593 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1596 vm_autosentstats[i].type = type;
1597 vm_autosentstats[i].fieldoffset = off;
1598 if(vm_autosentstats_last < i)
1599 vm_autosentstats_last = i;
1606 copies data from one entity to another
1608 copyentity(src, dst)
1611 void PF_copyentity (void)
1613 prvm_edict_t *in, *out;
1614 in = PRVM_G_EDICT(OFS_PARM0);
1615 if (in == prog->edicts)
1617 VM_Warning("copyentity: can not read world entity\n");
1620 if (in->priv.server->free)
1622 VM_Warning("copyentity: can not read free entity\n");
1625 out = PRVM_G_EDICT(OFS_PARM1);
1626 if (out == prog->edicts)
1628 VM_Warning("copyentity: can not modify world entity\n");
1631 if (out->priv.server->free)
1633 VM_Warning("copyentity: can not modify free entity\n");
1636 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1644 sets the color of a client and broadcasts the update to all connected clients
1646 setcolor(clientent, value)
1649 void PF_setcolor (void)
1655 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1656 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1658 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1660 Con_Print("tried to setcolor a non-client\n");
1664 client = svs.clients + entnum-1;
1667 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1669 client->edict->fields.server->team = (i & 15) + 1;
1672 if (client->old_colors != client->colors)
1674 client->old_colors = client->colors;
1675 // send notification to all clients
1676 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1677 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1678 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1686 effect(origin, modelname, startframe, framecount, framerate)
1689 void PF_effect (void)
1693 s = PRVM_G_STRING(OFS_PARM1);
1696 VM_Warning("effect: no model specified\n");
1700 i = SV_ModelIndex(s, 1);
1703 VM_Warning("effect: model not precached\n");
1706 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));
1709 void PF_te_blood (void)
1711 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1713 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1714 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1716 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1717 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1718 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1720 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1721 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1722 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1724 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1727 void PF_te_bloodshower (void)
1729 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1731 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1732 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1734 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1735 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1736 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1738 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1739 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1744 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1747 void PF_te_explosionrgb (void)
1749 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1750 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1752 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1753 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1754 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1756 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1757 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1758 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1761 void PF_te_particlecube (void)
1763 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1765 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1766 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1768 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1769 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1770 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1772 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1773 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1780 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1782 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1783 // gravity true/false
1784 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1786 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1789 void PF_te_particlerain (void)
1791 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1793 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1794 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1796 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1797 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1798 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1800 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1801 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1808 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1810 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1813 void PF_te_particlesnow (void)
1815 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1817 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1818 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1820 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1821 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1822 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1824 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1825 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1832 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1834 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1837 void PF_te_spark (void)
1839 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1841 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1842 MSG_WriteByte(&sv.datagram, TE_SPARK);
1844 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1845 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1846 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1848 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1849 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1850 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1852 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1855 void PF_te_gunshotquad (void)
1857 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1858 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1860 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1861 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1862 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1865 void PF_te_spikequad (void)
1867 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1868 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1870 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1871 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1872 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1875 void PF_te_superspikequad (void)
1877 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1878 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1880 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1881 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1882 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1885 void PF_te_explosionquad (void)
1887 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1888 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1890 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1891 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1892 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1895 void PF_te_smallflash (void)
1897 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1898 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1900 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1901 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1902 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1905 void PF_te_customflash (void)
1907 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1909 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1910 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1912 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1913 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1914 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1916 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1918 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1920 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1921 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1922 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1925 void PF_te_gunshot (void)
1927 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1930 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1931 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1932 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1935 void PF_te_spike (void)
1937 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1938 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1940 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1941 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1942 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1945 void PF_te_superspike (void)
1947 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1948 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1950 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1951 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1952 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1955 void PF_te_explosion (void)
1957 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1958 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1960 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1961 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1962 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1965 void PF_te_tarexplosion (void)
1967 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1968 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1970 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1971 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1972 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1975 void PF_te_wizspike (void)
1977 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1980 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1985 void PF_te_knightspike (void)
1987 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1990 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1991 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1992 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1995 void PF_te_lavasplash (void)
1997 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1998 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2000 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2001 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2002 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005 void PF_te_teleport (void)
2007 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2008 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2010 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2011 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2012 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2015 void PF_te_explosion2 (void)
2017 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2018 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2020 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2021 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2022 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2024 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2025 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2028 void PF_te_lightning1 (void)
2030 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2031 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2033 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2035 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2036 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2037 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2039 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2040 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2044 void PF_te_lightning2 (void)
2046 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2049 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2051 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2052 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2053 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2055 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2056 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2060 void PF_te_lightning3 (void)
2062 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2063 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2065 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2067 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2068 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2069 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2071 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2072 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2076 void PF_te_beam (void)
2078 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2079 MSG_WriteByte(&sv.datagram, TE_BEAM);
2081 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2083 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2084 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2085 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2087 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2088 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2092 void PF_te_plasmaburn (void)
2094 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2095 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2101 void PF_te_flamejet (void)
2103 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2104 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2106 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2107 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2108 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2110 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2111 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2114 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2117 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2120 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2122 bestdist = 1000000000;
2124 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2126 // clip original point to each triangle of the surface and find the
2127 // triangle that is closest
2128 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2129 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2130 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2131 TriangleNormal(v[0], v[1], v[2], facenormal);
2132 VectorNormalize(facenormal);
2133 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2134 VectorMA(p, offsetdist, facenormal, temp);
2135 for (j = 0, k = 2;j < 3;k = j, j++)
2137 VectorSubtract(v[k], v[j], edgenormal);
2138 CrossProduct(edgenormal, facenormal, sidenormal);
2139 VectorNormalize(sidenormal);
2140 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2142 VectorMA(temp, offsetdist, sidenormal, temp);
2144 dist = VectorDistance2(temp, p);
2145 if (bestdist > dist)
2148 VectorCopy(temp, out);
2153 static model_t *getmodel(prvm_edict_t *ed)
2156 if (!ed || ed->priv.server->free)
2158 modelindex = (int)ed->fields.server->modelindex;
2159 if (modelindex < 1 || modelindex >= MAX_MODELS)
2161 return sv.models[modelindex];
2164 static msurface_t *getsurface(model_t *model, int surfacenum)
2166 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2168 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2172 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2173 void PF_getsurfacenumpoints(void)
2176 msurface_t *surface;
2177 // return 0 if no such surface
2178 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2180 PRVM_G_FLOAT(OFS_RETURN) = 0;
2184 // note: this (incorrectly) assumes it is a simple polygon
2185 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2187 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2188 void PF_getsurfacepoint(void)
2192 msurface_t *surface;
2194 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2195 ed = PRVM_G_EDICT(OFS_PARM0);
2196 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2198 // note: this (incorrectly) assumes it is a simple polygon
2199 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2200 if (pointnum < 0 || pointnum >= surface->num_vertices)
2202 // FIXME: implement rotation/scaling
2203 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2205 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2206 void PF_getsurfacenormal(void)
2209 msurface_t *surface;
2211 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2212 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2214 // FIXME: implement rotation/scaling
2215 // note: this (incorrectly) assumes it is a simple polygon
2216 // note: this only returns the first triangle, so it doesn't work very
2217 // well for curved surfaces or arbitrary meshes
2218 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);
2219 VectorNormalize(normal);
2220 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2222 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2223 void PF_getsurfacetexture(void)
2226 msurface_t *surface;
2227 PRVM_G_INT(OFS_RETURN) = 0;
2228 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2230 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2232 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2233 void PF_getsurfacenearpoint(void)
2235 int surfacenum, best;
2237 vec_t dist, bestdist;
2240 msurface_t *surface;
2242 PRVM_G_FLOAT(OFS_RETURN) = -1;
2243 ed = PRVM_G_EDICT(OFS_PARM0);
2244 point = PRVM_G_VECTOR(OFS_PARM1);
2246 if (!ed || ed->priv.server->free)
2248 model = getmodel(ed);
2249 if (!model || !model->num_surfaces)
2252 // FIXME: implement rotation/scaling
2253 VectorSubtract(point, ed->fields.server->origin, p);
2255 bestdist = 1000000000;
2256 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2258 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2259 // first see if the nearest point on the surface's box is closer than the previous match
2260 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2261 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2262 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2263 dist = VectorLength2(clipped);
2264 if (dist < bestdist)
2266 // it is, check the nearest point on the actual geometry
2267 clippointtosurface(model, surface, p, clipped);
2268 VectorSubtract(clipped, p, clipped);
2269 dist += VectorLength2(clipped);
2270 if (dist < bestdist)
2272 // that's closer too, store it as the best match
2278 PRVM_G_FLOAT(OFS_RETURN) = best;
2280 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2281 void PF_getsurfaceclippedpoint(void)
2285 msurface_t *surface;
2287 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2288 ed = PRVM_G_EDICT(OFS_PARM0);
2289 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2291 // FIXME: implement rotation/scaling
2292 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2293 clippointtosurface(model, surface, p, out);
2294 // FIXME: implement rotation/scaling
2295 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2298 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2299 //this function originally written by KrimZon, made shorter by LordHavoc
2300 void PF_clientcommand (void)
2302 client_t *temp_client;
2305 //find client for this entity
2306 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2307 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2309 Con_Print("PF_clientcommand: entity is not a client\n");
2313 temp_client = host_client;
2314 host_client = svs.clients + i;
2315 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2316 host_client = temp_client;
2319 //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)
2320 void PF_setattachment (void)
2322 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2323 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2324 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2329 if (e == prog->edicts)
2331 VM_Warning("setattachment: can not modify world entity\n");
2334 if (e->priv.server->free)
2336 VM_Warning("setattachment: can not modify free entity\n");
2340 if (tagentity == NULL)
2341 tagentity = prog->edicts;
2343 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2345 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2347 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2350 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2352 modelindex = (int)tagentity->fields.server->modelindex;
2353 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2355 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2357 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);
2360 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));
2364 /////////////////////////////////////////
2365 // DP_MD3_TAGINFO extension coded by VorteX
2367 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2372 i = (int)e->fields.server->modelindex;
2373 if (i < 1 || i >= MAX_MODELS)
2375 model = sv.models[i];
2377 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2380 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2382 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2386 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);
2388 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);
2391 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2397 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2398 && (model = sv.models[(int)ent->fields.server->modelindex])
2399 && model->animscenes)
2401 // if model has wrong frame, engine automatically switches to model first frame
2402 frame = (int)ent->fields.server->frame;
2403 if (frame < 0 || frame >= model->numframes)
2405 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2407 *out = identitymatrix;
2411 // Warnings/errors code:
2412 // 0 - normal (everything all-right)
2415 // 3 - null or non-precached model
2416 // 4 - no tags with requested index
2417 // 5 - runaway loop at attachment chain
2418 extern cvar_t cl_bob;
2419 extern cvar_t cl_bobcycle;
2420 extern cvar_t cl_bobup;
2421 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2425 int modelindex, attachloop;
2426 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2429 *out = identitymatrix; // warnings and errors return identical matrix
2431 if (ent == prog->edicts)
2433 if (ent->priv.server->free)
2436 modelindex = (int)ent->fields.server->modelindex;
2437 if (modelindex <= 0 || modelindex > MAX_MODELS)
2440 model = sv.models[modelindex];
2442 tagmatrix = identitymatrix;
2443 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2447 if (attachloop >= 256) // prevent runaway looping
2449 // apply transformation by child's tagindex on parent entity and then
2450 // by parent entity itself
2451 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2452 if (ret && attachloop == 0)
2454 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2455 SV_GetEntityMatrix(ent, &entitymatrix, false);
2456 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2457 // next iteration we process the parent entity
2458 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2460 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2461 ent = PRVM_EDICT_NUM(val->edict);
2468 // RENDER_VIEWMODEL magic
2469 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2471 Matrix4x4_Copy(&tagmatrix, out);
2472 ent = PRVM_EDICT_NUM(val->edict);
2474 SV_GetEntityMatrix(ent, &entitymatrix, true);
2475 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2478 // Cl_bob, ported from rendering code
2479 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2482 // LordHavoc: this code is *weird*, but not replacable (I think it
2483 // should be done in QC on the server, but oh well, quake is quake)
2484 // LordHavoc: figured out bobup: the time at which the sin is at 180
2485 // degrees (which allows lengthening or squishing the peak or valley)
2486 cycle = sv.time/cl_bobcycle.value;
2487 cycle -= (int)cycle;
2488 if (cycle < cl_bobup.value)
2489 cycle = sin(M_PI * cycle / cl_bobup.value);
2491 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2492 // bob is proportional to velocity in the xy plane
2493 // (don't count Z, or jumping messes it up)
2494 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;
2495 bob = bob*0.3 + bob*0.7*cycle;
2496 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2503 //float(entity ent, string tagname) gettagindex;
2505 void PF_gettagindex (void)
2507 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2508 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2509 int modelindex, tag_index;
2511 if (ent == prog->edicts)
2513 VM_Warning("gettagindex: can't affect world entity\n");
2516 if (ent->priv.server->free)
2518 VM_Warning("gettagindex: can't affect free entity\n");
2522 modelindex = (int)ent->fields.server->modelindex;
2524 if (modelindex <= 0 || modelindex > MAX_MODELS)
2525 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2528 tag_index = SV_GetTagIndex(ent, tag_name);
2530 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2532 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2535 //vector(entity ent, float tagindex) gettaginfo;
2536 void PF_gettaginfo (void)
2538 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2539 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2540 matrix4x4_t tag_matrix;
2543 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2544 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2549 VM_Warning("gettagindex: can't affect world entity\n");
2552 VM_Warning("gettagindex: can't affect free entity\n");
2555 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2558 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2561 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2566 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2567 void PF_dropclient (void)
2570 client_t *oldhostclient;
2571 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2572 if (clientnum < 0 || clientnum >= svs.maxclients)
2574 VM_Warning("dropclient: not a client\n");
2577 if (!svs.clients[clientnum].active)
2579 VM_Warning("dropclient: that client slot is not connected\n");
2582 oldhostclient = host_client;
2583 host_client = svs.clients + clientnum;
2584 SV_DropClient(false);
2585 host_client = oldhostclient;
2588 //entity() spawnclient (DP_SV_BOTCLIENT)
2589 void PF_spawnclient (void)
2593 prog->xfunction->builtinsprofile += 2;
2595 for (i = 0;i < svs.maxclients;i++)
2597 if (!svs.clients[i].active)
2599 prog->xfunction->builtinsprofile += 100;
2600 SV_ConnectClient (i, NULL);
2601 // this has to be set or else ClientDisconnect won't be called
2602 // we assume the qc will call ClientConnect...
2603 svs.clients[i].clientconnectcalled = true;
2604 ed = PRVM_EDICT_NUM(i + 1);
2608 VM_RETURN_EDICT(ed);
2611 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2612 void PF_clienttype (void)
2615 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2616 if (clientnum < 0 || clientnum >= svs.maxclients)
2617 PRVM_G_FLOAT(OFS_RETURN) = 3;
2618 else if (!svs.clients[clientnum].active)
2619 PRVM_G_FLOAT(OFS_RETURN) = 0;
2620 else if (svs.clients[clientnum].netconnection)
2621 PRVM_G_FLOAT(OFS_RETURN) = 1;
2623 PRVM_G_FLOAT(OFS_RETURN) = 2;
2626 void PF_edict_num (void)
2628 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2631 prvm_builtin_t vm_sv_builtins[] = {
2633 PF_makevectors, // #1 void(vector ang) makevectors
2634 PF_setorigin, // #2 void(entity e, vector o) setorigin
2635 PF_setmodel, // #3 void(entity e, string m) setmodel
2636 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2637 NULL, // #5 void(entity e, vector min, vector max) setabssize
2638 VM_break, // #6 void() break
2639 VM_random, // #7 float() random
2640 PF_sound, // #8 void(entity e, float chan, string samp) sound
2641 VM_normalize, // #9 vector(vector v) normalize
2642 VM_error, // #10 void(string e) error
2643 VM_objerror, // #11 void(string e) objerror
2644 VM_vlen, // #12 float(vector v) vlen
2645 VM_vectoyaw, // #13 float(vector v) vectoyaw
2646 VM_spawn, // #14 entity() spawn
2647 VM_remove, // #15 void(entity e) remove
2648 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2649 PF_checkclient, // #17 entity() clientlist
2650 VM_find, // #18 entity(entity start, .string fld, string match) find
2651 PF_precache_sound, // #19 void(string s) precache_sound
2652 PF_precache_model, // #20 void(string s) precache_model
2653 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2654 PF_findradius, // #22 entity(vector org, float rad) findradius
2655 VM_bprint, // #23 void(string s) bprint
2656 PF_sprint, // #24 void(entity client, string s) sprint
2657 VM_dprint, // #25 void(string s) dprint
2658 VM_ftos, // #26 void(string s) ftos
2659 VM_vtos, // #27 void(string s) vtos
2660 VM_coredump, // #28 void() coredump
2661 VM_traceon, // #29 void() traceon
2662 VM_traceoff, // #30 void() traceoff
2663 VM_eprint, // #31 void(entity e) eprint
2664 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2666 PF_droptofloor, // #34 float() droptofloor
2667 PF_lightstyle, // #35 void(float style, string value) lightstyle
2668 VM_rint, // #36 float(float v) rint
2669 VM_floor, // #37 float(float v) floor
2670 VM_ceil, // #38 float(float v) ceil
2672 PF_checkbottom, // #40 float(entity e) checkbottom
2673 PF_pointcontents, // #41 float(vector v) pointcontents
2675 VM_fabs, // #43 float(float f) fabs
2676 PF_aim, // #44 vector(entity e, float speed) aim
2677 VM_cvar, // #45 float(string s) cvar
2678 VM_localcmd, // #46 void(string s) localcmd
2679 VM_nextent, // #47 entity(entity e) nextent
2680 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2681 PF_changeyaw, // #49 void() ChangeYaw
2683 VM_vectoangles, // #51 vector(vector v) vectoangles
2684 PF_WriteByte, // #52 void(float to, float f) WriteByte
2685 PF_WriteChar, // #53 void(float to, float f) WriteChar
2686 PF_WriteShort, // #54 void(float to, float f) WriteShort
2687 PF_WriteLong, // #55 void(float to, float f) WriteLong
2688 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2689 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2690 PF_WriteString, // #58 void(float to, string s) WriteString
2691 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2692 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2693 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2694 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2695 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2696 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2697 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2699 SV_MoveToGoal, // #67 void(float step) movetogoal
2700 PF_precache_file, // #68 string(string s) precache_file
2701 PF_makestatic, // #69 void(entity e) makestatic
2702 VM_changelevel, // #70 void(string s) changelevel
2704 VM_cvar_set, // #72 void(string var, string val) cvar_set
2705 PF_centerprint, // #73 void(entity client, strings) centerprint
2706 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2707 PF_precache_model, // #75 string(string s) precache_model2
2708 PF_precache_sound, // #76 string(string s) precache_sound2
2709 PF_precache_file, // #77 string(string s) precache_file2
2710 PF_setspawnparms, // #78 void(entity e) setspawnparms
2713 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2722 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2723 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2724 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2725 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2726 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2727 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2728 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2729 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2730 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2731 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2742 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2743 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2744 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2745 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2746 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2747 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2748 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2749 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2750 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2751 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2752 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2753 // FTEQW range #200-#299
2772 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2782 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2783 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2784 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2785 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2786 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2787 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2788 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2789 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2790 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2791 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2792 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2793 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2794 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2795 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2796 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2797 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2798 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2799 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2800 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2801 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2802 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2803 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2804 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2805 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2806 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2807 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2808 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2809 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2810 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2811 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2812 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2813 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2814 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2815 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2816 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2817 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2818 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2819 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2820 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2821 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2822 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2823 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2824 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2825 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2826 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2827 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2828 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2829 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2830 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2831 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2832 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2833 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2834 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2835 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2836 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2837 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2838 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2839 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2840 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2842 PF_edict_num, // #459 entity(float num) (??)
2843 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2844 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2845 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2846 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2847 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2848 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2849 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2850 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2851 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2852 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2853 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2854 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2855 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2856 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2857 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2858 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2863 e10, e10 // #480-499 (LordHavoc)
2866 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2868 void VM_SV_Cmd_Init(void)
2873 void VM_SV_Cmd_Reset(void)