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 "
102 "DP_SV_ROTATINGBMODEL "
105 "DP_SV_WRITEUNTERMINATEDSTRING "
109 "DP_TE_EXPLOSIONRGB "
111 "DP_TE_PARTICLECUBE "
112 "DP_TE_PARTICLERAIN "
113 "DP_TE_PARTICLESNOW "
115 "DP_TE_QUADEFFECTS1 "
118 "DP_TE_STANDARDEFFECTBUILTINS "
119 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
122 //"EXT_CSQC " // not ready yet
124 "KRIMZON_SV_PARSECLIENTCOMMAND "
128 "PRYDON_CLIENTCURSOR "
129 "TENEBRAE_GFX_DLIGHTS "
131 "NEXUIZ_PLAYERMODEL "
138 Writes new values for v_forward, v_up, and v_right based on angles
142 void PF_makevectors (void)
144 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
151 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.
153 setorigin (entity, origin)
156 void PF_setorigin (void)
161 e = PRVM_G_EDICT(OFS_PARM0);
162 if (e == prog->edicts)
164 VM_Warning("setorigin: can not modify world entity\n");
167 if (e->priv.server->free)
169 VM_Warning("setorigin: can not modify free entity\n");
172 org = PRVM_G_VECTOR(OFS_PARM1);
173 VectorCopy (org, e->fields.server->origin);
174 SV_LinkEdict (e, false);
178 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
182 for (i=0 ; i<3 ; i++)
184 PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
186 // set derived values
187 VectorCopy (min, e->fields.server->mins);
188 VectorCopy (max, e->fields.server->maxs);
189 VectorSubtract (max, min, e->fields.server->size);
191 SV_LinkEdict (e, false);
198 the size box is rotated by the current angle
199 LordHavoc: no it isn't...
201 setsize (entity, minvector, maxvector)
204 void PF_setsize (void)
209 e = PRVM_G_EDICT(OFS_PARM0);
210 if (e == prog->edicts)
212 VM_Warning("setsize: can not modify world entity\n");
215 if (e->priv.server->free)
217 VM_Warning("setsize: can not modify free entity\n");
220 min = PRVM_G_VECTOR(OFS_PARM1);
221 max = PRVM_G_VECTOR(OFS_PARM2);
222 SetMinMaxSize (e, min, max, false);
230 setmodel(entity, model)
233 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
234 void PF_setmodel (void)
240 e = PRVM_G_EDICT(OFS_PARM0);
241 if (e == prog->edicts)
243 VM_Warning("setmodel: can not modify world entity\n");
246 if (e->priv.server->free)
248 VM_Warning("setmodel: can not modify free entity\n");
251 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
252 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
253 e->fields.server->modelindex = i;
259 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
260 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
262 SetMinMaxSize (e, quakemins, quakemaxs, true);
265 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
272 single print to a specific client
274 sprint(clientent, value)
277 void PF_sprint (void)
281 char string[VM_STRINGTEMP_LENGTH];
283 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
285 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
287 VM_Warning("tried to centerprint to a non-client\n");
291 client = svs.clients + entnum-1;
292 if (!client->netconnection)
295 VM_VarString(1, string, sizeof(string));
296 MSG_WriteChar(&client->netconnection->message,svc_print);
297 MSG_WriteString(&client->netconnection->message, string);
305 single print to a specific client
307 centerprint(clientent, value)
310 void PF_centerprint (void)
314 char string[VM_STRINGTEMP_LENGTH];
316 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
318 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
320 VM_Warning("tried to centerprint to a non-client\n");
324 client = svs.clients + entnum-1;
325 if (!client->netconnection)
328 VM_VarString(1, string, sizeof(string));
329 MSG_WriteChar(&client->netconnection->message,svc_centerprint);
330 MSG_WriteString(&client->netconnection->message, string);
337 particle(origin, color, count)
340 void PF_particle (void)
346 org = PRVM_G_VECTOR(OFS_PARM0);
347 dir = PRVM_G_VECTOR(OFS_PARM1);
348 color = PRVM_G_FLOAT(OFS_PARM2);
349 count = PRVM_G_FLOAT(OFS_PARM3);
350 SV_StartParticle (org, dir, (int)color, (int)count);
360 void PF_ambientsound (void)
364 float vol, attenuation;
367 pos = PRVM_G_VECTOR (OFS_PARM0);
368 samp = PRVM_G_STRING(OFS_PARM1);
369 vol = PRVM_G_FLOAT(OFS_PARM2);
370 attenuation = PRVM_G_FLOAT(OFS_PARM3);
372 // check to see if samp was properly precached
373 soundnum = SV_SoundIndex(samp, 1);
381 // add an svc_spawnambient command to the level signon packet
384 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
386 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
388 MSG_WriteVector(&sv.signon, pos, sv.protocol);
391 MSG_WriteShort (&sv.signon, soundnum);
393 MSG_WriteByte (&sv.signon, soundnum);
395 MSG_WriteByte (&sv.signon, (int)(vol*255));
396 MSG_WriteByte (&sv.signon, (int)(attenuation*64));
404 Each entity can have eight independant sound sources, like voice,
407 Channel 0 is an auto-allocate channel, the others override anything
408 already running on that entity/channel pair.
410 An attenuation of 0 will play full volume everywhere in the level.
411 Larger attenuations will drop off.
419 prvm_edict_t *entity;
423 entity = PRVM_G_EDICT(OFS_PARM0);
424 channel = (int)PRVM_G_FLOAT(OFS_PARM1);
425 sample = PRVM_G_STRING(OFS_PARM2);
426 volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
427 attenuation = PRVM_G_FLOAT(OFS_PARM4);
429 if (volume < 0 || volume > 255)
431 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
435 if (attenuation < 0 || attenuation > 4)
437 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
441 if (channel < 0 || channel > 7)
443 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
447 SV_StartSound (entity, channel, sample, volume, attenuation);
454 Used for use tracing and shot targeting
455 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
456 if the tryents flag is set.
458 traceline (vector1, vector2, tryents)
461 void PF_traceline (void)
469 prog->xfunction->builtinsprofile += 30;
471 v1 = PRVM_G_VECTOR(OFS_PARM0);
472 v2 = PRVM_G_VECTOR(OFS_PARM1);
473 move = (int)PRVM_G_FLOAT(OFS_PARM2);
474 ent = PRVM_G_EDICT(OFS_PARM3);
476 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]))
477 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));
479 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
481 prog->globals.server->trace_allsolid = trace.allsolid;
482 prog->globals.server->trace_startsolid = trace.startsolid;
483 prog->globals.server->trace_fraction = trace.fraction;
484 prog->globals.server->trace_inwater = trace.inwater;
485 prog->globals.server->trace_inopen = trace.inopen;
486 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
487 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
488 prog->globals.server->trace_plane_dist = trace.plane.dist;
490 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
492 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
493 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
494 val->_float = trace.startsupercontents;
495 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
496 val->_float = trace.hitsupercontents;
497 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
498 val->_float = trace.hitq3surfaceflags;
499 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
501 if (trace.hittexture)
502 val->string = PRVM_SetTempString(trace.hittexture->name);
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)
564 val->string = PRVM_SetTempString(trace.hittexture->name);
570 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
571 void PF_tracetoss (void)
575 prvm_edict_t *ignore;
578 prog->xfunction->builtinsprofile += 600;
580 ent = PRVM_G_EDICT(OFS_PARM0);
581 if (ent == prog->edicts)
583 VM_Warning("tracetoss: can not use world entity\n");
586 ignore = PRVM_G_EDICT(OFS_PARM1);
588 trace = SV_Trace_Toss (ent, ignore);
590 prog->globals.server->trace_allsolid = trace.allsolid;
591 prog->globals.server->trace_startsolid = trace.startsolid;
592 prog->globals.server->trace_fraction = trace.fraction;
593 prog->globals.server->trace_inwater = trace.inwater;
594 prog->globals.server->trace_inopen = trace.inopen;
595 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
596 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
597 prog->globals.server->trace_plane_dist = trace.plane.dist;
599 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
601 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
602 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents)))
603 val->_float = trace.startsupercontents;
604 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents)))
605 val->_float = trace.hitsupercontents;
606 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags)))
607 val->_float = trace.hitq3surfaceflags;
608 if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename)))
610 if (trace.hittexture)
611 val->string = PRVM_SetTempString(trace.hittexture->name);
622 Returns true if the given entity can move to the given position from it's
623 current position by walking or rolling.
625 scalar checkpos (entity, vector)
628 void PF_checkpos (void)
632 //============================================================================
635 unsigned char checkpvs[MAX_MAP_LEAFS/8];
637 int PF_newcheckclient (int check)
643 // cycle to the next one
645 check = bound(1, check, svs.maxclients);
646 if (check == svs.maxclients)
654 prog->xfunction->builtinsprofile++;
656 if (i == svs.maxclients+1)
658 // look up the client's edict
659 ent = PRVM_EDICT_NUM(i);
660 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
661 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
663 // found a valid client (possibly the same one again)
667 // get the PVS for the entity
668 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
670 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
671 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
680 Returns a client (or object that has a client enemy) that would be a
683 If there is more than one valid option, they are cycled each frame
685 If (self.origin + self.viewofs) is not in the PVS of the current target,
686 it is not returned at all.
691 int c_invis, c_notvis;
692 void PF_checkclient (void)
694 prvm_edict_t *ent, *self;
697 // find a new check if on a new frame
698 if (sv.time - sv.lastchecktime >= 0.1)
700 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
701 sv.lastchecktime = sv.time;
704 // return check if it might be visible
705 ent = PRVM_EDICT_NUM(sv.lastcheck);
706 if (ent->priv.server->free || ent->fields.server->health <= 0)
708 VM_RETURN_EDICT(prog->edicts);
712 // if current entity can't possibly see the check entity, return 0
713 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
714 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
715 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
718 VM_RETURN_EDICT(prog->edicts);
722 // might be able to see it
724 VM_RETURN_EDICT(ent);
727 //============================================================================
734 Sends text over to the client's execution buffer
736 stuffcmd (clientent, value, ...)
739 void PF_stuffcmd (void)
743 char string[VM_STRINGTEMP_LENGTH];
745 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
746 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
748 VM_Warning("Can't stuffcmd to a non-client\n");
752 VM_VarString(1, string, sizeof(string));
755 host_client = svs.clients + entnum-1;
756 Host_ClientCommands ("%s", string);
764 Returns a chain of entities that have origins within a spherical area
766 findradius (origin, radius)
769 void PF_findradius (void)
771 prvm_edict_t *ent, *chain;
772 vec_t radius, radius2;
773 vec3_t org, eorg, mins, maxs;
776 prvm_edict_t *touchedicts[MAX_EDICTS];
778 chain = (prvm_edict_t *)prog->edicts;
780 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
781 radius = PRVM_G_FLOAT(OFS_PARM1);
782 radius2 = radius * radius;
784 mins[0] = org[0] - (radius + 1);
785 mins[1] = org[1] - (radius + 1);
786 mins[2] = org[2] - (radius + 1);
787 maxs[0] = org[0] + (radius + 1);
788 maxs[1] = org[1] + (radius + 1);
789 maxs[2] = org[2] + (radius + 1);
790 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
791 if (numtouchedicts > MAX_EDICTS)
793 // this never happens
794 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
795 numtouchedicts = MAX_EDICTS;
797 for (i = 0;i < numtouchedicts;i++)
799 ent = touchedicts[i];
800 prog->xfunction->builtinsprofile++;
801 // Quake did not return non-solid entities but darkplaces does
802 // (note: this is the reason you can't blow up fallen zombies)
803 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
805 // LordHavoc: compare against bounding box rather than center so it
806 // doesn't miss large objects, and use DotProduct instead of Length
807 // for a major speedup
808 VectorSubtract(org, ent->fields.server->origin, eorg);
809 if (sv_gameplayfix_findradiusdistancetobox.integer)
811 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
812 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
813 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
816 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
817 if (DotProduct(eorg, eorg) < radius2)
819 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
824 VM_RETURN_EDICT(chain);
827 void PF_precache_file (void)
828 { // precache_file is only used to copy files with qcc, it does nothing
829 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
833 void PF_precache_sound (void)
835 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
836 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
839 void PF_precache_model (void)
841 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
842 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
849 float(float yaw, float dist) walkmove
852 void PF_walkmove (void)
860 // assume failure if it returns early
861 PRVM_G_FLOAT(OFS_RETURN) = 0;
863 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
864 if (ent == prog->edicts)
866 VM_Warning("walkmove: can not modify world entity\n");
869 if (ent->priv.server->free)
871 VM_Warning("walkmove: can not modify free entity\n");
874 yaw = PRVM_G_FLOAT(OFS_PARM0);
875 dist = PRVM_G_FLOAT(OFS_PARM1);
877 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
880 yaw = yaw*M_PI*2 / 360;
882 move[0] = cos(yaw)*dist;
883 move[1] = sin(yaw)*dist;
886 // save program state, because SV_movestep may call other progs
887 oldf = prog->xfunction;
888 oldself = prog->globals.server->self;
890 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
893 // restore program state
894 prog->xfunction = oldf;
895 prog->globals.server->self = oldself;
905 void PF_droptofloor (void)
911 // assume failure if it returns early
912 PRVM_G_FLOAT(OFS_RETURN) = 0;
914 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
915 if (ent == prog->edicts)
917 VM_Warning("droptofloor: can not modify world entity\n");
920 if (ent->priv.server->free)
922 VM_Warning("droptofloor: can not modify free entity\n");
926 VectorCopy (ent->fields.server->origin, end);
929 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
931 if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer))
933 if (trace.fraction < 1)
934 VectorCopy (trace.endpos, ent->fields.server->origin);
935 SV_LinkEdict (ent, false);
936 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
937 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
938 PRVM_G_FLOAT(OFS_RETURN) = 1;
939 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
940 ent->priv.server->suspendedinairflag = true;
948 void(float style, string value) lightstyle
951 void PF_lightstyle (void)
958 style = (int)PRVM_G_FLOAT(OFS_PARM0);
959 val = PRVM_G_STRING(OFS_PARM1);
961 if( (unsigned) style >= MAX_LIGHTSTYLES ) {
962 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
965 // change the string in sv
966 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
968 // send message to all clients on this server
969 if (sv.state != ss_active)
972 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
974 if (client->active && client->netconnection)
976 MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
977 MSG_WriteChar (&client->netconnection->message,style);
978 MSG_WriteString (&client->netconnection->message, val);
988 void PF_checkbottom (void)
990 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
998 void PF_pointcontents (void)
1000 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1007 Pick a vector for the player to shoot along
1008 vector aim(entity, missilespeed)
1013 prvm_edict_t *ent, *check, *bestent;
1014 vec3_t start, dir, end, bestdir;
1017 float dist, bestdist;
1020 // assume failure if it returns early
1021 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1022 // if sv_aim is so high it can't possibly accept anything, skip out early
1023 if (sv_aim.value >= 1)
1026 ent = PRVM_G_EDICT(OFS_PARM0);
1027 if (ent == prog->edicts)
1029 VM_Warning("aim: can not use world entity\n");
1032 if (ent->priv.server->free)
1034 VM_Warning("aim: can not use free entity\n");
1037 speed = PRVM_G_FLOAT(OFS_PARM1);
1039 VectorCopy (ent->fields.server->origin, start);
1042 // try sending a trace straight
1043 VectorCopy (prog->globals.server->v_forward, dir);
1044 VectorMA (start, 2048, dir, end);
1045 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1046 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1047 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1049 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1054 // try all possible entities
1055 VectorCopy (dir, bestdir);
1056 bestdist = sv_aim.value;
1059 check = PRVM_NEXT_EDICT(prog->edicts);
1060 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1062 prog->xfunction->builtinsprofile++;
1063 if (check->fields.server->takedamage != DAMAGE_AIM)
1067 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1068 continue; // don't aim at teammate
1069 for (j=0 ; j<3 ; j++)
1070 end[j] = check->fields.server->origin[j]
1071 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1072 VectorSubtract (end, start, dir);
1073 VectorNormalize (dir);
1074 dist = DotProduct (dir, prog->globals.server->v_forward);
1075 if (dist < bestdist)
1076 continue; // to far to turn
1077 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1078 if (tr.ent == check)
1079 { // can shoot at this one
1087 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1088 dist = DotProduct (dir, prog->globals.server->v_forward);
1089 VectorScale (prog->globals.server->v_forward, dist, end);
1091 VectorNormalize (end);
1092 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1096 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1104 This was a major timewaster in progs, so it was converted to C
1107 void PF_changeyaw (void)
1110 float ideal, current, move, speed;
1112 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1113 if (ent == prog->edicts)
1115 VM_Warning("changeyaw: can not modify world entity\n");
1118 if (ent->priv.server->free)
1120 VM_Warning("changeyaw: can not modify free entity\n");
1123 current = ANGLEMOD(ent->fields.server->angles[1]);
1124 ideal = ent->fields.server->ideal_yaw;
1125 speed = ent->fields.server->yaw_speed;
1127 if (current == ideal)
1129 move = ideal - current;
1130 if (ideal > current)
1151 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1159 void PF_changepitch (void)
1162 float ideal, current, move, speed;
1165 ent = PRVM_G_EDICT(OFS_PARM0);
1166 if (ent == prog->edicts)
1168 VM_Warning("changepitch: can not modify world entity\n");
1171 if (ent->priv.server->free)
1173 VM_Warning("changepitch: can not modify free entity\n");
1176 current = ANGLEMOD( ent->fields.server->angles[0] );
1177 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1178 ideal = val->_float;
1181 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1184 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1185 speed = val->_float;
1188 VM_Warning("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1192 if (current == ideal)
1194 move = ideal - current;
1195 if (ideal > current)
1216 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1220 ===============================================================================
1224 ===============================================================================
1227 #define MSG_BROADCAST 0 // unreliable to all
1228 #define MSG_ONE 1 // reliable to one (msg_entity)
1229 #define MSG_ALL 2 // reliable to all
1230 #define MSG_INIT 3 // write to the init string
1231 #define MSG_ENTITY 5
1233 sizebuf_t *WriteDest (void)
1238 extern sizebuf_t *sv2csqcbuf;
1240 dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1244 return &sv.datagram;
1247 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1248 entnum = PRVM_NUM_FOR_EDICT(ent);
1249 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1251 VM_Warning ("WriteDest: tried to write to non-client\n");
1252 return &sv.reliable_datagram;
1255 return &svs.clients[entnum-1].netconnection->message;
1258 VM_Warning ("WriteDest: bad destination\n");
1260 return &sv.reliable_datagram;
1272 void PF_WriteByte (void)
1274 MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1277 void PF_WriteChar (void)
1279 MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1282 void PF_WriteShort (void)
1284 MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1287 void PF_WriteLong (void)
1289 MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1292 void PF_WriteAngle (void)
1294 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1297 void PF_WriteCoord (void)
1299 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1302 void PF_WriteString (void)
1304 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1307 void PF_WriteUnterminatedString (void)
1309 MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1313 void PF_WriteEntity (void)
1315 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1318 //////////////////////////////////////////////////////////
1320 void PF_makestatic (void)
1325 ent = PRVM_G_EDICT(OFS_PARM0);
1326 if (ent == prog->edicts)
1328 VM_Warning("makestatic: can not modify world entity\n");
1331 if (ent->priv.server->free)
1333 VM_Warning("makestatic: can not modify free entity\n");
1338 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1343 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1344 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1345 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1349 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1350 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1351 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1354 MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1355 MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1356 for (i=0 ; i<3 ; i++)
1358 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1359 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1362 // throw the entity away now
1366 //=============================================================================
1373 void PF_setspawnparms (void)
1379 ent = PRVM_G_EDICT(OFS_PARM0);
1380 i = PRVM_NUM_FOR_EDICT(ent);
1381 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1383 Con_Print("tried to setspawnparms on a non-client\n");
1387 // copy spawn parms out of the client_t
1388 client = svs.clients + i-1;
1389 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1390 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1397 Returns a color vector indicating the lighting at the requested point.
1399 (Internal Operation note: actually measures the light beneath the point, just like
1400 the model lighting on the client)
1405 void PF_getlight (void)
1407 vec3_t ambientcolor, diffusecolor, diffusenormal;
1409 p = PRVM_G_VECTOR(OFS_PARM0);
1410 VectorClear(ambientcolor);
1411 VectorClear(diffusecolor);
1412 VectorClear(diffusenormal);
1413 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1414 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1415 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1418 void PF_registercvar (void)
1420 const char *name, *value;
1421 name = PRVM_G_STRING(OFS_PARM0);
1422 value = PRVM_G_STRING(OFS_PARM1);
1423 PRVM_G_FLOAT(OFS_RETURN) = 0;
1425 // first check to see if it has already been defined
1426 if (Cvar_FindVar (name))
1429 // check for overlap with a command
1430 if (Cmd_Exists (name))
1432 VM_Warning("PF_registercvar: %s is a command\n", name);
1436 Cvar_Get(name, value, 0);
1438 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1443 unsigned char type; // 1/2/8 or other value if isn't used
1447 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1448 static int vm_autosentstats_last;
1450 void VM_AutoSentStats_Clear (void)
1452 if(vm_autosentstats)
1454 Z_Free(vm_autosentstats);
1455 vm_autosentstats = NULL;
1456 vm_autosentstats_last = -1;
1460 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1461 #define VM_SENDSTAT(a,b,c)\
1464 if((c)==(unsigned char)(c))\
1466 MSG_WriteByte((a), svc_updatestatubyte);\
1467 MSG_WriteByte((a), (b));\
1468 MSG_WriteByte((a), (c));\
1472 MSG_WriteByte((a), svc_updatestat);\
1473 MSG_WriteByte((a), (b));\
1474 MSG_WriteLong((a), (c));\
1478 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1490 if(!vm_autosentstats)
1493 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);
1495 for(i=0; i<vm_autosentstats_last+1 ;i++)
1497 if(!vm_autosentstats[i].type)
1499 switch(vm_autosentstats[i].type)
1503 t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1511 stats[i+32] = si[0];
1512 stats[i+33] = si[1];
1513 stats[i+34] = si[2];
1514 stats[i+35] = si[3];
1518 VM_SENDSTAT(msg, i+32, si[0]);
1519 VM_SENDSTAT(msg, i+33, si[1]);
1520 VM_SENDSTAT(msg, i+34, si[2]);
1521 VM_SENDSTAT(msg, i+35, si[3]);
1527 k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1528 k.i = LittleLong (k.i);
1532 VM_SENDSTAT(msg, i+32, k.i);
1536 v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1540 VM_SENDSTAT(msg, i+32, v);
1548 // void(float index, float type, .void field) SV_AddStat = #470;
1549 // Set up an auto-sent player stat.
1550 // Client's get thier own fields sent to them. Index may not be less than 32.
1551 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1552 // 1: string (4 stats carrying a total of 16 charactures)
1553 // 2: float (one stat, float converted to an integer for transportation)
1554 // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1555 void PF_SV_AddStat (void)
1560 if(!vm_autosentstats)
1562 vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1563 if(!vm_autosentstats)
1565 VM_Warning("PF_SV_AddStat: not enough memory\n");
1569 i = (int)PRVM_G_FLOAT(OFS_PARM0);
1570 type = (int)PRVM_G_FLOAT(OFS_PARM1);
1571 off = PRVM_G_INT (OFS_PARM2);
1576 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1579 if(i >= (MAX_CL_STATS-32))
1581 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1584 if(i > (MAX_CL_STATS-32-4) && type == 1)
1586 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1589 vm_autosentstats[i].type = type;
1590 vm_autosentstats[i].fieldoffset = off;
1591 if(vm_autosentstats_last < i)
1592 vm_autosentstats_last = i;
1599 copies data from one entity to another
1601 copyentity(src, dst)
1604 void PF_copyentity (void)
1606 prvm_edict_t *in, *out;
1607 in = PRVM_G_EDICT(OFS_PARM0);
1608 if (in == prog->edicts)
1610 VM_Warning("copyentity: can not read world entity\n");
1613 if (in->priv.server->free)
1615 VM_Warning("copyentity: can not read free entity\n");
1618 out = PRVM_G_EDICT(OFS_PARM1);
1619 if (out == prog->edicts)
1621 VM_Warning("copyentity: can not modify world entity\n");
1624 if (out->priv.server->free)
1626 VM_Warning("copyentity: can not modify free entity\n");
1629 memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1637 sets the color of a client and broadcasts the update to all connected clients
1639 setcolor(clientent, value)
1642 void PF_setcolor (void)
1648 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1649 i = (int)PRVM_G_FLOAT(OFS_PARM1);
1651 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1653 Con_Print("tried to setcolor a non-client\n");
1657 client = svs.clients + entnum-1;
1660 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1662 client->edict->fields.server->team = (i & 15) + 1;
1665 if (client->old_colors != client->colors)
1667 client->old_colors = client->colors;
1668 // send notification to all clients
1669 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1670 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1671 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1679 effect(origin, modelname, startframe, framecount, framerate)
1682 void PF_effect (void)
1686 s = PRVM_G_STRING(OFS_PARM1);
1689 VM_Warning("effect: no model specified\n");
1693 i = SV_ModelIndex(s, 1);
1696 VM_Warning("effect: model not precached\n");
1700 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1702 VM_Warning("effect: framecount < 1\n");
1706 if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1708 VM_Warning("effect: framerate < 1\n");
1712 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));
1715 void PF_te_blood (void)
1717 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1719 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1720 MSG_WriteByte(&sv.datagram, TE_BLOOD);
1722 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1723 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1724 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1726 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1727 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1728 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1730 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1733 void PF_te_bloodshower (void)
1735 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1737 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1738 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1740 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1741 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1742 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1744 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1745 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1746 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1748 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1750 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1753 void PF_te_explosionrgb (void)
1755 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1756 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1758 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1759 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1760 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1762 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1763 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1764 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1767 void PF_te_particlecube (void)
1769 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1771 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1772 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1774 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1775 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1776 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1778 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1779 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1780 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1782 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1783 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1784 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1786 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1788 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1789 // gravity true/false
1790 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1792 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1795 void PF_te_particlerain (void)
1797 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1799 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1800 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1802 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1803 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1804 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1806 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1807 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1808 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1810 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1811 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1812 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1814 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1816 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1819 void PF_te_particlesnow (void)
1821 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1823 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1824 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1826 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1827 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1828 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1830 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1831 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1832 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1834 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1835 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1836 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1838 MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1840 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1843 void PF_te_spark (void)
1845 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1847 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1848 MSG_WriteByte(&sv.datagram, TE_SPARK);
1850 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1851 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1852 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1854 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1855 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1856 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1858 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1861 void PF_te_gunshotquad (void)
1863 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1866 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1871 void PF_te_spikequad (void)
1873 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1874 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1876 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1877 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1878 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1881 void PF_te_superspikequad (void)
1883 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1886 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1891 void PF_te_explosionquad (void)
1893 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1896 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1897 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1898 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1901 void PF_te_smallflash (void)
1903 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1906 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1907 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1908 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1911 void PF_te_customflash (void)
1913 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1915 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1916 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1918 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1919 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1920 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1922 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1924 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1926 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1927 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1928 MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1931 void PF_te_gunshot (void)
1933 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1934 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1936 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1937 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1938 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1941 void PF_te_spike (void)
1943 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944 MSG_WriteByte(&sv.datagram, TE_SPIKE);
1946 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1947 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1948 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1951 void PF_te_superspike (void)
1953 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1954 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
1956 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1957 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1958 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1961 void PF_te_explosion (void)
1963 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1964 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1966 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1967 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1968 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1971 void PF_te_tarexplosion (void)
1973 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1974 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1976 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1977 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1978 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981 void PF_te_wizspike (void)
1983 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1984 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1986 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1987 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1988 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1991 void PF_te_knightspike (void)
1993 MSG_WriteByte(&sv.datagram, svc_temp_entity);
1994 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1996 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1997 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1998 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2001 void PF_te_lavasplash (void)
2003 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2006 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2011 void PF_te_teleport (void)
2013 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2014 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2016 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2017 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2018 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2021 void PF_te_explosion2 (void)
2023 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2024 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2026 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2027 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2028 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2030 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2031 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2034 void PF_te_lightning1 (void)
2036 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2037 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2039 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2041 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2042 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2043 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2045 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2046 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2047 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2050 void PF_te_lightning2 (void)
2052 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2053 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2055 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2057 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2058 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2059 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2061 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2062 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2063 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2066 void PF_te_lightning3 (void)
2068 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2069 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2071 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2073 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2074 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2075 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2077 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2078 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2079 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2082 void PF_te_beam (void)
2084 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2085 MSG_WriteByte(&sv.datagram, TE_BEAM);
2087 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2089 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2090 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2091 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2093 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2094 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2095 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2098 void PF_te_plasmaburn (void)
2100 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2101 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2102 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2103 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2104 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2107 void PF_te_flamejet (void)
2109 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2110 MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2112 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2113 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2114 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2116 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2117 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2118 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2120 MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2123 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
2126 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2128 bestdist = 1000000000;
2130 for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2132 // clip original point to each triangle of the surface and find the
2133 // triangle that is closest
2134 v[0] = model->surfmesh.data_vertex3f + e[0] * 3;
2135 v[1] = model->surfmesh.data_vertex3f + e[1] * 3;
2136 v[2] = model->surfmesh.data_vertex3f + e[2] * 3;
2137 TriangleNormal(v[0], v[1], v[2], facenormal);
2138 VectorNormalize(facenormal);
2139 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2140 VectorMA(p, offsetdist, facenormal, temp);
2141 for (j = 0, k = 2;j < 3;k = j, j++)
2143 VectorSubtract(v[k], v[j], edgenormal);
2144 CrossProduct(edgenormal, facenormal, sidenormal);
2145 VectorNormalize(sidenormal);
2146 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2148 VectorMA(temp, offsetdist, sidenormal, temp);
2150 dist = VectorDistance2(temp, p);
2151 if (bestdist > dist)
2154 VectorCopy(temp, out);
2159 static model_t *getmodel(prvm_edict_t *ed)
2162 if (!ed || ed->priv.server->free)
2164 modelindex = (int)ed->fields.server->modelindex;
2165 if (modelindex < 1 || modelindex >= MAX_MODELS)
2167 return sv.models[modelindex];
2170 static msurface_t *getsurface(model_t *model, int surfacenum)
2172 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2174 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2178 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2179 void PF_getsurfacenumpoints(void)
2182 msurface_t *surface;
2183 // return 0 if no such surface
2184 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2186 PRVM_G_FLOAT(OFS_RETURN) = 0;
2190 // note: this (incorrectly) assumes it is a simple polygon
2191 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2193 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2194 void PF_getsurfacepoint(void)
2198 msurface_t *surface;
2200 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2201 ed = PRVM_G_EDICT(OFS_PARM0);
2202 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2204 // note: this (incorrectly) assumes it is a simple polygon
2205 pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
2206 if (pointnum < 0 || pointnum >= surface->num_vertices)
2208 // FIXME: implement rotation/scaling
2209 VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2211 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2212 void PF_getsurfacenormal(void)
2215 msurface_t *surface;
2217 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2218 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2220 // FIXME: implement rotation/scaling
2221 // note: this (incorrectly) assumes it is a simple polygon
2222 // note: this only returns the first triangle, so it doesn't work very
2223 // well for curved surfaces or arbitrary meshes
2224 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);
2225 VectorNormalize(normal);
2226 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2228 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2229 void PF_getsurfacetexture(void)
2232 msurface_t *surface;
2233 PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2234 if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2236 PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
2238 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2239 void PF_getsurfacenearpoint(void)
2241 int surfacenum, best;
2243 vec_t dist, bestdist;
2246 msurface_t *surface;
2248 PRVM_G_FLOAT(OFS_RETURN) = -1;
2249 ed = PRVM_G_EDICT(OFS_PARM0);
2250 point = PRVM_G_VECTOR(OFS_PARM1);
2252 if (!ed || ed->priv.server->free)
2254 model = getmodel(ed);
2255 if (!model || !model->num_surfaces)
2258 // FIXME: implement rotation/scaling
2259 VectorSubtract(point, ed->fields.server->origin, p);
2261 bestdist = 1000000000;
2262 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2264 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2265 // first see if the nearest point on the surface's box is closer than the previous match
2266 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2267 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2268 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2269 dist = VectorLength2(clipped);
2270 if (dist < bestdist)
2272 // it is, check the nearest point on the actual geometry
2273 clippointtosurface(model, surface, p, clipped);
2274 VectorSubtract(clipped, p, clipped);
2275 dist += VectorLength2(clipped);
2276 if (dist < bestdist)
2278 // that's closer too, store it as the best match
2284 PRVM_G_FLOAT(OFS_RETURN) = best;
2286 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2287 void PF_getsurfaceclippedpoint(void)
2291 msurface_t *surface;
2293 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2294 ed = PRVM_G_EDICT(OFS_PARM0);
2295 if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
2297 // FIXME: implement rotation/scaling
2298 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2299 clippointtosurface(model, surface, p, out);
2300 // FIXME: implement rotation/scaling
2301 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2304 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2305 //this function originally written by KrimZon, made shorter by LordHavoc
2306 void PF_clientcommand (void)
2308 client_t *temp_client;
2311 //find client for this entity
2312 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2313 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2315 Con_Print("PF_clientcommand: entity is not a client\n");
2319 temp_client = host_client;
2320 host_client = svs.clients + i;
2321 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2322 host_client = temp_client;
2325 //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)
2326 void PF_setattachment (void)
2328 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2329 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2330 const char *tagname = PRVM_G_STRING(OFS_PARM2);
2335 if (e == prog->edicts)
2337 VM_Warning("setattachment: can not modify world entity\n");
2340 if (e->priv.server->free)
2342 VM_Warning("setattachment: can not modify free entity\n");
2346 if (tagentity == NULL)
2347 tagentity = prog->edicts;
2349 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2351 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2353 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2356 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2358 modelindex = (int)tagentity->fields.server->modelindex;
2359 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2361 v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2363 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);
2366 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));
2370 /////////////////////////////////////////
2371 // DP_MD3_TAGINFO extension coded by VorteX
2373 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2378 i = (int)e->fields.server->modelindex;
2379 if (i < 1 || i >= MAX_MODELS)
2381 model = sv.models[i];
2383 return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
2386 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2388 float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2392 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);
2394 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);
2397 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2403 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2404 && (model = sv.models[(int)ent->fields.server->modelindex])
2405 && model->animscenes)
2407 // if model has wrong frame, engine automatically switches to model first frame
2408 frame = (int)ent->fields.server->frame;
2409 if (frame < 0 || frame >= model->numframes)
2411 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2413 *out = identitymatrix;
2417 // Warnings/errors code:
2418 // 0 - normal (everything all-right)
2421 // 3 - null or non-precached model
2422 // 4 - no tags with requested index
2423 // 5 - runaway loop at attachment chain
2424 extern cvar_t cl_bob;
2425 extern cvar_t cl_bobcycle;
2426 extern cvar_t cl_bobup;
2427 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2431 int modelindex, attachloop;
2432 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2435 *out = identitymatrix; // warnings and errors return identical matrix
2437 if (ent == prog->edicts)
2439 if (ent->priv.server->free)
2442 modelindex = (int)ent->fields.server->modelindex;
2443 if (modelindex <= 0 || modelindex > MAX_MODELS)
2446 model = sv.models[modelindex];
2448 tagmatrix = identitymatrix;
2449 // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2453 if (attachloop >= 256) // prevent runaway looping
2455 // apply transformation by child's tagindex on parent entity and then
2456 // by parent entity itself
2457 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2458 if (ret && attachloop == 0)
2460 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2461 SV_GetEntityMatrix(ent, &entitymatrix, false);
2462 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2463 // next iteration we process the parent entity
2464 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2466 tagindex = (int)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2467 ent = PRVM_EDICT_NUM(val->edict);
2474 // RENDER_VIEWMODEL magic
2475 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2477 Matrix4x4_Copy(&tagmatrix, out);
2478 ent = PRVM_EDICT_NUM(val->edict);
2480 SV_GetEntityMatrix(ent, &entitymatrix, true);
2481 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2484 // Cl_bob, ported from rendering code
2485 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2488 // LordHavoc: this code is *weird*, but not replacable (I think it
2489 // should be done in QC on the server, but oh well, quake is quake)
2490 // LordHavoc: figured out bobup: the time at which the sin is at 180
2491 // degrees (which allows lengthening or squishing the peak or valley)
2492 cycle = sv.time/cl_bobcycle.value;
2493 cycle -= (int)cycle;
2494 if (cycle < cl_bobup.value)
2495 cycle = sin(M_PI * cycle / cl_bobup.value);
2497 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2498 // bob is proportional to velocity in the xy plane
2499 // (don't count Z, or jumping messes it up)
2500 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;
2501 bob = bob*0.3 + bob*0.7*cycle;
2502 Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2509 //float(entity ent, string tagname) gettagindex;
2511 void PF_gettagindex (void)
2513 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2514 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2515 int modelindex, tag_index;
2517 if (ent == prog->edicts)
2519 VM_Warning("gettagindex: can't affect world entity\n");
2522 if (ent->priv.server->free)
2524 VM_Warning("gettagindex: can't affect free entity\n");
2528 modelindex = (int)ent->fields.server->modelindex;
2530 if (modelindex <= 0 || modelindex > MAX_MODELS)
2531 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2534 tag_index = SV_GetTagIndex(ent, tag_name);
2536 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2538 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2541 //vector(entity ent, float tagindex) gettaginfo;
2542 void PF_gettaginfo (void)
2544 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2545 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2546 matrix4x4_t tag_matrix;
2549 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2550 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2555 VM_Warning("gettagindex: can't affect world entity\n");
2558 VM_Warning("gettagindex: can't affect free entity\n");
2561 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2564 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2567 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2572 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2573 void PF_dropclient (void)
2576 client_t *oldhostclient;
2577 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2578 if (clientnum < 0 || clientnum >= svs.maxclients)
2580 VM_Warning("dropclient: not a client\n");
2583 if (!svs.clients[clientnum].active)
2585 VM_Warning("dropclient: that client slot is not connected\n");
2588 oldhostclient = host_client;
2589 host_client = svs.clients + clientnum;
2590 SV_DropClient(false);
2591 host_client = oldhostclient;
2594 //entity() spawnclient (DP_SV_BOTCLIENT)
2595 void PF_spawnclient (void)
2599 prog->xfunction->builtinsprofile += 2;
2601 for (i = 0;i < svs.maxclients;i++)
2603 if (!svs.clients[i].active)
2605 prog->xfunction->builtinsprofile += 100;
2606 SV_ConnectClient (i, NULL);
2607 // this has to be set or else ClientDisconnect won't be called
2608 // we assume the qc will call ClientConnect...
2609 svs.clients[i].clientconnectcalled = true;
2610 ed = PRVM_EDICT_NUM(i + 1);
2614 VM_RETURN_EDICT(ed);
2617 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2618 void PF_clienttype (void)
2621 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2622 if (clientnum < 0 || clientnum >= svs.maxclients)
2623 PRVM_G_FLOAT(OFS_RETURN) = 3;
2624 else if (!svs.clients[clientnum].active)
2625 PRVM_G_FLOAT(OFS_RETURN) = 0;
2626 else if (svs.clients[clientnum].netconnection)
2627 PRVM_G_FLOAT(OFS_RETURN) = 1;
2629 PRVM_G_FLOAT(OFS_RETURN) = 2;
2632 void PF_edict_num (void)
2634 VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2637 prvm_builtin_t vm_sv_builtins[] = {
2639 PF_makevectors, // #1 void(vector ang) makevectors
2640 PF_setorigin, // #2 void(entity e, vector o) setorigin
2641 PF_setmodel, // #3 void(entity e, string m) setmodel
2642 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2643 NULL, // #5 void(entity e, vector min, vector max) setabssize
2644 VM_break, // #6 void() break
2645 VM_random, // #7 float() random
2646 PF_sound, // #8 void(entity e, float chan, string samp) sound
2647 VM_normalize, // #9 vector(vector v) normalize
2648 VM_error, // #10 void(string e) error
2649 VM_objerror, // #11 void(string e) objerror
2650 VM_vlen, // #12 float(vector v) vlen
2651 VM_vectoyaw, // #13 float(vector v) vectoyaw
2652 VM_spawn, // #14 entity() spawn
2653 VM_remove, // #15 void(entity e) remove
2654 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2655 PF_checkclient, // #17 entity() clientlist
2656 VM_find, // #18 entity(entity start, .string fld, string match) find
2657 PF_precache_sound, // #19 void(string s) precache_sound
2658 PF_precache_model, // #20 void(string s) precache_model
2659 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2660 PF_findradius, // #22 entity(vector org, float rad) findradius
2661 VM_bprint, // #23 void(string s) bprint
2662 PF_sprint, // #24 void(entity client, string s) sprint
2663 VM_dprint, // #25 void(string s) dprint
2664 VM_ftos, // #26 void(string s) ftos
2665 VM_vtos, // #27 void(string s) vtos
2666 VM_coredump, // #28 void() coredump
2667 VM_traceon, // #29 void() traceon
2668 VM_traceoff, // #30 void() traceoff
2669 VM_eprint, // #31 void(entity e) eprint
2670 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2672 PF_droptofloor, // #34 float() droptofloor
2673 PF_lightstyle, // #35 void(float style, string value) lightstyle
2674 VM_rint, // #36 float(float v) rint
2675 VM_floor, // #37 float(float v) floor
2676 VM_ceil, // #38 float(float v) ceil
2678 PF_checkbottom, // #40 float(entity e) checkbottom
2679 PF_pointcontents, // #41 float(vector v) pointcontents
2681 VM_fabs, // #43 float(float f) fabs
2682 PF_aim, // #44 vector(entity e, float speed) aim
2683 VM_cvar, // #45 float(string s) cvar
2684 VM_localcmd, // #46 void(string s) localcmd
2685 VM_nextent, // #47 entity(entity e) nextent
2686 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
2687 PF_changeyaw, // #49 void() ChangeYaw
2689 VM_vectoangles, // #51 vector(vector v) vectoangles
2690 PF_WriteByte, // #52 void(float to, float f) WriteByte
2691 PF_WriteChar, // #53 void(float to, float f) WriteChar
2692 PF_WriteShort, // #54 void(float to, float f) WriteShort
2693 PF_WriteLong, // #55 void(float to, float f) WriteLong
2694 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
2695 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
2696 PF_WriteString, // #58 void(float to, string s) WriteString
2697 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
2698 VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2699 VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2700 VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2701 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2702 PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2703 VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
2705 SV_MoveToGoal, // #67 void(float step) movetogoal
2706 PF_precache_file, // #68 string(string s) precache_file
2707 PF_makestatic, // #69 void(entity e) makestatic
2708 VM_changelevel, // #70 void(string s) changelevel
2710 VM_cvar_set, // #72 void(string var, string val) cvar_set
2711 PF_centerprint, // #73 void(entity client, strings) centerprint
2712 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2713 PF_precache_model, // #75 string(string s) precache_model2
2714 PF_precache_sound, // #76 string(string s) precache_sound2
2715 PF_precache_file, // #77 string(string s) precache_file2
2716 PF_setspawnparms, // #78 void(entity e) setspawnparms
2719 VM_stof, // #81 float(string s) stof (FRIK_FILE)
2728 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2729 VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
2730 PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2731 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2732 VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2733 VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2734 VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2735 VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2736 VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2737 VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
2748 VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
2749 VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
2750 VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
2751 VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2752 VM_strlen, // #114 float(string s) strlen (FRIK_FILE)
2753 VM_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
2754 VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
2755 VM_stov, // #117 vector(string) stov (FRIK_FILE)
2756 VM_strzone, // #118 string(string s) strzone (FRIK_FILE)
2757 VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
2758 e10, e10, e10, e10, e10, e10, e10, e10, // #120-199
2759 // FTEQW range #200-#299
2778 VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2788 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399
2789 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2790 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2791 VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2792 VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2793 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2794 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2795 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2796 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2797 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2798 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2799 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2800 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2801 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2802 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2803 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2804 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2805 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2806 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2807 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2808 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2809 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2810 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2811 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2812 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2813 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2814 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2815 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2816 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2817 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2818 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2819 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2820 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2821 VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2822 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2823 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2824 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2825 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2826 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2827 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2828 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2829 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2830 VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2831 VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2832 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2833 VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2834 VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
2835 VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2836 VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2837 VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2838 VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2839 VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2840 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2841 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2842 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2843 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2844 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2845 PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2846 PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2848 PF_edict_num, // #459 entity(float num) (??)
2849 VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2850 VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2851 VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2852 VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2853 VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2854 VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2855 VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2856 VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2857 VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2858 VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2859 PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2860 VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
2861 VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
2862 VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
2863 VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
2864 VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
2865 VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
2866 VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
2869 e10, e10 // #480-499 (LordHavoc)
2872 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2874 void VM_SV_Cmd_Init(void)
2879 void VM_SV_Cmd_Reset(void)