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 "
70 "DP_QC_STRINGBUFFERS "
71 "DP_QC_STRINGCOLORFUNCTIONS "
72 "DP_QC_UNLIMITEDTEMPSTRINGS "
75 "DP_QC_TRACE_MOVETYPE_HITMODEL "
76 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
77 "DP_QC_VECTORVECTORS "
83 "DP_SND_DIRECTIONLESSATTNNONE "
92 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
93 "DP_SV_DRAWONLYTOCLIENT "
96 "DP_SV_ENTITYCONTENTSTRANSITION "
97 "DP_SV_NODRAWTOCLIENT "
99 "DP_SV_PLAYERPHYSICS "
100 "DP_SV_PRECACHEANYTIME "
103 "DP_SV_ROTATINGBMODEL "
106 "DP_SV_WRITEUNTERMINATEDSTRING "
110 "DP_TE_EXPLOSIONRGB "
112 "DP_TE_PARTICLECUBE "
113 "DP_TE_PARTICLERAIN "
114 "DP_TE_PARTICLESNOW "
116 "DP_TE_QUADEFFECTS1 "
119 "DP_TE_STANDARDEFFECTBUILTINS "
120 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
123 //"EXT_CSQC " // not ready yet
125 "KRIMZON_SV_PARSECLIENTCOMMAND "
129 "PRYDON_CLIENTCURSOR "
130 "TENEBRAE_GFX_DLIGHTS "
132 "NEXUIZ_PLAYERMODEL "
139 Writes new values for v_forward, v_up, and v_right based on angles
143 void PF_makevectors (void)
145 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
152 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.
154 setorigin (entity, origin)
157 void PF_setorigin (void)
162 e = PRVM_G_EDICT(OFS_PARM0);
163 if (e == prog->edicts)
165 VM_Warning("setorigin: can not modify world entity\n");
168 if (e->priv.server->free)
170 VM_Warning("setorigin: can not modify free entity\n");
173 org = PRVM_G_VECTOR(OFS_PARM1);
174 VectorCopy (org, e->fields.server->origin);
175 SV_LinkEdict (e, false);
179 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
183 for (i=0 ; i<3 ; i++)
185 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
187 // set derived values
188 VectorCopy (min, e->fields.server->mins);
189 VectorCopy (max, e->fields.server->maxs);
190 VectorSubtract (max, min, e->fields.server->size);
192 SV_LinkEdict (e, false);
199 the size box is rotated by the current angle
200 LordHavoc: no it isn't...
202 setsize (entity, minvector, maxvector)
205 void PF_setsize (void)
210 e = PRVM_G_EDICT(OFS_PARM0);
211 if (e == prog->edicts)
213 VM_Warning("setsize: can not modify world entity\n");
216 if (e->priv.server->free)
218 VM_Warning("setsize: can not modify free entity\n");
221 min = PRVM_G_VECTOR(OFS_PARM1);
222 max = PRVM_G_VECTOR(OFS_PARM2);
223 SetMinMaxSize (e, min, max, false);
231 setmodel(entity, model)
234 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
235 void PF_setmodel (void)
241 e = PRVM_G_EDICT(OFS_PARM0);
242 if (e == prog->edicts)
244 VM_Warning("setmodel: can not modify world entity\n");
247 if (e->priv.server->free)
249 VM_Warning("setmodel: can not modify free entity\n");
252 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
253 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
254 e->fields.server->modelindex = i;
260 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
261 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
263 SetMinMaxSize (e, quakemins, quakemaxs, true);
266 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
273 single print to a specific client
275 sprint(clientent, value)
278 void PF_sprint (void)
282 char string[VM_STRINGTEMP_LENGTH];
284 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
286 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
288 VM_Warning("tried to centerprint to a non-client\n");
292 client = svs.clients + entnum-1;
293 if (!client->netconnection)
296 VM_VarString(1, string, sizeof(string));
297 MSG_WriteChar(&client->netconnection->message,svc_print);
298 MSG_WriteString(&client->netconnection->message, string);
306 single print to a specific client
308 centerprint(clientent, value)
311 void PF_centerprint (void)
315 char string[VM_STRINGTEMP_LENGTH];
317 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
319 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
321 VM_Warning("tried to centerprint to a non-client\n");
325 client = svs.clients + entnum-1;
326 if (!client->netconnection)
329 VM_VarString(1, string, sizeof(string));
330 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
331 MSG_WriteString(&client->netconnection->message, string);
338 particle(origin, color, count)
341 void PF_particle (void)
347 org = PRVM_G_VECTOR(OFS_PARM0);
348 dir = PRVM_G_VECTOR(OFS_PARM1);
349 color = PRVM_G_FLOAT(OFS_PARM2);
350 count = PRVM_G_FLOAT(OFS_PARM3);
351 SV_StartParticle (org, dir, (int)color, (int)count);
361 void PF_ambientsound (void)
365 float vol, attenuation;
368 pos = PRVM_G_VECTOR (OFS_PARM0);
369 samp = PRVM_G_STRING(OFS_PARM1);
370 vol = PRVM_G_FLOAT(OFS_PARM2);
371 attenuation = PRVM_G_FLOAT(OFS_PARM3);
373 // check to see if samp was properly precached
374 soundnum = SV_SoundIndex(samp, 1);
382 // add an svc_spawnambient command to the level signon packet
385 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
387 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
389 MSG_WriteVector(&sv.signon, pos, sv.protocol);
392 MSG_WriteShort (&sv.signon, soundnum);
394 MSG_WriteByte (&sv.signon, soundnum);
396 MSG_WriteByte (&sv.signon, (int)(vol*255));
397 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
405 Each entity can have eight independant sound sources, like voice,
408 Channel 0 is an auto-allocate channel, the others override anything
409 already running on that entity/channel pair.
411 An attenuation of 0 will play full volume everywhere in the level.
412 Larger attenuations will drop off.
420 prvm_edict_t *entity;
424 entity = PRVM_G_EDICT(OFS_PARM0);
425 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
426 sample = PRVM_G_STRING(OFS_PARM2);
427 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
428 attenuation = PRVM_G_FLOAT(OFS_PARM4);
430 if (volume < 0 || volume > 255)
432 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
436 if (attenuation < 0 || attenuation > 4)
438 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
442 if (channel < 0 || channel > 7)
444 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
448 SV_StartSound (entity, channel, sample, volume, attenuation);
455 Used for use tracing and shot targeting
456 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
457 if the tryents flag is set.
459 traceline (vector1, vector2, tryents)
462 void PF_traceline (void)
470 prog->xfunction->builtinsprofile += 30;
472 v1 = PRVM_G_VECTOR(OFS_PARM0);
473 v2 = PRVM_G_VECTOR(OFS_PARM1);
474 move = (int)PRVM_G_FLOAT(OFS_PARM2);
475 ent = PRVM_G_EDICT(OFS_PARM3);
477 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]))
478 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));
480 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
482 prog->globals.server->trace_allsolid = trace.allsolid;
483 prog->globals.server->trace_startsolid = trace.startsolid;
484 prog->globals.server->trace_fraction = trace.fraction;
485 prog->globals.server->trace_inwater = trace.inwater;
486 prog->globals.server->trace_inopen = trace.inopen;
487 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
488 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
489 prog->globals.server->trace_plane_dist = trace.plane.dist;
491 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
493 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
494 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
495 val->_float = trace.startsupercontents;
496 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
497 val->_float = trace.hitsupercontents;
498 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
499 val->_float = trace.hitq3surfaceflags;
500 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
502 if (trace.hittexture)
503 val->string = PRVM_SetTempString(trace.hittexture->name);
514 Used for use tracing and shot targeting
515 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
516 if the tryents flag is set.
518 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
521 // LordHavoc: added this for my own use, VERY useful, similar to traceline
522 void PF_tracebox (void)
524 float *v1, *v2, *m1, *m2;
530 prog->xfunction->builtinsprofile += 30;
532 v1 = PRVM_G_VECTOR(OFS_PARM0);
533 m1 = PRVM_G_VECTOR(OFS_PARM1);
534 m2 = PRVM_G_VECTOR(OFS_PARM2);
535 v2 = PRVM_G_VECTOR(OFS_PARM3);
536 move = (int)PRVM_G_FLOAT(OFS_PARM4);
537 ent = PRVM_G_EDICT(OFS_PARM5);
539 if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
540 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
542 trace = SV_Move (v1, m1, m2, v2, move, ent);
544 prog->globals.server->trace_allsolid = trace.allsolid;
545 prog->globals.server->trace_startsolid = trace.startsolid;
546 prog->globals.server->trace_fraction = trace.fraction;
547 prog->globals.server->trace_inwater = trace.inwater;
548 prog->globals.server->trace_inopen = trace.inopen;
549 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
550 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
551 prog->globals.server->trace_plane_dist = trace.plane.dist;
553 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
555 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
556 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
557 val->_float = trace.startsupercontents;
558 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
559 val->_float = trace.hitsupercontents;
560 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
561 val->_float = trace.hitq3surfaceflags;
562 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
564 if (trace.hittexture)
565 val->string = PRVM_SetTempString(trace.hittexture->name);
571 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
572 void PF_tracetoss (void)
576 prvm_edict_t *ignore;
579 prog->xfunction->builtinsprofile += 600;
581 ent = PRVM_G_EDICT(OFS_PARM0);
582 if (ent == prog->edicts)
584 VM_Warning("tracetoss: can not use world entity\n");
587 ignore = PRVM_G_EDICT(OFS_PARM1);
589 trace = SV_Trace_Toss (ent, ignore);
591 prog->globals.server->trace_allsolid = trace.allsolid;
592 prog->globals.server->trace_startsolid = trace.startsolid;
593 prog->globals.server->trace_fraction = trace.fraction;
594 prog->globals.server->trace_inwater = trace.inwater;
595 prog->globals.server->trace_inopen = trace.inopen;
596 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
597 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
598 prog->globals.server->trace_plane_dist = trace.plane.dist;
600 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
602 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
603 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
604 val->_float = trace.startsupercontents;
605 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
606 val->_float = trace.hitsupercontents;
607 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
608 val->_float = trace.hitq3surfaceflags;
609 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
611 if (trace.hittexture)
612 val->string = PRVM_SetTempString(trace.hittexture->name);
623 Returns true if the given entity can move to the given position from it's
624 current position by walking or rolling.
626 scalar checkpos (entity, vector)
629 void PF_checkpos (void)
633 //============================================================================
636 unsigned char checkpvs[MAX_MAP_LEAFS/8];
638 int PF_newcheckclient (int check)
644 // cycle to the next one
646 check = bound(1, check, svs.maxclients);
647 if (check == svs.maxclients)
655 prog->xfunction->builtinsprofile++;
657 if (i == svs.maxclients+1)
659 // look up the client's edict
660 ent = PRVM_EDICT_NUM(i);
661 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
662 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
664 // found a valid client (possibly the same one again)
668 // get the PVS for the entity
669 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
671 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
672 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
681 Returns a client (or object that has a client enemy) that would be a
684 If there is more than one valid option, they are cycled each frame
686 If (self.origin + self.viewofs) is not in the PVS of the current target,
687 it is not returned at all.
692 int c_invis, c_notvis;
693 void PF_checkclient (void)
695 prvm_edict_t *ent, *self;
698 // find a new check if on a new frame
699 if (sv.time - sv.lastchecktime >= 0.1)
701 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
702 sv.lastchecktime = sv.time;
705 // return check if it might be visible
706 ent = PRVM_EDICT_NUM(sv.lastcheck);
707 if (ent->priv.server->free || ent->fields.server->health <= 0)
709 VM_RETURN_EDICT(prog->edicts);
713 // if current entity can't possibly see the check entity, return 0
714 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
715 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
716 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
719 VM_RETURN_EDICT(prog->edicts);
723 // might be able to see it
725 VM_RETURN_EDICT(ent);
728 //============================================================================
735 Sends text over to the client's execution buffer
737 stuffcmd (clientent, value, ...)
740 void PF_stuffcmd (void)
744 char string[VM_STRINGTEMP_LENGTH];
746 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
747 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
749 VM_Warning("Can't stuffcmd to a non-client\n");
753 VM_VarString(1, string, sizeof(string));
756 host_client = svs.clients + entnum-1;
757 Host_ClientCommands ("%s", string);
765 Returns a chain of entities that have origins within a spherical area
767 findradius (origin, radius)
770 void PF_findradius (void)
772 prvm_edict_t *ent, *chain;
773 vec_t radius, radius2;
774 vec3_t org, eorg, mins, maxs;
777 prvm_edict_t *touchedicts[MAX_EDICTS];
779 chain = (prvm_edict_t *)prog->edicts;
781 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
782 radius = PRVM_G_FLOAT(OFS_PARM1);
783 radius2 = radius * radius;
785 mins[0] = org[0] - (radius + 1);
786 mins[1] = org[1] - (radius + 1);
787 mins[2] = org[2] - (radius + 1);
788 maxs[0] = org[0] + (radius + 1);
789 maxs[1] = org[1] + (radius + 1);
790 maxs[2] = org[2] + (radius + 1);
791 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
792 if (numtouchedicts > MAX_EDICTS)
794 // this never happens
795 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
796 numtouchedicts = MAX_EDICTS;
798 for (i = 0;i < numtouchedicts;i++)
800 ent = touchedicts[i];
801 prog->xfunction->builtinsprofile++;
802 // Quake did not return non-solid entities but darkplaces does
803 // (note: this is the reason you can't blow up fallen zombies)
804 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
806 // LordHavoc: compare against bounding box rather than center so it
807 // doesn't miss large objects, and use DotProduct instead of Length
808 // for a major speedup
809 VectorSubtract(org, ent->fields.server->origin, eorg);
810 if (sv_gameplayfix_findradiusdistancetobox.integer)
812 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
813 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
814 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
817 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
818 if (DotProduct(eorg, eorg) < radius2)
820 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
825 VM_RETURN_EDICT(chain);
828 void PF_precache_file (void)
829 { // precache_file is only used to copy files with qcc, it does nothing
830 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
834 void PF_precache_sound (void)
836 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
837 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
840 void PF_precache_model (void)
842 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
843 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
850 float(float yaw, float dist) walkmove
853 void PF_walkmove (void)
861 // assume failure if it returns early
862 PRVM_G_FLOAT(OFS_RETURN) = 0;
864 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
865 if (ent == prog->edicts)
867 VM_Warning("walkmove: can not modify world entity\n");
870 if (ent->priv.server->free)
872 VM_Warning("walkmove: can not modify free entity\n");
875 yaw = PRVM_G_FLOAT(OFS_PARM0);
876 dist = PRVM_G_FLOAT(OFS_PARM1);
878 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
881 yaw = yaw*M_PI*2 / 360;
883 move[0] = cos(yaw)*dist;
884 move[1] = sin(yaw)*dist;
887 // save program state, because SV_movestep may call other progs
888 oldf = prog->xfunction;
889 oldself = prog->globals.server->self;
891 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
894 // restore program state
895 prog->xfunction = oldf;
896 prog->globals.server->self = oldself;
906 void PF_droptofloor (void)
912 // assume failure if it returns early
913 PRVM_G_FLOAT(OFS_RETURN) = 0;
915 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
916 if (ent == prog->edicts)
918 VM_Warning("droptofloor: can not modify world entity\n");
921 if (ent->priv.server->free)
923 VM_Warning("droptofloor: can not modify free entity\n");
927 VectorCopy (ent->fields.server->origin, end);
930 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
932 if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
934 if (trace.fraction < 1)
935 VectorCopy (trace.endpos, ent->fields.server->origin);
936 SV_LinkEdict (ent, false);
937 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
938 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
939 PRVM_G_FLOAT(OFS_RETURN) = 1;
940 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
941 ent->priv.server->suspendedinairflag = true;
949 void(float style, string value) lightstyle
952 void PF_lightstyle (void)
959 style = (int)PRVM_G_FLOAT(OFS_PARM0);
960 val = PRVM_G_STRING(OFS_PARM1);
962 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
963 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
966 // change the string in sv
967 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
969 // send message to all clients on this server
970 if (sv.state != ss_active)
973 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
975 if (client->active && client->netconnection)
977 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
978 MSG_WriteChar (&client->netconnection->message,style);
979 MSG_WriteString (&client->netconnection->message, val);
989 void PF_checkbottom (void)
991 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
999 void PF_pointcontents (void)
1001 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1008 Pick a vector for the player to shoot along
1009 vector aim(entity, missilespeed)
1014 prvm_edict_t *ent, *check, *bestent;
1015 vec3_t start, dir, end, bestdir;
1018 float dist, bestdist;
1021 // assume failure if it returns early
1022 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1023 // if sv_aim is so high it can't possibly accept anything, skip out early
1024 if (sv_aim.value >= 1)
1027 ent = PRVM_G_EDICT(OFS_PARM0);
1028 if (ent == prog->edicts)
1030 VM_Warning("aim: can not use world entity\n");
1033 if (ent->priv.server->free)
1035 VM_Warning("aim: can not use free entity\n");
1038 speed = PRVM_G_FLOAT(OFS_PARM1);
1040 VectorCopy (ent->fields.server->origin, start);
1043 // try sending a trace straight
1044 VectorCopy (prog->globals.server->v_forward, dir);
1045 VectorMA (start, 2048, dir, end);
1046 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1047 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1048 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1050 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1055 // try all possible entities
1056 VectorCopy (dir, bestdir);
1057 bestdist = sv_aim.value;
1060 check = PRVM_NEXT_EDICT(prog->edicts);
1061 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1063 prog->xfunction->builtinsprofile++;
1064 if (check->fields.server->takedamage != DAMAGE_AIM)
1068 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1069 continue; // don't aim at teammate
1070 for (j=0 ; j<3 ; j++)
1071 end[j] = check->fields.server->origin[j]
1072 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1073 VectorSubtract (end, start, dir);
1074 VectorNormalize (dir);
1075 dist = DotProduct (dir, prog->globals.server->v_forward);
1076 if (dist < bestdist)
1077 continue; // to far to turn
1078 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1079 if (tr.ent == check)
1080 { // can shoot at this one
1088 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1089 dist = DotProduct (dir, prog->globals.server->v_forward);
1090 VectorScale (prog->globals.server->v_forward, dist, end);
1092 VectorNormalize (end);
1093 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1097 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1105 This was a major timewaster in progs, so it was converted to C
1108 void PF_changeyaw (void)
1111 float ideal, current, move, speed;
1113 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1114 if (ent == prog->edicts)
1116 VM_Warning("changeyaw: can not modify world entity\n");
1119 if (ent->priv.server->free)
1121 VM_Warning("changeyaw: can not modify free entity\n");
1124 current = ANGLEMOD(ent->fields.server->angles[1]);
1125 ideal = ent->fields.server->ideal_yaw;
1126 speed = ent->fields.server->yaw_speed;
1128 if (current == ideal)
1130 move = ideal - current;
1131 if (ideal > current)
1152 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1160 void PF_changepitch (void)
1163 float ideal, current, move, speed;
1166 ent = PRVM_G_EDICT(OFS_PARM0);
1167 if (ent == prog->edicts)
1169 VM_Warning("changepitch: can not modify world entity\n");
1172 if (ent->priv.server->free)
1174 VM_Warning("changepitch: can not modify free entity\n");
1177 current = ANGLEMOD( ent->fields.server->angles[0] );
1178 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1179 ideal = val->_float;
1182 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1185 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1186 speed = val->_float;
1189 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1193 if (current == ideal)
1195 move = ideal - current;
1196 if (ideal > current)
1217 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1221 ===============================================================================
1225 ===============================================================================
1228 #define MSG_BROADCAST 0 // unreliable to all
1229 #define MSG_ONE 1 // reliable to one (msg_entity)
1230 #define MSG_ALL 2 // reliable to all
1231 #define MSG_INIT 3 // write to the init string
1232 #define MSG_ENTITY 5
1234 sizebuf_t *WriteDest (void)
1239 extern sizebuf_t *sv2csqcbuf;
1241 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1245 return &sv.datagram;
1248 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1249 entnum = PRVM_NUM_FOR_EDICT(ent);
1250 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1252 VM_Warning ("WriteDest: tried to write to non-client\n");
1253 return &sv.reliable_datagram;
1256 return &svs.clients[entnum-1].netconnection->message;
1259 VM_Warning ("WriteDest: bad destination\n");
1261 return &sv.reliable_datagram;
1273 void PF_WriteByte (void)
1275 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1278 void PF_WriteChar (void)
1280 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1283 void PF_WriteShort (void)
1285 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1288 void PF_WriteLong (void)
1290 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1293 void PF_WriteAngle (void)
1295 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1298 void PF_WriteCoord (void)
1300 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1303 void PF_WriteString (void)
1305 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1308 void PF_WriteUnterminatedString (void)
1310 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1314 void PF_WriteEntity (void)
1316 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1319 //////////////////////////////////////////////////////////
1321 void PF_makestatic (void)
1326 ent = PRVM_G_EDICT(OFS_PARM0);
1327 if (ent == prog->edicts)
1329 VM_Warning("makestatic: can not modify world entity\n");
1332 if (ent->priv.server->free)
1334 VM_Warning("makestatic: can not modify free entity\n");
1339 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1344 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1345 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1346 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1350 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1351 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1352 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1355 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1356 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1357 for (i=0 ; i<3 ; i++)
1359 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1360 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1363 // throw the entity away now
1367 //=============================================================================
1374 void PF_setspawnparms (void)
1380 ent = PRVM_G_EDICT(OFS_PARM0);
1381 i = PRVM_NUM_FOR_EDICT(ent);
1382 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1384 Con_Print("tried to setspawnparms on a non-client\n");
1388 // copy spawn parms out of the client_t
1389 client = svs.clients + i-1;
1390 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1391 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1398 Returns a color vector indicating the lighting at the requested point.
1400 (Internal Operation note: actually measures the light beneath the point, just like
1401 the model lighting on the client)
1406 void PF_getlight (void)
1408 vec3_t ambientcolor, diffusecolor, diffusenormal;
1410 p = PRVM_G_VECTOR(OFS_PARM0);
1411 VectorClear(ambientcolor);
1412 VectorClear(diffusecolor);
1413 VectorClear(diffusenormal);
1414 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1415 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1416 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1419 void PF_registercvar (void)
1421 const char *name, *value;
1422 name = PRVM_G_STRING(OFS_PARM0);
1423 value = PRVM_G_STRING(OFS_PARM1);
1424 PRVM_G_FLOAT(OFS_RETURN) = 0;
1426 // first check to see if it has already been defined
1427 if (Cvar_FindVar (name))
1430 // check for overlap with a command
1431 if (Cmd_Exists (name))
1433 VM_Warning("PF_registercvar: %s is a command\n", name);
1437 Cvar_Get(name, value, 0);
1439 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1444 unsigned char type; // 1/2/8 or other value if isn't used
1448 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1449 static int vm_autosentstats_last;
1451 void VM_AutoSentStats_Clear (void)
1453 if(vm_autosentstats)
1455 Z_Free(vm_autosentstats);
1456 vm_autosentstats = NULL;
1457 vm_autosentstats_last = -1;
1461 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1462 #define VM_SENDSTAT(a,b,c)\
1465 if((c)==(unsigned char)(c))\
1467 MSG_WriteByte((a), svc_updatestatubyte);\
1468 MSG_WriteByte((a), (b));\
1469 MSG_WriteByte((a), (c));\
1473 MSG_WriteByte((a), svc_updatestat);\
1474 MSG_WriteByte((a), (b));\
1475 MSG_WriteLong((a), (c));\
1479 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1491 if(!vm_autosentstats)
1494 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);
1496 for(i=0; i<vm_autosentstats_last+1 ;i++)
1498 if(!vm_autosentstats[i].type)
1500 switch(vm_autosentstats[i].type)
1504 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1512 stats[i+32] = si[0];
1513 stats[i+33] = si[1];
1514 stats[i+34] = si[2];
1515 stats[i+35] = si[3];
1519 VM_SENDSTAT(msg, i+32, si[0]);
1520 VM_SENDSTAT(msg, i+33, si[1]);
1521 VM_SENDSTAT(msg, i+34, si[2]);
1522 VM_SENDSTAT(msg, i+35, si[3]);
1528 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1529 k.i = LittleLong (k.i);
1533 VM_SENDSTAT(msg, i+32, k.i);
1537 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1541 VM_SENDSTAT(msg, i+32, v);
1549 // void(float index, float type, .void field) SV_AddStat = #470;
1550 // Set up an auto-sent player stat.
1551 // Client's get thier own fields sent to them. Index may not be less than 32.
1552 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1553 // 1: string (4 stats carrying a total of 16 charactures)
1554 // 2: float (one stat, float converted to an integer for transportation)
1555 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1556 void PF_SV_AddStat (void)
1561 if(!vm_autosentstats)
1563 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1564 if(!vm_autosentstats)
1566 VM_Warning("PF_SV_AddStat: not enough memory\n");
1570 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1571 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1572 off = PRVM_G_INT (OFS_PARM2);
1577 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1580 if(i >= (MAX_CL_STATS-32))
1582 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1585 if(i > (MAX_CL_STATS-32-4) && type == 1)
1587 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1590 vm_autosentstats[i].type = type;
1591 vm_autosentstats[i].fieldoffset = off;
1592 if(vm_autosentstats_last < i)
1593 vm_autosentstats_last = i;
1600 copies data from one entity to another
1602 copyentity(src, dst)
1605 void PF_copyentity (void)
1607 prvm_edict_t *in, *out;
1608 in = PRVM_G_EDICT(OFS_PARM0);
1609 if (in == prog->edicts)
1611 VM_Warning("copyentity: can not read world entity\n");
1614 if (in->priv.server->free)
1616 VM_Warning("copyentity: can not read free entity\n");
1619 out = PRVM_G_EDICT(OFS_PARM1);
1620 if (out == prog->edicts)
1622 VM_Warning("copyentity: can not modify world entity\n");
1625 if (out->priv.server->free)
1627 VM_Warning("copyentity: can not modify free entity\n");
1630 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1638 sets the color of a client and broadcasts the update to all connected clients
1640 setcolor(clientent, value)
1643 void PF_setcolor (void)
1649 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1650 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1652 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1654 Con_Print("tried to setcolor a non-client\n");
1658 client = svs.clients + entnum-1;
1661 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1663 client->edict->fields.server->team = (i & 15) + 1;
1666 if (client->old_colors != client->colors)
1668 client->old_colors = client->colors;
1669 // send notification to all clients
1670 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1671 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1672 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1680 effect(origin, modelname, startframe, framecount, framerate)
1683 void PF_effect (void)
1687 s = PRVM_G_STRING(OFS_PARM1);
1690 VM_Warning("effect: no model specified\n");
1694 i = SV_ModelIndex(s, 1);
1697 VM_Warning("effect: model not precached\n");
1701 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1703 VM_Warning("effect: framecount < 1\n");
1707 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1709 VM_Warning("effect: framerate < 1\n");
1713 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));
1716 void PF_te_blood (void)
1718 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1720 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1721 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1725 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1727 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1728 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1729 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1731 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1734 void PF_te_bloodshower (void)
1736 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1738 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1739 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1743 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1747 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1749 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1751 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1754 void PF_te_explosionrgb (void)
1756 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1757 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1761 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1763 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1764 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1765 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1768 void PF_te_particlecube (void)
1770 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1772 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1773 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1777 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1781 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1785 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1787 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1789 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1790 // gravity true/false
1791 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1793 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1796 void PF_te_particlerain (void)
1798 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1800 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1801 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1805 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1809 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1813 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1815 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1817 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1820 void PF_te_particlesnow (void)
1822 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1824 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1825 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1829 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1833 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1837 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1839 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1841 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1844 void PF_te_spark (void)
1846 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1848 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1849 MSG_WriteByte(&sv.datagram, TE_SPARK);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1853 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1855 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1856 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1857 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1859 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1862 void PF_te_gunshotquad (void)
1864 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1865 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1869 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1872 void PF_te_spikequad (void)
1874 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1875 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1879 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1882 void PF_te_superspikequad (void)
1884 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1885 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1889 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1892 void PF_te_explosionquad (void)
1894 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1895 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1899 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1902 void PF_te_smallflash (void)
1904 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1905 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1909 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1912 void PF_te_customflash (void)
1914 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1916 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1917 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1921 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1923 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1925 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1927 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1928 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1929 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1932 void PF_te_gunshot (void)
1934 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1935 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1939 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1942 void PF_te_spike (void)
1944 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1945 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1949 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1952 void PF_te_superspike (void)
1954 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1955 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1959 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1962 void PF_te_explosion (void)
1964 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1965 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1969 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1972 void PF_te_tarexplosion (void)
1974 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1975 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1979 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982 void PF_te_wizspike (void)
1984 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1985 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1989 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1992 void PF_te_knightspike (void)
1994 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1995 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1999 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2002 void PF_te_lavasplash (void)
2004 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2005 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2009 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2012 void PF_te_teleport (void)
2014 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2015 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2019 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022 void PF_te_explosion2 (void)
2024 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2025 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2029 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2031 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2032 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2035 void PF_te_lightning1 (void)
2037 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2038 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2040 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2044 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2048 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2051 void PF_te_lightning2 (void)
2053 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2054 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2056 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2060 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2064 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2067 void PF_te_lightning3 (void)
2069 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2072 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2076 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2080 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2083 void PF_te_beam (void)
2085 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2086 MSG_WriteByte(&sv.datagram, TE_BEAM);
2088 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2092 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2096 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2099 void PF_te_plasmaburn (void)
2101 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2102 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2105 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108 void PF_te_flamejet (void)
2110 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2111 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2115 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2119 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2121 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2124 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2127 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2129 bestdist = 1000000000;
2131 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2133 // clip original point to each triangle of the surface and find the
2134 // triangle that is closest
2135 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2136 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2137 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2138 TriangleNormal(v[0], v[1], v[2], facenormal);
2139 VectorNormalize(facenormal);
2140 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2141 VectorMA(p, offsetdist, facenormal, temp);
2142 for (j = 0, k = 2;j < 3;k = j, j++)
2144 VectorSubtract(v[k], v[j], edgenormal);
2145 CrossProduct(edgenormal, facenormal, sidenormal);
2146 VectorNormalize(sidenormal);
2147 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2149 VectorMA(temp, offsetdist, sidenormal, temp);
2151 dist = VectorDistance2(temp, p);
2152 if (bestdist > dist)
2155 VectorCopy(temp, out);
2160 static model_t *getmodel(prvm_edict_t *ed)
2163 if (!ed || ed->priv.server->free)
2165 modelindex = (int)ed->fields.server->modelindex;
2166 if (modelindex < 1 || modelindex >= MAX_MODELS)
2168 return sv.models[modelindex];
2171 static msurface_t *getsurface(model_t *model, int surfacenum)
2173 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2175 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2179 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2180 void PF_getsurfacenumpoints(void)
2183 msurface_t *surface;
2184 // return 0 if no such surface
2185 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2187 PRVM_G_FLOAT(OFS_RETURN) = 0;
2191 // note: this (incorrectly) assumes it is a simple polygon
2192 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2194 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2195 void PF_getsurfacepoint(void)
2199 msurface_t *surface;
2201 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2202 ed = PRVM_G_EDICT(OFS_PARM0);
2203 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2205 // note: this (incorrectly) assumes it is a simple polygon
2206 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2207 if (pointnum < 0 || pointnum >= surface->num_vertices)
2209 // FIXME: implement rotation/scaling
2210 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2212 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2213 void PF_getsurfacenormal(void)
2216 msurface_t *surface;
2218 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2219 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2221 // FIXME: implement rotation/scaling
2222 // note: this (incorrectly) assumes it is a simple polygon
2223 // note: this only returns the first triangle, so it doesn't work very
2224 // well for curved surfaces or arbitrary meshes
2225 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);
2226 VectorNormalize(normal);
2227 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2229 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2230 void PF_getsurfacetexture(void)
2233 msurface_t *surface;
2234 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2235 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2237 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2239 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2240 void PF_getsurfacenearpoint(void)
2242 int surfacenum, best;
2244 vec_t dist, bestdist;
2247 msurface_t *surface;
2249 PRVM_G_FLOAT(OFS_RETURN) = -1;
2250 ed = PRVM_G_EDICT(OFS_PARM0);
2251 point = PRVM_G_VECTOR(OFS_PARM1);
2253 if (!ed || ed->priv.server->free)
2255 model = getmodel(ed);
2256 if (!model || !model->num_surfaces)
2259 // FIXME: implement rotation/scaling
2260 VectorSubtract(point, ed->fields.server->origin, p);
2262 bestdist = 1000000000;
2263 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2265 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2266 // first see if the nearest point on the surface's box is closer than the previous match
2267 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2268 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2269 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2270 dist = VectorLength2(clipped);
2271 if (dist < bestdist)
2273 // it is, check the nearest point on the actual geometry
2274 clippointtosurface(model, surface, p, clipped);
2275 VectorSubtract(clipped, p, clipped);
2276 dist += VectorLength2(clipped);
2277 if (dist < bestdist)
2279 // that's closer too, store it as the best match
2285 PRVM_G_FLOAT(OFS_RETURN) = best;
2287 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2288 void PF_getsurfaceclippedpoint(void)
2292 msurface_t *surface;
2294 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2295 ed = PRVM_G_EDICT(OFS_PARM0);
2296 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2298 // FIXME: implement rotation/scaling
2299 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2300 clippointtosurface(model, surface, p, out);
2301 // FIXME: implement rotation/scaling
2302 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2305 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2306 //this function originally written by KrimZon, made shorter by LordHavoc
2307 void PF_clientcommand (void)
2309 client_t *temp_client;
2312 //find client for this entity
2313 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2314 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2316 Con_Print("PF_clientcommand: entity is not a client\n");
2320 temp_client = host_client;
2321 host_client = svs.clients + i;
2322 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2323 host_client = temp_client;
2326 //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)
2327 void PF_setattachment (void)
2329 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2330 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2331 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2336 if (e == prog->edicts)
2338 VM_Warning("setattachment: can not modify world entity\n");
2341 if (e->priv.server->free)
2343 VM_Warning("setattachment: can not modify free entity\n");
2347 if (tagentity == NULL)
2348 tagentity = prog->edicts;
2350 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2352 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2354 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2357 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2359 modelindex = (int)tagentity->fields.server->modelindex;
2360 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2362 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2364 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);
2367 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));
2371 /////////////////////////////////////////
2372 // DP_MD3_TAGINFO extension coded by VorteX
2374 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2379 i = (int)e->fields.server->modelindex;
2380 if (i < 1 || i >= MAX_MODELS)
2382 model = sv.models[i];
2384 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2387 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2389 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2393 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);
2395 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);
2398 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2404 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2405 && (model = sv.models[(int)ent->fields.server->modelindex])
2406 && model->animscenes)
2408 // if model has wrong frame, engine automatically switches to model first frame
2409 frame = (int)ent->fields.server->frame;
2410 if (frame < 0 || frame >= model->numframes)
2412 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2414 *out = identitymatrix;
2418 // Warnings/errors code:
2419 // 0 - normal (everything all-right)
2422 // 3 - null or non-precached model
2423 // 4 - no tags with requested index
2424 // 5 - runaway loop at attachment chain
2425 extern cvar_t cl_bob;
2426 extern cvar_t cl_bobcycle;
2427 extern cvar_t cl_bobup;
2428 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2432 int modelindex, attachloop;
2433 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2436 *out = identitymatrix; // warnings and errors return identical matrix
2438 if (ent == prog->edicts)
2440 if (ent->priv.server->free)
2443 modelindex = (int)ent->fields.server->modelindex;
2444 if (modelindex <= 0 || modelindex > MAX_MODELS)
2447 model = sv.models[modelindex];
2449 tagmatrix = identitymatrix;
2450 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2454 if (attachloop >= 256) // prevent runaway looping
2456 // apply transformation by child's tagindex on parent entity and then
2457 // by parent entity itself
2458 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2459 if (ret && attachloop == 0)
2461 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2462 SV_GetEntityMatrix(ent, &entitymatrix, false);
2463 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2464 // next iteration we process the parent entity
2465 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2467 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2468 ent = PRVM_EDICT_NUM(val->edict);
2475 // RENDER_VIEWMODEL magic
2476 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2478 Matrix4x4_Copy(&tagmatrix, out);
2479 ent = PRVM_EDICT_NUM(val->edict);
2481 SV_GetEntityMatrix(ent, &entitymatrix, true);
2482 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2485 // Cl_bob, ported from rendering code
2486 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2489 // LordHavoc: this code is *weird*, but not replacable (I think it
2490 // should be done in QC on the server, but oh well, quake is quake)
2491 // LordHavoc: figured out bobup: the time at which the sin is at 180
2492 // degrees (which allows lengthening or squishing the peak or valley)
2493 cycle = sv.time/cl_bobcycle.value;
2494 cycle -= (int)cycle;
2495 if (cycle < cl_bobup.value)
2496 cycle = sin(M_PI * cycle / cl_bobup.value);
2498 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2499 // bob is proportional to velocity in the xy plane
2500 // (don't count Z, or jumping messes it up)
2501 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;
2502 bob = bob*0.3 + bob*0.7*cycle;
2503 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2510 //float(entity ent, string tagname) gettagindex;
2512 void PF_gettagindex (void)
2514 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2515 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2516 int modelindex, tag_index;
2518 if (ent == prog->edicts)
2520 VM_Warning("gettagindex: can't affect world entity\n");
2523 if (ent->priv.server->free)
2525 VM_Warning("gettagindex: can't affect free entity\n");
2529 modelindex = (int)ent->fields.server->modelindex;
2531 if (modelindex <= 0 || modelindex > MAX_MODELS)
2532 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2535 tag_index = SV_GetTagIndex(ent, tag_name);
2537 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2539 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2542 //vector(entity ent, float tagindex) gettaginfo;
2543 void PF_gettaginfo (void)
2545 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2546 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2547 matrix4x4_t tag_matrix;
2550 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2551 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2556 VM_Warning("gettagindex: can't affect world entity\n");
2559 VM_Warning("gettagindex: can't affect free entity\n");
2562 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2565 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2568 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2573 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2574 void PF_dropclient (void)
2577 client_t *oldhostclient;
2578 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2579 if (clientnum < 0 || clientnum >= svs.maxclients)
2581 VM_Warning("dropclient: not a client\n");
2584 if (!svs.clients[clientnum].active)
2586 VM_Warning("dropclient: that client slot is not connected\n");
2589 oldhostclient = host_client;
2590 host_client = svs.clients + clientnum;
2591 SV_DropClient(false);
2592 host_client = oldhostclient;
2595 //entity() spawnclient (DP_SV_BOTCLIENT)
2596 void PF_spawnclient (void)
2600 prog->xfunction->builtinsprofile += 2;
2602 for (i = 0;i < svs.maxclients;i++)
2604 if (!svs.clients[i].active)
2606 prog->xfunction->builtinsprofile += 100;
2607 SV_ConnectClient (i, NULL);
2608 // this has to be set or else ClientDisconnect won't be called
2609 // we assume the qc will call ClientConnect...
2610 svs.clients[i].clientconnectcalled = true;
2611 ed = PRVM_EDICT_NUM(i + 1);
2615 VM_RETURN_EDICT(ed);
2618 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2619 void PF_clienttype (void)
2622 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2623 if (clientnum < 0 || clientnum >= svs.maxclients)
2624 PRVM_G_FLOAT(OFS_RETURN) = 3;
2625 else if (!svs.clients[clientnum].active)
2626 PRVM_G_FLOAT(OFS_RETURN) = 0;
2627 else if (svs.clients[clientnum].netconnection)
2628 PRVM_G_FLOAT(OFS_RETURN) = 1;
2630 PRVM_G_FLOAT(OFS_RETURN) = 2;
2633 void PF_edict_num (void)
2635 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2638 prvm_builtin_t vm_sv_builtins[] = {
2640 PF_makevectors, // #1 void(vector ang) makevectors
2641 PF_setorigin, // #2 void(entity e, vector o) setorigin
2642 PF_setmodel, // #3 void(entity e, string m) setmodel
2643 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2644 NULL, // #5 void(entity e, vector min, vector max) setabssize
2645 VM_break, // #6 void() break
2646 VM_random, // #7 float() random
2647 PF_sound, // #8 void(entity e, float chan, string samp) sound
2648 VM_normalize, // #9 vector(vector v) normalize
2649 VM_error, // #10 void(string e) error
2650 VM_objerror, // #11 void(string e) objerror
2651 VM_vlen, // #12 float(vector v) vlen
2652 VM_vectoyaw, // #13 float(vector v) vectoyaw
2653 VM_spawn, // #14 entity() spawn
2654 VM_remove, // #15 void(entity e) remove
2655 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2656 PF_checkclient, // #17 entity() clientlist
2657 VM_find, // #18 entity(entity start, .string fld, string match) find
2658 PF_precache_sound, // #19 void(string s) precache_sound
2659 PF_precache_model, // #20 void(string s) precache_model
2660 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2661 PF_findradius, // #22 entity(vector org, float rad) findradius
2662 VM_bprint, // #23 void(string s) bprint
2663 PF_sprint, // #24 void(entity client, string s) sprint
2664 VM_dprint, // #25 void(string s) dprint
2665 VM_ftos, // #26 void(string s) ftos
2666 VM_vtos, // #27 void(string s) vtos
2667 VM_coredump, // #28 void() coredump
2668 VM_traceon, // #29 void() traceon
2669 VM_traceoff, // #30 void() traceoff
2670 VM_eprint, // #31 void(entity e) eprint
2671 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2673 PF_droptofloor, // #34 float() droptofloor
2674 PF_lightstyle, // #35 void(float style, string value) lightstyle
2675 VM_rint, // #36 float(float v) rint
2676 VM_floor, // #37 float(float v) floor
2677 VM_ceil, // #38 float(float v) ceil
2679 PF_checkbottom, // #40 float(entity e) checkbottom
2680 PF_pointcontents, // #41 float(vector v) pointcontents
2682 VM_fabs, // #43 float(float f) fabs
2683 PF_aim, // #44 vector(entity e, float speed) aim
2684 VM_cvar, // #45 float(string s) cvar
2685 VM_localcmd, // #46 void(string s) localcmd
2686 VM_nextent, // #47 entity(entity e) nextent
2687 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2688 PF_changeyaw, // #49 void() ChangeYaw
2690 VM_vectoangles, // #51 vector(vector v) vectoangles
2691 PF_WriteByte, // #52 void(float to, float f) WriteByte
2692 PF_WriteChar, // #53 void(float to, float f) WriteChar
2693 PF_WriteShort, // #54 void(float to, float f) WriteShort
2694 PF_WriteLong, // #55 void(float to, float f) WriteLong
2695 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2696 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2697 PF_WriteString, // #58 void(float to, string s) WriteString
2698 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2699 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2700 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2701 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2702 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2703 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2704 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2706 SV_MoveToGoal, // #67 void(float step) movetogoal
2707 PF_precache_file, // #68 string(string s) precache_file
2708 PF_makestatic, // #69 void(entity e) makestatic
2709 VM_changelevel, // #70 void(string s) changelevel
2711 VM_cvar_set, // #72 void(string var, string val) cvar_set
2712 PF_centerprint, // #73 void(entity client, strings) centerprint
2713 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2714 PF_precache_model, // #75 string(string s) precache_model2
2715 PF_precache_sound, // #76 string(string s) precache_sound2
2716 PF_precache_file, // #77 string(string s) precache_file2
2717 PF_setspawnparms, // #78 void(entity e) setspawnparms
2720 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2729 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2730 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2731 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2732 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2733 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2734 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2735 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2736 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2737 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2738 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2749 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2750 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2751 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2752 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2753 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2754 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2755 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2756 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2757 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2758 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2759 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2760 // FTEQW range #200-#299
2779 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2801 VM_print, // #339 void(string, ...) print (DP_SV_PRINT)
2808 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2809 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2810 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2811 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2812 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2813 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2814 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2815 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2816 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2817 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2818 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2819 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2820 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2821 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2822 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2823 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2824 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2825 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2826 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2827 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2828 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2829 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2830 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2831 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2832 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2833 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2834 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2835 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2836 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2837 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2838 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2839 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2840 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2841 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2842 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2843 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2844 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2845 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2846 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2847 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2848 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2849 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2850 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2851 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2852 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2853 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2854 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2855 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2856 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2857 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2858 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2859 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2860 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2861 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2862 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2863 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2864 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2865 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2867 PF_edict_num, // #459 entity(float num) (??)
2868 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2869 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2870 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2871 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2872 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2873 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2874 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2875 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2876 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2877 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2878 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2879 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2880 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2881 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2882 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2883 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2884 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2885 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2888 e10, e10 // #480-499 (LordHavoc)
2891 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2893 void VM_SV_Cmd_Init(void)
2898 void VM_SV_Cmd_Reset(void)